mirror of
https://github.com/electron/electron.git
synced 2026-02-19 03:14:51 -05:00
Compare commits
54 Commits
trash-erro
...
v1.3.14
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
049ea30964 | ||
|
|
9a3cf30bc9 | ||
|
|
2f4dc075e0 | ||
|
|
93c4f90bee | ||
|
|
35be33a02f | ||
|
|
746ea3e045 | ||
|
|
1bd9fc1a09 | ||
|
|
ac54984763 | ||
|
|
c300104cbd | ||
|
|
fc299189eb | ||
|
|
5a768b3dfe | ||
|
|
ab634e6c20 | ||
|
|
f5a6f290bc | ||
|
|
3fe9762082 | ||
|
|
cac7e9460d | ||
|
|
d29bed026c | ||
|
|
02dcc1bf3f | ||
|
|
7a9a2c003c | ||
|
|
ab21a8b03a | ||
|
|
0a587bc611 | ||
|
|
0037af51f3 | ||
|
|
435162af17 | ||
|
|
64077277b1 | ||
|
|
acb95f4614 | ||
|
|
082b47fb85 | ||
|
|
650867772a | ||
|
|
13d2fc9c81 | ||
|
|
04a846a106 | ||
|
|
cb84d26d20 | ||
|
|
78cf807cf0 | ||
|
|
f3de3334cf | ||
|
|
a9d5a1d771 | ||
|
|
2356577614 | ||
|
|
94a5132b07 | ||
|
|
dca200d918 | ||
|
|
e86e7d699f | ||
|
|
922fcfb3da | ||
|
|
1d35151353 | ||
|
|
cb9fdc45e6 | ||
|
|
2dafd845b9 | ||
|
|
9017f90b57 | ||
|
|
b94638894e | ||
|
|
8a3288d791 | ||
|
|
6f5336c63f | ||
|
|
73c1fab423 | ||
|
|
1e36ee918e | ||
|
|
1f49da7a06 | ||
|
|
037a458e1d | ||
|
|
03a274ee27 | ||
|
|
c4bd516b77 | ||
|
|
4c914c1277 | ||
|
|
e3688a8e9d | ||
|
|
375534cf4a | ||
|
|
397e5ad0ac |
@@ -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),
|
||||
|
||||
@@ -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_;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -17,9 +17,9 @@
|
||||
<key>CFBundleIconFile</key>
|
||||
<string>electron.icns</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1.3.6</string>
|
||||
<string>1.3.14</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.3.6</string>
|
||||
<string>1.3.14</string>
|
||||
<key>LSApplicationCategoryType</key>
|
||||
<string>public.app-category.developer-tools</string>
|
||||
<key>LSMinimumSystemVersion</key>
|
||||
|
||||
@@ -56,8 +56,8 @@ END
|
||||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 1,3,6,0
|
||||
PRODUCTVERSION 1,3,6,0
|
||||
FILEVERSION 1,3,14,0
|
||||
PRODUCTVERSION 1,3,14,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.14"
|
||||
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.14"
|
||||
VALUE "SquirrelAwareVersion", "1"
|
||||
END
|
||||
END
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
#define ATOM_MAJOR_VERSION 1
|
||||
#define ATOM_MINOR_VERSION 3
|
||||
#define ATOM_PATCH_VERSION 6
|
||||
#define ATOM_PATCH_VERSION 14
|
||||
|
||||
#define ATOM_VERSION_IS_RELEASE 1
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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()`
|
||||
|
||||
|
||||
@@ -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)`
|
||||
|
||||
|
||||
@@ -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)
|
||||
```
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
'product_name%': 'Electron',
|
||||
'company_name%': 'GitHub, Inc',
|
||||
'company_abbr%': 'github',
|
||||
'version%': '1.3.6',
|
||||
'version%': '1.3.14',
|
||||
},
|
||||
'includes': [
|
||||
'filenames.gypi',
|
||||
@@ -279,6 +279,7 @@
|
||||
'-lcomdlg32.lib',
|
||||
'-lwininet.lib',
|
||||
'-lwinmm.lib',
|
||||
'-luiautomationcore.lib',
|
||||
],
|
||||
},
|
||||
'dependencies': [
|
||||
|
||||
@@ -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)
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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)
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
})
|
||||
|
||||
@@ -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)) {
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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
|
||||
})
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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++) {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "electron",
|
||||
"version": "1.3.6",
|
||||
"version": "1.3.14",
|
||||
"devDependencies": {
|
||||
"asar": "^0.11.0",
|
||||
"electabul": "~0.0.4",
|
||||
|
||||
5
script/cibuild-electron-linux-arm
Executable file
5
script/cibuild-electron-linux-arm
Executable file
@@ -0,0 +1,5 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
export TARGET_ARCH=arm
|
||||
|
||||
script/cibuild-linux
|
||||
5
script/cibuild-electron-linux-ia32
Executable file
5
script/cibuild-electron-linux-ia32
Executable file
@@ -0,0 +1,5 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
export TARGET_ARCH=ia32
|
||||
|
||||
script/cibuild-linux
|
||||
5
script/cibuild-electron-linux-x64
Executable file
5
script/cibuild-electron-linux-x64
Executable file
@@ -0,0 +1,5 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
export TARGET_ARCH=x64
|
||||
|
||||
script/cibuild-linux
|
||||
23
script/cibuild-linux
Executable file
23
script/cibuild-linux
Executable 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
|
||||
@@ -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'
|
||||
'e93c6a82d7ab1e3b97a294200186d7254ad3f868'
|
||||
|
||||
PLATFORM = {
|
||||
'cygwin': 'win32',
|
||||
|
||||
@@ -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'))
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -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)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -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
|
||||
|
||||
32
spec/fixtures/api/render-view-deleted.html
vendored
Normal file
32
spec/fixtures/api/render-view-deleted.html
vendored
Normal 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>
|
||||
7
spec/fixtures/pages/window-opener-location.html
vendored
Normal file
7
spec/fixtures/pages/window-opener-location.html
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
<html>
|
||||
<body>
|
||||
<script type="text/javascript" charset="utf-8">
|
||||
window.opener.postMessage(window.opener.location, '*')
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -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/brightray
vendored
2
vendor/brightray
vendored
Submodule vendor/brightray updated: 554946c787...ee26c5218e
2
vendor/node
vendored
2
vendor/node
vendored
Submodule vendor/node updated: ee8c429dea...c47e9bf901
Reference in New Issue
Block a user