Browse Source

refactor: remove instances of createDeepCopy (#13703)

* add new native_mate converters for base::Value

* fix converter swapping

* remove createDeepCopy from browser/api

* replace missing ListValue converter

* convert bulk of remaining createDeepCopy instances

* convert last remaining instances of createDeepCopy

* incremental progress and helper methods for value conversion

* convert Get and add template function for GetString

* final DictionaryValue method conversions

* remove usage of base::DictionaryValue in web_contents_preferences

* use IsEnabled helper where possible

* Update atom_api_web_view_manager.cc
Shelley Vohr 6 years ago
parent
commit
9f328abe19

+ 2 - 1
atom/browser/api/atom_api_app.cc

@@ -990,7 +990,8 @@ void App::ImportCertificate(const base::DictionaryValue& options,
                             const net::CompletionCallback& callback) {
   auto browser_context = AtomBrowserContext::From("", false);
   if (!certificate_manager_model_) {
-    std::unique_ptr<base::DictionaryValue> copy = options.CreateDeepCopy();
+    auto copy = base::DictionaryValue::From(
+        base::Value::ToUniquePtrValue(options.Clone()));
     CertificateManagerModel::Create(
         browser_context.get(),
         base::Bind(&App::OnCertificateManagerModelCreated,

+ 1 - 1
atom/browser/api/atom_api_browser_window.cc

@@ -55,7 +55,7 @@ BrowserWindow::BrowserWindow(v8::Isolate* isolate,
     base::DictionaryValue web_preferences_dict;
     if (mate::ConvertFromV8(isolate, web_preferences.GetHandle(),
                             &web_preferences_dict)) {
-      existing_preferences->dict()->Clear();
+      existing_preferences->Clear();
       existing_preferences->Merge(web_preferences_dict);
     }
   } else {

+ 8 - 6
atom/browser/api/atom_api_cookies.cc

@@ -262,12 +262,13 @@ Cookies::~Cookies() {}
 
 void Cookies::Get(const base::DictionaryValue& filter,
                   const GetCallback& callback) {
-  std::unique_ptr<base::DictionaryValue> copied(filter.CreateDeepCopy());
+  auto copy = base::DictionaryValue::From(
+      base::Value::ToUniquePtrValue(filter.Clone()));
   auto* getter = browser_context_->GetRequestContext();
   content::BrowserThread::PostTask(
       BrowserThread::IO, FROM_HERE,
-      base::BindOnce(GetCookiesOnIO, base::RetainedRef(getter),
-                     std::move(copied), callback));
+      base::BindOnce(GetCookiesOnIO, base::RetainedRef(getter), std::move(copy),
+                     callback));
 }
 
 void Cookies::Remove(const GURL& url,
@@ -282,12 +283,13 @@ void Cookies::Remove(const GURL& url,
 
 void Cookies::Set(const base::DictionaryValue& details,
                   const SetCallback& callback) {
-  std::unique_ptr<base::DictionaryValue> copied(details.CreateDeepCopy());
+  auto copy = base::DictionaryValue::From(
+      base::Value::ToUniquePtrValue(details.Clone()));
   auto* getter = browser_context_->GetRequestContext();
   content::BrowserThread::PostTask(
       BrowserThread::IO, FROM_HERE,
-      base::BindOnce(SetCookieOnIO, base::RetainedRef(getter),
-                     std::move(copied), callback));
+      base::BindOnce(SetCookieOnIO, base::RetainedRef(getter), std::move(copy),
+                     callback));
 }
 
 void Cookies::FlushStore(const base::Closure& callback) {

+ 4 - 4
atom/browser/api/atom_api_web_contents.cc

@@ -1174,8 +1174,8 @@ void WebContents::LoadURL(const GURL& url, const mate::Dictionary& options) {
   if (view) {
     auto* web_preferences = WebContentsPreferences::From(web_contents());
     std::string color_name;
-    if (web_preferences->dict()->GetString(options::kBackgroundColor,
-                                           &color_name)) {
+    if (web_preferences->GetPreference(options::kBackgroundColor,
+                                       &color_name)) {
       view->SetBackgroundColor(ParseHexColor(color_name));
     } else {
       view->SetBackgroundColor(SK_ColorTRANSPARENT);
@@ -1888,7 +1888,7 @@ v8::Local<v8::Value> WebContents::GetWebPreferences(v8::Isolate* isolate) {
   auto* web_preferences = WebContentsPreferences::From(web_contents());
   if (!web_preferences)
     return v8::Null(isolate);
-  return mate::ConvertToV8(isolate, *web_preferences->dict());
+  return mate::ConvertToV8(isolate, *web_preferences->preference());
 }
 
 v8::Local<v8::Value> WebContents::GetLastWebPreferences(v8::Isolate* isolate) {
@@ -1896,7 +1896,7 @@ v8::Local<v8::Value> WebContents::GetLastWebPreferences(v8::Isolate* isolate) {
       WebContentsPreferences::FromWebContents(web_contents());
   if (!web_preferences)
     return v8::Null(isolate);
-  return mate::ConvertToV8(isolate, *web_preferences->last_dict());
+  return mate::ConvertToV8(isolate, *web_preferences->last_preference());
 }
 
 v8::Local<v8::Value> WebContents::GetOwnerBrowserWindow() {

+ 2 - 2
atom/browser/atom_browser_client.cc

@@ -252,11 +252,11 @@ void AtomBrowserClient::OverrideSiteInstanceForNavigation(
     return;
 
   // Do we have an affinity site to manage ?
-  std::string affinity;
   auto* web_contents = content::WebContents::FromRenderFrameHost(rfh);
   auto* web_preferences = WebContentsPreferences::From(web_contents);
+  std::string affinity;
   if (web_preferences &&
-      web_preferences->dict()->GetString("affinity", &affinity) &&
+      web_preferences->GetPreference("affinity", &affinity) &&
       !affinity.empty()) {
     affinity = base::ToLowerASCII(affinity);
     auto iter = site_per_affinities.find(affinity);

+ 1 - 1
atom/browser/atom_javascript_dialog_manager.cc

@@ -62,7 +62,7 @@ void AtomJavaScriptDialogManager::RunJavaScriptDialog(
   std::string checkbox;
   if (origin_counts_[origin] > 1 && web_preferences &&
       web_preferences->IsEnabled("safeDialogs") &&
-      !web_preferences->dict()->GetString("safeDialogsMessage", &checkbox)) {
+      !web_preferences->GetPreference("safeDialogsMessage", &checkbox)) {
     checkbox = "Prevent this app from creating additional dialogs";
   }
 

+ 2 - 1
atom/browser/net/atom_network_delegate.cc

@@ -452,7 +452,8 @@ void AtomNetworkDelegate::OnListenerResultInUI(
     uint64_t id,
     T out,
     const base::DictionaryValue& response) {
-  std::unique_ptr<base::DictionaryValue> copy = response.CreateDeepCopy();
+  auto copy = base::DictionaryValue::From(
+      base::Value::ToUniquePtrValue(response.Clone()));
   BrowserThread::PostTask(
       BrowserThread::IO, FROM_HERE,
       base::BindOnce(&AtomNetworkDelegate::OnListenerResultInIO<T>,

+ 2 - 1
atom/browser/render_process_preferences.cc

@@ -21,7 +21,8 @@ RenderProcessPreferences::~RenderProcessPreferences() {}
 
 int RenderProcessPreferences::AddEntry(const base::DictionaryValue& entry) {
   int id = ++next_id_;
-  entries_[id] = entry.CreateDeepCopy();
+  entries_[id] =
+      base::DictionaryValue::From(base::Value::ToUniquePtrValue(entry.Clone()));
   cache_needs_update_ = true;
   return id;
 }

+ 2 - 1
atom/browser/ui/webui/pdf_viewer_handler.cc

@@ -112,7 +112,8 @@ void PdfViewerHandler::Initialize(const base::ListValue* args) {
     PopulateStreamInfo(stream_info.get(), stream_, original_url_);
     ResolveJavascriptCallback(*callback_id, *stream_info);
   } else {
-    initialize_callback_id_ = callback_id->CreateDeepCopy();
+    initialize_callback_id_ =
+        base::Value::ToUniquePtrValue(callback_id.Clone());
   }
 
   auto zoom_controller =

+ 139 - 85
atom/browser/web_contents_preferences.cc

@@ -15,6 +15,7 @@
 #include "base/command_line.h"
 #include "base/memory/ptr_util.h"
 #include "base/strings/string_number_conversions.h"
+#include "base/strings/utf_string_conversions.h"
 #include "cc/base/switches.h"
 #include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/render_process_host.h"
@@ -29,6 +30,51 @@
 
 DEFINE_WEB_CONTENTS_USER_DATA_KEY(atom::WebContentsPreferences);
 
+namespace {
+
+bool GetAsString(const base::Value* val,
+                 const base::StringPiece& path,
+                 std::string* out) {
+  if (val) {
+    auto* found = val->FindKeyOfType(path, base::Value::Type::STRING);
+    if (found) {
+      *out = found->GetString();
+      return true;
+    }
+  }
+  return false;
+}
+
+bool GetAsString(const base::Value* val,
+                 const base::StringPiece& path,
+                 base::string16* out) {
+  if (val) {
+    auto* found = val->FindKeyOfType(path, base::Value::Type::STRING);
+    if (found) {
+      *out = base::UTF8ToUTF16(found->GetString());
+      return true;
+    }
+  }
+  return false;
+}
+
+bool GetAsInteger(const base::Value* val,
+                  const base::StringPiece& path,
+                  int* out) {
+  if (val) {
+    auto* found = val->FindKey(path);
+    if (found && found->is_int()) {
+      *out = found->GetInt();
+      return true;
+    } else if (found && found->is_string()) {
+      return base::StringToInt(found->GetString(), out);
+    }
+  }
+  return false;
+}
+
+}  // namespace
+
 namespace atom {
 
 // static
@@ -45,7 +91,7 @@ WebContentsPreferences::WebContentsPreferences(
   copied.Delete("isGuest");
   copied.Delete("session");
 
-  mate::ConvertFromV8(isolate, copied.GetHandle(), &dict_);
+  mate::ConvertFromV8(isolate, copied.GetHandle(), &preference_);
   web_contents->SetUserData(UserDataKey(), base::WrapUnique(this));
 
   instances_.push_back(this);
@@ -78,7 +124,7 @@ WebContentsPreferences::WebContentsPreferences(
 #endif
   SetDefaultBoolIfUndefined(options::kOffscreen, false);
 
-  last_dict_ = std::move(*dict_.CreateDeepCopy());
+  last_preference_ = preference_.Clone();
 }
 
 WebContentsPreferences::~WebContentsPreferences() {
@@ -89,23 +135,38 @@ WebContentsPreferences::~WebContentsPreferences() {
 bool WebContentsPreferences::SetDefaultBoolIfUndefined(
     const base::StringPiece& key,
     bool val) {
-  bool existing;
-  if (!dict_.GetBoolean(key, &existing)) {
-    dict_.SetBoolean(key, val);
+  auto* current_value =
+      preference_.FindKeyOfType(key, base::Value::Type::BOOLEAN);
+  if (current_value) {
+    return current_value->GetBool();
+  } else {
+    preference_.SetKey(key, base::Value(val));
     return val;
   }
-  return existing;
 }
 
 bool WebContentsPreferences::IsEnabled(const base::StringPiece& name,
-                                       bool default_value) {
-  bool bool_value = default_value;
-  dict_.GetBoolean(name, &bool_value);
-  return bool_value;
+                                       bool default_value) const {
+  auto* current_value =
+      preference_.FindKeyOfType(name, base::Value::Type::BOOLEAN);
+  if (current_value)
+    return current_value->GetBool();
+  return default_value;
 }
 
 void WebContentsPreferences::Merge(const base::DictionaryValue& extend) {
-  dict_.MergeDictionary(&extend);
+  if (preference_.is_dict())
+    static_cast<base::DictionaryValue*>(&preference_)->MergeDictionary(&extend);
+}
+
+void WebContentsPreferences::Clear() {
+  if (preference_.is_dict())
+    static_cast<base::DictionaryValue*>(&preference_)->Clear();
+}
+
+bool WebContentsPreferences::GetPreference(const base::StringPiece& name,
+                                           std::string* value) const {
+  return GetAsString(&preference_, name, value);
 }
 
 // static
@@ -129,51 +190,50 @@ WebContentsPreferences* WebContentsPreferences::From(
 
 void WebContentsPreferences::AppendCommandLineSwitches(
     base::CommandLine* command_line) {
-  bool b;
   // Check if plugins are enabled.
-  if (dict_.GetBoolean(options::kPlugins, &b) && b)
+  if (IsEnabled(options::kPlugins))
     command_line->AppendSwitch(switches::kEnablePlugins);
 
   // Experimental flags.
-  if (dict_.GetBoolean(options::kExperimentalFeatures, &b) && b)
+  if (IsEnabled(options::kExperimentalFeatures))
     command_line->AppendSwitch(
         ::switches::kEnableExperimentalWebPlatformFeatures);
 
   // Check if we have node integration specified.
-  bool node_integration = true;
-  dict_.GetBoolean(options::kNodeIntegration, &node_integration);
+  bool enable_node_integration = IsEnabled(options::kNodeIntegration, true);
   command_line->AppendSwitchASCII(switches::kNodeIntegration,
-                                  node_integration ? "true" : "false");
+                                  enable_node_integration ? "true" : "false");
 
   // Whether to enable node integration in Worker.
-  if (dict_.GetBoolean(options::kNodeIntegrationInWorker, &b) && b)
+  if (IsEnabled(options::kNodeIntegrationInWorker))
     command_line->AppendSwitch(switches::kNodeIntegrationInWorker);
 
   // Check if webview tag creation is enabled, default to nodeIntegration value.
   // TODO(kevinsawicki): Default to false in 2.0
-  bool webview_tag = node_integration;
-  dict_.GetBoolean(options::kWebviewTag, &webview_tag);
+  bool webview_tag = IsEnabled(options::kWebviewTag, enable_node_integration);
   command_line->AppendSwitchASCII(switches::kWebviewTag,
                                   webview_tag ? "true" : "false");
 
   // If the `sandbox` option was passed to the BrowserWindow's webPreferences,
   // pass `--enable-sandbox` to the renderer so it won't have any node.js
   // integration.
-  if (dict_.GetBoolean(options::kSandbox, &b) && b)
+  if (IsEnabled(options::kSandbox))
     command_line->AppendSwitch(switches::kEnableSandbox);
   else if (!command_line->HasSwitch(switches::kEnableSandbox))
     command_line->AppendSwitch(::switches::kNoSandbox);
-  if (dict_.GetBoolean(options::kNativeWindowOpen, &b) && b)
+
+  // Check if nativeWindowOpen is enabled.
+  if (IsEnabled(options::kNativeWindowOpen))
     command_line->AppendSwitch(switches::kNativeWindowOpen);
 
   // The preload script.
   base::FilePath::StringType preload;
-  if (dict_.GetString(options::kPreloadScript, &preload)) {
+  if (GetAsString(&preference_, options::kPreloadScript, &preload)) {
     if (base::FilePath(preload).IsAbsolute())
       command_line->AppendSwitchNative(switches::kPreloadScript, preload);
     else
       LOG(ERROR) << "preload script must have absolute path.";
-  } else if (dict_.GetString(options::kPreloadURL, &preload)) {
+  } else if (GetAsString(&preference_, options::kPreloadURL, &preload)) {
     // Translate to file path if there is "preload-url" option.
     base::FilePath preload_path;
     if (net::FileURLToFilePath(GURL(preload), &preload_path))
@@ -183,57 +243,61 @@ void WebContentsPreferences::AppendCommandLineSwitches(
   }
 
   // Custom args for renderer process
-  base::Value* customArgs;
-  if (dict_.Get(options::kCustomArgs, &customArgs) && customArgs->is_list()) {
-    for (const base::Value& customArg : customArgs->GetList()) {
+  auto* customArgs =
+      preference_.FindKeyOfType(options::kCustomArgs, base::Value::Type::LIST);
+  if (customArgs) {
+    for (const auto& customArg : customArgs->GetList()) {
       if (customArg.is_string())
         command_line->AppendArg(customArg.GetString());
     }
   }
 
   // Run Electron APIs and preload script in isolated world
-  if (dict_.GetBoolean(options::kContextIsolation, &b) && b)
+  if (IsEnabled(options::kContextIsolation))
     command_line->AppendSwitch(switches::kContextIsolation);
 
   // --background-color.
   std::string s;
-  if (dict_.GetString(options::kBackgroundColor, &s))
+  if (GetAsString(&preference_, options::kBackgroundColor, &s))
     command_line->AppendSwitchASCII(switches::kBackgroundColor, s);
 
   // --guest-instance-id, which is used to identify guest WebContents.
   int guest_instance_id = 0;
-  if (dict_.GetInteger(options::kGuestInstanceID, &guest_instance_id))
+  if (GetAsInteger(&preference_, options::kGuestInstanceID, &guest_instance_id))
     command_line->AppendSwitchASCII(switches::kGuestInstanceID,
                                     base::IntToString(guest_instance_id));
 
   // Pass the opener's window id.
   int opener_id;
-  if (dict_.GetInteger(options::kOpenerID, &opener_id))
+  if (GetAsInteger(&preference_, options::kOpenerID, &opener_id))
     command_line->AppendSwitchASCII(switches::kOpenerID,
                                     base::IntToString(opener_id));
 
 #if defined(OS_MACOSX)
   // Enable scroll bounce.
-  if (dict_.GetBoolean(options::kScrollBounce, &b) && b)
+  if (IsEnabled(options::kScrollBounce))
     command_line->AppendSwitch(switches::kScrollBounce);
 #endif
 
   // Custom command line switches.
-  const base::ListValue* args;
-  if (dict_.GetList("commandLineSwitches", &args)) {
-    for (size_t i = 0; i < args->GetSize(); ++i) {
-      std::string arg;
-      if (args->GetString(i, &arg) && !arg.empty())
-        command_line->AppendSwitch(arg);
+  auto* args =
+      preference_.FindKeyOfType("commandLineSwitches", base::Value::Type::LIST);
+  if (args) {
+    for (const auto& arg : args->GetList()) {
+      if (arg.is_string()) {
+        const auto& arg_val = arg.GetString();
+        if (!arg_val.empty())
+          command_line->AppendSwitch(arg_val);
+      }
     }
   }
 
   // Enable blink features.
-  if (dict_.GetString(options::kEnableBlinkFeatures, &s))
+  if (GetAsString(&preference_, options::kEnableBlinkFeatures, &s))
     command_line->AppendSwitchASCII(::switches::kEnableBlinkFeatures, s);
 
   // Disable blink features.
-  if (dict_.GetString(options::kDisableBlinkFeatures, &s))
+  if (GetAsString(&preference_, options::kDisableBlinkFeatures, &s))
     command_line->AppendSwitchASCII(::switches::kDisableBlinkFeatures, s);
 
   if (guest_instance_id) {
@@ -260,69 +324,59 @@ void WebContentsPreferences::AppendCommandLineSwitches(
   // We are appending args to a webContents so let's save the current state
   // of our preferences object so that during the lifetime of the WebContents
   // we can fetch the options used to initally configure the WebContents
-  last_dict_ = std::move(*dict_.CreateDeepCopy());
+  last_preference_ = preference_.Clone();
 }
 
 void WebContentsPreferences::OverrideWebkitPrefs(
     content::WebPreferences* prefs) {
-  bool b;
-  if (dict_.GetBoolean("javascript", &b))
-    prefs->javascript_enabled = b;
-  if (dict_.GetBoolean("images", &b))
-    prefs->images_enabled = b;
-  if (dict_.GetBoolean("textAreasAreResizable", &b))
-    prefs->text_areas_are_resizable = b;
-  if (dict_.GetBoolean("webgl", &b)) {
-    prefs->webgl1_enabled = b;
-    prefs->webgl2_enabled = b;
-  }
-  if (dict_.GetBoolean(options::kWebSecurity, &b)) {
-    prefs->web_security_enabled = b;
-    prefs->allow_running_insecure_content = !b;
-  }
-  if (dict_.GetBoolean(options::kAllowRunningInsecureContent, &b))
-    prefs->allow_running_insecure_content = b;
-  if (dict_.GetBoolean("navigateOnDragDrop", &b))
-    prefs->navigate_on_drag_drop = b;
-  const base::DictionaryValue* fonts = nullptr;
-  if (dict_.GetDictionary("defaultFontFamily", &fonts)) {
+  prefs->javascript_enabled = IsEnabled("javascript", true /* default_value */);
+  prefs->images_enabled = IsEnabled("images", true /* default_value */);
+  prefs->text_areas_are_resizable =
+      IsEnabled("textAreasAreResizable", true /* default_value */);
+  prefs->navigate_on_drag_drop =
+      IsEnabled("navigateOnDragDrop", false /* default_value */);
+
+  // Check if webgl should be enabled.
+  bool is_webgl_enabled = IsEnabled("webgl", true /* default_value */);
+  prefs->webgl1_enabled = is_webgl_enabled;
+  prefs->webgl2_enabled = is_webgl_enabled;
+
+  // Check if web security should be enabled.
+  bool is_web_security_enabled =
+      IsEnabled(options::kWebSecurity, true /* default_value */);
+  prefs->web_security_enabled = is_web_security_enabled;
+  prefs->allow_running_insecure_content =
+      IsEnabled(options::kAllowRunningInsecureContent,
+                !is_web_security_enabled /* default_value */);
+
+  auto* fonts_dict = preference_.FindKeyOfType("defaultFontFamily",
+                                               base::Value::Type::DICTIONARY);
+  if (fonts_dict) {
     base::string16 font;
-    if (fonts->GetString("standard", &font))
+    if (GetAsString(fonts_dict, "standard", &font))
       prefs->standard_font_family_map[content::kCommonScript] = font;
-    if (fonts->GetString("serif", &font))
+    if (GetAsString(fonts_dict, "serif", &font))
       prefs->serif_font_family_map[content::kCommonScript] = font;
-    if (fonts->GetString("sansSerif", &font))
+    if (GetAsString(fonts_dict, "sansSerif", &font))
       prefs->sans_serif_font_family_map[content::kCommonScript] = font;
-    if (fonts->GetString("monospace", &font))
+    if (GetAsString(fonts_dict, "monospace", &font))
       prefs->fixed_font_family_map[content::kCommonScript] = font;
-    if (fonts->GetString("cursive", &font))
+    if (GetAsString(fonts_dict, "cursive", &font))
       prefs->cursive_font_family_map[content::kCommonScript] = font;
-    if (fonts->GetString("fantasy", &font))
+    if (GetAsString(fonts_dict, "fantasy", &font))
       prefs->fantasy_font_family_map[content::kCommonScript] = font;
   }
+
   int size;
-  if (GetInteger("defaultFontSize", &size))
+  if (GetAsInteger(&preference_, "defaultFontSize", &size))
     prefs->default_font_size = size;
-  if (GetInteger("defaultMonospaceFontSize", &size))
+  if (GetAsInteger(&preference_, "defaultMonospaceFontSize", &size))
     prefs->default_fixed_font_size = size;
-  if (GetInteger("minimumFontSize", &size))
+  if (GetAsInteger(&preference_, "minimumFontSize", &size))
     prefs->minimum_font_size = size;
   std::string encoding;
-  if (dict_.GetString("defaultEncoding", &encoding))
+  if (GetAsString(&preference_, "defaultEncoding", &encoding))
     prefs->default_encoding = encoding;
 }
 
-bool WebContentsPreferences::GetInteger(const base::StringPiece& attribute_name,
-                                        int* val) {
-  // if it is already an integer, no conversion needed
-  if (dict_.GetInteger(attribute_name, val))
-    return true;
-
-  std::string str;
-  if (dict_.GetString(attribute_name, &str))
-    return base::StringToInt(str, val);
-
-  return false;
-}
-
 }  // namespace atom

+ 12 - 9
atom/browser/web_contents_preferences.h

@@ -37,7 +37,8 @@ class WebContentsPreferences
   ~WebContentsPreferences() override;
 
   // A simple way to know whether a Boolean property is enabled.
-  bool IsEnabled(const base::StringPiece& name, bool default_value = false);
+  bool IsEnabled(const base::StringPiece& name,
+                 bool default_value = false) const;
 
   // $.extend(|web_preferences|, |new_web_preferences|).
   void Merge(const base::DictionaryValue& new_web_preferences);
@@ -48,10 +49,15 @@ class WebContentsPreferences
   // Modify the WebPreferences according to preferences.
   void OverrideWebkitPrefs(content::WebPreferences* prefs);
 
+  // Clear the current WebPreferences.
+  void Clear();
+
+  // Return true if the particular preference value exists.
+  bool GetPreference(const base::StringPiece& name, std::string* value) const;
+
   // Returns the web preferences.
-  base::DictionaryValue* dict() { return &dict_; }
-  const base::DictionaryValue* dict() const { return &dict_; }
-  base::DictionaryValue* last_dict() { return &last_dict_; }
+  base::Value* preference() { return &preference_; }
+  base::Value* last_preference() { return &last_preference_; }
 
  private:
   friend class content::WebContentsUserData<WebContentsPreferences>;
@@ -63,15 +69,12 @@ class WebContentsPreferences
   // Set preference value to given bool if user did not provide value
   bool SetDefaultBoolIfUndefined(const base::StringPiece& key, bool val);
 
-  // Get preferences value as integer possibly coercing it from a string
-  bool GetInteger(const base::StringPiece& attribute_name, int* val);
-
   static std::vector<WebContentsPreferences*> instances_;
 
   content::WebContents* web_contents_;
 
-  base::DictionaryValue dict_;
-  base::DictionaryValue last_dict_;
+  base::Value preference_ = base::Value(base::Value::Type::DICTIONARY);
+  base::Value last_preference_ = base::Value(base::Value::Type::DICTIONARY);
 
   DISALLOW_COPY_AND_ASSIGN(WebContentsPreferences);
 };

+ 20 - 0
atom/common/native_mate_converters/value_converter.cc

@@ -30,6 +30,26 @@ v8::Local<v8::Value> Converter<base::DictionaryValue>::ToV8(
   return converter.ToV8Value(&val, isolate->GetCurrentContext());
 }
 
+bool Converter<base::Value>::FromV8(v8::Isolate* isolate,
+                                    v8::Local<v8::Value> val,
+                                    base::Value* out) {
+  atom::V8ValueConverter converter;
+  std::unique_ptr<base::Value> value(
+      converter.FromV8Value(val, isolate->GetCurrentContext()));
+  if (value) {
+    *out = value->Clone();
+    return true;
+  } else {
+    return false;
+  }
+}
+
+v8::Local<v8::Value> Converter<base::Value>::ToV8(v8::Isolate* isolate,
+                                                  const base::Value& val) {
+  atom::V8ValueConverter converter;
+  return converter.ToV8Value(&val, isolate->GetCurrentContext());
+}
+
 bool Converter<base::ListValue>::FromV8(v8::Isolate* isolate,
                                         v8::Local<v8::Value> val,
                                         base::ListValue* out) {

+ 10 - 0
atom/common/native_mate_converters/value_converter.h

@@ -10,6 +10,7 @@
 namespace base {
 class DictionaryValue;
 class ListValue;
+class Value;
 }  // namespace base
 
 namespace mate {
@@ -23,6 +24,15 @@ struct Converter<base::DictionaryValue> {
                                    const base::DictionaryValue& val);
 };
 
+template <>
+struct Converter<base::Value> {
+  static bool FromV8(v8::Isolate* isolate,
+                     v8::Local<v8::Value> val,
+                     base::Value* out);
+  static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
+                                   const base::Value& val);
+};
+
 template <>
 struct Converter<base::ListValue> {
   static bool FromV8(v8::Isolate* isolate,

+ 3 - 1
atom/renderer/preferences_manager.cc

@@ -26,7 +26,9 @@ bool PreferencesManager::OnControlMessageReceived(const IPC::Message& message) {
 
 void PreferencesManager::OnUpdatePreferences(
     const base::ListValue& preferences) {
-  preferences_ = preferences.CreateDeepCopy();
+  auto copy =
+      base::ListValue::From(base::Value::ToUniquePtrValue(preferences.Clone()));
+  preferences_.swap(copy);
 }
 
 }  // namespace atom