Merge pull request #5684 from electron/webview-visibilitychange

Support document visibility and events in webviews
This commit is contained in:
Cheng Zhao 2016-05-26 01:07:24 +00:00
commit 4ea7602871
8 changed files with 80 additions and 13 deletions

View file

@ -14,22 +14,12 @@ using atom::WebContentsPreferences;
namespace {
atom::WebViewManager* GetWebViewManager(content::WebContents* web_contents) {
auto context = web_contents->GetBrowserContext();
if (context) {
auto manager = context->GetGuestManager();
return static_cast<atom::WebViewManager*>(manager);
} else {
return nullptr;
}
}
void AddGuest(int guest_instance_id,
int element_instance_id,
content::WebContents* embedder,
content::WebContents* guest_web_contents,
const base::DictionaryValue& options) {
auto manager = GetWebViewManager(embedder);
auto manager = atom::WebViewManager::GetWebViewManager(embedder);
if (manager)
manager->AddGuest(guest_instance_id, element_instance_id, embedder,
guest_web_contents);
@ -38,7 +28,7 @@ void AddGuest(int guest_instance_id,
}
void RemoveGuest(content::WebContents* embedder, int guest_instance_id) {
auto manager = GetWebViewManager(embedder);
auto manager = atom::WebViewManager::GetWebViewManager(embedder);
if (manager)
manager->RemoveGuest(guest_instance_id);
}

View file

@ -9,6 +9,7 @@
#include <vector>
#include "atom/browser/native_window.h"
#include "atom/browser/web_view_manager.h"
#include "atom/common/native_mate_converters/value_converter.h"
#include "atom/common/options_switches.h"
#include "base/command_line.h"
@ -130,7 +131,7 @@ void WebContentsPreferences::AppendExtraCommandLineSwitches(
base::DoubleToString(zoom_factor));
// --guest-instance-id, which is used to identify guest WebContents.
int guest_instance_id;
int guest_instance_id = 0;
if (web_preferences.GetInteger(options::kGuestInstanceID, &guest_instance_id))
command_line->AppendSwitchASCII(switches::kGuestInstanceID,
base::IntToString(guest_instance_id));
@ -157,6 +158,17 @@ void WebContentsPreferences::AppendExtraCommandLineSwitches(
// The initial visibility state.
NativeWindow* window = NativeWindow::FromWebContents(web_contents);
// Use embedder window for webviews
if (guest_instance_id && !window) {
auto manager = WebViewManager::GetWebViewManager(web_contents);
if (manager) {
auto embedder = manager->GetEmbedder(guest_instance_id);
if (embedder)
window = NativeWindow::FromWebContents(embedder);
}
}
if (window) {
bool visible = window->IsVisible() && !window->IsMinimized();
if (!visible) // Default state is visible.

View file

@ -42,6 +42,13 @@ void WebViewManager::RemoveGuest(int guest_instance_id) {
}
}
content::WebContents* WebViewManager::GetEmbedder(int guest_instance_id) {
if (ContainsKey(web_contents_embedder_map_, guest_instance_id))
return web_contents_embedder_map_[guest_instance_id].embedder;
else
return nullptr;
}
content::WebContents* WebViewManager::GetGuestByInstanceID(
int owner_process_id,
int element_instance_id) {
@ -65,4 +72,16 @@ bool WebViewManager::ForEachGuest(content::WebContents* embedder_web_contents,
return false;
}
// static
WebViewManager* WebViewManager::GetWebViewManager(
content::WebContents* web_contents) {
auto context = web_contents->GetBrowserContext();
if (context) {
auto manager = context->GetGuestManager();
return static_cast<WebViewManager*>(manager);
} else {
return nullptr;
}
}
} // namespace atom

View file

@ -21,6 +21,9 @@ class WebViewManager : public content::BrowserPluginGuestManager {
content::WebContents* embedder,
content::WebContents* web_contents);
void RemoveGuest(int guest_instance_id);
content::WebContents* GetEmbedder(int guest_instance_id);
static WebViewManager* GetWebViewManager(content::WebContents* web_contents);
protected:
// content::BrowserPluginGuestManager:

View file

@ -42,6 +42,11 @@ var WebViewImpl = (function () {
this.webviewNode.setZoomLevel(zoomLevel)
}
webFrame.on('zoom-level-changed', this.onZoomLevelChanged)
this.onVisibilityChanged = (event, visibilityState) => {
this.webviewNode.send('ELECTRON_RENDERER_WINDOW_VISIBILITY_CHANGE', visibilityState)
}
ipcRenderer.on('ELECTRON_RENDERER_WINDOW_VISIBILITY_CHANGE', this.onVisibilityChanged)
}
WebViewImpl.prototype.createBrowserPluginNode = function () {
@ -56,6 +61,7 @@ var WebViewImpl = (function () {
WebViewImpl.prototype.reset = function () {
// Unlisten the zoom-level-changed event.
webFrame.removeListener('zoom-level-changed', this.onZoomLevelChanged)
ipcRenderer.removeListener('ELECTRON_RENDERER_WINDOW_VISIBILITY_CHANGE', this.onVisibilityChanged)
// If guestInstanceId is defined then the <webview> has navigated and has
// already picked up a partition ID. Thus, we need to reset the initialization

View file

@ -0,0 +1,11 @@
<html>
<body>
<script type="text/javascript" charset="utf-8">
const {ipcRenderer} = require('electron')
ipcRenderer.send('pong', document.visibilityState, document.hidden)
document.addEventListener('visibilitychange', function () {
ipcRenderer.send('pong', document.visibilityState, document.hidden)
})
</script>
</body>
</html>

View file

@ -0,0 +1,5 @@
<html>
<body>
<webview nodeintegration src="visibilitychange.html"/>
</body>
</html>

View file

@ -867,4 +867,25 @@ describe('<webview> tag', function () {
})
w.loadURL('file://' + fixtures + '/pages/webview-zoom-factor.html')
})
it('inherits the parent window visibility state and receives visibilitychange events', function (done) {
w = new BrowserWindow({
show: false
})
ipcMain.once('pong', function (event, visibilityState, hidden) {
assert.equal(visibilityState, 'hidden')
assert.equal(hidden, true)
w.webContents.send('ELECTRON_RENDERER_WINDOW_VISIBILITY_CHANGE', 'visible')
ipcMain.once('pong', function (event, visibilityState, hidden) {
assert.equal(visibilityState, 'visible')
assert.equal(hidden, false)
done()
})
})
w.loadURL('file://' + fixtures + '/pages/webview-visibilitychange.html')
})
})