/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */ /* 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/. */ /** * This code runs in the sandbox in the content process where the page that * loaded the plugin lives. It communicates with the process where the PPAPI * implementation lives. */ let mm = pluginElement.frameLoader.messageManager; let containerWindow = pluginElement.ownerGlobal; function mapValue(v, instance) { return instance.rt.toPP_Var(v, instance); } dump("<>>>>>>>>>>>>>>>>>>>> AHA <<<<<<<<<<<<<<<<<<<<<>\n"); dump(`pluginElement: ${pluginElement.toSource()}\n`); dump(`pluginElement.frameLoader: ${pluginElement.frameLoader.toSource()}\n`); dump(`pluginElement.frameLoader.messageManager: ${pluginElement.frameLoader.messageManager.toSource()}\n`); dump("<>>>>>>>>>>>>>>>>>>>> AHA2 <<<<<<<<<<<<<<<<<<<<<>\n"); mm.addMessageListener("ppapi.js:frameLoaded", ({ target }) => { let tagName = pluginElement.nodeName; // Getting absolute URL from the EMBED tag let url = pluginElement.srcURI.spec; let objectParams = new Map(); for (let i = 0; i < pluginElement.attributes.length; ++i) { let paramName = pluginElement.attributes[i].localName; objectParams.set(paramName, pluginElement.attributes[i].value); } if (tagName == "OBJECT") { let params = pluginElement.getElementsByTagName("param"); Array.prototype.forEach.call(params, (p) => { var paramName = p.getAttribute("name").toLowerCase(); objectParams.set(paramName, p.getAttribute("value")); }); } let documentURL = pluginElement.ownerDocument.location.href; let baseUrl = documentURL; if (objectParams.base) { try { let parsedDocumentUrl = Services.io.newURI(documentURL); baseUrl = Services.io.newURI(objectParams.base, null, parsedDocumentUrl).spec; } catch (e) { /* ignore */ } } let info = { url, documentURL, isFullFrame: pluginElement.ownerDocument.mozSyntheticDocument, setupJSInstanceObject: true, arguments: { keys: Array.from(objectParams.keys()), values: Array.from(objectParams.values()), }, }; mm.sendAsyncMessage("ppapi.js:createInstance", { type: "flash", info }, { pluginWindow: containerWindow }); }); mm.addMessageListener("ppapiflash.js:executeScript", ({ data, objects: { instance } }) => { return mapValue(containerWindow.eval(data), instance); }); let jsInterfaceObjects = new WeakMap(); mm.addMessageListener("ppapiflash.js:createObject", ({ data: { objectClass, objectData }, objects: { instance, call: callRemote } }) => { dump("ppapiflash.js:createObject\n"); let call = (name, args) => { /* let metaData = target[Symbol.for("metaData")]; let callObj = { __interface: "PPP_Class_Deprecated;1.0", __instance: metaData.objectClass, __member: name, object: metaData.objectData }; */ dump("ppapiflash.js:createObject -> call\n"); try { let result = callRemote(name, JSON.stringify(args)); } catch (e) { dump("FIXME: we rely on CPOWs!\n"); return undefined; } dump("RESULT: " + result[0] + "\n"); dump("EXCEPTION: " + result[1] + "\n"); return result[0]; }; const handler = { // getPrototypeOf -> target (see bug 888969) // setPrototypeOf -> target (see bug 888969) // isExtensible -> target // preventExtensions -> target getOwnPropertyDescriptor: function(target, name) { let value = this.get(target, name); if (this._hasProperty(target, name)) { return { "writable": true, "enumerable": true, "configurable": true, "get": this.get.bind(this, target, name), "set": this.set.bind(this, target, name), }; } if (this._hasMethod(target, name)) { return { "value": (...args) => { //call("Call", { name, argc, argv, exception }); }, "writable": true, "enumerable": true, "configurable": true, }; } return undefined; }, // defineProperty -> target has: function(target, name) { return this._hasProperty(target, name) || this._hasMethod(target, name); }, get: function(target, name, receiver) { dump(`Calling GetProperty for ${name.toSource()}\n`); let prop = call("GetProperty", { name }); if (!prop || PP_VarType[prop.type] == PP_VarType.PP_VARTYPE_UNDEFINED) { // FIXME Need to get the exception! return undefined; } return prop; }, set: function(target, name, value, receiver) { call("SetProperty", { name, value }); // FIXME Need to get the exception! return true; }, deleteProperty: function(target, name) { call("RemoveProperty", { name }); // FIXME Need to get the exception! return true; }, enumerate: function(target) { let keys = this.ownKeys(target); return keys[Symbol.iterator]; }, ownKeys: function(target) { let result = call("GetAllPropertyNames"); dump(result.toSource() + "\n"); dump(typeof result.properties + "\n"); return result.properties; }, apply: function(target, thisArg, args) { }, construct: function(target, args) { //call("Construct", { argc, argv, exception }); }, _hasProperty: function(target, name) { return call("HasProperty", { name }) == 1 /* PP_Bool.PP_TRUE */; }, _hasMethod: function(target, name) { return call("HasMethod", { name }) == 1 /* PP_Bool.PP_TRUE */; }, }; let metaData = { objectClass, objectData, }; let clonedHandler = Cu.cloneInto(handler, containerWindow, { cloneFunctions: true }); let clonedMetaData = Cu.cloneInto(metaData, containerWindow, { cloneFunctions: true }); let target = Cu.createObjectIn(containerWindow); target[Symbol.for("metaData")] = clonedMetaData; dump("IN CREATEOBJECT\n"); let proxy = new containerWindow.Proxy(target, clonedHandler); jsInterfaceObjects.set(proxy, metaData); let foo = mapValue(proxy.wrappedJSObject, instance); dump("CREATEDOBJECT: " + foo.toSource() + "\n"); return foo; }); mm.addMessageListener("ppapiflash.js:isInstanceOf", ({ data: { objectClass }, objects: { object, instance } }) => { let metaData = jsInterfaceObjects.get(object); if (!metaData || metaData.objectClass != objectClass) { return [false]; } return [true, metaData.objectData]; }); mm.addMessageListener("ppapiflash.js:getProperty", ({ data: { name }, objects: { object, instance } }) => { try { return [mapValue(object[name], instance), { exception: null }]; } catch (e) { return [mapValue(null, instance), { exception: mapValue(e, instance) }]; } }); mm.addMessageListener("ppapiflash.js:log", ({ data }) => { containerWindow.console.log(data); }); mm.addMessageListener("ppapiflash.js:setInstancePrototype", ({ objects: { proto } }) => { Object.setPrototypeOf(proto.wrappedJSObject, Object.getPrototypeOf(pluginElement.wrappedJSObject)); Object.setPrototypeOf(pluginElement.wrappedJSObject, proto.wrappedJSObject); }); mm.addMessageListener("ppapi.js:isFullscreen", () => { return containerWindow.document.fullscreenElement == pluginElement; }); mm.addMessageListener("ppapi.js:setFullscreen", ({ data }) => { if (data) { pluginElement.requestFullscreen(); } else { containerWindow.document.exitFullscreen(); } }); mm.loadFrameScript("resource://ppapi.js/ppapi-instance.js", true);