| OLD | NEW |
| (Empty) |
| 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/extensions/content_watcher.h" | |
| 6 | |
| 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/WebFrame.h" | |
| 13 #include "third_party/WebKit/public/web/WebScriptBindings.h" | |
| 14 #include "third_party/WebKit/public/web/WebView.h" | |
| 15 | |
| 16 namespace extensions { | |
| 17 | |
| 18 using blink::WebString; | |
| 19 using blink::WebVector; | |
| 20 using blink::WebView; | |
| 21 | |
| 22 ContentWatcher::ContentWatcher() {} | |
| 23 ContentWatcher::~ContentWatcher() {} | |
| 24 | |
| 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; | |
| 35 } | |
| 36 | |
| 37 if (!changed) | |
| 38 return; | |
| 39 | |
| 40 css_selectors_.swap(new_css_selectors); | |
| 41 | |
| 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) {} | |
| 48 | |
| 49 virtual 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_); | |
| 53 | |
| 54 return true; // Continue visiting. | |
| 55 } | |
| 56 | |
| 57 const WebVector<WebString>& css_selectors_; | |
| 58 }; | |
| 59 WatchSelectors visitor(css_selectors_); | |
| 60 content::RenderView::ForEach(&visitor); | |
| 61 } | |
| 62 | |
| 63 void ContentWatcher::DidCreateDocumentElement(blink::WebFrame* frame) { | |
| 64 frame->document().watchCSSSelectors(css_selectors_); | |
| 65 } | |
| 66 | |
| 67 void ContentWatcher::DidMatchCSS( | |
| 68 blink::WebFrame* 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()); | |
| 76 | |
| 77 if (frame_selectors.empty()) | |
| 78 matching_selectors_.erase(frame); | |
| 79 | |
| 80 NotifyBrowserOfChange(frame); | |
| 81 } | |
| 82 | |
| 83 void ContentWatcher::NotifyBrowserOfChange( | |
| 84 blink::WebFrame* changed_frame) const { | |
| 85 blink::WebFrame* const top_frame = changed_frame->top(); | |
| 86 const blink::WebSecurityOrigin top_origin = | |
| 87 top_frame->document().securityOrigin(); | |
| 88 // Want to aggregate matched selectors from all frames where an | |
| 89 // extension with access to top_origin could run on the frame. | |
| 90 if (!top_origin.canAccess(changed_frame->document().securityOrigin())) { | |
| 91 // If the changed frame can't be accessed by the top frame, then | |
| 92 // no change in it could affect the set of selectors we'd send back. | |
| 93 return; | |
| 94 } | |
| 95 | |
| 96 std::set<base::StringPiece> transitive_selectors; | |
| 97 for (blink::WebFrame* frame = top_frame; frame; | |
| 98 frame = frame->traverseNext(/*wrap=*/false)) { | |
| 99 if (top_origin.canAccess(frame->document().securityOrigin())) { | |
| 100 std::map<blink::WebFrame*, std::set<std::string> >::const_iterator | |
| 101 frame_selectors = matching_selectors_.find(frame); | |
| 102 if (frame_selectors != matching_selectors_.end()) { | |
| 103 transitive_selectors.insert(frame_selectors->second.begin(), | |
| 104 frame_selectors->second.end()); | |
| 105 } | |
| 106 } | |
| 107 } | |
| 108 std::vector<std::string> selector_strings; | |
| 109 for (std::set<base::StringPiece>::const_iterator | |
| 110 it = transitive_selectors.begin(); | |
| 111 it != transitive_selectors.end(); ++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( | |
| 116 view->GetRoutingID(), selector_strings)); | |
| 117 } | |
| 118 | |
| 119 } // namespace extensions | |
| OLD | NEW |