Compare commits

...

51 Commits

Author SHA1 Message Date
Kevin Sawicki
93c4f90bee Bump v1.3.13 2016-12-06 14:12:51 -08:00
Kevin Sawicki
35be33a02f Merge pull request #8142 from electron/1-3-backports
Backports to 1.3
2016-12-06 14:12:25 -08:00
Kevin Sawicki
746ea3e045 Use getId in render-view-deleted fixture 2016-12-06 13:27:59 -08:00
Kevin Sawicki
1bd9fc1a09 Remove unused CallbacksRegistry.call method 2016-12-06 12:59:22 -08:00
Kevin Sawicki
ac54984763 Use 1.3 getId implementation to track render view deletesp 2016-12-06 12:57:42 -08:00
Kevin Sawicki
c300104cbd Upgrade libcc for Chrome 56 Linux key event fix 2016-12-06 09:59:00 -08:00
Kevin Sawicki
fc299189eb Update expected error message for missing remote object 2016-12-05 12:57:32 -08:00
Kevin Sawicki
5a768b3dfe Expose getProcessId from 1.4 for render-view-deleted fix 2016-12-05 10:23:12 -08:00
Kevin Sawicki
ab634e6c20 Use spread syntax instead of function apply 2016-12-05 10:03:13 -08:00
Kevin Sawicki
f5a6f290bc 🎨 Assign binding as const 2016-12-05 09:56:14 -08:00
Kevin Sawicki
3fe9762082 Implement window.alert/confirm/close in main process 2016-12-05 09:55:10 -08:00
Kevin Sawicki
cac7e9460d Pass args array instead of arguments object 2016-12-05 09:51:54 -08:00
Kevin Sawicki
d29bed026c Co-locate with other private methods 2016-12-05 09:51:35 -08:00
Kevin Sawicki
02dcc1bf3f Add spec for render-view-deleted issue 2016-12-05 09:49:15 -08:00
Kevin Sawicki
7a9a2c003c Don't clear until render view is deleted for process id 2016-12-05 09:48:11 -08:00
Kevin Sawicki
ab21a8b03a Log build type 2016-12-05 09:47:51 -08:00
Kevin Sawicki
0a587bc611 Add initial arm specific cibuild script 2016-12-05 09:47:41 -08:00
Kevin Sawicki
0037af51f3 Bump v1.3.12 2016-11-28 10:50:25 -08:00
Kevin Sawicki
435162af17 Remove unintended returns 2016-11-28 10:49:26 -08:00
Kevin Sawicki
64077277b1 Access URL through webContents directly 2016-11-28 10:48:52 -08:00
Kevin Sawicki
acb95f4614 Add more origin comparison specs 2016-11-28 10:48:41 -08:00
Kevin Sawicki
082b47fb85 window.opener location should be webview src URL 2016-11-28 10:48:31 -08:00
Kevin Sawicki
650867772a Bump v1.3.11 2016-11-23 13:20:57 -08:00
Kevin Sawicki
13d2fc9c81 Always use guest contents for canAccessWindow check 2016-11-23 11:45:05 -08:00
Kevin Sawicki
04a846a106 Add failing specs window.opener from <webview> opened window 2016-11-23 11:44:58 -08:00
Kevin Sawicki
cb84d26d20 Bump v1.3.10 2016-11-22 09:33:38 -08:00
Kevin Sawicki
78cf807cf0 Add initial spec for zoom level limits 2016-11-22 09:19:55 -08:00
Kevin Sawicki
f3de3334cf Add setZoomLevelLimits to planned breaking changes 2016-11-22 09:19:39 -08:00
Kevin Sawicki
a9d5a1d771 Add 2.0 comment about setZoomLevelLimits 2016-11-22 09:18:59 -08:00
Kevin Sawicki
2356577614 Expose setVisualZoomLevelLimits on webContents and <web-view> 2016-11-22 09:18:54 -08:00
Kevin Sawicki
94a5132b07 Document webFrame.setVisualZoomLevelLimits as public 2016-11-22 09:18:50 -08:00
Kevin Sawicki
dca200d918 Export a setVisualZoomLevelLimits method 2016-11-22 09:18:45 -08:00
Paul Betts
e86e7d699f 📝 2016-11-22 09:18:16 -08:00
Paul Betts
922fcfb3da Lint 2016-11-22 09:18:11 -08:00
Paul Betts
1d35151353 Add new method to set layout-based zoom level limit 2016-11-22 09:18:07 -08:00
Kevin Sawicki
cb9fdc45e6 Bump v1.3.9 2016-11-16 11:29:03 -08:00
Kevin Sawicki
2dafd845b9 Make scheme const 2016-11-16 11:29:03 -08:00
Kevin Sawicki
9017f90b57 Use sender.id instead of sender.webContents.id 2016-11-16 11:29:03 -08:00
Kevin Sawicki
b94638894e Don't log blocked messages when guestWindow is null 2016-11-16 11:29:03 -08:00
Kevin Sawicki
8a3288d791 Always call done callback in before block 2016-11-16 11:29:03 -08:00
Cheng Zhao
6f5336c63f Fix standard linting errors 2016-11-16 11:29:03 -08:00
Cheng Zhao
73c1fab423 Print error messages 2016-11-16 11:29:03 -08:00
Cheng Zhao
1e36ee918e Do permission check when calling guest window methods 2016-11-16 11:29:03 -08:00
Cheng Zhao
1f49da7a06 spec: Should check origin before accessing window.opener 2016-11-16 11:28:52 -08:00
Kevin Sawicki
037a458e1d Bump v1.3.8 2016-10-20 11:34:18 +09:00
Jacob Groundwater
03a274ee27 Fire a11y event on touch screens using screen readers 2016-10-18 13:52:05 +09:00
Paul Betts
c4bd516b77 Code Cleanup 2016-10-18 13:51:55 +09:00
Paul Betts
4c914c1277 Check harder before enabling Accessibility support 2016-10-18 13:51:34 +09:00
Cheng Zhao
e3688a8e9d Bump v1.3.7 2016-09-27 03:19:21 +00:00
Cheng Zhao
375534cf4a module search paths have changed 2016-09-27 03:00:08 +00:00
Cheng Zhao
397e5ad0ac Update to Node v6.5.0 2016-09-27 02:45:19 +00:00
44 changed files with 552 additions and 142 deletions

View File

