Merge pull request #794 from atom/webivew-preload

Add "preload" attribute for <webview>
This commit is contained in:
Cheng Zhao 2014-11-06 16:04:36 +08:00
commit 111dcbac25
13 changed files with 71 additions and 3 deletions

View file

@ -156,6 +156,10 @@ void AtomBrowserClient::AppendExtraCommandLineSwitches(
info.node_integration ? "true" : "false"); info.node_integration ? "true" : "false");
if (info.plugins) if (info.plugins)
command_line->AppendSwitch(switches::kEnablePlugins); command_line->AppendSwitch(switches::kEnablePlugins);
if (!info.preload_script.empty())
command_line->AppendSwitchPath(
switches::kPreloadScript,
info.preload_script);
} }
} }

View file

@ -33,7 +33,8 @@ createGuest = (embedder, params) ->
guestInstanceId: id guestInstanceId: id
storagePartitionId: params.storagePartitionId storagePartitionId: params.storagePartitionId
guestInstances[id] = {guest, embedder} guestInstances[id] = {guest, embedder}
webViewManager.addGuest id, embedder, guest, params.nodeIntegration, params.plugins preload = params.preload ? ''
webViewManager.addGuest id, embedder, guest, params.nodeIntegration, params.plugins, preload
# Destroy guest when the embedder is gone. # Destroy guest when the embedder is gone.
embedder.once 'render-view-deleted', -> embedder.once 'render-view-deleted', ->

View file

