Wed, 31 Dec 2014 06:55:50 +0100
Added tag UPSTREAM_283F7C6 for changeset ca08bd8f51b2
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 file,
3 * You can obtain one at http://mozilla.org/MPL/2.0/. */
5 this.CC = Components.Constructor;
6 this.Cc = Components.classes;
7 this.Ci = Components.interfaces;
8 this.Cu = Components.utils;
10 const MARIONETTE_CONTRACTID = "@mozilla.org/marionette;1";
11 const MARIONETTE_CID = Components.ID("{786a1369-dca5-4adc-8486-33d23c88010a}");
12 const MARIONETTE_ENABLED_PREF = 'marionette.defaultPrefs.enabled';
13 const MARIONETTE_FORCELOCAL_PREF = 'marionette.force-local';
14 const MARIONETTE_LOG_PREF = 'marionette.logging';
16 this.ServerSocket = CC("@mozilla.org/network/server-socket;1",
17 "nsIServerSocket",
18 "initSpecialConnection");
20 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
21 Cu.import("resource://gre/modules/Services.jsm");
22 Cu.import("resource://gre/modules/FileUtils.jsm");
23 Cu.import("resource://gre/modules/Log.jsm");
25 let loader = Cc["@mozilla.org/moz/jssubscript-loader;1"]
26 .getService(Ci.mozIJSSubScriptLoader);
28 function MarionetteComponent() {
29 this._loaded = false;
30 this.observerService = Services.obs;
32 // set up the logger
33 this.logger = Log.repository.getLogger("Marionette");
34 this.logger.level = Log.Level["Trace"];
35 let dumper = false;
36 #ifdef DEBUG
37 dumper = true;
38 #endif
39 #ifdef MOZ_B2G
40 dumper = true;
41 #endif
42 try {
43 if (dumper || Services.prefs.getBoolPref(MARIONETTE_LOG_PREF)) {
44 let formatter = new Log.BasicFormatter();
45 this.logger.addAppender(new Log.DumpAppender(formatter));
46 }
47 }
48 catch(e) {}
49 }
51 MarionetteComponent.prototype = {
52 classDescription: "Marionette component",
53 classID: MARIONETTE_CID,
54 contractID: MARIONETTE_CONTRACTID,
55 QueryInterface: XPCOMUtils.generateQI([Ci.nsICommandLineHandler, Ci.nsIObserver]),
56 _xpcom_categories: [{category: "command-line-handler", entry: "b-marionette"},
57 {category: "profile-after-change", service: true}],
58 appName: Services.appinfo.name,
59 enabled: false,
60 finalUiStartup: false,
61 _marionetteServer: null,
63 onSocketAccepted: function mc_onSocketAccepted(aSocket, aTransport) {
64 this.logger.info("onSocketAccepted for Marionette dummy socket");
65 },
67 onStopListening: function mc_onStopListening(aSocket, status) {
68 this.logger.info("onStopListening for Marionette dummy socket, code " + status);
69 aSocket.close();
70 },
72 // Check cmdLine argument for --marionette
73 handle: function mc_handle(cmdLine) {
74 // If the CLI is there then lets do work otherwise nothing to see
75 if (cmdLine.handleFlag("marionette", false)) {
76 this.enabled = true;
77 this.logger.info("marionette enabled via command-line");
78 this.init();
79 }
80 },
82 observe: function mc_observe(aSubject, aTopic, aData) {
83 switch (aTopic) {
84 case "profile-after-change":
85 // Using final-ui-startup as the xpcom category doesn't seem to work,
86 // so we wait for that by adding an observer here.
87 this.observerService.addObserver(this, "final-ui-startup", false);
88 #ifdef ENABLE_MARIONETTE
89 let enabledPref = false;
90 try {
91 enabledPref = Services.prefs.getBoolPref(MARIONETTE_ENABLED_PREF);
92 } catch(e) {}
93 if (enabledPref) {
94 this.enabled = true;
95 this.logger.info("marionette enabled via build flag and pref");
97 // We want to suppress the modal dialog that's shown
98 // when starting up in safe-mode to enable testing.
99 if (Services.appinfo.inSafeMode) {
100 this.observerService.addObserver(this, "domwindowopened", false);
101 }
102 }
103 #endif
104 break;
105 case "final-ui-startup":
106 this.finalUiStartup = true;
107 this.observerService.removeObserver(this, aTopic);
108 this.observerService.addObserver(this, "xpcom-shutdown", false);
109 this.init();
110 break;
111 case "domwindowopened":
112 this.observerService.removeObserver(this, aTopic);
113 this._suppressSafeModeDialog(aSubject);
114 break;
115 case "xpcom-shutdown":
116 this.observerService.removeObserver(this, "xpcom-shutdown");
117 this.uninit();
118 break;
119 }
120 },
122 _suppressSafeModeDialog: function mc_suppressSafeModeDialog(aWindow) {
123 // Wait for the modal dialog to finish loading.
124 aWindow.addEventListener("load", function onLoad() {
125 aWindow.removeEventListener("load", onLoad);
127 if (aWindow.document.getElementById("safeModeDialog")) {
128 aWindow.setTimeout(() => {
129 // Accept the dialog to start in safe-mode.
130 aWindow.document.documentElement.getButton("accept").click();
131 });
132 }
133 });
134 },
136 init: function mc_init() {
137 if (!this._loaded && this.enabled && this.finalUiStartup) {
138 this._loaded = true;
140 let marionette_forcelocal = this.appName == 'B2G' ? false : true;
141 try {
142 marionette_forcelocal = Services.prefs.getBoolPref(MARIONETTE_FORCELOCAL_PREF);
143 }
144 catch(e) {}
145 Services.prefs.setBoolPref(MARIONETTE_FORCELOCAL_PREF, marionette_forcelocal);
147 if (!marionette_forcelocal) {
148 // See bug 800138. Because the first socket that opens with
149 // force-local=false fails, we open a dummy socket that will fail.
150 // keepWhenOffline=true so that it still work when offline (local).
151 // This allows the following attempt by Marionette to open a socket
152 // to succeed.
153 let insaneSacrificialGoat = new ServerSocket(666, Ci.nsIServerSocket.KeepWhenOffline, 4);
154 insaneSacrificialGoat.asyncListen(this);
155 }
157 let port;
158 try {
159 port = Services.prefs.getIntPref('marionette.defaultPrefs.port');
160 }
161 catch(e) {
162 port = 2828;
163 }
164 try {
165 loader.loadSubScript("chrome://marionette/content/marionette-server.js");
166 let forceLocal = Services.prefs.getBoolPref(MARIONETTE_FORCELOCAL_PREF);
167 this._marionetteServer = new MarionetteServer(port, forceLocal);
168 this.logger.info("Marionette server ready");
169 }
170 catch(e) {
171 this.logger.error('exception: ' + e.name + ', ' + e.message);
172 }
173 }
174 },
176 uninit: function mc_uninit() {
177 if (this._marionetteServer) {
178 this._marionetteServer.closeListener();
179 }
180 this._loaded = false;
181 },
183 };
185 this.NSGetFactory = XPCOMUtils.generateNSGetFactory([MarionetteComponent]);