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 16namespace extensions { 17 18namespace automation_errors { 19const char kErrorDesktopTrueInteractFalse[] = 20 "Cannot specify interactive=false if desktop=true is specified; " 21 "interactive=false will be ignored."; 22const char kErrorDesktopTrueMatchesSpecified[] = 23 "Cannot specify matches for Automation if desktop=true is specified; " 24 "matches will be ignored."; 25const char kErrorInvalidMatch[] = "Invalid match pattern '*': *"; 26const char kErrorNoMatchesProvided[] = "No valid match patterns provided."; 27} 28 29namespace errors = manifest_errors; 30namespace keys = extensions::manifest_keys; 31using api::manifest_types::Automation; 32 33AutomationHandler::AutomationHandler() { 34} 35 36AutomationHandler::~AutomationHandler() { 37} 38 39bool 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 57const std::vector<std::string> AutomationHandler::Keys() const { 58 return SingleKey(keys::kAutomation); 59} 60 61// static 62const AutomationInfo* AutomationInfo::Get(const Extension* extension) { 63 return static_cast<AutomationInfo*>( 64 extension->GetManifestData(keys::kAutomation)); 65} 66 67// static 68scoped_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 136AutomationInfo::AutomationInfo() 137 : desktop(false), interact(false), specified_matches(false) { 138} 139AutomationInfo::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 149AutomationInfo::~AutomationInfo() { 150} 151 152} // namespace extensions 153