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 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::WebNodeCollection elements = document.all(); 75 blink::WebNode cur_node = elements.firstItem(); 76 for (; !cur_node.isNull(); cur_node = elements.nextItem()) { 77 if (!cur_node.isElementNode()) { 78 continue; 79 } 80 blink::WebElement element = cur_node.to<blink::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 blink::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 blink::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