mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-25 22:01:30 +00:00
Bug 1097185 - Update Shumway to version 0.9.3693. r=till,r=jmathies
This commit is contained in:
parent
2baf81b59b
commit
797f4529b9
@ -1 +1,2 @@
|
||||
content shumway chrome/
|
||||
resource shumway content/
|
||||
|
192
browser/extensions/shumway/chrome/RtmpUtils.jsm
Normal file
192
browser/extensions/shumway/chrome/RtmpUtils.jsm
Normal file
@ -0,0 +1,192 @@
|
||||
/*
|
||||
* Copyright 2014 Mozilla Foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
var EXPORTED_SYMBOLS = ['RtmpUtils'];
|
||||
|
||||
Components.utils.import('resource://gre/modules/Services.jsm');
|
||||
|
||||
var Cc = Components.classes;
|
||||
var Ci = Components.interfaces;
|
||||
var Cu = Components.utils;
|
||||
var Cr = Components.results;
|
||||
|
||||
var RtmpUtils = {
|
||||
get isRtmpEnabled() {
|
||||
try {
|
||||
return Services.prefs.getBoolPref('shumway.rtmp.enabled');
|
||||
} catch (ex) {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
|
||||
createSocket: function (sandbox, params) {
|
||||
var host = params.host, port = params.port, ssl = params.ssl;
|
||||
|
||||
var baseSocket = Cc["@mozilla.org/tcp-socket;1"].createInstance(Ci.nsIDOMTCPSocket);
|
||||
var socket = baseSocket.open(host, port, {useSecureTransport: ssl, binaryType: 'arraybuffer'});
|
||||
if (!socket) {
|
||||
return null;
|
||||
}
|
||||
|
||||
var wrapperOnOpen = null, wrapperOnData = null, wrapperOnDrain = null;
|
||||
var wrapperOnError = null, wrapperOnClose = null;
|
||||
socket.onopen = function () {
|
||||
if (wrapperOnOpen) {
|
||||
wrapperOnOpen.call(wrapper, new sandbox.Object());
|
||||
}
|
||||
};
|
||||
socket.ondata = function (e) {
|
||||
if (wrapperOnData) {
|
||||
var wrappedE = new sandbox.Object();
|
||||
wrappedE.data = Components.utils.cloneInto(e.data, sandbox);
|
||||
wrapperOnData.call(wrapper, wrappedE);
|
||||
}
|
||||
};
|
||||
socket.ondrain = function () {
|
||||
if (wrapperOnDrain) {
|
||||
wrapperOnDrain.call(wrapper, new sandbox.Object());
|
||||
}
|
||||
};
|
||||
socket.onerror = function (e) {
|
||||
if (wrapperOnError) {
|
||||
var wrappedE = new sandbox.Object();
|
||||
wrappedE.data = Components.utils.cloneInto(e.data, sandbox);
|
||||
wrapperOnError.call(wrapper, wrappedE);
|
||||
}
|
||||
};
|
||||
socket.onclose = function () {
|
||||
if (wrapperOnClose) {
|
||||
wrapperOnClose.call(wrapper, new sandbox.Object());
|
||||
}
|
||||
};
|
||||
|
||||
var wrapper = new sandbox.Object();
|
||||
var waived = Components.utils.waiveXrays(wrapper);
|
||||
Object.defineProperties(waived, {
|
||||
onopen: {
|
||||
get: function () { return wrapperOnOpen; },
|
||||
set: function (value) { wrapperOnOpen = value; },
|
||||
enumerable: true
|
||||
},
|
||||
ondata: {
|
||||
get: function () { return wrapperOnData; },
|
||||
set: function (value) { wrapperOnData = value; },
|
||||
enumerable: true
|
||||
},
|
||||
ondrain: {
|
||||
get: function () { return wrapperOnDrain; },
|
||||
set: function (value) { wrapperOnDrain = value; },
|
||||
enumerable: true
|
||||
},
|
||||
onerror: {
|
||||
get: function () { return wrapperOnError; },
|
||||
set: function (value) { wrapperOnError = value; },
|
||||
enumerable: true
|
||||
},
|
||||
onclose: {
|
||||
get: function () { return wrapperOnClose; },
|
||||
set: function (value) { wrapperOnClose = value; },
|
||||
enumerable: true
|
||||
},
|
||||
|
||||
send: {
|
||||
value: function (buffer, offset, count) {
|
||||
return socket.send(buffer, offset, count);
|
||||
}
|
||||
},
|
||||
|
||||
close: {
|
||||
value: function () {
|
||||
socket.close();
|
||||
}
|
||||
}
|
||||
});
|
||||
return wrapper;
|
||||
},
|
||||
|
||||
createXHR: function (sandbox) {
|
||||
var xhr = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"]
|
||||
.createInstance(Ci.nsIXMLHttpRequest);
|
||||
var wrapperOnLoad = null, wrapperOnError = null;
|
||||
xhr.onload = function () {
|
||||
if (wrapperOnLoad) {
|
||||
wrapperOnLoad.call(wrapper, new sandbox.Object());
|
||||
}
|
||||
};
|
||||
xhr.onerror = function () {
|
||||
if (wrappedOnError) {
|
||||
wrappedOnError.call(wrapper, new sandbox.Object());
|
||||
}
|
||||
};
|
||||
|
||||
var wrapper = new sandbox.Object();
|
||||
var waived = Components.utils.waiveXrays(wrapper);
|
||||
Object.defineProperties(waived, {
|
||||
status: {
|
||||
get: function () { return xhr.status; },
|
||||
enumerable: true
|
||||
},
|
||||
response: {
|
||||
get: function () { return Components.utils.cloneInto(xhr.response, sandbox); },
|
||||
enumerable: true
|
||||
},
|
||||
responseType: {
|
||||
get: function () { return xhr.responseType; },
|
||||
set: function (value) {
|
||||
if (value !== 'arraybuffer') {
|
||||
throw new Error('Invalid responseType.');
|
||||
}
|
||||
},
|
||||
enumerable: true
|
||||
},
|
||||
onload: {
|
||||
get: function () { return wrapperOnLoad; },
|
||||
set: function (value) { wrapperOnLoad = value; },
|
||||
enumerable: true
|
||||
},
|
||||
onerror: {
|
||||
get: function () { return wrapperOnError; },
|
||||
set: function (value) { wrapperOnError = value; },
|
||||
enumerable: true
|
||||
},
|
||||
open: {
|
||||
value: function (method, path, async) {
|
||||
if (method !== 'POST' || !path || (async !== undefined && !async)) {
|
||||
throw new Error('invalid open() arguments');
|
||||
}
|
||||
// TODO check path
|
||||
xhr.open('POST', path, true);
|
||||
xhr.responseType = 'arraybuffer';
|
||||
xhr.setRequestHeader('Content-Type', 'application/x-fcs');
|
||||
}
|
||||
},
|
||||
setRequestHeader: {
|
||||
value: function (header, value) {
|
||||
if (header !== 'Content-Type' || value !== 'application/x-fcs') {
|
||||
throw new Error('invalid setRequestHeader() arguments');
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
send: {
|
||||
value: function (data) {
|
||||
xhr.send(data);
|
||||
}
|
||||
}
|
||||
});
|
||||
return wrapper;
|
||||
}
|
||||
};
|
132
browser/extensions/shumway/chrome/SpecialInflate.jsm
Normal file
132
browser/extensions/shumway/chrome/SpecialInflate.jsm
Normal file
@ -0,0 +1,132 @@
|
||||
/*
|
||||
* Copyright 2014 Mozilla Foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
var EXPORTED_SYMBOLS = ['SpecialInflate', 'SpecialInflateUtils'];
|
||||
|
||||
Components.utils.import('resource://gre/modules/Services.jsm');
|
||||
|
||||
var Cc = Components.classes;
|
||||
var Ci = Components.interfaces;
|
||||
var Cu = Components.utils;
|
||||
var Cr = Components.results;
|
||||
|
||||
function SimpleStreamListener() {
|
||||
this.binaryStream = Cc['@mozilla.org/binaryinputstream;1']
|
||||
.createInstance(Ci.nsIBinaryInputStream);
|
||||
this.onData = null;
|
||||
this.buffer = null;
|
||||
}
|
||||
SimpleStreamListener.prototype = {
|
||||
QueryInterface: function (iid) {
|
||||
if (iid.equals(Ci.nsIStreamListener) ||
|
||||
iid.equals(Ci.nsIRequestObserver) ||
|
||||
iid.equals(Ci.nsISupports))
|
||||
return this;
|
||||
throw Cr.NS_ERROR_NO_INTERFACE;
|
||||
},
|
||||
onStartRequest: function (aRequest, aContext) {
|
||||
return Cr.NS_OK;
|
||||
},
|
||||
onStopRequest: function (aRequest, aContext, sStatusCode) {
|
||||
return Cr.NS_OK;
|
||||
},
|
||||
onDataAvailable: function (aRequest, aContext, aInputStream, aOffset, aCount) {
|
||||
this.binaryStream.setInputStream(aInputStream);
|
||||
if (!this.buffer || aCount > this.buffer.byteLength) {
|
||||
this.buffer = new ArrayBuffer(aCount);
|
||||
}
|
||||
this.binaryStream.readArrayBuffer(aCount, this.buffer);
|
||||
this.onData(new Uint8Array(this.buffer, 0, aCount));
|
||||
return Cr.NS_OK;
|
||||
}
|
||||
};
|
||||
|
||||
function SpecialInflate() {
|
||||
var listener = new SimpleStreamListener();
|
||||
listener.onData = function (data) {
|
||||
this.onData(data);
|
||||
}.bind(this);
|
||||
|
||||
var converterService = Cc["@mozilla.org/streamConverters;1"].getService(Ci.nsIStreamConverterService);
|
||||
var converter = converterService.asyncConvertData("deflate", "uncompressed", listener, null);
|
||||
converter.onStartRequest(null, null);
|
||||
this.converter = converter;
|
||||
|
||||
var binaryStream = Cc["@mozilla.org/binaryoutputstream;1"].createInstance(Ci.nsIBinaryOutputStream);
|
||||
var pipe = Cc["@mozilla.org/pipe;1"].createInstance(Ci.nsIPipe);
|
||||
pipe.init(true, true, 0, 0xFFFFFFFF, null);
|
||||
binaryStream.setOutputStream(pipe.outputStream);
|
||||
this.binaryStream = binaryStream;
|
||||
|
||||
this.pipeInputStream = pipe.inputStream;
|
||||
|
||||
this.onData = null;
|
||||
}
|
||||
SpecialInflate.prototype = {
|
||||
push: function (data) {
|
||||
this.binaryStream.writeByteArray(data, data.length);
|
||||
this.converter.onDataAvailable(null, null, this.pipeInputStream, 0, data.length);
|
||||
},
|
||||
close: function () {
|
||||
this.binaryStream.close();
|
||||
this.converter.onStopRequest(null, null, Cr.NS_OK);
|
||||
}
|
||||
};
|
||||
|
||||
var SpecialInflateUtils = {
|
||||
get isSpecialInflateEnabled() {
|
||||
try {
|
||||
return Services.prefs.getBoolPref('shumway.specialInflate');
|
||||
} catch (ex) {
|
||||
return false; // TODO true;
|
||||
}
|
||||
},
|
||||
|
||||
createWrappedSpecialInflate: function (sandbox) {
|
||||
var wrapped = new SpecialInflate();
|
||||
var wrapperOnData = null;
|
||||
wrapped.onData = function(data) {
|
||||
if (wrapperOnData) {
|
||||
wrapperOnData.call(wrapper, Components.utils.cloneInto(data, sandbox));
|
||||
}
|
||||
};
|
||||
// We will return object created in the sandbox/content, with some exposed
|
||||
// properties/methods, so we can send data between wrapped object and
|
||||
// and sandbox/content.
|
||||
var wrapper = new sandbox.Object();
|
||||
var waived = Components.utils.waiveXrays(wrapper);
|
||||
Object.defineProperties(waived, {
|
||||
onData: {
|
||||
get: function () { return wrapperOnData; },
|
||||
set: function (value) { wrapperOnData = value; },
|
||||
enumerable: true
|
||||
},
|
||||
push: {
|
||||
value: function (data) {
|
||||
// Uint8Array is expected in the data parameter.
|
||||
// SpecialInflate.push() fails with other argument types.
|
||||
return wrapped.push(data);
|
||||
}
|
||||
},
|
||||
close: {
|
||||
value: function () {
|
||||
return wrapped.close();
|
||||
}
|
||||
}
|
||||
});
|
||||
return wrapper;
|
||||
}
|
||||
};
|
80
browser/extensions/shumway/chrome/bootstrap-content.js
vendored
Normal file
80
browser/extensions/shumway/chrome/bootstrap-content.js
vendored
Normal file
@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Copyright 2014 Mozilla Foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
(function contentScriptClosure() {
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
const Cm = Components.manager;
|
||||
const Cu = Components.utils;
|
||||
const Cr = Components.results;
|
||||
|
||||
// we need to use closure here -- we are running in the global context
|
||||
Cu.import('resource://gre/modules/Services.jsm');
|
||||
|
||||
var isRemote = Services.appinfo.processType ===
|
||||
Services.appinfo.PROCESS_TYPE_CONTENT;
|
||||
var isStarted = false;
|
||||
|
||||
function startup() {
|
||||
if (isStarted) {
|
||||
return;
|
||||
}
|
||||
|
||||
isStarted = true;
|
||||
Cu.import('resource://shumway/ShumwayBootstrapUtils.jsm');
|
||||
ShumwayBootstrapUtils.register();
|
||||
}
|
||||
|
||||
function shutdown() {
|
||||
if (!isStarted) {
|
||||
return;
|
||||
}
|
||||
|
||||
isStarted = false;
|
||||
ShumwayBootstrapUtils.unregister();
|
||||
Cu.unload('resource://shumway/ShumwayBootstrapUtils.jsm');
|
||||
}
|
||||
|
||||
|
||||
function updateSettings() {
|
||||
let mm = Cc["@mozilla.org/childprocessmessagemanager;1"]
|
||||
.getService(Ci.nsISyncMessageSender);
|
||||
var results = mm.sendSyncMessage('Shumway:Chrome:isEnabled');
|
||||
var isEnabled = results.some(function (item) {
|
||||
return item;
|
||||
});
|
||||
|
||||
if (isEnabled) {
|
||||
startup();
|
||||
} else {
|
||||
shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
if (isRemote) {
|
||||
addMessageListener('Shumway:Child:refreshSettings', updateSettings);
|
||||
updateSettings();
|
||||
|
||||
addMessageListener('Shumway:Child:shutdown', function shutdownListener(e) {
|
||||
removeMessageListener('Shumway:Child:refreshSettings', updateSettings);
|
||||
removeMessageListener('Shumway:Child:shutdown', shutdownListener);
|
||||
|
||||
shutdown();
|
||||
});
|
||||
}
|
||||
})();
|
98
browser/extensions/shumway/chrome/content.js
Normal file
98
browser/extensions/shumway/chrome/content.js
Normal file
@ -0,0 +1,98 @@
|
||||
/*
|
||||
* Copyright 2014 Mozilla Foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
Components.utils.import('resource://gre/modules/Services.jsm');
|
||||
Components.utils.import('chrome://shumway/content/SpecialInflate.jsm');
|
||||
Components.utils.import('chrome://shumway/content/RtmpUtils.jsm');
|
||||
|
||||
var externalInterfaceWrapper = {
|
||||
callback: function (call) {
|
||||
if (!shumwayComAdapter.onExternalCallback) {
|
||||
return undefined;
|
||||
}
|
||||
return shumwayComAdapter.onExternalCallback(
|
||||
Components.utils.cloneInto(JSON.parse(call), content));
|
||||
}
|
||||
};
|
||||
|
||||
// The object allows resending of external interface, clipboard and other
|
||||
// control messages between unprivileged content and ShumwayStreamConverter.
|
||||
var shumwayComAdapter;
|
||||
|
||||
function sendMessage(action, data, sync, callbackCookie) {
|
||||
var detail = {action: action, data: data, sync: sync};
|
||||
if (callbackCookie !== undefined) {
|
||||
detail.callback = true;
|
||||
detail.cookie = callbackCookie;
|
||||
}
|
||||
if (!sync) {
|
||||
sendAsyncMessage('Shumway:message', detail);
|
||||
return;
|
||||
}
|
||||
var result = sendSyncMessage('Shumway:message', detail);
|
||||
return Components.utils.cloneInto(result, content);
|
||||
}
|
||||
|
||||
addMessageListener('Shumway:init', function (message) {
|
||||
sendAsyncMessage('Shumway:running', {}, {
|
||||
externalInterface: externalInterfaceWrapper
|
||||
});
|
||||
|
||||
// Exposing ShumwayCom object/adapter to the unprivileged content -- setting
|
||||
// up Xray wrappers.
|
||||
shumwayComAdapter = Components.utils.createObjectIn(content, {defineAs: 'ShumwayCom'});
|
||||
Components.utils.exportFunction(sendMessage, shumwayComAdapter, {defineAs: 'sendMessage'});
|
||||
Object.defineProperties(shumwayComAdapter, {
|
||||
onLoadFileCallback: { value: null, writable: true },
|
||||
onExternalCallback: { value: null, writable: true },
|
||||
onMessageCallback: { value: null, writable: true }
|
||||
});
|
||||
Components.utils.makeObjectPropsNormal(shumwayComAdapter);
|
||||
|
||||
// Exposing createSpecialInflate function for DEFLATE stream decoding using
|
||||
// Gecko API.
|
||||
if (SpecialInflateUtils.isSpecialInflateEnabled) {
|
||||
Components.utils.exportFunction(function () {
|
||||
return SpecialInflateUtils.createWrappedSpecialInflate(content);
|
||||
}, content, {defineAs: 'createSpecialInflate'});
|
||||
}
|
||||
|
||||
if (RtmpUtils.isRtmpEnabled) {
|
||||
Components.utils.exportFunction(function (params) {
|
||||
return RtmpUtils.createSocket(content, params);
|
||||
}, content, {defineAs: 'createRtmpSocket'});
|
||||
Components.utils.exportFunction(function () {
|
||||
return RtmpUtils.createXHR(content);
|
||||
}, content, {defineAs: 'createRtmpXHR'});
|
||||
}
|
||||
|
||||
content.wrappedJSObject.runViewer();
|
||||
});
|
||||
|
||||
addMessageListener('Shumway:loadFile', function (message) {
|
||||
if (!shumwayComAdapter.onLoadFileCallback) {
|
||||
return;
|
||||
}
|
||||
shumwayComAdapter.onLoadFileCallback(Components.utils.cloneInto(message.data, content));
|
||||
});
|
||||
|
||||
addMessageListener('Shumway:messageCallback', function (message) {
|
||||
if (!shumwayComAdapter.onMessageCallback) {
|
||||
return;
|
||||
}
|
||||
shumwayComAdapter.onMessageCallback(message.data.cookie,
|
||||
Components.utils.cloneInto(message.data.response, content));
|
||||
});
|
46
browser/extensions/shumway/chrome/viewer.wrapper.html
Normal file
46
browser/extensions/shumway/chrome/viewer.wrapper.html
Normal file
@ -0,0 +1,46 @@
|
||||
<!DOCTYPE html>
|
||||
<!--
|
||||
Copyright 2013 Mozilla Foundation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
|
||||
|
||||
<style>
|
||||
html, body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
iframe {
|
||||
position:fixed !important;
|
||||
left:0;top:0;bottom:0;right:0;
|
||||
overflow: hidden;
|
||||
line-height: 0;
|
||||
border: 0px none;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<iframe id="viewer" src="resource://shumway/web/viewer.html" width="100%" height="100%" mozbrowser remote="true"></iframe>
|
||||
<script src="chrome://shumway/content/viewerWrapper.js"></script>
|
||||
</body>
|
||||
</html>
|
145
browser/extensions/shumway/chrome/viewerWrapper.js
Normal file
145
browser/extensions/shumway/chrome/viewerWrapper.js
Normal file
@ -0,0 +1,145 @@
|
||||
/*
|
||||
* Copyright 2014 Mozilla Foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
window.notifyShumwayMessage = function (detail) { };
|
||||
window.onExternalCallback = null;
|
||||
window.onMessageCallback = null;
|
||||
window.onLoadFileCallback = null;
|
||||
|
||||
var viewer = document.getElementById('viewer'), onLoaded;
|
||||
var promise = new Promise(function (resolve) {
|
||||
onLoaded = resolve;
|
||||
});
|
||||
viewer.addEventListener('load', function () {
|
||||
onLoaded(false);
|
||||
});
|
||||
viewer.addEventListener('mozbrowserloadend', function () {
|
||||
onLoaded(true);
|
||||
});
|
||||
|
||||
Components.utils.import('chrome://shumway/content/SpecialInflate.jsm');
|
||||
Components.utils.import('chrome://shumway/content/RtmpUtils.jsm');
|
||||
|
||||
function runViewer() {
|
||||
function handler() {
|
||||
function sendMessage(action, data, sync, callbackCookie) {
|
||||
var detail = {action: action, data: data, sync: sync};
|
||||
if (callbackCookie !== undefined) {
|
||||
detail.callback = true;
|
||||
detail.cookie = callbackCookie;
|
||||
}
|
||||
var result = window.notifyShumwayMessage(detail);
|
||||
return Components.utils.cloneInto(result, childWindow);
|
||||
}
|
||||
|
||||
var childWindow = viewer.contentWindow.wrappedJSObject;
|
||||
|
||||
// Exposing ShumwayCom object/adapter to the unprivileged content -- setting
|
||||
// up Xray wrappers. This allows resending of external interface, clipboard
|
||||
// and other control messages between unprivileged content and
|
||||
// ShumwayStreamConverter.
|
||||
var shumwayComAdapter = Components.utils.createObjectIn(childWindow, {defineAs: 'ShumwayCom'});
|
||||
Components.utils.exportFunction(sendMessage, shumwayComAdapter, {defineAs: 'sendMessage'});
|
||||
Object.defineProperties(shumwayComAdapter, {
|
||||
onLoadFileCallback: { value: null, writable: true },
|
||||
onExternalCallback: { value: null, writable: true },
|
||||
onMessageCallback: { value: null, writable: true }
|
||||
});
|
||||
Components.utils.makeObjectPropsNormal(shumwayComAdapter);
|
||||
|
||||
// Exposing createSpecialInflate function for DEFLATE stream decoding using
|
||||
// Gecko API.
|
||||
if (SpecialInflateUtils.isSpecialInflateEnabled) {
|
||||
Components.utils.exportFunction(function () {
|
||||
return SpecialInflateUtils.createWrappedSpecialInflate(childWindow);
|
||||
}, childWindow, {defineAs: 'createSpecialInflate'});
|
||||
}
|
||||
|
||||
if (RtmpUtils.isRtmpEnabled) {
|
||||
Components.utils.exportFunction(function (params) {
|
||||
return RtmpUtils.createSocket(childWindow, params);
|
||||
}, childWindow, {defineAs: 'createRtmpSocket'});
|
||||
Components.utils.exportFunction(function () {
|
||||
return RtmpUtils.createXHR(childWindow);
|
||||
}, childWindow, {defineAs: 'createRtmpXHR'});
|
||||
}
|
||||
|
||||
window.onExternalCallback = function (call) {
|
||||
return shumwayComAdapter.onExternalCallback(Components.utils.cloneInto(call, childWindow));
|
||||
};
|
||||
|
||||
window.onMessageCallback = function (response) {
|
||||
shumwayComAdapter.onMessageCallback(Components.utils.cloneInto(response, childWindow));
|
||||
};
|
||||
|
||||
window.onLoadFileCallback = function (args) {
|
||||
shumwayComAdapter.onLoadFileCallback(Components.utils.cloneInto(args, childWindow));
|
||||
};
|
||||
|
||||
childWindow.runViewer();
|
||||
}
|
||||
|
||||
function handlerOOP() {
|
||||
var frameLoader = viewer.QueryInterface(Components.interfaces.nsIFrameLoaderOwner).frameLoader;
|
||||
var messageManager = frameLoader.messageManager;
|
||||
messageManager.loadFrameScript('chrome://shumway/content/content.js', false);
|
||||
|
||||
var externalInterface;
|
||||
|
||||
messageManager.addMessageListener('Shumway:running', function (message) {
|
||||
externalInterface = message.objects.externalInterface;
|
||||
});
|
||||
|
||||
messageManager.addMessageListener('Shumway:message', function (message) {
|
||||
var detail = {
|
||||
action: message.data.action,
|
||||
data: message.data.data,
|
||||
sync: message.data.sync
|
||||
};
|
||||
if (message.data.callback) {
|
||||
detail.callback = true;
|
||||
detail.cookie = message.data.cookie;
|
||||
}
|
||||
|
||||
return window.notifyShumwayMessage(detail);
|
||||
});
|
||||
|
||||
window.onExternalCallback = function (call) {
|
||||
return externalInterface.callback(JSON.stringify(call));
|
||||
};
|
||||
|
||||
window.onMessageCallback = function (response) {
|
||||
messageManager.sendAsyncMessage('Shumway:messageCallback', {
|
||||
cookie: response.cookie,
|
||||
response: response.response
|
||||
});
|
||||
};
|
||||
|
||||
window.onLoadFileCallback = function (args) {
|
||||
messageManager.sendAsyncMessage('Shumway:loadFile', args);
|
||||
};
|
||||
|
||||
messageManager.sendAsyncMessage('Shumway:init', {});
|
||||
}
|
||||
|
||||
promise.then(function (oop) {
|
||||
if (oop) {
|
||||
handlerOOP();
|
||||
} else {
|
||||
handler();
|
||||
}
|
||||
});
|
||||
}
|
95
browser/extensions/shumway/content/ShumwayBootstrapUtils.jsm
Normal file
95
browser/extensions/shumway/content/ShumwayBootstrapUtils.jsm
Normal file
@ -0,0 +1,95 @@
|
||||
/*
|
||||
* Copyright 2014 Mozilla Foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
var EXPORTED_SYMBOLS = ['ShumwayBootstrapUtils'];
|
||||
|
||||
const PREF_PREFIX = 'shumway.';
|
||||
const PREF_IGNORE_CTP = PREF_PREFIX + 'ignoreCTP';
|
||||
const SWF_CONTENT_TYPE = 'application/x-shockwave-flash';
|
||||
|
||||
let Cc = Components.classes;
|
||||
let Ci = Components.interfaces;
|
||||
let Cm = Components.manager;
|
||||
let Cu = Components.utils;
|
||||
|
||||
Cu.import('resource://gre/modules/XPCOMUtils.jsm');
|
||||
Cu.import('resource://gre/modules/Services.jsm');
|
||||
|
||||
Cu.import('resource://shumway/ShumwayStreamConverter.jsm');
|
||||
|
||||
let Ph = Cc["@mozilla.org/plugin/host;1"].getService(Ci.nsIPluginHost);
|
||||
let registerOverlayPreview = 'registerPlayPreviewMimeType' in Ph;
|
||||
|
||||
function getBoolPref(pref, def) {
|
||||
try {
|
||||
return Services.prefs.getBoolPref(pref);
|
||||
} catch (ex) {
|
||||
return def;
|
||||
}
|
||||
}
|
||||
|
||||
function log(str) {
|
||||
dump(str + '\n');
|
||||
}
|
||||
|
||||
// Register/unregister a constructor as a factory.
|
||||
function Factory() {}
|
||||
Factory.prototype = {
|
||||
register: function register(targetConstructor) {
|
||||
var proto = targetConstructor.prototype;
|
||||
this._classID = proto.classID;
|
||||
|
||||
var factory = XPCOMUtils._getFactory(targetConstructor);
|
||||
this._factory = factory;
|
||||
|
||||
var registrar = Cm.QueryInterface(Ci.nsIComponentRegistrar);
|
||||
registrar.registerFactory(proto.classID, proto.classDescription,
|
||||
proto.contractID, factory);
|
||||
},
|
||||
|
||||
unregister: function unregister() {
|
||||
var registrar = Cm.QueryInterface(Ci.nsIComponentRegistrar);
|
||||
registrar.unregisterFactory(this._classID, this._factory);
|
||||
}
|
||||
};
|
||||
|
||||
let converterFactory = new Factory();
|
||||
let overlayConverterFactory = new Factory();
|
||||
|
||||
var ShumwayBootstrapUtils = {
|
||||
register: function () {
|
||||
// Register the components.
|
||||
converterFactory.register(ShumwayStreamConverter);
|
||||
overlayConverterFactory.register(ShumwayStreamOverlayConverter);
|
||||
|
||||
if (registerOverlayPreview) {
|
||||
var ignoreCTP = getBoolPref(PREF_IGNORE_CTP, true);
|
||||
Ph.registerPlayPreviewMimeType(SWF_CONTENT_TYPE, ignoreCTP);
|
||||
}
|
||||
},
|
||||
|
||||
unregister: function () {
|
||||
// Remove the contract/component.
|
||||
converterFactory.unregister();
|
||||
overlayConverterFactory.unregister();
|
||||
|
||||
if (registerOverlayPreview) {
|
||||
Ph.unregisterPlayPreviewMimeType(SWF_CONTENT_TYPE);
|
||||
}
|
||||
}
|
||||
};
|
@ -184,9 +184,17 @@ function fetchPolicyFile(url, cache, callback) {
|
||||
xhr.send(null);
|
||||
}
|
||||
|
||||
function isContentWindowPrivate(win) {
|
||||
if (!('isContentWindowPrivate' in PrivateBrowsingUtils)) {
|
||||
return PrivateBrowsingUtils.isWindowPrivate(win);
|
||||
}
|
||||
return PrivateBrowsingUtils.isContentWindowPrivate(win);
|
||||
}
|
||||
|
||||
function isShumwayEnabledFor(actions) {
|
||||
// disabled for PrivateBrowsing windows
|
||||
if (PrivateBrowsingUtils.isWindowPrivate(actions.window)) {
|
||||
if (isContentWindowPrivate(actions.window) &&
|
||||
!getBoolPref('shumway.enableForPrivate', false)) {
|
||||
return false;
|
||||
}
|
||||
// disabled if embed tag specifies shumwaymode (for testing purpose)
|
||||
@ -212,13 +220,15 @@ function isShumwayEnabledFor(actions) {
|
||||
function getVersionInfo() {
|
||||
var deferred = Promise.defer();
|
||||
var versionInfo = {
|
||||
geckoMstone : 'unknown',
|
||||
version: 'unknown',
|
||||
geckoBuildID: 'unknown',
|
||||
shumwayVersion: 'unknown'
|
||||
};
|
||||
try {
|
||||
versionInfo.geckoMstone = Services.prefs.getCharPref('gecko.mstone');
|
||||
versionInfo.geckoBuildID = Services.prefs.getCharPref('gecko.buildID');
|
||||
var appInfo = Components.classes["@mozilla.org/xre/app-info;1"]
|
||||
.getService(Components.interfaces.nsIXULAppInfo);
|
||||
versionInfo.geckoVersion = appInfo.version;
|
||||
versionInfo.geckoBuildID = appInfo.appBuildID;
|
||||
} catch (e) {
|
||||
log('Error encountered while getting platform version info:', e);
|
||||
}
|
||||
@ -275,11 +285,11 @@ ChromeActions.prototype = {
|
||||
return getBoolPref(data.pref, data.def);
|
||||
},
|
||||
getCompilerSettings: function getCompilerSettings() {
|
||||
return JSON.stringify({
|
||||
return {
|
||||
appCompiler: getBoolPref('shumway.appCompiler', true),
|
||||
sysCompiler: getBoolPref('shumway.sysCompiler', false),
|
||||
verifier: getBoolPref('shumway.verifier', true)
|
||||
});
|
||||
};
|
||||
},
|
||||
addProfilerMarker: function (marker) {
|
||||
if ('nsIProfiler' in Ci) {
|
||||
@ -288,14 +298,14 @@ ChromeActions.prototype = {
|
||||
}
|
||||
},
|
||||
getPluginParams: function getPluginParams() {
|
||||
return JSON.stringify({
|
||||
return {
|
||||
url: this.url,
|
||||
baseUrl : this.baseUrl,
|
||||
movieParams: this.movieParams,
|
||||
objectParams: this.objectParams,
|
||||
isOverlay: this.isOverlay,
|
||||
isPausedAtStart: this.isPausedAtStart
|
||||
});
|
||||
};
|
||||
},
|
||||
_canDownloadFile: function canDownloadFile(data, callback) {
|
||||
var url = data.url, checkPolicyFile = data.checkPolicyFile;
|
||||
@ -352,6 +362,13 @@ ChromeActions.prototype = {
|
||||
}.bind(this));
|
||||
},
|
||||
loadFile: function loadFile(data) {
|
||||
function notifyLoadFileListener(data) {
|
||||
if (!win.wrappedJSObject.onLoadFileCallback) {
|
||||
return;
|
||||
}
|
||||
win.wrappedJSObject.onLoadFileCallback(data);
|
||||
}
|
||||
|
||||
var url = data.url;
|
||||
var checkPolicyFile = data.checkPolicyFile;
|
||||
var sessionId = data.sessionId;
|
||||
@ -381,8 +398,8 @@ ChromeActions.prototype = {
|
||||
xhr.onprogress = function (e) {
|
||||
var position = e.loaded;
|
||||
var data = new Uint8Array(xhr.response);
|
||||
win.postMessage({callback:"loadFile", sessionId: sessionId, topic: "progress",
|
||||
array: data, loaded: e.loaded, total: e.total}, "*");
|
||||
notifyLoadFileListener({callback:"loadFile", sessionId: sessionId,
|
||||
topic: "progress", array: data, loaded: e.loaded, total: e.total});
|
||||
lastPosition = position;
|
||||
if (limit && e.total >= limit) {
|
||||
xhr.abort();
|
||||
@ -391,16 +408,15 @@ ChromeActions.prototype = {
|
||||
xhr.onreadystatechange = function(event) {
|
||||
if (xhr.readyState === 4) {
|
||||
if (xhr.status !== 200 && xhr.status !== 0) {
|
||||
win.postMessage({callback:"loadFile", sessionId: sessionId, topic: "error",
|
||||
error: xhr.statusText}, "*");
|
||||
notifyLoadFileListener({callback:"loadFile", sessionId: sessionId, topic: "error", error: xhr.statusText});
|
||||
}
|
||||
win.postMessage({callback:"loadFile", sessionId: sessionId, topic: "close"}, "*");
|
||||
notifyLoadFileListener({callback:"loadFile", sessionId: sessionId, topic: "close"});
|
||||
}
|
||||
};
|
||||
if (mimeType)
|
||||
xhr.setRequestHeader("Content-Type", mimeType);
|
||||
xhr.send(postData);
|
||||
win.postMessage({callback:"loadFile", sessionId: sessionId, topic: "open"}, "*");
|
||||
notifyLoadFileListener({callback:"loadFile", sessionId: sessionId, topic: "open"});
|
||||
};
|
||||
|
||||
this._canDownloadFile({url: url, checkPolicyFile: checkPolicyFile}, function (data) {
|
||||
@ -408,28 +424,65 @@ ChromeActions.prototype = {
|
||||
performXHR();
|
||||
} else {
|
||||
log("data access id prohibited to " + url + " from " + baseUrl);
|
||||
win.postMessage({callback:"loadFile", sessionId: sessionId, topic: "error",
|
||||
error: "only original swf file or file from the same origin loading supported"}, "*");
|
||||
notifyLoadFileListener({callback:"loadFile", sessionId: sessionId, topic: "error",
|
||||
error: "only original swf file or file from the same origin loading supported"});
|
||||
}
|
||||
});
|
||||
},
|
||||
navigateTo: function (data) {
|
||||
var embedTag = this.embedTag.wrappedJSObject;
|
||||
var window = embedTag ? embedTag.ownerDocument.defaultView : this.window;
|
||||
window.open(data.url, data.target || '_self');
|
||||
},
|
||||
fallback: function(automatic) {
|
||||
automatic = !!automatic;
|
||||
fallbackToNativePlugin(this.window, !automatic, automatic);
|
||||
},
|
||||
setClipboard: function (data) {
|
||||
userInput: function() {
|
||||
var win = this.window;
|
||||
var winUtils = win.QueryInterface(Components.interfaces.nsIInterfaceRequestor).
|
||||
getInterface(Components.interfaces.nsIDOMWindowUtils);
|
||||
if (winUtils.isHandlingUserInput) {
|
||||
this.lastUserInput = Date.now();
|
||||
}
|
||||
},
|
||||
isUserInputInProgress: function () {
|
||||
// TODO userInput does not work for OOP
|
||||
if (!getBoolPref('shumway.userInputSecurity', true)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// We don't trust our Shumway non-privileged code just yet to verify the
|
||||
// user input -- using monitorUserInput function below to track that.
|
||||
if (typeof data !== 'string' ||
|
||||
(Date.now() - this.lastUserInput) > MAX_USER_INPUT_TIMEOUT) {
|
||||
return;
|
||||
// user input -- using userInput function above to track that.
|
||||
if ((Date.now() - this.lastUserInput) > MAX_USER_INPUT_TIMEOUT) {
|
||||
return false;
|
||||
}
|
||||
// TODO other security checks?
|
||||
return true;
|
||||
},
|
||||
setClipboard: function (data) {
|
||||
if (typeof data !== 'string' || !this.isUserInputInProgress()) {
|
||||
return;
|
||||
}
|
||||
|
||||
let clipboard = Cc["@mozilla.org/widget/clipboardhelper;1"]
|
||||
.getService(Ci.nsIClipboardHelper);
|
||||
clipboard.copyString(data);
|
||||
},
|
||||
setFullscreen: function (enabled) {
|
||||
enabled = !!enabled;
|
||||
|
||||
if (!this.isUserInputInProgress()) {
|
||||
return;
|
||||
}
|
||||
|
||||
var target = this.embedTag || this.document.body;
|
||||
if (enabled) {
|
||||
target.mozRequestFullScreen();
|
||||
} else {
|
||||
target.ownerDocument.mozCancelFullScreen();
|
||||
}
|
||||
},
|
||||
endActivation: function () {
|
||||
if (ActivationQueue.currentNonActive === this) {
|
||||
ActivationQueue.activateNext();
|
||||
@ -487,20 +540,15 @@ ChromeActions.prototype = {
|
||||
getVersionInfo().then(function (versions) {
|
||||
params.versions = versions;
|
||||
}).then(function () {
|
||||
params.ffbuild = encodeURIComponent(params.versions.geckoMstone +
|
||||
' (' + params.versions.geckoBuildID + ')');
|
||||
params.shubuild = encodeURIComponent(params.versions.shumwayVersion);
|
||||
params.exceptions = encodeURIComponent(exceptions);
|
||||
var comment = '%2B%2B%2B This bug was initially via the problem reporting functionality in ' +
|
||||
'Shumway %2B%2B%2B%0A%0A' +
|
||||
'Please add any further information that you deem helpful here:%0A%0A%0A' +
|
||||
'----------------------%0A%0A' +
|
||||
'Technical Information:%0A' +
|
||||
'Firefox version: ' + params.ffbuild + '%0A' +
|
||||
'Shumway version: ' + params.shubuild;
|
||||
url = url.split('{comment}').join(comment);
|
||||
//this.window.openDialog('chrome://browser/content', '_blank', 'all,dialog=no', url);
|
||||
dump(111);
|
||||
var ffbuild = params.versions.geckoVersion + ' (' + params.versions.geckoBuildID + ')';
|
||||
//params.exceptions = encodeURIComponent(exceptions);
|
||||
var comment = '+++ Initially filed via the problem reporting functionality in Shumway +++\n' +
|
||||
'Please add any further information that you deem helpful here:\n\n\n\n' +
|
||||
'----------------------\n\n' +
|
||||
'Technical Information:\n' +
|
||||
'Firefox version: ' + ffbuild + '\n' +
|
||||
'Shumway version: ' + params.versions.shumwayVersion;
|
||||
url = url.split('{comment}').join(encodeURIComponent(comment));
|
||||
this.window.open(url);
|
||||
}.bind(this));
|
||||
},
|
||||
@ -517,8 +565,7 @@ ChromeActions.prototype = {
|
||||
return;
|
||||
|
||||
this.externalComInitialized = true;
|
||||
var eventTarget = this.window.document;
|
||||
initExternalCom(parentWindow, embedTag, eventTarget);
|
||||
initExternalCom(parentWindow, embedTag, this.window);
|
||||
return;
|
||||
case 'getId':
|
||||
return embedTag.id;
|
||||
@ -537,33 +584,15 @@ ChromeActions.prototype = {
|
||||
}
|
||||
};
|
||||
|
||||
function monitorUserInput(actions) {
|
||||
function notifyUserInput() {
|
||||
var win = actions.window;
|
||||
var winUtils = win.QueryInterface(Components.interfaces.nsIInterfaceRequestor).
|
||||
getInterface(Components.interfaces.nsIDOMWindowUtils);
|
||||
if (winUtils.isHandlingUserInput) {
|
||||
actions.lastUserInput = Date.now();
|
||||
}
|
||||
}
|
||||
|
||||
var document = actions.document;
|
||||
document.addEventListener('mousedown', notifyUserInput, false);
|
||||
document.addEventListener('mouseup', notifyUserInput, false);
|
||||
document.addEventListener('keydown', notifyUserInput, false);
|
||||
document.addEventListener('keyup', notifyUserInput, false);
|
||||
}
|
||||
|
||||
// Event listener to trigger chrome privedged code.
|
||||
function RequestListener(actions) {
|
||||
this.actions = actions;
|
||||
}
|
||||
// Receive an event and synchronously or asynchronously responds.
|
||||
RequestListener.prototype.receive = function(event) {
|
||||
var message = event.target;
|
||||
var action = event.detail.action;
|
||||
var data = event.detail.data;
|
||||
var sync = event.detail.sync;
|
||||
RequestListener.prototype.receive = function(detail) {
|
||||
var action = detail.action;
|
||||
var data = detail.data;
|
||||
var sync = detail.sync;
|
||||
var actions = this.actions;
|
||||
if (!(action in actions)) {
|
||||
log('Unknown action: ' + action);
|
||||
@ -571,30 +600,23 @@ RequestListener.prototype.receive = function(event) {
|
||||
}
|
||||
if (sync) {
|
||||
var response = actions[action].call(this.actions, data);
|
||||
event.detail.response = response;
|
||||
} else {
|
||||
var response;
|
||||
if (event.detail.callback) {
|
||||
var cookie = event.detail.cookie;
|
||||
response = function sendResponse(response) {
|
||||
var doc = actions.document;
|
||||
try {
|
||||
var listener = doc.createEvent('CustomEvent');
|
||||
listener.initCustomEvent('shumway.response', true, false,
|
||||
makeContentReadable({
|
||||
response: response,
|
||||
cookie: cookie
|
||||
}, doc.defaultView));
|
||||
|
||||
return message.dispatchEvent(listener);
|
||||
} catch (e) {
|
||||
// doc is no longer accessible because the requestor is already
|
||||
// gone. unloaded content cannot receive the response anyway.
|
||||
}
|
||||
};
|
||||
}
|
||||
actions[action].call(this.actions, data, response);
|
||||
return response === undefined ? undefined : JSON.stringify(response);
|
||||
}
|
||||
|
||||
var responseCallback;
|
||||
if (detail.callback) {
|
||||
var cookie = detail.cookie;
|
||||
response = function sendResponse(response) {
|
||||
var win = actions.window;
|
||||
if (win.wrappedJSObject.onMessageCallback) {
|
||||
win.wrappedJSObject.onMessageCallback({
|
||||
response: response === undefined ? undefined : JSON.stringify(response),
|
||||
cookie: cookie
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
actions[action].call(this.actions, data, responseCallback);
|
||||
};
|
||||
|
||||
var ActivationQueue = {
|
||||
@ -696,7 +718,7 @@ var ActivationQueue = {
|
||||
}
|
||||
};
|
||||
|
||||
function activateShumwayScripts(window, preview) {
|
||||
function activateShumwayScripts(window, requestListener) {
|
||||
function loadScripts(scripts, callback) {
|
||||
function loadScript(i) {
|
||||
if (i >= scripts.length) {
|
||||
@ -717,14 +739,12 @@ function activateShumwayScripts(window, preview) {
|
||||
}
|
||||
|
||||
function initScripts() {
|
||||
loadScripts(['resource://shumway/shumway.gfx.js',
|
||||
'resource://shumway/web/viewer.js'], function () {
|
||||
window.wrappedJSObject.runViewer();
|
||||
});
|
||||
window.wrappedJSObject.notifyShumwayMessage = function () {
|
||||
return requestListener.receive.apply(requestListener, arguments);
|
||||
};
|
||||
window.wrappedJSObject.runViewer();
|
||||
}
|
||||
|
||||
window.wrappedJSObject.SHUMWAY_ROOT = "resource://shumway/";
|
||||
|
||||
if (window.document.readyState === "interactive" ||
|
||||
window.document.readyState === "complete") {
|
||||
initScripts();
|
||||
@ -733,7 +753,7 @@ function activateShumwayScripts(window, preview) {
|
||||
}
|
||||
}
|
||||
|
||||
function initExternalCom(wrappedWindow, wrappedObject, targetDocument) {
|
||||
function initExternalCom(wrappedWindow, wrappedObject, targetWindow) {
|
||||
if (!wrappedWindow.__flash__initialized) {
|
||||
wrappedWindow.__flash__initialized = true;
|
||||
wrappedWindow.__flash__toXML = function __flash__toXML(obj) {
|
||||
@ -777,18 +797,15 @@ function initExternalCom(wrappedWindow, wrappedObject, targetDocument) {
|
||||
}
|
||||
wrappedObject.__flash__registerCallback = function (functionName) {
|
||||
wrappedWindow.console.log('__flash__registerCallback: ' + functionName);
|
||||
this[functionName] = function () {
|
||||
Components.utils.exportFunction(function () {
|
||||
var args = Array.prototype.slice.call(arguments, 0);
|
||||
wrappedWindow.console.log('__flash__callIn: ' + functionName);
|
||||
var e = targetDocument.createEvent('CustomEvent');
|
||||
e.initCustomEvent('shumway.remote', true, false, makeContentReadable({
|
||||
functionName: functionName,
|
||||
args: args,
|
||||
result: undefined
|
||||
}, targetDocument.defaultView));
|
||||
targetDocument.dispatchEvent(e);
|
||||
return e.detail.result;
|
||||
};
|
||||
var result;
|
||||
if (targetWindow.wrappedJSObject.onExternalCallback) {
|
||||
result = targetWindow.wrappedJSObject.onExternalCallback({functionName: functionName, args: args});
|
||||
}
|
||||
return wrappedWindow.eval(result);
|
||||
}, this, { defineAs: functionName });
|
||||
};
|
||||
wrappedObject.__flash__unregisterCallback = function (functionName) {
|
||||
wrappedWindow.console.log('__flash__unregisterCallback: ' + functionName);
|
||||
@ -849,6 +866,12 @@ ShumwayStreamConverterBase.prototype = {
|
||||
}
|
||||
|
||||
if (isOverlay) {
|
||||
// HACK For Facebook, CSS embed tag rescaling -- iframe (our overlay)
|
||||
// has no styling in document. Shall removed with jsplugins.
|
||||
for (var child = window.frameElement; child !== element; child = child.parentNode) {
|
||||
child.setAttribute('style', 'max-width: 100%; max-height: 100%');
|
||||
}
|
||||
|
||||
// Checking if overlay is a proper PlayPreview overlay.
|
||||
for (var i = 0; i < element.children.length; i++) {
|
||||
if (element.children[i] === containerElement) {
|
||||
@ -860,7 +883,7 @@ ShumwayStreamConverterBase.prototype = {
|
||||
|
||||
if (element) {
|
||||
// Getting absolute URL from the EMBED tag
|
||||
url = element.srcURI.spec;
|
||||
url = element.srcURI && element.srcURI.spec;
|
||||
|
||||
pageUrl = element.ownerDocument.location.href; // proper page url?
|
||||
|
||||
@ -961,14 +984,8 @@ ShumwayStreamConverterBase.prototype = {
|
||||
|
||||
var originalURI = aRequest.URI;
|
||||
|
||||
// checking if the plug-in shall be run in simple mode
|
||||
var isSimpleMode = originalURI.spec === EXPECTED_PLAYPREVIEW_URI_PREFIX &&
|
||||
getBoolPref('shumway.simpleMode', false);
|
||||
|
||||
// Create a new channel that loads the viewer as a resource.
|
||||
var viewerUrl = isSimpleMode ?
|
||||
'resource://shumway/web/simple.html' :
|
||||
'resource://shumway/web/viewer.html';
|
||||
// Create a new channel that loads the viewer as a chrome resource.
|
||||
var viewerUrl = 'chrome://shumway/content/viewer.wrapper.html';
|
||||
var channel = Services.io.newChannel(viewerUrl, null, null);
|
||||
|
||||
var converter = this;
|
||||
@ -1008,17 +1025,13 @@ ShumwayStreamConverterBase.prototype = {
|
||||
ShumwayTelemetry.onPageIndex(0);
|
||||
}
|
||||
|
||||
actions.activationCallback = function(domWindow, isSimpleMode) {
|
||||
delete this.activationCallback;
|
||||
activateShumwayScripts(domWindow, isSimpleMode);
|
||||
}.bind(actions, domWindow, isSimpleMode);
|
||||
ActivationQueue.enqueue(actions);
|
||||
|
||||
let requestListener = new RequestListener(actions);
|
||||
domWindow.addEventListener('shumway.message', function(event) {
|
||||
requestListener.receive(event);
|
||||
}, false, true);
|
||||
monitorUserInput(actions);
|
||||
|
||||
actions.activationCallback = function(domWindow, requestListener) {
|
||||
delete this.activationCallback;
|
||||
activateShumwayScripts(domWindow, requestListener);
|
||||
}.bind(actions, domWindow, requestListener);
|
||||
ActivationQueue.enqueue(actions);
|
||||
|
||||
listener.onStopRequest(aRequest, context, statusCode);
|
||||
}
|
||||
@ -1028,12 +1041,11 @@ ShumwayStreamConverterBase.prototype = {
|
||||
channel.originalURI = aRequest.URI;
|
||||
channel.loadGroup = aRequest.loadGroup;
|
||||
|
||||
// We can use resource principal when data is fetched by the chrome
|
||||
// e.g. useful for NoScript
|
||||
// We can use all powerful principal: we are opening chrome:// web page,
|
||||
// which will need lots of permission.
|
||||
var securityManager = Cc['@mozilla.org/scriptsecuritymanager;1']
|
||||
.getService(Ci.nsIScriptSecurityManager);
|
||||
var uri = Services.io.newURI(viewerUrl, null, null);
|
||||
var resourcePrincipal = securityManager.getNoAppCodebasePrincipal(uri);
|
||||
var resourcePrincipal = securityManager.getSystemPrincipal();
|
||||
aRequest.owner = resourcePrincipal;
|
||||
channel.asyncOpen(proxy, aContext);
|
||||
},
|
||||
|
@ -15,12 +15,8 @@
|
||||
|
||||
var EXPORTED_SYMBOLS = ["ShumwayUtils"];
|
||||
|
||||
const RESOURCE_NAME = 'shumway';
|
||||
const EXT_PREFIX = 'shumway@research.mozilla.org';
|
||||
const SWF_CONTENT_TYPE = 'application/x-shockwave-flash';
|
||||
const PREF_PREFIX = 'shumway.';
|
||||
const PREF_DISABLED = PREF_PREFIX + 'disabled';
|
||||
const PREF_IGNORE_CTP = PREF_PREFIX + 'ignoreCTP';
|
||||
|
||||
let Cc = Components.classes;
|
||||
let Ci = Components.interfaces;
|
||||
@ -30,14 +26,6 @@ let Cu = Components.utils;
|
||||
Cu.import('resource://gre/modules/XPCOMUtils.jsm');
|
||||
Cu.import('resource://gre/modules/Services.jsm');
|
||||
|
||||
let Svc = {};
|
||||
XPCOMUtils.defineLazyServiceGetter(Svc, 'mime',
|
||||
'@mozilla.org/mime;1',
|
||||
'nsIMIMEService');
|
||||
XPCOMUtils.defineLazyServiceGetter(Svc, 'pluginHost',
|
||||
'@mozilla.org/plugin/host;1',
|
||||
'nsIPluginHost');
|
||||
|
||||
function getBoolPref(pref, def) {
|
||||
try {
|
||||
return Services.prefs.getBoolPref(pref);
|
||||
@ -50,31 +38,6 @@ function log(str) {
|
||||
dump(str + '\n');
|
||||
}
|
||||
|
||||
// Register/unregister a constructor as a factory.
|
||||
function Factory() {}
|
||||
Factory.prototype = {
|
||||
register: function register(targetConstructor) {
|
||||
var proto = targetConstructor.prototype;
|
||||
this._classID = proto.classID;
|
||||
|
||||
var factory = XPCOMUtils._getFactory(targetConstructor);
|
||||
this._factory = factory;
|
||||
|
||||
var registrar = Cm.QueryInterface(Ci.nsIComponentRegistrar);
|
||||
registrar.registerFactory(proto.classID, proto.classDescription,
|
||||
proto.contractID, factory);
|
||||
},
|
||||
|
||||
unregister: function unregister() {
|
||||
var registrar = Cm.QueryInterface(Ci.nsIComponentRegistrar);
|
||||
registrar.unregisterFactory(this._classID, this._factory);
|
||||
this._factory = null;
|
||||
}
|
||||
};
|
||||
|
||||
let converterFactory = new Factory();
|
||||
let overlayConverterFactory = new Factory();
|
||||
|
||||
let ShumwayUtils = {
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver]),
|
||||
_registered: false,
|
||||
@ -85,6 +48,10 @@ let ShumwayUtils = {
|
||||
else
|
||||
this._ensureUnregistered();
|
||||
|
||||
Cc["@mozilla.org/parentprocessmessagemanager;1"]
|
||||
.getService(Ci.nsIMessageBroadcaster)
|
||||
.addMessageListener('Shumway:Chrome:isEnabled', this);
|
||||
|
||||
// Listen for when shumway is completely disabled.
|
||||
Services.prefs.addObserver(PREF_DISABLED, this, false);
|
||||
},
|
||||
@ -96,6 +63,13 @@ let ShumwayUtils = {
|
||||
else
|
||||
this._ensureUnregistered();
|
||||
},
|
||||
|
||||
receiveMessage: function(message) {
|
||||
switch (message.name) {
|
||||
case 'Shumway:Chrome:isEnabled':
|
||||
return this.enabled;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* shumway is only enabled if the global switch enabling is true.
|
||||
@ -110,17 +84,16 @@ let ShumwayUtils = {
|
||||
return;
|
||||
|
||||
// Load the component and register it.
|
||||
Cu.import('resource://shumway/ShumwayStreamConverter.jsm');
|
||||
converterFactory.register(ShumwayStreamConverter);
|
||||
overlayConverterFactory.register(ShumwayStreamOverlayConverter);
|
||||
|
||||
var ignoreCTP = getBoolPref(PREF_IGNORE_CTP, true);
|
||||
|
||||
Svc.pluginHost.registerPlayPreviewMimeType(SWF_CONTENT_TYPE, ignoreCTP);
|
||||
Cu.import('resource://shumway/ShumwayBootstrapUtils.jsm');
|
||||
ShumwayBootstrapUtils.register();
|
||||
|
||||
this._registered = true;
|
||||
|
||||
log('Shumway is registered');
|
||||
|
||||
let globalMM = Cc['@mozilla.org/globalmessagemanager;1']
|
||||
.getService(Ci.nsIFrameScriptLoader);
|
||||
globalMM.broadcastAsyncMessage('Shumway:Child:refreshSettings');
|
||||
},
|
||||
|
||||
_ensureUnregistered: function _ensureUnregistered() {
|
||||
@ -128,14 +101,15 @@ let ShumwayUtils = {
|
||||
return;
|
||||
|
||||
// Remove the contract/component.
|
||||
converterFactory.unregister();
|
||||
overlayConverterFactory.unregister();
|
||||
Cu.unload('resource://shumway/ShumwayStreamConverter.jsm');
|
||||
|
||||
Svc.pluginHost.unregisterPlayPreviewMimeType(SWF_CONTENT_TYPE);
|
||||
ShumwayBootstrapUtils.unregister();
|
||||
Cu.unload('resource://shumway/ShumwayBootstrapUtils.jsm');
|
||||
|
||||
this._registered = false;
|
||||
|
||||
log('Shumway is unregistered');
|
||||
|
||||
let globalMM = Cc['@mozilla.org/globalmessagemanager;1']
|
||||
.getService(Ci.nsIFrameScriptLoader);
|
||||
globalMM.broadcastAsyncMessage('Shumway:Child:refreshSettings');
|
||||
}
|
||||
};
|
||||
|
Binary file not shown.
Binary file not shown.
@ -1,127 +0,0 @@
|
||||
/*
|
||||
precision mediump float;
|
||||
|
||||
varying vec4 vColor;
|
||||
uniform sampler2D uSampler;
|
||||
varying vec2 vCoordinate;
|
||||
|
||||
out vec4 FragmentColor;
|
||||
|
||||
uniform float offset[5] = float[]( 0.0, 1.0, 2.0, 3.0, 4.0 );
|
||||
uniform float weight[5] = float[]( 0.2270270270, 0.1945945946, 0.1216216216,
|
||||
0.0540540541, 0.0162162162 );
|
||||
|
||||
void main(void)
|
||||
{
|
||||
FragmentColor = texture2D( uSampler, vec2(vCoordinate) * weight[0];
|
||||
for (int i=1; i<5; i++) {
|
||||
FragmentColor +=
|
||||
texture2D( uSampler, ( vec2(gl_FragCoord)+vec2(0.0, offset[i]) )/1024.0 )
|
||||
* weight[i];
|
||||
FragmentColor +=
|
||||
texture2D( uSampler, ( vec2(gl_FragCoord)-vec2(0.0, offset[i]) )/1024.0 )
|
||||
* weight[i];
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
precision mediump float;
|
||||
|
||||
varying vec4 vColor;
|
||||
uniform sampler2D uSampler;
|
||||
varying vec2 vCoordinate;
|
||||
|
||||
void main() {
|
||||
const int sampleRadius = 16;
|
||||
const int samples = sampleRadius * 2 + 1;
|
||||
float dy = 1.0 / 512.0;
|
||||
vec4 sample = vec4(0, 0, 0, 0);
|
||||
for (int i = -sampleRadius; i <= sampleRadius; i++) {
|
||||
sample += texture2D(uSampler, vCoordinate + vec2(0, float(i) * dy));
|
||||
}
|
||||
gl_FragColor = sample / float(samples);
|
||||
// gl_FragColor = texture2D(uSampler, vCoordinate);
|
||||
}
|
||||
*/
|
||||
|
||||
precision mediump float;
|
||||
|
||||
varying vec4 vColor;
|
||||
uniform sampler2D uSampler;
|
||||
varying vec2 vCoordinate;
|
||||
|
||||
void main() {
|
||||
vec4 sum = vec4(0.0);
|
||||
float blur = 1.0 / 512.0 * 1.0;
|
||||
sum += texture2D(uSampler, vec2(vCoordinate.x - 4.0 * blur, vCoordinate.y)) * 0.05;
|
||||
sum += texture2D(uSampler, vec2(vCoordinate.x - 3.0 * blur, vCoordinate.y)) * 0.09;
|
||||
sum += texture2D(uSampler, vec2(vCoordinate.x - 2.0 * blur, vCoordinate.y)) * 0.12;
|
||||
sum += texture2D(uSampler, vec2(vCoordinate.x - blur, vCoordinate.y)) * 0.15;
|
||||
sum += texture2D(uSampler, vec2(vCoordinate.x, vCoordinate.y)) * 0.16;
|
||||
sum += texture2D(uSampler, vec2(vCoordinate.x + blur, vCoordinate.y)) * 0.15;
|
||||
sum += texture2D(uSampler, vec2(vCoordinate.x + 2.0 * blur, vCoordinate.y)) * 0.12;
|
||||
sum += texture2D(uSampler, vec2(vCoordinate.x + 3.0 * blur, vCoordinate.y)) * 0.09;
|
||||
sum += texture2D(uSampler, vec2(vCoordinate.x + 4.0 * blur, vCoordinate.y)) * 0.05;
|
||||
gl_FragColor = sum;
|
||||
// gl_FragColor = texture2D(uSampler, vCoordinate);
|
||||
}
|
||||
|
||||
/*
|
||||
precision mediump float;
|
||||
|
||||
varying vec4 vColor;
|
||||
uniform sampler2D uSampler;
|
||||
varying vec2 vCoordinate;
|
||||
|
||||
void main() {
|
||||
vec4 sum = vec4(0.0);
|
||||
float blur = 0.1;
|
||||
sum += texture2D(uSampler, vec2(vCoordinate.x - 4.0 * blur, vCoordinate.y)) * 0.05;
|
||||
sum += texture2D(uSampler, vec2(vCoordinate.x - 3.0 * blur, vCoordinate.y)) * 0.09;
|
||||
sum += texture2D(uSampler, vec2(vCoordinate.x - 2.0 * blur, vCoordinate.y)) * 0.12;
|
||||
sum += texture2D(uSampler, vec2(vCoordinate.x - blur, vCoordinate.y)) * 0.15;
|
||||
sum += texture2D(uSampler, vec2(vCoordinate.x, vCoordinate.y)) * 0.16;
|
||||
sum += texture2D(uSampler, vec2(vCoordinate.x + blur, vCoordinate.y)) * 0.15;
|
||||
sum += texture2D(uSampler, vec2(vCoordinate.x + 2.0 * blur, vCoordinate.y)) * 0.12;
|
||||
sum += texture2D(uSampler, vec2(vCoordinate.x + 3.0 * blur, vCoordinate.y)) * 0.09;
|
||||
sum += texture2D(uSampler, vec2(vCoordinate.x + 4.0 * blur, vCoordinate.y)) * 0.05;
|
||||
gl_FragColor = sum;
|
||||
// gl_FragColor = texture2D(uSampler, vCoordinate);
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
precision mediump float;
|
||||
|
||||
varying vec4 vColor;
|
||||
uniform sampler2D uSampler;
|
||||
varying vec2 vCoordinate;
|
||||
|
||||
void main() {
|
||||
gl_FragColor = texture2D(uSampler, vCoordinate);
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
/*
|
||||
precision mediump float;
|
||||
varying vec2 vCoordinate;
|
||||
varying float vColor;
|
||||
uniform float blur;
|
||||
uniform sampler2D uSampler;
|
||||
void main(void) {
|
||||
vec4 sum = vec4(0.0);
|
||||
sum += texture2D(uSampler, vec2(vCoordinate.x - 4.0*blur, vCoordinate.y)) * 0.05;
|
||||
sum += texture2D(uSampler, vec2(vCoordinate.x - 3.0*blur, vCoordinate.y)) * 0.09;
|
||||
sum += texture2D(uSampler, vec2(vCoordinate.x - 2.0*blur, vCoordinate.y)) * 0.12;
|
||||
sum += texture2D(uSampler, vec2(vCoordinate.x - blur, vCoordinate.y)) * 0.15;
|
||||
sum += texture2D(uSampler, vec2(vCoordinate.x, vCoordinate.y)) * 0.16;
|
||||
sum += texture2D(uSampler, vec2(vCoordinate.x + blur, vCoordinate.y)) * 0.15;
|
||||
sum += texture2D(uSampler, vec2(vCoordinate.x + 2.0*blur, vCoordinate.y)) * 0.12;
|
||||
sum += texture2D(uSampler, vec2(vCoordinate.x + 3.0*blur, vCoordinate.y)) * 0.09;
|
||||
sum += texture2D(uSampler, vec2(vCoordinate.x + 4.0*blur, vCoordinate.y)) * 0.05;
|
||||
gl_FragColor = sum;
|
||||
}
|
||||
|
||||
*/
|
@ -1,16 +0,0 @@
|
||||
precision mediump float;
|
||||
|
||||
varying vec4 vColor;
|
||||
uniform sampler2D uSampler;
|
||||
varying vec2 vCoordinate;
|
||||
|
||||
void main() {
|
||||
const int sampleRadius = 8;
|
||||
const int samples = sampleRadius * 2 + 1;
|
||||
float dx = 0.01;
|
||||
vec4 sample = vec4(0, 0, 0, 0);
|
||||
for (int i = -sampleRadius; i <= sampleRadius; i++) {
|
||||
sample += texture2D(uSampler, vCoordinate + vec2(0, float(i) * dy));
|
||||
}
|
||||
gl_FragColor = sample / float(samples);
|
||||
}
|
@ -1,19 +0,0 @@
|
||||
uniform vec2 uResolution;
|
||||
uniform mat3 uTransformMatrix;
|
||||
uniform float uZ;
|
||||
|
||||
attribute vec2 aPosition;
|
||||
attribute vec4 aColor;
|
||||
attribute vec2 aCoordinate;
|
||||
|
||||
varying vec4 vColor;
|
||||
varying vec2 vCoordinate;
|
||||
|
||||
void main() {
|
||||
vec2 position = ((uTransformMatrix * vec3(aPosition, 1.0)).xy / uResolution) * 2.0 - 1.0;
|
||||
position *= vec2(1.0, -1.0);
|
||||
// position *= vec2(40.0, -4.0);
|
||||
gl_Position = vec4(vec3(position, uZ), 1.0);
|
||||
vColor = aColor;
|
||||
vCoordinate = aCoordinate;
|
||||
}
|
@ -1,18 +0,0 @@
|
||||
precision mediump float;
|
||||
|
||||
uniform vec4 uColor;
|
||||
varying vec2 vTextureCoordinate;
|
||||
|
||||
void main() {
|
||||
gl_FragColor = uColor;
|
||||
gl_FragColor = vec4(vTextureCoordinate.x, vTextureCoordinate.y, 0, 0.5);
|
||||
|
||||
float u = vTextureCoordinate.x;
|
||||
float v = vTextureCoordinate.y;
|
||||
float r = u * u - v;
|
||||
if (r < 0.0) {
|
||||
gl_FragColor = vec4(1, 0, 0, 1);
|
||||
} else {
|
||||
gl_FragColor = vec4(1, 0, 0, 0.2);
|
||||
}
|
||||
}
|
@ -1,7 +0,0 @@
|
||||
precision mediump float;
|
||||
|
||||
varying vec4 vColor;
|
||||
|
||||
void main() {
|
||||
gl_FragColor = vColor;
|
||||
}
|
@ -1,15 +0,0 @@
|
||||
uniform vec2 uResolution;
|
||||
uniform mat3 uTransformMatrix;
|
||||
uniform float uZ;
|
||||
|
||||
attribute vec2 aPosition;
|
||||
attribute vec4 aColor;
|
||||
|
||||
varying vec4 vColor;
|
||||
|
||||
void main() {
|
||||
vec2 position = ((uTransformMatrix * vec3(aPosition, 1.0)).xy / uResolution) * 2.0 - 1.0;
|
||||
position *= vec2(1.0, -1.0);
|
||||
gl_Position = vec4(vec3(position, uZ), 1.0);
|
||||
vColor = aColor;
|
||||
}
|
@ -1,12 +0,0 @@
|
||||
precision mediump float;
|
||||
|
||||
varying vec4 vColor;
|
||||
uniform sampler2D uSampler;
|
||||
varying vec2 vCoordinate;
|
||||
|
||||
void main() {
|
||||
// gl_FragColor = vColor;
|
||||
// gl_FragColor = vec4(vTextureCoordinate.x, vTextureCoordinate.y, 0, 0.5);
|
||||
// gl_FragColor = gl_FragColor; // + texture2D(uSampler, vCoordinate);
|
||||
gl_FragColor = texture2D(uSampler, vCoordinate);
|
||||
}
|
@ -1,19 +0,0 @@
|
||||
uniform vec2 uResolution;
|
||||
uniform mat3 uTransformMatrix;
|
||||
uniform float uZ;
|
||||
|
||||
attribute vec2 aPosition;
|
||||
attribute vec4 aColor;
|
||||
attribute vec2 aCoordinate;
|
||||
|
||||
varying vec4 vColor;
|
||||
varying vec2 vCoordinate;
|
||||
|
||||
void main() {
|
||||
vec2 position = ((uTransformMatrix * vec3(aPosition, 1.0)).xy / uResolution) * 2.0 - 1.0;
|
||||
position *= vec2(1.0, -1.0);
|
||||
// position *= vec2(40.0, -4.0);
|
||||
gl_Position = vec4(vec3(position, uZ), 1.0);
|
||||
vColor = aColor;
|
||||
vCoordinate = aCoordinate;
|
||||
}
|
Binary file not shown.
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,2 +1,2 @@
|
||||
0.9.2970
|
||||
22f884f
|
||||
0.9.3693
|
||||
217e2e2
|
||||
|
@ -35,7 +35,7 @@ limitations under the License.
|
||||
display: none;
|
||||
}
|
||||
|
||||
#stageContainer {
|
||||
#easelContainer {
|
||||
position:fixed !important;
|
||||
left:0;top:0;bottom:0;right:0;
|
||||
overflow: hidden;
|
||||
@ -49,7 +49,7 @@ limitations under the License.
|
||||
#overlay.enabled {
|
||||
display: block;
|
||||
position:fixed;
|
||||
bottom: 0;
|
||||
top: 0;
|
||||
right: 0;
|
||||
}
|
||||
|
||||
@ -58,7 +58,7 @@ limitations under the License.
|
||||
width: 70px; height: 16px;
|
||||
padding: 8px 4px 4px;
|
||||
color: white;
|
||||
background-color: rgba(0, 0, 0, 0.62);
|
||||
background-color: rgba(218, 56, 7, 0.63);
|
||||
font: bold 10px sans-serif;
|
||||
text-align: center;
|
||||
text-decoration: none;
|
||||
@ -100,7 +100,7 @@ limitations under the License.
|
||||
|
||||
<body contextmenu="shumwayMenu">
|
||||
<iframe id="playerWindow" width="9" height="9" src=""></iframe>
|
||||
<div id="stageContainer"></div>
|
||||
<div id="easelContainer"></div>
|
||||
<section>
|
||||
<div id="overlay">
|
||||
<a id="fallback" href="#">Shumway <span class="icon">×</span></a>
|
||||
@ -114,5 +114,8 @@ limitations under the License.
|
||||
<menuitem label="About Shumway" id="aboutMenu"></menuitem>
|
||||
</menu>
|
||||
</section>
|
||||
|
||||
<script src='resource://shumway/shumway.gfx.js'></script>
|
||||
<script src='resource://shumway/web/viewer.js'></script>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -27,11 +27,8 @@ var FirefoxCom = (function FirefoxComClosure() {
|
||||
* @return {*} The response.
|
||||
*/
|
||||
requestSync: function(action, data) {
|
||||
var e = document.createEvent('CustomEvent');
|
||||
e.initCustomEvent('shumway.message', true, false,
|
||||
{action: action, data: data, sync: true});
|
||||
document.dispatchEvent(e);
|
||||
return e.detail.response;
|
||||
var result = String(ShumwayCom.sendMessage(action, data, true, undefined));
|
||||
return result !== 'undefined' ? JSON.parse(result) : undefined;
|
||||
},
|
||||
/**
|
||||
* Creates an event that the extension is listening for and will
|
||||
@ -42,38 +39,45 @@ var FirefoxCom = (function FirefoxComClosure() {
|
||||
* with one data argument.
|
||||
*/
|
||||
request: function(action, data, callback) {
|
||||
var e = document.createEvent('CustomEvent');
|
||||
e.initCustomEvent('shumway.message', true, false,
|
||||
{action: action, data: data, sync: false});
|
||||
var cookie = undefined;
|
||||
if (callback) {
|
||||
if ('nextId' in FirefoxCom.request) {
|
||||
FirefoxCom.request.nextId = 1;
|
||||
cookie = "requestId" + (this._nextRequestId++);
|
||||
|
||||
if (!ShumwayCom.onMessageCallback) {
|
||||
ShumwayCom.onMessageCallback = this._notifyMessageCallback.bind(this);
|
||||
}
|
||||
var cookie = "requestId" + (FirefoxCom.request.nextId++);
|
||||
e.detail.cookie = cookie;
|
||||
e.detail.callback = true;
|
||||
|
||||
document.addEventListener('shumway.response', function listener(event) {
|
||||
if (cookie !== event.detail.cookie)
|
||||
return;
|
||||
|
||||
document.removeEventListener('shumway.response', listener, false);
|
||||
|
||||
var response = event.detail.response;
|
||||
return callback(response);
|
||||
}, false);
|
||||
this._requestCallbacks[cookie] = callback;
|
||||
}
|
||||
return document.dispatchEvent(e);
|
||||
ShumwayCom.sendMessage(action, data, false, cookie);
|
||||
},
|
||||
_notifyMessageCallback: function (cookie, response) {
|
||||
var callback = this._requestCallbacks[cookie];
|
||||
if (!callback) {
|
||||
return;
|
||||
}
|
||||
delete this._requestCallbacks[cookie];
|
||||
callback(response !== 'undefined' ? JSON.parse(response) : undefined);
|
||||
},
|
||||
_nextRequestId: 1,
|
||||
_requestCallbacks: Object.create(null),
|
||||
initJS: function (callback) {
|
||||
FirefoxCom.request('externalCom', {action: 'init'});
|
||||
document.addEventListener('shumway.remote', function (e) {
|
||||
e.detail.result = callback(e.detail.functionName, e.detail.args);
|
||||
}, false);
|
||||
ShumwayCom.onExternalCallback = function (call) {
|
||||
return callback(call.functionName, call.args);
|
||||
};
|
||||
}
|
||||
};
|
||||
})();
|
||||
|
||||
function notifyUserInput() {
|
||||
ShumwayCom.sendMessage('userInput', null, true, undefined);
|
||||
}
|
||||
|
||||
document.addEventListener('mousedown', notifyUserInput, true);
|
||||
document.addEventListener('mouseup', notifyUserInput, true);
|
||||
document.addEventListener('keydown', notifyUserInput, true);
|
||||
document.addEventListener('keyup', notifyUserInput, true);
|
||||
|
||||
function fallback() {
|
||||
FirefoxCom.requestSync('fallback', null)
|
||||
}
|
||||
@ -82,13 +86,14 @@ window.print = function(msg) {
|
||||
console.log(msg);
|
||||
};
|
||||
|
||||
var SHUMWAY_ROOT = "resource://shumway/";
|
||||
|
||||
var viewerPlayerglobalInfo = {
|
||||
abcs: SHUMWAY_ROOT + "playerglobal/playerglobal.abcs",
|
||||
catalog: SHUMWAY_ROOT + "playerglobal/playerglobal.json"
|
||||
};
|
||||
|
||||
var builtinPath = SHUMWAY_ROOT + "avm2/generated/builtin/builtin.abc";
|
||||
var avm1Path = SHUMWAY_ROOT + "avm2/generated/avm1lib/avm1lib.abc";
|
||||
|
||||
var playerWindow;
|
||||
var playerWindowLoaded = new Promise(function(resolve) {
|
||||
@ -101,7 +106,14 @@ var playerWindowLoaded = new Promise(function(resolve) {
|
||||
});
|
||||
|
||||
function runViewer() {
|
||||
var flashParams = JSON.parse(FirefoxCom.requestSync('getPluginParams', null));
|
||||
ShumwayCom.onLoadFileCallback = function (data) {
|
||||
playerWindow.postMessage({
|
||||
type: "loadFileResponse",
|
||||
args: data
|
||||
}, '*');
|
||||
};
|
||||
|
||||
var flashParams = FirefoxCom.requestSync('getPluginParams', null);
|
||||
|
||||
movieUrl = flashParams.url;
|
||||
if (!movieUrl) {
|
||||
@ -112,6 +124,7 @@ function runViewer() {
|
||||
|
||||
movieParams = flashParams.movieParams;
|
||||
objectParams = flashParams.objectParams;
|
||||
var baseUrl = flashParams.baseUrl;
|
||||
var isOverlay = flashParams.isOverlay;
|
||||
pauseExecution = flashParams.isPausedAtStart;
|
||||
|
||||
@ -125,7 +138,7 @@ function runViewer() {
|
||||
}
|
||||
|
||||
playerWindowLoaded.then(function () {
|
||||
parseSwf(movieUrl, movieParams, objectParams);
|
||||
parseSwf(movieUrl, baseUrl, movieParams, objectParams);
|
||||
});
|
||||
|
||||
if (isOverlay) {
|
||||
@ -193,12 +206,6 @@ var movieUrl, movieParams, objectParams;
|
||||
window.addEventListener("message", function handlerMessage(e) {
|
||||
var args = e.data;
|
||||
switch (args.callback) {
|
||||
case 'loadFile':
|
||||
playerWindow.postMessage({
|
||||
type: "loadFileResponse",
|
||||
args: args
|
||||
}, '*');
|
||||
break;
|
||||
case 'loadFileRequest':
|
||||
FirefoxCom.request('loadFile', args.data, null);
|
||||
break;
|
||||
@ -208,6 +215,9 @@ window.addEventListener("message", function handlerMessage(e) {
|
||||
case 'setClipboard':
|
||||
FirefoxCom.request('setClipboard', args.data, null);
|
||||
break;
|
||||
case 'navigateTo':
|
||||
FirefoxCom.request('navigateTo', args.data, null);
|
||||
break;
|
||||
case 'started':
|
||||
document.body.classList.add('started');
|
||||
break;
|
||||
@ -232,13 +242,11 @@ function processExternalCommand(command) {
|
||||
}
|
||||
}
|
||||
|
||||
function parseSwf(url, movieParams, objectParams) {
|
||||
var compilerSettings = JSON.parse(
|
||||
FirefoxCom.requestSync('getCompilerSettings', null));
|
||||
function parseSwf(url, baseUrl, movieParams, objectParams) {
|
||||
var compilerSettings = FirefoxCom.requestSync('getCompilerSettings', null);
|
||||
|
||||
// init misc preferences
|
||||
var turboMode = FirefoxCom.requestSync('getBoolPref', {pref: 'shumway.turboMode', def: false});
|
||||
Shumway.GFX.backend.value = FirefoxCom.requestSync('getBoolPref', {pref: 'shumway.webgl', def: false}) ? 1 : 0;
|
||||
Shumway.GFX.hud.value = FirefoxCom.requestSync('getBoolPref', {pref: 'shumway.hud', def: false});
|
||||
//forceHidpi.value = FirefoxCom.requestSync('getBoolPref', {pref: 'shumway.force_hidpi', def: false});
|
||||
//dummyAnimation.value = FirefoxCom.requestSync('getBoolPref', {pref: 'shumway.dummyMode', def: false});
|
||||
@ -249,22 +257,23 @@ function parseSwf(url, movieParams, objectParams) {
|
||||
FirefoxCom.request('endActivation', null);
|
||||
}
|
||||
|
||||
var bgcolor;
|
||||
var backgroundColor;
|
||||
if (objectParams) {
|
||||
var m;
|
||||
if (objectParams.bgcolor && (m = /#([0-9A-F]{6})/i.exec(objectParams.bgcolor))) {
|
||||
var hexColor = parseInt(m[1], 16);
|
||||
bgcolor = hexColor << 8 | 0xff;
|
||||
backgroundColor = hexColor << 8 | 0xff;
|
||||
}
|
||||
if (objectParams.wmode === 'transparent') {
|
||||
bgcolor = 0;
|
||||
backgroundColor = 0;
|
||||
}
|
||||
}
|
||||
|
||||
var easel = createEasel(bgcolor);
|
||||
var easel = createEasel(backgroundColor);
|
||||
easelHost = new Shumway.GFX.Window.WindowEaselHost(easel, playerWindow, window);
|
||||
easelHost.processExternalCommand = processExternalCommand;
|
||||
|
||||
var displayParameters = easel.getDisplayParameters();
|
||||
var data = {
|
||||
type: 'runSwf',
|
||||
settings: Shumway.Settings.getSettings(),
|
||||
@ -272,21 +281,21 @@ function parseSwf(url, movieParams, objectParams) {
|
||||
compilerSettings: compilerSettings,
|
||||
movieParams: movieParams,
|
||||
objectParams: objectParams,
|
||||
displayParameters: displayParameters,
|
||||
turboMode: turboMode,
|
||||
bgcolor: bgcolor,
|
||||
bgcolor: backgroundColor,
|
||||
url: url,
|
||||
baseUrl: url
|
||||
baseUrl: baseUrl || url
|
||||
}
|
||||
};
|
||||
playerWindow.postMessage(data, '*');
|
||||
}
|
||||
|
||||
function createEasel(bgcolor) {
|
||||
function createEasel(backgroundColor) {
|
||||
var Stage = Shumway.GFX.Stage;
|
||||
var Easel = Shumway.GFX.Easel;
|
||||
var Canvas2DStageRenderer = Shumway.GFX.Canvas2DStageRenderer;
|
||||
var Canvas2DRenderer = Shumway.GFX.Canvas2DRenderer;
|
||||
|
||||
Shumway.GFX.WebGL.SHADER_ROOT = SHUMWAY_ROOT + "gfx/gl/shaders/";
|
||||
var backend = Shumway.GFX.backend.value | 0;
|
||||
return new Easel(document.getElementById("stageContainer"), backend, false, bgcolor);
|
||||
return new Easel(document.getElementById("easelContainer"), false, backgroundColor);
|
||||
}
|
||||
|
@ -24,7 +24,6 @@ var viewerPlayerglobalInfo = {
|
||||
|
||||
var avm2Root = SHUMWAY_ROOT + "avm2/";
|
||||
var builtinPath = avm2Root + "generated/builtin/builtin.abc";
|
||||
var avm1Path = avm2Root + "generated/avm1lib/avm1lib.abc";
|
||||
|
||||
window.print = function(msg) {
|
||||
console.log(msg);
|
||||
@ -38,29 +37,32 @@ function runSwfPlayer(flashParams) {
|
||||
var appMode = compilerSettings.appCompiler ? EXECUTION_MODE.COMPILE : EXECUTION_MODE.INTERPRET;
|
||||
var asyncLoading = true;
|
||||
var baseUrl = flashParams.baseUrl;
|
||||
var movieParams = flashParams.movieParams;
|
||||
var objectParams = flashParams.objectParams;
|
||||
var movieUrl = flashParams.url;
|
||||
|
||||
Shumway.frameRateOption.value = flashParams.turboMode ? 60 : -1;
|
||||
Shumway.AVM2.Verifier.enabled.value = compilerSettings.verifier;
|
||||
|
||||
Shumway.createAVM2(builtinPath, viewerPlayerglobalInfo, avm1Path, sysMode, appMode, function (avm2) {
|
||||
Shumway.createAVM2(builtinPath, viewerPlayerglobalInfo, sysMode, appMode, function (avm2) {
|
||||
function runSWF(file) {
|
||||
var player = new Shumway.Player.Window.WindowPlayer(window, window.parent);
|
||||
player.defaultStageColor = flashParams.bgcolor;
|
||||
player.movieParams = flashParams.movieParams;
|
||||
player.stageAlign = (objectParams && (objectParams.salign || objectParams.align)) || '';
|
||||
player.stageScale = (objectParams && objectParams.scale) || 'showall';
|
||||
player.displayParameters = flashParams.displayParameters;
|
||||
|
||||
Shumway.ExternalInterfaceService.instance = player.createExternalInterfaceService();
|
||||
|
||||
player.load(file);
|
||||
}
|
||||
file = Shumway.FileLoadingService.instance.setBaseUrl(baseUrl);
|
||||
Shumway.FileLoadingService.instance.setBaseUrl(baseUrl);
|
||||
if (asyncLoading) {
|
||||
runSWF(movieUrl);
|
||||
} else {
|
||||
new Shumway.BinaryFileReader(movieUrl).readAll(null, function(buffer, error) {
|
||||
if (!buffer) {
|
||||
throw "Unable to open the file " + file + ": " + error;
|
||||
throw "Unable to open the file " + movieUrl + ": " + error;
|
||||
}
|
||||
runSWF(movieUrl, buffer);
|
||||
});
|
||||
@ -129,32 +131,34 @@ function setupServices() {
|
||||
};
|
||||
},
|
||||
setBaseUrl: function (url) {
|
||||
var baseUrl;
|
||||
if (typeof URL !== 'undefined') {
|
||||
baseUrl = new URL(url, document.location.href).href;
|
||||
} else {
|
||||
var a = document.createElement('a');
|
||||
a.href = url || '#';
|
||||
a.setAttribute('style', 'display: none;');
|
||||
document.body.appendChild(a);
|
||||
baseUrl = a.href;
|
||||
document.body.removeChild(a);
|
||||
}
|
||||
Shumway.FileLoadingService.instance.baseUrl = baseUrl;
|
||||
return baseUrl;
|
||||
Shumway.FileLoadingService.instance.baseUrl = url;
|
||||
},
|
||||
resolveUrl: function (url) {
|
||||
if (url.indexOf('://') >= 0) return url;
|
||||
|
||||
var base = Shumway.FileLoadingService.instance.baseUrl;
|
||||
base = base.lastIndexOf('/') >= 0 ? base.substring(0, base.lastIndexOf('/') + 1) : '';
|
||||
if (url.indexOf('/') === 0) {
|
||||
var m = /^[^:]+:\/\/[^\/]+/.exec(base);
|
||||
if (m) base = m[0];
|
||||
}
|
||||
return base + url;
|
||||
return new URL(url, Shumway.FileLoadingService.instance.baseUrl).href;
|
||||
},
|
||||
navigateTo: function (url, target) {
|
||||
window.parent.postMessage({
|
||||
callback: 'navigateTo',
|
||||
data: {
|
||||
url: this.resolveUrl(url),
|
||||
target: target
|
||||
}
|
||||
}, '*');
|
||||
}
|
||||
};
|
||||
|
||||
// Using SpecialInflate when chrome code provides it.
|
||||
if (parent.createSpecialInflate) {
|
||||
window.SpecialInflate = function () {
|
||||
return parent.createSpecialInflate();
|
||||
};
|
||||
}
|
||||
|
||||
// Using createRtmpXHR/createRtmpSocket when chrome code provides it.
|
||||
if (parent.createRtmpXHR) {
|
||||
window.createRtmpSocket = parent.createRtmpSocket;
|
||||
window.createRtmpXHR = parent.createRtmpXHR;
|
||||
}
|
||||
}
|
||||
|
||||
window.addEventListener('message', function onWindowMessage(e) {
|
||||
|
Loading…
Reference in New Issue
Block a user