Bug 798395 - Let us specify a file to load into about:memory (as about:memory?file=/path/to/file). r=njn
authorJustin Lebar <justin.lebar@gmail.com>
Fri, 19 Oct 2012 11:51:51 -0400
changeset 110916 610a7c294f0ed3f3b094c654e86515af118bf6d3
parent 110915 9086b50a71c3c0fce9af0f55a4df5ab82fed605f
child 110917 fb33f8e799c8d3ccb0db558054623ed415c084dd
push id93
push usernmatsakis@mozilla.com
push dateWed, 31 Oct 2012 21:26:57 +0000
reviewersnjn
bugs798395
milestone19.0a1
Bug 798395 - Let us specify a file to load into about:memory (as about:memory?file=/path/to/file). r=njn
toolkit/components/aboutmemory/content/aboutMemory.js
--- a/toolkit/components/aboutmemory/content/aboutMemory.js
+++ b/toolkit/components/aboutmemory/content/aboutMemory.js
@@ -1,14 +1,30 @@
 /* -*- Mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil; -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 // This file is used for both about:memory and about:compartments.
+//
+//
+// about:memory will by default show information about the browser's current
+// memory usage, but you can direct it to load information from a file by
+// providing a file= query string.  For example,
+//
+//     about:memory?file=/foo/bar
+//     about:memory?verbose&file=/foo/bar
+//
+// The order of "verbose" and "file=" isn't significant, and neither "verbose"
+// nor "file=" is case-sensitive.  Obviously the filename is case-sensitive iff
+// you're on a case-sensitive filesystem.  If you specify more than one "file="
+// argument, only the first one is used.
+//
+// about:compartments doesn't support the "verbose" or "file=" parameters and
+// will ignore them if they're provided.
 
 "use strict";
 
 //---------------------------------------------------------------------------
 // Code shared by about:memory and about:compartments
 //---------------------------------------------------------------------------
 
 const Cc = Components.classes;
@@ -30,17 +46,26 @@ let gUnnamedProcessStr = "Main Process";
 
 // Because about:memory and about:compartments are non-standard URLs,
 // location.search is undefined, so we have to use location.href here.
 // The toLowerCase() calls ensure that addresses like "ABOUT:MEMORY" work.
 let gVerbose;
 {
   let split = document.location.href.split('?');
   document.title = split[0].toLowerCase();
-  gVerbose = split.length == 2 && split[1].toLowerCase() == 'verbose';
+
+  gVerbose = false;
+  if (split.length == 2) {
+    let searchSplit = split[1].split('&');
+    for (let i = 0; i < searchSplit.length; i++) {
+      if (searchSplit[i].toLowerCase() == 'verbose') {
+        gVerbose = true;
+      }
+    }
+  }
 }
 
 let gChildMemoryListener = undefined;
 
 // This is a useful function and an efficient way to implement it.
 String.prototype.startsWith =
   function(s) { return this.lastIndexOf(s, 0) === 0; }
 
@@ -331,16 +356,31 @@ function isSmapsPath(aUnsafePath)
   }
   return false;
 }
 
 //---------------------------------------------------------------------------
 
 function onLoadAboutMemory()
 {
+  // Check location.href to see if we're loading from a file.
+  let search = location.href.split('?')[1];
+  if (search) {
+    let searchSplit = search.split('&');
+    for (let i = 0; i < searchSplit.length; i++) {
+      if (searchSplit[i].toLowerCase().startsWith('file=')) {
+        let filename = searchSplit[i].substring('file='.length);
+        let file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
+        file.initWithPath(filename);
+        updateAboutMemoryFromFile(file);
+        return;
+      }
+    }
+  }
+
   addChildObserversAndUpdate(updateAboutMemory);
 }
 
 function doGlobalGC()
 {
   Cu.forceGC();
   let os = Cc["@mozilla.org/observer-service;1"]
             .getService(Ci.nsIObserverService);
@@ -423,33 +463,41 @@ function updateAboutMemoryFromJSONString
   }
 }
 
 /**
  * Like updateAboutMemory(), but gets its data from a file instead of the
  * memory reporters.
  *
  * @param aFile
- *        The File being read from.  Accepted format is described in the
+ *        The File or nsILocalFile being read from.
+ *
+ *        The expected format of the file's contents is described in the
  *        comment describing nsIMemoryReporterManager::dumpReports.
  */
 function updateAboutMemoryFromFile(aFile)
 {
   // Note: reader.onload is called asynchronously, once FileReader.readAsText()
   // completes.  Therefore its exception handling has to be distinct from that
   // surrounding the |reader.readAsText(aFile)| call.
 
   try {
+    // Convert nsILocalFile to a File object, if necessary.
+    let file = aFile;
+    if (aFile instanceof Ci.nsILocalFile) {
+      file = new File(aFile);
+    }
+
     let reader = new FileReader();
     reader.onerror = function(aEvent) { throw "FileReader.onerror"; };
     reader.onabort = function(aEvent) { throw "FileReader.onabort"; };
     reader.onload = function(aEvent) {
       updateAboutMemoryFromJSONString(aEvent.target.result);
     };
-    reader.readAsText(aFile);
+    reader.readAsText(file);
 
   } catch (ex) {
     let body = clearBody();
     handleException(ex);
     appendAboutMemoryFooter(body);
   }
 }