From 4fb9e20c336a07f5530714afbc375967339f4483 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Fri, 27 May 2016 08:51:02 +0900 Subject: [PATCH] Add API to set render process preferences --- .../api/atom_api_render_process_preferences.cc | 74 ++++++++++++++++++++++ .../api/atom_api_render_process_preferences.h | 44 +++++++++++++ atom/browser/render_process_preferences.cc | 63 ++++++++++++++++++ atom/browser/render_process_preferences.h | 61 ++++++++++++++++++ atom/common/api/api_messages.h | 3 + atom/common/node_bindings.cc | 1 + atom/renderer/atom_renderer_client.cc | 24 +++++++ atom/renderer/atom_renderer_client.h | 2 + atom/renderer/preferences_manager.cc | 34 ++++++++++ atom/renderer/preferences_manager.h | 35 ++++++++++ filenames.gypi | 6 ++ 11 files changed, 347 insertions(+) create mode 100644 atom/browser/api/atom_api_render_process_preferences.cc create mode 100644 atom/browser/api/atom_api_render_process_preferences.h create mode 100644 atom/browser/render_process_preferences.cc create mode 100644 atom/browser/render_process_preferences.h create mode 100644 atom/renderer/preferences_manager.cc create mode 100644 atom/renderer/preferences_manager.h 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 index 0000000..3bdbfae --- /dev/null +++ b/atom/browser/api/atom_api_render_process_preferences.cc @@ -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 prototype) { + mate::ObjectTemplateBuilder(isolate, prototype) + .SetMethod("addEntry", &RenderProcessPreferences::AddEntry) + .SetMethod("removeEntry", &RenderProcessPreferences::RemoveEntry); +} + +// static +mate::Handle +RenderProcessPreferences::ForAllBrowserWindow(v8::Isolate* isolate) { + return mate::CreateHandle( + isolate, + new RenderProcessPreferences(isolate, base::Bind(&IsBrowserWindow))); +} + +} // namespace api + +} // namespace atom + +namespace { + +void Initialize(v8::Local exports, v8::Local unused, + v8::Local 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 index 0000000..a305f13 --- /dev/null +++ b/atom/browser/api/atom_api_render_process_preferences.h @@ -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 { + public: + static mate::Handle + ForAllBrowserWindow(v8::Isolate* isolate); + + static void BuildPrototype(v8::Isolate* isolate, + v8::Local 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 index 0000000..d109c87 --- /dev/null +++ b/atom/browser/render_process_preferences.cc @@ -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(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 index 0000000..77bf176 --- /dev/null +++ b/atom/browser/render_process_preferences.h @@ -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 +#include + +#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; + + // 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> 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_ diff --git a/atom/common/api/api_messages.h b/atom/common/api/api_messages.h index eeb2661..c7ba38d 100644 --- a/atom/common/api/api_messages.h +++ b/atom/common/api/api_messages.h @@ -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 /* regions */) + +// Update renderer process preferences. +IPC_MESSAGE_CONTROL1(AtomMsg_UpdatePreferences, base::ListValue) diff --git a/atom/common/node_bindings.cc b/atom/common/node_bindings.cc index a556205..ed2ea01 100644 --- a/atom/common/node_bindings.cc +++ b/atom/common/node_bindings.cc @@ -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); diff --git a/atom/renderer/atom_renderer_client.cc b/atom/renderer/atom_renderer_client.cc index 5613f20..114fb90 100644 --- a/atom/renderer/atom_renderer_client.cc +++ b/atom/renderer/atom_renderer_client.cc @@ -11,12 +11,14 @@ #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 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 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); diff --git a/atom/renderer/atom_renderer_client.h b/atom/renderer/atom_renderer_client.h index 16b975f..78c2e49 100644 --- a/atom/renderer/atom_renderer_client.h +++ b/atom/renderer/atom_renderer_client.h @@ -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 node_bindings_; std::unique_ptr atom_bindings_; + std::unique_ptr 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 index 0000000..a9ed710 --- /dev/null +++ b/atom/renderer/preferences_manager.cc @@ -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 index 0000000..4519280 --- /dev/null +++ b/atom/renderer/preferences_manager.h @@ -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 + +#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 preferences_; + + DISALLOW_COPY_AND_ASSIGN(PreferencesManager); +}; + +} // namespace atom + +#endif // ATOM_RENDERER_PREFERENCES_MANAGER_H_ diff --git a/filenames.gypi b/filenames.gypi index 14d0127..d8e6657 100644 --- a/filenames.gypi +++ b/filenames.gypi @@ -109,6 +109,8 @@ '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', @@ -220,6 +222,8 @@ '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', @@ -396,6 +400,8 @@ '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', -- 2.7.4