@@ -138,7 +138,7 @@ NativeWindowViews::NativeWindowViews(
menu_bar_visible_(false),
menu_bar_alt_pressed_(false),
#if defined(OS_WIN)
enabled_a11y_support_(false),
checked_for_a11y_support_(false),
thick_frame_(true),
#endif
keyboard_event_handler_(new views::UnhandledKeyboardEventHandler),

View File

@@ -18,6 +18,8 @@
#include "atom/browser/ui/win/message_handler_delegate.h"
#include "atom/browser/ui/win/taskbar_host.h"
#include "base/win/scoped_gdi_object.h"
#include "ui/base/win/accessibility_misc_utils.h"
#include <UIAutomationCoreApi.h>
#endif
namespace views {
@@ -228,8 +230,8 @@ class NativeWindowViews : public NativeWindow,
// In charge of running taskbar related APIs.
TaskbarHost taskbar_host_;
// If true we have enabled a11y
bool enabled_a11y_support_;
// Memoized version of a11y check
bool checked_for_a11y_support_;
// Whether to show the WS_THICKFRAME style.
bool thick_frame_;

View File

@@ -72,6 +72,12 @@ const char* AppCommandToString(int command_id) {
}
}
bool IsScreenReaderActive() {
UINT screenReader = 0;
SystemParametersInfo(SPI_GETSCREENREADER, 0, &screenReader, 0);
return screenReader && UiaClientsAreListening();
}
} // namespace
bool NativeWindowViews::ExecuteWindowsCommand(int command_id) {
@@ -91,16 +97,24 @@ bool NativeWindowViews::PreHandleMSG(
// because we still want Chromium to handle returning the actual
// accessibility object.
case WM_GETOBJECT: {
const DWORD obj_id = static_cast<DWORD>(l_param);
if (enabled_a11y_support_) return false;
if (checked_for_a11y_support_) return false;
if (obj_id == OBJID_CLIENT) {
const auto axState = content::BrowserAccessibilityState::GetInstance();
if (axState && !axState->IsAccessibleBrowser()) {
axState->OnScreenReaderDetected();
enabled_a11y_support_ = true;
Browser::Get()->OnAccessibilitySupportChanged();
}
const DWORD obj_id = static_cast<DWORD>(l_param);
if (obj_id != OBJID_CLIENT) {
return false;
}
if (!IsScreenReaderActive()) {
return false;
}
checked_for_a11y_support_ = true;
const auto axState = content::BrowserAccessibilityState::GetInstance();
if (axState && !axState->IsAccessibleBrowser()) {
axState->OnScreenReaderDetected();
Browser::Get()->OnAccessibilitySupportChanged();
}
return false;

View File

@@ -17,9 +17,9 @@
<key>CFBundleIconFile</key>
<string>electron.icns</string>
<key>CFBundleVersion</key>
<string>1.3.6</string>
<string>1.3.13</string>
<key>CFBundleShortVersionString</key>
<string>1.3.6</string>
<string>1.3.13</string>
<key>LSApplicationCategoryType</key>
<string>public.app-category.developer-tools</string>
<key>LSMinimumSystemVersion</key>

View File

@@ -56,8 +56,8 @@ END
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 1,3,6,0
PRODUCTVERSION 1,3,6,0
FILEVERSION 1,3,13,0
PRODUCTVERSION 1,3,13,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@@ -74,12 +74,12 @@ BEGIN
BEGIN
VALUE "CompanyName", "GitHub, Inc."
VALUE "FileDescription", "Electron"
VALUE "FileVersion", "1.3.6"
VALUE "FileVersion", "1.3.13"
VALUE "InternalName", "electron.exe"
VALUE "LegalCopyright", "Copyright (C) 2015 GitHub, Inc. All rights reserved."
VALUE "OriginalFilename", "electron.exe"
VALUE "ProductName", "Electron"
VALUE "ProductVersion", "1.3.6"
VALUE "ProductVersion", "1.3.13"
VALUE "SquirrelAwareVersion", "1"
END
END

View File

@@ -9,9 +9,11 @@
#include "atom/common/api/remote_callback_freer.h"
#include "atom/common/api/remote_object_freer.h"
#include "atom/common/native_mate_converters/content_converter.h"
#include "atom/common/native_mate_converters/gurl_converter.h"
#include "atom/common/node_includes.h"
#include "base/hash.h"
#include "native_mate/dictionary.h"
#include "url/origin.h"
#include "v8/include/v8-profiler.h"
namespace std {
@@ -92,6 +94,10 @@ void TakeHeapSnapshot(v8::Isolate* isolate) {
isolate->GetHeapProfiler()->TakeHeapSnapshot();
}
bool IsSameOrigin(const GURL& l, const GURL& r) {
return url::Origin(l).IsSameOriginWith(url::Origin(r));
}
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);
@@ -105,6 +111,7 @@ void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
dict.SetMethod("createIDWeakMap", &atom::api::KeyWeakMap<int32_t>::Create);
dict.SetMethod("createDoubleIDWeakMap",
&atom::api::KeyWeakMap<std::pair<int32_t, int32_t>>::Create);
dict.SetMethod("isSameOrigin", &IsSameOrigin);
}
} // namespace

View File

@@ -7,7 +7,7 @@
#define ATOM_MAJOR_VERSION 1
#define ATOM_MINOR_VERSION 3
#define ATOM_PATCH_VERSION 6
#define ATOM_PATCH_VERSION 13
#define ATOM_VERSION_IS_RELEASE 1

View File

@@ -88,10 +88,14 @@ double WebFrame::GetZoomFactor() const {
return blink::WebView::zoomLevelToZoomFactor(GetZoomLevel());
}
void WebFrame::SetZoomLevelLimits(double min_level, double max_level) {
void WebFrame::SetVisualZoomLevelLimits(double min_level, double max_level) {
web_frame_->view()->setDefaultPageScaleLimits(min_level, max_level);
}
void WebFrame::SetLayoutZoomLevelLimits(double min_level, double max_level) {
web_frame_->view()->zoomLimitsChanged(min_level, max_level);
}
v8::Local<v8::Value> WebFrame::RegisterEmbedderCustomElement(
const base::string16& name, v8::Local<v8::Object> options) {
blink::WebExceptionCode c = 0;
@@ -196,7 +200,10 @@ void WebFrame::BuildPrototype(
.SetMethod("getZoomLevel", &WebFrame::GetZoomLevel)
.SetMethod("setZoomFactor", &WebFrame::SetZoomFactor)
.SetMethod("getZoomFactor", &WebFrame::GetZoomFactor)
.SetMethod("setZoomLevelLimits", &WebFrame::SetZoomLevelLimits)
.SetMethod("setVisualZoomLevelLimits",
&WebFrame::SetVisualZoomLevelLimits)
.SetMethod("setLayoutZoomLevelLimits",
&WebFrame::SetLayoutZoomLevelLimits)
.SetMethod("registerEmbedderCustomElement",
&WebFrame::RegisterEmbedderCustomElement)
.SetMethod("registerElementResizeCallback",
@@ -212,7 +219,9 @@ void WebFrame::BuildPrototype(
.SetMethod("insertText", &WebFrame::InsertText)
.SetMethod("executeJavaScript", &WebFrame::ExecuteJavaScript)
.SetMethod("getResourceUsage", &WebFrame::GetResourceUsage)
.SetMethod("clearCache", &WebFrame::ClearCache);
.SetMethod("clearCache", &WebFrame::ClearCache)
// TODO(kevinsawicki): Remove in 2.0, deprecate before then with warnings
.SetMethod("setZoomLevelLimits", &WebFrame::SetVisualZoomLevelLimits);
}
} // namespace api

View File

@@ -45,7 +45,8 @@ class WebFrame : public mate::Wrappable<WebFrame> {
double SetZoomFactor(double factor);
double GetZoomFactor() const;
void SetZoomLevelLimits(double min_level, double max_level);
void SetVisualZoomLevelLimits(double min_level, double max_level);
void SetLayoutZoomLevelLimits(double min_level, double max_level);
v8::Local<v8::Value> RegisterEmbedderCustomElement(
const base::string16& name, v8::Local<v8::Object> options);

View File

@@ -36,6 +36,7 @@
'node_use_perfctr': 'false',
'node_use_v8_platform': 'false',
'node_use_bundled_v8': 'false',
'node_enable_d8': 'false',
'uv_library': 'static_library',
'uv_parent_path': 'vendor/node/deps/uv',
'uv_use_dtrace': 'false',

View File

@@ -684,7 +684,22 @@ Sends a request to get current zoom level, the `callback` will be called with
* `minimumLevel` Number
* `maximumLevel` Number
Sets the maximum and minimum zoom level.
**Deprecated:** Call `setVisualZoomLevelLimits` instead to set the visual zoom
level limits. This method will be removed in Electron 2.0.
#### `contents.setVisualZoomLevelLimits(minimumLevel, maximumLevel)`
* `minimumLevel` Number
* `maximumLevel` Number
Sets the maximum and minimum pinch-to-zoom level.
#### `contents.setLayoutZoomLevelLimits(minimumLevel, maximumLevel)`
* `minimumLevel` Number
* `maximumLevel` Number
Sets the maximum and minimum layout-based (i.e. non-visual) zoom level.
#### `contents.undo()`

View File

@@ -42,7 +42,22 @@ Returns the current zoom level.
* `minimumLevel` Number
* `maximumLevel` Number
Sets the maximum and minimum zoom level.
**Deprecated:** Call `setVisualZoomLevelLimits` instead to set the visual zoom
level limits. This method will be removed in Electron 2.0.
### `webFrame.setVisualZoomLevelLimits(minimumLevel, maximumLevel)`
* `minimumLevel` Number
* `maximumLevel` Number
Sets the maximum and minimum pinch-to-zoom level.
### `webFrame.setLayoutZoomLevelLimits(minimumLevel, maximumLevel)`
* `minimumLevel` Number
* `maximumLevel` Number
Sets the maximum and minimum layout-based (i.e. non-visual) zoom level.
### `webFrame.setSpellCheckProvider(language, autoCorrectWord, provider)`

View File

@@ -76,3 +76,28 @@ webContents.openDevTools({detach: true})
// Replace with
webContents.openDevTools({mode: 'detach'})
```
```js
// Deprecated
webContents.setZoomLevelLimits(1, 2)
// Replace with
webContents.setVisualZoomLevelLimits(1, 2)
```
## `webFrame`
```js
// Deprecated
webFrame.setZoomLevelLimits(1, 2)
// Replace with
webFrame.setVisualZoomLevelLimits(1, 2)
```
## `<webview>`
```js
// Deprecated
webview.setZoomLevelLimits(1, 2)
// Replace with
webview.setVisualZoomLevelLimits(1, 2)
```

View File

@@ -4,7 +4,7 @@
'product_name%': 'Electron',
'company_name%': 'GitHub, Inc',
'company_abbr%': 'github',
'version%': '1.3.6',
'version%': '1.3.13',
},
'includes': [
'filenames.gypi',
@@ -279,6 +279,7 @@
'-lcomdlg32.lib',
'-lwininet.lib',
'-lwinmm.lib',
'-luiautomationcore.lib',
],
},
'dependencies': [

View File

@@ -71,7 +71,7 @@ app.allowNTLMCredentialsForAllDomains = function (allow) {
const events = ['login', 'certificate-error', 'select-client-certificate']
for (let name of events) {
app.on(name, (event, webContents, ...args) => {
webContents.emit.apply(webContents, [name, event].concat(args))
webContents.emit(name, event, ...args)
})
}

View File

@@ -119,19 +119,19 @@ BrowserWindow.fromDevToolsWebContents = (webContents) => {
// Helpers.
Object.assign(BrowserWindow.prototype, {
loadURL (...args) {
return this.webContents.loadURL.apply(this.webContents, args)
return this.webContents.loadURL(...args)
},
getURL (...args) {
return this.webContents.getURL()
},
reload (...args) {
return this.webContents.reload.apply(this.webContents, args)
return this.webContents.reload(...args)
},
send (...args) {
return this.webContents.send.apply(this.webContents, args)
return this.webContents.send(...args)
},
openDevTools (...args) {
return this.webContents.openDevTools.apply(this.webContents, args)
return this.webContents.openDevTools(...args)
},
closeDevTools () {
return this.webContents.closeDevTools()
@@ -146,7 +146,7 @@ Object.assign(BrowserWindow.prototype, {
return this.webContents.toggleDevTools()
},
inspectElement (...args) {
return this.webContents.inspectElement.apply(this.webContents, args)
return this.webContents.inspectElement(...args)
},
inspectServiceWorker () {
return this.webContents.inspectServiceWorker()
@@ -155,7 +155,7 @@ Object.assign(BrowserWindow.prototype, {
return this.webContents.showDefinitionForSelection()
},
capturePage (...args) {
return this.webContents.capturePage.apply(this.webContents, args)
return this.webContents.capturePage(...args)
}
})

View File

@@ -50,7 +50,7 @@ module.exports = {
showOpenDialog: function (...args) {
var prop, properties, value, wrappedCallback
checkAppInitialized()
let [window, options, callback] = parseArgs.apply(null, args)
let [window, options, callback] = parseArgs(...args)
if (options == null) {
options = {
title: 'Open',
@@ -97,7 +97,7 @@ module.exports = {
showSaveDialog: function (...args) {
var wrappedCallback
checkAppInitialized()
let [window, options, callback] = parseArgs.apply(null, args)
let [window, options, callback] = parseArgs(...args)
if (options == null) {
options = {
title: 'Save'
@@ -130,7 +130,7 @@ module.exports = {
showMessageBox: function (...args) {
var flags, i, j, len, messageBoxType, ref2, ref3, text
checkAppInitialized()
let [window, options, callback] = parseArgs.apply(null, args)
let [window, options, callback] = parseArgs(...args)
if (options == null) {
options = {
type: 'none'
@@ -185,7 +185,7 @@ module.exports = {
},
showErrorBox: function (...args) {
return binding.showErrorBox.apply(binding, args)
return binding.showErrorBox(...args)
}
}

View File

@@ -4,13 +4,11 @@ const {ipcMain} = require('electron')
// The history operation in renderer is redirected to browser.
ipcMain.on('ELECTRON_NAVIGATION_CONTROLLER', function (event, method, ...args) {
var ref
(ref = event.sender)[method].apply(ref, args)
event.sender[method](...args)
})
ipcMain.on('ELECTRON_SYNC_NAVIGATION_CONTROLLER', function (event, method, ...args) {
var ref
event.returnValue = (ref = event.sender)[method].apply(ref, args)
event.returnValue = event.sender[method](...args)
})
// JavaScript implementation of Chromium's NavigationController.

View File

@@ -100,8 +100,11 @@ WebContents.prototype.sendToAll = function (channel, ...args) {
// Following methods are mapped to webFrame.
const webFrameMethods = [
'insertText',
'setLayoutZoomLevelLimits',
'setVisualZoomLevelLimits',
'setZoomFactor',
'setZoomLevel',
// TODO(kevinsawicki): Remove in 2.0, deprecate before then with warnings
'setZoomLevelLimits'
]
const webFrameMethodsWithResult = [
@@ -234,7 +237,7 @@ WebContents.prototype._init = function () {
// Delays the page-title-updated event to next tick.
this.on('-page-title-updated', function (...args) {
setImmediate(() => {
this.emit.apply(this, ['page-title-updated'].concat(args))
this.emit('page-title-updated', ...args)
})
})

View File

@@ -1,6 +1,7 @@
'use strict'
const {BrowserWindow, ipcMain, webContents} = require('electron')
const {isSameOrigin} = process.atomBinding('v8_util')
const hasProp = {}.hasOwnProperty
const frameToGuest = {}
@@ -86,10 +87,7 @@ const createGuest = function (embedder, url, frameName, options) {
return guestId
}
const getGuestWindow = function (guestId) {
const guestContents = webContents.fromId(guestId)
if (guestContents == null) return
const getGuestWindow = function (guestContents) {
let guestWindow = BrowserWindow.fromWebContents(guestContents)
if (guestWindow == null) {
const hostContents = guestContents.hostWebContents
@@ -100,6 +98,22 @@ const getGuestWindow = function (guestId) {
return guestWindow
}
// Checks whether |sender| can access the |target|:
// 1. Check whether |sender| is the parent of |target|.
// 2. Check whether |sender| has node integration, if so it is allowed to
// do anything it wants.
// 3. Check whether the origins match.
//
// However it allows a child window without node integration but with same
// origin to do anything it wants, when its opener window has node integration.
// The W3C does not have anything on this, but from my understanding of the
// security model of |window.opener|, this should be fine.
const canAccessWindow = function (sender, target) {
return (target.getWebPreferences().openerId === sender.id) ||
(sender.getWebPreferences().nodeIntegration === true) ||
isSameOrigin(sender.getURL(), target.getURL())
}
// Routed window.open messages.
ipcMain.on('ELECTRON_GUEST_WINDOW_MANAGER_WINDOW_OPEN', function (event, url, frameName, disposition, options) {
options = mergeBrowserWindowOptions(event.sender, options)
@@ -112,19 +126,46 @@ ipcMain.on('ELECTRON_GUEST_WINDOW_MANAGER_WINDOW_OPEN', function (event, url, fr
})
ipcMain.on('ELECTRON_GUEST_WINDOW_MANAGER_WINDOW_CLOSE', function (event, guestId) {
const guestWindow = getGuestWindow(guestId)
const guestContents = webContents.fromId(guestId)
if (guestContents == null) return
if (!canAccessWindow(event.sender, guestContents)) {
console.error(`Blocked ${event.sender.getURL()} from closing its opener.`)
return
}
const guestWindow = getGuestWindow(guestContents)
if (guestWindow != null) guestWindow.destroy()
})
ipcMain.on('ELECTRON_GUEST_WINDOW_MANAGER_WINDOW_METHOD', function (event, guestId, method, ...args) {
const guestWindow = getGuestWindow(guestId)
event.returnValue = guestWindow != null ? guestWindow[method].apply(guestWindow, args) : null
const guestContents = webContents.fromId(guestId)
if (guestContents == null) {
event.returnValue = null
return
}
if (!canAccessWindow(event.sender, guestContents)) {
console.error(`Blocked ${event.sender.getURL()} from calling ${method} on its opener.`)
event.returnValue = null
return
}
const guestWindow = getGuestWindow(guestContents)
if (guestWindow != null) {
event.returnValue = guestWindow[method](...args)
} else {
event.returnValue = null
}
})
ipcMain.on('ELECTRON_GUEST_WINDOW_MANAGER_WINDOW_POSTMESSAGE', function (event, guestId, message, targetOrigin, sourceOrigin) {
const guestContents = webContents.fromId(guestId)
if (guestContents == null) return
// The W3C does not seem to have word on how postMessage should work when the
// origins do not match, so we do not do |canAccessWindow| check here since
// postMessage across origins is useful and not harmful.
if (guestContents.getURL().indexOf(targetOrigin) === 0 || targetOrigin === '*') {
const sourceId = event.sender.id
guestContents.send('ELECTRON_GUEST_WINDOW_POSTMESSAGE', sourceId, message, sourceOrigin)
@@ -133,5 +174,26 @@ ipcMain.on('ELECTRON_GUEST_WINDOW_MANAGER_WINDOW_POSTMESSAGE', function (event,
ipcMain.on('ELECTRON_GUEST_WINDOW_MANAGER_WEB_CONTENTS_METHOD', function (event, guestId, method, ...args) {
const guestContents = webContents.fromId(guestId)
if (guestContents != null) guestContents[method].apply(guestContents, args)
if (guestContents == null) return
if (canAccessWindow(event.sender, guestContents)) {
guestContents[method](...args)
} else {
console.error(`Blocked ${event.sender.getURL()} from calling ${method} on its opener.`)
}
})
ipcMain.on('ELECTRON_GUEST_WINDOW_MANAGER_WEB_CONTENTS_METHOD_SYNC', function (event, guestId, method, ...args) {
const guestContents = webContents.fromId(guestId)
if (guestContents == null) {
event.returnValue = null
return
}
if (canAccessWindow(event.sender, guestContents)) {
event.returnValue = guestContents[method](...args)
} else {
console.error(`Blocked ${event.sender.getURL()} from calling ${method} on its opener.`)
event.returnValue = null
}
})

View File

@@ -26,7 +26,7 @@ if (process.platform === 'win32') {
// Redirect node's console to use our own implementations, since node can not
// handle console output when running as GUI program.
var consoleLog = function (...args) {
return process.log(util.format.apply(util, args) + '\n')
return process.log(util.format(...args) + '\n')
}
var streamWrite = function (chunk, encoding, callback) {
if (Buffer.isBuffer(chunk)) {

View File

@@ -19,17 +19,14 @@ class ObjectsRegistry {
// registered then the already assigned ID would be returned.
add (webContents, obj) {
// Get or assign an ID to the object.
let id = this.saveToStorage(obj)
const id = this.saveToStorage(obj)
// Add object to the set of referenced objects.
let webContentsId = webContents.getId()
const webContentsId = webContents.getId()
let owner = this.owners[webContentsId]
if (!owner) {
owner = this.owners[webContentsId] = new Set()
// Clear the storage when webContents is reloaded/navigated.
webContents.once('render-view-deleted', () => {
this.clear(webContentsId)
})
this.registerDeleteListener(webContents, webContentsId)
}
if (!owner.has(id)) {
owner.add(id)
@@ -89,9 +86,20 @@ class ObjectsRegistry {
pointer.count -= 1
if (pointer.count === 0) {
v8Util.deleteHiddenValue(pointer.object, 'atomId')
return delete this.storage[id]
delete this.storage[id]
}
}
// Private: Clear the storage when webContents is reloaded/navigated.
registerDeleteListener (webContents, webContentsId) {
const listener = (event, deletedProcessId) => {
if (deletedProcessId === webContentsId) {
webContents.removeListener('render-view-deleted', listener)
this.clear(webContentsId)
}
}
webContents.on('render-view-deleted', listener)
}
}
module.exports = new ObjectsRegistry()

View File

@@ -371,3 +371,34 @@ ipcMain.on('ELECTRON_BROWSER_SEND_TO', function (event, sendToAll, webContentsId
contents.send(channel, ...args)
}
})
// Implements window.alert(message, title)
ipcMain.on('ELECTRON_BROWSER_WINDOW_ALERT', function (event, message, title) {
if (message == null) message = ''
if (title == null) title = ''
event.returnValue = electron.dialog.showMessageBox(event.sender.getOwnerBrowserWindow(), {
message: `${message}`,
title: `${title}`,
buttons: ['OK']
})
})
// Implements window.confirm(message, title)
ipcMain.on('ELECTRON_BROWSER_WINDOW_CONFIRM', function (event, message, title) {
if (message == null) message = ''
if (title == null) title = ''
event.returnValue = !electron.dialog.showMessageBox(event.sender.getOwnerBrowserWindow(), {
message: `${message}`,
title: `${title}`,
buttons: ['OK', 'Cancel'],
cancelId: 1
})
})
// Implements window.close()
ipcMain.on('ELECTRON_BROWSER_WINDOW_CLOSE', function (event) {
event.sender.getOwnerBrowserWindow().close()
event.returnValue = null
})

View File

@@ -44,14 +44,8 @@ class CallbacksRegistry {
return (ref = this.callbacks[id]) != null ? ref : function () {}
}
call (id, ...args) {
var ref
return (ref = this.get(id)).call.apply(ref, [global].concat(args))
}
apply (id, ...args) {
var ref
return (ref = this.get(id)).apply.apply(ref, [global].concat(args))
return this.get(id).apply(global, ...args)
}
remove (id) {

View File

@@ -1,11 +1,13 @@
const timers = require('timers')
const {binding} = process
process.atomBinding = function (name) {
try {
return process.binding('atom_' + process.type + '_' + name)
return binding('atom_' + process.type + '_' + name)
} catch (error) {
if (/No such module/.test(error.message)) {
return process.binding('atom_common_' + name)
return binding('atom_common_' + name)
}
}
}

View File

@@ -88,7 +88,7 @@ const wrapArgs = function (args, visited) {
}
}
}
return Array.prototype.slice.call(args).map(valueToMeta)
return args.map(valueToMeta)
}
// Populate object's members from descriptors.
@@ -100,14 +100,14 @@ const setObjectMembers = function (ref, object, metaId, members) {
let descriptor = { enumerable: member.enumerable }
if (member.type === 'method') {
const remoteMemberFunction = function () {
const remoteMemberFunction = function (...args) {
if (this && this.constructor === remoteMemberFunction) {
// Constructor call.
let ret = ipcRenderer.sendSync('ELECTRON_BROWSER_MEMBER_CONSTRUCTOR', metaId, member.name, wrapArgs(arguments))
let ret = ipcRenderer.sendSync('ELECTRON_BROWSER_MEMBER_CONSTRUCTOR', metaId, member.name, wrapArgs(args))
return metaToValue(ret)
} else {
// Call member function.
let ret = ipcRenderer.sendSync('ELECTRON_BROWSER_MEMBER_CALL', metaId, member.name, wrapArgs(arguments))
let ret = ipcRenderer.sendSync('ELECTRON_BROWSER_MEMBER_CALL', metaId, member.name, wrapArgs(args))
return metaToValue(ret)
}
}
@@ -213,17 +213,17 @@ const metaToValue = function (meta) {
if (meta.type === 'function') {
// A shadow class to represent the remote function object.
let remoteFunction = function () {
let remoteFunction = function (...args) {
if (this && this.constructor === remoteFunction) {
// Constructor call.
let obj = ipcRenderer.sendSync('ELECTRON_BROWSER_CONSTRUCTOR', meta.id, wrapArgs(arguments))
let obj = ipcRenderer.sendSync('ELECTRON_BROWSER_CONSTRUCTOR', meta.id, wrapArgs(args))
// Returning object in constructor will replace constructed object
// with the returned object.
// http://stackoverflow.com/questions/1978049/what-values-can-a-constructor-return-to-avoid-returning-this
return metaToValue(obj)
} else {
// Function call.
let obj = ipcRenderer.sendSync('ELECTRON_BROWSER_FUNCTION_CALL', meta.id, wrapArgs(arguments))
let obj = ipcRenderer.sendSync('ELECTRON_BROWSER_FUNCTION_CALL', meta.id, wrapArgs(args))
return metaToValue(obj)
}
}

View File

@@ -29,20 +29,18 @@ const electron = require('electron')
// Call webFrame method.
electron.ipcRenderer.on('ELECTRON_INTERNAL_RENDERER_WEB_FRAME_METHOD', (event, method, args) => {
electron.webFrame[method].apply(electron.webFrame, args)
electron.webFrame[method](...args)
})
electron.ipcRenderer.on('ELECTRON_INTERNAL_RENDERER_SYNC_WEB_FRAME_METHOD', (event, requestId, method, args) => {
const result = electron.webFrame[method].apply(electron.webFrame, args)
const result = electron.webFrame[method](...args)
event.sender.send(`ELECTRON_INTERNAL_BROWSER_SYNC_WEB_FRAME_RESPONSE_${requestId}`, result)
})
electron.ipcRenderer.on('ELECTRON_INTERNAL_RENDERER_ASYNC_WEB_FRAME_METHOD', (event, requestId, method, args) => {
const responseCallback = function (result) {
electron.webFrame[method](...args, function (result) {
event.sender.send(`ELECTRON_INTERNAL_BROWSER_ASYNC_WEB_FRAME_RESPONSE_${requestId}`, result)
}
args.push(responseCallback)
electron.webFrame[method].apply(electron.webFrame, args)
})
})
// Process command line arguments.

View File

@@ -1,31 +1,35 @@
'use strict'
const ipcRenderer = require('electron').ipcRenderer
const remote = require('electron').remote
const {ipcRenderer} = require('electron')
const {defineProperty} = Object
// Helper function to resolve relative url.
var a = window.top.document.createElement('a')
var resolveURL = function (url) {
const a = window.top.document.createElement('a')
const resolveURL = function (url) {
a.href = url
return a.href
}
// Window object returned by "window.open".
var BrowserWindowProxy = (function () {
const BrowserWindowProxy = (function () {
BrowserWindowProxy.proxies = {}
BrowserWindowProxy.getOrCreate = function (guestId) {
var base = this.proxies
base[guestId] != null ? base[guestId] : base[guestId] = new BrowserWindowProxy(guestId)
return base[guestId]
let proxy = this.proxies[guestId]
if (proxy == null) {
proxy = new BrowserWindowProxy(guestId)
this.proxies[guestId] = proxy
}
return proxy
}
BrowserWindowProxy.remove = function (guestId) {
return delete this.proxies[guestId]
delete this.proxies[guestId]
}
function BrowserWindowProxy (guestId1) {
Object.defineProperty(this, 'guestId', {
defineProperty(this, 'guestId', {
configurable: false,
enumerable: true,
writeable: false,
@@ -40,28 +44,28 @@ var BrowserWindowProxy = (function () {
}
BrowserWindowProxy.prototype.close = function () {
return ipcRenderer.send('ELECTRON_GUEST_WINDOW_MANAGER_WINDOW_CLOSE', this.guestId)
ipcRenderer.send('ELECTRON_GUEST_WINDOW_MANAGER_WINDOW_CLOSE', this.guestId)
}
BrowserWindowProxy.prototype.focus = function () {
return ipcRenderer.send('ELECTRON_GUEST_WINDOW_MANAGER_WINDOW_METHOD', this.guestId, 'focus')
ipcRenderer.send('ELECTRON_GUEST_WINDOW_MANAGER_WINDOW_METHOD', this.guestId, 'focus')
}
BrowserWindowProxy.prototype.blur = function () {
return ipcRenderer.send('ELECTRON_GUEST_WINDOW_MANAGER_WINDOW_METHOD', this.guestId, 'blur')
ipcRenderer.send('ELECTRON_GUEST_WINDOW_MANAGER_WINDOW_METHOD', this.guestId, 'blur')
}
BrowserWindowProxy.prototype.print = function () {
return ipcRenderer.send('ELECTRON_GUEST_WINDOW_MANAGER_WEB_CONTENTS_METHOD', this.guestId, 'print')
ipcRenderer.send('ELECTRON_GUEST_WINDOW_MANAGER_WEB_CONTENTS_METHOD', this.guestId, 'print')
}
Object.defineProperty(BrowserWindowProxy.prototype, 'location', {
defineProperty(BrowserWindowProxy.prototype, 'location', {
get: function () {
return ipcRenderer.sendSync('ELECTRON_GUEST_WINDOW_MANAGER_WINDOW_METHOD', this.guestId, 'getURL')
return ipcRenderer.sendSync('ELECTRON_GUEST_WINDOW_MANAGER_WEB_CONTENTS_METHOD_SYNC', this.guestId, 'getURL')
},
set: function (url) {
url = resolveURL(url)
return ipcRenderer.sendSync('ELECTRON_GUEST_WINDOW_MANAGER_WINDOW_METHOD', this.guestId, 'loadURL', url)
return ipcRenderer.sendSync('ELECTRON_GUEST_WINDOW_MANAGER_WEB_CONTENTS_METHOD_SYNC', this.guestId, 'loadURL', url)
}
})
@@ -69,11 +73,11 @@ var BrowserWindowProxy = (function () {
if (targetOrigin == null) {
targetOrigin = '*'
}
return ipcRenderer.send('ELECTRON_GUEST_WINDOW_MANAGER_WINDOW_POSTMESSAGE', this.guestId, message, targetOrigin, window.location.origin)
ipcRenderer.send('ELECTRON_GUEST_WINDOW_MANAGER_WINDOW_POSTMESSAGE', this.guestId, message, targetOrigin, window.location.origin)
}
BrowserWindowProxy.prototype['eval'] = function (...args) {
return ipcRenderer.send.apply(ipcRenderer, ['ELECTRON_GUEST_WINDOW_MANAGER_WEB_CONTENTS_METHOD', this.guestId, 'executeJavaScript'].concat(args))
ipcRenderer.send('ELECTRON_GUEST_WINDOW_MANAGER_WEB_CONTENTS_METHOD', this.guestId, 'executeJavaScript', ...args)
}
return BrowserWindowProxy
@@ -82,7 +86,7 @@ var BrowserWindowProxy = (function () {
if (process.guestInstanceId == null) {
// Override default window.close.
window.close = function () {
return remote.getCurrentWindow().close()
ipcRenderer.sendSync('ELECTRON_BROWSER_WINDOW_CLOSE')
}
}
@@ -158,29 +162,12 @@ window.open = function (url, frameName, features) {
}
}
// Use the dialog API to implement alert().
window.alert = function (message = '', title = '') {
remote.dialog.showMessageBox(remote.getCurrentWindow(), {
message: String(message),
title: String(title),
buttons: ['OK']
})
window.alert = function (message, title) {
ipcRenderer.sendSync('ELECTRON_BROWSER_WINDOW_ALERT', message, title)
}
// And the confirm().
window.confirm = function (message, title) {
var buttons, cancelId
if (title == null) {
title = ''
}
buttons = ['OK', 'Cancel']
cancelId = 1
return !remote.dialog.showMessageBox(remote.getCurrentWindow(), {
message: message,
title: title,
buttons: buttons,
cancelId: cancelId
})
return ipcRenderer.sendSync('ELECTRON_BROWSER_WINDOW_CONFIRM', message, title)
}
// But we do not support prompt().
@@ -205,26 +192,26 @@ ipcRenderer.on('ELECTRON_GUEST_WINDOW_POSTMESSAGE', function (event, sourceId, m
// Forward history operations to browser.
var sendHistoryOperation = function (...args) {
return ipcRenderer.send.apply(ipcRenderer, ['ELECTRON_NAVIGATION_CONTROLLER'].concat(args))
ipcRenderer.send('ELECTRON_NAVIGATION_CONTROLLER', ...args)
}
var getHistoryOperation = function (...args) {
return ipcRenderer.sendSync.apply(ipcRenderer, ['ELECTRON_SYNC_NAVIGATION_CONTROLLER'].concat(args))
return ipcRenderer.sendSync('ELECTRON_SYNC_NAVIGATION_CONTROLLER', ...args)
}
window.history.back = function () {
return sendHistoryOperation('goBack')
sendHistoryOperation('goBack')
}
window.history.forward = function () {
return sendHistoryOperation('goForward')
sendHistoryOperation('goForward')
}
window.history.go = function (offset) {
return sendHistoryOperation('goToOffset', offset)
sendHistoryOperation('goToOffset', offset)
}
Object.defineProperty(window.history, 'length', {
defineProperty(window.history, 'length', {
get: function () {
return getHistoryOperation('length')
}
@@ -242,13 +229,13 @@ ipcRenderer.on('ELECTRON_RENDERER_WINDOW_VISIBILITY_CHANGE', function (event, vi
})
// Make document.hidden and document.visibilityState return the correct value.
Object.defineProperty(document, 'hidden', {
defineProperty(document, 'hidden', {
get: function () {
return cachedVisibilityState !== 'visible'
}
})
Object.defineProperty(document, 'visibilityState', {
defineProperty(document, 'visibilityState', {
get: function () {
return cachedVisibilityState
}

View File

@@ -46,7 +46,7 @@ var DEPRECATED_EVENTS = {
var dispatchEvent = function (webView, eventName, eventKey, ...args) {
var domEvent, f, i, j, len, ref1
if (DEPRECATED_EVENTS[eventName] != null) {
dispatchEvent.apply(null, [webView, DEPRECATED_EVENTS[eventName], eventKey].concat(args))
dispatchEvent(webView, DEPRECATED_EVENTS[eventName], eventKey, ...args)
}
domEvent = new Event(eventName)
ref1 = WEB_VIEW_EVENTS[eventKey]
@@ -63,7 +63,7 @@ var dispatchEvent = function (webView, eventName, eventKey, ...args) {
module.exports = {
registerEvents: function (webView, viewInstanceId) {
ipcRenderer.on('ELECTRON_GUEST_VIEW_INTERNAL_DISPATCH_EVENT-' + viewInstanceId, function (event, eventName, ...args) {
dispatchEvent.apply(null, [webView, eventName, eventName].concat(args))
dispatchEvent(webView, eventName, eventName, ...args)
})
ipcRenderer.on('ELECTRON_GUEST_VIEW_INTERNAL_IPC_MESSAGE-' + viewInstanceId, function (event, channel, ...args) {

View File

@@ -394,8 +394,11 @@ var registerWebViewElement = function () {
'insertText',
'send',
'sendInputEvent',
'setLayoutZoomLevelLimits',
'setVisualZoomLevelLimits',
'setZoomFactor',
'setZoomLevel',
// TODO(kevinsawicki): Remove in 2.0, deprecate before then with warnings
'setZoomLevelLimits'
]
@@ -404,7 +407,7 @@ var registerWebViewElement = function () {
return function (...args) {
const internal = v8Util.getHiddenValue(this, 'internal')
if (internal.webContents) {
return internal.webContents[m].apply(internal.webContents, args)
return internal.webContents[m](...args)
} else {
throw new Error(`Cannot call ${m} because the webContents is unavailable. The WebView must be attached to the DOM and the dom-ready event emitted before this method can be called.`)
}
@@ -417,7 +420,7 @@ var registerWebViewElement = function () {
createNonBlockHandler = function (m) {
return function (...args) {
const internal = v8Util.getHiddenValue(this, 'internal')
return ipcRenderer.send.apply(ipcRenderer, ['ELECTRON_BROWSER_ASYNC_CALL_TO_GUEST_VIEW', null, internal.guestInstanceId, m].concat(args))
return ipcRenderer.send('ELECTRON_BROWSER_ASYNC_CALL_TO_GUEST_VIEW', null, internal.guestInstanceId, m, ...args)
}
}
for (j = 0, len1 = nonblockMethods.length; j < len1; j++) {

View File

@@ -1,6 +1,6 @@
{
"name": "electron",
"version": "1.3.6",
"version": "1.3.13",
"devDependencies": {
"asar": "^0.11.0",
"electabul": "~0.0.4",

View File

@@ -0,0 +1,5 @@
#!/usr/bin/env bash
export TARGET_ARCH=arm
script/cibuild-linux

View File

@@ -0,0 +1,5 @@
#!/usr/bin/env bash
export TARGET_ARCH=ia32
script/cibuild-linux

View File

@@ -0,0 +1,5 @@
#!/usr/bin/env bash
export TARGET_ARCH=x64
script/cibuild-linux

23
script/cibuild-linux Executable file
View File

@@ -0,0 +1,23 @@
#!/usr/bin/env bash
MESSAGE="$(git log --format=%B -n 1 HEAD)"
case ${MESSAGE} in
Bump* ) export ELECTRON_RELEASE=1 ;;
esac
set +x
export ELECTRON_GITHUB_TOKEN="$BUILD_ELECTRON_ELECTRON_GITHUB_TOKEN"
export ELECTRON_S3_BUCKET="$BUILD_ELECTRON_ELECTRON_S3_BUCKET"
export ELECTRON_S3_ACCESS_KEY="$BUILD_ELECTRON_ELECTRON_S3_ACCESS_KEY"
export ELECTRON_S3_SECRET_KEY="$BUILD_ELECTRON_ELECTRON_S3_SECRET_KEY"
if [[ -z "${ELECTRON_RELEASE}" ]]; then
echo "Generating Linux $TARGET_ARCH debug build"
else
echo "Generating Linux $TARGET_ARCH release build"
fi
set -x
script/cibuild

View File

@@ -9,7 +9,7 @@ import sys
BASE_URL = os.getenv('LIBCHROMIUMCONTENT_MIRROR') or \
'https://s3.amazonaws.com/github-janky-artifacts/libchromiumcontent'
LIBCHROMIUMCONTENT_COMMIT = os.getenv('LIBCHROMIUMCONTENT_COMMIT') or \
'c5cf295ef93d4ee88bff0c4b06b28ff0969a890e'
'27add4cfef98f21d5910539bebb47ae175f024c2'
PLATFORM = {
'cygwin': 'win32',

View File

@@ -492,4 +492,19 @@ describe('ipc module', function () {
assert.equal(w.listenerCount('test'), 0)
})
})
describe('remote objects registry', function () {
it('does not dereference until the render view is deleted (regression)', function (done) {
w = new BrowserWindow({
show: false
})
ipcMain.once('error-message', (event, message) => {
assert(message.startsWith('Cannot read property \'object\' of undefined'), message)
done()
})
w.loadURL('file://' + path.join(fixtures, 'api', 'render-view-deleted.html'))
})
})
})

View File

@@ -6,6 +6,7 @@ const {BrowserWindow, protocol, ipcMain} = remote
describe('webFrame module', function () {
var fixtures = path.resolve(__dirname, 'fixtures')
describe('webFrame.registerURLSchemeAsPrivileged', function () {
it('supports fetch api', function (done) {
webFrame.registerURLSchemeAsPrivileged('file')
@@ -61,4 +62,12 @@ describe('webFrame module', function () {
})
})
})
it('supports setting the visual and layout zoom level limits', function () {
assert.doesNotThrow(function () {
webFrame.setZoomLevelLimits(1, 100)
webFrame.setVisualZoomLevelLimits(1, 50)
webFrame.setLayoutZoomLevelLimits(0, 25)
})
})
})

View File

@@ -5,7 +5,7 @@ const ws = require('ws')
const url = require('url')
const remote = require('electron').remote
const {BrowserWindow, session, webContents} = remote
const {BrowserWindow, protocol, session, webContents} = remote
const isCI = remote.getGlobal('isCi')
@@ -283,11 +283,11 @@ describe('chromium feature', function () {
describe('window.opener', function () {
this.timeout(10000)
var url = 'file://' + fixtures + '/pages/window-opener.html'
var w = null
let url = 'file://' + fixtures + '/pages/window-opener.html'
let w = null
afterEach(function () {
w != null ? w.destroy() : void 0
if (w) w.destroy()
})
it('is null for main window', function (done) {
@@ -302,7 +302,7 @@ describe('chromium feature', function () {
})
it('is not null for window opened by window.open', function (done) {
var b
let b
listener = function (event) {
assert.equal(event.data, 'object')
b.close()
@@ -313,6 +313,138 @@ describe('chromium feature', function () {
})
})
describe('window.opener access from BrowserWindow', function () {
this.timeout(10000)
const scheme = 'other'
let url = `${scheme}://${fixtures}/pages/window-opener-location.html`
let w = null
before(function (done) {
protocol.registerFileProtocol(scheme, function (request, callback) {
callback(`${fixtures}/pages/window-opener-location.html`)
}, function (error) {
done(error)
})
})
after(function () {
protocol.unregisterProtocol(scheme)
})
afterEach(function () {
w.close()
})
it('does nothing when origin of current window does not match opener', function (done) {
listener = function (event) {
assert.equal(event.data, undefined)
done()
}
window.addEventListener('message', listener)
w = window.open(url, '', 'show=no')
})
it('works when origin matches', function (done) {
listener = function (event) {
assert.equal(event.data, location.href)
done()
}
window.addEventListener('message', listener)
w = window.open(`file://${fixtures}/pages/window-opener-location.html`, '', 'show=no')
})
it('works when origin does not match opener but has node integration', function (done) {
listener = function (event) {
assert.equal(event.data, location.href)
done()
}
window.addEventListener('message', listener)
w = window.open(url, '', 'show=no,nodeIntegration=yes')
})
})
describe('window.opener access from <webview>', function () {
this.timeout(10000)
const scheme = 'other'
const srcPath = `${fixtures}/pages/webview-opener-postMessage.html`
const pageURL = `file://${fixtures}/pages/window-opener-location.html`
let webview = null
before(function (done) {
protocol.registerFileProtocol(scheme, function (request, callback) {
callback(srcPath)
}, function (error) {
done(error)
})
})
after(function () {
protocol.unregisterProtocol(scheme)
})
afterEach(function () {
if (webview != null) webview.remove()
})
it('does nothing when origin of webview src URL does not match opener', function (done) {
webview = new WebView()
webview.addEventListener('console-message', function (e) {
assert.equal(e.message, 'null')
done()
})
webview.setAttribute('allowpopups', 'on')
webview.src = url.format({
pathname: srcPath,
protocol: scheme,
query: {
p: pageURL
},
slashes: true
})
document.body.appendChild(webview)
})
it('works when origin matches', function (done) {
webview = new WebView()
webview.addEventListener('console-message', function (e) {
assert.equal(e.message, webview.src)
done()
})
webview.setAttribute('allowpopups', 'on')
webview.src = url.format({
pathname: srcPath,
protocol: 'file',
query: {
p: pageURL
},
slashes: true
})
document.body.appendChild(webview)
})
it('works when origin does not match opener but has node integration', function (done) {
webview = new WebView()
webview.addEventListener('console-message', function (e) {
webview.remove()
assert.equal(e.message, webview.src)
done()
})
webview.setAttribute('allowpopups', 'on')
webview.setAttribute('nodeintegration', 'on')
webview.src = url.format({
pathname: srcPath,
protocol: scheme,
query: {
p: pageURL
},
slashes: true
})
document.body.appendChild(webview)
})
})
describe('window.postMessage', function () {
it('sets the source and origin correctly', function (done) {
var b, sourceId

View File

@@ -0,0 +1,32 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script>
const {ipcRenderer, remote} = require('electron')
const contents = remote.getCurrentWebContents()
// This should not trigger a dereference and a remote getURL call should not fail
contents.emit('render-view-deleted', {}, 'not-a-process-id')
try {
contents.getURL()
} catch (error) {
ipcRenderer.send('error-message', 'Unexpected error on getURL call')
}
// This should trigger a dereference and a remote getURL call should fail
contents.emit('render-view-deleted', {}, contents.getId())
try {
contents.getURL()
ipcRenderer.send('error-message', 'No error thrown')
} catch (error) {
ipcRenderer.send('error-message', error.message)
}
</script>
</head>
<body>
</body>
</html>

View File

@@ -0,0 +1,7 @@
<html>
<body>
<script type="text/javascript" charset="utf-8">
window.opener.postMessage(window.opener.location, '*')
</script>
</body>
</html>

View File

@@ -94,7 +94,8 @@ describe('Module._nodeModulePaths', function () {
it('includes paths outside of the resources path', function () {
let modulePath = path.resolve('/foo')
assert.deepEqual(Module._nodeModulePaths(modulePath), [
path.join(modulePath, 'node_modules')
path.join(modulePath, 'node_modules'),
path.resolve('/node_modules')
])
})
})

2
vendor/node vendored