summaryrefslogtreecommitdiffstats
path: root/chrome/common/extensions/manifest_handlers/externally_connectable.cc
blob: 712cebb16c2d9bfa76734f4614d94e9eaeca36a8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
// Copyright 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/common/extensions/manifest_handlers/externally_connectable.h"

#include "base/utf_string_conversions.h"
#include "chrome/common/extensions/api/manifest_types.h"
#include "chrome/common/extensions/extension_manifest_constants.h"
#include "extensions/common/error_utils.h"
#include "extensions/common/url_pattern.h"
#include "googleurl/src/gurl.h"

namespace extensions {

namespace externally_connectable_errors {
  const char kErrorInvalid[] = "Invalid value for 'externally_connectable'";
  const char kErrorInvalidMatchPattern[] = "Invalid match pattern '*'";
  const char kErrorInvalidId[] = "Invalid ID '*'";
}

namespace keys = extension_manifest_keys;
namespace errors = externally_connectable_errors;
using api::manifest_types::ExternallyConnectable;

namespace {
const char kAllIds[] = "*";
}

ExternallyConnectableHandler::ExternallyConnectableHandler() {}

ExternallyConnectableHandler::~ExternallyConnectableHandler() {}

bool ExternallyConnectableHandler::Parse(Extension* extension,
                                         string16* error) {
  const base::Value* externally_connectable = NULL;
  CHECK(extension->manifest()->Get(keys::kExternallyConnectable,
                                   &externally_connectable));
  scoped_ptr<ExternallyConnectableInfo> info =
      ExternallyConnectableInfo::FromValue(*externally_connectable, error);
  if (!info)
    return false;
  extension->SetManifestData(keys::kExternallyConnectable, info.release());
  return true;
}

const std::vector<std::string> ExternallyConnectableHandler::Keys() const {
  return SingleKey(keys::kExternallyConnectable);
}

// static
ExternallyConnectableInfo* ExternallyConnectableInfo::Get(
    const Extension* extension) {
  return static_cast<ExternallyConnectableInfo*>(
      extension->GetManifestData(keys::kExternallyConnectable));
}

// static
scoped_ptr<ExternallyConnectableInfo> ExternallyConnectableInfo::FromValue(
    const base::Value& value,
    string16* error) {
  scoped_ptr<ExternallyConnectable> externally_connectable =
      ExternallyConnectable::FromValue(value);
  if (!externally_connectable) {
    *error = UTF8ToUTF16(errors::kErrorInvalid);
    return scoped_ptr<ExternallyConnectableInfo>();
  }

  URLPatternSet matches;

  if (externally_connectable->matches) {
    for (std::vector<std::string>::iterator it =
             externally_connectable->matches->begin();
         it != externally_connectable->matches->end(); ++it) {
      // Safe to use SCHEME_ALL here; externally_connectable gives a page ->
      // extension communication path, not the other way.
      URLPattern pattern(URLPattern::SCHEME_ALL);
      if (pattern.Parse(*it) != URLPattern::PARSE_SUCCESS) {
        *error = ErrorUtils::FormatErrorMessageUTF16(
            errors::kErrorInvalidMatchPattern, *it);
        return scoped_ptr<ExternallyConnectableInfo>();
      }
      matches.AddPattern(pattern);
    }
  }

  std::vector<std::string> ids;
  bool matches_all_ids = false;

  if (externally_connectable->ids) {
    for (std::vector<std::string>::iterator it =
             externally_connectable->ids->begin();
         it != externally_connectable->ids->end(); ++it) {
      if (*it == kAllIds) {
        matches_all_ids = true;
      } else if (Extension::IdIsValid(*it)) {
        ids.push_back(*it);
      } else {
        *error = ErrorUtils::FormatErrorMessageUTF16(
            errors::kErrorInvalidId, *it);
        return scoped_ptr<ExternallyConnectableInfo>();
      }
    }
  }

  return make_scoped_ptr(
      new ExternallyConnectableInfo(matches, ids, matches_all_ids));
}

ExternallyConnectableInfo::~ExternallyConnectableInfo() {}

ExternallyConnectableInfo::ExternallyConnectableInfo(
    const URLPatternSet& matches,
    const std::vector<std::string>& ids,
    bool matches_all_ids)
    : matches(matches), ids(ids), matches_all_ids(matches_all_ids) {}

}   // namespace extensions