Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(185)

Side by Side Diff: extensions/renderer/storage_area.cc

Issue 2704823002: [Extensions Bindings] Add support for custom property types (Closed)
Patch Set: . Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2017 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/renderer/storage_area.h"
6
7 #include "base/memory/ptr_util.h"
8 #include "base/strings/stringprintf.h"
9 #include "base/values.h"
10 #include "extensions/common/api/storage.h"
11 #include "extensions/common/extension_api.h"
12 #include "extensions/renderer/api_request_handler.h"
13 #include "extensions/renderer/api_signature.h"
14 #include "gin/arguments.h"
15 #include "gin/handle.h"
16 #include "gin/object_template_builder.h"
17 #include "gin/wrappable.h"
18
19 namespace extensions {
20
21 namespace {
22
23 // gin::Wrappables for each of the storage areas. Since each has slightly
24 // different properties, and the object template is shared between all
25 // instances, this is a little verbose.
26 class LocalStorageArea final : public gin::Wrappable<LocalStorageArea> {
27 public:
28 LocalStorageArea(APIRequestHandler* request_handler,
29 const APITypeReferenceMap* type_refs)
30 : storage_area_(request_handler, type_refs, "local") {}
31 ~LocalStorageArea() override = default;
32
33 static gin::WrapperInfo kWrapperInfo;
34
35 gin::ObjectTemplateBuilder GetObjectTemplateBuilder(
36 v8::Isolate* isolate) override {
37 gin::ObjectTemplateBuilder builder =
38 Wrappable<LocalStorageArea>::GetObjectTemplateBuilder(isolate);
39 storage_area_.DecorateTemplate(&builder);
40 builder.SetValue("QUOTA_BYTES", api::storage::local::QUOTA_BYTES);
41 return builder;
42 }
43
44 private:
45 StorageArea storage_area_;
46
47 DISALLOW_COPY_AND_ASSIGN(LocalStorageArea);
48 };
49
50 gin::WrapperInfo LocalStorageArea::kWrapperInfo = {gin::kEmbedderNativeGin};
51
52 class SyncStorageArea final : public gin::Wrappable<SyncStorageArea> {
53 public:
54 SyncStorageArea(APIRequestHandler* request_handler,
55 const APITypeReferenceMap* type_refs)
56 : storage_area_(request_handler, type_refs, "sync") {}
57 ~SyncStorageArea() override = default;
58
59 static gin::WrapperInfo kWrapperInfo;
60
61 gin::ObjectTemplateBuilder GetObjectTemplateBuilder(
62 v8::Isolate* isolate) override {
63 gin::ObjectTemplateBuilder builder =
64 Wrappable<SyncStorageArea>::GetObjectTemplateBuilder(isolate);
65 storage_area_.DecorateTemplate(&builder);
66 builder.SetValue("QUOTA_BYTES", api::storage::sync::QUOTA_BYTES);
67 builder.SetValue("QUOTA_BYTES_PER_ITEM",
68 api::storage::sync::QUOTA_BYTES_PER_ITEM);
69 builder.SetValue("MAX_ITEMS", api::storage::sync::MAX_ITEMS);
70 builder.SetValue("MAX_WRITE_OPERATIONS_PER_HOUR",
71 api::storage::sync::MAX_WRITE_OPERATIONS_PER_HOUR);
72 builder.SetValue("MAX_WRITE_OPERATIONS_PER_MINUTE",
73 api::storage::sync::MAX_WRITE_OPERATIONS_PER_MINUTE);
74 builder.SetValue(
75 "MAX_SUSTAINED_WRITE_OPERATIONS_PER_MINUTE",
76 api::storage::sync::MAX_SUSTAINED_WRITE_OPERATIONS_PER_MINUTE);
77 return builder;
78 }
79
80 private:
81 StorageArea storage_area_;
82
83 DISALLOW_COPY_AND_ASSIGN(SyncStorageArea);
84 };
85
86 gin::WrapperInfo SyncStorageArea::kWrapperInfo = {gin::kEmbedderNativeGin};
87
88 class ManagedStorageArea final : public gin::Wrappable<ManagedStorageArea> {
89 public:
90 ManagedStorageArea(APIRequestHandler* request_handler,
91 const APITypeReferenceMap* type_refs)
92 : storage_area_(request_handler, type_refs, "managed") {}
93 ~ManagedStorageArea() override = default;
94
95 static gin::WrapperInfo kWrapperInfo;
96
97 gin::ObjectTemplateBuilder GetObjectTemplateBuilder(
98 v8::Isolate* isolate) override {
99 gin::ObjectTemplateBuilder builder =
100 Wrappable<ManagedStorageArea>::GetObjectTemplateBuilder(isolate);
101 storage_area_.DecorateTemplate(&builder);
102 return builder;
103 }
104
105 private:
106 StorageArea storage_area_;
107
108 DISALLOW_COPY_AND_ASSIGN(ManagedStorageArea);
109 };
110
111 gin::WrapperInfo ManagedStorageArea::kWrapperInfo = {gin::kEmbedderNativeGin};
112
113 } // namespace
114
115 StorageArea::StorageArea(APIRequestHandler* request_handler,
116 const APITypeReferenceMap* type_refs,
117 const std::string& name)
118 : request_handler_(request_handler), type_refs_(type_refs), name_(name) {}
119 StorageArea::~StorageArea() = default;
120
121 // static
122 v8::Local<v8::Object> StorageArea::CreateStorageArea(
123 v8::Local<v8::Context> context,
124 const std::string& property_name,
125 APIRequestHandler* request_handler,
126 APITypeReferenceMap* type_refs) {
127 v8::Context::Scope context_scope(context);
128 v8::Local<v8::Object> object;
129 if (property_name == "local") {
130 gin::Handle<LocalStorageArea> handle =
131 gin::CreateHandle(context->GetIsolate(),
132 new LocalStorageArea(request_handler, type_refs));
133 object = handle.ToV8().As<v8::Object>();
134 } else if (property_name == "sync") {
135 gin::Handle<SyncStorageArea> handle = gin::CreateHandle(
136 context->GetIsolate(), new SyncStorageArea(request_handler, type_refs));
137 object = handle.ToV8().As<v8::Object>();
138 } else {
139 CHECK_EQ("managed", property_name);
140 gin::Handle<ManagedStorageArea> handle =
141 gin::CreateHandle(context->GetIsolate(),
142 new ManagedStorageArea(request_handler, type_refs));
143 object = handle.ToV8().As<v8::Object>();
144 }
145 return object;
146 }
147
148 void StorageArea::DecorateTemplate(gin::ObjectTemplateBuilder* builder) {
149 builder
150 ->SetMethod("get", base::Bind(&StorageArea::HandleFunctionCall,
151 base::Unretained(this), "get"))
jbroman 2017/02/21 16:47:37 The object template is per-isolate-cached, but |th
Devlin 2017/02/21 18:05:40 Opted for the second - I'm really not keen on re-i
152 .SetMethod("set", base::Bind(&StorageArea::HandleFunctionCall,
153 base::Unretained(this), "set"))
154 .SetMethod("remove", base::Bind(&StorageArea::HandleFunctionCall,
155 base::Unretained(this), "remove"))
156 .SetMethod("clear", base::Bind(&StorageArea::HandleFunctionCall,
157 base::Unretained(this), "clear"))
158 .SetMethod("getBytesInUse",
159 base::Bind(&StorageArea::HandleFunctionCall,
160 base::Unretained(this), "getBytesInUse"));
161 }
162
163 void StorageArea::HandleFunctionCall(const std::string& method_name,
164 gin::Arguments* arguments) {
165 v8::Isolate* isolate = arguments->isolate();
166 v8::HandleScope handle_scope(isolate);
167 v8::Local<v8::Context> context = isolate->GetCurrentContext();
168
169 std::vector<v8::Local<v8::Value>> argument_list;
170 if (arguments->Length() > 0) {
171 // Just copying handles should never fail.
172 CHECK(arguments->GetRemaining(&argument_list));
173 }
174
175 std::unique_ptr<base::ListValue> converted_arguments;
176 v8::Local<v8::Function> callback;
177 std::string error;
178 if (!GetFunctionSchema("storage", "storage.StorageArea", method_name)
179 .ParseArgumentsToJSON(context, argument_list, *type_refs_,
180 &converted_arguments, &callback, &error)) {
181 arguments->ThrowTypeError("Invalid invocation");
182 return;
183 }
184
185 converted_arguments->Insert(0u, base::MakeUnique<base::Value>(name_));
186 request_handler_->StartRequest(context, "storage." + method_name,
187 std::move(converted_arguments), callback,
188 v8::Local<v8::Function>());
189 }
190
191 const APISignature& StorageArea::GetFunctionSchema(
192 base::StringPiece api_name,
193 base::StringPiece type_name,
194 base::StringPiece function_name) {
195 std::string full_name = base::StringPrintf(
196 "%s.%s.%s", api_name.data(), type_name.data(), function_name.data());
197 auto iter = signatures_.find(full_name);
198 if (iter != signatures_.end())
199 return *iter->second;
200
201 const base::DictionaryValue* full_schema =
202 ExtensionAPI::GetSharedInstance()->GetSchema(api_name.as_string());
203 const base::ListValue* types = nullptr;
204 CHECK(full_schema->GetList("types", &types));
205 const base::DictionaryValue* type_schema = nullptr;
206 for (const auto& type : *types) {
207 const base::DictionaryValue* type_dict = nullptr;
208 CHECK(type->GetAsDictionary(&type_dict));
209 std::string id;
210 CHECK(type_dict->GetString("id", &id));
211 if (id == type_name) {
212 type_schema = type_dict;
213 break;
214 }
215 }
216 CHECK(type_schema);
217 const base::ListValue* type_functions = nullptr;
218 CHECK(type_schema->GetList("functions", &type_functions));
219 const base::ListValue* parameters = nullptr;
220 for (const auto& function : *type_functions) {
221 const base::DictionaryValue* function_dict = nullptr;
222 CHECK(function->GetAsDictionary(&function_dict));
223 std::string name;
224 CHECK(function_dict->GetString("name", &name));
225 if (name == function_name) {
226 CHECK(function_dict->GetList("parameters", &parameters));
227 break;
228 }
229 }
230 CHECK(parameters);
231 auto signature = base::MakeUnique<APISignature>(*parameters);
232 auto raw_signature = signature.get();
233 signatures_[full_name] = std::move(signature);
234 return *raw_signature;
235 }
236
237 } // namespace extensions
OLDNEW
« extensions/renderer/api_binding_unittest.cc ('K') | « extensions/renderer/storage_area.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698