• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
4 
5 #include "chrome/common/extensions/manifest_handlers/automation.h"
6 
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"
15 
16 namespace extensions {
17 
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.";
27 }
28 
29 namespace errors = manifest_errors;
30 namespace keys = extensions::manifest_keys;
31 using api::manifest_types::Automation;
32 
AutomationHandler()33 AutomationHandler::AutomationHandler() {
34 }
35 
~AutomationHandler()36 AutomationHandler::~AutomationHandler() {
37 }
38 
Parse(Extension * extension,base::string16 * error)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);
45   if (!error->empty())
46     return false;
47 
48   extension->AddInstallWarnings(install_warnings);
49 
50   if (!info)
51     return true;
52 
53   extension->SetManifestData(keys::kAutomation, info.release());
54   return true;
55 }
56 
Keys() const57 const std::vector<std::string> AutomationHandler::Keys() const {
58   return SingleKey(keys::kAutomation);
59 }
60 
61 // static
Get(const Extension * extension)62 const AutomationInfo* AutomationInfo::Get(const Extension* extension) {
63   return static_cast<AutomationInfo*>(
64       extension->GetManifestData(keys::kAutomation));
65 }
66 
67 // static
FromValue(const base::Value & value,std::vector<InstallWarning> * install_warnings,base::string16 * error)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);
73   if (!automation)
74     return scoped_ptr<AutomationInfo>();
75 
76   if (automation->as_boolean) {
77     if (*automation->as_boolean)
78       return make_scoped_ptr(new AutomationInfo());
79     return scoped_ptr<AutomationInfo>();
80   }
81   const Automation::Object& automation_object = *automation->as_object;
82 
83   bool desktop = false;
84   bool interact = false;
85   if (automation_object.desktop && *automation_object.desktop) {
86     desktop = true;
87     interact = true;
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));
92     }
93   } else if (automation_object.interact && *automation_object.interact) {
94     interact = true;
95   }
96 
97   URLPatternSet matches;
98   bool specified_matches = false;
99   if (automation_object.matches) {
100     if (desktop) {
101       install_warnings->push_back(
102           InstallWarning(automation_errors::kErrorDesktopTrueMatchesSpecified));
103     } else {
104       specified_matches = true;
105       for (std::vector<std::string>::iterator it =
106                automation_object.matches->begin();
107            it != automation_object.matches->end();
108            ++it) {
109         // TODO(aboxhall): Refactor common logic from content_scripts_handler,
110         // manifest_url_handler and user_script.cc into a single location and
111         // re-use here.
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,
119                   *it,
120                   URLPattern::GetParseResultString(parse_result))));
121           continue;
122         }
123 
124         matches.AddPattern(pattern);
125       }
126     }
127   }
128   if (specified_matches && matches.is_empty())
129     install_warnings->push_back(
130         InstallWarning(automation_errors::kErrorNoMatchesProvided));
131 
132   return make_scoped_ptr(
133       new AutomationInfo(desktop, matches, interact, specified_matches));
134 }
135 
AutomationInfo()136 AutomationInfo::AutomationInfo()
137     : desktop(false), interact(false), specified_matches(false) {
138 }
AutomationInfo(bool desktop,const URLPatternSet & matches,bool interact,bool specified_matches)139 AutomationInfo::AutomationInfo(bool desktop,
140                                const URLPatternSet& matches,
141                                bool interact,
142                                bool specified_matches)
143     : desktop(desktop),
144       matches(matches),
145       interact(interact),
146       specified_matches(specified_matches) {
147 }
148 
~AutomationInfo()149 AutomationInfo::~AutomationInfo() {
150 }
151 
152 }  // namespace extensions
153