Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / extensions / renderer / content_watcher.cc
blob75740b554fd19542c1cc42d25fa8ace48e6738ac
1 // Copyright 2014 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 "extensions/renderer/content_watcher.h"
7 #include "content/public/renderer/render_view.h"
8 #include "content/public/renderer/render_view_visitor.h"
9 #include "extensions/common/extension_messages.h"
10 #include "third_party/WebKit/public/web/WebDocument.h"
11 #include "third_party/WebKit/public/web/WebElement.h"
12 #include "third_party/WebKit/public/web/WebLocalFrame.h"
13 #include "third_party/WebKit/public/web/WebScriptBindings.h"
14 #include "third_party/WebKit/public/web/WebView.h"
16 namespace extensions {
18 using blink::WebString;
19 using blink::WebVector;
20 using blink::WebView;
22 ContentWatcher::ContentWatcher() {}
23 ContentWatcher::~ContentWatcher() {}
25 void ContentWatcher::OnWatchPages(
26 const std::vector<std::string>& new_css_selectors_utf8) {
27 blink::WebVector<blink::WebString> new_css_selectors(
28 new_css_selectors_utf8.size());
29 bool changed = new_css_selectors.size() != css_selectors_.size();
30 for (size_t i = 0; i < new_css_selectors.size(); ++i) {
31 new_css_selectors[i] =
32 blink::WebString::fromUTF8(new_css_selectors_utf8[i]);
33 if (!changed && new_css_selectors[i] != css_selectors_[i])
34 changed = true;
37 if (!changed)
38 return;
40 css_selectors_.swap(new_css_selectors);
42 // Tell each frame's document about the new set of watched selectors. These
43 // will trigger calls to DidMatchCSS after Blink has a chance to apply the new
44 // style, which will in turn notify the browser about the changes.
45 struct WatchSelectors : public content::RenderViewVisitor {
46 explicit WatchSelectors(const WebVector<WebString>& css_selectors)
47 : css_selectors_(css_selectors) {}
49 bool Visit(content::RenderView* view) override {
50 for (blink::WebFrame* frame = view->GetWebView()->mainFrame(); frame;
51 frame = frame->traverseNext(/*wrap=*/false))
52 frame->document().watchCSSSelectors(css_selectors_);
54 return true; // Continue visiting.
57 const WebVector<WebString>& css_selectors_;
59 WatchSelectors visitor(css_selectors_);
60 content::RenderView::ForEach(&visitor);
63 void ContentWatcher::DidCreateDocumentElement(blink::WebLocalFrame* frame) {
64 frame->document().watchCSSSelectors(css_selectors_);
67 void ContentWatcher::DidMatchCSS(
68 blink::WebLocalFrame* frame,
69 const WebVector<WebString>& newly_matching_selectors,
70 const WebVector<WebString>& stopped_matching_selectors) {
71 std::set<std::string>& frame_selectors = matching_selectors_[frame];
72 for (size_t i = 0; i < stopped_matching_selectors.size(); ++i)
73 frame_selectors.erase(stopped_matching_selectors[i].utf8());
74 for (size_t i = 0; i < newly_matching_selectors.size(); ++i)
75 frame_selectors.insert(newly_matching_selectors[i].utf8());
77 if (frame_selectors.empty())
78 matching_selectors_.erase(frame);
80 NotifyBrowserOfChange(frame);
83 void ContentWatcher::NotifyBrowserOfChange(
84 blink::WebLocalFrame* changed_frame) const {
85 blink::WebFrame* const top_frame = changed_frame->top();
86 const blink::WebSecurityOrigin top_origin = top_frame->securityOrigin();
87 // Want to aggregate matched selectors from all frames where an
88 // extension with access to top_origin could run on the frame.
89 if (!top_origin.canAccess(changed_frame->document().securityOrigin())) {
90 // If the changed frame can't be accessed by the top frame, then
91 // no change in it could affect the set of selectors we'd send back.
92 return;
95 std::set<base::StringPiece> transitive_selectors;
96 for (blink::WebFrame* frame = top_frame; frame;
97 frame = frame->traverseNext(/*wrap=*/false)) {
98 if (top_origin.canAccess(frame->document().securityOrigin())) {
99 std::map<blink::WebFrame*, std::set<std::string> >::const_iterator
100 frame_selectors = matching_selectors_.find(frame);
101 if (frame_selectors != matching_selectors_.end()) {
102 transitive_selectors.insert(frame_selectors->second.begin(),
103 frame_selectors->second.end());
107 std::vector<std::string> selector_strings;
108 for (std::set<base::StringPiece>::const_iterator it =
109 transitive_selectors.begin();
110 it != transitive_selectors.end();
111 ++it)
112 selector_strings.push_back(it->as_string());
113 content::RenderView* view =
114 content::RenderView::FromWebView(top_frame->view());
115 view->Send(new ExtensionHostMsg_OnWatchedPageChange(view->GetRoutingID(),
116 selector_strings));
119 } // namespace extensions