Bug 1100964 - Reset phone while enabling unrestricted devtools mode. r=fabrice, r=sicking
authorAlexandre Poirot <poirot.alex@gmail.com>
Wed, 26 Nov 2014 06:46:00 -0500
changeset 231092 2e4cbe93b9b0a65275d3f37884d56513e7c3c1f8
parent 231091 6271f062572dccfd34b5be99c63464cfd3b804c5
child 231093 73349687b4267aab6c94f9e338698e5dc60a4527
push id191
push usernalexander@mozilla.com
push dateMon, 08 Dec 2014 20:47:29 +0000
reviewersfabrice, sicking
bugs1100964
milestone37.0a1
Bug 1100964 - Reset phone while enabling unrestricted devtools mode. r=fabrice, r=sicking
b2g/components/ProcessGlobal.js
b2g/components/RecoveryService.js
dom/webidl/MozPowerManager.webidl
hal/gonk/GonkHal.cpp
hal/sandbox/SandboxHal.cpp
--- a/b2g/components/ProcessGlobal.js
+++ b/b2g/components/ProcessGlobal.js
@@ -17,16 +17,20 @@
 
 const Cc = Components.classes;
 const Ci = Components.interfaces;
 const Cu = Components.utils;
 
 Cu.import('resource://gre/modules/Services.jsm');
 Cu.import('resource://gre/modules/XPCOMUtils.jsm');
 
+XPCOMUtils.defineLazyServiceGetter(this, "settings",
+                                   "@mozilla.org/settingsService;1",
+                                   "nsISettingsService");
+
 function debug(msg) {
   log(msg);
 }
 function log(msg) {
   // This file implements console.log(), so use dump().
   //dump('ProcessGlobal: ' + msg + '\n');
 }
 
@@ -84,50 +88,55 @@ ProcessGlobal.prototype = {
       let file = entries.getNext().QueryInterface(Ci.nsIFile);
       log("Deleting " + file.path);
       try {
         file.remove(true);
       } catch(e) {}
     }
   },
 
