From 07a4c5291980f6d0d22ee7600911562bd5cf4e3d Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Wed, 13 Apr 2016 21:36:43 +0900 Subject: [PATCH 1/4] Reduces the IPC messages used for visibilityState --- lib/browser/api/browser-window.js | 47 ++++++++++++------------------- lib/renderer/override.js | 39 ++++++++----------------- 2 files changed, 29 insertions(+), 57 deletions(-) diff --git a/lib/browser/api/browser-window.js b/lib/browser/api/browser-window.js index 694cbf6d66..80c1f29eb2 100644 --- a/lib/browser/api/browser-window.js +++ b/lib/browser/api/browser-window.js @@ -78,19 +78,23 @@ BrowserWindow.prototype._init = function () { app.emit('browser-window-focus', event, this) }) - // Evented visibilityState changes - this.on('show', () => { - this.webContents.send('ELECTRON_RENDERER_WINDOW_VISIBILITY_CHANGE', this.isVisible(), this.isMinimized()) - }) - this.on('hide', () => { - this.webContents.send('ELECTRON_RENDERER_WINDOW_VISIBILITY_CHANGE', this.isVisible(), this.isMinimized()) - }) - this.on('minimize', () => { - this.webContents.send('ELECTRON_RENDERER_WINDOW_VISIBILITY_CHANGE', this.isVisible(), this.isMinimized()) - }) - this.on('restore', () => { - this.webContents.send('ELECTRON_RENDERER_WINDOW_VISIBILITY_CHANGE', this.isVisible(), this.isMinimized()) - }) + // Subscribe to visibilityState changes and pass to renderer process. + let isVisible = false + let visibilityChanged = () => { + let newState = this.isVisible() && !this.isMinimized() + if (isVisible != newState) { + isVisible = newState + this.webContents.send('ELECTRON_RENDERER_WINDOW_VISIBILITY_CHANGE', isVisible ? 'visible' : 'hidden') + } + } + this.on('show', visibilityChanged) + this.on('hide', visibilityChanged) + this.on('minimize', visibilityChanged) + this.on('restore', visibilityChanged) + this.on('maximize', visibilityChanged) + + // Make renderer process have correct initial state. + visibilityChanged() // Notify the creation of the window. app.emit('browser-window-created', {}, this) @@ -105,6 +109,7 @@ BrowserWindow.prototype._init = function () { this.webContents.on('devtools-closed', () => { this.emit('devtools-closed') }) + Object.defineProperty(this, 'devToolsWebContents', { enumerable: true, configurable: false, @@ -195,37 +200,21 @@ BrowserWindow.prototype.inspectServiceWorker = function () { } // Deprecated. - deprecate.member(BrowserWindow, 'undo', 'webContents') - deprecate.member(BrowserWindow, 'redo', 'webContents') - deprecate.member(BrowserWindow, 'cut', 'webContents') - deprecate.member(BrowserWindow, 'copy', 'webContents') - deprecate.member(BrowserWindow, 'paste', 'webContents') - deprecate.member(BrowserWindow, 'selectAll', 'webContents') - deprecate.member(BrowserWindow, 'reloadIgnoringCache', 'webContents') - deprecate.member(BrowserWindow, 'isLoading', 'webContents') - deprecate.member(BrowserWindow, 'isWaitingForResponse', 'webContents') - deprecate.member(BrowserWindow, 'stop', 'webContents') - deprecate.member(BrowserWindow, 'isCrashed', 'webContents') - deprecate.member(BrowserWindow, 'print', 'webContents') - deprecate.member(BrowserWindow, 'printToPDF', 'webContents') - deprecate.rename(BrowserWindow, 'restart', 'reload') - deprecate.rename(BrowserWindow, 'loadUrl', 'loadURL') - deprecate.rename(BrowserWindow, 'getUrl', 'getURL') BrowserWindow.prototype.executeJavaScriptInDevTools = deprecate('executeJavaScriptInDevTools', 'devToolsWebContents.executeJavaScript', function (code) { diff --git a/lib/renderer/override.js b/lib/renderer/override.js index 5f808d6630..ba46bdf51e 100644 --- a/lib/renderer/override.js +++ b/lib/renderer/override.js @@ -3,17 +3,6 @@ const ipcRenderer = require('electron').ipcRenderer const remote = require('electron').remote -// Cache browser window visibility -var _isVisible = true -var _isMinimized = false -var initWindow = function initWindow () { - var currentWindow - currentWindow = remote.getCurrentWindow() - _isVisible = currentWindow.isVisible() - _isMinimized = currentWindow.isMinimized() -} -initWindow() - // Helper function to resolve relative url. var a = window.top.document.createElement('a') @@ -200,17 +189,6 @@ if (process.openerId != null) { window.opener = BrowserWindowProxy.getOrCreate(process.openerId) } -ipcRenderer.on('ELECTRON_RENDERER_WINDOW_VISIBILITY_CHANGE', function (event, isVisible, isMinimized) { - var hasChanged = _isVisible !== isVisible || _isMinimized !== isMinimized - - if (hasChanged) { - _isVisible = isVisible - _isMinimized = isMinimized - - document.dispatchEvent(new Event('visibilitychange')) - } -}) - ipcRenderer.on('ELECTRON_GUEST_WINDOW_POSTMESSAGE', function (event, sourceId, message, sourceOrigin) { // Manually dispatch event instead of using postMessage because we also need to // set event.source. @@ -249,19 +227,24 @@ Object.defineProperty(window.history, 'length', { } }) +// Subscribe to visibilityState changes. +let cachedVisibilityState = 'hidden' +ipcRenderer.on('ELECTRON_RENDERER_WINDOW_VISIBILITY_CHANGE', function (event, visibilityState) { + if (cachedVisibilityState != visibilityState) { + cachedVisibilityState = visibilityState + document.dispatchEvent(new Event('visibilitychange')) + } +}) + // Make document.hidden and document.visibilityState return the correct value. Object.defineProperty(document, 'hidden', { get: function () { - return _isMinimized || !_isVisible + return cachedVisibilityState != 'visible' } }) Object.defineProperty(document, 'visibilityState', { get: function () { - if (_isVisible && !_isMinimized) { - return 'visible' - } else { - return 'hidden' - } + return cachedVisibilityState } }) From 43c44da50bb2e0bf38a0c6af632533e14baef525 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Wed, 13 Apr 2016 22:56:11 +0900 Subject: [PATCH 2/4] Correctly set initial visibilityState --- atom/browser/api/atom_api_web_contents.cc | 7 +++++++ atom/browser/api/atom_api_web_contents.h | 1 + atom/browser/web_contents_preferences.cc | 17 +++++++++++------ atom/common/options_switches.cc | 4 ++++ atom/common/options_switches.h | 2 ++ lib/browser/api/browser-window.js | 5 +++-- lib/renderer/init.js | 8 +++----- lib/renderer/override.js | 10 ++++++---- 8 files changed, 37 insertions(+), 17 deletions(-) diff --git a/atom/browser/api/atom_api_web_contents.cc b/atom/browser/api/atom_api_web_contents.cc index 81e2423a35..5530081961 100644 --- a/atom/browser/api/atom_api_web_contents.cc +++ b/atom/browser/api/atom_api_web_contents.cc @@ -1127,6 +1127,12 @@ bool WebContents::IsGuest() const { return type_ == WEB_VIEW; } +void WebContents::MergeWebPreferences(const base::DictionaryValue& extend) { + WebContentsPreferences* web_preferences = + WebContentsPreferences::FromWebContents(web_contents()); + web_preferences->Merge(extend); +} + v8::Local WebContents::GetWebPreferences(v8::Isolate* isolate) { WebContentsPreferences* web_preferences = WebContentsPreferences::FromWebContents(web_contents()); @@ -1221,6 +1227,7 @@ void WebContents::BuildPrototype(v8::Isolate* isolate, .SetMethod("endFrameSubscription", &WebContents::EndFrameSubscription) .SetMethod("setSize", &WebContents::SetSize) .SetMethod("isGuest", &WebContents::IsGuest) + .SetMethod("mergeWebPreferences", &WebContents::MergeWebPreferences) .SetMethod("getWebPreferences", &WebContents::GetWebPreferences) .SetMethod("getOwnerBrowserWindow", &WebContents::GetOwnerBrowserWindow) .SetMethod("hasServiceWorker", &WebContents::HasServiceWorker) diff --git a/atom/browser/api/atom_api_web_contents.h b/atom/browser/api/atom_api_web_contents.h index 0cb2a348e1..91b860bff9 100644 --- a/atom/browser/api/atom_api_web_contents.h +++ b/atom/browser/api/atom_api_web_contents.h @@ -144,6 +144,7 @@ class WebContents : public mate::TrackableObject, WindowOpenDisposition disposition); // Returns the web preferences of current WebContents. + void MergeWebPreferences(const base::DictionaryValue& extend); v8::Local GetWebPreferences(v8::Isolate* isolate); // Returns the owner window. diff --git a/atom/browser/web_contents_preferences.cc b/atom/browser/web_contents_preferences.cc index f36e7c076d..14bbf3e719 100644 --- a/atom/browser/web_contents_preferences.cc +++ b/atom/browser/web_contents_preferences.cc @@ -131,20 +131,25 @@ void WebContentsPreferences::AppendExtraCommandLineSwitches( // --guest-instance-id, which is used to identify guest WebContents. int guest_instance_id; if (web_preferences.GetInteger(options::kGuestInstanceID, &guest_instance_id)) - command_line->AppendSwitchASCII(switches::kGuestInstanceID, - base::IntToString(guest_instance_id)); + command_line->AppendSwitchASCII(switches::kGuestInstanceID, + base::IntToString(guest_instance_id)); // Pass the opener's window id. int opener_id; if (web_preferences.GetInteger(options::kOpenerID, &opener_id)) - command_line->AppendSwitchASCII(switches::kOpenerID, - base::IntToString(opener_id)); + command_line->AppendSwitchASCII(switches::kOpenerID, + base::IntToString(opener_id)); // Enable blink features. std::string blink_features; if (web_preferences.GetString(options::kBlinkFeatures, &blink_features)) - command_line->AppendSwitchASCII(::switches::kEnableBlinkFeatures, - blink_features); + command_line->AppendSwitchASCII(::switches::kEnableBlinkFeatures, + blink_features); + + // The initial visibility state. + std::string visibility; + if (web_preferences.GetString(options::kVisibilityState, &visibility)) + command_line->AppendSwitchASCII(switches::kVisibilityState, visibility); } // static diff --git a/atom/common/options_switches.cc b/atom/common/options_switches.cc index ce28cc98fa..bd9657eb37 100644 --- a/atom/common/options_switches.cc +++ b/atom/common/options_switches.cc @@ -106,6 +106,9 @@ const char kOpenerID[] = "openerId"; // Enable blink features. const char kBlinkFeatures[] = "blinkFeatures"; +// The initiali visibility state. +const char kVisibilityState[] = "visibilityState"; + } // namespace options namespace switches { @@ -149,6 +152,7 @@ const char kPreloadURL[] = "preload-url"; const char kNodeIntegration[] = "node-integration"; const char kGuestInstanceID[] = "guest-instance-id"; const char kOpenerID[] = "opener-id"; +const char kVisibilityState[] = "visibility-state"; // Widevine options // Path to Widevine CDM binaries. diff --git a/atom/common/options_switches.h b/atom/common/options_switches.h index 52d64c00d5..f7548c5388 100644 --- a/atom/common/options_switches.h +++ b/atom/common/options_switches.h @@ -56,6 +56,7 @@ extern const char kGuestInstanceID[]; extern const char kExperimentalFeatures[]; extern const char kExperimentalCanvasFeatures[]; extern const char kOpenerID[]; +extern const char kVisibilityState[]; extern const char kBlinkFeatures[]; } // namespace options @@ -83,6 +84,7 @@ extern const char kPreloadURL[]; extern const char kNodeIntegration[]; extern const char kGuestInstanceID[]; extern const char kOpenerID[]; +extern const char kVisibilityState[]; extern const char kWidevineCdmPath[]; extern const char kWidevineCdmVersion[]; diff --git a/lib/browser/api/browser-window.js b/lib/browser/api/browser-window.js index 80c1f29eb2..5e95aa2e01 100644 --- a/lib/browser/api/browser-window.js +++ b/lib/browser/api/browser-window.js @@ -79,7 +79,7 @@ BrowserWindow.prototype._init = function () { }) // Subscribe to visibilityState changes and pass to renderer process. - let isVisible = false + let isVisible = this.isVisible() && !this.isMinimized() let visibilityChanged = () => { let newState = this.isVisible() && !this.isMinimized() if (isVisible != newState) { @@ -94,7 +94,8 @@ BrowserWindow.prototype._init = function () { this.on('maximize', visibilityChanged) // Make renderer process have correct initial state. - visibilityChanged() + if (!isVisible) + this.webContents.mergeWebPreferences({visibilityState: 'hidden'}) // Notify the creation of the window. app.emit('browser-window-created', {}, this) diff --git a/lib/renderer/init.js b/lib/renderer/init.js index 02ac36c28e..689307ed68 100644 --- a/lib/renderer/init.js +++ b/lib/renderer/init.js @@ -47,11 +47,7 @@ electron.ipcRenderer.on('ELECTRON_INTERNAL_RENDERER_ASYNC_WEB_FRAME_METHOD', (ev // Process command line arguments. var nodeIntegration = 'false' var preloadScript = null - -var ref = process.argv -var i, len, arg -for (i = 0, len = ref.length; i < len; i++) { - arg = ref[i] +for (let arg of process.argv) { if (arg.indexOf('--guest-instance-id=') === 0) { // This is a guest web view. process.guestInstanceId = parseInt(arg.substr(arg.indexOf('=') + 1)) @@ -62,6 +58,8 @@ for (i = 0, len = ref.length; i < len; i++) { nodeIntegration = arg.substr(arg.indexOf('=') + 1) } else if (arg.indexOf('--preload=') === 0) { preloadScript = arg.substr(arg.indexOf('=') + 1) + } else if (arg.indexOf('--visibility-state=') === 0) { + process.visibilityState = arg.substr(arg.indexOf('=') + 1) } } diff --git a/lib/renderer/override.js b/lib/renderer/override.js index ba46bdf51e..4b86a74de7 100644 --- a/lib/renderer/override.js +++ b/lib/renderer/override.js @@ -5,7 +5,6 @@ const remote = require('electron').remote // Helper function to resolve relative url. var a = window.top.document.createElement('a') - var resolveURL = function (url) { a.href = url return a.href @@ -160,8 +159,6 @@ window.alert = function (message, title) { title: title, buttons: buttons }) - -// Alert should always return undefined. } // And the confirm(). @@ -227,8 +224,13 @@ Object.defineProperty(window.history, 'length', { } }) +// The initial visibilityState. +let cachedVisibilityState = 'visible' +if (process.visibilityState) { + cachedVisibilityState = process.visibilityState +} + // Subscribe to visibilityState changes. -let cachedVisibilityState = 'hidden' ipcRenderer.on('ELECTRON_RENDERER_WINDOW_VISIBILITY_CHANGE', function (event, visibilityState) { if (cachedVisibilityState != visibilityState) { cachedVisibilityState = visibilityState From 8f0e594007b805b0641eeb57a89ac50aa0de4653 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Wed, 13 Apr 2016 23:10:31 +0900 Subject: [PATCH 3/4] Fix lint warnings --- lib/browser/api/browser-window.js | 5 +++-- lib/renderer/override.js | 4 ++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/lib/browser/api/browser-window.js b/lib/browser/api/browser-window.js index 5e95aa2e01..0524c43942 100644 --- a/lib/browser/api/browser-window.js +++ b/lib/browser/api/browser-window.js @@ -82,7 +82,7 @@ BrowserWindow.prototype._init = function () { let isVisible = this.isVisible() && !this.isMinimized() let visibilityChanged = () => { let newState = this.isVisible() && !this.isMinimized() - if (isVisible != newState) { + if (isVisible !== newState) { isVisible = newState this.webContents.send('ELECTRON_RENDERER_WINDOW_VISIBILITY_CHANGE', isVisible ? 'visible' : 'hidden') } @@ -94,8 +94,9 @@ BrowserWindow.prototype._init = function () { this.on('maximize', visibilityChanged) // Make renderer process have correct initial state. - if (!isVisible) + if (!isVisible) { this.webContents.mergeWebPreferences({visibilityState: 'hidden'}) + } // Notify the creation of the window. app.emit('browser-window-created', {}, this) diff --git a/lib/renderer/override.js b/lib/renderer/override.js index 4b86a74de7..1d01d2b5b7 100644 --- a/lib/renderer/override.js +++ b/lib/renderer/override.js @@ -232,7 +232,7 @@ if (process.visibilityState) { // Subscribe to visibilityState changes. ipcRenderer.on('ELECTRON_RENDERER_WINDOW_VISIBILITY_CHANGE', function (event, visibilityState) { - if (cachedVisibilityState != visibilityState) { + if (cachedVisibilityState !== visibilityState) { cachedVisibilityState = visibilityState document.dispatchEvent(new Event('visibilitychange')) } @@ -241,7 +241,7 @@ ipcRenderer.on('ELECTRON_RENDERER_WINDOW_VISIBILITY_CHANGE', function (event, vi // Make document.hidden and document.visibilityState return the correct value. Object.defineProperty(document, 'hidden', { get: function () { - return cachedVisibilityState != 'visible' + return cachedVisibilityState !== 'visible' } }) From 31eb793fb00114e06efac10d38fd0798e65bde1b Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Thu, 14 Apr 2016 10:50:07 +0900 Subject: [PATCH 4/4] Avoid adding a new option to webPreferences --- atom/browser/api/atom_api_web_contents.cc | 7 ------- atom/browser/api/atom_api_web_contents.h | 1 - atom/browser/web_contents_preferences.cc | 10 +++++++--- atom/common/options_switches.cc | 4 ---- atom/common/options_switches.h | 2 -- lib/browser/api/browser-window.js | 5 ----- lib/renderer/init.js | 2 -- lib/renderer/override.js | 5 +---- 8 files changed, 8 insertions(+), 28 deletions(-) diff --git a/atom/browser/api/atom_api_web_contents.cc b/atom/browser/api/atom_api_web_contents.cc index 5530081961..81e2423a35 100644 --- a/atom/browser/api/atom_api_web_contents.cc +++ b/atom/browser/api/atom_api_web_contents.cc @@ -1127,12 +1127,6 @@ bool WebContents::IsGuest() const { return type_ == WEB_VIEW; } -void WebContents::MergeWebPreferences(const base::DictionaryValue& extend) { - WebContentsPreferences* web_preferences = - WebContentsPreferences::FromWebContents(web_contents()); - web_preferences->Merge(extend); -} - v8::Local WebContents::GetWebPreferences(v8::Isolate* isolate) { WebContentsPreferences* web_preferences = WebContentsPreferences::FromWebContents(web_contents()); @@ -1227,7 +1221,6 @@ void WebContents::BuildPrototype(v8::Isolate* isolate, .SetMethod("endFrameSubscription", &WebContents::EndFrameSubscription) .SetMethod("setSize", &WebContents::SetSize) .SetMethod("isGuest", &WebContents::IsGuest) - .SetMethod("mergeWebPreferences", &WebContents::MergeWebPreferences) .SetMethod("getWebPreferences", &WebContents::GetWebPreferences) .SetMethod("getOwnerBrowserWindow", &WebContents::GetOwnerBrowserWindow) .SetMethod("hasServiceWorker", &WebContents::HasServiceWorker) diff --git a/atom/browser/api/atom_api_web_contents.h b/atom/browser/api/atom_api_web_contents.h index 91b860bff9..0cb2a348e1 100644 --- a/atom/browser/api/atom_api_web_contents.h +++ b/atom/browser/api/atom_api_web_contents.h @@ -144,7 +144,6 @@ class WebContents : public mate::TrackableObject, WindowOpenDisposition disposition); // Returns the web preferences of current WebContents. - void MergeWebPreferences(const base::DictionaryValue& extend); v8::Local GetWebPreferences(v8::Isolate* isolate); // Returns the owner window. diff --git a/atom/browser/web_contents_preferences.cc b/atom/browser/web_contents_preferences.cc index 14bbf3e719..05286a2d3b 100644 --- a/atom/browser/web_contents_preferences.cc +++ b/atom/browser/web_contents_preferences.cc @@ -8,6 +8,7 @@ #include #include +#include "atom/browser/native_window.h" #include "atom/common/native_mate_converters/value_converter.h" #include "atom/common/options_switches.h" #include "base/command_line.h" @@ -147,9 +148,12 @@ void WebContentsPreferences::AppendExtraCommandLineSwitches( blink_features); // The initial visibility state. - std::string visibility; - if (web_preferences.GetString(options::kVisibilityState, &visibility)) - command_line->AppendSwitchASCII(switches::kVisibilityState, visibility); + NativeWindow* window = NativeWindow::FromWebContents(web_contents); + if (window) { + bool visible = window->IsVisible() && !window->IsMinimized(); + if (!visible) // Default state is visible. + command_line->AppendSwitch("hidden-page"); + } } // static diff --git a/atom/common/options_switches.cc b/atom/common/options_switches.cc index bd9657eb37..ce28cc98fa 100644 --- a/atom/common/options_switches.cc +++ b/atom/common/options_switches.cc @@ -106,9 +106,6 @@ const char kOpenerID[] = "openerId"; // Enable blink features. const char kBlinkFeatures[] = "blinkFeatures"; -// The initiali visibility state. -const char kVisibilityState[] = "visibilityState"; - } // namespace options namespace switches { @@ -152,7 +149,6 @@ const char kPreloadURL[] = "preload-url"; const char kNodeIntegration[] = "node-integration"; const char kGuestInstanceID[] = "guest-instance-id"; const char kOpenerID[] = "opener-id"; -const char kVisibilityState[] = "visibility-state"; // Widevine options // Path to Widevine CDM binaries. diff --git a/atom/common/options_switches.h b/atom/common/options_switches.h index f7548c5388..52d64c00d5 100644 --- a/atom/common/options_switches.h +++ b/atom/common/options_switches.h @@ -56,7 +56,6 @@ extern const char kGuestInstanceID[]; extern const char kExperimentalFeatures[]; extern const char kExperimentalCanvasFeatures[]; extern const char kOpenerID[]; -extern const char kVisibilityState[]; extern const char kBlinkFeatures[]; } // namespace options @@ -84,7 +83,6 @@ extern const char kPreloadURL[]; extern const char kNodeIntegration[]; extern const char kGuestInstanceID[]; extern const char kOpenerID[]; -extern const char kVisibilityState[]; extern const char kWidevineCdmPath[]; extern const char kWidevineCdmVersion[]; diff --git a/lib/browser/api/browser-window.js b/lib/browser/api/browser-window.js index 0524c43942..c9d63278f9 100644 --- a/lib/browser/api/browser-window.js +++ b/lib/browser/api/browser-window.js @@ -93,11 +93,6 @@ BrowserWindow.prototype._init = function () { this.on('restore', visibilityChanged) this.on('maximize', visibilityChanged) - // Make renderer process have correct initial state. - if (!isVisible) { - this.webContents.mergeWebPreferences({visibilityState: 'hidden'}) - } - // Notify the creation of the window. app.emit('browser-window-created', {}, this) diff --git a/lib/renderer/init.js b/lib/renderer/init.js index 689307ed68..a9f4acc5cb 100644 --- a/lib/renderer/init.js +++ b/lib/renderer/init.js @@ -58,8 +58,6 @@ for (let arg of process.argv) { nodeIntegration = arg.substr(arg.indexOf('=') + 1) } else if (arg.indexOf('--preload=') === 0) { preloadScript = arg.substr(arg.indexOf('=') + 1) - } else if (arg.indexOf('--visibility-state=') === 0) { - process.visibilityState = arg.substr(arg.indexOf('=') + 1) } } diff --git a/lib/renderer/override.js b/lib/renderer/override.js index 1d01d2b5b7..db56eadd34 100644 --- a/lib/renderer/override.js +++ b/lib/renderer/override.js @@ -225,10 +225,7 @@ Object.defineProperty(window.history, 'length', { }) // The initial visibilityState. -let cachedVisibilityState = 'visible' -if (process.visibilityState) { - cachedVisibilityState = process.visibilityState -} +let cachedVisibilityState = process.argv.includes('--hidden-page') ? 'hidden' : 'visible' // Subscribe to visibilityState changes. ipcRenderer.on('ELECTRON_RENDERER_WINDOW_VISIBILITY_CHANGE', function (event, visibilityState) {