| 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(),
|
|
|