Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(325)

Side by Side Diff: chrome/browser/extensions/api/declarative_content/chrome_content_rules_registry.cc

Issue 1159623014: Revert of Encapsulate CSS selector declarative content condition tracking (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@stars-declarative-content-range-for
Patch Set: Created 5 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/extensions/api/declarative_content/chrome_content_rules _registry.h" 5 #include "chrome/browser/extensions/api/declarative_content/chrome_content_rules _registry.h"
6 6
7 #include "chrome/browser/chrome_notification_types.h" 7 #include "chrome/browser/chrome_notification_types.h"
8 #include "chrome/browser/extensions/api/declarative_content/content_action.h" 8 #include "chrome/browser/extensions/api/declarative_content/content_action.h"
9 #include "chrome/browser/extensions/api/declarative_content/content_condition.h" 9 #include "chrome/browser/extensions/api/declarative_content/content_condition.h"
10 #include "chrome/browser/extensions/api/declarative_content/content_constants.h" 10 #include "chrome/browser/extensions/api/declarative_content/content_constants.h"
11 #include "chrome/browser/extensions/extension_tab_util.h"
11 #include "chrome/browser/extensions/extension_util.h" 12 #include "chrome/browser/extensions/extension_util.h"
12 #include "chrome/browser/profiles/profile.h" 13 #include "chrome/browser/profiles/profile.h"
13 #include "chrome/browser/ui/browser.h" 14 #include "chrome/browser/ui/browser.h"
14 #include "chrome/browser/ui/browser_iterator.h" 15 #include "chrome/browser/ui/browser_iterator.h"
15 #include "chrome/browser/ui/tabs/tab_strip_model.h" 16 #include "chrome/browser/ui/tabs/tab_strip_model.h"
16 #include "content/public/browser/navigation_details.h" 17 #include "content/public/browser/navigation_details.h"
17 #include "content/public/browser/notification_service.h" 18 #include "content/public/browser/notification_service.h"
18 #include "content/public/browser/notification_source.h" 19 #include "content/public/browser/notification_source.h"
20 #include "content/public/browser/render_process_host.h"
19 #include "content/public/browser/web_contents.h" 21 #include "content/public/browser/web_contents.h"
20 #include "extensions/browser/api/declarative/rules_registry_service.h" 22 #include "extensions/browser/api/declarative/rules_registry_service.h"
21 #include "extensions/browser/extension_registry.h" 23 #include "extensions/browser/extension_registry.h"
22 #include "extensions/browser/extension_system.h" 24 #include "extensions/browser/extension_system.h"
25 #include "extensions/common/extension_messages.h"
23 26
24 using url_matcher::URLMatcherConditionSet; 27 using url_matcher::URLMatcherConditionSet;
25 28
26 namespace extensions { 29 namespace extensions {
27 30
28 template <class Func>
29 void ChromeContentRulesRegistry::ForEachWebContents(const Func& func) {
30 for (chrome::BrowserIterator it; !it.done(); it.Next()) {
31 Browser* browser = *it;
32 if (!ManagingRulesForBrowserContext(browser->profile()))
33 continue;
34
35 for (int i = 0, tab_count = browser->tab_strip_model()->count();
36 i < tab_count; ++i) {
37 func(browser->tab_strip_model()->GetWebContentsAt(i));
38 }
39 }
40 }
41
42 ChromeContentRulesRegistry::ChromeContentRulesRegistry( 31 ChromeContentRulesRegistry::ChromeContentRulesRegistry(
43 content::BrowserContext* browser_context, 32 content::BrowserContext* browser_context,
44 RulesCacheDelegate* cache_delegate) 33 RulesCacheDelegate* cache_delegate)
45 : ContentRulesRegistry(browser_context, 34 : ContentRulesRegistry(browser_context,
46 declarative_content_constants::kOnPageChanged, 35 declarative_content_constants::kOnPageChanged,
47 content::BrowserThread::UI, 36 content::BrowserThread::UI,
48 cache_delegate, 37 cache_delegate,
49 RulesRegistryService::kDefaultRulesRegistryID), 38 RulesRegistryService::kDefaultRulesRegistryID) {
50 css_condition_tracker_(browser_context, this) {
51 extension_info_map_ = ExtensionSystem::Get(browser_context)->info_map(); 39 extension_info_map_ = ExtensionSystem::Get(browser_context)->info_map();
52 40
53 // Set up rule tracking for any existing WebContents.
54 ForEachWebContents([this](content::WebContents* contents) {
55 TrackRulesForWebContents(contents);
56 });
57
58 registrar_.Add(this, 41 registrar_.Add(this,
59 chrome::NOTIFICATION_TAB_ADDED, 42 content::NOTIFICATION_RENDERER_PROCESS_CREATED,
60 content::NotificationService::AllSources()); 43 content::NotificationService::AllBrowserContextsAndSources());
61 registrar_.Add(this, 44 registrar_.Add(this,
62 content::NOTIFICATION_WEB_CONTENTS_DESTROYED, 45 content::NOTIFICATION_WEB_CONTENTS_DESTROYED,
63 content::NotificationService::AllBrowserContextsAndSources()); 46 content::NotificationService::AllBrowserContextsAndSources());
64 } 47 }
65 48
66 void ChromeContentRulesRegistry::Observe( 49 void ChromeContentRulesRegistry::Observe(
67 int type, 50 int type,
68 const content::NotificationSource& source, 51 const content::NotificationSource& source,
69 const content::NotificationDetails& details) { 52 const content::NotificationDetails& details) {
70 switch (type) { 53 switch (type) {
71 case chrome::NOTIFICATION_TAB_ADDED: { 54 case content::NOTIFICATION_RENDERER_PROCESS_CREATED: {
72 content::WebContents* contents = 55 content::RenderProcessHost* process =
73 content::Details<content::WebContents>(details).ptr(); 56 content::Source<content::RenderProcessHost>(source).ptr();
74 TrackRulesForWebContents(contents); 57 InstructRenderProcessIfSameBrowserContext(process);
75 break; 58 break;
76 } 59 }
77 case content::NOTIFICATION_WEB_CONTENTS_DESTROYED: { 60 case content::NOTIFICATION_WEB_CONTENTS_DESTROYED: {
78 content::WebContents* tab = 61 content::WebContents* tab =
79 content::Source<content::WebContents>(source).ptr(); 62 content::Source<content::WebContents>(source).ptr();
80 // Note that neither non-tab WebContents nor tabs from other browser 63 // Note that neither non-tab WebContents nor tabs from other browser
81 // contexts will be in the map. 64 // contexts will be in the map.
82 active_rules_.erase(tab); 65 active_rules_.erase(tab);
66 matching_css_selectors_.erase(tab);
83 break; 67 break;
84 } 68 }
85 } 69 }
86 } 70 }
87 71
88 void ChromeContentRulesRegistry::RequestEvaluation( 72 void ChromeContentRulesRegistry::Apply(
89 content::WebContents* contents) { 73 content::WebContents* contents,
74 const std::vector<std::string>& matching_css_selectors) {
75 matching_css_selectors_[contents] = matching_css_selectors;
76
90 EvaluateConditionsForTab(contents); 77 EvaluateConditionsForTab(contents);
91 } 78 }
92 79
93 bool ChromeContentRulesRegistry::ShouldManageConditionsForBrowserContext(
94 content::BrowserContext* context) {
95 return ManagingRulesForBrowserContext(context);
96 }
97
98 void ChromeContentRulesRegistry::DidNavigateMainFrame( 80 void ChromeContentRulesRegistry::DidNavigateMainFrame(
99 content::WebContents* contents, 81 content::WebContents* contents,
100 const content::LoadCommittedDetails& details, 82 const content::LoadCommittedDetails& details,
101 const content::FrameNavigateParams& params) { 83 const content::FrameNavigateParams& params) {
102 if (ContainsKey(active_rules_, contents)) 84 OnTabNavigation(contents, details.is_in_page);
103 css_condition_tracker_.OnWebContentsNavigation(contents, details, params);
104 } 85 }
105 86
106 void ChromeContentRulesRegistry::DidNavigateMainFrameOfOriginalContext( 87 void ChromeContentRulesRegistry::DidNavigateMainFrameOfOriginalContext(
107 content::WebContents* contents, 88 content::WebContents* contents,
108 const content::LoadCommittedDetails& details, 89 const content::LoadCommittedDetails& details,
109 const content::FrameNavigateParams& params) { 90 const content::FrameNavigateParams& params) {
110 DCHECK(browser_context()->IsOffTheRecord()); 91 DCHECK(browser_context()->IsOffTheRecord());
111 if (ContainsKey(active_rules_, contents)) 92 OnTabNavigation(contents, details.is_in_page);
112 css_condition_tracker_.OnWebContentsNavigation(contents, details, params);
113 } 93 }
114 94
115 void ChromeContentRulesRegistry::TrackRulesForWebContents( 95 void ChromeContentRulesRegistry::OnTabNavigation(content::WebContents* tab,
116 content::WebContents* contents) { 96 bool is_in_page_navigation) {
117 // We rely on the_rules_ to have a key-value pair for |contents| to know which 97 if (is_in_page_navigation) {
118 // WebContents we are working with. 98 // Within-page navigations don't change the set of elements that
119 active_rules_[contents] = std::set<const ContentRule*>(); 99 // exist, and we only support filtering on the top-level URL, so
120 css_condition_tracker_.TrackForWebContents(contents); 100 // this can't change which rules match.
101 return;
102 }
103
104 // Top-level navigation produces a new document. Initially, the
105 // document's empty, so no CSS rules match. The renderer will send
106 // an ExtensionHostMsg_OnWatchedPageChange later if any CSS rules
107 // match.
108 matching_css_selectors_[tab].clear();
109 EvaluateConditionsForTab(tab);
121 } 110 }
122 111
123 bool ChromeContentRulesRegistry::ManagingRulesForBrowserContext( 112 bool ChromeContentRulesRegistry::ManagingRulesForBrowserContext(
124 content::BrowserContext* context) { 113 content::BrowserContext* context) {
125 // Manage both the normal context and incognito contexts associated with it. 114 // Manage both the normal context and incognito contexts associated with it.
126 return Profile::FromBrowserContext(context)->GetOriginalProfile() == 115 return Profile::FromBrowserContext(context)->GetOriginalProfile() ==
127 Profile::FromBrowserContext(browser_context()); 116 Profile::FromBrowserContext(browser_context());
128 } 117 }
129 118
130 std::set<const ContentRule*> ChromeContentRulesRegistry::GetMatches( 119 std::set<const ContentRule*> ChromeContentRulesRegistry::GetMatches(
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
223 // Register url patterns in url_matcher_. 212 // Register url patterns in url_matcher_.
224 URLMatcherConditionSet::Vector all_new_condition_sets; 213 URLMatcherConditionSet::Vector all_new_condition_sets;
225 for (const std::pair<ContentRule::GlobalRuleId, 214 for (const std::pair<ContentRule::GlobalRuleId,
226 linked_ptr<const ContentRule>>& rule_id_rule_pair : 215 linked_ptr<const ContentRule>>& rule_id_rule_pair :
227 new_content_rules) { 216 new_content_rules) {
228 const linked_ptr<const ContentRule>& rule = rule_id_rule_pair.second; 217 const linked_ptr<const ContentRule>& rule = rule_id_rule_pair.second;
229 rule->conditions().GetURLMatcherConditionSets(&all_new_condition_sets); 218 rule->conditions().GetURLMatcherConditionSets(&all_new_condition_sets);
230 } 219 }
231 url_matcher_.AddConditionSets(all_new_condition_sets); 220 url_matcher_.AddConditionSets(all_new_condition_sets);
232 221
233 UpdateCssSelectorsFromRules(); 222 UpdateConditionCache();
234 EvaluateConditionsForAllTabs(); 223 EvaluateConditionsForAllTabs();
235 224
236 return std::string(); 225 return std::string();
237 } 226 }
238 227
239 std::string ChromeContentRulesRegistry::RemoveRulesImpl( 228 std::string ChromeContentRulesRegistry::RemoveRulesImpl(
240 const std::string& extension_id, 229 const std::string& extension_id,
241 const std::vector<std::string>& rule_identifiers) { 230 const std::vector<std::string>& rule_identifiers) {
242 // URLMatcherConditionSet IDs that can be removed from URLMatcher. 231 // URLMatcherConditionSet IDs that can be removed from URLMatcher.
243 std::vector<URLMatcherConditionSet::ID> remove_from_url_matcher; 232 std::vector<URLMatcherConditionSet::ID> remove_from_url_matcher;
(...skipping 26 matching lines...) Expand all
270 } 259 }
271 } 260 }
272 261
273 // Remove reference to actual rule. 262 // Remove reference to actual rule.
274 content_rules_.erase(content_rules_entry); 263 content_rules_.erase(content_rules_entry);
275 } 264 }
276 265
277 // Clear URLMatcher based on condition_set_ids that are not needed any more. 266 // Clear URLMatcher based on condition_set_ids that are not needed any more.
278 url_matcher_.RemoveConditionSets(remove_from_url_matcher); 267 url_matcher_.RemoveConditionSets(remove_from_url_matcher);
279 268
280 UpdateCssSelectorsFromRules(); 269 UpdateConditionCache();
281 270
282 return std::string(); 271 return std::string();
283 } 272 }
284 273
285 std::string ChromeContentRulesRegistry::RemoveAllRulesImpl( 274 std::string ChromeContentRulesRegistry::RemoveAllRulesImpl(
286 const std::string& extension_id) { 275 const std::string& extension_id) {
287 // Search all identifiers of rules that belong to extension |extension_id|. 276 // Search all identifiers of rules that belong to extension |extension_id|.
288 std::vector<std::string> rule_identifiers; 277 std::vector<std::string> rule_identifiers;
289 for (const std::pair<ContentRule::GlobalRuleId, 278 for (const std::pair<ContentRule::GlobalRuleId,
290 linked_ptr<const ContentRule>>& rule_id_rule_pair : 279 linked_ptr<const ContentRule>>& rule_id_rule_pair :
291 content_rules_) { 280 content_rules_) {
292 const ContentRule::GlobalRuleId& global_rule_id = rule_id_rule_pair.first; 281 const ContentRule::GlobalRuleId& global_rule_id = rule_id_rule_pair.first;
293 if (global_rule_id.first == extension_id) 282 if (global_rule_id.first == extension_id)
294 rule_identifiers.push_back(global_rule_id.second); 283 rule_identifiers.push_back(global_rule_id.second);
295 } 284 }
296 285
297 return RemoveRulesImpl(extension_id, rule_identifiers); 286 return RemoveRulesImpl(extension_id, rule_identifiers);
298 } 287 }
299 288
300 void ChromeContentRulesRegistry::UpdateCssSelectorsFromRules() { 289 void ChromeContentRulesRegistry::UpdateConditionCache() {
301 std::set<std::string> css_selectors; // We rely on this being sorted. 290 std::set<std::string> css_selectors; // We rely on this being sorted.
302 for (const std::pair<ContentRule::GlobalRuleId, 291 for (const std::pair<ContentRule::GlobalRuleId,
303 linked_ptr<const ContentRule>>& rule_id_rule_pair : 292 linked_ptr<const ContentRule>>& rule_id_rule_pair :
304 content_rules_) { 293 content_rules_) {
305 const ContentRule& rule = *rule_id_rule_pair.second; 294 const ContentRule& rule = *rule_id_rule_pair.second;
306 for (const linked_ptr<const ContentCondition>& condition : 295 for (const linked_ptr<const ContentCondition>& condition :
307 rule.conditions()) { 296 rule.conditions()) {
308 const std::vector<std::string>& condition_css_selectors = 297 const std::vector<std::string>& condition_css_selectors =
309 condition->css_selectors(); 298 condition->css_selectors();
310 css_selectors.insert(condition_css_selectors.begin(), 299 css_selectors.insert(condition_css_selectors.begin(),
311 condition_css_selectors.end()); 300 condition_css_selectors.end());
312 } 301 }
313 } 302 }
314 303
315 css_condition_tracker_.SetWatchedCssSelectors(css_selectors); 304 if (css_selectors.size() != watched_css_selectors_.size() ||
305 !std::equal(css_selectors.begin(),
306 css_selectors.end(),
307 watched_css_selectors_.begin())) {
308 watched_css_selectors_.assign(css_selectors.begin(), css_selectors.end());
309
310 for (content::RenderProcessHost::iterator it(
311 content::RenderProcessHost::AllHostsIterator());
312 !it.IsAtEnd();
313 it.Advance()) {
314 content::RenderProcessHost* process = it.GetCurrentValue();
315 InstructRenderProcessIfSameBrowserContext(process);
316 }
317 }
318 }
319
320 void ChromeContentRulesRegistry::InstructRenderProcessIfSameBrowserContext(
321 content::RenderProcessHost* process) {
322 if (ManagingRulesForBrowserContext(process->GetBrowserContext()))
323 process->Send(new ExtensionMsg_WatchPages(watched_css_selectors_));
316 } 324 }
317 325
318 void ChromeContentRulesRegistry::EvaluateConditionsForTab( 326 void ChromeContentRulesRegistry::EvaluateConditionsForTab(
319 content::WebContents* tab) { 327 content::WebContents* tab) {
320 extensions::RendererContentMatchData renderer_data; 328 extensions::RendererContentMatchData renderer_data;
321 renderer_data.page_url_matches = url_matcher_.MatchURL(tab->GetURL()); 329 renderer_data.page_url_matches = url_matcher_.MatchURL(tab->GetURL());
322 css_condition_tracker_.GetMatchingCssSelectors(tab, 330 renderer_data.css_selectors.insert(matching_css_selectors_[tab].begin(),
323 &renderer_data.css_selectors); 331 matching_css_selectors_[tab].end());
324 std::set<const ContentRule*> matching_rules = 332 std::set<const ContentRule*> matching_rules =
325 GetMatches(renderer_data, tab->GetBrowserContext()->IsOffTheRecord()); 333 GetMatches(renderer_data, tab->GetBrowserContext()->IsOffTheRecord());
326 if (matching_rules.empty() && !ContainsKey(active_rules_, tab)) 334 if (matching_rules.empty() && !ContainsKey(active_rules_, tab))
327 return; 335 return;
328 336
329 std::set<const ContentRule*>& prev_matching_rules = active_rules_[tab]; 337 std::set<const ContentRule*>& prev_matching_rules = active_rules_[tab];
330 ContentAction::ApplyInfo apply_info = {browser_context(), tab}; 338 ContentAction::ApplyInfo apply_info = {browser_context(), tab};
331 for (const ContentRule* rule : matching_rules) { 339 for (const ContentRule* rule : matching_rules) {
332 apply_info.priority = rule->priority(); 340 apply_info.priority = rule->priority();
333 if (!ContainsKey(prev_matching_rules, rule)) { 341 if (!ContainsKey(prev_matching_rules, rule)) {
334 rule->actions().Apply(rule->extension_id(), base::Time(), &apply_info); 342 rule->actions().Apply(rule->extension_id(), base::Time(), &apply_info);
335 } else { 343 } else {
336 rule->actions().Reapply(rule->extension_id(), base::Time(), &apply_info); 344 rule->actions().Reapply(rule->extension_id(), base::Time(), &apply_info);
337 } 345 }
338 } 346 }
339 for (const ContentRule* rule : prev_matching_rules) { 347 for (const ContentRule* rule : prev_matching_rules) {
340 if (!ContainsKey(matching_rules, rule)) { 348 if (!ContainsKey(matching_rules, rule)) {
341 apply_info.priority = rule->priority(); 349 apply_info.priority = rule->priority();
342 rule->actions().Revert(rule->extension_id(), base::Time(), &apply_info); 350 rule->actions().Revert(rule->extension_id(), base::Time(), &apply_info);
343 } 351 }
344 } 352 }
345 353
346 if (matching_rules.empty()) 354 if (matching_rules.empty())
347 active_rules_[tab].clear(); 355 active_rules_.erase(tab);
348 else 356 else
349 swap(matching_rules, prev_matching_rules); 357 swap(matching_rules, prev_matching_rules);
350 } 358 }
351 359
352 void ChromeContentRulesRegistry::EvaluateConditionsForAllTabs() { 360 void ChromeContentRulesRegistry::EvaluateConditionsForAllTabs() {
353 ForEachWebContents([this](content::WebContents* contents) { 361 for (chrome::BrowserIterator it; !it.done(); it.Next()) {
354 EvaluateConditionsForTab(contents); 362 Browser* browser = *it;
355 }); 363 if (!ManagingRulesForBrowserContext(browser->profile()))
364 continue;
365
366 for (int i = 0, tab_count = browser->tab_strip_model()->count();
367 i < tab_count;
368 ++i)
369 EvaluateConditionsForTab(browser->tab_strip_model()->GetWebContentsAt(i));
370 }
356 } 371 }
357 372
358 bool ChromeContentRulesRegistry::IsEmpty() const { 373 bool ChromeContentRulesRegistry::IsEmpty() const {
359 return match_id_to_rule_.empty() && content_rules_.empty() && 374 return match_id_to_rule_.empty() && content_rules_.empty() &&
360 url_matcher_.IsEmpty(); 375 url_matcher_.IsEmpty();
361 } 376 }
362 377
363 void ChromeContentRulesRegistry::UpdateMatchingCssSelectorsForTesting(
364 content::WebContents* contents,
365 const std::vector<std::string>& matching_css_selectors) {
366 css_condition_tracker_.UpdateMatchingCssSelectorsForTesting(
367 contents,
368 matching_css_selectors);
369 }
370
371 size_t ChromeContentRulesRegistry::GetActiveRulesCountForTesting() {
372 size_t count = 0;
373 for (auto web_contents_rules_pair : active_rules_)
374 count += web_contents_rules_pair.second.size();
375 return count;
376 }
377
378 ChromeContentRulesRegistry::~ChromeContentRulesRegistry() { 378 ChromeContentRulesRegistry::~ChromeContentRulesRegistry() {
379 } 379 }
380 380
381 base::Time ChromeContentRulesRegistry::GetExtensionInstallationTime( 381 base::Time ChromeContentRulesRegistry::GetExtensionInstallationTime(
382 const std::string& extension_id) const { 382 const std::string& extension_id) const {
383 if (!extension_info_map_.get()) // May be NULL during testing. 383 if (!extension_info_map_.get()) // May be NULL during testing.
384 return base::Time(); 384 return base::Time();
385 385
386 return extension_info_map_->GetInstallTime(extension_id); 386 return extension_info_map_->GetInstallTime(extension_id);
387 } 387 }
388 388
389 } // namespace extensions 389 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698