diff --git a/docs/api/web-view-tag.md b/docs/api/web-view-tag.md
index 595e32353e2d..0c8c1bb94cb0 100644
--- a/docs/api/web-view-tag.md
+++ b/docs/api/web-view-tag.md
@@ -194,6 +194,20 @@ value will fail with a DOM exception.
If "on", the guest page will be allowed to open new windows.
+### `webpreferences`
+
+```html
+
+```
+
+A list of strings which specifies the web preferences to be set on the webview, separated by `,`.
+The full list of supported preference strings can be found in [BrowserWindow](browser-window.md#new-browserwindowoptions).
+
+The string follows the same format as the features string in `window.open`.
+A name by itself is given a `true` boolean value.
+A preference can be set to another value by including an `=`, followed by the value.
+Special values `yes` and `1` are interpreted as `true`, while `no` and `0` are interpreted as `false`.
+
### `blinkfeatures`
```html
diff --git a/filenames.gypi b/filenames.gypi
index f1ee8d069c34..ed1329b9bf98 100644
--- a/filenames.gypi
+++ b/filenames.gypi
@@ -48,6 +48,7 @@
'lib/common/api/native-image.js',
'lib/common/api/shell.js',
'lib/common/init.js',
+ 'lib/common/parse-features-string.js',
'lib/common/reset-search-paths.js',
'lib/renderer/chrome-api.js',
'lib/renderer/content-scripts-injector.js',
diff --git a/lib/browser/guest-view-manager.js b/lib/browser/guest-view-manager.js
index df2589a9bcf5..2f8ffefebc1c 100644
--- a/lib/browser/guest-view-manager.js
+++ b/lib/browser/guest-view-manager.js
@@ -2,6 +2,7 @@
const ipcMain = require('electron').ipcMain
const webContents = require('electron').webContents
+const parseFeaturesString = require('../common/parse-features-string')
// Doesn't exist in early initialization.
let webViewManager = null
@@ -184,6 +185,18 @@ const attachGuest = function (embedder, elementInstanceId, guestInstanceId, para
disableBlinkFeatures: params.disableblinkfeatures
}
+ // parse the 'webpreferences' attribute string, if set
+ // this uses the same parsing rules as window.open uses for its features
+ if (typeof params.webpreferences === 'string') {
+ parseFeaturesString(params.webpreferences, function (key, value) {
+ if (value === undefined) {
+ // no value was specified, default it to true
+ value = true
+ }
+ webPreferences[key] = value
+ })
+ }
+
if (params.preload) {
webPreferences.preloadURL = params.preload
}
diff --git a/lib/common/parse-features-string.js b/lib/common/parse-features-string.js
new file mode 100644
index 000000000000..a700617e6c9e
--- /dev/null
+++ b/lib/common/parse-features-string.js
@@ -0,0 +1,18 @@
+// parses a feature string that has the format used in window.open()
+// - `features` input string
+// - `emit` function(key, value) - called for each parsed KV
+module.exports = function parseFeaturesString (features, emit) {
+ // split the string by ','
+ features.split(/,\s*/).forEach((feature) => {
+ // expected form is either a key by itself or a key/value pair in the form of
+ // 'key=value'
+ let [key, value] = feature.split(/\s*=/)
+ if (!key) return
+
+ // interpret the value as a boolean, if possible
+ value = (value === 'yes' || value === '1') ? true : (value === 'no' || value === '0') ? false : value
+
+ // emit the parsed pair
+ emit(key, value)
+ })
+}
diff --git a/lib/renderer/override.js b/lib/renderer/override.js
index 9358a06a09d6..6b5e0e1615dd 100644
--- a/lib/renderer/override.js
+++ b/lib/renderer/override.js
@@ -2,6 +2,7 @@
const ipcRenderer = require('electron').ipcRenderer
const remote = require('electron').remote
+const parseFeaturesString = require('../common/parse-features-string')
// Helper function to resolve relative url.
var a = window.top.document.createElement('a')
@@ -88,7 +89,7 @@ if (process.guestInstanceId == null) {
// Make the browser window or guest view emit "new-window" event.
window.open = function (url, frameName, features) {
- var feature, guestId, i, j, len, len1, name, options, ref1, ref2, value, additionalFeatures
+ var guestId, j, len1, name, options, additionalFeatures
if (frameName == null) {
frameName = ''
}
@@ -104,27 +105,21 @@ window.open = function (url, frameName, features) {
// Used to store additional features
additionalFeatures = []
- // Make sure to get rid of excessive whitespace in the property name
- ref1 = features.split(/,\s*/)
- for (i = 0, len = ref1.length; i < len; i++) {
- feature = ref1[i]
- ref2 = feature.split(/\s*=/)
- name = ref2[0]
- value = ref2[1]
- value = value === 'yes' || value === '1' ? true : value === 'no' || value === '0' ? false : value
+ // Parse the features
+ parseFeaturesString(features, function (key, value) {
if (value === undefined) {
- additionalFeatures.push(feature)
+ additionalFeatures.push(key)
} else {
- if (webPreferences.includes(name)) {
+ if (webPreferences.includes(key)) {
if (options.webPreferences == null) {
options.webPreferences = {}
}
- options.webPreferences[name] = value
+ options.webPreferences[key] = value
} else {
- options[name] = value
+ options[key] = value
}
}
- }
+ })
if (options.left) {
if (options.x == null) {
options.x = options.left
diff --git a/lib/renderer/web-view/web-view-attributes.js b/lib/renderer/web-view/web-view-attributes.js
index 3bbc83311124..f87fca312238 100644
--- a/lib/renderer/web-view/web-view-attributes.js
+++ b/lib/renderer/web-view/web-view-attributes.js
@@ -312,6 +312,13 @@ class DisableBlinkFeaturesAttribute extends WebViewAttribute {
}
}
+// Attribute that specifies the web preferences to be enabled.
+class WebPreferencesAttribute extends WebViewAttribute {
+ constructor (webViewImpl) {
+ super(webViewConstants.ATTRIBUTE_WEBPREFERENCES, webViewImpl)
+ }
+}
+
// Sets up all of the webview attributes.
WebViewImpl.prototype.setupWebViewAttributes = function () {
this.attributes = {}
@@ -328,6 +335,7 @@ WebViewImpl.prototype.setupWebViewAttributes = function () {
this.attributes[webViewConstants.ATTRIBUTE_BLINKFEATURES] = new BlinkFeaturesAttribute(this)
this.attributes[webViewConstants.ATTRIBUTE_DISABLEBLINKFEATURES] = new DisableBlinkFeaturesAttribute(this)
this.attributes[webViewConstants.ATTRIBUTE_GUESTINSTANCE] = new GuestInstanceAttribute(this)
+ this.attributes[webViewConstants.ATTRIBUTE_WEBPREFERENCES] = new WebPreferencesAttribute(this)
const autosizeAttributes = [webViewConstants.ATTRIBUTE_MAXHEIGHT, webViewConstants.ATTRIBUTE_MAXWIDTH, webViewConstants.ATTRIBUTE_MINHEIGHT, webViewConstants.ATTRIBUTE_MINWIDTH]
autosizeAttributes.forEach((attribute) => {
diff --git a/lib/renderer/web-view/web-view-constants.js b/lib/renderer/web-view/web-view-constants.js
index 5aed6d5ea9e4..80fcaf91f24b 100644
--- a/lib/renderer/web-view/web-view-constants.js
+++ b/lib/renderer/web-view/web-view-constants.js
@@ -18,6 +18,7 @@ module.exports = {
ATTRIBUTE_BLINKFEATURES: 'blinkfeatures',
ATTRIBUTE_DISABLEBLINKFEATURES: 'disableblinkfeatures',
ATTRIBUTE_GUESTINSTANCE: 'guestinstance',
+ ATTRIBUTE_WEBPREFERENCES: 'webpreferences',
// Internal attribute.
ATTRIBUTE_INTERNALINSTANCEID: 'internalinstanceid',
diff --git a/spec/webview-spec.js b/spec/webview-spec.js
index 1c49688adeb8..059fc7228889 100644
--- a/spec/webview-spec.js
+++ b/spec/webview-spec.js
@@ -406,6 +406,33 @@ describe(' tag', function () {
})
})
+ describe('webpreferences attribute', function () {
+ it('can enable nodeintegration', function (done) {
+ webview.addEventListener('console-message', function (e) {
+ assert.equal(e.message, 'function object object')
+ done()
+ })
+ webview.setAttribute('webpreferences', 'nodeIntegration')
+ webview.src = 'file://' + fixtures + '/pages/d.html'
+ document.body.appendChild(webview)
+ })
+
+ it('can disables web security and enable nodeintegration', function (done) {
+ var jqueryPath = path.join(__dirname, '/static/jquery-2.0.3.min.js')
+ var src = ` `
+ var encoded = btoa(unescape(encodeURIComponent(src)))
+ var listener = function (e) {
+ assert.equal(e.message, 'ok function')
+ webview.removeEventListener('console-message', listener)
+ done()
+ }
+ webview.addEventListener('console-message', listener)
+ webview.setAttribute('webpreferences', 'webSecurity=no, nodeIntegration=yes')
+ webview.src = 'data:text/html;base64,' + encoded
+ document.body.appendChild(webview)
+ })
+ })
+
describe('new-window event', function () {
if (process.env.TRAVIS === 'true' && process.platform === 'darwin') {
return