1 // Copyright (c) 2013 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.
5 #include "chrome/browser/extensions/api/messaging/native_messaging_host_manifest.h"
7 #include "base/json/json_file_value_serializer.h"
8 #include "base/logging.h"
9 #include "base/values.h"
11 namespace extensions
{
13 NativeMessagingHostManifest::~NativeMessagingHostManifest() {}
16 bool NativeMessagingHostManifest::IsValidName(const std::string
& name
) {
21 for (size_t i
= 0; i
< name
.size(); ++i
) {
24 // Verify that only the following characters are used: [a-z0-9._].
25 if (!((c
>= 'a' && c
<= 'z') || (c
>= '0' && c
<= '9') ||
26 c
== '.' || c
== '_')) {
30 // Verify that dots are separated by other characters and that string
31 // doesn't begin or end with a dot.
32 if (c
== '.' && (i
== 0 || name
[i
- 1] == '.' || i
== name
.size() - 1)) {
41 scoped_ptr
<NativeMessagingHostManifest
> NativeMessagingHostManifest::Load(
42 const base::FilePath
& file_path
,
43 std::string
* error_message
) {
44 DCHECK(error_message
);
46 JSONFileValueSerializer
serializer(file_path
);
47 scoped_ptr
<base::Value
> parsed(serializer
.Deserialize(NULL
, error_message
));
49 return scoped_ptr
<NativeMessagingHostManifest
>();
52 base::DictionaryValue
* dictionary
;
53 if (!parsed
->GetAsDictionary(&dictionary
)) {
54 *error_message
= "Invalid manifest file.";
55 return scoped_ptr
<NativeMessagingHostManifest
>();
58 scoped_ptr
<NativeMessagingHostManifest
> result(
59 new NativeMessagingHostManifest());
60 if (!result
->Parse(dictionary
, error_message
)) {
61 return scoped_ptr
<NativeMessagingHostManifest
>();
67 NativeMessagingHostManifest::NativeMessagingHostManifest() {
70 bool NativeMessagingHostManifest::Parse(base::DictionaryValue
* dictionary
,
71 std::string
* error_message
) {
72 if (!dictionary
->GetString("name", &name_
) ||
73 !IsValidName(name_
)) {
74 *error_message
= "Invalid value for name.";
78 if (!dictionary
->GetString("description", &description_
) ||
79 description_
.empty()) {
80 *error_message
= "Invalid value for description.";
85 // stdio is the only host type that's currently supported.
86 if (!dictionary
->GetString("type", &type
) ||
88 *error_message
= "Invalid value for type.";
91 interface_
= HOST_INTERFACE_STDIO
;
94 // JSON parsed checks that all strings are valid UTF8.
95 if (!dictionary
->GetString("path", &path
) ||
96 (path_
= base::FilePath::FromUTF8Unsafe(path
)).empty()) {
97 *error_message
= "Invalid value for path.";
101 const base::ListValue
* allowed_origins_list
;
102 if (!dictionary
->GetList("allowed_origins", &allowed_origins_list
)) {
104 "Invalid value for allowed_origins. Expected a list of strings.";
107 allowed_origins_
.ClearPatterns();
108 for (base::ListValue::const_iterator it
= allowed_origins_list
->begin();
109 it
!= allowed_origins_list
->end(); ++it
) {
110 std::string pattern_string
;
111 if (!(*it
)->GetAsString(&pattern_string
)) {
112 *error_message
= "allowed_origins must be list of strings.";
116 URLPattern
pattern(URLPattern::SCHEME_EXTENSION
);
117 URLPattern::ParseResult result
= pattern
.Parse(pattern_string
);
118 if (result
!= URLPattern::PARSE_SUCCESS
) {
119 *error_message
= "Failed to parse pattern \"" + pattern_string
+
120 "\": " + URLPattern::GetParseResultString(result
);
124 // Disallow patterns that are too broad. Set of allowed origins must be a
125 // fixed list of extensions.
126 if (pattern
.match_all_urls() || pattern
.match_subdomains()) {
127 *error_message
= "Pattern \"" + pattern_string
+ "\" is not allowed.";
131 allowed_origins_
.AddPattern(pattern
);
137 } // namespace extensions