Merge remote-tracking branch 'electron/master' into certificate-addition-windows

This commit is contained in:
Brendan Forster 2017-04-24 11:13:34 +10:00
commit 253a4b0114
21 changed files with 240 additions and 91 deletions

View file

@ -655,6 +655,14 @@ void App::OnGpuProcessCrashed(base::TerminationStatus status) {
status == base::TERMINATION_STATUS_PROCESS_WAS_KILLED);
}
base::FilePath App::GetAppPath() const {
return app_path_;
}
void App::SetAppPath(const base::FilePath& app_path) {
app_path_ = app_path;
}
base::FilePath App::GetPath(mate::Arguments* args, const std::string& name) {
bool succeed = false;
base::FilePath path;
@ -959,6 +967,8 @@ void App::BuildPrototype(
.SetMethod("isUnityRunning",
base::Bind(&Browser::IsUnityRunning, browser))
#endif
.SetMethod("setAppPath", &App::SetAppPath)
.SetMethod("getAppPath", &App::GetAppPath)
.SetMethod("setPath", &App::SetPath)
.SetMethod("getPath", &App::GetPath)
.SetMethod("setDesktopName", &App::SetDesktopName)

View file

@ -70,6 +70,8 @@ class App : public AtomBrowserClient::Delegate,
std::unique_ptr<CertificateManagerModel> model);
#endif
base::FilePath GetAppPath() const;
protected:
explicit App(v8::Isolate* isolate);
~App() override;
@ -115,6 +117,8 @@ class App : public AtomBrowserClient::Delegate,
void OnGpuProcessCrashed(base::TerminationStatus status) override;
private:
void SetAppPath(const base::FilePath& app_path);
// Get/Set the pre-defined path in PathService.
base::FilePath GetPath(mate::Arguments* args, const std::string& name);
void SetPath(mate::Arguments* args,
@ -154,6 +158,8 @@ class App : public AtomBrowserClient::Delegate,
// Tracks tasks requesting file icons.
base::CancelableTaskTracker cancelable_task_tracker_;
base::FilePath app_path_;
DISALLOW_COPY_AND_ASSIGN(App);
};

View file

@ -263,6 +263,14 @@ void Window::OnWindowSwipe(const std::string& direction) {
Emit("swipe", direction);
}
void Window::OnWindowSheetBegin() {
Emit("sheet-begin");
}
void Window::OnWindowSheetEnd() {
Emit("sheet-end");
}
void Window::OnWindowEnterHtmlFullScreen() {
Emit("enter-html-full-screen");
}

View file

@ -79,6 +79,8 @@ class Window : public mate::TrackableObject<Window>,
void OnWindowScrollTouchEnd() override;
void OnWindowScrollTouchEdge() override;
void OnWindowSwipe(const std::string& direction) override;
void OnWindowSheetBegin() override;
void OnWindowSheetEnd() override;
void OnWindowEnterFullScreen() override;
void OnWindowLeaveFullScreen() override;
void OnWindowEnterHtmlFullScreen() override;

View file

@ -235,6 +235,11 @@ void AtomBrowserClient::AppendExtraCommandLineSwitches(
}
#endif
if (delegate_) {
auto app_path = static_cast<api::App*>(delegate_)->GetAppPath();
command_line->AppendSwitchPath(switches::kAppPath, app_path);
}
content::WebContents* web_contents = GetWebContentsFromProcessID(process_id);
if (!web_contents)
return;

View file

@ -554,6 +554,16 @@ void NativeWindow::NotifyWindowSwipe(const std::string& direction) {
observer.OnWindowSwipe(direction);
}
void NativeWindow::NotifyWindowSheetBegin() {
for (NativeWindowObserver& observer : observers_)
observer.OnWindowSheetBegin();
}
void NativeWindow::NotifyWindowSheetEnd() {
for (NativeWindowObserver& observer : observers_)
observer.OnWindowSheetEnd();
}
void NativeWindow::NotifyWindowLeaveFullScreen() {
for (NativeWindowObserver& observer : observers_)
observer.OnWindowLeaveFullScreen();

View file

@ -233,6 +233,8 @@ class NativeWindow : public base::SupportsUserData,
void NotifyWindowScrollTouchEnd();
void NotifyWindowScrollTouchEdge();
void NotifyWindowSwipe(const std::string& direction);
void NotifyWindowSheetBegin();
void NotifyWindowSheetEnd();
void NotifyWindowEnterFullScreen();
void NotifyWindowLeaveFullScreen();
void NotifyWindowEnterHtmlFullScreen();

View file

@ -313,6 +313,14 @@ bool ScopedDisableResize::disable_resize_ = false;
return rect;
}
- (void)windowWillBeginSheet:(NSNotification *)notification {
shell_->NotifyWindowSheetBegin();
}
- (void)windowDidEndSheet:(NSNotification *)notification {
shell_->NotifyWindowSheetEnd();
}
@end
@interface AtomPreviewItem : NSObject <QLPreviewItem>

View file

@ -67,6 +67,8 @@ class NativeWindowObserver {
virtual void OnWindowScrollTouchEnd() {}
virtual void OnWindowScrollTouchEdge() {}
virtual void OnWindowSwipe(const std::string& direction) {}
virtual void OnWindowSheetBegin() {}
virtual void OnWindowSheetEnd() {}
virtual void OnWindowEnterFullScreen() {}
virtual void OnWindowLeaveFullScreen() {}
virtual void OnWindowEnterHtmlFullScreen() {}

View file

@ -159,6 +159,9 @@ const char kSecureSchemes[] = "secure-schemes";
// The browser process app model ID
const char kAppUserModelId[] = "app-user-model-id";
// The application path
const char kAppPath[] = "app-path";
// The command line switch versions of the options.
const char kBackgroundColor[] = "background-color";
const char kPreloadScript[] = "preload";

View file

@ -81,6 +81,7 @@ extern const char kStandardSchemes[];
extern const char kRegisterServiceWorkerSchemes[];
extern const char kSecureSchemes[];
extern const char kAppUserModelId[];
extern const char kAppPath[];
extern const char kBackgroundColor[];
extern const char kPreloadScript[];

View file

@ -498,6 +498,14 @@ Returns:
Emitted on 3-finger swipe. Possible directions are `up`, `right`, `down`, `left`.
#### Event: 'sheet-begin' _macOS_
Emitted when the window opens a sheet.
#### Event: 'sheet-end' _macOS_
Emitted when the window has closed a sheet.
### Static Methods
The `BrowserWindow` class has the following static methods:

View file

@ -28,6 +28,10 @@ effect on macOS.
Returns `Menu` - The application menu, if set, or `null`, if not set.
**Note:** The returned `Menu` instance doesn't support dynamic addition or
removal of menu items. [Instance properties](#instance-properties) can still
be dynamically modified.
#### `Menu.sendActionToFirstResponder(action)` _macOS_
* `action` String

View file

@ -12,7 +12,8 @@ rendered.
Unlike an `iframe`, the `webview` runs in a separate process than your
app. It doesn't have the same permissions as your web page and all interactions
between your app and embedded content will be asynchronous. This keeps your app
safe from the embedded content.
safe from the embedded content. **Note:** Most methods called on the
webview from the host page require a syncronous call to the main process.
For security purposes, `webview` can only be used in `BrowserWindow`s that have
`nodeIntegration` enabled.

View file

@ -10,6 +10,9 @@ Follow the guidelines below for building Electron on Windows.
* [Python 2.7](http://www.python.org/download/releases/2.7/)
* [Node.js](http://nodejs.org/download/)
* [Git](http://git-scm.com)
* [Debugging Tools for Windows](https://msdn.microsoft.com/en-us/library/windows/hardware/ff551063.aspx)
if you plan on creating a full distribution since `symstore.exe` is used for
creating a symbol store from `.pdb` files.
If you don't currently have a Windows installation,
[dev.microsoftedge.com](https://developer.microsoft.com/en-us/microsoft-edge/tools/vms/)

View file

@ -12,11 +12,7 @@ const {EventEmitter} = require('events')
Object.setPrototypeOf(App.prototype, EventEmitter.prototype)
let appPath = null
Object.assign(app, {
getAppPath () { return appPath },
setAppPath (path) { appPath = path },
setApplicationMenu (menu) {
return Menu.setApplicationMenu(menu)
},

View file

@ -56,6 +56,7 @@ electron.ipcRenderer.on('ELECTRON_INTERNAL_RENDERER_ASYNC_WEB_FRAME_METHOD', (ev
let nodeIntegration = 'false'
let preloadScript = null
let isBackgroundPage = false
let appPath = null
for (let arg of process.argv) {
if (arg.indexOf('--guest-instance-id=') === 0) {
// This is a guest web view.
@ -69,6 +70,8 @@ for (let arg of process.argv) {
preloadScript = arg.substr(arg.indexOf('=') + 1)
} else if (arg === '--background-page') {
isBackgroundPage = true
} else if (arg.indexOf('--app-path=') === 0) {
appPath = arg.substr(arg.indexOf('=') + 1)
}
}
@ -116,6 +119,11 @@ if (nodeIntegration === 'true') {
} else {
global.__filename = __filename
global.__dirname = __dirname
if (appPath) {
// Search for module under the app directory
module.paths = module.paths.concat(Module._nodeModulePaths(appPath))
}
}
// Redirect window.onerror to uncaughtException.

View file

@ -86,8 +86,6 @@ def main():
run_script('create-dist.py')
run_script('upload.py')
else:
if PLATFORM == 'win32':
os.environ['OUTPUT_TO_FILE'] = 'output.log'
run_script('build.py', ['-c', 'D'])
if PLATFORM == 'win32' or target_arch == 'x64':
run_script('test.py', ['--ci'])

View file

@ -1191,6 +1191,54 @@ describe('BrowserWindow module', function () {
})
})
describe('sheet-begin event', function () {
if (process.platform !== 'darwin') {
return
}
let sheet = null
afterEach(function () {
return closeWindow(sheet, {assertSingleWindow: false}).then(function () { sheet = null })
})
it('emits when window opens a sheet', function (done) {
w.show()
w.once('sheet-begin', function () {
sheet.close()
done()
})
sheet = new BrowserWindow({
modal: true,
parent: w
})
})
})
describe('sheet-end event', function () {
if (process.platform !== 'darwin') {
return
}
let sheet = null
afterEach(function () {
return closeWindow(sheet, {assertSingleWindow: false}).then(function () { sheet = null })
})
it('emits when window has closed a sheet', function (done) {
w.show()
sheet = new BrowserWindow({
modal: true,
parent: w
})
w.once('sheet-end', function () {
done()
})
sheet.close()
})
})
describe('beginFrameSubscription method', function () {
// This test is too slow, only test it on CI.
if (!isCI) return

View file

@ -1,60 +1,63 @@
const assert = require('assert')
const Module = require('module')
const path = require('path')
const temp = require('temp')
const {remote} = require('electron')
const {BrowserWindow} = remote
const {closeWindow} = require('./window-helpers')
describe('third-party module', function () {
describe('modules support', function () {
var fixtures = path.join(__dirname, 'fixtures')
temp.track()
if (process.platform !== 'win32' || process.execPath.toLowerCase().indexOf('\\out\\d\\') === -1) {
describe('runas', function () {
it('can be required in renderer', function () {
require('runas')
describe('third-party module', function () {
if (process.platform !== 'win32' || process.execPath.toLowerCase().indexOf('\\out\\d\\') === -1) {
describe('runas', function () {
it('can be required in renderer', function () {
require('runas')
})
it('can be required in node binary', function (done) {
var runas = path.join(fixtures, 'module', 'runas.js')
var child = require('child_process').fork(runas)
child.on('message', function (msg) {
assert.equal(msg, 'ok')
done()
})
})
})
it('can be required in node binary', function (done) {
var runas = path.join(fixtures, 'module', 'runas.js')
var child = require('child_process').fork(runas)
child.on('message', function (msg) {
assert.equal(msg, 'ok')
done()
describe('ffi', function () {
if (process.platform === 'win32') return
it('does not crash', function () {
var ffi = require('ffi')
var libm = ffi.Library('libm', {
ceil: ['double', ['double']]
})
assert.equal(libm.ceil(1.5), 2)
})
})
}
describe('q', function () {
var Q = require('q')
describe('Q.when', function () {
it('emits the fullfil callback', function (done) {
Q(true).then(function (val) {
assert.equal(val, true)
done()
})
})
})
})
describe('ffi', function () {
if (process.platform === 'win32') return
it('does not crash', function () {
var ffi = require('ffi')
var libm = ffi.Library('libm', {
ceil: ['double', ['double']]
describe('coffee-script', function () {
it('can be registered and used to require .coffee files', function () {
assert.doesNotThrow(function () {
require('coffee-script').register()
})
assert.equal(libm.ceil(1.5), 2)
assert.strictEqual(require('./fixtures/module/test.coffee'), true)
})
})
}
describe('q', function () {
var Q = require('q')
describe('Q.when', function () {
it('emits the fullfil callback', function (done) {
Q(true).then(function (val) {
assert.equal(val, true)
done()
})
})
})
})
describe('coffee-script', function () {
it('can be registered and used to require .coffee files', function () {
assert.doesNotThrow(function () {
require('coffee-script').register()
})
assert.strictEqual(require('./fixtures/module/test.coffee'), true)
})
})
describe('global variables', function () {
@ -76,56 +79,79 @@ describe('third-party module', function () {
})
})
})
})
describe('Module._nodeModulePaths', function () {
describe('when the path is inside the resources path', function () {
it('does not include paths outside of the resources path', function () {
let modulePath = process.resourcesPath
assert.deepEqual(Module._nodeModulePaths(modulePath), [
path.join(process.resourcesPath, 'node_modules')
])
describe('Module._nodeModulePaths', function () {
describe('when the path is inside the resources path', function () {
it('does not include paths outside of the resources path', function () {
let modulePath = process.resourcesPath
assert.deepEqual(Module._nodeModulePaths(modulePath), [
path.join(process.resourcesPath, 'node_modules')
])
modulePath = process.resourcesPath + '-foo'
let nodeModulePaths = Module._nodeModulePaths(modulePath)
assert(nodeModulePaths.includes(path.join(modulePath, 'node_modules')))
assert(nodeModulePaths.includes(path.join(modulePath, '..', 'node_modules')))
modulePath = process.resourcesPath + '-foo'
let nodeModulePaths = Module._nodeModulePaths(modulePath)
assert(nodeModulePaths.includes(path.join(modulePath, 'node_modules')))
assert(nodeModulePaths.includes(path.join(modulePath, '..', 'node_modules')))
modulePath = path.join(process.resourcesPath, 'foo')
assert.deepEqual(Module._nodeModulePaths(modulePath), [
path.join(process.resourcesPath, 'foo', 'node_modules'),
path.join(process.resourcesPath, 'node_modules')
])
modulePath = path.join(process.resourcesPath, 'foo')
assert.deepEqual(Module._nodeModulePaths(modulePath), [
path.join(process.resourcesPath, 'foo', 'node_modules'),
path.join(process.resourcesPath, 'node_modules')
])
modulePath = path.join(process.resourcesPath, 'node_modules', 'foo')
assert.deepEqual(Module._nodeModulePaths(modulePath), [
path.join(process.resourcesPath, 'node_modules', 'foo', 'node_modules'),
path.join(process.resourcesPath, 'node_modules')
])
modulePath = path.join(process.resourcesPath, 'node_modules', 'foo')
assert.deepEqual(Module._nodeModulePaths(modulePath), [
path.join(process.resourcesPath, 'node_modules', 'foo', 'node_modules'),
path.join(process.resourcesPath, 'node_modules')
])
modulePath = path.join(process.resourcesPath, 'node_modules', 'foo', 'bar')
assert.deepEqual(Module._nodeModulePaths(modulePath), [
path.join(process.resourcesPath, 'node_modules', 'foo', 'bar', 'node_modules'),
path.join(process.resourcesPath, 'node_modules', 'foo', 'node_modules'),
path.join(process.resourcesPath, 'node_modules')
])
modulePath = path.join(process.resourcesPath, 'node_modules', 'foo', 'bar')
assert.deepEqual(Module._nodeModulePaths(modulePath), [
path.join(process.resourcesPath, 'node_modules', 'foo', 'bar', 'node_modules'),
path.join(process.resourcesPath, 'node_modules', 'foo', 'node_modules'),
path.join(process.resourcesPath, 'node_modules')
])
modulePath = path.join(process.resourcesPath, 'node_modules', 'foo', 'node_modules', 'bar')
assert.deepEqual(Module._nodeModulePaths(modulePath), [
path.join(process.resourcesPath, 'node_modules', 'foo', 'node_modules', 'bar', 'node_modules'),
path.join(process.resourcesPath, 'node_modules', 'foo', 'node_modules'),
path.join(process.resourcesPath, 'node_modules')
])
modulePath = path.join(process.resourcesPath, 'node_modules', 'foo', 'node_modules', 'bar')
assert.deepEqual(Module._nodeModulePaths(modulePath), [
path.join(process.resourcesPath, 'node_modules', 'foo', 'node_modules', 'bar', 'node_modules'),
path.join(process.resourcesPath, 'node_modules', 'foo', 'node_modules'),
path.join(process.resourcesPath, 'node_modules')
])
})
})
describe('when the path is outside the resources path', 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.resolve('/node_modules')
])
})
})
})
describe('when the path is outside the resources path', 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.resolve('/node_modules')
])
describe('require', () => {
describe('when loaded URL is not file: protocol', () => {
let w
beforeEach(() => {
w = new BrowserWindow({
show: false
})
})
afterEach(async () => {
await closeWindow(w)
w = null
})
it('searches for module under app directory', async () => {
w.loadURL('about:blank')
const result = await w.webContents.executeJavaScript('typeof require("q").when')
assert.equal(result, 'function')
})
})
})
})

View file

@ -85,7 +85,7 @@ describe('node feature', function () {
child.stdout.on('data', (chunk) => {
data += String(chunk)
})
child.on('exit', (code) => {
child.on('close', (code) => {
assert.equal(code, 0)
assert.equal(data, 'pipes stdio')
done()