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 namespace { 21 22 // Handler for the various HTML elements that we extract URLs from. 23 void HandleElement( 24 const blink::WebElement& element, 25 SafeBrowsingHostMsg_MalwareDOMDetails_Node* parent_node, 26 std::vector<SafeBrowsingHostMsg_MalwareDOMDetails_Node>* resources) { 27 if (!element.hasAttribute("src")) 28 return; 29 30 // Retrieve the link and resolve the link in case it's relative. 31 blink::WebURL full_url = element.document().completeURL( 32 element.getAttribute("src")); 33 34 const GURL& child_url = GURL(full_url); 35 36 // Add to the parent node. 37 parent_node->children.push_back(child_url); 38 39 // Create the child node. 40 SafeBrowsingHostMsg_MalwareDOMDetails_Node child_node; 41 child_node.url = child_url; 42 child_node.tag_name = element.tagName().utf8(); 43 child_node.parent = parent_node->url; 44 resources->push_back(child_node); 45 } 46 47 } // namespace 48 49 // An upper limit on the number of nodes we collect. 50 uint32 MalwareDOMDetails::kMaxNodes = 500; 51 52 // static 53 MalwareDOMDetails* MalwareDOMDetails::Create(content::RenderView* render_view) { 54 // Private constructor and public static Create() method to facilitate 55 // stubbing out this class for binary-size reduction purposes. 56 return new MalwareDOMDetails(render_view); 57 } 58 59 MalwareDOMDetails::MalwareDOMDetails(content::RenderView* render_view) 60 : content::RenderViewObserver(render_view) { 61 } 62 63 MalwareDOMDetails::~MalwareDOMDetails() { 64 } 65 66 bool MalwareDOMDetails::OnMessageReceived(const IPC::Message& message) { 67 bool handled = true; 68 IPC_BEGIN_MESSAGE_MAP(MalwareDOMDetails, message) 69 IPC_MESSAGE_HANDLER(SafeBrowsingMsg_GetMalwareDOMDetails, 70 OnGetMalwareDOMDetails) 71 IPC_MESSAGE_UNHANDLED(handled = false) 72 IPC_END_MESSAGE_MAP() 73 return handled; 74 } 75 76 void MalwareDOMDetails::OnGetMalwareDOMDetails() { 77 std::vector<SafeBrowsingHostMsg_MalwareDOMDetails_Node> resources; 78 ExtractResources(&resources); 79 // Notify the browser. 80 render_view()->Send(new SafeBrowsingHostMsg_MalwareDOMDetails( 81 render_view()->GetRoutingID(), resources)); 82 } 83 84 void MalwareDOMDetails::ExtractResources( 85 std::vector<SafeBrowsingHostMsg_MalwareDOMDetails_Node>* resources) { 86 blink::WebView* web_view = render_view()->GetWebView(); 87 if (!web_view) { 88 NOTREACHED(); 89 return; 90 } 91 blink::WebFrame* frame = web_view->mainFrame(); 92 for (; frame; frame = frame->traverseNext(false /* don't wrap */)) { 93 DCHECK(frame); 94 SafeBrowsingHostMsg_MalwareDOMDetails_Node details_node; 95 blink::WebDocument document = frame->document(); 96 details_node.url = GURL(document.url()); 97 if (document.isNull()) { 98 // Nothing in this frame, move on to the next one. 99 resources->push_back(details_node); 100 continue; 101 } 102 103 blink::WebElementCollection elements = document.all(); 104 blink::WebElement element = elements.firstItem(); 105 for (; !element.isNull(); element = elements.nextItem()) { 106 if (element.hasHTMLTagName("iframe") || element.hasHTMLTagName("frame") || 107 element.hasHTMLTagName("embed") || element.hasHTMLTagName("script")) { 108 HandleElement(element, &details_node, resources); 109 if (resources->size() >= kMaxNodes) { 110 // We have reached kMaxNodes, exit early. 111 resources->push_back(details_node); 112 return; 113 } 114 } 115 } 116 117 resources->push_back(details_node); 118 } 119 } 120 121 } // namespace safe_browsing 122