Add API to set render process preferences
authorCheng Zhao <zcbenz@gmail.com>
Thu, 26 May 2016 23:51:02 +0000 (08:51 +0900)
committerCheng Zhao <zcbenz@gmail.com>
Thu, 26 May 2016 23:51:02 +0000 (08:51 +0900)
atom/browser/api/atom_api_render_process_preferences.cc [new file with mode: 0644]
atom/browser/api/atom_api_render_process_preferences.h [new file with mode: 0644]
atom/browser/render_process_preferences.cc [new file with mode: 0644]
atom/browser/render_process_preferences.h [new file with mode: 0644]
atom/common/api/api_messages.h
atom/common/node_bindings.cc
atom/renderer/atom_renderer_client.cc
atom/renderer/atom_renderer_client.h
atom/renderer/preferences_manager.cc [new file with mode: 0644]
atom/renderer/preferences_manager.h [new file with mode: 0644]
filenames.gypi

diff --git a/atom/browser/api/atom_api_render_process_preferences.cc b/atom/browser/api/atom_api_render_process_preferences.cc
new file mode 100644 (file)
index 0000000..3bdbfae
--- /dev/null
@@ -0,0 +1,74 @@
+// Copyright (c) 2016 GitHub, Inc.
+// Use of this source code is governed by the MIT license that can be
+// found in the LICENSE file.
+
+#include "atom/browser/api/atom_api_render_process_preferences.h"
+
+#include "atom/common/native_mate_converters/value_converter.h"
+#include "atom/common/node_includes.h"
+#include "native_mate/dictionary.h"
+#include "native_mate/object_template_builder.h"
+
+namespace atom {
+
+namespace api {
+
+namespace {
+
+bool IsBrowserWindow(content::RenderProcessHost* process) {
+  return true;
+}
+
+}  // namespace
+
+RenderProcessPreferences::RenderProcessPreferences(
+    v8::Isolate* isolate,
+    const atom::RenderProcessPreferences::Predicate& predicate)
+    : preferences_(predicate) {
+  Init(isolate);
+}
+
+RenderProcessPreferences::~RenderProcessPreferences() {
+}
+
+int RenderProcessPreferences::AddEntry(const base::DictionaryValue& entry) {
+  return preferences_.AddEntry(entry);
+}
+
+void RenderProcessPreferences::RemoveEntry(int id) {
+  preferences_.RemoveEntry(id);
+}
+
+// static
+void RenderProcessPreferences::BuildPrototype(
+    v8::Isolate* isolate, v8::Local<v8::ObjectTemplate> prototype) {
+  mate::ObjectTemplateBuilder(isolate, prototype)
+      .SetMethod("addEntry", &RenderProcessPreferences::AddEntry)
+      .SetMethod("removeEntry", &RenderProcessPreferences::RemoveEntry);
+}
+
+// static
+mate::Handle<RenderProcessPreferences>
+RenderProcessPreferences::ForAllBrowserWindow(v8::Isolate* isolate) {
+  return mate::CreateHandle(
+      isolate,
+      new RenderProcessPreferences(isolate, base::Bind(&IsBrowserWindow)));
+}
+
+}  // namespace api
+
+}  // namespace atom
+
+namespace {
+
+void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
+                v8::Local<v8::Context> context, void* priv) {
+  mate::Dictionary dict(context->GetIsolate(), exports);
+  dict.SetMethod("forAllBrowserWindow",
+                 &atom::api::RenderProcessPreferences::ForAllBrowserWindow);
+}
+
+}  // namespace
+
+NODE_MODULE_CONTEXT_AWARE_BUILTIN(atom_browser_render_process_preferences,
+                                  Initialize)
diff --git a/atom/browser/api/atom_api_render_process_preferences.h b/atom/browser/api/atom_api_render_process_preferences.h
new file mode 100644 (file)
index 0000000..a305f13
--- /dev/null
@@ -0,0 +1,44 @@
+// Copyright (c) 2016 GitHub, Inc.
+// Use of this source code is governed by the MIT license that can be
+// found in the LICENSE file.
+
+#ifndef ATOM_BROWSER_API_ATOM_API_RENDER_PROCESS_PREFERENCES_H_
+#define ATOM_BROWSER_API_ATOM_API_RENDER_PROCESS_PREFERENCES_H_
+
+#include "atom/browser/render_process_preferences.h"
+#include "native_mate/handle.h"
+#include "native_mate/wrappable.h"
+
+namespace atom {
+
+namespace api {
+
+class RenderProcessPreferences
+    : public mate::Wrappable<RenderProcessPreferences> {
+ public:
+  static mate::Handle<RenderProcessPreferences>
+      ForAllBrowserWindow(v8::Isolate* isolate);
+
+  static void BuildPrototype(v8::Isolate* isolate,
+                             v8::Local<v8::ObjectTemplate> prototype);
+
+  int AddEntry(const base::DictionaryValue& entry);
+  void RemoveEntry(int id);
+
+ protected:
+  RenderProcessPreferences(
+      v8::Isolate* isolate,
+      const atom::RenderProcessPreferences::Predicate& predicate);
+  ~RenderProcessPreferences() override;
+
+ private:
+  atom::RenderProcessPreferences preferences_;
+
+  DISALLOW_COPY_AND_ASSIGN(RenderProcessPreferences);
+};
+
+}  // namespace api
+
+}  // namespace atom
+
+#endif  // ATOM_BROWSER_API_ATOM_API_RENDER_PROCESS_PREFERENCES_H_
diff --git a/atom/browser/render_process_preferences.cc b/atom/browser/render_process_preferences.cc
new file mode 100644 (file)
index 0000000..d109c87
--- /dev/null
@@ -0,0 +1,63 @@
+// Copyright (c) 2016 GitHub, Inc.
+// Use of this source code is governed by the MIT license that can be
+// found in the LICENSE file.
+
+#include "atom/browser/render_process_preferences.h"
+
+#include "atom/common/api/api_messages.h"
+#include "content/public/browser/notification_service.h"
+#include "content/public/browser/notification_types.h"
+#include "content/public/browser/render_process_host.h"
+
+namespace atom {
+
+RenderProcessPreferences::RenderProcessPreferences(const Predicate& predicate)
+    : predicate_(predicate),
+      next_id_(0),
+      cache_needs_update_(true) {
+  registrar_.Add(this,
+                 content::NOTIFICATION_RENDERER_PROCESS_CREATED,
+                 content::NotificationService::AllBrowserContextsAndSources());
+}
+
+RenderProcessPreferences::~RenderProcessPreferences() {
+}
+
+int RenderProcessPreferences::AddEntry(const base::DictionaryValue& entry) {
+  int id = ++next_id_;
+  entries_[id] = entry.CreateDeepCopy();
+  cache_needs_update_ = true;
+  return id;
+}
+
+void RenderProcessPreferences::RemoveEntry(int id) {
+  cache_needs_update_ = true;
+  entries_.erase(id);
+}
+
+void RenderProcessPreferences::Observe(
+    int type,
+    const content::NotificationSource& source,
+    const content::NotificationDetails& details) {
+  DCHECK_EQ(type, content::NOTIFICATION_RENDERER_PROCESS_CREATED);
+  content::RenderProcessHost* process =
+      content::Source<content::RenderProcessHost>(source).ptr();
+
+  if (!predicate_.Run(process))
+    return;
+
+  UpdateCache();
+  process->Send(new AtomMsg_UpdatePreferences(cached_entries_));
+}
+
+void RenderProcessPreferences::UpdateCache() {
+  if (!cache_needs_update_)
+    return;
+
+  cached_entries_.Clear();
+  for (const auto& iter : entries_)
+    cached_entries_.Append(iter.second->CreateDeepCopy());
+  cache_needs_update_ = false;
+}
+
+}  // namespace atom
diff --git a/atom/browser/render_process_preferences.h b/atom/browser/render_process_preferences.h
new file mode 100644 (file)
index 0000000..77bf176
--- /dev/null
@@ -0,0 +1,61 @@
+// Copyright (c) 2016 GitHub, Inc.
+// Use of this source code is governed by the MIT license that can be
+// found in the LICENSE file.
+
+#ifndef ATOM_BROWSER_RENDER_PROCESS_PREFERENCES_H_
+#define ATOM_BROWSER_RENDER_PROCESS_PREFERENCES_H_
+
+#include <memory>
+#include <unordered_map>
+
+#include "base/callback.h"
+#include "base/values.h"
+#include "content/public/browser/notification_observer.h"
+#include "content/public/browser/notification_registrar.h"
+
+namespace content {
+class RenderProcessHost;
+}
+
+namespace atom {
+
+// Sets user preferences for render processes.
+class RenderProcessPreferences : public content::NotificationObserver {
+ public:
+  using Predicate = base::Callback<bool(content::RenderProcessHost*)>;
+
+  // The |predicate| is used to determine whether to set preferences for a
+  // render process.
+  explicit RenderProcessPreferences(const Predicate& predicate);
+  virtual ~RenderProcessPreferences();
+
+  int AddEntry(const base::DictionaryValue& entry);
+  void RemoveEntry(int id);
+
+ private:
+  // content::NotificationObserver:
+  void Observe(int type,
+               const content::NotificationSource& source,
+               const content::NotificationDetails& details) override;
+
+  void UpdateCache();
+
+  // Manages our notification registrations.
+  content::NotificationRegistrar registrar_;
+
+  Predicate predicate_;
+
+  int next_id_;
+  std::unordered_map<int, std::unique_ptr<base::DictionaryValue>> entries_;
+
+  // We need to convert the |entries_| to ListValue for multiple times, this
+  // caches is only updated when we are sending messages.
+  bool cache_needs_update_;
+  base::ListValue cached_entries_;
+
+  DISALLOW_COPY_AND_ASSIGN(RenderProcessPreferences);
+};
+
+}  // namespace atom
+
+#endif  // ATOM_BROWSER_RENDER_PROCESS_PREFERENCES_H_
index eeb2661..c7ba38d 100644 (file)
@@ -37,3 +37,6 @@ IPC_MESSAGE_ROUTED2(AtomViewMsg_Message,
 // Sent by the renderer when the draggable regions are updated.
 IPC_MESSAGE_ROUTED1(AtomViewHostMsg_UpdateDraggableRegions,
                     std::vector<atom::DraggableRegion> /* regions */)
+
+// Update renderer process preferences.
+IPC_MESSAGE_CONTROL1(AtomMsg_UpdatePreferences, base::ListValue)
index a556205..ed2ea01 100644 (file)
@@ -42,6 +42,7 @@ REFERENCE_MODULE(atom_browser_power_monitor);
 REFERENCE_MODULE(atom_browser_power_save_blocker);
 REFERENCE_MODULE(atom_browser_protocol);
 REFERENCE_MODULE(atom_browser_global_shortcut);
+REFERENCE_MODULE(atom_browser_render_process_preferences);
 REFERENCE_MODULE(atom_browser_session);
 REFERENCE_MODULE(atom_browser_system_preferences);
 REFERENCE_MODULE(atom_browser_tray);
index 5613f20..114fb90 100644 (file)
 #include "atom/common/api/atom_bindings.h"
 #include "atom/common/api/event_emitter_caller.h"
 #include "atom/common/color_util.h"
+#include "atom/common/native_mate_converters/value_converter.h"
 #include "atom/common/node_bindings.h"
 #include "atom/common/node_includes.h"
 #include "atom/common/options_switches.h"
 #include "atom/renderer/atom_render_view_observer.h"
 #include "atom/renderer/guest_view_container.h"
 #include "atom/renderer/node_array_buffer_bridge.h"
+#include "atom/renderer/preferences_manager.h"
 #include "base/command_line.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/renderer/media/chrome_key_systems.h"
@@ -29,6 +31,7 @@
 #include "content/public/renderer/render_thread.h"
 #include "content/public/renderer/render_view.h"
 #include "ipc/ipc_message_macros.h"
+#include "native_mate/dictionary.h"
 #include "net/base/net_errors.h"
 #include "third_party/WebKit/public/web/WebCustomElement.h"
 #include "third_party/WebKit/public/web/WebFrameWidget.h"
@@ -85,6 +88,23 @@ class AtomRenderFrameObserver : public content::RenderFrameObserver {
   DISALLOW_COPY_AND_ASSIGN(AtomRenderFrameObserver);
 };
 
+v8::Local<v8::Value> GetRenderProcessPreferences(
+    const PreferencesManager* preferences_manager, v8::Isolate* isolate) {
+  if (preferences_manager->preferences())
+    return mate::ConvertToV8(isolate, *preferences_manager->preferences());
+  else
+    return v8::Null(isolate);
+}
+
+void AddRenderBindings(v8::Isolate* isolate,
+                       v8::Local<v8::Object> process,
+                       const PreferencesManager* preferences_manager) {
+  mate::Dictionary dict(isolate, process);
+  dict.SetMethod(
+      "getRenderProcessPreferences",
+      base::Bind(GetRenderProcessPreferences, preferences_manager));
+}
+
 }  // namespace
 
 AtomRendererClient::AtomRendererClient()
