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.

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

mercurial