Skip to content

Commit

Permalink
Merge pull request electron#10430 from electron/global-preloads
Browse files Browse the repository at this point in the history
Add ability to set per-session preload scripts
  • Loading branch information
zcbenz authored Dec 5, 2017
2 parents d598aa1 + 24b3ee3 commit 95cb601
Show file tree
Hide file tree
Showing 18 changed files with 212 additions and 9 deletions.
18 changes: 18 additions & 0 deletions atom/browser/api/atom_api_session.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -680,6 +683,19 @@ void Session::CreateInterruptedDownload(const mate::Dictionary& options) {
length, last_modified, etag, base::Time::FromDoubleT(start_time)));
}

void Session::SetPreloads(
const std::vector<base::FilePath::StringType>& preloads) {
auto* prefs = SessionPreferences::FromBrowserContext(browser_context());
DCHECK(prefs);
prefs->set_preloads(preloads);
}

std::vector<base::FilePath::StringType> Session::GetPreloads() const {
auto* prefs = SessionPreferences::FromBrowserContext(browser_context());
DCHECK(prefs);
return prefs->preloads();
}

v8::Local<v8::Value> Session::Cookies(v8::Isolate* isolate) {
if (cookies_.IsEmpty()) {
auto handle = Cookies::Create(isolate, browser_context());
Expand Down Expand Up @@ -766,6 +782,8 @@ void Session::BuildPrototype(v8::Isolate* isolate,
.SetMethod("getBlobData", &Session::GetBlobData)
.SetMethod("createInterruptedDownload",
&Session::CreateInterruptedDownload)
.SetMethod("setPreloads", &Session::SetPreloads)
.SetMethod("getPreloads", &Session::GetPreloads)
.SetProperty("cookies", &Session::Cookies)
.SetProperty("protocol", &Session::Protocol)
.SetProperty("webRequest", &Session::WebRequest);
Expand Down
3 changes: 3 additions & 0 deletions atom/browser/api/atom_api_session.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#define ATOM_BROWSER_API_ATOM_API_SESSION_H_

#include <string>
#include <vector>

#include "atom/browser/api/trackable_object.h"
#include "atom/browser/atom_blob_reader.h"
Expand Down Expand Up @@ -81,6 +82,8 @@ class Session: public mate::TrackableObject<Session>,
void GetBlobData(const std::string& uuid,
const AtomBlobReader::CompletionCallback& callback);
void CreateInterruptedDownload(const mate::Dictionary& options);
void SetPreloads(const std::vector<base::FilePath::StringType>& preloads);
std::vector<base::FilePath::StringType> GetPreloads() const;
v8::Local<v8::Value> Cookies(v8::Isolate* isolate);
v8::Local<v8::Value> Protocol(v8::Isolate* isolate);
v8::Local<v8::Value> WebRequest(v8::Isolate* isolate);
Expand Down
2 changes: 1 addition & 1 deletion atom/browser/api/atom_api_window.cc
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
// found in the LICENSE file.

#include "atom/browser/api/atom_api_window.h"
#include "atom/common/native_mate_converters/value_converter.h"

#include "atom/browser/api/atom_api_browser_view.h"
#include "atom/browser/api/atom_api_menu.h"
Expand All @@ -17,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"
Expand Down
6 changes: 5 additions & 1 deletion atom/browser/atom_browser_client.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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(
Expand Down
61 changes: 61 additions & 0 deletions atom/browser/session_preferences.cc
Original file line number Diff line number Diff line change
@@ -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<SessionPreferences*>(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
46 changes: 46 additions & 0 deletions atom/browser/session_preferences.h
Original file line number Diff line number Diff line change
@@ -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 <vector>

#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<base::FilePath::StringType>& preloads) {
preloads_ = preloads;
}
const std::vector<base::FilePath::StringType>& preloads() const {
return preloads_;
}

private:
// The user data key.
static int kLocatorKey;

std::vector<base::FilePath::StringType> preloads_;
};

} // namespace atom

#endif // ATOM_BROWSER_SESSION_PREFERENCES_H_
6 changes: 3 additions & 3 deletions atom/browser/web_contents_preferences.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,14 +61,14 @@ class WebContentsPreferences
private:
friend class content::WebContentsUserData<WebContentsPreferences>;

// Get preferences value as integer possibly coercing it from a string
bool GetInteger(const std::string& attributeName, int* intValue);

static std::vector<WebContentsPreferences*> 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);
};

