// Copyright 2014 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "chrome/common/extensions/manifest_handlers/automation.h" #include "base/strings/string_number_conversions.h" #include "base/strings/utf_string_conversions.h" #include "chrome/common/extensions/api/manifest_types.h" #include "extensions/common/error_utils.h" #include "extensions/common/manifest_constants.h" #include "extensions/common/permissions/api_permission_set.h" #include "extensions/common/permissions/permissions_data.h" #include "extensions/common/url_pattern.h" namespace extensions { namespace automation_errors { const char kErrorDesktopTrueInteractFalse[] = "Cannot specify interactive=false if desktop=true is specified; " "interactive=false will be ignored."; const char kErrorDesktopTrueMatchesSpecified[] = "Cannot specify matches for Automation if desktop=true is specified; " "matches will be ignored."; const char kErrorInvalidMatch[] = "Invalid match pattern '*': *"; const char kErrorNoMatchesProvided[] = "No valid match patterns provided."; } namespace errors = manifest_errors; namespace keys = extensions::manifest_keys; using api::manifest_types::Automation; AutomationHandler::AutomationHandler() { } AutomationHandler::~AutomationHandler() { } bool AutomationHandler::Parse(Extension* extension, base::string16* error) { const base::Value* automation = NULL; CHECK(extension->manifest()->Get(keys::kAutomation, &automation)); std::vector<InstallWarning> install_warnings; scoped_ptr<AutomationInfo> info = AutomationInfo::FromValue(*automation, &install_warnings, error); if (!error->empty()) return false; extension->AddInstallWarnings(install_warnings); if (!info) return true; extension->SetManifestData(keys::kAutomation, info.release()); return true; } const std::vector<std::string> AutomationHandler::Keys() const { return SingleKey(keys::kAutomation); } // static const AutomationInfo* AutomationInfo::Get(const Extension* extension) { return static_cast<AutomationInfo*>( extension->GetManifestData(keys::kAutomation)); } // static scoped_ptr<AutomationInfo> AutomationInfo::FromValue( const base::Value& value, std::vector<InstallWarning>* install_warnings, base::string16* error) { scoped_ptr<Automation> automation = Automation::FromValue(value, error); if (!automation) return scoped_ptr<AutomationInfo>(); if (automation->as_boolean) { if (*automation->as_boolean) return make_scoped_ptr(new AutomationInfo()); return scoped_ptr<AutomationInfo>(); } const Automation::Object& automation_object = *automation->as_object; bool desktop = false; bool interact = false; if (automation_object.desktop && *automation_object.desktop) { desktop = true; interact = true; if (automation_object.interact && !*automation_object.interact) { // TODO(aboxhall): Do we want to allow this? install_warnings->push_back( InstallWarning(automation_errors::kErrorDesktopTrueInteractFalse)); } } else if (automation_object.interact && *automation_object.interact) { interact = true; } URLPatternSet matches; bool specified_matches = false; if (automation_object.matches) { if (desktop) { install_warnings->push_back( InstallWarning(automation_errors::kErrorDesktopTrueMatchesSpecified)); } else { specified_matches = true; for (std::vector<std::string>::iterator it = automation_object.matches->begin(); it != automation_object.matches->end(); ++it) { // TODO(aboxhall): Refactor common logic from content_scripts_handler, // manifest_url_handler and user_script.cc into a single location and // re-use here. URLPattern pattern(URLPattern::SCHEME_ALL & ~URLPattern::SCHEME_CHROMEUI); URLPattern::ParseResult parse_result = pattern.Parse(*it); if (parse_result != URLPattern::PARSE_SUCCESS) { install_warnings->push_back( InstallWarning(ErrorUtils::FormatErrorMessage( automation_errors::kErrorInvalidMatch, *it, URLPattern::GetParseResultString(parse_result)))); continue; } matches.AddPattern(pattern); } } } if (specified_matches && matches.is_empty()) install_warnings->push_back( InstallWarning(automation_errors::kErrorNoMatchesProvided)); return make_scoped_ptr( new AutomationInfo(desktop, matches, interact, specified_matches)); } AutomationInfo::AutomationInfo() : desktop(false), interact(false), specified_matches(false) { } AutomationInfo::AutomationInfo(bool desktop, const URLPatternSet& matches, bool interact, bool specified_matches) : desktop(desktop), matches(matches), interact(interact), specified_matches(specified_matches) { } AutomationInfo::~AutomationInfo() { } } // namespace extensions