refactor: simplify content script injection (#18532)

This commit is contained in:
Jeremy Apthorp 2019-06-04 16:07:34 -07:00 коммит произвёл GitHub
Родитель f80601da16
Коммит ed5fb4a720
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
17 изменённых файлов: 63 добавлений и 407 удалений

Просмотреть файл

@ -807,6 +807,14 @@ void App::BrowserChildProcessKilled(
void App::RenderProcessReady(content::RenderProcessHost* host) { void App::RenderProcessReady(content::RenderProcessHost* host) {
ChildProcessLaunched(content::PROCESS_TYPE_RENDERER, ChildProcessLaunched(content::PROCESS_TYPE_RENDERER,
host->GetProcess().Handle()); host->GetProcess().Handle());
// TODO(jeremy): this isn't really the right place to be creating
// `WebContents` instances, but this was implicitly happening before in
// `RenderProcessPreferences`, so this is at least more explicit...
content::WebContents* web_contents =
AtomBrowserClient::Get()->GetWebContentsFromProcessID(host->GetID());
if (web_contents)
WebContents::FromOrCreate(v8::Isolate::GetCurrent(), web_contents);
} }
void App::RenderProcessDisconnected(base::ProcessId host_pid) { void App::RenderProcessDisconnected(base::ProcessId host_pid) {

Просмотреть файл

@ -1,90 +0,0 @@
// 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/browser/api/atom_api_web_contents.h"
#include "atom/browser/atom_browser_client.h"
#include "atom/common/native_mate_converters/value_converter.h"
#include "atom/common/node_includes.h"
#include "content/public/browser/render_process_host.h"
#include "native_mate/dictionary.h"
#include "native_mate/object_template_builder.h"
namespace atom {
namespace api {
namespace {
bool IsWebContents(v8::Isolate* isolate, content::RenderProcessHost* process) {
content::WebContents* web_contents =
static_cast<AtomBrowserClient*>(AtomBrowserClient::Get())
->GetWebContentsFromProcessID(process->GetID());
if (!web_contents)
return false;
auto api_web_contents = WebContents::FromOrCreate(isolate, web_contents);
auto type = api_web_contents->GetType();
return type == WebContents::Type::BROWSER_WINDOW ||
type == WebContents::Type::WEB_VIEW;
}
} // 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::FunctionTemplate> prototype) {
prototype->SetClassName(
mate::StringToV8(isolate, "RenderProcessPreferences"));
mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
.SetMethod("addEntry", &RenderProcessPreferences::AddEntry)
.SetMethod("removeEntry", &RenderProcessPreferences::RemoveEntry);
}
// static
mate::Handle<RenderProcessPreferences>
RenderProcessPreferences::ForAllWebContents(v8::Isolate* isolate) {
return mate::CreateHandle(
isolate, new RenderProcessPreferences(
isolate, base::BindRepeating(&IsWebContents, isolate)));
}
} // 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("forAllWebContents",
&atom::api::RenderProcessPreferences::ForAllWebContents);
}
} // namespace
NODE_LINKED_MODULE_CONTEXT_AWARE(atom_browser_render_process_preferences,
Initialize)

Просмотреть файл

@ -1,44 +0,0 @@
// 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> ForAllWebContents(
v8::Isolate* isolate);
static void BuildPrototype(v8::Isolate* isolate,
v8::Local<v8::FunctionTemplate> 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_

Просмотреть файл

@ -1,60 +0,0 @@
// 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) {
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] =
base::DictionaryValue::From(base::Value::ToUniquePtrValue(entry.Clone()));
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(base::Value::ToUniquePtrValue(iter.second->Clone()));
cache_needs_update_ = false;
}
} // namespace atom

Просмотреть файл

@ -1,61 +0,0 @@
// 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);
~RenderProcessPreferences() override;
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_ = 0;
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_ = true;
base::ListValue cached_entries_;
DISALLOW_COPY_AND_ASSIGN(RenderProcessPreferences);
};
} // namespace atom
#endif // ATOM_BROWSER_RENDER_PROCESS_PREFERENCES_H_

Просмотреть файл

