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

Side by Side Diff: chrome/common/extensions/manifest_handlers/automation.cc

Issue 377553003: Create a ManifestPermission implementation for Automation. (Closed) Base URL: https://chromium.googlesource.com/chromium/src@master
Patch Set: Simplify AutomationInfo::Clone Created 6 years, 5 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 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 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/common/extensions/manifest_handlers/automation.h" 5 #include "chrome/common/extensions/manifest_handlers/automation.h"
6 6
7 #include "base/strings/string_number_conversions.h"
8 #include "base/strings/utf_string_conversions.h" 7 #include "base/strings/utf_string_conversions.h"
9 #include "chrome/common/extensions/api/manifest_types.h" 8 #include "chrome/common/extensions/api/manifest_types.h"
10 #include "extensions/common/error_utils.h" 9 #include "extensions/common/error_utils.h"
10 #include "extensions/common/extensions_client.h"
11 #include "extensions/common/manifest_constants.h" 11 #include "extensions/common/manifest_constants.h"
12 #include "extensions/common/permissions/api_permission_set.h" 12 #include "extensions/common/permissions/api_permission_set.h"
13 #include "extensions/common/permissions/manifest_permission.h"
14 #include "extensions/common/permissions/permission_message.h"
15 #include "extensions/common/permissions/permission_message_util.h"
13 #include "extensions/common/permissions/permissions_data.h" 16 #include "extensions/common/permissions/permissions_data.h"
14 #include "extensions/common/url_pattern.h" 17 #include "extensions/common/url_pattern.h"
18 #include "grit/generated_resources.h"
19 #include "ipc/ipc_message.h"
20 #include "ipc/ipc_message_utils.h"
21 #include "ui/base/l10n/l10n_util.h"
15 22
16 namespace extensions { 23 namespace extensions {
17 24
18 namespace automation_errors { 25 namespace automation_errors {
19 const char kErrorDesktopTrueInteractFalse[] = 26 const char kErrorDesktopTrueInteractFalse[] =
20 "Cannot specify interactive=false if desktop=true is specified; " 27 "Cannot specify interactive=false if desktop=true is specified; "
21 "interactive=false will be ignored."; 28 "interactive=false will be ignored.";
22 const char kErrorDesktopTrueMatchesSpecified[] = 29 const char kErrorDesktopTrueMatchesSpecified[] =
23 "Cannot specify matches for Automation if desktop=true is specified; " 30 "Cannot specify matches for Automation if desktop=true is specified; "
24 "matches will be ignored."; 31 "matches will be ignored.";
25 const char kErrorInvalidMatch[] = "Invalid match pattern '*': *"; 32 const char kErrorInvalidMatch[] = "Invalid match pattern '*': *";
26 const char kErrorNoMatchesProvided[] = "No valid match patterns provided."; 33 const char kErrorNoMatchesProvided[] = "No valid match patterns provided.";
27 } 34 }
28 35
29 namespace errors = manifest_errors; 36 namespace errors = manifest_errors;
30 namespace keys = extensions::manifest_keys; 37 namespace keys = extensions::manifest_keys;
31 using api::manifest_types::Automation; 38 using api::manifest_types::Automation;
32 39
40 class AutomationManifestPermission : public ManifestPermission {
41 public:
42 explicit AutomationManifestPermission(
43 scoped_ptr<const AutomationInfo> automation_info)
44 : automation_info_(automation_info.Pass()) {}
45
46 // extensions::ManifestPermission overrides.
47 virtual std::string name() const OVERRIDE { return keys::kAutomation; }
48
49 virtual std::string id() const OVERRIDE { return keys::kAutomation; }
50
51 virtual bool HasMessages() const OVERRIDE { return GetMessages().size() > 0; }
52
53 virtual PermissionMessages GetMessages() const OVERRIDE {
Devlin 2014/07/18 22:38:51 We should probably not have these all in-lined...
aboxhall 2014/07/19 22:08:21 This is the .cc file, so they're not inlined, unle
Devlin 2014/07/21 19:45:35 Inlining has nothing to do with .h vs .cc file - i
aboxhall 2014/07/21 22:44:10 I see. But given these are virtual methods and nev
Devlin 2014/07/21 23:43:52 More than anything else... style. In theory, inli
aboxhall 2014/07/22 17:00:09 Done, although please note that this style is used
Devlin 2014/07/22 17:36:02 Thanks for humoring me. :)
54 PermissionMessages messages;
55 if (automation_info_->desktop) {
56 messages.push_back(PermissionMessage(
57 PermissionMessage::kFullAccess,
58 l10n_util::GetStringUTF16(IDS_EXTENSION_PROMPT_WARNING_FULL_ACCESS)));
59 } else if (automation_info_->matches.MatchesAllURLs()) {
60 messages.push_back(PermissionMessage(
61 PermissionMessage::kHostsAll,
62 l10n_util::GetStringUTF16(IDS_EXTENSION_PROMPT_WARNING_ALL_HOSTS)));
63 } else {
64 URLPatternSet regular_hosts;
65 std::set<PermissionMessage> message_set;
66 ExtensionsClient::Get()->FilterHostPermissions(
67 automation_info_->matches, &regular_hosts, &message_set);
68 messages.insert(messages.end(), message_set.begin(), message_set.end());
69
70 std::set<std::string> hosts =
71 permission_message_util::GetDistinctHosts(regular_hosts, true, true);
72 if (!hosts.empty())
73 messages.push_back(permission_message_util::CreateFromHostList(hosts));
74 }
75
76 return messages;
77 }
78
79 virtual bool FromValue(const base::Value* value) OVERRIDE {
80 base::string16 error;
81 automation_info_.reset(
82 AutomationInfo::FromValue(*value, NULL /* install_warnings */, &error)
83 .release());
84 return error.empty();
85 }
86
87 virtual scoped_ptr<base::Value> ToValue() const OVERRIDE {
88 return AutomationInfo::ToValue(*automation_info_).Pass();
89 }
90
91 virtual ManifestPermission* Clone() const OVERRIDE {
not at google - send to devlin 2014/07/18 16:07:22 (comment made even later) and you could implement
Devlin 2014/07/18 22:38:51 Still gonna need Clone() for line 243, so I'm not
aboxhall 2014/07/19 22:08:21 This is moot now, since Clone() is implemented in
92 scoped_ptr<const AutomationInfo> info(
93 AutomationInfo::Clone(*automation_info_.get()));
94 return new AutomationManifestPermission(info.Pass());
95 }
96
97 virtual ManifestPermission* Diff(
98 const ManifestPermission* rhs) const OVERRIDE {
99 const AutomationManifestPermission* other =
100 static_cast<const AutomationManifestPermission*>(rhs);
101
102 bool desktop =
103 automation_info_->desktop && !other->automation_info_->desktop;
104 bool interact =
105 automation_info_->interact && !other->automation_info_->interact;
106 URLPatternSet matches;
107 URLPatternSet::CreateDifference(
108 automation_info_->matches, other->automation_info_->matches, &matches);
109 scoped_ptr<const AutomationInfo> info(
110 new AutomationInfo(desktop, matches, interact));
111 return new AutomationManifestPermission(info.Pass());
Devlin 2014/07/18 22:38:51 nit: inline |info| (here and below)
aboxhall 2014/07/19 22:08:21 Done.
112 }
113
114 virtual ManifestPermission* Union(
115 const ManifestPermission* rhs) const OVERRIDE {
116 const AutomationManifestPermission* other =
117 static_cast<const AutomationManifestPermission*>(rhs);
118
119 bool desktop =
120 automation_info_->desktop || other->automation_info_->desktop;
121 bool interact =
122 automation_info_->interact || other->automation_info_->interact;
123 URLPatternSet matches;
124 URLPatternSet::CreateUnion(
125 automation_info_->matches, other->automation_info_->matches, &matches);
126 scoped_ptr<const AutomationInfo> info(
127 new AutomationInfo(desktop, matches, interact));
128 return new AutomationManifestPermission(info.Pass());
129 }
130
131 virtual ManifestPermission* Intersect(
132 const ManifestPermission* rhs) const OVERRIDE {
133 const AutomationManifestPermission* other =
134 static_cast<const AutomationManifestPermission*>(rhs);
135
136 bool desktop =
137 automation_info_->desktop && other->automation_info_->desktop;
138 bool interact =
139 automation_info_->interact && other->automation_info_->interact;
140 URLPatternSet matches;
141 URLPatternSet::CreateIntersection(
142 automation_info_->matches, other->automation_info_->matches, &matches);
143 scoped_ptr<const AutomationInfo> info(
144 new AutomationInfo(desktop, matches, interact));
145 return new AutomationManifestPermission(info.Pass());
146 }
147
148 virtual bool Contains(const ManifestPermission* rhs) const OVERRIDE {
149 const AutomationManifestPermission* other =
150 static_cast<const AutomationManifestPermission*>(rhs);
151
152 bool contains_desktop =
153 automation_info_->desktop || !other->automation_info_->desktop;
154 bool contains_interact =
155 automation_info_->interact || !other->automation_info_->interact;
156 bool contains_matches =
157 automation_info_->matches.Contains(other->automation_info_->matches);
158
159 return contains_desktop && contains_interact && contains_matches;
160 }
161
162 virtual bool Equal(const ManifestPermission* rhs) const OVERRIDE {
not at google - send to devlin 2014/07/18 16:07:22 (writing this comment before below) and you could
Devlin 2014/07/18 22:38:50 I don't think that's a great solution - it's a ton
aboxhall 2014/07/19 22:08:21 Moot: this is now in the superclass.
163 const AutomationManifestPermission* other =
164 static_cast<const AutomationManifestPermission*>(rhs);
165
166 bool same_desktop =
167 automation_info_->desktop == other->automation_info_->desktop;
168 bool same_interact =
169 automation_info_->interact == other->automation_info_->interact;
170 bool same_matches =
171 automation_info_->matches == other->automation_info_->matches;
172
173 return same_desktop && same_interact && same_matches;
174 }
175
176 virtual void Write(IPC::Message* m) const OVERRIDE {
177 base::ListValue singleton;
Devlin 2014/07/18 22:38:50 not sure "singleton" is the right name for this...
aboxhall 2014/07/19 22:08:21 Moot, now in superclass. FWIW, this was intended
178 base::Value* value = ToValue().release();
179 singleton.Append(value);
Devlin 2014/07/18 22:38:50 nit: inline value.
aboxhall 2014/07/19 22:08:21 Moot :)
180 IPC::WriteParam(m, singleton);
181 }
182
183 virtual bool Read(const IPC::Message* m, PickleIterator* iter) OVERRIDE {
not at google - send to devlin 2014/07/18 16:07:22 It makes a lot of sense to implement Read/Write in
Devlin 2014/07/18 22:38:51 +1
aboxhall 2014/07/19 22:08:21 Done.
184 base::ListValue singleton;
185 if (!IPC::ReadParam(m, iter, &singleton))
186 return false;
187 if (singleton.GetSize() != 1)
188 return false;
189 base::Value* value = NULL;
190 if (!singleton.Get(0, &value))
191 return false;
192 return FromValue(value);
193 }
194
195 virtual void Log(std::string* log) const OVERRIDE {
not at google - send to devlin 2014/07/18 16:07:22 Likewise. and it may make sense to implement Log
aboxhall 2014/07/19 22:08:21 Done.
196 base::ListValue singleton;
197 scoped_ptr<base::Value> value(ToValue());
198 singleton.Append(value.get());
199 IPC::LogParam(singleton, log);
200 }
201
202 private:
203 scoped_ptr<const AutomationInfo> automation_info_;
204 };
205
33 AutomationHandler::AutomationHandler() { 206 AutomationHandler::AutomationHandler() {
34 } 207 }
35 208
36 AutomationHandler::~AutomationHandler() { 209 AutomationHandler::~AutomationHandler() {
37 } 210 }
38 211
39 bool AutomationHandler::Parse(Extension* extension, base::string16* error) { 212 bool AutomationHandler::Parse(Extension* extension, base::string16* error) {
40 const base::Value* automation = NULL; 213 const base::Value* automation = NULL;
41 CHECK(extension->manifest()->Get(keys::kAutomation, &automation)); 214 CHECK(extension->manifest()->Get(keys::kAutomation, &automation));
42 std::vector<InstallWarning> install_warnings; 215 std::vector<InstallWarning> install_warnings;
43 scoped_ptr<AutomationInfo> info = 216 scoped_ptr<AutomationInfo> info =
44 AutomationInfo::FromValue(*automation, &install_warnings, error); 217 AutomationInfo::FromValue(*automation, &install_warnings, error);
45 if (!error->empty()) 218 if (!error->empty())
46 return false; 219 return false;
47 220
48 extension->AddInstallWarnings(install_warnings); 221 extension->AddInstallWarnings(install_warnings);
49 222
50 if (!info) 223 if (!info)
51 return true; 224 return true;
52 225
53 extension->SetManifestData(keys::kAutomation, info.release()); 226 extension->SetManifestData(keys::kAutomation, info.release());
54 return true; 227 return true;
55 } 228 }
56 229
57 const std::vector<std::string> AutomationHandler::Keys() const { 230 const std::vector<std::string> AutomationHandler::Keys() const {
58 return SingleKey(keys::kAutomation); 231 return SingleKey(keys::kAutomation);
59 } 232 }
60 233
234 ManifestPermission* AutomationHandler::CreatePermission() {
235 scoped_ptr<const AutomationInfo> info(new AutomationInfo);
236 return new AutomationManifestPermission(info.Pass());
237 }
238
239 ManifestPermission* AutomationHandler::CreateInitialRequiredPermission(
240 const Extension* extension) {
241 const AutomationInfo* info = AutomationInfo::Get(extension);
242 if (info)
243 return new AutomationManifestPermission(AutomationInfo::Clone(*info));
244 return NULL;
245 }
246
61 // static 247 // static
62 const AutomationInfo* AutomationInfo::Get(const Extension* extension) { 248 const AutomationInfo* AutomationInfo::Get(const Extension* extension) {
63 return static_cast<AutomationInfo*>( 249 return static_cast<AutomationInfo*>(
64 extension->GetManifestData(keys::kAutomation)); 250 extension->GetManifestData(keys::kAutomation));
65 } 251 }
66 252
67 // static 253 // static
254 scoped_ptr<AutomationInfo> AutomationInfo::FromValue(const base::Value& value) {
255 std::vector<InstallWarning> install_warnings;
256 base::string16 error;
257 return AutomationInfo::FromValue(value, &install_warnings, &error);
258 }
259
260 // static
68 scoped_ptr<AutomationInfo> AutomationInfo::FromValue( 261 scoped_ptr<AutomationInfo> AutomationInfo::FromValue(
69 const base::Value& value, 262 const base::Value& value,
70 std::vector<InstallWarning>* install_warnings, 263 std::vector<InstallWarning>* install_warnings,
71 base::string16* error) { 264 base::string16* error) {
72 scoped_ptr<Automation> automation = Automation::FromValue(value, error); 265 scoped_ptr<Automation> automation = Automation::FromValue(value, error);
73 if (!automation) 266 if (!automation)
74 return scoped_ptr<AutomationInfo>(); 267 return scoped_ptr<AutomationInfo>();
75 268
76 if (automation->as_boolean) { 269 if (automation->as_boolean) {
77 if (*automation->as_boolean) 270 if (*automation->as_boolean)
78 return make_scoped_ptr(new AutomationInfo()); 271 return make_scoped_ptr(new AutomationInfo());
79 return scoped_ptr<AutomationInfo>(); 272 return scoped_ptr<AutomationInfo>();
80 } 273 }
81 const Automation::Object& automation_object = *automation->as_object; 274 Automation::Object& automation_object = *automation->as_object;
82 275
83 bool desktop = false; 276 bool desktop = false;
84 bool interact = false; 277 bool interact = false;
85 if (automation_object.desktop && *automation_object.desktop) { 278 if (automation_object.desktop && *automation_object.desktop) {
86 desktop = true; 279 desktop = true;
87 interact = true; 280 interact = true;
88 if (automation_object.interact && !*automation_object.interact) { 281 if (automation_object.interact && !*automation_object.interact) {
89 // TODO(aboxhall): Do we want to allow this? 282 // TODO(aboxhall): Do we want to allow this?
90 install_warnings->push_back( 283 install_warnings->push_back(
91 InstallWarning(automation_errors::kErrorDesktopTrueInteractFalse)); 284 InstallWarning(automation_errors::kErrorDesktopTrueInteractFalse));
92 } 285 }
93 } else if (automation_object.interact && *automation_object.interact) { 286 } else if (automation_object.interact && *automation_object.interact) {
94 interact = true; 287 interact = true;
95 } 288 }
96 289
97 URLPatternSet matches; 290 URLPatternSet matches;
98 bool specified_matches = false; 291 bool specified_matches = false;
99 if (automation_object.matches) { 292 if (automation_object.matches) {
100 if (desktop) { 293 if (desktop) {
101 install_warnings->push_back( 294 install_warnings->push_back(
102 InstallWarning(automation_errors::kErrorDesktopTrueMatchesSpecified)); 295 InstallWarning(automation_errors::kErrorDesktopTrueMatchesSpecified));
103 } else { 296 } else {
104 specified_matches = true; 297 specified_matches = true;
298
105 for (std::vector<std::string>::iterator it = 299 for (std::vector<std::string>::iterator it =
106 automation_object.matches->begin(); 300 automation_object.matches->begin();
107 it != automation_object.matches->end(); 301 it != automation_object.matches->end();
108 ++it) { 302 ++it) {
109 // TODO(aboxhall): Refactor common logic from content_scripts_handler, 303 // TODO(aboxhall): Refactor common logic from content_scripts_handler,
110 // manifest_url_handler and user_script.cc into a single location and 304 // manifest_url_handler and user_script.cc into a single location and
111 // re-use here. 305 // re-use here.
112 URLPattern pattern(URLPattern::SCHEME_ALL & 306 URLPattern pattern(URLPattern::SCHEME_ALL &
113 ~URLPattern::SCHEME_CHROMEUI); 307 ~URLPattern::SCHEME_CHROMEUI);
114 URLPattern::ParseResult parse_result = pattern.Parse(*it); 308 URLPattern::ParseResult parse_result = pattern.Parse(*it);
309
115 if (parse_result != URLPattern::PARSE_SUCCESS) { 310 if (parse_result != URLPattern::PARSE_SUCCESS) {
116 install_warnings->push_back( 311 install_warnings->push_back(
117 InstallWarning(ErrorUtils::FormatErrorMessage( 312 InstallWarning(ErrorUtils::FormatErrorMessage(
118 automation_errors::kErrorInvalidMatch, 313 automation_errors::kErrorInvalidMatch,
119 *it, 314 *it,
120 URLPattern::GetParseResultString(parse_result)))); 315 URLPattern::GetParseResultString(parse_result))));
121 continue; 316 continue;
122 } 317 }
123 318
124 matches.AddPattern(pattern); 319 matches.AddPattern(pattern);
125 } 320 }
126 } 321 }
127 } 322 }
128 if (specified_matches && matches.is_empty()) 323 if (specified_matches && matches.is_empty()) {
129 install_warnings->push_back( 324 install_warnings->push_back(
130 InstallWarning(automation_errors::kErrorNoMatchesProvided)); 325 InstallWarning(automation_errors::kErrorNoMatchesProvided));
326 }
131 327
132 return make_scoped_ptr( 328 return make_scoped_ptr(new AutomationInfo(desktop, matches, interact));
133 new AutomationInfo(desktop, matches, interact, specified_matches));
134 } 329 }
135 330
136 AutomationInfo::AutomationInfo() 331 // static
137 : desktop(false), interact(false), specified_matches(false) { 332 scoped_ptr<base::Value> AutomationInfo::ToValue(const AutomationInfo& info) {
333 return AsManifestType(info)->ToValue().Pass();
138 } 334 }
335
336 // static
337 scoped_ptr<Automation> AutomationInfo::AsManifestType(
338 const AutomationInfo& info) {
339 Automation* automation = new Automation;
Devlin 2014/07/18 22:38:50 Why not make this a scoped_ptr from the start? It
aboxhall 2014/07/19 22:08:21 Good point, done.
340 if (!info.desktop && !info.interact && info.matches.size() == 0) {
341 automation->as_boolean.reset(new bool(true));
342 return make_scoped_ptr(automation).Pass();
343 }
344
345 Automation::Object* as_object = new Automation::Object;
346 as_object->desktop.reset(new bool(info.desktop));
347 as_object->interact.reset(new bool(info.interact));
348 if (info.matches.size() > 0) {
349 as_object->matches.reset(info.matches.ToStringVector().release());
350 }
351 automation->as_object.reset(as_object);
352 return make_scoped_ptr(automation).Pass();
353 }
354
355 // static
356 scoped_ptr<const AutomationInfo> AutomationInfo::Clone(
357 const AutomationInfo& info) {
358 const AutomationInfo* result =
359 new AutomationInfo(info.desktop, info.matches, info.interact);
360 return make_scoped_ptr(result);
361 }
362
363 AutomationInfo::AutomationInfo() : desktop(false), interact(false) {
364 }
365
139 AutomationInfo::AutomationInfo(bool desktop, 366 AutomationInfo::AutomationInfo(bool desktop,
140 const URLPatternSet& matches, 367 const URLPatternSet matches,
141 bool interact, 368 bool interact)
142 bool specified_matches) 369 : desktop(desktop), matches(matches), interact(interact) {
143 : desktop(desktop),
144 matches(matches),
145 interact(interact),
146 specified_matches(specified_matches) {
147 } 370 }
148 371
149 AutomationInfo::~AutomationInfo() { 372 AutomationInfo::~AutomationInfo() {
150 } 373 }
151 374
152 } // namespace extensions 375 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698