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
{
20 // An upper limit on the number of nodes we collect.
21 uint32
MalwareDOMDetails::kMaxNodes
= 500;
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
);
30 MalwareDOMDetails::MalwareDOMDetails(content::RenderView
* render_view
)
31 : content::RenderViewObserver(render_view
) {
34 MalwareDOMDetails::~MalwareDOMDetails() {
37 bool MalwareDOMDetails::OnMessageReceived(const IPC::Message
& message
) {
39 IPC_BEGIN_MESSAGE_MAP(MalwareDOMDetails
, message
)
40 IPC_MESSAGE_HANDLER(SafeBrowsingMsg_GetMalwareDOMDetails
,
41 OnGetMalwareDOMDetails
)
42 IPC_MESSAGE_UNHANDLED(handled
= false)
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
));
55 void MalwareDOMDetails::ExtractResources(
56 std::vector
<SafeBrowsingHostMsg_MalwareDOMDetails_Node
>* resources
) {
57 blink::WebView
* web_view
= render_view()->GetWebView();
62 blink::WebFrame
* frame
= web_view
->mainFrame();
63 for (; frame
; frame
= frame
->traverseNext(false /* don't wrap */)) {
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
);
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
);
88 resources
->push_back(details_node
);
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")) {
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"));
104 const GURL
& child_url
= GURL(full_url
);
106 // Add to the parent node.
107 parent_node
->children
.push_back(child_url
);
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
);
117 } // namespace safe_browsing