browser/extensions/shumway/content/web/avm-sandbox.js

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 /* -*- Mode: js; js-indent-level: 2; indent-tabs-mode: nil; tab-width: 2 -*- */
michael@0 2 /* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
michael@0 3 /*
michael@0 4 * Copyright 2013 Mozilla Foundation
michael@0 5 *
michael@0 6 * Licensed under the Apache License, Version 2.0 (the "License");
michael@0 7 * you may not use this file except in compliance with the License.
michael@0 8 * You may obtain a copy of the License at
michael@0 9 *
michael@0 10 * http://www.apache.org/licenses/LICENSE-2.0
michael@0 11 *
michael@0 12 * Unless required by applicable law or agreed to in writing, software
michael@0 13 * distributed under the License is distributed on an "AS IS" BASIS,
michael@0 14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
michael@0 15 * See the License for the specific language governing permissions and
michael@0 16 * limitations under the License.
michael@0 17 */
michael@0 18
michael@0 19 // Extension communication object
michael@0 20 var FirefoxCom = (function FirefoxComClosure() {
michael@0 21 return {
michael@0 22 /**
michael@0 23 * Creates an event that the extension is listening for and will
michael@0 24 * synchronously respond to.
michael@0 25 * NOTE: It is reccomended to use request() instead since one day we may not
michael@0 26 * be able to synchronously reply.
michael@0 27 * @param {String} action The action to trigger.
michael@0 28 * @param {String} data Optional data to send.
michael@0 29 * @return {*} The response.
michael@0 30 */
michael@0 31 requestSync: function(action, data) {
michael@0 32 var e = document.createEvent('CustomEvent');
michael@0 33 e.initCustomEvent('shumway.message', true, false,
michael@0 34 {action: action, data: data, sync: true});
michael@0 35 document.dispatchEvent(e);
michael@0 36 return e.detail.response;
michael@0 37 },
michael@0 38 /**
michael@0 39 * Creates an event that the extension is listening for and will
michael@0 40 * asynchronously respond by calling the callback.
michael@0 41 * @param {String} action The action to trigger.
michael@0 42 * @param {String} data Optional data to send.
michael@0 43 * @param {Function} callback Optional response callback that will be called
michael@0 44 * with one data argument.
michael@0 45 */
michael@0 46 request: function(action, data, callback) {
michael@0 47 var e = document.createEvent('CustomEvent');
michael@0 48 e.initCustomEvent('shumway.message', true, false,
michael@0 49 {action: action, data: data, sync: false});
michael@0 50 if (callback) {
michael@0 51 if ('nextId' in FirefoxCom.request) {
michael@0 52 FirefoxCom.request.nextId = 1;
michael@0 53 }
michael@0 54 var cookie = "requestId" + (FirefoxCom.request.nextId++);
michael@0 55 e.detail.cookie = cookie;
michael@0 56 e.detail.callback = true;
michael@0 57
michael@0 58 document.addEventListener('shumway.response', function listener(event) {
michael@0 59 if (cookie !== event.detail.cookie)
michael@0 60 return;
michael@0 61
michael@0 62 document.removeEventListener('shumway.response', listener, false);
michael@0 63
michael@0 64 var response = event.detail.response;
michael@0 65 return callback(response);
michael@0 66 }, false);
michael@0 67 }
michael@0 68 return document.dispatchEvent(e);
michael@0 69 },
michael@0 70 initJS: function (callback) {
michael@0 71 FirefoxCom.request('externalCom', {action: 'init'});
michael@0 72 document.addEventListener('shumway.remote', function (e) {
michael@0 73 e.detail.result = callback(e.detail.functionName, e.detail.args);
michael@0 74 }, false);
michael@0 75 }
michael@0 76 };
michael@0 77 })();
michael@0 78
michael@0 79 function fallback() {
michael@0 80 FirefoxCom.requestSync('fallback', null)
michael@0 81 }
michael@0 82
michael@0 83 var playerglobalInfo = {
michael@0 84 abcs: SHUMWAY_ROOT + "playerglobal/playerglobal.abcs",
michael@0 85 catalog: SHUMWAY_ROOT + "playerglobal/playerglobal.json"
michael@0 86 };
michael@0 87
michael@0 88 function runViewer() {
michael@0 89 var flashParams = JSON.parse(FirefoxCom.requestSync('getPluginParams', null));
michael@0 90 FileLoadingService.setBaseUrl(flashParams.baseUrl);
michael@0 91
michael@0 92 movieUrl = flashParams.url;
michael@0 93 if (!movieUrl) {
michael@0 94 console.log("no movie url provided -- stopping here");
michael@0 95 FirefoxCom.request('endActivation', null);
michael@0 96 return;
michael@0 97 }
michael@0 98
michael@0 99 movieParams = flashParams.movieParams;
michael@0 100 objectParams = flashParams.objectParams;
michael@0 101 var isOverlay = flashParams.isOverlay;
michael@0 102 pauseExecution = flashParams.isPausedAtStart;
michael@0 103
michael@0 104 console.log("url=" + movieUrl + ";params=" + uneval(movieParams));
michael@0 105 if (movieParams.fmt_list && movieParams.url_encoded_fmt_stream_map) {
michael@0 106 // HACK removing FLVs from the fmt_list
michael@0 107 movieParams.fmt_list = movieParams.fmt_list.split(',').filter(function (s) {
michael@0 108 var fid = s.split('/')[0];
michael@0 109 return fid !== '5' && fid !== '34' && fid !== '35'; // more?
michael@0 110 }).join(',');
michael@0 111 }
michael@0 112
michael@0 113 parseSwf(movieUrl, movieParams, objectParams);
michael@0 114
michael@0 115 if (isOverlay) {
michael@0 116 document.getElementById('overlay').className = 'enabled';
michael@0 117 var fallbackDiv = document.getElementById('fallback');
michael@0 118 fallbackDiv.addEventListener('click', function(e) {
michael@0 119 fallback();
michael@0 120 e.preventDefault();
michael@0 121 });
michael@0 122 var reportDiv = document.getElementById('report');
michael@0 123 reportDiv.addEventListener('click', function(e) {
michael@0 124 reportIssue();
michael@0 125 e.preventDefault();
michael@0 126 });
michael@0 127 var fallbackMenu = document.getElementById('fallbackMenu');
michael@0 128 fallbackMenu.removeAttribute('hidden');
michael@0 129 fallbackMenu.addEventListener('click', fallback);
michael@0 130 }
michael@0 131 var showURLMenu = document.getElementById('showURLMenu');
michael@0 132 showURLMenu.addEventListener('click', showURL);
michael@0 133 var inspectorMenu = document.getElementById('inspectorMenu');
michael@0 134 inspectorMenu.addEventListener('click', showInInspector);
michael@0 135 var reportMenu = document.getElementById('reportMenu');
michael@0 136 reportMenu.addEventListener('click', reportIssue);
michael@0 137
michael@0 138 document.getElementById('copyProfileMenu').addEventListener('click', copyProfile);
michael@0 139 }
michael@0 140
michael@0 141 function showURL() {
michael@0 142 window.prompt("Copy to clipboard", movieUrl);
michael@0 143 }
michael@0 144
michael@0 145 function showInInspector() {
michael@0 146 var base = "http://www.areweflashyet.com/shumway/examples/inspector/inspector.html?rfile=";
michael@0 147 var params = '';
michael@0 148 for (var k in movieParams) {
michael@0 149 params += '&' + k + '=' + encodeURIComponent(movieParams[k]);
michael@0 150 }
michael@0 151 window.open(base + encodeURIComponent(movieUrl) + params);
michael@0 152 }
michael@0 153
michael@0 154 function reportIssue() {
michael@0 155 var duplicatesMap = Object.create(null);
michael@0 156 var prunedExceptions = [];
michael@0 157 avm2.exceptions.forEach(function(e) {
michael@0 158 var ident = e.source + e.message + e.stack;
michael@0 159 var entry = duplicatesMap[ident];
michael@0 160 if (!entry) {
michael@0 161 entry = duplicatesMap[ident] = {
michael@0 162 source: e.source,
michael@0 163 message: e.message,
michael@0 164 stack: e.stack,
michael@0 165 count: 0
michael@0 166 };
michael@0 167 prunedExceptions.push(entry);
michael@0 168 }
michael@0 169 entry.count++;
michael@0 170 });
michael@0 171 FirefoxCom.requestSync('reportIssue', JSON.stringify(prunedExceptions));
michael@0 172 }
michael@0 173
michael@0 174 function copyProfile() {
michael@0 175 function toArray(v) {
michael@0 176 var array = [];
michael@0 177 for (var i = 0; i < v.length; i++) {
michael@0 178 array.push(v[i]);
michael@0 179 }
michael@0 180 return array;
michael@0 181 }
michael@0 182 var profile = {
michael@0 183 loops: {counts: toArray($L), lines: $LL},
michael@0 184 functions: {counts: toArray($F), lines: $FL},
michael@0 185 allocations: {counts: toArray($A), lines: $AL}
michael@0 186 };
michael@0 187 FirefoxCom.request('unsafeSetClipboard', JSON.stringify(profile));
michael@0 188 }
michael@0 189
michael@0 190 var movieUrl, movieParams, objectParams;
michael@0 191
michael@0 192 window.addEventListener("message", function handlerMessage(e) {
michael@0 193 var args = e.data;
michael@0 194 switch (args.callback) {
michael@0 195 case "loadFile":
michael@0 196 var session = FileLoadingService.sessions[args.sessionId];
michael@0 197 if (session) {
michael@0 198 session.notify(args);
michael@0 199 }
michael@0 200 break;
michael@0 201 }
michael@0 202 }, true);
michael@0 203
michael@0 204 var TelemetryService = {
michael@0 205 reportTelemetry: function (data) {
michael@0 206 FirefoxCom.request('reportTelemetry', data, null);
michael@0 207 }
michael@0 208 };
michael@0 209
michael@0 210 var FileLoadingService = {
michael@0 211 get baseUrl() { return movieUrl; },
michael@0 212 nextSessionId: 1, // 0 - is reserved
michael@0 213 sessions: [],
michael@0 214 createSession: function () {
michael@0 215 var sessionId = this.nextSessionId++;
michael@0 216 return this.sessions[sessionId] = {
michael@0 217 open: function (request) {
michael@0 218 var self = this;
michael@0 219 var path = FileLoadingService.resolveUrl(request.url);
michael@0 220 console.log('Session #' + sessionId +': loading ' + path);
michael@0 221 FirefoxCom.requestSync('loadFile', {url: path, method: request.method,
michael@0 222 mimeType: request.mimeType, postData: request.data,
michael@0 223 checkPolicyFile: request.checkPolicyFile, sessionId: sessionId});
michael@0 224 },
michael@0 225 notify: function (args) {
michael@0 226 switch (args.topic) {
michael@0 227 case "open": this.onopen(); break;
michael@0 228 case "close":
michael@0 229 this.onclose();
michael@0 230 FileLoadingService.sessions[sessionId] = null;
michael@0 231 console.log('Session #' + sessionId +': closed');
michael@0 232 break;
michael@0 233 case "error":
michael@0 234 this.onerror && this.onerror(args.error);
michael@0 235 break;
michael@0 236 case "progress":
michael@0 237 console.log('Session #' + sessionId + ': loaded ' + args.loaded + '/' + args.total);
michael@0 238 this.onprogress && this.onprogress(args.array, {bytesLoaded: args.loaded, bytesTotal: args.total});
michael@0 239 break;
michael@0 240 }
michael@0 241 }
michael@0 242 };
michael@0 243 },
michael@0 244 setBaseUrl: function (url) {
michael@0 245 var a = document.createElement('a');
michael@0 246 a.href = url || '#';
michael@0 247 a.setAttribute('style', 'display: none;');
michael@0 248 document.body.appendChild(a);
michael@0 249 FileLoadingService.baseUrl = a.href;
michael@0 250 document.body.removeChild(a);
michael@0 251 },
michael@0 252 resolveUrl: function (url) {
michael@0 253 if (url.indexOf('://') >= 0) return url;
michael@0 254
michael@0 255 var base = FileLoadingService.baseUrl;
michael@0 256 base = base.lastIndexOf('/') >= 0 ? base.substring(0, base.lastIndexOf('/') + 1) : '';
michael@0 257 if (url.indexOf('/') === 0) {
michael@0 258 var m = /^[^:]+:\/\/[^\/]+/.exec(base);
michael@0 259 if (m) base = m[0];
michael@0 260 }
michael@0 261 return base + url;
michael@0 262 }
michael@0 263 };
michael@0 264
michael@0 265 function parseSwf(url, movieParams, objectParams) {
michael@0 266 var enableVerifier = Shumway.AVM2.Runtime.enableVerifier;
michael@0 267 var EXECUTION_MODE = Shumway.AVM2.Runtime.EXECUTION_MODE;
michael@0 268
michael@0 269 var compilerSettings = JSON.parse(
michael@0 270 FirefoxCom.requestSync('getCompilerSettings', null));
michael@0 271 enableVerifier.value = compilerSettings.verifier;
michael@0 272
michael@0 273 // init misc preferences
michael@0 274 turboMode.value = FirefoxCom.requestSync('getBoolPref', {pref: 'shumway.turboMode', def: false});
michael@0 275 hud.value = FirefoxCom.requestSync('getBoolPref', {pref: 'shumway.hud', def: false});
michael@0 276 forceHidpi.value = FirefoxCom.requestSync('getBoolPref', {pref: 'shumway.force_hidpi', def: false});
michael@0 277 dummyAnimation.value = FirefoxCom.requestSync('getBoolPref', {pref: 'shumway.dummyMode', def: false});
michael@0 278
michael@0 279 console.log("Compiler settings: " + JSON.stringify(compilerSettings));
michael@0 280 console.log("Parsing " + url + "...");
michael@0 281 function loaded() {
michael@0 282 FirefoxCom.request('endActivation', null);
michael@0 283 }
michael@0 284
michael@0 285 createAVM2(builtinPath, playerglobalInfo, avm1Path,
michael@0 286 compilerSettings.sysCompiler ? EXECUTION_MODE.COMPILE : EXECUTION_MODE.INTERPRET,
michael@0 287 compilerSettings.appCompiler ? EXECUTION_MODE.COMPILE : EXECUTION_MODE.INTERPRET,
michael@0 288 function (avm2) {
michael@0 289 console.time("Initialize Renderer");
michael@0 290 SWF.embed(url, document, document.getElementById("viewer"), {
michael@0 291 url: url,
michael@0 292 movieParams: movieParams,
michael@0 293 objectParams: objectParams,
michael@0 294 onComplete: loaded,
michael@0 295 onBeforeFrame: frame
michael@0 296 });
michael@0 297 });
michael@0 298 }
michael@0 299
michael@0 300 var pauseExecution = false;
michael@0 301 var initializeFrameControl = true;
michael@0 302 function frame(e) {
michael@0 303 if (initializeFrameControl) {
michael@0 304 // marking that movie is started
michael@0 305 document.body.classList.add("started");
michael@0 306
michael@0 307 TelemetryService.reportTelemetry({topic: "firstFrame"});
michael@0 308
michael@0 309 // skipping frame 0
michael@0 310 initializeFrameControl = false;
michael@0 311 return;
michael@0 312 }
michael@0 313 if (pauseExecution) {
michael@0 314 e.cancel = true;
michael@0 315 }
michael@0 316 }
michael@0 317
michael@0 318 document.addEventListener('keydown', function (e) {
michael@0 319 if (e.keyCode == 119 && e.ctrlKey) { // Ctrl+F8
michael@0 320 pauseExecution = !pauseExecution;
michael@0 321 }
michael@0 322 }, false);

mercurial