1// Copyright 2014 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 "extensions/common/extension_messages.h"
6
7#include "content/public/common/common_param_traits.h"
8#include "extensions/common/extension.h"
9#include "extensions/common/manifest.h"
10#include "extensions/common/manifest_handler.h"
11#include "extensions/common/permissions/permissions_data.h"
12#include "extensions/common/permissions/permissions_info.h"
13
14using extensions::APIPermission;
15using extensions::APIPermissionInfo;
16using extensions::APIPermissionSet;
17using extensions::Extension;
18using extensions::Manifest;
19using extensions::ManifestHandler;
20using extensions::ManifestPermission;
21using extensions::ManifestPermissionSet;
22using extensions::PermissionSet;
23using extensions::URLPatternSet;
24
25ExtensionMsg_PermissionSetStruct::ExtensionMsg_PermissionSetStruct() {
26}
27
28ExtensionMsg_PermissionSetStruct::ExtensionMsg_PermissionSetStruct(
29    const PermissionSet& permissions)
30    : apis(permissions.apis()),
31      manifest_permissions(permissions.manifest_permissions()),
32      explicit_hosts(permissions.explicit_hosts()),
33      scriptable_hosts(permissions.scriptable_hosts()) {
34}
35
36ExtensionMsg_PermissionSetStruct::~ExtensionMsg_PermissionSetStruct() {
37}
38
39scoped_refptr<const PermissionSet>
40ExtensionMsg_PermissionSetStruct::ToPermissionSet() const {
41  return new PermissionSet(
42      apis, manifest_permissions, explicit_hosts, scriptable_hosts);
43}
44
45ExtensionMsg_Loaded_Params::ExtensionMsg_Loaded_Params()
46    : location(Manifest::INVALID_LOCATION),
47      creation_flags(Extension::NO_FLAGS) {}
48
49ExtensionMsg_Loaded_Params::~ExtensionMsg_Loaded_Params() {}
50
51ExtensionMsg_Loaded_Params::ExtensionMsg_Loaded_Params(
52    const Extension* extension)
53    : manifest(extension->manifest()->value()->DeepCopy()),
54      location(extension->location()),
55      path(extension->path()),
56      active_permissions(*extension->permissions_data()->active_permissions()),
57      withheld_permissions(
58          *extension->permissions_data()->withheld_permissions()),
59      id(extension->id()),
60      creation_flags(extension->creation_flags()) {
61}
62
63scoped_refptr<Extension> ExtensionMsg_Loaded_Params::ConvertToExtension(
64    std::string* error) const {
65  scoped_refptr<Extension> extension =
66      Extension::Create(path, location, *manifest, creation_flags, error);
67  if (extension.get()) {
68    extension->permissions_data()->SetPermissions(
69        active_permissions.ToPermissionSet(),
70        withheld_permissions.ToPermissionSet());
71  }
72  return extension;
73}
74
75namespace IPC {
76
77template <>
78struct ParamTraits<Manifest::Location> {
79  typedef Manifest::Location param_type;
80  static void Write(Message* m, const param_type& p) {
81    int val = static_cast<int>(p);
82    WriteParam(m, val);
83  }
84  static bool Read(const Message* m, PickleIterator* iter, param_type* p) {
85    int val = 0;
86    if (!ReadParam(m, iter, &val) ||
87        val < Manifest::INVALID_LOCATION ||
88        val >= Manifest::NUM_LOCATIONS)
89      return false;
90    *p = static_cast<param_type>(val);
91    return true;
92  }
93  static void Log(const param_type& p, std::string* l) {
94    ParamTraits<int>::Log(static_cast<int>(p), l);
95  }
96};
97
98void ParamTraits<URLPattern>::Write(Message* m, const param_type& p) {
99  WriteParam(m, p.valid_schemes());
100  WriteParam(m, p.GetAsString());
101}
102
103bool ParamTraits<URLPattern>::Read(const Message* m, PickleIterator* iter,
104                                   param_type* p) {
105  int valid_schemes;
106  std::string spec;
107  if (!ReadParam(m, iter, &valid_schemes) ||
108      !ReadParam(m, iter, &spec))
109    return false;
110
111  // TODO(jstritar): We don't want the URLPattern to fail parsing when the
112  // scheme is invalid. Instead, the pattern should parse but it should not
113  // match the invalid patterns. We get around this by setting the valid
114  // schemes after parsing the pattern. Update these method calls once we can
115  // ignore scheme validation with URLPattern parse options. crbug.com/90544
116  p->SetValidSchemes(URLPattern::SCHEME_ALL);
117  URLPattern::ParseResult result = p->Parse(spec);
118  p->SetValidSchemes(valid_schemes);
119  return URLPattern::PARSE_SUCCESS == result;
120}
121
122void ParamTraits<URLPattern>::Log(const param_type& p, std::string* l) {
123  LogParam(p.GetAsString(), l);
124}
125
126void ParamTraits<URLPatternSet>::Write(Message* m, const param_type& p) {
127  WriteParam(m, p.patterns());
128}
129
130bool ParamTraits<URLPatternSet>::Read(const Message* m, PickleIterator* iter,
131                                        param_type* p) {
132  std::set<URLPattern> patterns;
133  if (!ReadParam(m, iter, &patterns))
134    return false;
135
136  for (std::set<URLPattern>::iterator i = patterns.begin();
137       i != patterns.end(); ++i)
138    p->AddPattern(*i);
139  return true;
140}
141
142void ParamTraits<URLPatternSet>::Log(const param_type& p, std::string* l) {
143  LogParam(p.patterns(), l);
144}
145
146void ParamTraits<APIPermission::ID>::Write(
147    Message* m, const param_type& p) {
148  WriteParam(m, static_cast<int>(p));
149}
150
151bool ParamTraits<APIPermission::ID>::Read(
152    const Message* m, PickleIterator* iter, param_type* p) {
153  int api_id = -2;
154  if (!ReadParam(m, iter, &api_id))
155    return false;
156
157  *p = static_cast<APIPermission::ID>(api_id);
158  return true;
159}
160
161void ParamTraits<APIPermission::ID>::Log(
162    const param_type& p, std::string* l) {
163  LogParam(static_cast<int>(p), l);
164}
165
166void ParamTraits<APIPermissionSet>::Write(
167    Message* m, const param_type& p) {
168  APIPermissionSet::const_iterator it = p.begin();
169  const APIPermissionSet::const_iterator end = p.end();
170  WriteParam(m, p.size());
171  for (; it != end; ++it) {
172    WriteParam(m, it->id());
173    it->Write(m);
174  }
175}
176
177bool ParamTraits<APIPermissionSet>::Read(
178    const Message* m, PickleIterator* iter, param_type* r) {
179  size_t size;
180  if (!ReadParam(m, iter, &size))
181    return false;
182  for (size_t i = 0; i < size; ++i) {
183    APIPermission::ID id;
184    if (!ReadParam(m, iter, &id))
185      return false;
186    const APIPermissionInfo* permission_info =
187      extensions::PermissionsInfo::GetInstance()->GetByID(id);
188    if (!permission_info)
189      return false;
190    scoped_ptr<APIPermission> p(permission_info->CreateAPIPermission());
191    if (!p->Read(m, iter))
192      return false;
193    r->insert(p.release());
194  }
195  return true;
196}
197
198void ParamTraits<APIPermissionSet>::Log(
199    const param_type& p, std::string* l) {
200  LogParam(p.map(), l);
201}
202
203void ParamTraits<ManifestPermissionSet>::Write(
204    Message* m, const param_type& p) {
205  ManifestPermissionSet::const_iterator it = p.begin();
206  const ManifestPermissionSet::const_iterator end = p.end();
207  WriteParam(m, p.size());
208  for (; it != end; ++it) {
209    WriteParam(m, it->name());
210    it->Write(m);
211  }
212}
213
214bool ParamTraits<ManifestPermissionSet>::Read(
215    const Message* m, PickleIterator* iter, param_type* r) {
216  size_t size;
217  if (!ReadParam(m, iter, &size))
218    return false;
219  for (size_t i = 0; i < size; ++i) {
220    std::string name;
221    if (!ReadParam(m, iter, &name))
222      return false;
223    scoped_ptr<ManifestPermission> p(ManifestHandler::CreatePermission(name));
224    if (!p)
225      return false;
226    if (!p->Read(m, iter))
227      return false;
228    r->insert(p.release());
229  }
230  return true;
231}
232
233void ParamTraits<ManifestPermissionSet>::Log(
234    const param_type& p, std::string* l) {
235  LogParam(p.map(), l);
236}
237
238void ParamTraits<ExtensionMsg_PermissionSetStruct>::Write(Message* m,
239                                                          const param_type& p) {
240  WriteParam(m, p.apis);
241  WriteParam(m, p.manifest_permissions);
242  WriteParam(m, p.explicit_hosts);
243  WriteParam(m, p.scriptable_hosts);
244}
245
246bool ParamTraits<ExtensionMsg_PermissionSetStruct>::Read(const Message* m,
247                                                         PickleIterator* iter,
248                                                         param_type* p) {
249  return ReadParam(m, iter, &p->apis) &&
250         ReadParam(m, iter, &p->manifest_permissions) &&
251         ReadParam(m, iter, &p->explicit_hosts) &&
252         ReadParam(m, iter, &p->scriptable_hosts);
253}
254
255void ParamTraits<ExtensionMsg_PermissionSetStruct>::Log(const param_type& p,
256                                                        std::string* l) {
257  LogParam(p.apis, l);
258  LogParam(p.manifest_permissions, l);
259  LogParam(p.explicit_hosts, l);
260  LogParam(p.scriptable_hosts, l);
261}
262
263void ParamTraits<ExtensionMsg_Loaded_Params>::Write(Message* m,
264                                                    const param_type& p) {
265  WriteParam(m, p.location);
266  WriteParam(m, p.path);
267  WriteParam(m, *(p.manifest));
268  WriteParam(m, p.creation_flags);
269  WriteParam(m, p.active_permissions);
270  WriteParam(m, p.withheld_permissions);
271}
272
273bool ParamTraits<ExtensionMsg_Loaded_Params>::Read(const Message* m,
274                                                   PickleIterator* iter,
275                                                   param_type* p) {
276  p->manifest.reset(new base::DictionaryValue());
277  return ReadParam(m, iter, &p->location) && ReadParam(m, iter, &p->path) &&
278         ReadParam(m, iter, p->manifest.get()) &&
279         ReadParam(m, iter, &p->creation_flags) &&
280         ReadParam(m, iter, &p->active_permissions) &&
281         ReadParam(m, iter, &p->withheld_permissions);
282}
283
284void ParamTraits<ExtensionMsg_Loaded_Params>::Log(const param_type& p,
285                                                  std::string* l) {
286  l->append(p.id);
287}
288
289}  // namespace IPC
290