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/WebElementCollection.h"
     15 #include "third_party/WebKit/public/web/WebFrame.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   blink::WebView* web_view = render_view()->GetWebView();
     58   if (!web_view) {
     59     NOTREACHED();
     60     return;
     61   }
     62   blink::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     blink::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     blink::WebElementCollection elements = document.all();
     75     blink::WebElement element = elements.firstItem();
     76     for (; !element.isNull(); element = elements.nextItem()) {
     77       if (element.hasTagName("iframe") || element.hasTagName("frame") ||
     78           element.hasTagName("embed") || element.hasTagName("script")) {
     79         HandleElement(element, &details_node, resources);
     80         if (resources->size() >= kMaxNodes) {
     81           // We have reached kMaxNodes, exit early.
     82           resources->push_back(details_node);
     83           return;
     84         }
     85       }
     86     }
     87 
     88     resources->push_back(details_node);
     89   }
     90 }
     91 
     92 void MalwareDOMDetails::HandleElement(
     93     const blink::WebElement& element,
     94     SafeBrowsingHostMsg_MalwareDOMDetails_Node* parent_node,
     95     std::vector<SafeBrowsingHostMsg_MalwareDOMDetails_Node>* resources) {
     96   if (!element.hasAttribute("src")) {
     97     return;
     98   }
     99 
    100   // Retrieve the link and resolve the link in case it's relative.
    101   blink::WebURL full_url = element.document().completeURL(
    102       element.getAttribute("src"));
    103 
    104   const GURL& child_url = GURL(full_url);
    105 
    106   // Add to the parent node.
    107   parent_node->children.push_back(child_url);
    108 
    109   // Create the child node.
    110   SafeBrowsingHostMsg_MalwareDOMDetails_Node child_node;
    111   child_node.url = child_url;
    112   child_node.tag_name = element.tagName().utf8();
    113   child_node.parent = parent_node->url;
    114   resources->push_back(child_node);
    115 }
    116 
    117 }  // namespace safe_browsing
    118