root/chrome/browser/extensions/api/messaging/native_messaging_host_manifest.cc

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. IsValidName
  2. Load
  3. Parse

// Copyright (c) 2013 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/browser/extensions/api/messaging/native_messaging_host_manifest.h"

#include "base/json/json_file_value_serializer.h"
#include "base/logging.h"
#include "base/values.h"

namespace extensions {

NativeMessagingHostManifest::~NativeMessagingHostManifest() {}

// static
bool NativeMessagingHostManifest::IsValidName(const std::string& name) {
  if (name.empty()) {
    return false;
  }

  for (size_t i = 0; i < name.size(); ++i) {
    char c = name[i];

    // Verify that only the following characters are used: [a-z0-9._].
    if (!((c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') ||
          c == '.' || c == '_')) {
      return false;
    }

    // Verify that dots are separated by other characters and that string
    // doesn't begin or end with a dot.
    if (c == '.' && (i == 0 || name[i - 1] == '.' || i == name.size() - 1)) {
      return false;
    }
  }

  return true;
}

// static
scoped_ptr<NativeMessagingHostManifest> NativeMessagingHostManifest::Load(
    const base::FilePath& file_path,
    std::string* error_message) {
  DCHECK(error_message);

  JSONFileValueSerializer serializer(file_path);
  scoped_ptr<base::Value> parsed(serializer.Deserialize(NULL, error_message));
  if (!parsed) {
    return scoped_ptr<NativeMessagingHostManifest>();
  }

  base::DictionaryValue* dictionary;
  if (!parsed->GetAsDictionary(&dictionary)) {
    *error_message = "Invalid manifest file.";
    return scoped_ptr<NativeMessagingHostManifest>();
  }

  scoped_ptr<NativeMessagingHostManifest> result(
      new NativeMessagingHostManifest());
  if (!result->Parse(dictionary, error_message)) {
    return scoped_ptr<NativeMessagingHostManifest>();
  }

  return result.Pass();
}

NativeMessagingHostManifest::NativeMessagingHostManifest() {
}

bool NativeMessagingHostManifest::Parse(base::DictionaryValue* dictionary,
                                        std::string* error_message) {
  if (!dictionary->GetString("name", &name_) ||
      !IsValidName(name_)) {
    *error_message = "Invalid value for name.";
    return false;
  }

  if (!dictionary->GetString("description", &description_) ||
      description_.empty()) {
    *error_message = "Invalid value for description.";
    return false;
  }

  std::string type;
  // stdio is the only host type that's currently supported.
  if (!dictionary->GetString("type", &type) ||
      type != "stdio") {
    *error_message = "Invalid value for type.";
    return false;
  }
  interface_ = HOST_INTERFACE_STDIO;

  std::string path;
  // JSON parsed checks that all strings are valid UTF8.
  if (!dictionary->GetString("path", &path) ||
      (path_ = base::FilePath::FromUTF8Unsafe(path)).empty()) {
    *error_message = "Invalid value for path.";
    return false;
  }

  const base::ListValue* allowed_origins_list;
  if (!dictionary->GetList("allowed_origins", &allowed_origins_list)) {
    *error_message =
        "Invalid value for allowed_origins. Expected a list of strings.";
    return false;
  }
  allowed_origins_.ClearPatterns();
  for (base::ListValue::const_iterator it = allowed_origins_list->begin();
       it != allowed_origins_list->end(); ++it) {
    std::string pattern_string;
    if (!(*it)->GetAsString(&pattern_string)) {
      *error_message = "allowed_origins must be list of strings.";
      return false;
    }

    URLPattern pattern(URLPattern::SCHEME_EXTENSION);
    URLPattern::ParseResult result = pattern.Parse(pattern_string);
    if (result != URLPattern::PARSE_SUCCESS) {
      *error_message = "Failed to parse pattern \"" + pattern_string +
          "\": " + URLPattern::GetParseResultString(result);
      return false;
    }

    // Disallow patterns that are too broad. Set of allowed origins must be a
    // fixed list of extensions.
    if (pattern.match_all_urls() || pattern.match_subdomains()) {
      *error_message = "Pattern \"" + pattern_string + "\" is not allowed.";
      return false;
    }

    allowed_origins_.AddPattern(pattern);
  }

  return true;
}

}  // namespace extensions

/* [<][>][^][v][top][bottom][index][help] */