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

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

Issue 1159733004: Encapsulate CSS selector declarative content condition tracking (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@stars-declarative-content-range-for
Patch Set: iwyu 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"
12 #include "chrome/browser/extensions/extension_util.h" 11 #include "chrome/browser/extensions/extension_util.h"
13 #include "chrome/browser/profiles/profile.h" 12 #include "chrome/browser/profiles/profile.h"
14 #include "chrome/browser/ui/browser.h" 13 #include "chrome/browser/ui/browser.h"
15 #include "chrome/browser/ui/browser_iterator.h" 14 #include "chrome/browser/ui/browser_iterator.h"
16 #include "chrome/browser/ui/tabs/tab_strip_model.h" 15 #include "chrome/browser/ui/tabs/tab_strip_model.h"
17 #include "content/public/browser/navigation_details.h" 16 #include "content/public/browser/navigation_details.h"
18 #include "content/public/browser/notification_service.h" 17 #include "content/public/browser/notification_service.h"
19 #include "content/public/browser/notification_source.h" 18 #include "content/public/browser/notification_source.h"
20 #include "content/public/browser/render_process_host.h"
21 #include "content/public/browser/web_contents.h" 19 #include "content/public/browser/web_contents.h"
22 #include "extensions/browser/api/declarative/rules_registry_service.h" 20 #include "extensions/browser/api/declarative/rules_registry_service.h"
23 #include "extensions/browser/extension_registry.h" 21 #include "extensions/browser/extension_registry.h"
24 #include "extensions/browser/extension_system.h" 22 #include "extensions/browser/extension_system.h"
25 #include "extensions/common/extension_messages.h"
26 23
27 using url_matcher::URLMatcherConditionSet; 24 using url_matcher::URLMatcherConditionSet;
28 25
29 namespace extensions { 26 namespace extensions {
30 27
31 ChromeContentRulesRegistry::ChromeContentRulesRegistry( 28 ChromeContentRulesRegistry::ChromeContentRulesRegistry(
32 content::BrowserContext* browser_context, 29 content::BrowserContext* browser_context,
33 RulesCacheDelegate* cache_delegate) 30 RulesCacheDelegate* cache_delegate)
34 : ContentRulesRegistry(browser_context, 31 : ContentRulesRegistry(browser_context,
35 declarative_content_constants::kOnPageChanged, 32 declarative_content_constants::kOnPageChanged,
36 content::BrowserThread::UI, 33 content::BrowserThread::UI,
37 cache_delegate, 34 cache_delegate,
38 RulesRegistryService::kDefaultRulesRegistryID) { 35 RulesRegistryService::kDefaultRulesRegistryID),
36 css_condition_tracker_(browser_context, this) {
39 extension_info_map_ = ExtensionSystem::Get(browser_context)->info_map(); 37 extension_info_map_ = ExtensionSystem::Get(browser_context)->info_map();
40 38
41 registrar_.Add(this, 39 registrar_.Add(this,
42 content::NOTIFICATION_RENDERER_PROCESS_CREATED,
43 content::NotificationService::AllBrowserContextsAndSources());
44 registrar_.Add(this,
45 content::NOTIFICATION_WEB_CONTENTS_DESTROYED, 40 content::NOTIFICATION_WEB_CONTENTS_DESTROYED,
46 content::NotificationService::AllBrowserContextsAndSources()); 41 content::NotificationService::AllBrowserContextsAndSources());
47 } 42 }
48 43
49 void ChromeContentRulesRegistry::Observe( 44 void ChromeContentRulesRegistry::Observe(
50 int type, 45 int type,
51 const content::NotificationSource& source, 46 const content::NotificationSource& source,
52 const content::NotificationDetails& details) { 47 const content::NotificationDetails& details) {
53 switch (type) { 48 switch (type) {
54 case content::NOTIFICATION_RENDERER_PROCESS_CREATED: {
55 content::RenderProcessHost* process =
56 content::Source<content::RenderProcessHost>(source).ptr();
57 InstructRenderProcessIfSameBrowserContext(process);
58 break;
59 }
60 case content::NOTIFICATION_WEB_CONTENTS_DESTROYED: { 49 case content::NOTIFICATION_WEB_CONTENTS_DESTROYED: {
not at google - send to devlin 2015/06/01 22:51:11 Another case for using a WebContentsObserver here
Mike Wittman 2015/06/05 01:17:44 Yes, I'll look at this in a future CL.
61 content::WebContents* tab = 50 content::WebContents* tab =
62 content::Source<content::WebContents>(source).ptr(); 51 content::Source<content::WebContents>(source).ptr();
63 // Note that neither non-tab WebContents nor tabs from other browser 52 // Note that neither non-tab WebContents nor tabs from other browser
64 // contexts will be in the map. 53 // contexts will be in the map.
65 active_rules_.erase(tab); 54 active_rules_.erase(tab);
66 matching_css_selectors_.erase(tab);
67 break; 55 break;
68 } 56 }
69 } 57 }
70 } 58 }
71 59
72 void ChromeContentRulesRegistry::Apply( 60 void ChromeContentRulesRegistry::RequestEvaluation(
61 content::WebContents* contents) {
62 EvaluateConditionsForTab(contents);
63 }
64
65 bool ChromeContentRulesRegistry::ShouldManageConditionsForBrowserContext(
66 content::BrowserContext* context) {
67 return ManagingRulesForBrowserContext(context);
68 }
69
70 void ChromeContentRulesRegistry::UpdateMatchingCssSelectorsForTesting(
73 content::WebContents* contents, 71 content::WebContents* contents,
74 const std::vector<std::string>& matching_css_selectors) { 72 const std::vector<std::string>& matching_css_selectors) {
75 matching_css_selectors_[contents] = matching_css_selectors; 73 css_condition_tracker_.UpdateMatchingCssSelectorsForTesting(
76 74 contents,
77 EvaluateConditionsForTab(contents); 75 matching_css_selectors);
78 } 76 }
79 77
80 void ChromeContentRulesRegistry::DidNavigateMainFrame( 78 void ChromeContentRulesRegistry::DidNavigateMainFrame(
81 content::WebContents* contents, 79 content::WebContents* contents,
82 const content::LoadCommittedDetails& details, 80 const content::LoadCommittedDetails& details,
83 const content::FrameNavigateParams& params) { 81 const content::FrameNavigateParams& params) {
84 OnTabNavigation(contents, details.is_in_page); 82 css_condition_tracker_.OnWebContentsNavigation(contents, details, params);
85 } 83 }
86 84
87 void ChromeContentRulesRegistry::DidNavigateMainFrameOfOriginalContext( 85 void ChromeContentRulesRegistry::DidNavigateMainFrameOfOriginalContext(
88 content::WebContents* contents, 86 content::WebContents* contents,
89 const content::LoadCommittedDetails& details, 87 const content::LoadCommittedDetails& details,
90 const content::FrameNavigateParams& params) { 88 const content::FrameNavigateParams& params) {
91 DCHECK(browser_context()->IsOffTheRecord()); 89 DCHECK(browser_context()->IsOffTheRecord());
92 OnTabNavigation(contents, details.is_in_page); 90 css_condition_tracker_.OnWebContentsNavigation(contents, details, params);
93 }
94
95 void ChromeContentRulesRegistry::OnTabNavigation(content::WebContents* tab,
96 bool is_in_page_navigation) {
97 if (is_in_page_navigation) {
98 // Within-page navigations don't change the set of elements that
99 // exist, and we only support filtering on the top-level URL, so
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);
110 } 91 }
111 92
112 bool ChromeContentRulesRegistry::ManagingRulesForBrowserContext( 93 bool ChromeContentRulesRegistry::ManagingRulesForBrowserContext(
113 content::BrowserContext* context) { 94 content::BrowserContext* context) {
114 // Manage both the normal context and incognito contexts associated with it. 95 // Manage both the normal context and incognito contexts associated with it.
115 return Profile::FromBrowserContext(context)->GetOriginalProfile() == 96 return Profile::FromBrowserContext(context)->GetOriginalProfile() ==
116 Profile::FromBrowserContext(browser_context()); 97 Profile::FromBrowserContext(browser_context());
117 } 98 }
118 99
119 std::set<const ContentRule*> ChromeContentRulesRegistry::GetMatches( 100 std::set<const ContentRule*> ChromeContentRulesRegistry::GetMatches(
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
212 // Register url patterns in url_matcher_. 193 // Register url patterns in url_matcher_.
213 URLMatcherConditionSet::Vector all_new_condition_sets; 194 URLMatcherConditionSet::Vector all_new_condition_sets;
214 for (const std::pair<ContentRule::GlobalRuleId, 195 for (const std::pair<ContentRule::GlobalRuleId,
215 linked_ptr<const ContentRule>>& rule_id_rule_pair : 196 linked_ptr<const ContentRule>>& rule_id_rule_pair :
216 new_content_rules) { 197 new_content_rules) {
217 const linked_ptr<const ContentRule>& rule = rule_id_rule_pair.second; 198 const linked_ptr<const ContentRule>& rule = rule_id_rule_pair.second;
218 rule->conditions().GetURLMatcherConditionSets(&all_new_condition_sets); 199 rule->conditions().GetURLMatcherConditionSets(&all_new_condition_sets);
219 } 200 }
220 url_matcher_.AddConditionSets(all_new_condition_sets); 201 url_matcher_.AddConditionSets(all_new_condition_sets);
221 202
222 UpdateConditionCache(); 203 UpdateCssSelectorsFromRules();
223 EvaluateConditionsForAllTabs(); 204 EvaluateConditionsForAllTabs();
224 205
225 return std::string(); 206 return std::string();
226 } 207 }
227 208
228 std::string ChromeContentRulesRegistry::RemoveRulesImpl( 209 std::string ChromeContentRulesRegistry::RemoveRulesImpl(
229 const std::string& extension_id, 210 const std::string& extension_id,
230 const std::vector<std::string>& rule_identifiers) { 211 const std::vector<std::string>& rule_identifiers) {
231 // URLMatcherConditionSet IDs that can be removed from URLMatcher. 212 // URLMatcherConditionSet IDs that can be removed from URLMatcher.
232 std::vector<URLMatcherConditionSet::ID> remove_from_url_matcher; 213 std::vector<URLMatcherConditionSet::ID> remove_from_url_matcher;
(...skipping 26 matching lines...) Expand all
259 } 240 }
260 } 241 }
261 242
262 // Remove reference to actual rule. 243 // Remove reference to actual rule.
263 content_rules_.erase(content_rules_entry); 244 content_rules_.erase(content_rules_entry);
264 } 245 }
265 246
266 // Clear URLMatcher based on condition_set_ids that are not needed any more. 247 // Clear URLMatcher based on condition_set_ids that are not needed any more.
267 url_matcher_.RemoveConditionSets(remove_from_url_matcher); 248 url_matcher_.RemoveConditionSets(remove_from_url_matcher);
268 249
269 UpdateConditionCache(); 250 UpdateCssSelectorsFromRules();
270 251
271 return std::string(); 252 return std::string();
272 } 253 }
273 254
274 std::string ChromeContentRulesRegistry::RemoveAllRulesImpl( 255 std::string ChromeContentRulesRegistry::RemoveAllRulesImpl(
275 const std::string& extension_id) { 256 const std::string& extension_id) {
276 // Search all identifiers of rules that belong to extension |extension_id|. 257 // Search all identifiers of rules that belong to extension |extension_id|.
277 std::vector<std::string> rule_identifiers; 258 std::vector<std::string> rule_identifiers;
278 for (const std::pair<ContentRule::GlobalRuleId, 259 for (const std::pair<ContentRule::GlobalRuleId,
279 linked_ptr<const ContentRule>>& rule_id_rule_pair : 260 linked_ptr<const ContentRule>>& rule_id_rule_pair :
280 content_rules_) { 261 content_rules_) {
281 const ContentRule::GlobalRuleId& global_rule_id = rule_id_rule_pair.first; 262 const ContentRule::GlobalRuleId& global_rule_id = rule_id_rule_pair.first;
282 if (global_rule_id.first == extension_id) 263 if (global_rule_id.first == extension_id)
283 rule_identifiers.push_back(global_rule_id.second); 264 rule_identifiers.push_back(global_rule_id.second);
284 } 265 }
285 266
286 return RemoveRulesImpl(extension_id, rule_identifiers); 267 return RemoveRulesImpl(extension_id, rule_identifiers);
287 } 268 }
288 269
289 void ChromeContentRulesRegistry::UpdateConditionCache() { 270 void ChromeContentRulesRegistry::UpdateCssSelectorsFromRules() {
290 std::set<std::string> css_selectors; // We rely on this being sorted. 271 std::set<std::string> css_selectors; // We rely on this being sorted.
291 for (const std::pair<ContentRule::GlobalRuleId, 272 for (const std::pair<ContentRule::GlobalRuleId,
292 linked_ptr<const ContentRule>>& rule_id_rule_pair : 273 linked_ptr<const ContentRule>>& rule_id_rule_pair :
293 content_rules_) { 274 content_rules_) {
294 const ContentRule& rule = *rule_id_rule_pair.second; 275 const ContentRule& rule = *rule_id_rule_pair.second;
295 for (const linked_ptr<const ContentCondition>& condition : 276 for (const linked_ptr<const ContentCondition>& condition :
296 rule.conditions()) { 277 rule.conditions()) {
297 const std::vector<std::string>& condition_css_selectors = 278 const std::vector<std::string>& condition_css_selectors =
298 condition->css_selectors(); 279 condition->css_selectors();
299 css_selectors.insert(condition_css_selectors.begin(), 280 css_selectors.insert(condition_css_selectors.begin(),
300 condition_css_selectors.end()); 281 condition_css_selectors.end());
301 } 282 }
302 } 283 }
303 284
304 if (css_selectors.size() != watched_css_selectors_.size() || 285 css_condition_tracker_.SetWatchedCssSelectors(css_selectors);
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_));
324 } 286 }
325 287
326 void ChromeContentRulesRegistry::EvaluateConditionsForTab( 288 void ChromeContentRulesRegistry::EvaluateConditionsForTab(
327 content::WebContents* tab) { 289 content::WebContents* tab) {
328 extensions::RendererContentMatchData renderer_data; 290 extensions::RendererContentMatchData renderer_data;
329 renderer_data.page_url_matches = url_matcher_.MatchURL(tab->GetURL()); 291 renderer_data.page_url_matches = url_matcher_.MatchURL(tab->GetURL());
330 renderer_data.css_selectors.insert(matching_css_selectors_[tab].begin(), 292 css_condition_tracker_.GetMatchingCssSelectors(tab,
331 matching_css_selectors_[tab].end()); 293 &renderer_data.css_selectors);
332 std::set<const ContentRule*> matching_rules = 294 std::set<const ContentRule*> matching_rules =
333 GetMatches(renderer_data, tab->GetBrowserContext()->IsOffTheRecord()); 295 GetMatches(renderer_data, tab->GetBrowserContext()->IsOffTheRecord());
334 if (matching_rules.empty() && !ContainsKey(active_rules_, tab)) 296 if (matching_rules.empty() && !ContainsKey(active_rules_, tab))
335 return; 297 return;
336 298
337 std::set<const ContentRule*>& prev_matching_rules = active_rules_[tab]; 299 std::set<const ContentRule*>& prev_matching_rules = active_rules_[tab];
338 ContentAction::ApplyInfo apply_info = {browser_context(), tab}; 300 ContentAction::ApplyInfo apply_info = {browser_context(), tab};
339 for (const ContentRule* rule : matching_rules) { 301 for (const ContentRule* rule : matching_rules) {
340 apply_info.priority = rule->priority(); 302 apply_info.priority = rule->priority();
341 if (!ContainsKey(prev_matching_rules, rule)) { 303 if (!ContainsKey(prev_matching_rules, rule)) {
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
380 342
381 base::Time ChromeContentRulesRegistry::GetExtensionInstallationTime( 343 base::Time ChromeContentRulesRegistry::GetExtensionInstallationTime(
382 const std::string& extension_id) const { 344 const std::string& extension_id) const {
383 if (!extension_info_map_.get()) // May be NULL during testing. 345 if (!extension_info_map_.get()) // May be NULL during testing.
384 return base::Time(); 346 return base::Time();
385 347
386 return extension_info_map_->GetInstallTime(extension_id); 348 return extension_info_map_->GetInstallTime(extension_id);
387 } 349 }
388 350
389 } // namespace extensions 351 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698