From 0ddd078aaffae231d2e97a5865e007cee268fccb Mon Sep 17 00:00:00 2001 From: Samuel Attard Date: Sun, 3 Sep 2017 02:15:46 +1000 Subject: [PATCH 01/12] Add ability to set global preload scripts --- atom/browser/api/atom_api_window.cc | 23 +++++++++++++++- atom/browser/api/atom_api_window.h | 4 +++ atom/browser/web_contents_preferences.cc | 9 ++++++ atom/common/options_switches.cc | 23 ++++++++-------- atom/common/options_switches.h | 1 + docs/api/browser-window.md | 19 +++++++++++++ lib/renderer/init.js | 12 ++++++++ spec/api-browser-window-spec.js | 35 ++++++++++++++++++++++++ spec/fixtures/module/set-global-2.js | 1 + spec/fixtures/module/set-global.js | 2 +- 10 files changed, 116 insertions(+), 13 deletions(-) create mode 100644 spec/fixtures/module/set-global-2.js diff --git a/atom/browser/api/atom_api_window.cc b/atom/browser/api/atom_api_window.cc index bb7060adb76d..372bf3d1e053 100644 --- a/atom/browser/api/atom_api_window.cc +++ b/atom/browser/api/atom_api_window.cc @@ -3,7 +3,8 @@ // found in the LICENSE file. #include "atom/browser/api/atom_api_window.h" -#include "atom/common/native_mate_converters/value_converter.h" + +#include #include "atom/browser/api/atom_api_browser_view.h" #include "atom/browser/api/atom_api_menu.h" @@ -17,6 +18,7 @@ #include "atom/common/native_mate_converters/gurl_converter.h" #include "atom/common/native_mate_converters/image_converter.h" #include "atom/common/native_mate_converters/string16_converter.h" +#include "atom/common/native_mate_converters/value_converter.h" #include "atom/common/options_switches.h" #include "base/command_line.h" #include "base/threading/thread_task_runner_handle.h" @@ -174,6 +176,19 @@ Window::~Window() { base::ThreadTaskRunnerHandle::Get()->DeleteSoon(FROM_HERE, window_.release()); } +std::vector g_preloads; +void Window::AddGlobalPreload(const base::FilePath::StringType preloadPath) { + g_preloads.push_back(preloadPath); +} +void Window::RemoveGlobalPreload(const base::FilePath::StringType preloadPath) { + g_preloads.erase( + std::remove(g_preloads.begin(), g_preloads.end(), preloadPath), + g_preloads.end()); +} +std::vector Window::GetGlobalPreloads() { + return g_preloads; +} + void Window::WillCloseWindow(bool* prevent_default) { *prevent_default = Emit("close"); } @@ -1152,6 +1167,12 @@ void Initialize(v8::Local exports, v8::Local unused, &mate::TrackableObject::FromWeakMapID); browser_window.SetMethod("getAllWindows", &mate::TrackableObject::GetAll); + browser_window.SetMethod("addGlobalPreload", + &Window::AddGlobalPreload); + browser_window.SetMethod("removeGlobalPreload", + &Window::RemoveGlobalPreload); + browser_window.SetMethod("getGlobalPreloads", + &Window::GetGlobalPreloads); mate::Dictionary dict(isolate, exports); dict.Set("BrowserWindow", browser_window); diff --git a/atom/browser/api/atom_api_window.h b/atom/browser/api/atom_api_window.h index 657688f128b0..3602fbd2f747 100644 --- a/atom/browser/api/atom_api_window.h +++ b/atom/browser/api/atom_api_window.h @@ -54,6 +54,10 @@ class Window : public mate::TrackableObject, int32_t ID() const; + static void AddGlobalPreload(const base::FilePath::StringType preloadPath); + static void RemoveGlobalPreload(const base::FilePath::StringType preloadPath); + static std::vector GetGlobalPreloads(); + protected: Window(v8::Isolate* isolate, v8::Local wrapper, const mate::Dictionary& options); diff --git a/atom/browser/web_contents_preferences.cc b/atom/browser/web_contents_preferences.cc index 81ce0c1e0646..262f164c29b5 100644 --- a/atom/browser/web_contents_preferences.cc +++ b/atom/browser/web_contents_preferences.cc @@ -8,6 +8,7 @@ #include #include +#include "atom/browser/api/atom_api_window.h" #include "atom/browser/native_window.h" #include "atom/browser/web_view_manager.h" #include "atom/common/native_mate_converters/value_converter.h" @@ -136,6 +137,14 @@ void WebContentsPreferences::AppendExtraCommandLineSwitches( LOG(ERROR) << "preload url must be file:// protocol."; } + for (auto preloadPath : atom::api::Window::GetGlobalPreloads()) { + if (base::FilePath(preloadPath).IsAbsolute()) + command_line->AppendSwitchNative(switches::kGlobalPreloadScript, + preloadPath); + else + LOG(ERROR) << "preload script must have absolute path."; + } + // Run Electron APIs and preload script in isolated world bool isolated; if (web_preferences.GetBoolean(options::kContextIsolation, &isolated) && diff --git a/atom/common/options_switches.cc b/atom/common/options_switches.cc index 78235426efea..33322788847b 100644 --- a/atom/common/options_switches.cc +++ b/atom/common/options_switches.cc @@ -177,17 +177,18 @@ const char kAppUserModelId[] = "app-user-model-id"; const char kAppPath[] = "app-path"; // The command line switch versions of the options. -const char kBackgroundColor[] = "background-color"; -const char kPreloadScript[] = "preload"; -const char kPreloadURL[] = "preload-url"; -const char kNodeIntegration[] = "node-integration"; -const char kContextIsolation[] = "context-isolation"; -const char kGuestInstanceID[] = "guest-instance-id"; -const char kOpenerID[] = "opener-id"; -const char kScrollBounce[] = "scroll-bounce"; -const char kHiddenPage[] = "hidden-page"; -const char kNativeWindowOpen[] = "native-window-open"; -const char kWebviewTag[] = "webview-tag"; +const char kBackgroundColor[] = "background-color"; +const char kPreloadScript[] = "preload"; +const char kPreloadURL[] = "preload-url"; +const char kGlobalPreloadScript[] = "global-preload"; +const char kNodeIntegration[] = "node-integration"; +const char kContextIsolation[] = "context-isolation"; +const char kGuestInstanceID[] = "guest-instance-id"; +const char kOpenerID[] = "opener-id"; +const char kScrollBounce[] = "scroll-bounce"; +const char kHiddenPage[] = "hidden-page"; +const char kNativeWindowOpen[] = "native-window-open"; +const char kWebviewTag[] = "webview-tag"; // Command switch passed to renderer process to control nodeIntegration. const char kNodeIntegrationInWorker[] = "node-integration-in-worker"; diff --git a/atom/common/options_switches.h b/atom/common/options_switches.h index 401feae48a09..550f19f191dc 100644 --- a/atom/common/options_switches.h +++ b/atom/common/options_switches.h @@ -91,6 +91,7 @@ extern const char kAppPath[]; extern const char kBackgroundColor[]; extern const char kPreloadScript[]; extern const char kPreloadURL[]; +extern const char kGlobalPreloadScript[]; extern const char kNodeIntegration[]; extern const char kContextIsolation[]; extern const char kGuestInstanceID[]; diff --git a/docs/api/browser-window.md b/docs/api/browser-window.md index ef90dc013307..bb97c50b61df 100644 --- a/docs/api/browser-window.md +++ b/docs/api/browser-window.md @@ -662,6 +662,25 @@ console.log(installed) **Note:** This API cannot be called before the `ready` event of the `app` module is emitted. +#### `BrowserWindow.addGlobalPreload(preloadPath)` + +* `preloadPath` String - An absolute path to the preload script + +Adds a script that will be executed on ALL new BrowserWindows just before normal `preload` scripts run. + +#### `BrowserWindow.removeGlobalPreload(preloadPath)` + +* `preloadPath` String - An absolute path to the preload script + +Removes the given script from the list of global preload scripts + +#### `BrowserWindow.getGlobalPreloads()` + +Returns `String[]` an array of paths to preload scripts that have been registered + +Adds a script that will be executed on ALL new BrowserWindows just before normal `preload` scripts run. + + ### Instance Properties Objects created with `new BrowserWindow` have the following properties: diff --git a/lib/renderer/init.js b/lib/renderer/init.js index 0d1a251c4da9..fa6eeb3af86c 100644 --- a/lib/renderer/init.js +++ b/lib/renderer/init.js @@ -67,6 +67,7 @@ electron.ipcRenderer.on('ELECTRON_INTERNAL_RENDERER_ASYNC_WEB_FRAME_METHOD', (ev let nodeIntegration = 'false' let webviewTag = 'false' let preloadScript = null +const globalPreloadScripts = [] let isBackgroundPage = false let appPath = null for (let arg of process.argv) { @@ -86,6 +87,8 @@ for (let arg of process.argv) { appPath = arg.substr(arg.indexOf('=') + 1) } else if (arg.indexOf('--webview-tag=') === 0) { webviewTag = arg.substr(arg.indexOf('=') + 1) + } else if (arg.indexOf('--global-preload') === 0) { + globalPreloadScripts.push(arg.substr(arg.indexOf('=') + 1)) } } @@ -171,6 +174,15 @@ if (nodeIntegration === 'true') { }) } +for (const globalPreloadScript of globalPreloadScripts) { + try { + require(globalPreloadScript) + } catch (error) { + console.error('Unable to load global preload script: ' + globalPreloadScript) + console.error(error.stack || error.message) + } +} + // Load the script specfied by the "preload" attribute. if (preloadScript) { try { diff --git a/spec/api-browser-window-spec.js b/spec/api-browser-window-spec.js index d04c340dbb90..1ffbbf01a679 100644 --- a/spec/api-browser-window-spec.js +++ b/spec/api-browser-window-spec.js @@ -1021,6 +1021,41 @@ describe('BrowserWindow module', () => { }) }) + describe('global preload scripts', function () { + it('can add and remove multiple global preload script', function () { + var preload = path.join(fixtures, 'module', 'set-global.js') + var preload2 = path.join(fixtures, 'module', 'set-global-2.js') + assert.deepEqual(BrowserWindow.getGlobalPreloads(), []) + BrowserWindow.addGlobalPreload(preload) + assert.deepEqual(BrowserWindow.getGlobalPreloads(), [preload]) + BrowserWindow.addGlobalPreload(preload2) + assert.deepEqual(BrowserWindow.getGlobalPreloads(), [preload, preload2]) + BrowserWindow.removeGlobalPreload(preload) + assert.deepEqual(BrowserWindow.getGlobalPreloads(), [preload2]) + BrowserWindow.removeGlobalPreload(preload2) + assert.deepEqual(BrowserWindow.getGlobalPreloads(), []) + }) + + it('loads the script before other scripts in window including normal preloads', function (done) { + var preload = path.join(fixtures, 'module', 'set-global.js') + var preload2 = path.join(fixtures, 'module', 'set-global-2.js') + ipcMain.once('answer', function (event, test) { + BrowserWindow.removeGlobalPreload(preload2) + assert.equal(test, 'preload2') + done() + }) + w.destroy() + BrowserWindow.addGlobalPreload(preload2) + w = new BrowserWindow({ + show: false, + webPreferences: { + preload: preload + } + }) + w.loadURL('file://' + path.join(fixtures, 'api', 'preload.html')) + }) + }) + describe('"node-integration" option', () => { it('disables node integration when specified to false', (done) => { const preload = path.join(fixtures, 'module', 'send-later.js') diff --git a/spec/fixtures/module/set-global-2.js b/spec/fixtures/module/set-global-2.js new file mode 100644 index 000000000000..9e2b61da2b9f --- /dev/null +++ b/spec/fixtures/module/set-global-2.js @@ -0,0 +1 @@ +if (!window.test) window.test = 'preload2' diff --git a/spec/fixtures/module/set-global.js b/spec/fixtures/module/set-global.js index ba4f30d155b7..5ad98817e0bd 100644 --- a/spec/fixtures/module/set-global.js +++ b/spec/fixtures/module/set-global.js @@ -1 +1 @@ -window.test = 'preload' +if (!window.test) window.test = 'preload' From 448ccc261de6f42886b48efa36ac48e44312e232 Mon Sep 17 00:00:00 2001 From: Samuel Attard Date: Tue, 5 Sep 2017 18:01:27 +1000 Subject: [PATCH 02/12] Use const references --- atom/browser/api/atom_api_window.cc | 4 ++-- atom/browser/api/atom_api_window.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/atom/browser/api/atom_api_window.cc b/atom/browser/api/atom_api_window.cc index 372bf3d1e053..041601057fae 100644 --- a/atom/browser/api/atom_api_window.cc +++ b/atom/browser/api/atom_api_window.cc @@ -177,10 +177,10 @@ Window::~Window() { } std::vector g_preloads; -void Window::AddGlobalPreload(const base::FilePath::StringType preloadPath) { +void Window::AddGlobalPreload(const base::FilePath::StringType& preloadPath) { g_preloads.push_back(preloadPath); } -void Window::RemoveGlobalPreload(const base::FilePath::StringType preloadPath) { +void Window::RemoveGlobalPreload(const base::FilePath::StringType& preloadPath) { g_preloads.erase( std::remove(g_preloads.begin(), g_preloads.end(), preloadPath), g_preloads.end()); diff --git a/atom/browser/api/atom_api_window.h b/atom/browser/api/atom_api_window.h index 3602fbd2f747..304339218887 100644 --- a/atom/browser/api/atom_api_window.h +++ b/atom/browser/api/atom_api_window.h @@ -54,8 +54,8 @@ class Window : public mate::TrackableObject, int32_t ID() const; - static void AddGlobalPreload(const base::FilePath::StringType preloadPath); - static void RemoveGlobalPreload(const base::FilePath::StringType preloadPath); + static void AddGlobalPreload(const base::FilePath::StringType& preloadPath); + static void RemoveGlobalPreload(const base::FilePath::StringType& preloadPath); static std::vector GetGlobalPreloads(); protected: From 3b80ee06552d24998cfceeb2a836e6e1308c00b8 Mon Sep 17 00:00:00 2001 From: Samuel Attard Date: Sun, 17 Sep 2017 01:05:49 +1000 Subject: [PATCH 03/12] Move global preload implementation to be session based --- atom/browser/api/atom_api_session.cc | 15 ++++++++++++ atom/browser/api/atom_api_session.h | 4 ++++ atom/browser/api/atom_api_web_contents.h | 2 +- atom/browser/api/atom_api_window.cc | 22 ----------------- atom/browser/api/atom_api_window.h | 4 ---- atom/browser/web_contents_preferences.cc | 6 ++++- docs/api/browser-window.md | 19 --------------- docs/api/session.md | 17 ++++++++++++++ spec/api-browser-window-spec.js | 30 +++++++++++++----------- 9 files changed, 58 insertions(+), 61 deletions(-) diff --git a/atom/browser/api/atom_api_session.cc b/atom/browser/api/atom_api_session.cc index 0a124c446623..ce60fb0aed33 100644 --- a/atom/browser/api/atom_api_session.cc +++ b/atom/browser/api/atom_api_session.cc @@ -680,6 +680,18 @@ void Session::CreateInterruptedDownload(const mate::Dictionary& options) { length, last_modified, etag, base::Time::FromDoubleT(start_time))); } +void Session::AddPreload(const base::FilePath::StringType& preloadPath) { + g_preloads.push_back(preloadPath); +} +void Session::RemovePreload(const base::FilePath::StringType& preloadPath) { + g_preloads.erase( + std::remove(g_preloads.begin(), g_preloads.end(), preloadPath), + g_preloads.end()); +} +std::vector Session::GetPreloads() { + return g_preloads; +} + v8::Local Session::Cookies(v8::Isolate* isolate) { if (cookies_.IsEmpty()) { auto handle = Cookies::Create(isolate, browser_context()); @@ -766,6 +778,9 @@ void Session::BuildPrototype(v8::Isolate* isolate, .SetMethod("getBlobData", &Session::GetBlobData) .SetMethod("createInterruptedDownload", &Session::CreateInterruptedDownload) + .SetMethod("addPreload", &Session::AddPreload) + .SetMethod("removePreload", &Session::RemovePreload) + .SetMethod("getPreloads", &Session::GetPreloads) .SetProperty("cookies", &Session::Cookies) .SetProperty("protocol", &Session::Protocol) .SetProperty("webRequest", &Session::WebRequest); diff --git a/atom/browser/api/atom_api_session.h b/atom/browser/api/atom_api_session.h index 72f186e4fee4..00ad00002f75 100644 --- a/atom/browser/api/atom_api_session.h +++ b/atom/browser/api/atom_api_session.h @@ -81,6 +81,9 @@ class Session: public mate::TrackableObject, void GetBlobData(const std::string& uuid, const AtomBlobReader::CompletionCallback& callback); void CreateInterruptedDownload(const mate::Dictionary& options); + void AddPreload(const base::FilePath::StringType& preloadPath); + void RemovePreload(const base::FilePath::StringType& preloadPath); + std::vector GetPreloads(); v8::Local Cookies(v8::Isolate* isolate); v8::Local Protocol(v8::Isolate* isolate); v8::Local WebRequest(v8::Isolate* isolate); @@ -103,6 +106,7 @@ class Session: public mate::TrackableObject, std::string devtools_network_emulation_client_id_; scoped_refptr browser_context_; + std::vector g_preloads; DISALLOW_COPY_AND_ASSIGN(Session); }; diff --git a/atom/browser/api/atom_api_web_contents.h b/atom/browser/api/atom_api_web_contents.h index 16f23210557c..71436b3ad600 100644 --- a/atom/browser/api/atom_api_web_contents.h +++ b/atom/browser/api/atom_api_web_contents.h @@ -230,6 +230,7 @@ class WebContents : public mate::TrackableObject, v8::Local Debugger(v8::Isolate* isolate); WebContentsZoomController* GetZoomController() { return zoom_controller_; } + AtomBrowserContext* GetBrowserContext() const; protected: WebContents(v8::Isolate* isolate, @@ -367,7 +368,6 @@ class WebContents : public mate::TrackableObject, const std::vector& labels); private: - AtomBrowserContext* GetBrowserContext() const; uint32_t GetNextRequestId() { return ++request_id_; diff --git a/atom/browser/api/atom_api_window.cc b/atom/browser/api/atom_api_window.cc index 041601057fae..ea7e6c473c1f 100644 --- a/atom/browser/api/atom_api_window.cc +++ b/atom/browser/api/atom_api_window.cc @@ -4,8 +4,6 @@ #include "atom/browser/api/atom_api_window.h" -#include - #include "atom/browser/api/atom_api_browser_view.h" #include "atom/browser/api/atom_api_menu.h" #include "atom/browser/api/atom_api_web_contents.h" @@ -18,7 +16,6 @@ #include "atom/common/native_mate_converters/gurl_converter.h" #include "atom/common/native_mate_converters/image_converter.h" #include "atom/common/native_mate_converters/string16_converter.h" -#include "atom/common/native_mate_converters/value_converter.h" #include "atom/common/options_switches.h" #include "base/command_line.h" #include "base/threading/thread_task_runner_handle.h" @@ -176,19 +173,6 @@ Window::~Window() { base::ThreadTaskRunnerHandle::Get()->DeleteSoon(FROM_HERE, window_.release()); } -std::vector g_preloads; -void Window::AddGlobalPreload(const base::FilePath::StringType& preloadPath) { - g_preloads.push_back(preloadPath); -} -void Window::RemoveGlobalPreload(const base::FilePath::StringType& preloadPath) { - g_preloads.erase( - std::remove(g_preloads.begin(), g_preloads.end(), preloadPath), - g_preloads.end()); -} -std::vector Window::GetGlobalPreloads() { - return g_preloads; -} - void Window::WillCloseWindow(bool* prevent_default) { *prevent_default = Emit("close"); } @@ -1167,12 +1151,6 @@ void Initialize(v8::Local exports, v8::Local unused, &mate::TrackableObject::FromWeakMapID); browser_window.SetMethod("getAllWindows", &mate::TrackableObject::GetAll); - browser_window.SetMethod("addGlobalPreload", - &Window::AddGlobalPreload); - browser_window.SetMethod("removeGlobalPreload", - &Window::RemoveGlobalPreload); - browser_window.SetMethod("getGlobalPreloads", - &Window::GetGlobalPreloads); mate::Dictionary dict(isolate, exports); dict.Set("BrowserWindow", browser_window); diff --git a/atom/browser/api/atom_api_window.h b/atom/browser/api/atom_api_window.h index 304339218887..657688f128b0 100644 --- a/atom/browser/api/atom_api_window.h +++ b/atom/browser/api/atom_api_window.h @@ -54,10 +54,6 @@ class Window : public mate::TrackableObject, int32_t ID() const; - static void AddGlobalPreload(const base::FilePath::StringType& preloadPath); - static void RemoveGlobalPreload(const base::FilePath::StringType& preloadPath); - static std::vector GetGlobalPreloads(); - protected: Window(v8::Isolate* isolate, v8::Local wrapper, const mate::Dictionary& options); diff --git a/atom/browser/web_contents_preferences.cc b/atom/browser/web_contents_preferences.cc index 262f164c29b5..1f19eb0e778c 100644 --- a/atom/browser/web_contents_preferences.cc +++ b/atom/browser/web_contents_preferences.cc @@ -8,6 +8,8 @@ #include #include +#include "atom/browser/api/atom_api_session.h" +#include "atom/browser/api/atom_api_web_contents.h" #include "atom/browser/api/atom_api_window.h" #include "atom/browser/native_window.h" #include "atom/browser/web_view_manager.h" @@ -137,7 +139,9 @@ void WebContentsPreferences::AppendExtraCommandLineSwitches( LOG(ERROR) << "preload url must be file:// protocol."; } - for (auto preloadPath : atom::api::Window::GetGlobalPreloads()) { + v8::Isolate* isolate = v8::Isolate::GetCurrent(); + mate::Handle api_web_contents = atom::api::WebContents::CreateFrom(isolate, web_contents); + for (auto preloadPath : atom::api::Session::CreateFrom(isolate, api_web_contents.get()->GetBrowserContext())->GetPreloads()) { if (base::FilePath(preloadPath).IsAbsolute()) command_line->AppendSwitchNative(switches::kGlobalPreloadScript, preloadPath); diff --git a/docs/api/browser-window.md b/docs/api/browser-window.md index bb97c50b61df..ef90dc013307 100644 --- a/docs/api/browser-window.md +++ b/docs/api/browser-window.md @@ -662,25 +662,6 @@ console.log(installed) **Note:** This API cannot be called before the `ready` event of the `app` module is emitted. -#### `BrowserWindow.addGlobalPreload(preloadPath)` - -* `preloadPath` String - An absolute path to the preload script - -Adds a script that will be executed on ALL new BrowserWindows just before normal `preload` scripts run. - -#### `BrowserWindow.removeGlobalPreload(preloadPath)` - -* `preloadPath` String - An absolute path to the preload script - -Removes the given script from the list of global preload scripts - -#### `BrowserWindow.getGlobalPreloads()` - -Returns `String[]` an array of paths to preload scripts that have been registered - -Adds a script that will be executed on ALL new BrowserWindows just before normal `preload` scripts run. - - ### Instance Properties Objects created with `new BrowserWindow` have the following properties: diff --git a/docs/api/session.md b/docs/api/session.md index f75b6399f10b..54ca97fe662e 100644 --- a/docs/api/session.md +++ b/docs/api/session.md @@ -384,6 +384,23 @@ the initial state will be `interrupted`. The download will start only when the Clears the session’s HTTP authentication cache. +#### `ses.addPreload(preloadPath)` + +* `preloadPath` String - An absolute path to the preload script + +Adds a script that will be executed on ALL web contents that are associated with +this session just before normal `preload` scripts run. + +#### `ses.removePreload(preloadPath)` + +* `preloadPath` String - An absolute path to the preload script + +Removes the given script from the list of preload scripts + +#### `ses.getPreloads()` + +Returns `String[]` an array of paths to preload scripts that have been registered + ### Instance Properties The following properties are available on instances of `Session`: diff --git a/spec/api-browser-window-spec.js b/spec/api-browser-window-spec.js index 1ffbbf01a679..2a37de50f8d2 100644 --- a/spec/api-browser-window-spec.js +++ b/spec/api-browser-window-spec.js @@ -9,7 +9,7 @@ const http = require('http') const {closeWindow} = require('./window-helpers') const {ipcRenderer, remote, screen} = require('electron') -const {app, ipcMain, BrowserWindow, BrowserView, protocol, webContents} = remote +const {app, ipcMain, BrowserWindow, BrowserView, protocol, session, webContents} = remote const isCI = remote.getGlobal('isCi') const nativeModulesEnabled = remote.getGlobal('nativeModulesEnabled') @@ -1021,31 +1021,33 @@ describe('BrowserWindow module', () => { }) }) - describe('global preload scripts', function () { - it('can add and remove multiple global preload script', function () { + describe.only('session preload scripts', function () { + it('can add and remove multiple session preload script', function () { var preload = path.join(fixtures, 'module', 'set-global.js') var preload2 = path.join(fixtures, 'module', 'set-global-2.js') - assert.deepEqual(BrowserWindow.getGlobalPreloads(), []) - BrowserWindow.addGlobalPreload(preload) - assert.deepEqual(BrowserWindow.getGlobalPreloads(), [preload]) - BrowserWindow.addGlobalPreload(preload2) - assert.deepEqual(BrowserWindow.getGlobalPreloads(), [preload, preload2]) - BrowserWindow.removeGlobalPreload(preload) - assert.deepEqual(BrowserWindow.getGlobalPreloads(), [preload2]) - BrowserWindow.removeGlobalPreload(preload2) - assert.deepEqual(BrowserWindow.getGlobalPreloads(), []) + const mSession = session.defaultSession; + assert.deepEqual(mSession.getPreloads(), []) + mSession.addPreload(preload) + assert.deepEqual(mSession.getPreloads(), [preload]) + mSession.addPreload(preload2) + assert.deepEqual(mSession.getPreloads(), [preload, preload2]) + mSession.removePreload(preload) + assert.deepEqual(mSession.getPreloads(), [preload2]) + mSession.removePreload(preload2) + assert.deepEqual(mSession.getPreloads(), []) }) it('loads the script before other scripts in window including normal preloads', function (done) { var preload = path.join(fixtures, 'module', 'set-global.js') var preload2 = path.join(fixtures, 'module', 'set-global-2.js') + const mSession = session.defaultSession; ipcMain.once('answer', function (event, test) { - BrowserWindow.removeGlobalPreload(preload2) + mSession.removePreload(preload2) assert.equal(test, 'preload2') done() }) w.destroy() - BrowserWindow.addGlobalPreload(preload2) + mSession.addPreload(preload2) w = new BrowserWindow({ show: false, webPreferences: { From d2707315e6fbd1c201b198af12e36e2ed53497db Mon Sep 17 00:00:00 2001 From: Samuel Attard Date: Sun, 17 Sep 2017 01:08:44 +1000 Subject: [PATCH 04/12] s/global/session --- lib/renderer/init.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/renderer/init.js b/lib/renderer/init.js index fa6eeb3af86c..62df35223141 100644 --- a/lib/renderer/init.js +++ b/lib/renderer/init.js @@ -67,7 +67,7 @@ electron.ipcRenderer.on('ELECTRON_INTERNAL_RENDERER_ASYNC_WEB_FRAME_METHOD', (ev let nodeIntegration = 'false' let webviewTag = 'false' let preloadScript = null -const globalPreloadScripts = [] +const sessionPreloadScripts = [] let isBackgroundPage = false let appPath = null for (let arg of process.argv) { @@ -88,7 +88,7 @@ for (let arg of process.argv) { } else if (arg.indexOf('--webview-tag=') === 0) { webviewTag = arg.substr(arg.indexOf('=') + 1) } else if (arg.indexOf('--global-preload') === 0) { - globalPreloadScripts.push(arg.substr(arg.indexOf('=') + 1)) + sessionPreloadScripts.push(arg.substr(arg.indexOf('=') + 1)) } } @@ -174,11 +174,11 @@ if (nodeIntegration === 'true') { }) } -for (const globalPreloadScript of globalPreloadScripts) { +for (const sessionPreloadScript of sessionPreloadScripts) { try { - require(globalPreloadScript) + require(sessionPreloadScript) } catch (error) { - console.error('Unable to load global preload script: ' + globalPreloadScript) + console.error('Unable to load session preload script: ' + sessionPreloadScript) console.error(error.stack || error.message) } } From d9359d8b6c6ac8d2d114349500e74840fac3122b Mon Sep 17 00:00:00 2001 From: Samuel Attard Date: Sun, 17 Sep 2017 01:10:01 +1000 Subject: [PATCH 05/12] s/global/session in constants --- atom/browser/web_contents_preferences.cc | 2 +- atom/common/options_switches.cc | 24 ++++++++++++------------ atom/common/options_switches.h | 2 +- lib/renderer/init.js | 2 +- 4 files changed, 15 insertions(+), 15 deletions(-) diff --git a/atom/browser/web_contents_preferences.cc b/atom/browser/web_contents_preferences.cc index 1f19eb0e778c..9b59b6e14485 100644 --- a/atom/browser/web_contents_preferences.cc +++ b/atom/browser/web_contents_preferences.cc @@ -143,7 +143,7 @@ void WebContentsPreferences::AppendExtraCommandLineSwitches( mate::Handle api_web_contents = atom::api::WebContents::CreateFrom(isolate, web_contents); for (auto preloadPath : atom::api::Session::CreateFrom(isolate, api_web_contents.get()->GetBrowserContext())->GetPreloads()) { if (base::FilePath(preloadPath).IsAbsolute()) - command_line->AppendSwitchNative(switches::kGlobalPreloadScript, + command_line->AppendSwitchNative(switches::kSessionPreloadScript, preloadPath); else LOG(ERROR) << "preload script must have absolute path."; diff --git a/atom/common/options_switches.cc b/atom/common/options_switches.cc index 33322788847b..3daf7419b09e 100644 --- a/atom/common/options_switches.cc +++ b/atom/common/options_switches.cc @@ -177,18 +177,18 @@ const char kAppUserModelId[] = "app-user-model-id"; const char kAppPath[] = "app-path"; // The command line switch versions of the options. -const char kBackgroundColor[] = "background-color"; -const char kPreloadScript[] = "preload"; -const char kPreloadURL[] = "preload-url"; -const char kGlobalPreloadScript[] = "global-preload"; -const char kNodeIntegration[] = "node-integration"; -const char kContextIsolation[] = "context-isolation"; -const char kGuestInstanceID[] = "guest-instance-id"; -const char kOpenerID[] = "opener-id"; -const char kScrollBounce[] = "scroll-bounce"; -const char kHiddenPage[] = "hidden-page"; -const char kNativeWindowOpen[] = "native-window-open"; -const char kWebviewTag[] = "webview-tag"; +const char kBackgroundColor[] = "background-color"; +const char kPreloadScript[] = "preload"; +const char kPreloadURL[] = "preload-url"; +const char kSessionPreloadScript[] = "session-preload"; +const char kNodeIntegration[] = "node-integration"; +const char kContextIsolation[] = "context-isolation"; +const char kGuestInstanceID[] = "guest-instance-id"; +const char kOpenerID[] = "opener-id"; +const char kScrollBounce[] = "scroll-bounce"; +const char kHiddenPage[] = "hidden-page"; +const char kNativeWindowOpen[] = "native-window-open"; +const char kWebviewTag[] = "webview-tag"; // Command switch passed to renderer process to control nodeIntegration. const char kNodeIntegrationInWorker[] = "node-integration-in-worker"; diff --git a/atom/common/options_switches.h b/atom/common/options_switches.h index 550f19f191dc..ee5c1fcf58e5 100644 --- a/atom/common/options_switches.h +++ b/atom/common/options_switches.h @@ -91,7 +91,7 @@ extern const char kAppPath[]; extern const char kBackgroundColor[]; extern const char kPreloadScript[]; extern const char kPreloadURL[]; -extern const char kGlobalPreloadScript[]; +extern const char kSessionPreloadScript[]; extern const char kNodeIntegration[]; extern const char kContextIsolation[]; extern const char kGuestInstanceID[]; diff --git a/lib/renderer/init.js b/lib/renderer/init.js index 62df35223141..5ddf1d38d06e 100644 --- a/lib/renderer/init.js +++ b/lib/renderer/init.js @@ -87,7 +87,7 @@ for (let arg of process.argv) { appPath = arg.substr(arg.indexOf('=') + 1) } else if (arg.indexOf('--webview-tag=') === 0) { webviewTag = arg.substr(arg.indexOf('=') + 1) - } else if (arg.indexOf('--global-preload') === 0) { + } else if (arg.indexOf('--session-preload') === 0) { sessionPreloadScripts.push(arg.substr(arg.indexOf('=') + 1)) } } From d1aded283100d23f722b3a8c68dd8cff3484783c Mon Sep 17 00:00:00 2001 From: Samuel Attard Date: Sun, 17 Sep 2017 01:13:55 +1000 Subject: [PATCH 06/12] Appease the almighty linter --- atom/browser/api/atom_api_session.h | 1 + atom/browser/api/atom_api_web_contents.h | 1 - atom/browser/web_contents_preferences.cc | 7 +++++-- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/atom/browser/api/atom_api_session.h b/atom/browser/api/atom_api_session.h index 00ad00002f75..5d05fbe7390f 100644 --- a/atom/browser/api/atom_api_session.h +++ b/atom/browser/api/atom_api_session.h @@ -6,6 +6,7 @@ #define ATOM_BROWSER_API_ATOM_API_SESSION_H_ #include +#include #include "atom/browser/api/trackable_object.h" #include "atom/browser/atom_blob_reader.h" diff --git a/atom/browser/api/atom_api_web_contents.h b/atom/browser/api/atom_api_web_contents.h index 71436b3ad600..f7425f640119 100644 --- a/atom/browser/api/atom_api_web_contents.h +++ b/atom/browser/api/atom_api_web_contents.h @@ -368,7 +368,6 @@ class WebContents : public mate::TrackableObject, const std::vector& labels); private: - uint32_t GetNextRequestId() { return ++request_id_; } diff --git a/atom/browser/web_contents_preferences.cc b/atom/browser/web_contents_preferences.cc index 9b59b6e14485..9f4a47895061 100644 --- a/atom/browser/web_contents_preferences.cc +++ b/atom/browser/web_contents_preferences.cc @@ -140,8 +140,11 @@ void WebContentsPreferences::AppendExtraCommandLineSwitches( } v8::Isolate* isolate = v8::Isolate::GetCurrent(); - mate::Handle api_web_contents = atom::api::WebContents::CreateFrom(isolate, web_contents); - for (auto preloadPath : atom::api::Session::CreateFrom(isolate, api_web_contents.get()->GetBrowserContext())->GetPreloads()) { + mate::Handle api_web_contents = + atom::api::WebContents::CreateFrom(isolate, web_contents); + auto session = atom::api::Session::CreateFrom( + isolate, api_web_contents.get()->GetBrowserContext()); + for (auto preloadPath : session->GetPreloads()) { if (base::FilePath(preloadPath).IsAbsolute()) command_line->AppendSwitchNative(switches::kSessionPreloadScript, preloadPath); From e535ba48084b95d2fcd8215f177df986030b70fe Mon Sep 17 00:00:00 2001 From: Samuel Attard Date: Sun, 17 Sep 2017 01:18:05 +1000 Subject: [PATCH 07/12] Don't know why we suddenly need this, but hey :/ --- atom/browser/api/atom_api_window.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/atom/browser/api/atom_api_window.cc b/atom/browser/api/atom_api_window.cc index ea7e6c473c1f..7b7b1d87b918 100644 --- a/atom/browser/api/atom_api_window.cc +++ b/atom/browser/api/atom_api_window.cc @@ -16,6 +16,7 @@ #include "atom/common/native_mate_converters/gurl_converter.h" #include "atom/common/native_mate_converters/image_converter.h" #include "atom/common/native_mate_converters/string16_converter.h" +#include "atom/common/native_mate_converters/value_converter.h" #include "atom/common/options_switches.h" #include "base/command_line.h" #include "base/threading/thread_task_runner_handle.h" From 009459bd38e7164faad5908fe33651983cb23b90 Mon Sep 17 00:00:00 2001 From: Samuel Attard Date: Sun, 17 Sep 2017 01:59:39 +1000 Subject: [PATCH 08/12] Standard JS --- spec/api-browser-window-spec.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spec/api-browser-window-spec.js b/spec/api-browser-window-spec.js index 2a37de50f8d2..a77c8ed23b87 100644 --- a/spec/api-browser-window-spec.js +++ b/spec/api-browser-window-spec.js @@ -1025,7 +1025,7 @@ describe('BrowserWindow module', () => { it('can add and remove multiple session preload script', function () { var preload = path.join(fixtures, 'module', 'set-global.js') var preload2 = path.join(fixtures, 'module', 'set-global-2.js') - const mSession = session.defaultSession; + const mSession = session.defaultSession assert.deepEqual(mSession.getPreloads(), []) mSession.addPreload(preload) assert.deepEqual(mSession.getPreloads(), [preload]) @@ -1040,7 +1040,7 @@ describe('BrowserWindow module', () => { it('loads the script before other scripts in window including normal preloads', function (done) { var preload = path.join(fixtures, 'module', 'set-global.js') var preload2 = path.join(fixtures, 'module', 'set-global-2.js') - const mSession = session.defaultSession; + const mSession = session.defaultSession ipcMain.once('answer', function (event, test) { mSession.removePreload(preload2) assert.equal(test, 'preload2') From eaa4b71c24d657fb16f068c6e3b596b8f813952b Mon Sep 17 00:00:00 2001 From: Samuel Attard Date: Sun, 17 Sep 2017 03:34:35 +1000 Subject: [PATCH 09/12] Remove .only --- spec/api-browser-window-spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/api-browser-window-spec.js b/spec/api-browser-window-spec.js index a77c8ed23b87..ab085c205b1a 100644 --- a/spec/api-browser-window-spec.js +++ b/spec/api-browser-window-spec.js @@ -1021,7 +1021,7 @@ describe('BrowserWindow module', () => { }) }) - describe.only('session preload scripts', function () { + describe('session preload scripts', function () { it('can add and remove multiple session preload script', function () { var preload = path.join(fixtures, 'module', 'set-global.js') var preload2 = path.join(fixtures, 'module', 'set-global-2.js') From 776e8afa2bb97f6cfe803c3f563c26a64ba350b9 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 5 Dec 2017 11:50:06 +0900 Subject: [PATCH 10/12] Coding style changes --- atom/browser/api/atom_api_session.cc | 14 ++++++++------ atom/browser/api/atom_api_session.h | 4 ++-- atom/browser/web_contents_preferences.cc | 6 +++--- 3 files changed, 13 insertions(+), 11 deletions(-) diff --git a/atom/browser/api/atom_api_session.cc b/atom/browser/api/atom_api_session.cc index ce60fb0aed33..5bae8a179e19 100644 --- a/atom/browser/api/atom_api_session.cc +++ b/atom/browser/api/atom_api_session.cc @@ -681,15 +681,17 @@ void Session::CreateInterruptedDownload(const mate::Dictionary& options) { } void Session::AddPreload(const base::FilePath::StringType& preloadPath) { - g_preloads.push_back(preloadPath); + preloads_.push_back(preloadPath); } + void Session::RemovePreload(const base::FilePath::StringType& preloadPath) { - g_preloads.erase( - std::remove(g_preloads.begin(), g_preloads.end(), preloadPath), - g_preloads.end()); + preloads_.erase( + std::remove(preloads_.begin(), preloads_.end(), preloadPath), + preloads_.end()); } -std::vector Session::GetPreloads() { - return g_preloads; + +std::vector Session::GetPreloads() const { + return preloads_; } v8::Local Session::Cookies(v8::Isolate* isolate) { diff --git a/atom/browser/api/atom_api_session.h b/atom/browser/api/atom_api_session.h index 5d05fbe7390f..bd52a05cf875 100644 --- a/atom/browser/api/atom_api_session.h +++ b/atom/browser/api/atom_api_session.h @@ -84,7 +84,7 @@ class Session: public mate::TrackableObject, void CreateInterruptedDownload(const mate::Dictionary& options); void AddPreload(const base::FilePath::StringType& preloadPath); void RemovePreload(const base::FilePath::StringType& preloadPath); - std::vector GetPreloads(); + std::vector GetPreloads() const; v8::Local Cookies(v8::Isolate* isolate); v8::Local Protocol(v8::Isolate* isolate); v8::Local WebRequest(v8::Isolate* isolate); @@ -107,7 +107,7 @@ class Session: public mate::TrackableObject, std::string devtools_network_emulation_client_id_; scoped_refptr browser_context_; - std::vector g_preloads; + std::vector preloads_; DISALLOW_COPY_AND_ASSIGN(Session); }; diff --git a/atom/browser/web_contents_preferences.cc b/atom/browser/web_contents_preferences.cc index 9f4a47895061..1a369dd0e9a0 100644 --- a/atom/browser/web_contents_preferences.cc +++ b/atom/browser/web_contents_preferences.cc @@ -141,10 +141,10 @@ void WebContentsPreferences::AppendExtraCommandLineSwitches( v8::Isolate* isolate = v8::Isolate::GetCurrent(); mate::Handle api_web_contents = - atom::api::WebContents::CreateFrom(isolate, web_contents); + atom::api::WebContents::CreateFrom(isolate, web_contents); auto session = atom::api::Session::CreateFrom( - isolate, api_web_contents.get()->GetBrowserContext()); - for (auto preloadPath : session->GetPreloads()) { + isolate, api_web_contents.get()->GetBrowserContext()); + for (const auto& preloadPath : session->GetPreloads()) { if (base::FilePath(preloadPath).IsAbsolute()) command_line->AppendSwitchNative(switches::kSessionPreloadScript, preloadPath); From cb3a9c69ab395fdc8af98890819104ff612264d4 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 5 Dec 2017 15:59:15 +0900 Subject: [PATCH 11/12] Add a SessionPreferences to manage session related data By design the BrowserClient should not be aware of the api:: classes. --- atom/browser/api/atom_api_session.cc | 23 ++++---- atom/browser/api/atom_api_session.h | 4 +- atom/browser/atom_browser_client.cc | 6 +- atom/browser/session_preferences.cc | 61 ++++++++++++++++++++ atom/browser/session_preferences.h | 46 +++++++++++++++ atom/browser/web_contents_preferences.cc | 16 ----- atom/browser/web_contents_preferences.h | 6 +- atom/common/options_switches.cc | 24 ++++---- atom/common/options_switches.h | 2 +- docs/api/session.md | 15 ++--- filenames.gypi | 2 + lib/renderer/init.js | 24 ++++---- spec/api-browser-window-spec.js | 44 +++++++------- spec/fixtures/api/preloads.html | 7 +++ spec/fixtures/module/set-global-2.js | 1 - spec/fixtures/module/set-global-preload-1.js | 1 + spec/fixtures/module/set-global-preload-2.js | 1 + spec/fixtures/module/set-global-preload-3.js | 1 + 18 files changed, 190 insertions(+), 94 deletions(-) create mode 100644 atom/browser/session_preferences.cc create mode 100644 atom/browser/session_preferences.h create mode 100644 spec/fixtures/api/preloads.html delete mode 100644 spec/fixtures/module/set-global-2.js create mode 100644 spec/fixtures/module/set-global-preload-1.js create mode 100644 spec/fixtures/module/set-global-preload-2.js create mode 100644 spec/fixtures/module/set-global-preload-3.js diff --git a/atom/browser/api/atom_api_session.cc b/atom/browser/api/atom_api_session.cc index 5bae8a179e19..39da83789102 100644 --- a/atom/browser/api/atom_api_session.cc +++ b/atom/browser/api/atom_api_session.cc @@ -17,6 +17,7 @@ #include "atom/browser/atom_permission_manager.h" #include "atom/browser/browser.h" #include "atom/browser/net/atom_cert_verifier.h" +#include "atom/browser/session_preferences.h" #include "atom/common/native_mate_converters/callback.h" #include "atom/common/native_mate_converters/content_converter.h" #include "atom/common/native_mate_converters/file_path_converter.h" @@ -447,6 +448,8 @@ Session::Session(v8::Isolate* isolate, AtomBrowserContext* browser_context) content::BrowserContext::GetDownloadManager(browser_context)-> AddObserver(this); + new SessionPreferences(browser_context); + Init(isolate); AttachAsUserData(browser_context); } @@ -680,18 +683,17 @@ void Session::CreateInterruptedDownload(const mate::Dictionary& options) { length, last_modified, etag, base::Time::FromDoubleT(start_time))); } -void Session::AddPreload(const base::FilePath::StringType& preloadPath) { - preloads_.push_back(preloadPath); -} - -void Session::RemovePreload(const base::FilePath::StringType& preloadPath) { - preloads_.erase( - std::remove(preloads_.begin(), preloads_.end(), preloadPath), - preloads_.end()); +void Session::SetPreloads( + const std::vector& preloads) { + auto* prefs = SessionPreferences::FromBrowserContext(browser_context()); + DCHECK(prefs); + prefs->set_preloads(preloads); } std::vector Session::GetPreloads() const { - return preloads_; + auto* prefs = SessionPreferences::FromBrowserContext(browser_context()); + DCHECK(prefs); + return prefs->preloads(); } v8::Local Session::Cookies(v8::Isolate* isolate) { @@ -780,8 +782,7 @@ void Session::BuildPrototype(v8::Isolate* isolate, .SetMethod("getBlobData", &Session::GetBlobData) .SetMethod("createInterruptedDownload", &Session::CreateInterruptedDownload) - .SetMethod("addPreload", &Session::AddPreload) - .SetMethod("removePreload", &Session::RemovePreload) + .SetMethod("setPreloads", &Session::SetPreloads) .SetMethod("getPreloads", &Session::GetPreloads) .SetProperty("cookies", &Session::Cookies) .SetProperty("protocol", &Session::Protocol) diff --git a/atom/browser/api/atom_api_session.h b/atom/browser/api/atom_api_session.h index bd52a05cf875..d56c2400d4df 100644 --- a/atom/browser/api/atom_api_session.h +++ b/atom/browser/api/atom_api_session.h @@ -82,8 +82,7 @@ class Session: public mate::TrackableObject, void GetBlobData(const std::string& uuid, const AtomBlobReader::CompletionCallback& callback); void CreateInterruptedDownload(const mate::Dictionary& options); - void AddPreload(const base::FilePath::StringType& preloadPath); - void RemovePreload(const base::FilePath::StringType& preloadPath); + void SetPreloads(const std::vector& preloads); std::vector GetPreloads() const; v8::Local Cookies(v8::Isolate* isolate); v8::Local Protocol(v8::Isolate* isolate); @@ -107,7 +106,6 @@ class Session: public mate::TrackableObject, std::string devtools_network_emulation_client_id_; scoped_refptr browser_context_; - std::vector preloads_; DISALLOW_COPY_AND_ASSIGN(Session); }; diff --git a/atom/browser/atom_browser_client.cc b/atom/browser/atom_browser_client.cc index 49ca11bfa58e..24500c4c3075 100644 --- a/atom/browser/atom_browser_client.cc +++ b/atom/browser/atom_browser_client.cc @@ -17,6 +17,7 @@ #include "atom/browser/atom_speech_recognition_manager_delegate.h" #include "atom/browser/child_web_contents_tracker.h" #include "atom/browser/native_window.h" +#include "atom/browser/session_preferences.h" #include "atom/browser/web_contents_permission_helper.h" #include "atom/browser/web_contents_preferences.h" #include "atom/browser/window_list.h" @@ -277,9 +278,12 @@ void AtomBrowserClient::AppendExtraCommandLineSwitches( } content::WebContents* web_contents = GetWebContentsFromProcessID(process_id); - if (web_contents) + if (web_contents) { WebContentsPreferences::AppendExtraCommandLineSwitches( web_contents, command_line); + SessionPreferences::AppendExtraCommandLineSwitches( + web_contents->GetBrowserContext(), command_line); + } } void AtomBrowserClient::DidCreatePpapiPlugin( diff --git a/atom/browser/session_preferences.cc b/atom/browser/session_preferences.cc new file mode 100644 index 000000000000..0731036d66f2 --- /dev/null +++ b/atom/browser/session_preferences.cc @@ -0,0 +1,61 @@ +// Copyright (c) 2017 GitHub, Inc. +// Use of this source code is governed by the MIT license that can be +// found in the LICENSE file. + +#include "atom/browser/session_preferences.h" + +#include "atom/common/options_switches.h" +#include "base/command_line.h" +#include "base/memory/ptr_util.h" + +namespace atom { + +namespace { + +#if defined(OS_WIN) +const base::FilePath::CharType kPathDelimiter = FILE_PATH_LITERAL(';'); +#else +const base::FilePath::CharType kPathDelimiter = FILE_PATH_LITERAL(':'); +#endif + +} // namespace + +// static +int SessionPreferences::kLocatorKey = 0; + +SessionPreferences::SessionPreferences(content::BrowserContext* context) { + context->SetUserData(&kLocatorKey, base::WrapUnique(this)); +} + +SessionPreferences::~SessionPreferences() { +} + +// static +SessionPreferences* SessionPreferences::FromBrowserContext( + content::BrowserContext* context) { + return static_cast(context->GetUserData(&kLocatorKey)); +} + +// static +void SessionPreferences::AppendExtraCommandLineSwitches( + content::BrowserContext* context, base::CommandLine* command_line) { + SessionPreferences* self = FromBrowserContext(context); + if (!self) + return; + + base::FilePath::StringType preloads; + for (const auto& preload : self->preloads()) { + if (!base::FilePath(preload).IsAbsolute()) { + LOG(ERROR) << "preload script must have absolute path: " << preload; + continue; + } + if (preloads.empty()) + preloads = preload; + else + preloads += kPathDelimiter + preload; + } + if (!preloads.empty()) + command_line->AppendSwitchNative(switches::kPreloadScripts, preloads); +} + +} // namespace atom diff --git a/atom/browser/session_preferences.h b/atom/browser/session_preferences.h new file mode 100644 index 000000000000..ab0ba470bbf0 --- /dev/null +++ b/atom/browser/session_preferences.h @@ -0,0 +1,46 @@ +// Copyright (c) 2017 GitHub, Inc. +// Use of this source code is governed by the MIT license that can be +// found in the LICENSE file. + +#ifndef ATOM_BROWSER_SESSION_PREFERENCES_H_ +#define ATOM_BROWSER_SESSION_PREFERENCES_H_ + +#include + +#include "base/files/file_path.h" +#include "base/supports_user_data.h" +#include "content/public/browser/browser_context.h" + +namespace base { +class CommandLine; +} + +namespace atom { + +class SessionPreferences : public base::SupportsUserData::Data { + public: + static SessionPreferences* FromBrowserContext( + content::BrowserContext* context); + static void AppendExtraCommandLineSwitches( + content::BrowserContext* context, base::CommandLine* command_line); + + explicit SessionPreferences(content::BrowserContext* context); + ~SessionPreferences() override; + + void set_preloads(const std::vector& preloads) { + preloads_ = preloads; + } + const std::vector& preloads() const { + return preloads_; + } + + private: + // The user data key. + static int kLocatorKey; + + std::vector preloads_; +}; + +} // namespace atom + +#endif // ATOM_BROWSER_SESSION_PREFERENCES_H_ diff --git a/atom/browser/web_contents_preferences.cc b/atom/browser/web_contents_preferences.cc index 1a369dd0e9a0..81ce0c1e0646 100644 --- a/atom/browser/web_contents_preferences.cc +++ b/atom/browser/web_contents_preferences.cc @@ -8,9 +8,6 @@ #include #include -#include "atom/browser/api/atom_api_session.h" -#include "atom/browser/api/atom_api_web_contents.h" -#include "atom/browser/api/atom_api_window.h" #include "atom/browser/native_window.h" #include "atom/browser/web_view_manager.h" #include "atom/common/native_mate_converters/value_converter.h" @@ -139,19 +136,6 @@ void WebContentsPreferences::AppendExtraCommandLineSwitches( LOG(ERROR) << "preload url must be file:// protocol."; } - v8::Isolate* isolate = v8::Isolate::GetCurrent(); - mate::Handle api_web_contents = - atom::api::WebContents::CreateFrom(isolate, web_contents); - auto session = atom::api::Session::CreateFrom( - isolate, api_web_contents.get()->GetBrowserContext()); - for (const auto& preloadPath : session->GetPreloads()) { - if (base::FilePath(preloadPath).IsAbsolute()) - command_line->AppendSwitchNative(switches::kSessionPreloadScript, - preloadPath); - else - LOG(ERROR) << "preload script must have absolute path."; - } - // Run Electron APIs and preload script in isolated world bool isolated; if (web_preferences.GetBoolean(options::kContextIsolation, &isolated) && diff --git a/atom/browser/web_contents_preferences.h b/atom/browser/web_contents_preferences.h index 366aa1d95208..00f582b00617 100644 --- a/atom/browser/web_contents_preferences.h +++ b/atom/browser/web_contents_preferences.h @@ -61,14 +61,14 @@ class WebContentsPreferences private: friend class content::WebContentsUserData; + // Get preferences value as integer possibly coercing it from a string + bool GetInteger(const std::string& attributeName, int* intValue); + static std::vector instances_; content::WebContents* web_contents_; base::DictionaryValue web_preferences_; - // Get preferences value as integer possibly coercing it from a string - bool GetInteger(const std::string& attributeName, int* intValue); - DISALLOW_COPY_AND_ASSIGN(WebContentsPreferences); }; diff --git a/atom/common/options_switches.cc b/atom/common/options_switches.cc index 3daf7419b09e..0bfbae8c5c4b 100644 --- a/atom/common/options_switches.cc +++ b/atom/common/options_switches.cc @@ -177,18 +177,18 @@ const char kAppUserModelId[] = "app-user-model-id"; const char kAppPath[] = "app-path"; // The command line switch versions of the options. -const char kBackgroundColor[] = "background-color"; -const char kPreloadScript[] = "preload"; -const char kPreloadURL[] = "preload-url"; -const char kSessionPreloadScript[] = "session-preload"; -const char kNodeIntegration[] = "node-integration"; -const char kContextIsolation[] = "context-isolation"; -const char kGuestInstanceID[] = "guest-instance-id"; -const char kOpenerID[] = "opener-id"; -const char kScrollBounce[] = "scroll-bounce"; -const char kHiddenPage[] = "hidden-page"; -const char kNativeWindowOpen[] = "native-window-open"; -const char kWebviewTag[] = "webview-tag"; +const char kBackgroundColor[] = "background-color"; +const char kPreloadScript[] = "preload"; +const char kPreloadURL[] = "preload-url"; +const char kPreloadScripts[] = "preload-scripts"; +const char kNodeIntegration[] = "node-integration"; +const char kContextIsolation[] = "context-isolation"; +const char kGuestInstanceID[] = "guest-instance-id"; +const char kOpenerID[] = "opener-id"; +const char kScrollBounce[] = "scroll-bounce"; +const char kHiddenPage[] = "hidden-page"; +const char kNativeWindowOpen[] = "native-window-open"; +const char kWebviewTag[] = "webview-tag"; // Command switch passed to renderer process to control nodeIntegration. const char kNodeIntegrationInWorker[] = "node-integration-in-worker"; diff --git a/atom/common/options_switches.h b/atom/common/options_switches.h index ee5c1fcf58e5..7576fc9f61dc 100644 --- a/atom/common/options_switches.h +++ b/atom/common/options_switches.h @@ -91,7 +91,7 @@ extern const char kAppPath[]; extern const char kBackgroundColor[]; extern const char kPreloadScript[]; extern const char kPreloadURL[]; -extern const char kSessionPreloadScript[]; +extern const char kPreloadScripts[]; extern const char kNodeIntegration[]; extern const char kContextIsolation[]; extern const char kGuestInstanceID[]; diff --git a/docs/api/session.md b/docs/api/session.md index 54ca97fe662e..aa975fddd54f 100644 --- a/docs/api/session.md +++ b/docs/api/session.md @@ -384,22 +384,17 @@ the initial state will be `interrupted`. The download will start only when the Clears the session’s HTTP authentication cache. -#### `ses.addPreload(preloadPath)` +#### `ses.setPreloads(preloads)` -* `preloadPath` String - An absolute path to the preload script +* `preloads` String[] - An array of absolute path to preload scripts -Adds a script that will be executed on ALL web contents that are associated with +Adds scripts that will be executed on ALL web contents that are associated with this session just before normal `preload` scripts run. -#### `ses.removePreload(preloadPath)` - -* `preloadPath` String - An absolute path to the preload script - -Removes the given script from the list of preload scripts - #### `ses.getPreloads()` -Returns `String[]` an array of paths to preload scripts that have been registered +Returns `String[]` an array of paths to preload scripts that have been +registered. ### Instance Properties diff --git a/filenames.gypi b/filenames.gypi index 2559aeb61255..b2ab8a36103f 100644 --- a/filenames.gypi +++ b/filenames.gypi @@ -283,6 +283,8 @@ '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.h', 'atom/browser/ui/accelerator_util.cc', 'atom/browser/ui/accelerator_util.h', 'atom/browser/ui/accelerator_util_mac.mm', diff --git a/lib/renderer/init.js b/lib/renderer/init.js index 5ddf1d38d06e..1b0766d3007d 100644 --- a/lib/renderer/init.js +++ b/lib/renderer/init.js @@ -67,7 +67,7 @@ electron.ipcRenderer.on('ELECTRON_INTERNAL_RENDERER_ASYNC_WEB_FRAME_METHOD', (ev let nodeIntegration = 'false' let webviewTag = 'false' let preloadScript = null -const sessionPreloadScripts = [] +let preloadScripts = [] let isBackgroundPage = false let appPath = null for (let arg of process.argv) { @@ -87,11 +87,16 @@ for (let arg of process.argv) { appPath = arg.substr(arg.indexOf('=') + 1) } else if (arg.indexOf('--webview-tag=') === 0) { webviewTag = arg.substr(arg.indexOf('=') + 1) - } else if (arg.indexOf('--session-preload') === 0) { - sessionPreloadScripts.push(arg.substr(arg.indexOf('=') + 1)) + } else if (arg.indexOf('--preload-scripts') === 0) { + preloadScripts = arg.substr(arg.indexOf('=') + 1).split(path.delimiter) } } +// The webContents preload script is loaded after the session preload scripts. +if (preloadScript) { + preloadScripts.push(preloadScript) +} + if (window.location.protocol === 'chrome-devtools:') { // Override some inspector APIs. require('./inspector') @@ -174,17 +179,8 @@ if (nodeIntegration === 'true') { }) } -for (const sessionPreloadScript of sessionPreloadScripts) { - try { - require(sessionPreloadScript) - } catch (error) { - console.error('Unable to load session preload script: ' + sessionPreloadScript) - console.error(error.stack || error.message) - } -} - -// Load the script specfied by the "preload" attribute. -if (preloadScript) { +// Load the preload scripts. +for (const preloadScript of preloadScripts) { try { require(preloadScript) } catch (error) { diff --git a/spec/api-browser-window-spec.js b/spec/api-browser-window-spec.js index ab085c205b1a..195e94f39b78 100644 --- a/spec/api-browser-window-spec.js +++ b/spec/api-browser-window-spec.js @@ -1022,39 +1022,39 @@ describe('BrowserWindow module', () => { }) describe('session preload scripts', function () { - it('can add and remove multiple session preload script', function () { - var preload = path.join(fixtures, 'module', 'set-global.js') - var preload2 = path.join(fixtures, 'module', 'set-global-2.js') - const mSession = session.defaultSession - assert.deepEqual(mSession.getPreloads(), []) - mSession.addPreload(preload) - assert.deepEqual(mSession.getPreloads(), [preload]) - mSession.addPreload(preload2) - assert.deepEqual(mSession.getPreloads(), [preload, preload2]) - mSession.removePreload(preload) - assert.deepEqual(mSession.getPreloads(), [preload2]) - mSession.removePreload(preload2) - assert.deepEqual(mSession.getPreloads(), []) + const preloads = [ + path.join(fixtures, 'module', 'set-global-preload-1.js'), + path.join(fixtures, 'module', 'set-global-preload-2.js') + ] + const defaultSession = session.defaultSession + + beforeEach(() => { + assert.deepEqual(defaultSession.getPreloads(), []) + defaultSession.setPreloads(preloads) + }) + afterEach(() => { + defaultSession.setPreloads([]) + }) + + it('can set multiple session preload script', function () { + assert.deepEqual(defaultSession.getPreloads(), preloads) }) it('loads the script before other scripts in window including normal preloads', function (done) { - var preload = path.join(fixtures, 'module', 'set-global.js') - var preload2 = path.join(fixtures, 'module', 'set-global-2.js') - const mSession = session.defaultSession - ipcMain.once('answer', function (event, test) { - mSession.removePreload(preload2) - assert.equal(test, 'preload2') + ipcMain.once('vars', function (event, preload1, preload2, preload3) { + assert.equal(preload1, 'preload-1') + assert.equal(preload2, 'preload-1-2') + assert.equal(preload3, 'preload-1-2-3') done() }) w.destroy() - mSession.addPreload(preload2) w = new BrowserWindow({ show: false, webPreferences: { - preload: preload + preload: path.join(fixtures, 'module', 'set-global-preload-3.js') } }) - w.loadURL('file://' + path.join(fixtures, 'api', 'preload.html')) + w.loadURL('file://' + path.join(fixtures, 'api', 'preloads.html')) }) }) diff --git a/spec/fixtures/api/preloads.html b/spec/fixtures/api/preloads.html new file mode 100644 index 000000000000..f13510b1b212 --- /dev/null +++ b/spec/fixtures/api/preloads.html @@ -0,0 +1,7 @@ + + + + + diff --git a/spec/fixtures/module/set-global-2.js b/spec/fixtures/module/set-global-2.js deleted file mode 100644 index 9e2b61da2b9f..000000000000 --- a/spec/fixtures/module/set-global-2.js +++ /dev/null @@ -1 +0,0 @@ -if (!window.test) window.test = 'preload2' diff --git a/spec/fixtures/module/set-global-preload-1.js b/spec/fixtures/module/set-global-preload-1.js new file mode 100644 index 000000000000..22dfdf918506 --- /dev/null +++ b/spec/fixtures/module/set-global-preload-1.js @@ -0,0 +1 @@ +window.preload1 = 'preload-1' diff --git a/spec/fixtures/module/set-global-preload-2.js b/spec/fixtures/module/set-global-preload-2.js new file mode 100644 index 000000000000..7542009f7b09 --- /dev/null +++ b/spec/fixtures/module/set-global-preload-2.js @@ -0,0 +1 @@ +window.preload2 = window.preload1 + '-2' diff --git a/spec/fixtures/module/set-global-preload-3.js b/spec/fixtures/module/set-global-preload-3.js new file mode 100644 index 000000000000..9cfef949277e --- /dev/null +++ b/spec/fixtures/module/set-global-preload-3.js @@ -0,0 +1 @@ +window.preload3 = window.preload2 + '-3' From 24b3ee3a4a3519ac3b37122d2d20f8aefe1c0e01 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 5 Dec 2017 16:50:25 +0900 Subject: [PATCH 12/12] Revert some unnecessary changes --- atom/browser/api/atom_api_web_contents.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/atom/browser/api/atom_api_web_contents.h b/atom/browser/api/atom_api_web_contents.h index f7425f640119..16f23210557c 100644 --- a/atom/browser/api/atom_api_web_contents.h +++ b/atom/browser/api/atom_api_web_contents.h @@ -230,7 +230,6 @@ class WebContents : public mate::TrackableObject, v8::Local Debugger(v8::Isolate* isolate); WebContentsZoomController* GetZoomController() { return zoom_controller_; } - AtomBrowserContext* GetBrowserContext() const; protected: WebContents(v8::Isolate* isolate, @@ -368,6 +367,8 @@ class WebContents : public mate::TrackableObject, const std::vector& labels); private: + AtomBrowserContext* GetBrowserContext() const; + uint32_t GetNextRequestId() { return ++request_id_; }