Index: chrome/renderer/extensions/content_watcher.cc |
diff --git a/chrome/renderer/extensions/content_watcher.cc b/chrome/renderer/extensions/content_watcher.cc |
index 5c2bb7ea5d0e58de7577ae758a1851e8c39a3cde..ccbea0b3863efaa7697646bc65e4c87ee5e91c7b 100644 |
--- a/chrome/renderer/extensions/content_watcher.cc |
+++ b/chrome/renderer/extensions/content_watcher.cc |
@@ -15,76 +15,86 @@ |
namespace extensions { |
-namespace { |
-class MutationHandler : public ChromeV8Extension { |
- public: |
- explicit MutationHandler(Dispatcher* dispatcher, |
- base::WeakPtr<ContentWatcher> content_watcher) |
- : ChromeV8Extension(dispatcher), |
- content_watcher_(content_watcher) { |
- RouteFunction("FrameMutated", |
- base::Bind(&MutationHandler::FrameMutated, |
- base::Unretained(this))); |
- } |
- |
- private: |
- v8::Handle<v8::Value> FrameMutated(const v8::Arguments& args) { |
- if (content_watcher_) { |
- content_watcher_->ScanAndNotify( |
- WebKit::WebFrame::frameForCurrentContext()); |
- } |
- return v8::Undefined(); |
- } |
- |
- base::WeakPtr<ContentWatcher> content_watcher_; |
-}; |
- |
-} // namespace |
+using WebKit::WebString; |
+using WebKit::WebVector; |
+using WebKit::WebView; |
ContentWatcher::ContentWatcher(Dispatcher* dispatcher) |
: weak_ptr_factory_(this), |
dispatcher_(dispatcher) {} |
ContentWatcher::~ContentWatcher() {} |
-scoped_ptr<NativeHandler> ContentWatcher::MakeNatives() { |
- return scoped_ptr<NativeHandler>( |
- new MutationHandler(dispatcher_, weak_ptr_factory_.GetWeakPtr())); |
-} |
- |
void ContentWatcher::OnWatchPages( |
const std::vector<std::string>& new_css_selectors) { |
if (new_css_selectors == css_selectors_) |
return; |
+ std::string rules; |
+ // Turn off callbacks for old selectors. |
+ for (size_t i = 0; i < css_selectors_.size(); ++i) { |
+ rules.append(css_selectors_[i]); |
+ rules.append("{callback:none}\n"); |
+ } |
+ |
css_selectors_ = new_css_selectors; |
- for (std::map<WebKit::WebFrame*, |
- std::vector<base::StringPiece> >::iterator |
+ // Turn on callbacks for new selectors. |
+ for (size_t i = 0; i < css_selectors_.size(); ++i) { |
+ rules.append(css_selectors_[i]); |
+ rules.append("{-webkit-callback:-webkit-presence}\n"); |
+ } |
+ |
+ for (std::map<WebKit::WebFrame*, std::set<std::string> >::iterator |
it = matching_selectors_.begin(); |
it != matching_selectors_.end(); ++it) { |
WebKit::WebFrame* frame = it->first; |
if (!css_selectors_.empty()) |
EnsureWatchingMutations(frame); |
- // Make sure to replace the contents of it->second because it contains |
- // dangling StringPieces that referred into the old css_selectors_ content. |
+ // Update the contents of it->second since css_selectors_ could have changed |
+ // completely. |
it->second = FindMatchingSelectors(frame); |
} |
// For each top-level frame, inform the browser about its new matching set of |
- // selectors. |
+ // selectors, and set a user style sheet to watch for changes in the future. |
struct NotifyVisitor : public content::RenderViewVisitor { |
- explicit NotifyVisitor(ContentWatcher* watcher) : watcher_(watcher) {} |
+ explicit NotifyVisitor(ContentWatcher* watcher, WebString rules) |
+ : watcher_(watcher), |
+ rules_(rules) {} |
virtual bool Visit(content::RenderView* view) OVERRIDE { |
- watcher_->NotifyBrowserOfChange(view->GetWebView()->mainFrame()); |
+ WebView* web_view = view->GetWebView(); |
+ // Notify of the matching selectors found above. |
+ watcher_->NotifyBrowserOfChange(web_view->mainFrame()); |
+ |
+ // Watch for future changes. |
+ web_view->addUserStyleSheet(rules_, |
+ WebKit::WebVector<WebString>(), // All URLs. |
+ WebView::UserContentInjectInAllFrames, |
+ WebView::UserStyleInjectInExistingDocuments); |
return true; // Continue visiting. |
} |
ContentWatcher* watcher_; |
+ WebString rules_; |
}; |
- NotifyVisitor visitor(this); |
+ NotifyVisitor visitor(this, WebString::fromUTF8(rules)); |
content::RenderView::ForEach(&visitor); |
} |
+void ContentWatcher::OnWebViewCreated(WebKit::WebView* view) { |
+ std::string rules; |
+ // Turn on callbacks for watched selectors. |
+ for (size_t i = 0; i < css_selectors_.size(); ++i) { |
+ rules.append(css_selectors_[i]); |
+ rules.append("{-webkit-callback:-webkit-presence}\n"); |
+ } |
+ |
+ view->addUserStyleSheet(WebString::fromUTF8(rules), |
+ WebKit::WebVector<WebString>(), // All URLs. |
+ WebView::UserContentInjectInAllFrames, |
+ WebView::UserStyleInjectInExistingDocuments); |
+} |
+ |
void ContentWatcher::DidCreateDocumentElement(WebKit::WebFrame* frame) { |
// Make sure the frame is represented in the matching_selectors_ map. |
matching_selectors_[frame]; |
@@ -113,20 +123,25 @@ ModuleSystem* ContentWatcher::GetModuleSystem(WebKit::WebFrame* frame) const { |
return v8_context->module_system(); |
} |
-void ContentWatcher::ScanAndNotify(WebKit::WebFrame* frame) { |
- std::vector<base::StringPiece> new_matches = FindMatchingSelectors(frame); |
- std::vector<base::StringPiece>& old_matches = matching_selectors_[frame]; |
- if (new_matches == old_matches) |
- return; |
+void ContentWatcher::CssMatches( |
+ WebKit::WebFrame* frame, |
+ const WebVector<WebString>& newlyMatchingSelectors, |
+ const WebVector<WebString>& stoppedMatchingSelectors) { |
+ std::set<std::string>& frame_selectors = matching_selectors_[frame]; |
+ for (size_t i = 0; i < stoppedMatchingSelectors.size(); ++i) |
+ frame_selectors.erase(stoppedMatchingSelectors[i].utf8()); |
+ for (size_t i = 0; i < newlyMatchingSelectors.size(); ++i) |
+ frame_selectors.insert(newlyMatchingSelectors[i].utf8()); |
+ |
+ if (frame_selectors.empty()) |
+ matching_selectors_.erase(frame); |
- using std::swap; |
- swap(old_matches, new_matches); |
NotifyBrowserOfChange(frame); |
} |
-std::vector<base::StringPiece> ContentWatcher::FindMatchingSelectors( |
+std::set<std::string> ContentWatcher::FindMatchingSelectors( |
WebKit::WebFrame* frame) const { |
- std::vector<base::StringPiece> result; |
+ std::set<std::string> result; |
v8::HandleScope scope; |
// Get the indices within |css_selectors_| that match elements in |
@@ -153,7 +168,6 @@ std::vector<base::StringPiece> ContentWatcher::FindMatchingSelectors( |
// converting them back to integers. |
v8::Local<v8::Array> index_array = selector_indices.As<v8::Array>(); |
const size_t length = index_array->Length(); |
- result.reserve(length); |
for (size_t i = 0; i < length; ++i) { |
v8::Local<v8::Value> index_value = index_array->Get(i); |
if (!index_value->IsNumber()) |
@@ -162,9 +176,8 @@ std::vector<base::StringPiece> ContentWatcher::FindMatchingSelectors( |
// Make sure the index is within bounds. |
if (index < 0 || css_selectors_.size() <= index) |
continue; |
- // Push a StringPiece referring to the CSS selector onto the result. |
- result.push_back( |
- base::StringPiece(css_selectors_[static_cast<size_t>(index)])); |
+ // Add the CSS selector to the result. |
+ result.insert(css_selectors_[static_cast<size_t>(index)]); |
} |
return result; |
} |
@@ -186,8 +199,7 @@ void ContentWatcher::NotifyBrowserOfChange( |
for (WebKit::WebFrame* frame = top_frame; frame; |
frame = frame->traverseNext(/*wrap=*/false)) { |
if (top_origin.canAccess(frame->document().securityOrigin())) { |
- std::map<WebKit::WebFrame*, |
- std::vector<base::StringPiece> >::const_iterator |
+ std::map<WebKit::WebFrame*, std::set<std::string> >::const_iterator |
frame_selectors = matching_selectors_.find(frame); |
if (frame_selectors != matching_selectors_.end()) { |
transitive_selectors.insert(frame_selectors->second.begin(), |