普通文本  |  153行  |  5.07 KB

// 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