Index: extensions/renderer/chrome_setting.cc |
diff --git a/extensions/renderer/chrome_setting.cc b/extensions/renderer/chrome_setting.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..13f5c2042d377d6903a7e2fdaadf1e020dcbf976 |
--- /dev/null |
+++ b/extensions/renderer/chrome_setting.cc |
@@ -0,0 +1,190 @@ |
+// Copyright 2017 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 "extensions/renderer/chrome_setting.h" |
+ |
+#include "base/memory/ptr_util.h" |
+#include "base/strings/stringprintf.h" |
+#include "base/values.h" |
+#include "extensions/renderer/api_event_handler.h" |
+#include "extensions/renderer/api_request_handler.h" |
+#include "extensions/renderer/api_signature.h" |
+#include "extensions/renderer/api_type_reference_map.h" |
+#include "gin/arguments.h" |
+#include "gin/handle.h" |
+#include "gin/object_template_builder.h" |
+ |
+namespace extensions { |
+ |
+v8::Local<v8::Object> ChromeSetting::Create(v8::Local<v8::Context> context, |
+ const std::string& property_name, |
+ APIRequestHandler* request_handler, |
+ APIEventHandler* event_handler, |
+ APITypeReferenceMap* type_refs) { |
+ auto value_spec = base::MakeUnique<base::DictionaryValue>(); |
+ // Most ChromeSettings have a pref that matches the property name and are of |
+ // type boolean. |
+ base::StringPiece pref_name = property_name; |
+ base::StringPiece type = "boolean"; |
+ |
+ // A few of ChromeSettings are special, and have different arguments. |
+ base::StringPiece ref; |
+ if (property_name == "animationPolicy") { |
+ type = "string"; |
+ auto enum_list = base::MakeUnique<base::ListValue>(); |
+ enum_list->AppendString("allowed"); |
+ enum_list->AppendString("once"); |
+ enum_list->AppendString("none"); |
+ value_spec->Set("enum", std::move(enum_list)); |
+ } else if (property_name == "webRTCIPHandlingPolicy") { |
+ ref = "IPHandlingPolicy"; |
+ } else if (property_name == "spdyProxyEnabled") { |
+ pref_name = "spdy_proxy.enabled"; |
+ } else if (property_name == "dataReductionDailyContentLength") { |
+ type = "array"; |
+ pref_name = "data_reduction.daily_original_length"; |
+ } else if (property_name == "dataReductionDailyReceivedLength") { |
+ type = "array"; |
+ pref_name = "data_reduction.daily_received_length"; |
+ } else if (property_name == "dataUsageReportingEnabled") { |
+ pref_name = "data_usage_reporting.enabled"; |
+ } else if (property_name == "proxy") { |
+ ref = "ProxyConfig"; |
+ } |
+ |
+ if (!ref.empty()) |
+ value_spec->SetString("$ref", ref); |
+ else |
+ value_spec->SetString("type", type); |
+ |
+ // The set() call takes an object { value: { type: <t> }, ... }, where <t> |
+ // is the custom set() argument specified above by value_spec. |
+ base::DictionaryValue set_spec; |
+ set_spec.SetString("type", "object"); |
+ auto properties = base::MakeUnique<base::DictionaryValue>(); |
+ properties->Set("value", std::move(value_spec)); |
+ set_spec.Set("properties", std::move(properties)); |
+ |
+ gin::Handle<ChromeSetting> handle = gin::CreateHandle( |
+ context->GetIsolate(), |
+ new ChromeSetting(request_handler, event_handler, type_refs, |
+ pref_name.as_string(), set_spec)); |
+ return handle.ToV8().As<v8::Object>(); |
+} |
+ |
+ChromeSetting::ChromeSetting(APIRequestHandler* request_handler, |
+ APIEventHandler* event_handler, |
+ const APITypeReferenceMap* type_refs, |
+ const std::string& pref_name, |
+ const base::DictionaryValue& argument_spec) |
+ : request_handler_(request_handler), |
+ event_handler_(event_handler), |
+ type_refs_(type_refs), |
+ pref_name_(pref_name), |
+ argument_spec_(argument_spec) {} |
+ |
+ChromeSetting::~ChromeSetting() = default; |
+ |
+gin::WrapperInfo ChromeSetting::kWrapperInfo = {gin::kEmbedderNativeGin}; |
+ |
+gin::ObjectTemplateBuilder ChromeSetting::GetObjectTemplateBuilder( |
+ v8::Isolate* isolate) { |
+ return Wrappable<ChromeSetting>::GetObjectTemplateBuilder(isolate) |
+ .SetMethod("get", &ChromeSetting::Get) |
+ .SetMethod("set", &ChromeSetting::Set) |
+ .SetMethod("clear", &ChromeSetting::Clear) |
+ .SetProperty("onChange", &ChromeSetting::GetOnChangeEvent); |
+} |
+ |
+void ChromeSetting::Get(gin::Arguments* arguments) { |
+ HandleFunction("get", arguments); |
+} |
+ |
+void ChromeSetting::Set(gin::Arguments* arguments) { |
+ v8::Isolate* isolate = arguments->isolate(); |
+ v8::HandleScope handle_scope(isolate); |
+ |
+ v8::Local<v8::Object> holder; |
+ CHECK(arguments->GetHolder(&holder)); |
+ v8::Local<v8::Context> context = holder->CreationContext(); |
+ |
+ v8::Local<v8::Value> value = arguments->PeekNext(); |
+ // The set schema included in the Schema object is generic, since it varies |
+ // per-setting. However, this is only ever for a single setting, so we can |
+ // enforce the types more thoroughly. |
+ std::string error; |
+ if (!value.IsEmpty() && !argument_spec_.ParseArgument( |
+ context, value, *type_refs_, nullptr, &error)) { |
+ arguments->ThrowTypeError("Invalid invocation"); |
+ return; |
+ } |
+ HandleFunction("set", arguments); |
+} |
+ |
+void ChromeSetting::Clear(gin::Arguments* arguments) { |
+ HandleFunction("clear", arguments); |
+} |
+ |
+v8::Local<v8::Value> ChromeSetting::GetOnChangeEvent( |
+ gin::Arguments* arguments) { |
+ v8::Isolate* isolate = arguments->isolate(); |
+ v8::Local<v8::Object> holder; |
+ CHECK(arguments->GetHolder(&holder)); |
+ v8::Local<v8::Context> context = holder->CreationContext(); |
+ v8::Local<v8::Object> wrapper = GetWrapper(isolate); |
+ v8::Local<v8::Private> key = v8::Private::ForApi( |
+ isolate, gin::StringToSymbol(isolate, "onChangeEvent")); |
+ v8::Local<v8::Value> event; |
+ if (!wrapper->GetPrivate(context, key).ToLocal(&event)) { |
+ NOTREACHED(); |
+ return v8::Local<v8::Value>(); |
+ } |
+ |
+ DCHECK(!event.IsEmpty()); |
+ if (event->IsUndefined()) { |
+ event = event_handler_->CreateEventInstance( |
+ base::StringPrintf("types.ChromeSetting.%s.onChange", |
+ pref_name_.c_str()), |
+ context); |
+ v8::Maybe<bool> set_result = wrapper->SetPrivate(context, key, event); |
+ if (!set_result.IsJust() || !set_result.FromJust()) { |
+ NOTREACHED(); |
+ return v8::Local<v8::Value>(); |
+ } |
+ } |
+ return event; |
+} |
+ |
+void ChromeSetting::HandleFunction(const std::string& method_name, |
+ gin::Arguments* arguments) { |
+ v8::Isolate* isolate = arguments->isolate(); |
+ v8::HandleScope handle_scope(isolate); |
+ v8::Local<v8::Object> holder; |
+ CHECK(arguments->GetHolder(&holder)); |
+ v8::Local<v8::Context> context = holder->CreationContext(); |
+ |
+ std::vector<v8::Local<v8::Value>> argument_list; |
+ if (arguments->Length() > 0) { |
+ // Just copying handles should never fail. |
+ CHECK(arguments->GetRemaining(&argument_list)); |
+ } |
+ |
+ std::string full_name = "types.ChromeSetting." + method_name; |
+ std::unique_ptr<base::ListValue> converted_arguments; |
+ v8::Local<v8::Function> callback; |
+ std::string error; |
+ if (!type_refs_->GetTypeMethodSignature(full_name)->ParseArgumentsToJSON( |
+ context, argument_list, *type_refs_, &converted_arguments, &callback, |
+ &error)) { |
+ arguments->ThrowTypeError("Invalid invocation"); |
+ return; |
+ } |
+ |
+ converted_arguments->Insert(0u, base::MakeUnique<base::Value>(pref_name_)); |
+ request_handler_->StartRequest(context, full_name, |
+ std::move(converted_arguments), callback, |
+ v8::Local<v8::Function>()); |
+} |
+ |
+} // namespace extensions |