mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1196654 - navigator.mozBrowserElementProxy for access Browser API methods from the embedded, r=kanru, sr=sicking
This commit is contained in:
parent
65c6b2e305
commit
31d6fa527e
@ -382,6 +382,8 @@
|
||||
@RESPATH@/components/ConsoleAPIStorage.js
|
||||
@RESPATH@/components/BrowserElementParent.manifest
|
||||
@RESPATH@/components/BrowserElementParent.js
|
||||
@RESPATH@/components/BrowserElementProxy.manifest
|
||||
@RESPATH@/components/BrowserElementProxy.js
|
||||
@RESPATH@/components/ContactManager.js
|
||||
@RESPATH@/components/ContactManager.manifest
|
||||
@RESPATH@/components/PhoneNumberService.js
|
||||
|
@ -365,6 +365,8 @@
|
||||
@RESPATH@/components/ConsoleAPIStorage.js
|
||||
@RESPATH@/components/BrowserElementParent.manifest
|
||||
@RESPATH@/components/BrowserElementParent.js
|
||||
@RESPATH@/components/BrowserElementProxy.manifest
|
||||
@RESPATH@/components/BrowserElementProxy.js
|
||||
@RESPATH@/components/FeedProcessor.manifest
|
||||
@RESPATH@/components/FeedProcessor.js
|
||||
@RESPATH@/components/PackagedAppUtils.js
|
||||
|
@ -131,6 +131,11 @@ this.PermissionsTable = { geolocation: {
|
||||
privileged: ALLOW_ACTION,
|
||||
certified: ALLOW_ACTION
|
||||
},
|
||||
"browser:embedded-system-app": {
|
||||
app: DENY_ACTION,
|
||||
privileged: DENY_ACTION,
|
||||
certified: ALLOW_ACTION
|
||||
},
|
||||
bluetooth: {
|
||||
app: DENY_ACTION,
|
||||
privileged: DENY_ACTION,
|
||||
|
@ -85,6 +85,38 @@ const COMMAND_MAP = {
|
||||
|
||||
var global = this;
|
||||
|
||||
function BrowserElementProxyForwarder() {
|
||||
}
|
||||
|
||||
BrowserElementProxyForwarder.prototype = {
|
||||
init: function() {
|
||||
Services.obs.addObserver(this, "browser-element-api:proxy-call", false);
|
||||
addMessageListener("browser-element-api:proxy", this);
|
||||
},
|
||||
|
||||
uninit: function() {
|
||||
Services.obs.removeObserver(this, "browser-element-api:proxy-call", false);
|
||||
removeMessageListener("browser-element-api:proxy", this);
|
||||
},
|
||||
|
||||
// Observer callback receives messages from BrowserElementProxy.js
|
||||
observe: function(subject, topic, stringifedData) {
|
||||
if (subject !== content) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Forward it to BrowserElementParent.js
|
||||
sendAsyncMessage(topic, JSON.parse(stringifedData));
|
||||
},
|
||||
|
||||
// Message manager callback receives messages from BrowserElementParent.js
|
||||
receiveMessage: function(mmMsg) {
|
||||
// Forward it to BrowserElementProxy.js
|
||||
Services.obs.notifyObservers(
|
||||
content, mmMsg.name, JSON.stringify(mmMsg.json));
|
||||
}
|
||||
};
|
||||
|
||||
function BrowserElementChild() {
|
||||
// Maps outer window id --> weak ref to window. Used by modal dialog code.
|
||||
this._windowIDDict = {};
|
||||
@ -104,6 +136,8 @@ function BrowserElementChild() {
|
||||
this._pendingSetInputMethodActive = [];
|
||||
this._selectionStateChangedTarget = null;
|
||||
|
||||
this.forwarder = new BrowserElementProxyForwarder();
|
||||
|
||||
this._init();
|
||||
};
|
||||
|
||||
@ -288,6 +322,8 @@ BrowserElementChild.prototype = {
|
||||
OBSERVED_EVENTS.forEach((aTopic) => {
|
||||
Services.obs.addObserver(this, aTopic, false);
|
||||
});
|
||||
|
||||
this.forwarder.init();
|
||||
},
|
||||
|
||||
observe: function(subject, topic, data) {
|
||||
@ -327,6 +363,9 @@ BrowserElementChild.prototype = {
|
||||
OBSERVED_EVENTS.forEach((aTopic) => {
|
||||
Services.obs.removeObserver(this, aTopic);
|
||||
});
|
||||
|
||||
this.forwarder.uninit();
|
||||
this.forwarder = null;
|
||||
},
|
||||
|
||||
get _windowUtils() {
|
||||
@ -934,7 +973,7 @@ BrowserElementChild.prototype = {
|
||||
},
|
||||
|
||||
_getSystemCtxMenuData: function(elem) {
|
||||
let documentURI =
|
||||
let documentURI =
|
||||
docShell.QueryInterface(Ci.nsIWebNavigation).currentURI.spec;
|
||||
if ((elem instanceof Ci.nsIDOMHTMLAnchorElement && elem.href) ||
|
||||
(elem instanceof Ci.nsIDOMHTMLAreaElement && elem.href)) {
|
||||
|
@ -64,6 +64,177 @@ function defineDOMRequestMethod(msgName) {
|
||||
};
|
||||
}
|
||||
|
||||
function BrowserElementParentProxyCallHandler() {
|
||||
}
|
||||
|
||||
BrowserElementParentProxyCallHandler.prototype = {
|
||||
_frameElement: null,
|
||||
_mm: null,
|
||||
|
||||
MOZBROWSER_EVENT_NAMES: Object.freeze([
|
||||
"loadstart", "loadend", "close", "error", "firstpaint",
|
||||
"documentfirstpaint", "audioplaybackchange",
|
||||
"contextmenu", "securitychange", "locationchange",
|
||||
"iconchange", "scrollareachanged", "titlechange",
|
||||
"opensearch", "manifestchange", "metachange",
|
||||
"resize", "selectionstatechanged", "scrollviewchange",
|
||||
"caretstatechanged", "activitydone", "scroll", "opentab"]),
|
||||
|
||||
init: function(frameElement, mm) {
|
||||
this._frameElement = frameElement;
|
||||
this._mm = mm;
|
||||
this.innerWindowIDSet = new Set();
|
||||
|
||||
mm.addMessageListener("browser-element-api:proxy-call", this);
|
||||
},
|
||||
|
||||
// Message manager callback receives messages from BrowserElementProxy.js
|
||||
receiveMessage: function(mmMsg) {
|
||||
let data = mmMsg.json;
|
||||
|
||||
let mm;
|
||||
try {
|
||||
mm = mmMsg.target.QueryInterface(Ci.nsIFrameLoaderOwner)
|
||||
.frameLoader.messageManager;
|
||||
} catch(e) {
|
||||
mm = mmMsg.target;
|
||||
}
|
||||
if (!mm.assertPermission("browser:embedded-system-app")) {
|
||||
dump("BrowserElementParent.js: Method call " + data.methodName +
|
||||
" from a content process with no 'browser:embedded-system-app'" +
|
||||
" privileges.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
switch (data.methodName) {
|
||||
case '_proxyInstanceInit':
|
||||
if (!this.innerWindowIDSet.size) {
|
||||
this._attachEventListeners();
|
||||
}
|
||||
this.innerWindowIDSet.add(data.innerWindowID);
|
||||
|
||||
break;
|
||||
|
||||
case '_proxyInstanceUninit':
|
||||
this.innerWindowIDSet.delete(data.innerWindowID);
|
||||
if (!this.innerWindowIDSet.size) {
|
||||
this._detachEventListeners();
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
// void methods
|
||||
case 'setVisible':
|
||||
case 'setActive':
|
||||
case 'sendMouseEvent':
|
||||
case 'sendTouchEvent':
|
||||
case 'goBack':
|
||||
case 'goForward':
|
||||
case 'reload':
|
||||
case 'stop':
|
||||
case 'zoom':
|
||||
case 'setNFCFocus':
|
||||
case 'findAll':
|
||||
case 'findNext':
|
||||
case 'clearMatch':
|
||||
case 'mute':
|
||||
case 'unmute':
|
||||
case 'setVolume':
|
||||
this._frameElement[data.methodName]
|
||||
.apply(this._frameElement, data.args);
|
||||
|
||||
break;
|
||||
|
||||
// DOMRequest methods
|
||||
case 'getVisible':
|
||||
case 'download':
|
||||
case 'purgeHistory':
|
||||
case 'getCanGoBack':
|
||||
case 'getCanGoForward':
|
||||
case 'getContentDimensions':
|
||||
case 'setInputMethodActive':
|
||||
case 'executeScript':
|
||||
case 'getMuted':
|
||||
case 'getVolume':
|
||||
let req = this._frameElement[data.methodName]
|
||||
.apply(this._frameElement, data.args);
|
||||
req.onsuccess = () => {
|
||||
this._sendToProxy({
|
||||
domRequestId: data.domRequestId,
|
||||
innerWindowID: data.innerWindowID,
|
||||
result: req.result
|
||||
});
|
||||
};
|
||||
req.onerror = () => {
|
||||
this._sendToProxy({
|
||||
domRequestId: data.domRequestId,
|
||||
innerWindowID: data.innerWindowID,
|
||||
err: req.error
|
||||
});
|
||||
};
|
||||
|
||||
break;
|
||||
|
||||
// Not implemented
|
||||
case 'getActive': // Sync ???
|
||||
case 'addNextPaintListener': // Takes a callback
|
||||
case 'removeNextPaintListener': // Takes a callback
|
||||
case 'getScreenshot': // Need to pass a blob back
|
||||
dump("BrowserElementParentProxyCallHandler Error:" +
|
||||
"Attempt to call unimplemented method " + data.methodName + ".\n");
|
||||
break;
|
||||
|
||||
default:
|
||||
dump("BrowserElementParentProxyCallHandler Error:" +
|
||||
"Attempt to call non-exist method " + data.methodName + ".\n");
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
// Receving events from the frame element and forward it.
|
||||
handleEvent: function(evt) {
|
||||
// Ignore the events from nested mozbrowser iframes
|
||||
if (evt.target !== this._frameElement) {
|
||||
return;
|
||||
}
|
||||
|
||||
let detailString;
|
||||
try {
|
||||
detailString = JSON.stringify(evt.detail);
|
||||
} catch (e) {
|
||||
dump("BrowserElementParentProxyCallHandler Error:" +
|
||||
"Event detail of " + evt.type + " can't be stingified.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
this.innerWindowIDSet.forEach((innerWindowID) => {
|
||||
this._sendToProxy({
|
||||
eventName: evt.type,
|
||||
innerWindowID: innerWindowID,
|
||||
eventDetailString: detailString
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
_sendToProxy: function(data) {
|
||||
this._mm.sendAsyncMessage("browser-element-api:proxy", data);
|
||||
},
|
||||
|
||||
_attachEventListeners: function() {
|
||||
this.MOZBROWSER_EVENT_NAMES.forEach(function(eventName) {
|
||||
this._frameElement.addEventListener(
|
||||
"mozbrowser" + eventName, this, true);
|
||||
}, this);
|
||||
},
|
||||
|
||||
_detachEventListeners: function() {
|
||||
this.MOZBROWSER_EVENT_NAMES.forEach(function(eventName) {
|
||||
this._frameElement.removeEventListener(
|
||||
"mozbrowser" + eventName, this, true);
|
||||
}, this);
|
||||
}
|
||||
};
|
||||
|
||||
function BrowserElementParent() {
|
||||
debug("Creating new BrowserElementParent object");
|
||||
this._domRequestCounter = 0;
|
||||
@ -77,6 +248,8 @@ function BrowserElementParent() {
|
||||
Services.obs.addObserver(this, 'oop-frameloader-crashed', /* ownsWeak = */ true);
|
||||
Services.obs.addObserver(this, 'copypaste-docommand', /* ownsWeak = */ true);
|
||||
Services.obs.addObserver(this, 'ask-children-to-execute-copypaste-command', /* ownsWeak = */ true);
|
||||
|
||||
this.proxyCallHandler = new BrowserElementParentProxyCallHandler();
|
||||
}
|
||||
|
||||
BrowserElementParent.prototype = {
|
||||
@ -123,6 +296,9 @@ BrowserElementParent.prototype = {
|
||||
BrowserElementPromptService.mapFrameToBrowserElementParent(this._frameElement, this);
|
||||
this._setupMessageListener();
|
||||
this._registerAppManifest();
|
||||
|
||||
this.proxyCallHandler.init(
|
||||
this._frameElement, this._frameLoader.messageManager);
|
||||
},
|
||||
|
||||
_runPendingAPICall: function() {
|
||||
@ -736,7 +912,7 @@ BrowserElementParent.prototype = {
|
||||
if (!this._isAlive()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
let uri = Services.io.newURI(_url, null, null);
|
||||
let url = uri.QueryInterface(Ci.nsIURL);
|
||||
|
||||
@ -826,7 +1002,7 @@ BrowserElementParent.prototype = {
|
||||
Ci.nsIRequestObserver])
|
||||
};
|
||||
|
||||
// If we have a URI we'll use it to get the triggering principal to use,
|
||||
// If we have a URI we'll use it to get the triggering principal to use,
|
||||
// if not available a null principal is acceptable.
|
||||
let referrer = null;
|
||||
let principal = null;
|
||||
@ -849,9 +1025,9 @@ BrowserElementParent.prototype = {
|
||||
|
||||
debug('Using principal? ' + !!principal);
|
||||
|
||||
let channel =
|
||||
let channel =
|
||||
Services.io.newChannelFromURI2(url,
|
||||
null, // No document.
|
||||
null, // No document.
|
||||
principal, // Loading principal
|
||||
principal, // Triggering principal
|
||||
Ci.nsILoadInfo.SEC_NORMAL,
|
||||
@ -872,7 +1048,7 @@ BrowserElementParent.prototype = {
|
||||
channel.loadFlags |= flags;
|
||||
|
||||
if (channel instanceof Ci.nsIHttpChannel) {
|
||||
debug('Setting HTTP referrer = ' + (referrer && referrer.spec));
|
||||
debug('Setting HTTP referrer = ' + (referrer && referrer.spec));
|
||||
channel.referrer = referrer;
|
||||
if (channel instanceof Ci.nsIHttpChannelInternal) {
|
||||
channel.forceAllowThirdPartyCookie = true;
|
||||
|
220
dom/browser-element/BrowserElementProxy.js
Normal file
220
dom/browser-element/BrowserElementProxy.js
Normal file
@ -0,0 +1,220 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
'use strict';
|
||||
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
const Cu = Components.utils;
|
||||
const Cr = Components.results;
|
||||
|
||||
Cu.import('resource://gre/modules/XPCOMUtils.jsm');
|
||||
Cu.import('resource://gre/modules/Services.jsm');
|
||||
|
||||
function defineNoReturnMethod(methodName) {
|
||||
return function noReturnMethod() {
|
||||
let args = Array.slice(arguments);
|
||||
this._sendToParent(methodName, args);
|
||||
};
|
||||
}
|
||||
|
||||
function defineDOMRequestMethod(methodName) {
|
||||
return function domRequestMethod() {
|
||||
let args = Array.slice(arguments);
|
||||
return this._sendDOMRequest(methodName, args);
|
||||
};
|
||||
}
|
||||
|
||||
function defineUnimplementedMethod(methodName) {
|
||||
return function unimplementedMethod() {
|
||||
throw Components.Exception(
|
||||
'Unimplemented method: ' + methodName, Cr.NS_ERROR_FAILURE);
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* The BrowserElementProxy talks to the Browser IFrameElement instance on
|
||||
* behave of the embedded document. It implements all the methods on
|
||||
* the Browser IFrameElement and the methods will work if they are applicable.
|
||||
*
|
||||
* The message is forwarded to BrowserElementParent.js by creating an
|
||||
* 'browser-element-api:proxy-call' observer message.
|
||||
* BrowserElementChildPreload will get notified and send the message through
|
||||
* to the main process through sendAsyncMessage with message of the same name.
|
||||
*
|
||||
* The return message will follow the same route. The message name on the
|
||||
* return route is 'browser-element-api:proxy'.
|
||||
*
|
||||
* Both BrowserElementProxy and BrowserElementParent must be modified if there
|
||||
* is a new method implemented, or a new event added to the Browser
|
||||
* IFrameElement.
|
||||
*
|
||||
* Other details unmentioned here are checks of message sender and recipients
|
||||
* to identify proxy instance on different innerWindows or ensure the content
|
||||
* process has the right permission.
|
||||
*/
|
||||
function BrowserElementProxy() {
|
||||
// Pad the 0th element so that DOMRequest ID will always be a truthy value.
|
||||
this._pendingDOMRequests = [ undefined ];
|
||||
}
|
||||
|
||||
BrowserElementProxy.prototype = {
|
||||
classDescription: 'BrowserElementProxy allowed embedded frame to control ' +
|
||||
'it\'s own embedding browser element frame instance.',
|
||||
classID: Components.ID('{7e95d54c-9930-49c8-9a10-44fe40fe8251}'),
|
||||
contractID: '@mozilla.org/dom/browser-element-proxy;1',
|
||||
|
||||
QueryInterface: XPCOMUtils.generateQI([
|
||||
Ci.nsIDOMGlobalPropertyInitializer,
|
||||
Ci.nsIObserver]),
|
||||
|
||||
_window: null,
|
||||
_innerWindowID: undefined,
|
||||
|
||||
get allowedAudioChannels() {
|
||||
return this._window.navigator.mozAudioChannelManager ?
|
||||
this._window.navigator.mozAudioChannelManager.allowedAudioChannels :
|
||||
null;
|
||||
},
|
||||
|
||||
init: function(win) {
|
||||
this._window = win;
|
||||
this._innerWindowID = win.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDOMWindowUtils)
|
||||
.currentInnerWindowID;
|
||||
|
||||
this._sendToParent('_proxyInstanceInit');
|
||||
Services.obs.addObserver(this, 'browser-element-api:proxy', false);
|
||||
},
|
||||
|
||||
uninit: function(win) {
|
||||
this._sendToParent('_proxyInstanceUninit');
|
||||
|
||||
this._window = null;
|
||||
this._innerWindowID = undefined;
|
||||
|
||||
Services.obs.removeObserver(this, 'browser-element-api:proxy');
|
||||
},
|
||||
|
||||
observe: function(subject, topic, stringifedData) {
|
||||
let data = JSON.parse(stringifedData);
|
||||
|
||||
if (subject !== this._window ||
|
||||
data.innerWindowID !== data.innerWindowID) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (data.eventName) {
|
||||
this._fireEvent(data.eventName, JSON.parse(data.eventDetailString));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if ('domRequestId' in data) {
|
||||
let req = this._pendingDOMRequests[data.domRequestId];
|
||||
this._pendingDOMRequests[data.domRequestId] = undefined;
|
||||
|
||||
if (!req) {
|
||||
dump('BrowserElementProxy Error: ' +
|
||||
'Multiple observer messages for the same DOMRequest result.\n');
|
||||
return;
|
||||
}
|
||||
|
||||
if ('result' in data) {
|
||||
let clientObj = Cu.cloneInto(data.result, this._window);
|
||||
Services.DOMRequest.fireSuccess(req, clientObj);
|
||||
} else {
|
||||
let clientObj = Cu.cloneInto(data.error, this._window);
|
||||
Services.DOMRequest.fireSuccess(req, clientObj);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
dump('BrowserElementProxy Error: ' +
|
||||
'Received unhandled observer messages ' + stringifedData + '.\n');
|
||||
},
|
||||
|
||||
_sendDOMRequest: function(methodName, args) {
|
||||
let id = this._pendingDOMRequests.length;
|
||||
let req = Services.DOMRequest.createRequest(this._window);
|
||||
|
||||
this._pendingDOMRequests.push(req);
|
||||
this._sendToParent(methodName, args, id);
|
||||
|
||||
return req;
|
||||
},
|
||||
|
||||
_sendToParent: function(methodName, args, domRequestId) {
|
||||
let data = {
|
||||
methodName: methodName,
|
||||
args: args,
|
||||
innerWindowID: this._innerWindowID
|
||||
};
|
||||
|
||||
if (domRequestId) {
|
||||
data.domRequestId = domRequestId;
|
||||
}
|
||||
|
||||
Services.obs.notifyObservers(
|
||||
this._window, 'browser-element-api:proxy-call', JSON.stringify(data));
|
||||
},
|
||||
|
||||
_fireEvent: function(name, detail) {
|
||||
let evt = this._createEvent(name, detail,
|
||||
/* cancelable = */ false);
|
||||
this.__DOM_IMPL__.dispatchEvent(evt);
|
||||
},
|
||||
|
||||
_createEvent: function(evtName, detail, cancelable) {
|
||||
// This will have to change if we ever want to send a CustomEvent with null
|
||||
// detail. For now, it's OK.
|
||||
if (detail !== undefined && detail !== null) {
|
||||
detail = Cu.cloneInto(detail, this._window);
|
||||
return new this._window.CustomEvent(evtName,
|
||||
{ bubbles: false,
|
||||
cancelable: cancelable,
|
||||
detail: detail });
|
||||
}
|
||||
|
||||
return new this._window.Event(evtName,
|
||||
{ bubbles: false,
|
||||
cancelable: cancelable });
|
||||
},
|
||||
|
||||
setVisible: defineNoReturnMethod('setVisible'),
|
||||
setActive: defineNoReturnMethod('setActive'),
|
||||
sendMouseEvent: defineNoReturnMethod('sendMouseEvent'),
|
||||
sendTouchEvent: defineNoReturnMethod('sendTouchEvent'),
|
||||
goBack: defineNoReturnMethod('goBack'),
|
||||
goForward: defineNoReturnMethod('goForward'),
|
||||
reload: defineNoReturnMethod('reload'),
|
||||
stop: defineNoReturnMethod('stop'),
|
||||
zoom: defineNoReturnMethod('zoom'),
|
||||
setNFCFocus: defineNoReturnMethod('setNFCFocus'),
|
||||
findAll: defineNoReturnMethod('findAll'),
|
||||
findNext: defineNoReturnMethod('findNext'),
|
||||
clearMatch: defineNoReturnMethod('clearMatch'),
|
||||
mute: defineNoReturnMethod('mute'),
|
||||
unmute: defineNoReturnMethod('unmute'),
|
||||
setVolume: defineNoReturnMethod('setVolume'),
|
||||
|
||||
getVisible: defineDOMRequestMethod('getVisible'),
|
||||
download: defineDOMRequestMethod('download'),
|
||||
purgeHistory: defineDOMRequestMethod('purgeHistory'),
|
||||
getCanGoBack: defineDOMRequestMethod('getCanGoBack'),
|
||||
getCanGoForward: defineDOMRequestMethod('getCanGoForward'),
|
||||
getContentDimensions: defineDOMRequestMethod('getContentDimensions'),
|
||||
setInputMethodActive: defineDOMRequestMethod('setInputMethodActive'),
|
||||
executeScript: defineDOMRequestMethod('executeScript'),
|
||||
getMuted: defineDOMRequestMethod('getMuted'),
|
||||
getVolume: defineDOMRequestMethod('getVolume'),
|
||||
|
||||
getActive: defineUnimplementedMethod('getActive'),
|
||||
addNextPaintListener: defineUnimplementedMethod('addNextPaintListener'),
|
||||
removeNextPaintListener: defineUnimplementedMethod('removeNextPaintListener'),
|
||||
getScreenshot: defineUnimplementedMethod('getScreenshot')
|
||||
};
|
||||
|
||||
this.NSGetFactory = XPCOMUtils.generateNSGetFactory([BrowserElementProxy]);
|
2
dom/browser-element/BrowserElementProxy.manifest
Normal file
2
dom/browser-element/BrowserElementProxy.manifest
Normal file
@ -0,0 +1,2 @@
|
||||
component {7e95d54c-9930-49c8-9a10-44fe40fe8251} BrowserElementProxy.js
|
||||
contract @mozilla.org/dom/browser-element-proxy;1 {7e95d54c-9930-49c8-9a10-44fe40fe8251}
|
161
dom/browser-element/mochitest/browserElement_Proxy.js
Normal file
161
dom/browser-element/mochitest/browserElement_Proxy.js
Normal file
@ -0,0 +1,161 @@
|
||||
/* Any copyright is dedicated to the public domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
browserElementTestHelpers.setEnabledPref(true);
|
||||
browserElementTestHelpers.addPermission();
|
||||
|
||||
function runTest() {
|
||||
let frameUrl = SimpleTest.getTestFileURL('/file_empty.html');
|
||||
SpecialPowers.pushPermissions([{
|
||||
type: 'browser:embedded-system-app',
|
||||
allow: true,
|
||||
context: {
|
||||
url: frameUrl,
|
||||
appId: SpecialPowers.Ci.nsIScriptSecurityManager.NO_APP_ID,
|
||||
isInBrowserElement: true
|
||||
}
|
||||
},{
|
||||
type: 'browser',
|
||||
allow: true,
|
||||
context: {
|
||||
url: frameUrl,
|
||||
appId: SpecialPowers.Ci.nsIScriptSecurityManager.NO_APP_ID,
|
||||
isInBrowserElement: true
|
||||
}
|
||||
}], createFrame);
|
||||
}
|
||||
|
||||
var frame;
|
||||
var mm;
|
||||
|
||||
function createFrame() {
|
||||
let loadEnd = function() {
|
||||
// The frame script running in the frame where the input is hosted.
|
||||
let appFrameScript = function appFrameScript() {
|
||||
let i = 1;
|
||||
|
||||
addMessageListener('test:next', function() {
|
||||
try {
|
||||
switch (i) {
|
||||
case 1:
|
||||
content.document.addEventListener(
|
||||
'visibilitychange', function fn() {
|
||||
content.document.removeEventListener('visibilitychange', fn);
|
||||
sendAsyncMessage('test:done', {
|
||||
ok: true,
|
||||
msg: 'setVisible()'
|
||||
});
|
||||
});
|
||||
|
||||
// Test a no return method
|
||||
content.navigator.mozBrowserElementProxy.setVisible(false);
|
||||
|
||||
break;
|
||||
case 2:
|
||||
// Test a DOMRequest method
|
||||
var req = content.navigator.mozBrowserElementProxy.getVisible();
|
||||
req.onsuccess = function() {
|
||||
sendAsyncMessage('test:done', {
|
||||
ok: true,
|
||||
msg: 'getVisible()'
|
||||
});
|
||||
};
|
||||
|
||||
req.onerror = function() {
|
||||
sendAsyncMessage('test:done', {
|
||||
ok: false,
|
||||
msg: 'getVisible() DOMRequest return error.'
|
||||
});
|
||||
};
|
||||
|
||||
break;
|
||||
case 3:
|
||||
// Test an unimplemented method
|
||||
try {
|
||||
content.navigator.mozBrowserElementProxy.getActive();
|
||||
sendAsyncMessage('test:done', {
|
||||
ok: false,
|
||||
msg: 'getActive() should throw.'
|
||||
});
|
||||
|
||||
} catch (e) {
|
||||
sendAsyncMessage('test:done', {
|
||||
ok: true,
|
||||
msg: 'getActive() throws.'
|
||||
});
|
||||
}
|
||||
|
||||
break;
|
||||
case 4:
|
||||
content.navigator.mozBrowserElementProxy
|
||||
.addEventListener(
|
||||
'mozbrowserlocationchange',
|
||||
function() {
|
||||
content.navigator.mozBrowserElementProxy
|
||||
.onmozbrowserlocationchange = null;
|
||||
|
||||
sendAsyncMessage('test:done', {
|
||||
ok: true,
|
||||
msg: 'mozbrowserlocationchange'
|
||||
});
|
||||
});
|
||||
|
||||
// Test event
|
||||
content.location.hash = '#foo';
|
||||
|
||||
break;
|
||||
}
|
||||
} catch (e) {
|
||||
sendAsyncMessage('test:done', {
|
||||
ok: false, msg: 'thrown: ' + e.toString() });
|
||||
}
|
||||
|
||||
i++;
|
||||
});
|
||||
|
||||
sendAsyncMessage('test:done', {});
|
||||
}
|
||||
|
||||
mm = SpecialPowers.getBrowserFrameMessageManager(frame);
|
||||
mm.loadFrameScript('data:,(' + encodeURIComponent(appFrameScript.toString()) + ')();', false);
|
||||
mm.addMessageListener("test:done", next);
|
||||
};
|
||||
|
||||
frame = document.createElement('iframe');
|
||||
frame.setAttribute('mozbrowser', 'true');
|
||||
frame.src = 'file_empty.html';
|
||||
document.body.appendChild(frame);
|
||||
frame.addEventListener('mozbrowserloadend', loadEnd);
|
||||
}
|
||||
|
||||
var i = 0;
|
||||
function next(msg) {
|
||||
let wrappedMsg = SpecialPowers.wrap(msg);
|
||||
let isOK = wrappedMsg.data.ok;
|
||||
let msgString = wrappedMsg.data.msg;
|
||||
|
||||
switch (i) {
|
||||
case 0:
|
||||
mm.sendAsyncMessage('test:next');
|
||||
break;
|
||||
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
ok(isOK, msgString);
|
||||
mm.sendAsyncMessage('test:next');
|
||||
break;
|
||||
|
||||
case 4:
|
||||
ok(isOK, msgString);
|
||||
SimpleTest.finish();
|
||||
break;
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
addEventListener('testready', runTest);
|
@ -76,6 +76,8 @@ skip-if = (toolkit == 'gonk') # Disabled on emulator. See bug 1144015 comment 8
|
||||
[test_browserElement_oop_PrivateBrowsing.html]
|
||||
[test_browserElement_oop_PromptCheck.html]
|
||||
[test_browserElement_oop_PromptConfirm.html]
|
||||
[test_browserElement_oop_Proxy.html]
|
||||
skip-if = (toolkit == 'gonk') # Disabled on B2G Emulator bug 1198163
|
||||
[test_browserElement_oop_PurgeHistory.html]
|
||||
[test_browserElement_oop_Reload.html]
|
||||
[test_browserElement_oop_ReloadPostRequest.html]
|
||||
|
@ -54,6 +54,7 @@ support-files =
|
||||
browserElement_PrivateBrowsing.js
|
||||
browserElement_PromptCheck.js
|
||||
browserElement_PromptConfirm.js
|
||||
browserElement_Proxy.js
|
||||
browserElement_PurgeHistory.js
|
||||
browserElement_Reload.js
|
||||
browserElement_ReloadPostRequest.js
|
||||
@ -204,6 +205,8 @@ skip-if = (toolkit == 'gonk' && !debug)
|
||||
[test_browserElement_inproc_PrivateBrowsing.html]
|
||||
[test_browserElement_inproc_PromptCheck.html]
|
||||
[test_browserElement_inproc_PromptConfirm.html]
|
||||
[test_browserElement_inproc_Proxy.html]
|
||||
skip-if = (toolkit == 'gonk') # Disabled on B2G Emulator bug 1198163
|
||||
[test_browserElement_inproc_PurgeHistory.html]
|
||||
[test_browserElement_inproc_ReloadPostRequest.html]
|
||||
[test_browserElement_inproc_RemoveBrowserElement.html]
|
||||
|
@ -0,0 +1,18 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=1196654
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 1196654</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="browserElementTestHelpers.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1196654">Mozilla Bug 1196654</a>
|
||||
|
||||
<script type="application/javascript;version=1.7" src="browserElement_Proxy.js">
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,18 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=1196654
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 1196654</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="browserElementTestHelpers.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1196654">Mozilla Bug 1196654</a>
|
||||
|
||||
<script type="application/javascript;version=1.7" src="browserElement_Proxy.js">
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -26,6 +26,8 @@ XPIDL_MODULE = 'browser-element'
|
||||
EXTRA_COMPONENTS += [
|
||||
'BrowserElementParent.js',
|
||||
'BrowserElementParent.manifest',
|
||||
'BrowserElementProxy.js',
|
||||
'BrowserElementProxy.manifest',
|
||||
]
|
||||
|
||||
EXTRA_JS_MODULES += [
|
||||
|
15
dom/webidl/BrowserElementProxy.webidl
Normal file
15
dom/webidl/BrowserElementProxy.webidl
Normal file
@ -0,0 +1,15 @@
|
||||
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
[Constructor,
|
||||
JSImplementation="@mozilla.org/dom/browser-element-proxy;1",
|
||||
NavigatorProperty="mozBrowserElementProxy",
|
||||
Pref="dom.mozBrowserFramesEnabled",
|
||||
CheckAnyPermissions="browser:embedded-system-app"]
|
||||
interface BrowserElementProxy : EventTarget {
|
||||
};
|
||||
BrowserElementProxy implements BrowserElementCommon;
|
||||
BrowserElementProxy implements BrowserElementPrivileged;
|
@ -59,6 +59,7 @@ WEBIDL_FILES = [
|
||||
'BrowserElement.webidl',
|
||||
'BrowserElementAudioChannel.webidl',
|
||||
'BrowserElementDictionaries.webidl',
|
||||
'BrowserElementProxy.webidl',
|
||||
'Cache.webidl',
|
||||
'CacheStorage.webidl',
|
||||
'CallsList.webidl',
|
||||
|
@ -2,7 +2,7 @@
|
||||
; License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
; file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
; Package file for the Fennec build.
|
||||
; Package file for the Fennec build.
|
||||
;
|
||||
; File format:
|
||||
;
|
||||
@ -309,6 +309,8 @@
|
||||
@BINPATH@/components/SettingsService.manifest
|
||||
@BINPATH@/components/BrowserElementParent.manifest
|
||||
@BINPATH@/components/BrowserElementParent.js
|
||||
@BINPATH@/components/BrowserElementProxy.manifest
|
||||
@BINPATH@/components/BrowserElementProxy.js
|
||||
@BINPATH@/components/PackagedAppUtils.manifest
|
||||
@BINPATH@/components/PackagedAppUtils.js
|
||||
@BINPATH@/components/BrowserFeeds.manifest
|
||||
@ -518,7 +520,7 @@
|
||||
@BINPATH@/defaults/profile/prefs.js
|
||||
|
||||
; [Layout Engine Resources]
|
||||
; Style Sheets, Graphics and other Resources used by the layout engine.
|
||||
; Style Sheets, Graphics and other Resources used by the layout engine.
|
||||
@BINPATH@/res/EditorOverride.css
|
||||
@BINPATH@/res/contenteditable.css
|
||||
@BINPATH@/res/designmode.css
|
||||
@ -649,7 +651,7 @@ bin/libfreebl_32int64_3.so
|
||||
@BINPATH@/components/browsercomps.xpt
|
||||
|
||||
#ifdef ENABLE_MARIONETTE
|
||||
@BINPATH@/chrome/marionette@JAREXT@
|
||||
@BINPATH@/chrome/marionette@JAREXT@
|
||||
@BINPATH@/chrome/marionette.manifest
|
||||
@BINPATH@/components/MarionetteComponents.manifest
|
||||
@BINPATH@/components/marionettecomponent.js
|
||||
|
@ -310,6 +310,8 @@
|
||||
@BINPATH@/components/SettingsManager.manifest
|
||||
@BINPATH@/components/BrowserElementParent.manifest
|
||||
@BINPATH@/components/BrowserElementParent.js
|
||||
@BINPATH@/components/BrowserElementProxy.manifest
|
||||
@BINPATH@/components/BrowserElementProxy.js
|
||||
@BINPATH@/components/FeedProcessor.manifest
|
||||
@BINPATH@/components/FeedProcessor.js
|
||||
@BINPATH@/components/PackagedAppUtils.manifest
|
||||
|
Loading…
Reference in New Issue
Block a user