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");
if (info.plugins)
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
storagePartitionId: params.storagePartitionId
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.
embedder.once 'render-view-deleted', ->

View file

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

View file

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

View file

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

View file

@ -66,6 +66,9 @@ const char kEnablePlugins[] = "enable-plugins";
// Instancd ID of guest WebContents.
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.
const char kExperimentalFeatures[] = "experimental-features";
const char kExperimentalCanvasFeatures[] = "experimental-canvas-features";

View file

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

View file

@ -31,6 +31,8 @@ for arg in process.argv
require('web-frame').setName 'ATOM_SHELL_GUEST_WEB_VIEW'
else if arg.indexOf('--node-integration=') == 0
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:'
# Override some inspector APIs.
@ -86,3 +88,6 @@ else
delete global.process
delete global.setImmediate
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_NODEINTEGRATION = 'nodeintegration'
WEB_VIEW_ATTRIBUTE_PLUGINS = 'plugins'
WEB_VIEW_ATTRIBUTE_PRELOAD = 'preload'
AUTO_SIZE_ATTRIBUTES = [
WEB_VIEW_ATTRIBUTE_AUTOSIZE,
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 ' +
'when the page has finished loading.'
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.
class Partition
@ -379,6 +382,17 @@ class WebView
storagePartitionId: storagePartitionId
nodeIntegration: @webviewNode.hasAttribute WEB_VIEW_ATTRIBUTE_NODEINTEGRATION
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) =>
@pendingGuestCreation = false
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.
### 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
### `<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"
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', ->
it 'emits when window.open is called', (done) ->
webview.addEventListener 'new-window', (e) ->