Home | History | Annotate | Download | only in manifest_handlers
      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 
     33 AutomationHandler::AutomationHandler() {
     34 }
     35 
     36 AutomationHandler::~AutomationHandler() {
     37 }
     38 
     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 
     57 const std::vector<std::string> AutomationHandler::Keys() const {
     58   return SingleKey(keys::kAutomation);
     59 }
     60 
     61 // static
     62 const AutomationInfo* AutomationInfo::Get(const Extension* extension) {
     63   return static_cast<AutomationInfo*>(
     64       extension->GetManifestData(keys::kAutomation));
     65 }
     66 
     67 // static
     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 
    136 AutomationInfo::AutomationInfo()
    137     : desktop(false), interact(false), specified_matches(false) {
    138 }
    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 
    149 AutomationInfo::~AutomationInfo() {
    150 }
    151 
    152 }  // namespace extensions
    153