-  processWipeFile: function(text) {
-    log("processWipeFile " + text);
+  processCommandsFile: function(text) {
+    log("processCommandsFile " + text);
     let lines = text.split("\n");
     lines.forEach((line) => {
       log(line);
       let params = line.split(" ");
       if (params[0] == "wipe") {
         this.wipeDir(params[1]);
+      } else if (params[0] == "root") {
+        log("unrestrict devtools");
+        Services.prefs.setBoolPref("devtools.debugger.forbid-certified-apps", false);
+        let lock = settings.createLock();
+        lock.set("developer.menu.enabled", true, null);
       }
     });
   },
 
   cleanupAfterFactoryReset: function() {
     log("cleanupAfterWipe start");
 
     Cu.import("resource://gre/modules/osfile.jsm");
     let dir = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
     dir.initWithPath("/persist");
     var postResetFile = dir.exists() ?
                         OS.Path.join("/persist", gFactoryResetFile):
                         OS.Path.join("/cache", gFactoryResetFile);
     let file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
     file.initWithPath(postResetFile);
     if (!file.exists()) {
-      debug("Nothing to wipe.")
+      debug("No additional command.")
       return;
     }
 
     let promise = OS.File.read(postResetFile);
     promise.then(
       (array) => {
         file.remove(false);
         let decoder = new TextDecoder();
-        this.processWipeFile(decoder.decode(array));
+        this.processCommandsFile(decoder.decode(array));
       },
       function onError(error) {
         debug("Error: " + error);
       }
     );
 
     log("cleanupAfterWipe end.");
   },
--- a/b2g/components/RecoveryService.js
+++ b/b2g/components/RecoveryService.js
@@ -76,36 +76,42 @@ RecoveryService.prototype = {
                     .getService(Ci.nsICacheStorageService);
       cache.clear();
       if (librecovery.factoryReset() != 0) {
         log("Error: Factory reset failed again");
       }
     }
 
     log("factoryReset " + reason);
+    let commands = [];
     if (reason == "wipe") {
       let volumeService = Cc["@mozilla.org/telephony/volume-service;1"]
                           .getService(Ci.nsIVolumeService);
       let volNames = volumeService.getVolumeNames();
       log("Found " + volNames.length + " volumes");
-      let text = "";
+
       for (let i = 0; i < volNames.length; i++) {
         let name = volNames.queryElementAt(i, Ci.nsISupportsString);
         let volume = volumeService.getVolumeByName(name.data);
         log("Got volume: " + name.data + " at " + volume.mountPoint);
-        text += "wipe " + volume.mountPoint + "\n";
+        commands.push("wipe " + volume.mountPoint);
       }
+    } else if (reason == "root") {
+      commands.push("root");
+    }
 
+    if (commands.length > 0) {
       Cu.import("resource://gre/modules/osfile.jsm");
       let dir = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
       dir.initWithPath("/persist");
       var postResetFile = dir.exists() ?
                           OS.Path.join("/persist", gFactoryResetFile):
                           OS.Path.join("/cache", gFactoryResetFile);
       let encoder = new TextEncoder();
+      let text = commands.join("\n");
       let array = encoder.encode(text);
       let promise = OS.File.writeAtomic(postResetFile, array,
                                         { tmpPath: postResetFile + ".tmp" });
 
       promise.then(doReset, function onError(error) {
         log("Error: " + error);
       });
     } else {
--- a/dom/webidl/MozPowerManager.webidl
+++ b/dom/webidl/MozPowerManager.webidl
@@ -4,20 +4,23 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 interface MozWakeLockListener;
 
 /**
   * The reason for the factory reset.
   * "normal" : simple factory reset.
   * "wipe"   : will also attempt to wipe all user storage areas.
+  * "root"   : simple factory reset that also root the phone to get more
+  *            privileges when using devtools.
   */
 enum FactoryResetReason {
     "normal",
-    "wipe"
+    "wipe",
+    "root"
 };
 
 /**
  * This interface implements navigator.mozPower
  */
 interface MozPowerManager
 {
     [Throws]
--- a/hal/gonk/GonkHal.cpp
+++ b/hal/gonk/GonkHal.cpp
@@ -1772,15 +1772,17 @@ FactoryReset(FactoryResetReason& aReason
     do_GetService("@mozilla.org/recovery-service;1");
   if (!recoveryService) {
     NS_WARNING("Could not get recovery service!");
     return;
   }
 
   if (aReason == FactoryResetReason::Wipe) {
     recoveryService->FactoryReset("wipe");
+  } else if (aReason == FactoryResetReason::Root) {
+    recoveryService->FactoryReset("root");
   } else {
     recoveryService->FactoryReset("normal");
   }
 }
 
 } // hal_impl
 } // mozilla
--- a/hal/sandbox/SandboxHal.cpp
+++ b/hal/sandbox/SandboxHal.cpp
@@ -441,16 +441,18 @@ DisableRDS()
 
 void
 FactoryReset(FactoryResetReason& aReason)
 {
   if (aReason == FactoryResetReason::Normal) {
     Hal()->SendFactoryReset(NS_LITERAL_STRING("normal"));
   } else if (aReason == FactoryResetReason::Wipe) {
     Hal()->SendFactoryReset(NS_LITERAL_STRING("wipe"));
+  } else if (aReason == FactoryResetReason::Root) {
+    Hal()->SendFactoryReset(NS_LITERAL_STRING("root"));
   }
 }
 
 void
 StartDiskSpaceWatcher()
 {
   NS_RUNTIMEABORT("StartDiskSpaceWatcher() can't be called from sandboxed contexts.");
 }
@@ -865,16 +867,18 @@ public:
       return false;
     }
 
     FactoryResetReason reason = FactoryResetReason::Normal;
     if (aReason.EqualsLiteral("normal")) {
       reason = FactoryResetReason::Normal;
     } else if (aReason.EqualsLiteral("wipe")) {
       reason = FactoryResetReason::Wipe;
+    } else if (aReason.EqualsLiteral("root")) {
+      reason = FactoryResetReason::Root;
     } else {
       // Invalid factory reset reason. That should never happen.
       return false;
     }
 
     hal::FactoryReset(reason);
     return true;
   }