@@ -101,6 +121,8 @@ void AtomRendererClient::RenderThreadStarted() {
 
   OverrideNodeArrayBuffer();
 
+  preferences_manager_.reset(new PreferencesManager);
+
 #if defined(OS_WIN)
   // Set ApplicationUserModelID in renderer process.
   base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
@@ -201,6 +223,8 @@ void AtomRendererClient::DidCreateScriptContext(
 
   // Add atom-shell extended APIs.
   atom_bindings_->BindTo(env->isolate(), env->process_object());
+  AddRenderBindings(env->isolate(), env->process_object(),
+                    preferences_manager_.get());
 
   // Load everything.
   node_bindings_->LoadEnvironment(env);
index 16b975f..78c2e49 100644 (file)
@@ -13,6 +13,7 @@
 namespace atom {
 
 class AtomBindings;
+class PreferencesManager;
 class NodeBindings;
 
 class AtomRendererClient : public content::ContentRendererClient {
@@ -61,6 +62,7 @@ class AtomRendererClient : public content::ContentRendererClient {
 
   std::unique_ptr<NodeBindings> node_bindings_;
   std::unique_ptr<AtomBindings> atom_bindings_;
+  std::unique_ptr<PreferencesManager> preferences_manager_;
 
   DISALLOW_COPY_AND_ASSIGN(AtomRendererClient);
 };
diff --git a/atom/renderer/preferences_manager.cc b/atom/renderer/preferences_manager.cc
new file mode 100644 (file)
index 0000000..a9ed710
--- /dev/null
@@ -0,0 +1,34 @@
+// Copyright (c) 2016 GitHub, Inc.
+// Use of this source code is governed by the MIT license that can be
+// found in the LICENSE file.
+
+#include "atom/renderer/preferences_manager.h"
+
+#include "atom/common/api/api_messages.h"
+#include "content/public/renderer/render_thread.h"
+
+namespace atom {
+
+PreferencesManager::PreferencesManager() {
+  content::RenderThread::Get()->AddObserver(this);
+}
+
+PreferencesManager::~PreferencesManager() {
+}
+
+bool PreferencesManager::OnControlMessageReceived(
+    const IPC::Message& message) {
+  bool handled = true;
+  IPC_BEGIN_MESSAGE_MAP(PreferencesManager, message)
+    IPC_MESSAGE_HANDLER(AtomMsg_UpdatePreferences, OnUpdatePreferences)
+    IPC_MESSAGE_UNHANDLED(handled = false)
+  IPC_END_MESSAGE_MAP()
+  return handled;
+}
+
+void PreferencesManager::OnUpdatePreferences(
+    const base::ListValue& preferences) {
+  preferences_ = preferences.CreateDeepCopy();
+}
+
+}  // namespace atom
diff --git a/atom/renderer/preferences_manager.h b/atom/renderer/preferences_manager.h
new file mode 100644 (file)
index 0000000..4519280
--- /dev/null
@@ -0,0 +1,35 @@
+// Copyright (c) 2016 GitHub, Inc.
+// Use of this source code is governed by the MIT license that can be
+// found in the LICENSE file.
+
+#ifndef ATOM_RENDERER_PREFERENCES_MANAGER_H_
+#define ATOM_RENDERER_PREFERENCES_MANAGER_H_
+
+#include <memory>
+
+#include "base/values.h"
+#include "content/public/renderer/render_process_observer.h"
+
+namespace atom {
+
+class PreferencesManager : public content::RenderProcessObserver {
+ public:
+  PreferencesManager();
+  ~PreferencesManager() override;
+
+  const base::ListValue* preferences() const { return preferences_.get(); }
+
+ private:
+  // content::RenderThreadObserver:
+  bool OnControlMessageReceived(const IPC::Message& message) override;
+
+  void OnUpdatePreferences(const base::ListValue& preferences);
+
+  std::unique_ptr<base::ListValue> preferences_;
+
+  DISALLOW_COPY_AND_ASSIGN(PreferencesManager);
+};
+
+}  // namespace atom
+
+#endif  // ATOM_RENDERER_PREFERENCES_MANAGER_H_
index 14d0127..d8e6657 100644 (file)
       'atom/browser/api/atom_api_power_monitor.h',
       'atom/browser/api/atom_api_power_save_blocker.cc',
       'atom/browser/api/atom_api_power_save_blocker.h',
+      'atom/browser/api/atom_api_render_process_preferences.cc',
+      'atom/browser/api/atom_api_render_process_preferences.h',
       'atom/browser/api/atom_api_protocol.cc',
       'atom/browser/api/atom_api_protocol.h',
       'atom/browser/api/atom_api_screen.cc',
       'atom/browser/net/url_request_fetch_job.h',
       'atom/browser/node_debugger.cc',
       'atom/browser/node_debugger.h',
+      'atom/browser/render_process_preferences.cc',
+      'atom/browser/render_process_preferences.h',
       'atom/browser/ui/accelerator_util.cc',
       'atom/browser/ui/accelerator_util.h',
       'atom/browser/ui/accelerator_util_mac.mm',
       'atom/renderer/guest_view_container.h',
       'atom/renderer/node_array_buffer_bridge.cc',
       'atom/renderer/node_array_buffer_bridge.h',
+      'atom/renderer/preferences_manager.cc',
+      'atom/renderer/preferences_manager.h',
       'atom/utility/atom_content_utility_client.cc',
       'atom/utility/atom_content_utility_client.h',
       'chromium_src/chrome/browser/browser_process.cc',