@ -7,12 +7,14 @@
#include "atom/browser/api/atom_api_web_contents.h" #include "atom/browser/api/atom_api_web_contents.h"
#include "atom/browser/atom_browser_context.h" #include "atom/browser/atom_browser_context.h"
#include "atom/browser/web_view/web_view_renderer_state.h" #include "atom/browser/web_view/web_view_renderer_state.h"
#include "atom/common/native_mate_converters/gurl_converter.h"
#include "base/bind.h" #include "base/bind.h"
#include "base/stl_util.h" #include "base/stl_util.h"
#include "content/public/browser/browser_thread.h" #include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_process_host.h" #include "content/public/browser/render_process_host.h"
#include "native_mate/dictionary.h" #include "native_mate/dictionary.h"
#include "native_mate/object_template_builder.h" #include "native_mate/object_template_builder.h"
#include "net/base/filename_util.h"
#include "atom/common/node_includes.h" #include "atom/common/node_includes.h"
@ -44,12 +46,14 @@ void WebViewManager::AddGuest(int guest_instance_id,
content::WebContents* embedder, content::WebContents* embedder,
content::WebContents* web_contents, content::WebContents* web_contents,
bool node_integration, bool node_integration,
bool plugins) { bool plugins,
const GURL& preload_url) {
web_contents_map_[guest_instance_id] = { web_contents, embedder }; web_contents_map_[guest_instance_id] = { web_contents, embedder };
WebViewRendererState::WebViewInfo web_view_info = { WebViewRendererState::WebViewInfo web_view_info = {
guest_instance_id, node_integration, plugins guest_instance_id, node_integration, plugins
}; };
net::FileURLToFilePath(preload_url, &web_view_info.preload_script);
content::BrowserThread::PostTask( content::BrowserThread::PostTask(
content::BrowserThread::IO, content::BrowserThread::IO,
FROM_HERE, FROM_HERE,

View file

@ -24,7 +24,8 @@ class WebViewManager : public content::BrowserPluginGuestManager {
content::WebContents* embedder, content::WebContents* embedder,
content::WebContents* web_contents, content::WebContents* web_contents,
bool node_integration, bool node_integration,
bool plugins); bool plugins,
const GURL& preload_url);
void RemoveGuest(int guest_instance_id); void RemoveGuest(int guest_instance_id);
protected: protected:

View file

@ -9,6 +9,7 @@
#include <string> #include <string>
#include <utility> #include <utility>
#include "base/files/file_path.h"
#include "base/memory/singleton.h" #include "base/memory/singleton.h"
namespace atom { namespace atom {
@ -23,6 +24,7 @@ class WebViewRendererState {
int guest_instance_id; int guest_instance_id;
bool node_integration; bool node_integration;
bool plugins; bool plugins;
base::FilePath preload_script;
}; };
static WebViewRendererState* GetInstance(); static WebViewRendererState* GetInstance();

View file

@ -66,6 +66,9 @@ const char kEnablePlugins[] = "enable-plugins";
// Instancd ID of guest WebContents. // Instancd ID of guest WebContents.
const char kGuestInstanceID[] = "guest-instance-id"; const char kGuestInstanceID[] = "guest-instance-id";
// Script that will be loaded by guest WebContents before other scripts.
const char kPreloadScript[] = "preload-script";
// Web runtime features. // Web runtime features.
const char kExperimentalFeatures[] = "experimental-features"; const char kExperimentalFeatures[] = "experimental-features";
const char kExperimentalCanvasFeatures[] = "experimental-canvas-features"; const char kExperimentalCanvasFeatures[] = "experimental-canvas-features";

View file

@ -38,6 +38,7 @@ extern const char kDarkTheme[];
extern const char kDirectWrite[]; extern const char kDirectWrite[];
extern const char kEnablePlugins[]; extern const char kEnablePlugins[];
extern const char kGuestInstanceID[]; extern const char kGuestInstanceID[];
extern const char kPreloadScript[];
extern const char kExperimentalFeatures[]; extern const char kExperimentalFeatures[];
extern const char kExperimentalCanvasFeatures[]; extern const char kExperimentalCanvasFeatures[];

View file

@ -31,6 +31,8 @@ for arg in process.argv
require('web-frame').setName 'ATOM_SHELL_GUEST_WEB_VIEW' require('web-frame').setName 'ATOM_SHELL_GUEST_WEB_VIEW'
else if arg.indexOf('--node-integration=') == 0 else if arg.indexOf('--node-integration=') == 0
nodeIntegration = arg.substr arg.indexOf('=') + 1 nodeIntegration = arg.substr arg.indexOf('=') + 1
else if arg.indexOf('--preload-script=') == 0
preloadScript = arg.substr arg.indexOf('=') + 1
if location.protocol is 'chrome-devtools:' if location.protocol is 'chrome-devtools:'
# Override some inspector APIs. # Override some inspector APIs.
@ -86,3 +88,6 @@ else
delete global.process delete global.process
delete global.setImmediate delete global.setImmediate
delete global.clearImmediate delete global.clearImmediate
# Load the script specfied by the "preload" attribute.
require preloadScript if preloadScript

View file

@ -21,6 +21,7 @@ WEB_VIEW_ATTRIBUTE_MINWIDTH = 'minwidth'
WEB_VIEW_ATTRIBUTE_PARTITION = 'partition' WEB_VIEW_ATTRIBUTE_PARTITION = 'partition'
WEB_VIEW_ATTRIBUTE_NODEINTEGRATION = 'nodeintegration' WEB_VIEW_ATTRIBUTE_NODEINTEGRATION = 'nodeintegration'
WEB_VIEW_ATTRIBUTE_PLUGINS = 'plugins' WEB_VIEW_ATTRIBUTE_PLUGINS = 'plugins'
WEB_VIEW_ATTRIBUTE_PRELOAD = 'preload'
AUTO_SIZE_ATTRIBUTES = [ AUTO_SIZE_ATTRIBUTES = [
WEB_VIEW_ATTRIBUTE_AUTOSIZE, WEB_VIEW_ATTRIBUTE_AUTOSIZE,
WEB_VIEW_ATTRIBUTE_MAXHEIGHT, WEB_VIEW_ATTRIBUTE_MAXHEIGHT,
@ -38,6 +39,8 @@ ERROR_MSG_CONTENTWINDOW_NOT_AVAILABLE = '<webview>: ' +
'contentWindow is not available at this time. It will become available ' + 'contentWindow is not available at this time. It will become available ' +
'when the page has finished loading.' 'when the page has finished loading.'
ERROR_MSG_INVALID_PARTITION_ATTRIBUTE = 'Invalid partition attribute.' ERROR_MSG_INVALID_PARTITION_ATTRIBUTE = 'Invalid partition attribute.'
ERROR_MSG_INVALID_PRELOAD_ATTRIBUTE =
'Only "file:" or "asar:" protocol is supported in "preload" attribute.'
# Represents the state of the storage partition. # Represents the state of the storage partition.
class Partition class Partition
@ -379,6 +382,17 @@ class WebView
storagePartitionId: storagePartitionId storagePartitionId: storagePartitionId
nodeIntegration: @webviewNode.hasAttribute WEB_VIEW_ATTRIBUTE_NODEINTEGRATION nodeIntegration: @webviewNode.hasAttribute WEB_VIEW_ATTRIBUTE_NODEINTEGRATION
plugins: @webviewNode.hasAttribute WEB_VIEW_ATTRIBUTE_PLUGINS plugins: @webviewNode.hasAttribute WEB_VIEW_ATTRIBUTE_PLUGINS
if @webviewNode.hasAttribute WEB_VIEW_ATTRIBUTE_PRELOAD
preload = @webviewNode.getAttribute WEB_VIEW_ATTRIBUTE_PRELOAD
# Get the full path.
a = document.createElement 'a'
a.href = preload
params.preload = a.href
# Only support file: or asar: protocol.
protocol = params.preload.substr 0, 5
unless protocol in ['file:', 'asar:']
delete params.preload
console.error ERROR_MSG_INVALID_PRELOAD_ATTRIBUTE
guestViewInternal.createGuest 'webview', params, (guestInstanceId) => guestViewInternal.createGuest 'webview', params, (guestInstanceId) =>
@pendingGuestCreation = false @pendingGuestCreation = false
unless @elementAttached unless @elementAttached

View file

@ -90,6 +90,20 @@ APIs like `require` and `process` to access low level system resources.
If "on", the guest page in `webview` will be able to use browser plugins. If "on", the guest page in `webview` will be able to use browser plugins.
### preload
```html
<webview src="https://www.github.com/" preload="./test.js"></webview>
```
Specifies a script that will be loaded before other scripts run in the guest
page. The protocol of script's URL must be either `file:` or `asar:`, because it
will be loaded by `require` in guest page under the hood.
When the guest page doesn't have node integration this script will still have
access to all Node APIs, but global objects injected by Node will be deleted
after this script has done execution.
## Methods ## Methods
### `<webview>`.getUrl() ### `<webview>`.getUrl()

1
spec/fixtures/module/preload.js vendored Normal file
View file

@ -0,0 +1 @@
console.log([typeof require, typeof module, typeof process].join(' '));

7
spec/fixtures/pages/e.html vendored Normal file
View file

@ -0,0 +1,7 @@
<html>
<body>
<script type="text/javascript" charset="utf-8">
console.log('Window script is loaded before preload script');
</script>
</body>
</html>

View file

@ -47,6 +47,17 @@ describe '<webview> tag', ->
webview.src = "file://#{fixtures}/pages/d.html" webview.src = "file://#{fixtures}/pages/d.html"
document.body.appendChild webview document.body.appendChild webview
describe 'preload attribute', ->
it 'loads the script before other scripts in window', (done) ->
listener = (e) ->
assert.equal e.message, 'function object object'
webview.removeEventListener 'console-message', listener
done()
webview.addEventListener 'console-message', listener
webview.setAttribute 'preload', "#{fixtures}/module/preload.js"
webview.src = "file://#{fixtures}/pages/e.html"
document.body.appendChild webview
describe 'new-window event', -> describe 'new-window event', ->
it 'emits when window.open is called', (done) -> it 'emits when window.open is called', (done) ->
webview.addEventListener 'new-window', (e) -> webview.addEventListener 'new-window', (e) ->