• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
4 
5 #include "chrome/browser/extensions/api/messaging/native_messaging_host_manifest.h"
6 
7 #include "base/json/json_file_value_serializer.h"
8 #include "base/logging.h"
9 #include "base/values.h"
10 
11 namespace extensions {
12 
~NativeMessagingHostManifest()13 NativeMessagingHostManifest::~NativeMessagingHostManifest() {}
14 
15 // static
IsValidName(const std::string & name)16 bool NativeMessagingHostManifest::IsValidName(const std::string& name) {
17   if (name.empty()) {
18     return false;
19   }
20 
21   for (size_t i = 0; i < name.size(); ++i) {
22     char c = name[i];
23 
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 == '_')) {
27       return false;
28     }
29 
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)) {
33       return false;
34     }
35   }
36 
37   return true;
38 }
39 
40 // static
Load(const base::FilePath & file_path,std::string * error_message)41 scoped_ptr<NativeMessagingHostManifest> NativeMessagingHostManifest::Load(
42     const base::FilePath& file_path,
43     std::string* error_message) {
44   DCHECK(error_message);
45 
46   JSONFileValueSerializer serializer(file_path);
47   scoped_ptr<base::Value> parsed(serializer.Deserialize(NULL, error_message));
48   if (!parsed) {
49     return scoped_ptr<NativeMessagingHostManifest>();
50   }
51 
52   base::DictionaryValue* dictionary;
53   if (!parsed->GetAsDictionary(&dictionary)) {
54     *error_message = "Invalid manifest file.";
55     return scoped_ptr<NativeMessagingHostManifest>();
56   }
57 
58   scoped_ptr<NativeMessagingHostManifest> result(
59       new NativeMessagingHostManifest());
60   if (!result->Parse(dictionary, error_message)) {
61     return scoped_ptr<NativeMessagingHostManifest>();
62   }
63 
64   return result.Pass();
65 }
66 
NativeMessagingHostManifest()67 NativeMessagingHostManifest::NativeMessagingHostManifest() {
68 }
69 
Parse(base::DictionaryValue * dictionary,std::string * error_message)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.";
75     return false;
76   }
77 
78   if (!dictionary->GetString("description", &description_) ||
79       description_.empty()) {
80     *error_message = "Invalid value for description.";
81     return false;
82   }
83 
84   std::string type;
85   // stdio is the only host type that's currently supported.
86   if (!dictionary->GetString("type", &type) ||
87       type != "stdio") {
88     *error_message = "Invalid value for type.";
89     return false;
90   }
91   interface_ = HOST_INTERFACE_STDIO;
92 
93   std::string path;
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.";
98     return false;
99   }
100 
101   const base::ListValue* allowed_origins_list;
102   if (!dictionary->GetList("allowed_origins", &allowed_origins_list)) {
103     *error_message =
104         "Invalid value for allowed_origins. Expected a list of strings.";
105     return false;
106   }
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.";
113       return false;
114     }
115 
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);
121       return false;
122     }
123 
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.";
128       return false;
129     }
130 
131     allowed_origins_.AddPattern(pattern);
132   }
133 
134   return true;
135 }
136 
137 }  // namespace extensions
138