Add new certificateProvider extension API.
[chromium-blink-merge.git] / chrome / browser / extensions / api / declarative_content / declarative_content_css_condition_tracker.cc
blob733b8c148dc109f573a2eee028952832defda830
1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/extensions/api/declarative_content/declarative_content_css_condition_tracker.h"
7 #include <algorithm>
9 #include "base/stl_util.h"
10 #include "base/strings/stringprintf.h"
11 #include "base/values.h"
12 #include "chrome/browser/chrome_notification_types.h"
13 #include "chrome/browser/extensions/api/declarative_content/content_constants.h"
14 #include "chrome/browser/extensions/api/declarative_content/declarative_content_condition_tracker_delegate.h"
15 #include "chrome/browser/profiles/profile.h"
16 #include "content/public/browser/navigation_details.h"
17 #include "content/public/browser/notification_service.h"
18 #include "content/public/browser/notification_source.h"
19 #include "content/public/browser/render_process_host.h"
20 #include "extensions/common/extension_messages.h"
21 #include "ipc/ipc_message.h"
22 #include "ipc/ipc_message_macros.h"
24 namespace extensions {
26 namespace {
28 const char kInvalidTypeOfParameter[] = "Attribute '%s' has an invalid type";
30 } // namespace
33 // DeclarativeContentCssPredicate
36 DeclarativeContentCssPredicate::~DeclarativeContentCssPredicate() {
39 // static
40 scoped_ptr<DeclarativeContentCssPredicate>
41 DeclarativeContentCssPredicate::Create(
42 const base::Value& value,
43 std::string* error) {
44 std::vector<std::string> css_rules;
45 const base::ListValue* css_rules_value = nullptr;
46 if (value.GetAsList(&css_rules_value)) {
47 for (size_t i = 0; i < css_rules_value->GetSize(); ++i) {
48 std::string css_rule;
49 if (!css_rules_value->GetString(i, &css_rule)) {
50 *error = base::StringPrintf(kInvalidTypeOfParameter,
51 declarative_content_constants::kCss);
52 return scoped_ptr<DeclarativeContentCssPredicate>();
54 css_rules.push_back(css_rule);
56 } else {
57 *error = base::StringPrintf(kInvalidTypeOfParameter,
58 declarative_content_constants::kCss);
59 return scoped_ptr<DeclarativeContentCssPredicate>();
62 return !css_rules.empty() ?
63 make_scoped_ptr(new DeclarativeContentCssPredicate(css_rules)) :
64 scoped_ptr<DeclarativeContentCssPredicate>();
67 DeclarativeContentCssPredicate::DeclarativeContentCssPredicate(
68 const std::vector<std::string>& css_selectors)
69 : css_selectors_(css_selectors) {
70 DCHECK(!css_selectors.empty());
74 // PerWebContentsTracker
77 DeclarativeContentCssConditionTracker::PerWebContentsTracker::
78 PerWebContentsTracker(
79 content::WebContents* contents,
80 const RequestEvaluationCallback& request_evaluation,
81 const WebContentsDestroyedCallback& web_contents_destroyed)
82 : WebContentsObserver(contents),
83 request_evaluation_(request_evaluation),
84 web_contents_destroyed_(web_contents_destroyed) {
87 DeclarativeContentCssConditionTracker::PerWebContentsTracker::
88 ~PerWebContentsTracker() {
91 scoped_ptr<DeclarativeContentCssPredicate>
92 DeclarativeContentCssConditionTracker::CreatePredicate(
93 const Extension* extension,
94 const base::Value& value,
95 std::string* error) {
96 return DeclarativeContentCssPredicate::Create(value, error);
99 void DeclarativeContentCssConditionTracker::PerWebContentsTracker::
100 OnWebContentsNavigation(const content::LoadCommittedDetails& details,
101 const content::FrameNavigateParams& params) {
102 if (details.is_in_page) {
103 // Within-page navigations don't change the set of elements that
104 // exist, and we only support filtering on the top-level URL, so
105 // this can't change which rules match.
106 return;
109 // Top-level navigation produces a new document. Initially, the
110 // document's empty, so no CSS rules match. The renderer will send
111 // an ExtensionHostMsg_OnWatchedPageChange later if any CSS rules
112 // match.
113 matching_css_selectors_.clear();
114 request_evaluation_.Run(web_contents());
117 void DeclarativeContentCssConditionTracker::PerWebContentsTracker::
118 UpdateMatchingCssSelectorsForTesting(
119 const std::vector<std::string>& matching_css_selectors) {
120 matching_css_selectors_.clear();
121 matching_css_selectors_.insert(matching_css_selectors.begin(),
122 matching_css_selectors.end());
123 request_evaluation_.Run(web_contents());
126 bool
127 DeclarativeContentCssConditionTracker::PerWebContentsTracker::
128 OnMessageReceived(
129 const IPC::Message& message) {
130 bool handled = true;
131 IPC_BEGIN_MESSAGE_MAP(PerWebContentsTracker, message)
132 IPC_MESSAGE_HANDLER(ExtensionHostMsg_OnWatchedPageChange,
133 OnWatchedPageChange)
134 IPC_MESSAGE_UNHANDLED(handled = false)
135 IPC_END_MESSAGE_MAP()
136 return handled;
139 void DeclarativeContentCssConditionTracker::PerWebContentsTracker::
140 WebContentsDestroyed() {
141 web_contents_destroyed_.Run(web_contents());
144 void
145 DeclarativeContentCssConditionTracker::PerWebContentsTracker::
146 OnWatchedPageChange(
147 const std::vector<std::string>& css_selectors) {
148 matching_css_selectors_.clear();
149 matching_css_selectors_.insert(css_selectors.begin(), css_selectors.end());
150 request_evaluation_.Run(web_contents());
154 // DeclarativeContentCssConditionTracker
157 DeclarativeContentCssConditionTracker::DeclarativeContentCssConditionTracker(
158 content::BrowserContext* context,
159 DeclarativeContentConditionTrackerDelegate* delegate)
160 : context_(context),
161 delegate_(delegate) {
162 registrar_.Add(this,
163 content::NOTIFICATION_RENDERER_PROCESS_CREATED,
164 content::NotificationService::AllBrowserContextsAndSources());
167 DeclarativeContentCssConditionTracker::
168 ~DeclarativeContentCssConditionTracker() {}
170 // We use the sorted propery of the set for equality checks with
171 // watched_css_selectors_, which is guaranteed to be sorted because it's set
172 // from the set contents.
173 void DeclarativeContentCssConditionTracker::SetWatchedCssSelectors(
174 const std::set<std::string>& new_watched_css_selectors) {
175 if (new_watched_css_selectors.size() != watched_css_selectors_.size() ||
176 !std::equal(new_watched_css_selectors.begin(),
177 new_watched_css_selectors.end(),
178 watched_css_selectors_.begin())) {
179 watched_css_selectors_.assign(new_watched_css_selectors.begin(),
180 new_watched_css_selectors.end());
182 for (content::RenderProcessHost::iterator it(
183 content::RenderProcessHost::AllHostsIterator());
184 !it.IsAtEnd();
185 it.Advance()) {
186 InstructRenderProcessIfManagingBrowserContext(it.GetCurrentValue());
191 void DeclarativeContentCssConditionTracker::TrackForWebContents(
192 content::WebContents* contents) {
193 per_web_contents_tracker_[contents] =
194 make_linked_ptr(new PerWebContentsTracker(
195 contents,
196 base::Bind(&DeclarativeContentConditionTrackerDelegate::
197 RequestEvaluation,
198 base::Unretained(delegate_)),
199 base::Bind(&DeclarativeContentCssConditionTracker::
200 DeletePerWebContentsTracker,
201 base::Unretained(this))));
202 // Note: the condition is always false until we receive OnWatchedPageChange,
203 // so there's no need to evaluate it here.
206 void DeclarativeContentCssConditionTracker::OnWebContentsNavigation(
207 content::WebContents* contents,
208 const content::LoadCommittedDetails& details,
209 const content::FrameNavigateParams& params) {
210 DCHECK(ContainsKey(per_web_contents_tracker_, contents));
211 per_web_contents_tracker_[contents]->OnWebContentsNavigation(details, params);
214 bool DeclarativeContentCssConditionTracker::EvaluatePredicate(
215 const DeclarativeContentCssPredicate* predicate,
216 content::WebContents* contents) const {
217 auto loc = per_web_contents_tracker_.find(contents);
218 DCHECK(loc != per_web_contents_tracker_.end());
219 const base::hash_set<std::string>& matching_css_selectors =
220 loc->second->matching_css_selectors();
221 for (const std::string& predicate_css_selector : predicate->css_selectors()) {
222 if (!ContainsKey(matching_css_selectors, predicate_css_selector))
223 return false;
226 return true;
229 void DeclarativeContentCssConditionTracker::
230 UpdateMatchingCssSelectorsForTesting(
231 content::WebContents* contents,
232 const std::vector<std::string>& matching_css_selectors) {
233 DCHECK(ContainsKey(per_web_contents_tracker_, contents));
234 per_web_contents_tracker_[contents]->
235 UpdateMatchingCssSelectorsForTesting(matching_css_selectors);
238 void DeclarativeContentCssConditionTracker::Observe(
239 int type,
240 const content::NotificationSource& source,
241 const content::NotificationDetails& details) {
242 switch (type) {
243 case content::NOTIFICATION_RENDERER_PROCESS_CREATED: {
244 content::RenderProcessHost* process =
245 content::Source<content::RenderProcessHost>(source).ptr();
246 InstructRenderProcessIfManagingBrowserContext(process);
247 break;
252 void DeclarativeContentCssConditionTracker::
253 InstructRenderProcessIfManagingBrowserContext(
254 content::RenderProcessHost* process) {
255 if (delegate_->ShouldManageConditionsForBrowserContext(
256 process->GetBrowserContext())) {
257 process->Send(new ExtensionMsg_WatchPages(watched_css_selectors_));
261 void DeclarativeContentCssConditionTracker::DeletePerWebContentsTracker(
262 content::WebContents* contents) {
263 DCHECK(ContainsKey(per_web_contents_tracker_, contents));
264 per_web_contents_tracker_.erase(contents);
267 } // namespace extensions