@ -5,7 +5,6 @@
// Multiply-included file, no traditional include guard. // Multiply-included file, no traditional include guard.
#include "base/strings/string16.h" #include "base/strings/string16.h"
#include "base/values.h"
#include "content/public/common/common_param_traits.h" #include "content/public/common/common_param_traits.h"
#include "ipc/ipc_message_macros.h" #include "ipc/ipc_message_macros.h"
#include "ui/gfx/geometry/rect_f.h" #include "ui/gfx/geometry/rect_f.h"
@ -22,6 +21,3 @@ IPC_MESSAGE_ROUTED0(AtomAutofillFrameHostMsg_HidePopup)
IPC_MESSAGE_ROUTED1(AtomAutofillFrameMsg_AcceptSuggestion, IPC_MESSAGE_ROUTED1(AtomAutofillFrameMsg_AcceptSuggestion,
base::string16 /* suggestion */) base::string16 /* suggestion */)
// Update renderer process preferences.
IPC_MESSAGE_CONTROL1(AtomMsg_UpdatePreferences, base::ListValue)

Просмотреть файл

@ -45,7 +45,6 @@
V(atom_browser_power_monitor) \ V(atom_browser_power_monitor) \
V(atom_browser_power_save_blocker) \ V(atom_browser_power_save_blocker) \
V(atom_browser_protocol) \ V(atom_browser_protocol) \
V(atom_browser_render_process_preferences) \
V(atom_browser_session) \ V(atom_browser_session) \
V(atom_browser_system_preferences) \ V(atom_browser_system_preferences) \
V(atom_browser_top_level_window) \ V(atom_browser_top_level_window) \

Просмотреть файл

@ -1,34 +0,0 @@
// 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) {
auto copy =
base::ListValue::From(base::Value::ToUniquePtrValue(preferences.Clone()));
preferences_.swap(copy);
}
} // namespace atom

Просмотреть файл

