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.
5 #include "chrome/renderer/safe_browsing/malware_dom_details.h"
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"
18 namespace safe_browsing
{
22 // Handler for the various HTML elements that we extract URLs from.
24 const blink::WebElement
& element
,
25 SafeBrowsingHostMsg_MalwareDOMDetails_Node
* parent_node
,
26 std::vector
<SafeBrowsingHostMsg_MalwareDOMDetails_Node
>* resources
) {
27 if (!element
.hasAttribute("src"))
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"));
34 const GURL
& child_url
= GURL(full_url
);
36 // Add to the parent node.
37 parent_node
->children
.push_back(child_url
);
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
);
49 // An upper limit on the number of nodes we collect.
50 uint32
MalwareDOMDetails::kMaxNodes
= 500;
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
);
59 MalwareDOMDetails::MalwareDOMDetails(content::RenderView
* render_view
)
60 : content::RenderViewObserver(render_view
) {
63 MalwareDOMDetails::~MalwareDOMDetails() {
66 bool MalwareDOMDetails::OnMessageReceived(const IPC::Message
& message
) {
68 IPC_BEGIN_MESSAGE_MAP(MalwareDOMDetails
, message
)
69 IPC_MESSAGE_HANDLER(SafeBrowsingMsg_GetMalwareDOMDetails
,
70 OnGetMalwareDOMDetails
)
71 IPC_MESSAGE_UNHANDLED(handled
= false)
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
));
84 void MalwareDOMDetails::ExtractResources(
85 std::vector
<SafeBrowsingHostMsg_MalwareDOMDetails_Node
>* resources
) {
86 blink::WebView
* web_view
= render_view()->GetWebView();
91 blink::WebFrame
* frame
= web_view
->mainFrame();
92 for (; frame
; frame
= frame
->traverseNext(false /* don't wrap */)) {
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
);
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
);
117 resources
->push_back(details_node
);
121 } // namespace safe_browsing