Index: chrome/browser/extensions/api/declarative_content/chrome_content_rules_registry.cc |
diff --git a/chrome/browser/extensions/api/declarative_content/chrome_content_rules_registry.cc b/chrome/browser/extensions/api/declarative_content/chrome_content_rules_registry.cc |
index 0907b913c9bdade731e9d1a3d1becf482c1bbfa2..da88ec27948b99e923df6742fd0b29970a7d72de 100644 |
--- a/chrome/browser/extensions/api/declarative_content/chrome_content_rules_registry.cc |
+++ b/chrome/browser/extensions/api/declarative_content/chrome_content_rules_registry.cc |
@@ -8,6 +8,7 @@ |
#include "chrome/browser/extensions/api/declarative_content/content_action.h" |
#include "chrome/browser/extensions/api/declarative_content/content_condition.h" |
#include "chrome/browser/extensions/api/declarative_content/content_constants.h" |
+#include "chrome/browser/extensions/extension_tab_util.h" |
#include "chrome/browser/extensions/extension_util.h" |
#include "chrome/browser/profiles/profile.h" |
#include "chrome/browser/ui/browser.h" |
@@ -16,28 +17,16 @@ |
#include "content/public/browser/navigation_details.h" |
#include "content/public/browser/notification_service.h" |
#include "content/public/browser/notification_source.h" |
+#include "content/public/browser/render_process_host.h" |
#include "content/public/browser/web_contents.h" |
#include "extensions/browser/api/declarative/rules_registry_service.h" |
#include "extensions/browser/extension_registry.h" |
#include "extensions/browser/extension_system.h" |
+#include "extensions/common/extension_messages.h" |
using url_matcher::URLMatcherConditionSet; |
namespace extensions { |
- |
-template <class Func> |
-void ChromeContentRulesRegistry::ForEachWebContents(const Func& func) { |
- for (chrome::BrowserIterator it; !it.done(); it.Next()) { |
- Browser* browser = *it; |
- if (!ManagingRulesForBrowserContext(browser->profile())) |
- continue; |
- |
- for (int i = 0, tab_count = browser->tab_strip_model()->count(); |
- i < tab_count; ++i) { |
- func(browser->tab_strip_model()->GetWebContentsAt(i)); |
- } |
- } |
-} |
ChromeContentRulesRegistry::ChromeContentRulesRegistry( |
content::BrowserContext* browser_context, |
@@ -46,18 +35,12 @@ |
declarative_content_constants::kOnPageChanged, |
content::BrowserThread::UI, |
cache_delegate, |
- RulesRegistryService::kDefaultRulesRegistryID), |
- css_condition_tracker_(browser_context, this) { |
+ RulesRegistryService::kDefaultRulesRegistryID) { |
extension_info_map_ = ExtensionSystem::Get(browser_context)->info_map(); |
- // Set up rule tracking for any existing WebContents. |
- ForEachWebContents([this](content::WebContents* contents) { |
- TrackRulesForWebContents(contents); |
- }); |
- |
registrar_.Add(this, |
- chrome::NOTIFICATION_TAB_ADDED, |
- content::NotificationService::AllSources()); |
+ content::NOTIFICATION_RENDERER_PROCESS_CREATED, |
+ content::NotificationService::AllBrowserContextsAndSources()); |
registrar_.Add(this, |
content::NOTIFICATION_WEB_CONTENTS_DESTROYED, |
content::NotificationService::AllBrowserContextsAndSources()); |
@@ -68,10 +51,10 @@ |
const content::NotificationSource& source, |
const content::NotificationDetails& details) { |
switch (type) { |
- case chrome::NOTIFICATION_TAB_ADDED: { |
- content::WebContents* contents = |
- content::Details<content::WebContents>(details).ptr(); |
- TrackRulesForWebContents(contents); |
+ case content::NOTIFICATION_RENDERER_PROCESS_CREATED: { |
+ content::RenderProcessHost* process = |
+ content::Source<content::RenderProcessHost>(source).ptr(); |
+ InstructRenderProcessIfSameBrowserContext(process); |
break; |
} |
case content::NOTIFICATION_WEB_CONTENTS_DESTROYED: { |
@@ -80,27 +63,25 @@ |
// Note that neither non-tab WebContents nor tabs from other browser |
// contexts will be in the map. |
active_rules_.erase(tab); |
+ matching_css_selectors_.erase(tab); |
break; |
} |
} |
} |
-void ChromeContentRulesRegistry::RequestEvaluation( |
- content::WebContents* contents) { |
+void ChromeContentRulesRegistry::Apply( |
+ content::WebContents* contents, |
+ const std::vector<std::string>& matching_css_selectors) { |
+ matching_css_selectors_[contents] = matching_css_selectors; |
+ |
EvaluateConditionsForTab(contents); |
-} |
- |
-bool ChromeContentRulesRegistry::ShouldManageConditionsForBrowserContext( |
- content::BrowserContext* context) { |
- return ManagingRulesForBrowserContext(context); |
} |
void ChromeContentRulesRegistry::DidNavigateMainFrame( |
content::WebContents* contents, |
const content::LoadCommittedDetails& details, |
const content::FrameNavigateParams& params) { |
- if (ContainsKey(active_rules_, contents)) |
- css_condition_tracker_.OnWebContentsNavigation(contents, details, params); |
+ OnTabNavigation(contents, details.is_in_page); |
} |
void ChromeContentRulesRegistry::DidNavigateMainFrameOfOriginalContext( |
@@ -108,16 +89,24 @@ |
const content::LoadCommittedDetails& details, |
const content::FrameNavigateParams& params) { |
DCHECK(browser_context()->IsOffTheRecord()); |
- if (ContainsKey(active_rules_, contents)) |
- css_condition_tracker_.OnWebContentsNavigation(contents, details, params); |
-} |
- |
-void ChromeContentRulesRegistry::TrackRulesForWebContents( |
- content::WebContents* contents) { |
- // We rely on the_rules_ to have a key-value pair for |contents| to know which |
- // WebContents we are working with. |
- active_rules_[contents] = std::set<const ContentRule*>(); |
- css_condition_tracker_.TrackForWebContents(contents); |
+ OnTabNavigation(contents, details.is_in_page); |
+} |
+ |
+void ChromeContentRulesRegistry::OnTabNavigation(content::WebContents* tab, |
+ bool is_in_page_navigation) { |
+ if (is_in_page_navigation) { |
+ // Within-page navigations don't change the set of elements that |
+ // exist, and we only support filtering on the top-level URL, so |
+ // this can't change which rules match. |
+ return; |
+ } |
+ |
+ // Top-level navigation produces a new document. Initially, the |
+ // document's empty, so no CSS rules match. The renderer will send |
+ // an ExtensionHostMsg_OnWatchedPageChange later if any CSS rules |
+ // match. |
+ matching_css_selectors_[tab].clear(); |
+ EvaluateConditionsForTab(tab); |
} |
bool ChromeContentRulesRegistry::ManagingRulesForBrowserContext( |
@@ -230,7 +219,7 @@ |
} |
url_matcher_.AddConditionSets(all_new_condition_sets); |
- UpdateCssSelectorsFromRules(); |
+ UpdateConditionCache(); |
EvaluateConditionsForAllTabs(); |
return std::string(); |
@@ -277,7 +266,7 @@ |
// Clear URLMatcher based on condition_set_ids that are not needed any more. |
url_matcher_.RemoveConditionSets(remove_from_url_matcher); |
- UpdateCssSelectorsFromRules(); |
+ UpdateConditionCache(); |
return std::string(); |
} |
@@ -297,7 +286,7 @@ |
return RemoveRulesImpl(extension_id, rule_identifiers); |
} |
-void ChromeContentRulesRegistry::UpdateCssSelectorsFromRules() { |
+void ChromeContentRulesRegistry::UpdateConditionCache() { |
std::set<std::string> css_selectors; // We rely on this being sorted. |
for (const std::pair<ContentRule::GlobalRuleId, |
linked_ptr<const ContentRule>>& rule_id_rule_pair : |
@@ -312,15 +301,34 @@ |
} |
} |
- css_condition_tracker_.SetWatchedCssSelectors(css_selectors); |
+ if (css_selectors.size() != watched_css_selectors_.size() || |
+ !std::equal(css_selectors.begin(), |
+ css_selectors.end(), |
+ watched_css_selectors_.begin())) { |
+ watched_css_selectors_.assign(css_selectors.begin(), css_selectors.end()); |
+ |
+ for (content::RenderProcessHost::iterator it( |
+ content::RenderProcessHost::AllHostsIterator()); |
+ !it.IsAtEnd(); |
+ it.Advance()) { |
+ content::RenderProcessHost* process = it.GetCurrentValue(); |
+ InstructRenderProcessIfSameBrowserContext(process); |
+ } |
+ } |
+} |
+ |
+void ChromeContentRulesRegistry::InstructRenderProcessIfSameBrowserContext( |
+ content::RenderProcessHost* process) { |
+ if (ManagingRulesForBrowserContext(process->GetBrowserContext())) |
+ process->Send(new ExtensionMsg_WatchPages(watched_css_selectors_)); |
} |
void ChromeContentRulesRegistry::EvaluateConditionsForTab( |
content::WebContents* tab) { |
extensions::RendererContentMatchData renderer_data; |
renderer_data.page_url_matches = url_matcher_.MatchURL(tab->GetURL()); |
- css_condition_tracker_.GetMatchingCssSelectors(tab, |
- &renderer_data.css_selectors); |
+ renderer_data.css_selectors.insert(matching_css_selectors_[tab].begin(), |
+ matching_css_selectors_[tab].end()); |
std::set<const ContentRule*> matching_rules = |
GetMatches(renderer_data, tab->GetBrowserContext()->IsOffTheRecord()); |
if (matching_rules.empty() && !ContainsKey(active_rules_, tab)) |
@@ -344,35 +352,27 @@ |
} |
if (matching_rules.empty()) |
- active_rules_[tab].clear(); |
+ active_rules_.erase(tab); |
else |
swap(matching_rules, prev_matching_rules); |
} |
void ChromeContentRulesRegistry::EvaluateConditionsForAllTabs() { |
- ForEachWebContents([this](content::WebContents* contents) { |
- EvaluateConditionsForTab(contents); |
- }); |
+ for (chrome::BrowserIterator it; !it.done(); it.Next()) { |
+ Browser* browser = *it; |
+ if (!ManagingRulesForBrowserContext(browser->profile())) |
+ continue; |
+ |
+ for (int i = 0, tab_count = browser->tab_strip_model()->count(); |
+ i < tab_count; |
+ ++i) |
+ EvaluateConditionsForTab(browser->tab_strip_model()->GetWebContentsAt(i)); |
+ } |
} |
bool ChromeContentRulesRegistry::IsEmpty() const { |
return match_id_to_rule_.empty() && content_rules_.empty() && |
url_matcher_.IsEmpty(); |
-} |
- |
-void ChromeContentRulesRegistry::UpdateMatchingCssSelectorsForTesting( |
- content::WebContents* contents, |
- const std::vector<std::string>& matching_css_selectors) { |
- css_condition_tracker_.UpdateMatchingCssSelectorsForTesting( |
- contents, |
- matching_css_selectors); |
-} |
- |
-size_t ChromeContentRulesRegistry::GetActiveRulesCountForTesting() { |
- size_t count = 0; |
- for (auto web_contents_rules_pair : active_rules_) |
- count += web_contents_rules_pair.second.size(); |
- return count; |
} |
ChromeContentRulesRegistry::~ChromeContentRulesRegistry() { |