@ -1,35 +0,0 @@
// 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_thread_observer.h"
namespace atom {
class PreferencesManager : public content::RenderThreadObserver {
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_

Просмотреть файл

@ -15,7 +15,6 @@
#include "atom/renderer/atom_render_frame_observer.h" #include "atom/renderer/atom_render_frame_observer.h"
#include "atom/renderer/content_settings_observer.h" #include "atom/renderer/content_settings_observer.h"
#include "atom/renderer/electron_api_service_impl.h" #include "atom/renderer/electron_api_service_impl.h"
#include "atom/renderer/preferences_manager.h"
#include "base/command_line.h" #include "base/command_line.h"
#include "base/strings/string_split.h" #include "base/strings/string_split.h"
#include "base/strings/stringprintf.h" #include "base/strings/stringprintf.h"
@ -67,15 +66,6 @@ namespace atom {
namespace { namespace {
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);
}
std::vector<std::string> ParseSchemesCLISwitch(base::CommandLine* command_line, std::vector<std::string> ParseSchemesCLISwitch(base::CommandLine* command_line,
const char* switch_name) { const char* switch_name) {
std::string custom_schemes = command_line->GetSwitchValueASCII(switch_name); std::string custom_schemes = command_line->GetSwitchValueASCII(switch_name);
@ -134,9 +124,6 @@ void RendererClientBase::AddRenderBindings(
v8::Isolate* isolate, v8::Isolate* isolate,
v8::Local<v8::Object> binding_object) { v8::Local<v8::Object> binding_object) {
mate::Dictionary dict(isolate, binding_object); mate::Dictionary dict(isolate, binding_object);
dict.SetMethod("getRenderProcessPreferences",
base::BindRepeating(GetRenderProcessPreferences,
preferences_manager_.get()));
} }
void RendererClientBase::RenderThreadStarted() { void RendererClientBase::RenderThreadStarted() {
@ -200,8 +187,6 @@ void RendererClientBase::RenderThreadStarted() {
blink::WebSecurityPolicy::RegisterURLSchemeAsAllowingServiceWorkers("file"); blink::WebSecurityPolicy::RegisterURLSchemeAsAllowingServiceWorkers("file");
blink::SchemeRegistry::RegisterURLSchemeAsSupportingFetchAPI("file"); blink::SchemeRegistry::RegisterURLSchemeAsSupportingFetchAPI("file");
preferences_manager_.reset(new PreferencesManager);
#if defined(OS_WIN) #if defined(OS_WIN)
// Set ApplicationUserModelID in renderer process. // Set ApplicationUserModelID in renderer process.
base::string16 app_id = base::string16 app_id =

Просмотреть файл

@ -20,8 +20,6 @@
namespace atom { namespace atom {
class PreferencesManager;
class RendererClientBase : public content::ContentRendererClient { class RendererClientBase : public content::ContentRendererClient {
public: public:
RendererClientBase(); RendererClientBase();
@ -66,7 +64,6 @@ class RendererClientBase : public content::ContentRendererClient {
void DidSetUserAgent(const std::string& user_agent) override; void DidSetUserAgent(const std::string& user_agent) override;
private: private:
std::unique_ptr<PreferencesManager> preferences_manager_;
#if defined(WIDEVINE_CDM_AVAILABLE) #if defined(WIDEVINE_CDM_AVAILABLE)
ChromeKeySystemsProvider key_systems_provider_; ChromeKeySystemsProvider key_systems_provider_;
#endif #endif

Просмотреть файл

@ -79,8 +79,6 @@ filenames = {
"atom/browser/api/atom_api_protocol.h", "atom/browser/api/atom_api_protocol.h",
"atom/browser/api/atom_api_protocol_ns.cc", "atom/browser/api/atom_api_protocol_ns.cc",
"atom/browser/api/atom_api_protocol_ns.h", "atom/browser/api/atom_api_protocol_ns.h",
"atom/browser/api/atom_api_render_process_preferences.cc",
"atom/browser/api/atom_api_render_process_preferences.h",
"atom/browser/api/atom_api_screen.cc", "atom/browser/api/atom_api_screen.cc",
"atom/browser/api/atom_api_screen.h", "atom/browser/api/atom_api_screen.h",
"atom/browser/api/atom_api_session.cc", "atom/browser/api/atom_api_session.cc",
@ -312,8 +310,6 @@ filenames = {
"atom/browser/relauncher_win.cc", "atom/browser/relauncher_win.cc",
"atom/browser/relauncher.cc", "atom/browser/relauncher.cc",
"atom/browser/relauncher.h", "atom/browser/relauncher.h",
"atom/browser/render_process_preferences.cc",
"atom/browser/render_process_preferences.h",
"atom/browser/session_preferences.cc", "atom/browser/session_preferences.cc",
"atom/browser/session_preferences.h", "atom/browser/session_preferences.h",
"atom/browser/special_storage_policy.cc", "atom/browser/special_storage_policy.cc",
@ -585,8 +581,6 @@ filenames = {
"atom/renderer/atom_sandboxed_renderer_client.h", "atom/renderer/atom_sandboxed_renderer_client.h",
"atom/renderer/guest_view_container.cc", "atom/renderer/guest_view_container.cc",
"atom/renderer/guest_view_container.h", "atom/renderer/guest_view_container.h",
"atom/renderer/preferences_manager.cc",
"atom/renderer/preferences_manager.h",
"atom/renderer/renderer_client_base.cc", "atom/renderer/renderer_client_base.cc",
"atom/renderer/renderer_client_base.h", "atom/renderer/renderer_client_base.h",
"atom/renderer/web_worker_observer.cc", "atom/renderer/web_worker_observer.cc",

Просмотреть файл

@ -2,7 +2,6 @@
const { app, webContents, BrowserWindow } = require('electron') const { app, webContents, BrowserWindow } = require('electron')
const { getAllWebContents } = process.electronBinding('web_contents') const { getAllWebContents } = process.electronBinding('web_contents')
const renderProcessPreferences = process.electronBinding('render_process_preferences').forAllWebContents()
const ipcMainUtils = require('@electron/internal/browser/ipc-main-internal-utils') const ipcMainUtils = require('@electron/internal/browser/ipc-main-internal-utils')
const { Buffer } = require('buffer') const { Buffer } = require('buffer')
@ -313,6 +312,10 @@ ipcMainUtils.handle('CHROME_TABS_EXECUTE_SCRIPT', async function (event, tabId,
return ipcMainUtils.invokeInWebContents(contents, false, 'CHROME_TABS_EXECUTE_SCRIPT', extensionId, url, code) return ipcMainUtils.invokeInWebContents(contents, false, 'CHROME_TABS_EXECUTE_SCRIPT', extensionId, url, code)
}) })
ipcMainUtils.handle('CHROME_GET_CONTENT_SCRIPTS', async (event) => {
return Object.values(contentScripts)
})
// Transfer the content scripts to renderer. // Transfer the content scripts to renderer.
const contentScripts = {} const contentScripts = {}
@ -341,7 +344,7 @@ const injectContentScripts = function (manifest) {
extensionId: manifest.extensionId, extensionId: manifest.extensionId,
contentScripts: manifest.content_scripts.map(contentScriptToEntry) contentScripts: manifest.content_scripts.map(contentScriptToEntry)
} }
contentScripts[manifest.name] = renderProcessPreferences.addEntry(entry) contentScripts[manifest.name] = entry
} catch (e) { } catch (e) {
console.error('Failed to read content scripts', e) console.error('Failed to read content scripts', e)
} }
@ -350,7 +353,6 @@ const injectContentScripts = function (manifest) {
const removeContentScripts = function (manifest) { const removeContentScripts = function (manifest) {
if (!contentScripts[manifest.name]) return if (!contentScripts[manifest.name]) return
renderProcessPreferences.removeEntry(contentScripts[manifest.name])
delete contentScripts[manifest.name] delete contentScripts[manifest.name]
} }

Просмотреть файл

@ -108,15 +108,17 @@ ipcRendererUtils.handle('CHROME_TABS_EXECUTE_SCRIPT', function (
return runContentScript.call(window, extensionId, url, code) return runContentScript.call(window, extensionId, url, code)
}) })
module.exports = (getRenderProcessPreferences: typeof process.getRenderProcessPreferences) => { type ContentScriptEntry = {
// Read the renderer process preferences. extensionId: string;
const preferences = getRenderProcessPreferences() contentScripts: Electron.ContentScript[];
if (preferences) { }
for (const pref of preferences) {
if (pref.contentScripts) { module.exports = () => {
for (const script of pref.contentScripts) { const entries = ipcRendererUtils.invokeSync<ContentScriptEntry[]>('CHROME_GET_CONTENT_SCRIPTS')
injectContentScript(pref.extensionId, script) for (const entry of entries) {
} if (entry.contentScripts) {
for (const script of entry.contentScripts) {
injectContentScript(entry.extensionId, script)
} }
} }
} }

Просмотреть файл

@ -111,7 +111,7 @@ switch (window.location.protocol) {
windowSetup(guestInstanceId, openerId, isHiddenPage, usesNativeWindowOpen) windowSetup(guestInstanceId, openerId, isHiddenPage, usesNativeWindowOpen)
// Inject content scripts. // Inject content scripts.
require('@electron/internal/renderer/content-scripts-injector')(process.getRenderProcessPreferences) require('@electron/internal/renderer/content-scripts-injector')()
} }
} }

Просмотреть файл

@ -124,7 +124,7 @@ switch (window.location.protocol) {
} }
default: { default: {
// Inject content scripts. // Inject content scripts.
require('@electron/internal/renderer/content-scripts-injector')(binding.getRenderProcessPreferences) require('@electron/internal/renderer/content-scripts-injector')()
} }
} }

3
typings/internal-ambient.d.ts поставляемый
Просмотреть файл

@ -31,9 +31,6 @@ declare namespace NodeJS {
log: NodeJS.WriteStream['write']; log: NodeJS.WriteStream['write'];
activateUvLoop(): void; activateUvLoop(): void;
// Additional methods
getRenderProcessPreferences(): Array<Electron.RendererProcessPreference> | null;
// Additional events // Additional events
once(event: 'document-start', listener: () => any): this; once(event: 'document-start', listener: () => any): this;
once(event: 'document-end', listener: () => any): this; once(event: 'document-end', listener: () => any): this;