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