Expand Down
1 change: 1 addition & 0 deletions atom/common/options_switches.cc
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,7 @@ const char kAppPath[] = "app-path";
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";
Expand Down
1 change: 1 addition & 0 deletions atom/common/options_switches.h
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ extern const char kAppPath[];
extern const char kBackgroundColor[];
extern const char kPreloadScript[];
extern const char kPreloadURL[];
extern const char kPreloadScripts[];
extern const char kNodeIntegration[];
extern const char kContextIsolation[];
extern const char kGuestInstanceID[];
Expand Down
12 changes: 12 additions & 0 deletions docs/api/session.md
Original file line number Diff line number Diff line change
Expand Up @@ -384,6 +384,18 @@ the initial state will be `interrupted`. The download will start only when the

Clears the session’s HTTP authentication cache.

#### `ses.setPreloads(preloads)`

* `preloads` String[] - An array of absolute path to preload scripts

Adds scripts that will be executed on ALL web contents that are associated with
this session just before normal `preload` scripts run.

#### `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`:
Expand Down
2 changes: 2 additions & 0 deletions filenames.gypi
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down
12 changes: 10 additions & 2 deletions lib/renderer/init.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ electron.ipcRenderer.on('ELECTRON_INTERNAL_RENDERER_ASYNC_WEB_FRAME_METHOD', (ev
let nodeIntegration = 'false'
let webviewTag = 'false'
let preloadScript = null
let preloadScripts = []
let isBackgroundPage = false
let appPath = null
for (let arg of process.argv) {
Expand All @@ -86,9 +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('--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')
Expand Down Expand Up @@ -171,8 +179,8 @@ if (nodeIntegration === 'true') {
})
}

// Load the script specfied by the "preload" attribute.
if (preloadScript) {
// Load the preload scripts.
for (const preloadScript of preloadScripts) {
try {
require(preloadScript)
} catch (error) {
Expand Down
39 changes: 38 additions & 1 deletion spec/api-browser-window-spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -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')
Expand Down Expand Up @@ -1021,6 +1021,43 @@ describe('BrowserWindow module', () => {
})
})

describe('session preload scripts', function () {
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) {
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()
w = new BrowserWindow({
show: false,
webPreferences: {
preload: path.join(fixtures, 'module', 'set-global-preload-3.js')
}
})
w.loadURL('file://' + path.join(fixtures, 'api', 'preloads.html'))
})
})

describe('"node-integration" option', () => {
it('disables node integration when specified to false', (done) => {
const preload = path.join(fixtures, 'module', 'send-later.js')
Expand Down
7 changes: 7 additions & 0 deletions spec/fixtures/api/preloads.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<html>
<body>
<script type="text/javascript" charset="utf-8">
require('electron').ipcRenderer.send('vars', preload1, preload2, preload3);
</script>
</body>
</html>
1 change: 1 addition & 0 deletions spec/fixtures/module/set-global-preload-1.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
window.preload1 = 'preload-1'
1 change: 1 addition & 0 deletions spec/fixtures/module/set-global-preload-2.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
window.preload2 = window.preload1 + '-2'
1 change: 1 addition & 0 deletions spec/fixtures/module/set-global-preload-3.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
window.preload3 = window.preload2 + '-3'
2 changes: 1 addition & 1 deletion spec/fixtures/module/set-global.js
Original file line number Diff line number Diff line change
@@ -1 +1 @@
window.test = 'preload'
if (!window.test) window.test = 'preload'

0 comments on commit 95cb601

Please sign in to comment.