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
3 // found in the LICENSE file.
5 #include "chrome/common/extensions/manifest_handlers/automation.h"
7 #include "base/strings/string_number_conversions.h"
8 #include "base/strings/utf_string_conversions.h"
9 #include "chrome/common/extensions/api/manifest_types.h"
10 #include "extensions/common/error_utils.h"
11 #include "extensions/common/manifest_constants.h"
12 #include "extensions/common/permissions/api_permission_set.h"
13 #include "extensions/common/permissions/permissions_data.h"
14 #include "extensions/common/url_pattern.h"
16 namespace extensions {
18 namespace automation_errors {
19 const char kErrorDesktopTrueInteractFalse[] =
20 "Cannot specify interactive=false if desktop=true is specified; "
21 "interactive=false will be ignored.";
22 const char kErrorDesktopTrueMatchesSpecified[] =
23 "Cannot specify matches for Automation if desktop=true is specified; "
24 "matches will be ignored.";
25 const char kErrorInvalidMatch[] = "Invalid match pattern '*': *";
26 const char kErrorNoMatchesProvided[] = "No valid match patterns provided.";
29 namespace errors = manifest_errors;
30 namespace keys = extensions::manifest_keys;
31 using api::manifest_types::Automation;
33 AutomationHandler::AutomationHandler() {
36 AutomationHandler::~AutomationHandler() {
39 bool AutomationHandler::Parse(Extension* extension, base::string16* error) {
40 const base::Value* automation = NULL;
41 CHECK(extension->manifest()->Get(keys::kAutomation, &automation));
42 std::vector<InstallWarning> install_warnings;
43 scoped_ptr<AutomationInfo> info =
44 AutomationInfo::FromValue(*automation, &install_warnings, error);
48 extension->AddInstallWarnings(install_warnings);
53 extension->SetManifestData(keys::kAutomation, info.release());
57 const std::vector<std::string> AutomationHandler::Keys() const {
58 return SingleKey(keys::kAutomation);
62 const AutomationInfo* AutomationInfo::Get(const Extension* extension) {
63 return static_cast<AutomationInfo*>(
64 extension->GetManifestData(keys::kAutomation));
68 scoped_ptr<AutomationInfo> AutomationInfo::FromValue(
69 const base::Value& value,
70 std::vector<InstallWarning>* install_warnings,
71 base::string16* error) {
72 scoped_ptr<Automation> automation = Automation::FromValue(value, error);
74 return scoped_ptr<AutomationInfo>();
76 if (automation->as_boolean) {
77 if (*automation->as_boolean)
78 return make_scoped_ptr(new AutomationInfo());
79 return scoped_ptr<AutomationInfo>();
81 const Automation::Object& automation_object = *automation->as_object;
84 bool interact = false;
85 if (automation_object.desktop && *automation_object.desktop) {
88 if (automation_object.interact && !*automation_object.interact) {
89 // TODO(aboxhall): Do we want to allow this?
90 install_warnings->push_back(
91 InstallWarning(automation_errors::kErrorDesktopTrueInteractFalse));
93 } else if (automation_object.interact && *automation_object.interact) {
97 URLPatternSet matches;
98 bool specified_matches = false;
99 if (automation_object.matches) {
101 install_warnings->push_back(
102 InstallWarning(automation_errors::kErrorDesktopTrueMatchesSpecified));
104 specified_matches = true;
105 for (std::vector<std::string>::iterator it =
106 automation_object.matches->begin();
107 it != automation_object.matches->end();
109 // TODO(aboxhall): Refactor common logic from content_scripts_handler,
110 // manifest_url_handler and user_script.cc into a single location and
112 URLPattern pattern(URLPattern::SCHEME_ALL &
113 ~URLPattern::SCHEME_CHROMEUI);
114 URLPattern::ParseResult parse_result = pattern.Parse(*it);
115 if (parse_result != URLPattern::PARSE_SUCCESS) {
116 install_warnings->push_back(
117 InstallWarning(ErrorUtils::FormatErrorMessage(
118 automation_errors::kErrorInvalidMatch,
120 URLPattern::GetParseResultString(parse_result))));
124 matches.AddPattern(pattern);
128 if (specified_matches && matches.is_empty())
129 install_warnings->push_back(
130 InstallWarning(automation_errors::kErrorNoMatchesProvided));
132 return make_scoped_ptr(
133 new AutomationInfo(desktop, matches, interact, specified_matches));
136 AutomationInfo::AutomationInfo()
137 : desktop(false), interact(false), specified_matches(false) {
139 AutomationInfo::AutomationInfo(bool desktop,
140 const URLPatternSet& matches,
142 bool specified_matches)
146 specified_matches(specified_matches) {
149 AutomationInfo::~AutomationInfo() {
152 } // namespace extensions