Tue, 06 Jan 2015 21:39:09 +0100
Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
4 */
6 'use strict';
8 const { Cc, Ci, Cu, ChromeWorker } = require("chrome");
10 Cu.import("resource://gre/modules/Services.jsm");
12 const { EventTarget } = require("sdk/event/target");
13 const { emit, off } = require("sdk/event/core");
14 const { Class } = require("sdk/core/heritage");
15 const Environment = require("sdk/system/environment").env;
16 const Runtime = require("sdk/system/runtime");
17 const Self = require("sdk/self");
18 const URL = require("sdk/url");
19 const Subprocess = require("subprocess");
20 const { Promise: promise } = Cu.import("resource://gre/modules/Promise.jsm", {});
21 const Prefs = require("sdk/simple-prefs").prefs;
23 const { rootURI: ROOT_URI } = require('@loader/options');
24 const PROFILE_URL = ROOT_URI + "profile/";
25 const BIN_URL = ROOT_URI + "b2g/";
27 // Log subprocess error and debug messages to the console. This logs messages
28 // for all consumers of the API. We trim the messages because they sometimes
29 // have trailing newlines. And note that registerLogHandler actually registers
30 // an error handler, despite its name.
31 Subprocess.registerLogHandler(
32 function(s) console.error("subprocess: " + s.trim())
33 );
34 Subprocess.registerDebugHandler(
35 function(s) console.debug("subprocess: " + s.trim())
36 );
38 exports.SimulatorProcess = Class({
39 extends: EventTarget,
40 initialize: function initialize(options) {
41 EventTarget.prototype.initialize.call(this, options);
43 this.on("stdout", function onStdout(data) console.log(data.trim()));
44 this.on("stderr", function onStderr(data) console.error(data.trim()));
45 },
47 // check if b2g is running
48 get isRunning() !!this.process,
50 /**
51 * Start the process and connect the debugger client.
52 */
53 run: function() {
54 // kill before start if already running
55 if (this.process != null) {
56 this.process
57 .kill()
58 .then(this.run.bind(this));
59 return;
60 }
62 // resolve b2g binaries path (raise exception if not found)
63 let b2gExecutable = this.b2gExecutable;
65 this.once("stdout", function () {
66 if (Runtime.OS == "Darwin") {
67 console.debug("WORKAROUND run osascript to show b2g-desktop window"+
68 " on Runtime.OS=='Darwin'");
69 // Escape double quotes and escape characters for use in AppleScript.
70 let path = b2gExecutable.path
71 .replace(/\\/g, "\\\\").replace(/\"/g, '\\"');
73 Subprocess.call({
74 command: "/usr/bin/osascript",
75 arguments: ["-e", 'tell application "' + path + '" to activate'],
76 });
77 }
78 });
80 let environment;
81 if (Runtime.OS == "Linux") {
82 environment = ["TMPDIR=" + Services.dirsvc.get("TmpD",Ci.nsIFile).path];
83 if ("DISPLAY" in Environment) {
84 environment.push("DISPLAY=" + Environment.DISPLAY);
85 }
86 }
88 // spawn a b2g instance
89 this.process = Subprocess.call({
90 command: b2gExecutable,
91 arguments: this.b2gArguments,
92 environment: environment,
94 // emit stdout event
95 stdout: (function(data) {
96 emit(this, "stdout", data);
97 }).bind(this),
99 // emit stderr event
100 stderr: (function(data) {
101 emit(this, "stderr", data);
102 }).bind(this),
104 // on b2g instance exit, reset tracked process, remoteDebuggerPort and
105 // shuttingDown flag, then finally emit an exit event
106 done: (function(result) {
107 console.log(this.b2gFilename + " terminated with " + result.exitCode);
108 this.process = null;
109 emit(this, "exit", result.exitCode);
110 }).bind(this)
111 });
112 },
114 // request a b2g instance kill
115 kill: function() {
116 let deferred = promise.defer();
117 if (this.process) {
118 this.once("exit", (exitCode) => {
119 this.shuttingDown = false;
120 deferred.resolve(exitCode);
121 });
122 if (!this.shuttingDown) {
123 this.shuttingDown = true;
124 emit(this, "kill", null);
125 this.process.kill();
126 }
127 return deferred.promise;
128 } else {
129 return promise.resolve(undefined);
130 }
131 },
133 // compute current b2g filename
134 get b2gFilename() {
135 return this._executable ? this._executableFilename : "B2G";
136 },
138 // compute current b2g file handle
139 get b2gExecutable() {
140 if (this._executable) {
141 return this._executable;
142 }
144 if (Prefs.customRuntime) {
145 this._executable = Prefs.customRuntime;
146 this._executableFilename = "Custom runtime";
147 return this._executable;
148 }
150 let bin = URL.toFilename(BIN_URL);
151 let executables = {
152 WINNT: "b2g-bin.exe",
153 Darwin: "B2G.app/Contents/MacOS/b2g-bin",
154 Linux: "b2g-bin",
155 };
157 let path = bin;
158 path += Runtime.OS == "WINNT" ? "\\" : "/";
159 path += executables[Runtime.OS];
160 console.log("simulator path: " + path);
162 let executable = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
163 executable.initWithPath(path);
165 if (!executable.exists()) {
166 // B2G binaries not found
167 throw Error("b2g-desktop Executable not found.");
168 }
170 this._executable = executable;
171 this._executableFilename = "b2g-bin";
173 return executable;
174 },
176 // compute b2g CLI arguments
177 get b2gArguments() {
178 let args = [];
180 let profile = Prefs.gaiaProfile || URL.toFilename(PROFILE_URL);
181 args.push("-profile", profile);
182 console.log("profile", profile);
184 // NOTE: push dbgport option on the b2g-desktop commandline
185 args.push("-start-debugger-server", "" + this.remoteDebuggerPort);
187 // Ignore eventual zombie instances of b2g that are left over
188 args.push("-no-remote");
190 return args;
191 },
192 });