Home | History | Annotate | Download | only in safe_browsing
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "chrome/renderer/safe_browsing/malware_dom_details.h"
      6 
      7 #include "base/compiler_specific.h"
      8 #include "chrome/common/chrome_constants.h"
      9 #include "chrome/common/safe_browsing/safebrowsing_messages.h"
     10 #include "content/public/renderer/render_view.h"
     11 #include "third_party/WebKit/public/platform/WebString.h"
     12 #include "third_party/WebKit/public/web/WebDocument.h"
     13 #include "third_party/WebKit/public/web/WebElement.h"
     14 #include "third_party/WebKit/public/web/WebFrame.h"
     15 #include "third_party/WebKit/public/web/WebNodeCollection.h"
     16 #include "third_party/WebKit/public/web/WebView.h"
     17 
     18 namespace safe_browsing {
     19 
     20 // An upper limit on the number of nodes we collect.
     21 uint32 MalwareDOMDetails::kMaxNodes = 500;
     22 
     23 // static
     24 MalwareDOMDetails* MalwareDOMDetails::Create(content::RenderView* render_view) {
     25   // Private constructor and public static Create() method to facilitate
     26   // stubbing out this class for binary-size reduction purposes.
     27   return new MalwareDOMDetails(render_view);
     28 }
     29 
     30 MalwareDOMDetails::MalwareDOMDetails(content::RenderView* render_view)
     31     : content::RenderViewObserver(render_view) {
     32 }
     33 
     34 MalwareDOMDetails::~MalwareDOMDetails() {
     35 }
     36 
     37 bool MalwareDOMDetails::OnMessageReceived(const IPC::Message& message) {
     38   bool handled = true;
     39   IPC_BEGIN_MESSAGE_MAP(MalwareDOMDetails, message)
     40     IPC_MESSAGE_HANDLER(SafeBrowsingMsg_GetMalwareDOMDetails,
     41                         OnGetMalwareDOMDetails)
     42     IPC_MESSAGE_UNHANDLED(handled = false)
     43   IPC_END_MESSAGE_MAP()
     44   return handled;
     45 }
     46 
     47 void MalwareDOMDetails::OnGetMalwareDOMDetails() {
     48   std::vector<SafeBrowsingHostMsg_MalwareDOMDetails_Node> resources;
     49   ExtractResources(&resources);
     50   // Notify the browser.
     51   render_view()->Send(new SafeBrowsingHostMsg_MalwareDOMDetails(
     52       render_view()->GetRoutingID(), resources));
     53 }
     54 
     55 void MalwareDOMDetails::ExtractResources(
     56     std::vector<SafeBrowsingHostMsg_MalwareDOMDetails_Node>* resources) {
     57   WebKit::WebView* web_view = render_view()->GetWebView();
     58   if (!web_view) {
     59     NOTREACHED();
     60     return;
     61   }
     62   WebKit::WebFrame* frame = web_view->mainFrame();
     63   for (; frame; frame = frame->traverseNext(false /* don't wrap */)) {
     64     DCHECK(frame);
     65     SafeBrowsingHostMsg_MalwareDOMDetails_Node details_node;
     66     WebKit::WebDocument document = frame->document();
     67     details_node.url = GURL(document.url());
     68     if (document.isNull()) {
     69       // Nothing in this frame, move on to the next one.
     70       resources->push_back(details_node);
     71       continue;
     72     }
     73 
     74     WebKit::WebNodeCollection elements = document.all();
     75     WebKit::WebNode cur_node = elements.firstItem();
     76     for (; !cur_node.isNull(); cur_node = elements.nextItem()) {
     77       if (!cur_node.isElementNode()) {
     78         continue;
     79       }
     80       WebKit::WebElement element = cur_node.to<WebKit::WebElement>();
     81       if (element.hasTagName("iframe") || element.hasTagName("frame") ||
     82           element.hasTagName("embed") || element.hasTagName("script")) {
     83         HandleElement(element, &details_node, resources);
     84         if (resources->size() >= kMaxNodes) {
     85           // We have reached kMaxNodes, exit early.
     86           resources->push_back(details_node);
     87           return;
     88         }
     89       }
     90     }
     91 
     92     resources->push_back(details_node);
     93   }
     94 }
     95 
     96 void MalwareDOMDetails::HandleElement(
     97     const WebKit::WebElement& element,
     98     SafeBrowsingHostMsg_MalwareDOMDetails_Node* parent_node,
     99     std::vector<SafeBrowsingHostMsg_MalwareDOMDetails_Node>* resources) {
    100   if (!element.hasAttribute("src")) {
    101     return;
    102   }
    103 
    104   // Retrieve the link and resolve the link in case it's relative.
    105   WebKit::WebURL full_url = element.document().completeURL(
    106       element.getAttribute("src"));
    107 
    108   const GURL& child_url = GURL(full_url);
    109 
    110   // Add to the parent node.
    111   parent_node->children.push_back(child_url);
    112 
    113   // Create the child node.
    114   SafeBrowsingHostMsg_MalwareDOMDetails_Node child_node;
    115   child_node.url = child_url;
    116   child_node.tag_name = element.tagName().utf8();
    117   child_node.parent = parent_node->url;
    118   resources->push_back(child_node);
    119 }
    120 
    121 }  // namespace safe_browsing
    122