This commit is contained in:
Yury Delendik 2015-02-10 17:27:27 -06:00
Родитель a82ac47af3
Коммит 98f236b344
18 изменённых файлов: 738 добавлений и 5 удалений

Просмотреть файл

@ -103,6 +103,9 @@ module.exports = function(grunt) {
(grunt.option('rebuild') ? ' -r' : ''),
cwd: 'utils/playerglobal-builder'
},
debug_server: {
cmd: 'node examples/inspector/debug/server.js'
},
gate: {
cmd: '"utils/jsshell/js" build/ts/shell.js -x -g ' +
(grunt.option('verbose') ? '-v ' : '') +

Просмотреть файл

@ -0,0 +1,130 @@
/*
* Copyright 2015 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.
*/
// Simple class for synchronous XHR communication.
// See also examples/inspector/debug/server.js.
var PingPongConnection = (function () {
function PingPongConnection(url, onlySend) {
this.url = url;
this.onData = null;
this.onError = null;
this.currentXhr = null;
this.closed = false;
if (!onlySend) {
this.idle();
}
}
PingPongConnection.prototype = {
idle: function () {
function requestIncoming(connection) {
var xhr = new XMLHttpRequest();
xhr.open('GET', connection.url + '?idle', true);
xhr.onload = function () {
if (xhr.status === 204 &&
xhr.getResponseHeader('X-PingPong-Error') === 'timeout') {
requestIncoming(connection);
return;
}
if (xhr.status === 200) {
var result;
if (connection.onData) {
var response = xhr.responseText;
result = connection.onData(response ? JSON.parse(response) : undefined);
}
if (xhr.getResponseHeader('X-PingPong-Async') === '1') {
requestIncoming(connection);
} else {
sendResponse(connection, result);
}
return;
}
if (connection.onError) {
connection.onError(xhr.statusText);
}
};
xhr.onerror = function () {
if (connection.onError) {
connection.onError(xhr.error);
}
};
xhr.send();
connection.currentXhr = xhr;
}
function sendResponse(connection, result) {
var xhr = new XMLHttpRequest();
xhr.open('POST', connection.url + '?response', false);
xhr.onload = function () {
if (xhr.status !== 204) {
if (connection.onError) {
connection.onError(xhr.statusText);
}
}
requestIncoming(connection);
};
xhr.onerror = function () {
if (connection.onError) {
connection.onError(xhr.error);
}
};
xhr.send(result === undefined ? '' : JSON.stringify(result));
connection.currentXhr = xhr;
}
requestIncoming(this);
},
send: function (data, async, timeout) {
if (this.closed) {
throw new Error('connection closed');
}
async = !!async;
timeout |= 0;
var encoded = data === undefined ? '' : JSON.stringify(data);
if (async) {
var xhr = new XMLHttpRequest();
xhr.open('POST', this.url + '?async', true);
xhr.send(encoded);
return;
} else {
var xhr = new XMLHttpRequest();
xhr.open('POST', this.url, false);
if (timeout > 0) {
xhr.setRequestHeader('X-PingPong-Timeout', timeout);
}
xhr.send(encoded);
if (xhr.status === 204 &&
xhr.getResponseHeader('X-PingPong-Error') === 'timeout') {
throw new Error('sync request timeout');
}
var response = xhr.responseText;
return response ? JSON.parse(response) : undefined;
}
},
close: function () {
if (this.currentXhr) {
this.currentXhr.abort();
this.currentXhr = null;
}
this.closed = true;
}
};
return PingPongConnection;
})();

Просмотреть файл

@ -0,0 +1,217 @@
/*
* Copyright 2015 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.
*/
/*jslint node: true */
// Simple HTTP server for synchronous XHR communication.
// See also examples/inspector/debug/pingpong.js.
'use strict';
var http = require('http');
var ALLOW_FROM_DOMAIN = 'http://localhost:8000';
var DEFAULT_BIND_HOST = 'localhost';
var DEFAULT_BIND_PORT = 8010;
var IDLE_TIMEOUT = 500;
var SYNC_TIMEOUT = 120000;
var incomingData = {};
var incomingResponse = {};
var outgoingResponse = {};
var currentReading = [];
var verbose = false;
function WebServer() {
this.host = DEFAULT_BIND_HOST;
this.port = DEFAULT_BIND_PORT;
this.server = null;
}
WebServer.prototype = {
start: function (callback) {
this.server = http.createServer(this._handler.bind(this));
this.server.listen(this.port, this.host, callback);
console.log(
'Server running at http://' + this.host + ':' + this.port + '/');
console.log('Allowing requests from: ' + ALLOW_FROM_DOMAIN);
},
stop: function (callback) {
this.server.close(callback);
this.server = null;
},
_handler: function (request, response) {
function setStandardHeaders(response) {
response.setHeader('Access-Control-Allow-Origin', ALLOW_FROM_DOMAIN);
response.setHeader('Access-Control-Allow-Headers', 'Content-Type,X-PingPong-Timeout');
response.setHeader('Access-Control-Expose-Headers', 'Content-Type,X-PingPong-Async,X-PingPong-From,X-PingPong-Error');
response.setHeader('Content-Type', 'text/plain');
response.setHeader('Cache-Control', 'no-cache, no-store, must-revalidate');
response.setHeader('Pragma', 'no-cache');
response.setHeader('Expires', 0);
}
function sendData(response, data, isAsync, fromId) {
setStandardHeaders(response);
response.setHeader('Content-Type', 'text/plain');
if (isAsync) {
response.setHeader('X-PingPong-Async', 1);
}
response.setHeader('X-PingPong-From', fromId);
response.writeHead(200);
response.end(data);
}
function sendNoData(response) {
setStandardHeaders(response);
response.writeHead(204);
response.end();
}
function sendTimeout(response) {
setStandardHeaders(response);
response.setHeader('X-PingPong-Error', 'timeout');
response.writeHead(204);
response.end();
}
var method = request.method;
if (request.method === 'OPTIONS') {
setStandardHeaders(response);
response.writeHead(200);
response.end();
return;
}
var url = request.url;
var urlParts = /([^?]*)((?:\?(.*))?)/.exec(url);
var pathParts = urlParts[1].split('/');
var queryPart = urlParts[3];
var sessionId = pathParts[1], fromId = pathParts[2], toId = pathParts[3];
var isResponse = queryPart === 'response', isAsync = queryPart === 'async';
verbose && console.log(sessionId + ': ' + fromId + '->' + toId + ' ' +
isResponse + ' ' + isAsync + ' ' + request.method);
var keyId = sessionId + '_' + fromId + '_' + toId;
var reverseKeyId = sessionId + '_' + toId + '_' + fromId;
if (request.method === 'POST') {
response.on('close', function () {
verbose && console.log('connection closed'); // TODO client closed without response.end
});
var body = '';
request.on('data', function (data) {
body += data;
});
request.on('end', function () {
verbose && console.log(' ... ' + body.substring(0, 140));
item.isReady = true;
while (currentReading.length > 0 && currentReading[0].isReady) {
currentReading.shift().fn();
}
});
var item = {
isReady: false,
fn: function () {
if (isResponse) {
if (outgoingResponse[reverseKeyId]) {
sendData(outgoingResponse[reverseKeyId].shift().response, body, true, fromId);
if (outgoingResponse[reverseKeyId].length === 0) {
delete outgoingResponse[reverseKeyId];
}
} else {
console.error('Out of sequence response for ' + reverseKeyId);
}
sendNoData(response);
} else {
if (!isAsync) {
if (!outgoingResponse[keyId]) {
outgoingResponse[keyId] = [];
}
var requestTimeout = +request.headers['x-pingpong-timeout'];
var syncTimeout = requestTimeout || SYNC_TIMEOUT;
outgoingResponse[keyId].push({response: response});
setTimeout(function () {
var responses = outgoingResponse[keyId];
if (!responses) {
return;
}
for (var i = 0; i < responses.length; i++) {
if (responses[i].response === response) {
if (responses.length === 1) {
delete outgoingResponse[keyId];
} else {
responses.splice(i, 1);
}
sendTimeout(response);
if (!requestTimeout) {
console.error('Sync request timeout: ' + keyId);
}
break;
}
}
}, syncTimeout);
} else {
sendNoData(response);
}
if (incomingResponse[reverseKeyId]) {
sendData(incomingResponse[reverseKeyId].response, body, isAsync, fromId);
delete incomingResponse[reverseKeyId];
} else {
if (!incomingData[reverseKeyId]) {
incomingData[reverseKeyId] = [];
}
incomingData[reverseKeyId].push({data: body, isAsync: isAsync});
}
}
}
};
currentReading.push(item);
return;
}
if (request.method == 'GET' && !isResponse) {
if (incomingData[keyId]) {
var data = incomingData[keyId].shift();
sendData(response, data.data, data.isAsync, toId);
if (incomingData[keyId].length === 0) {
delete incomingData[keyId];
}
} else {
if (incomingResponse[keyId]) {
console.error('Double incoming response from ' + keyId);
}
incomingResponse[keyId] = {response: response};
}
setTimeout(function () {
if (incomingResponse[keyId] && incomingResponse[keyId].response === response) {
delete incomingResponse[keyId];
sendTimeout(response);
}
}, IDLE_TIMEOUT);
return;
}
setStandardHeaders(response);
response.writeHead(500);
response.end('Invalid request');
}
};
var server = new WebServer();
server.start();

Просмотреть файл

@ -160,6 +160,7 @@ limitations under the License.
<script src="js/classes/SWFController.js"></script>
<script src="js/classes/classList.min.js"></script>
<script src="js/classes/dat.gui.js"></script>
<script src="debug/pingpong.js"></script>
<script src="js/inspectorProfiler.js"></script>
<script src="js/inspectorSettings.js"></script>
@ -168,6 +169,7 @@ limitations under the License.
<script src="js/inspectorDisplayList.js"></script>
<script src="js/inspectorMocks.js"></script>
<script src="js/inspectorDebugging.js"></script> <!-- P -->
<script src="js/remoteDebugging.js"></script>
<script src="js/unit.js"></script>
<script src="js/inspector.js"></script>
</body>

Просмотреть файл

@ -82,6 +82,10 @@ if (queryVariables['rfile'] && !startPromise) {
url: queryVariables['rfile'],
args: parseQueryString(queryVariables['flashvars'])
});
} else {
if (state.remoteEnabled) {
initRemoteDebugging();
}
}
if (startPromise) {
startPromise.then(function (config) {
@ -106,6 +110,7 @@ function showOpenFileButton(show) {
var flashOverlay;
var currentSWFUrl;
var currentPlayer;
var processExternalCommand;
var easelHost;
function runIFramePlayer(data) {
@ -130,11 +135,14 @@ function runIFramePlayer(data) {
playerWorker.postMessage(data, '*');
easelHost = new Shumway.GFX.Window.WindowEaselHost(easel, playerWorker, window);
if (processExternalCommand) {
easelHost.processExternalCommand = processExternalCommand;
}
});
container.appendChild(playerWorkerIFrame);
}
function executeFile(file, buffer, movieParams) {
function executeFile(file, buffer, movieParams, remoteDebugging) {
var filename = file.split('?')[0].split('#')[0];
if (state.useIFramePlayer && filename.endsWith(".swf")) {
@ -142,7 +150,8 @@ function executeFile(file, buffer, movieParams) {
runIFramePlayer({sysMode: sysMode, appMode: appMode,
movieParams: movieParams, file: file, asyncLoading: asyncLoading,
stageAlign: state.salign, stageScale: state.scale,
fileReadChunkSize: state.fileReadChunkSize, loaderURL: state.loaderURL});
fileReadChunkSize: state.fileReadChunkSize, loaderURL: state.loaderURL,
remoteDebugging: !!remoteDebugging});
return;
}
@ -189,7 +198,15 @@ function executeFile(file, buffer, movieParams) {
player.displayParameters = easel.getDisplayParameters();
player.loaderUrl = state.loaderURL;
if (remoteDebugging) {
Shumway.ExternalInterfaceService.instance = player.createExternalInterfaceService();
}
easelHost = new Shumway.GFX.Test.TestEaselHost(easel);
if (processExternalCommand) {
easelHost.processExternalCommand = processExternalCommand;
}
player.load(file, buffer);
currentSWFUrl = swfURL;

Просмотреть файл

@ -102,6 +102,10 @@ function runSwfPlayer(data) {
fileReadChunkSize = data.fileReadChunkSize;
var file = data.file;
configureExternalInterfaceMocks(file);
if (data.remoteDebugging) {
Shumway.ClipboardService.instance = parent.Shumway.ClipboardService.instance;
Shumway.FileLoadingService.instance = parent.Shumway.FileLoadingService.instance;
}
Shumway.createAVM2(builtinPath, playerglobalInfo, sysMode, appMode, function (avm2) {
function runSWF(file) {
var player = new Shumway.Player.Window.WindowPlayer(window);
@ -111,6 +115,10 @@ function runSwfPlayer(data) {
player.displayParameters = displayParameters;
player.loaderUrl = loaderURL;
player.load(file);
if (data.remoteDebugging) {
Shumway.ExternalInterfaceService.instance = player.createExternalInterfaceService();
}
}
file = Shumway.FileLoadingService.instance.setBaseUrl(file);
if (asyncLoading) {

Просмотреть файл

@ -35,7 +35,9 @@ var stateDefaults = {
scale: 'noscale',
width: -1,
height: -1,
loaderURL: ''
loaderURL: '',
remoteEnabled: false,
remoteSWF: ''
};
for (var option in stateDefaults) {
@ -115,6 +117,8 @@ var GUI = (function () {
inspectorOptions.add(state, "width", -1, 4096, 1).onChange(saveInspectorOption);
inspectorOptions.add(state, "height", -1, 4096, 1).onChange(saveInspectorOption);
inspectorOptions.add(state, "loaderURL").onChange(saveInspectorOption);
inspectorOptions.add(state, "remoteEnabled").onChange(saveInspectorOption);
inspectorOptions.add(state, "remoteSWF").onChange(saveInspectorOption);
//inspectorOptions.add(state, "mute").onChange(saveInspectorOption);
if (state.folderOpen) {
inspectorOptions.open();

Просмотреть файл

@ -0,0 +1,170 @@
/*
* Copyright 2015 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 removeDebuggerBaseURL = 'http://localhost:8010';
var remoteDebuggerId;
var remoteDebugger;
var remoteDebuggerController;
function initRemoteDebugging() {
remoteDebuggerId = (Date.now() % 100000) + 2;
remoteDebugger = new PingPongConnection(removeDebuggerBaseURL + '/debug/' + remoteDebuggerId + '/1');
remoteDebugger.onData = remoteDebugger_onData;
remoteDebuggerController = new PingPongConnection(removeDebuggerBaseURL + '/debugController/1/2');
remoteDebuggerController.onData = function (data) {
switch (data.action) {
case 'getDebugger':
if (data.swfUrl && data.swfUrl.indexOf(state.remoteSWF) === 0) {
return remoteDebuggerId;
}
return 0;
case 'enableDebugging':
var properties = document.getElementById('settingsContainer').querySelectorAll('.property-name');
for (var i = 0; i < properties.length; i++) {
if (properties[i].textContent === 'remoteSWF') {
var input = properties[i].parentElement.getElementsByTagName('input')[0];
input.value = data.swfUrl;
break;
}
}
state.remoteSWF = data.swfUrl;
saveInspectorState();
return;
}
};
}
var externalInteraceCallback;
function remoteDebuggerInitServices() {
window.addEventListener('beforeunload', function(event) {
remoteDebugger.send({action: 'reload'}, true);
});
processExternalCommand = function (command) {
switch (command.action) {
case 'isEnabled':
command.result = true;
break;
case 'initJS':
remoteDebuggerSendMessage({action: 'externalCom', data: {action: 'init'}, sync: true});
externalInteraceCallback = function (functionName, args) {
return easelHost.sendExernalCallback(functionName, args);
};
break;
default:
var result = remoteDebuggerSendMessage({action: 'externalCom', data: command, sync: true});
command.result = result ? JSON.parse(result) : undefined;
break;
}
};
Shumway.ClipboardService.instance = {
setClipboard: function (data) {
remoteDebuggerSendMessage({action: 'setClipboard', data: data}, false);
}
};
Shumway.FileLoadingService.instance = {
baseUrl: null,
nextSessionId: 1, // 0 - is reserved
sessions: [],
createSession: function () {
var sessionId = this.nextSessionId++;
return this.sessions[sessionId] = {
open: function (request) {
var self = this;
var path = Shumway.FileLoadingService.instance.resolveUrl(request.url);
console.log('Session #' + sessionId + ': loading ' + path);
remoteDebuggerSendMessage({
action: 'loadFile',
data: {url: path, method: request.method,
mimeType: request.mimeType, postData: request.data,
checkPolicyFile: request.checkPolicyFile, sessionId: sessionId}
}, true);
},
notify: function (args) {
switch (args.topic) {
case "open":
this.onopen();
break;
case "close":
this.onclose();
Shumway.FileLoadingService.instance.sessions[sessionId] = null;
console.log('Session #' + sessionId + ': closed');
break;
case "error":
this.onerror && this.onerror(args.error);
break;
case "progress":
console.log('Session #' + sessionId + ': loaded ' + args.loaded + '/' + args.total);
this.onprogress && this.onprogress(new Uint8Array(args.array), {bytesLoaded: args.loaded, bytesTotal: args.total});
break;
}
},
close: function () {
if (Shumway.FileLoadingService.instance.sessions[sessionId]) {
// TODO send abort
}
}
};
},
setBaseUrl: function (url) {
return Shumway.FileLoadingService.instance.baseUrl = url;
},
resolveUrl: function (url) {
return new URL(url, Shumway.FileLoadingService.instance.baseUrl).href;
},
navigateTo: function (url, target) {
remoteDebuggerSendMessage({
action: 'navigateTo',
data: {
url: this.resolveUrl(url),
target: target
}
}, true);
}
};
}
function remoteDebuggerSendMessage(detail, async) {
return remoteDebugger.send({action: 'sendMessage', detail: detail}, async);
}
function remoteDebugger_onData(data) {
switch (data.action) {
case 'runViewer':
showOpenFileButton(false);
remoteDebuggerInitServices();
var flashParams = JSON.parse(remoteDebuggerSendMessage({action: 'getPluginParams', data: null, sync: true}));
var movieUrl = flashParams.url;
var movieParams = flashParams.movieParams;
executeFile(movieUrl, undefined, movieParams, true);
remoteDebuggerSendMessage({action: 'endActivation', data: null}, true);
return;
case 'onExternalCallback':
var call = data.detail;
externalInteraceCallback(call.functionName, call.args);
return;
case 'onLoadFileCallback':
var args = data.detail;
var session = Shumway.FileLoadingService.instance.sessions[args.sessionId];
if (session) {
session.notify(args);
}
return;
}
}

Просмотреть файл

@ -27,6 +27,7 @@ build: ensureoutputdir
cp -R ../../LICENSE content chrome bootstrap.js chrome.manifest icon.png icon64.png $(BUILD_DIR)/
sed s/\(SHUMWAY_VERSION\)/$(VERSION)/ install.rdf > $(BUILD_DIR)/install.rdf
sed s/\(SHUMWAY_VERSION\)/$(VERSION)/ update.rdf > $(BUILD_DIR)/update.rdf
cp ../../examples/inspector/debug/pingpong.js $(BUILD_DIR)/chrome/
# Copying WebGL shaders
mkdir -p $(BUILD_DIR)/content/gfx/gl/shaders
cp ../../src/gfx/gl/shaders/combined.frag $(BUILD_DIR)/content/gfx/gl/shaders/

Просмотреть файл

@ -46,6 +46,10 @@ function sendMessage(action, data, sync, callbackCookie) {
return Components.utils.cloneInto(result, content);
}
function enableDebug() {
sendAsyncMessage('Shumway:enableDebug', null);
}
addMessageListener('Shumway:init', function (message) {
sendAsyncMessage('Shumway:running', {}, {
externalInterface: externalInterfaceWrapper
@ -55,6 +59,7 @@ addMessageListener('Shumway:init', function (message) {
// up Xray wrappers.
shumwayComAdapter = Components.utils.createObjectIn(content, {defineAs: 'ShumwayCom'});
Components.utils.exportFunction(sendMessage, shumwayComAdapter, {defineAs: 'sendMessage'});
Components.utils.exportFunction(enableDebug, shumwayComAdapter, {defineAs: 'enableDebug'});
Object.defineProperties(shumwayComAdapter, {
onLoadFileCallback: { value: null, writable: true },
onExternalCallback: { value: null, writable: true },

Просмотреть файл

@ -36,11 +36,23 @@ limitations under the License.
line-height: 0;
border: 0px none;
}
body.remoteStopped {
background-color: red;
}
body.remoteDebug {
background-color: green;
}
body.remoteReload {
background-color: yellow;
}
</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/pingpong.js"></script>
<script src="chrome://shumway/content/viewerDebugger.js"></script>
<script src="chrome://shumway/content/viewerWrapper.js"></script>
</body>
</html>

Просмотреть файл

@ -0,0 +1,80 @@
/*
* Copyright 2015 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');
var DebugUtils = (function () {
var baseUrl = null;
function getBaseUrl() {
if (baseUrl === null) {
try {
baseUrl = Services.prefs.getCharPref('shumway.debug.url');
} catch (e) {
baseUrl = 'http://localhost:8010';
}
}
return baseUrl;
}
function getEnabledDebuggerId(swfUrl) {
var id = 0;
var url = getBaseUrl() + '/debugController/2/1';
var connection = new PingPongConnection(url, true);
try {
id = connection.send({action: 'getDebugger', swfUrl: swfUrl},
false, 500);
} catch (e) {
// ignoring failed send request
}
connection.close();
return id;
}
function enableDebug(swfUrl) {
var url = getBaseUrl() + '/debugController/2/1';
var connection = new PingPongConnection(url, true);
try {
connection.send({action: 'enableDebugging', swfUrl: swfUrl}, true);
} catch (e) {
// ignoring failed send request
}
connection.close();
}
function createDebuggerConnection(swfUrl) {
var debuggerId = getEnabledDebuggerId(swfUrl);
if (!debuggerId) {
return null;
}
var url = getBaseUrl() + '/debug/1/' + debuggerId;
console.log('Starting remote debugger with ' + url);
return new PingPongConnection(url);
}
return {
get isEnabled() {
try {
return Services.prefs.getBoolPref('shumway.debug.enabled');
} catch (e) {
return false;
}
},
enableDebug: enableDebug,
createDebuggerConnection: createDebuggerConnection
};
})();

Просмотреть файл

@ -53,6 +53,7 @@ function runViewer() {
// ShumwayStreamConverter.
var shumwayComAdapter = Components.utils.createObjectIn(childWindow, {defineAs: 'ShumwayCom'});
Components.utils.exportFunction(sendMessage, shumwayComAdapter, {defineAs: 'sendMessage'});
Components.utils.exportFunction(enableDebug, shumwayComAdapter, {defineAs: 'enableDebug'});
Object.defineProperties(shumwayComAdapter, {
onLoadFileCallback: { value: null, writable: true },
onExternalCallback: { value: null, writable: true },
@ -117,6 +118,10 @@ function runViewer() {
return window.notifyShumwayMessage(detail);
});
messageManager.addMessageListener('Shumway:enableDebug', function (message) {
enableDebug();
});
window.onExternalCallback = function (call) {
return externalInterface.callback(JSON.stringify(call));
};
@ -135,7 +140,71 @@ function runViewer() {
messageManager.sendAsyncMessage('Shumway:init', {});
}
function handleDebug(connection) {
viewer.parentNode.removeChild(viewer); // we don't need viewer anymore
document.body.className = 'remoteDebug';
function sendMessage(data) {
var detail = {
action: data.action,
data: data.data,
sync: data.sync
};
if (data.callback) {
detail.callback = true;
detail.cookie = data.cookie;
}
return window.notifyShumwayMessage(detail);
}
connection.onData = function (data) {
switch (data.action) {
case 'sendMessage':
return sendMessage(data.detail);
case 'reload':
document.body.className = 'remoteReload';
setTimeout(function () {
window.top.location.reload();
}, 1000);
return;
}
};
window.onExternalCallback = function (call) {
return connection.send({action: 'onExternalCallback', detail: call});
};
window.onMessageCallback = function (response) {
return connection.send({action: 'onMessageCallback', detail: response});
};
window.onLoadFileCallback = function (args) {
if (args.array) {
args.array = Array.prototype.slice.call(args.array, 0);
}
return connection.send({action: 'onLoadFileCallback', detail: args}, true);
};
connection.send({action: 'runViewer'}, true);
}
function enableDebug() {
DebugUtils.enableDebug(window.swfUrlLoading);
setTimeout(function () {
window.top.location.reload();
}, 1000);
}
promise.then(function (oop) {
if (DebugUtils.isEnabled) {
var debuggerConnection = DebugUtils.createDebuggerConnection(window.swfUrlLoading);
if (debuggerConnection) {
handleDebug(debuggerConnection);
return;
}
}
if (oop) {
handlerOOP();
} else {

Просмотреть файл

@ -411,7 +411,7 @@ ChromeActions.prototype = {
var position = e.loaded;
var data = new Uint8Array(xhr.response);
notifyLoadFileListener({callback:"loadFile", sessionId: sessionId,
topic: "progress", array: data, loaded: e.loaded, total: e.total});
topic: "progress", array: data, loaded: position, total: e.total});
lastPosition = position;
if (limit && e.total >= limit) {
xhr.abort();
@ -1034,6 +1034,8 @@ ShumwayStreamConverterBase.prototype = {
return;
}
domWindow.swfUrlLoading = actions.url;
// Report telemetry on amount of swfs on the page
if (actions.isOverlay) {
// Looking for last actions with same baseUrl

Просмотреть файл

@ -111,6 +111,7 @@ limitations under the License.
<menuitem label="Open in Inspector" id="inspectorMenu"></menuitem>
<menuitem label="Report Problems" id="reportMenu"></menuitem>
<menuitem label="Reload in Adobe Flash Player" id="fallbackMenu" hidden></menuitem>
<menuitem label="Debug this SWF" id="debugMenu"></menuitem>
<menuitem label="About Shumway %version%..." id="aboutMenu"></menuitem>
</menu>
</section>

Просмотреть файл

@ -165,6 +165,13 @@ function runViewer() {
var version = Shumway.version || '';
document.getElementById('aboutMenu').label =
document.getElementById('aboutMenu').label.replace('%version%', version);
var debugMenuEnabled = FirefoxCom.requestSync('getBoolPref', {pref: 'shumway.debug.enabled', def: false});
if (debugMenuEnabled) {
document.getElementById('debugMenu').addEventListener('click', enableDebug);
} else {
document.getElementById('debugMenu').remove();
}
}
function showURL() {
@ -205,6 +212,10 @@ function showAbout() {
window.open('http://areweflashyet.com/');
}
function enableDebug() {
ShumwayCom.enableDebug();
}
var movieUrl, movieParams, objectParams;
window.addEventListener("message", function handlerMessage(e) {

Просмотреть файл

@ -26,6 +26,7 @@ build: ensureoutputdir
echo "Creating mozcentral package"
mkdir -p $(BUILD_EXTENSION_DIR)
cp -R ../../LICENSE $(EXTENSION_SRC)/chrome $(EXTENSION_SRC)/content $(BUILD_EXTENSION_DIR)/
cp ../../examples/inspector/debug/pingpong.js $(BUILD_DIR)/chrome/
cp -R browser $(BUILD_DIR)/
mkdir -p $(BUILD_EXTENSION_DIR)/content/gfx/gl/shaders
cp ../../src/gfx/gl/shaders/combined.frag $(BUILD_EXTENSION_DIR)/content/gfx/gl/shaders/

Просмотреть файл

@ -113,7 +113,7 @@ module Shumway.AVM2.AS {
buffer = new Uint8Array(source).buffer;
} else if ('buffer' in source) {
if (source.buffer instanceof ArrayBuffer) {
buffer = new Uint8Array(source).buffer;
buffer = new Uint8Array(source.buffer).buffer;
} else if (source.buffer instanceof Uint8Array) {
var begin = source.buffer.byteOffset;
buffer = source.buffer.buffer.slice(begin, begin + source.buffer.length);