Bug 562406 - Omnijar js components from startupcache during build(disabled by default, landing for mobile use) r=bsmedberg a=approval2.0
authorTaras Glek <tglek@mozilla.com>
Fri, 07 Jan 2011 11:04:33 -0800
changeset 60139 80dcb82a0cb7065aac5b8163005f1362c337f3de
parent 60138 d902db23c04ef8c83515991b654e08df43ff7ca0
child 60140 8ba73a8038a90ec3f31d64231de80cd30563e081
push id17879
push usertglek@mozilla.com
push dateFri, 07 Jan 2011 19:04:47 +0000
treeherdermozilla-central@80dcb82a0cb7 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbsmedberg, approval2
bugs562406
milestone2.0b9pre
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 562406 - Omnijar js components from startupcache during build(disabled by default, landing for mobile use) r=bsmedberg a=approval2.0
browser/installer/package-manifest.in
browser/installer/precompile_cache.js
startupcache/StartupCache.cpp
toolkit/mozapps/installer/packager.mk
--- a/browser/installer/package-manifest.in
+++ b/browser/installer/package-manifest.in
@@ -79,16 +79,17 @@
 #else
 @BINPATH@/mozcrt19.dll
 @BINPATH@/mozcpp19.dll
 #endif
 #endif
 
 [browser]
 ; [Base Browser Files]
+@BINPATH@/jsloader/
 #ifndef XP_UNIX
 @BINPATH@/@MOZ_APP_NAME@.exe
 #else
 @BINPATH@/@MOZ_APP_NAME@-bin
 @BINPATH@/@MOZ_APP_NAME@
 #endif
 @BINPATH@/application.ini
 @BINPATH@/platform.ini
new file mode 100644
--- /dev/null
+++ b/browser/installer/precompile_cache.js
@@ -0,0 +1,149 @@
+/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et: */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ * 
+ * Contributor(s):
+ *  Taras Glek <tglek@mozilla.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+// see http://mxr.mozilla.org/mozilla-central/source/services/sync/Weave.js#76
+
+const Cc = Components.classes;
+const Ci = Components.interfaces;
+const Cu = Components.utils;
+
+function setenv(name, val) {
+  try {
+        var environment = Components.classes["@mozilla.org/process/environment;1"].
+          getService(Components.interfaces.nsIEnvironment);
+        environment.set(name, val);
+  }
+  catch(e) {
+    displayError("setenv", e);
+  }
+}
+
+function load(url) {
+  print(url)
+  try {
+    Cu.import(url, null)
+  } catch(e) {
+    dump("Failed to import "+url + ":"+e+"\n");
+  }
+}
+
+function load_entries(entries, prefix) {
+  while(entries.hasMore()) {
+    var c = entries.getNext();
+    load(prefix + c);
+  }
+}
+
+function getGreDir() {
+  return Cc["@mozilla.org/file/directory_service;1"].getService(Ci.nsIProperties).get("GreD", Ci.nsIFile);
+}
+
+function openJar(file) {
+  var zipreader = Cc["@mozilla.org/libjar/zip-reader;1"].createInstance(Ci.nsIZipReader);
+  zipreader.open(file);
+  return zipreader;
+}
+
+// Check that files can be read from after closing zipreader
+function populate_omnijar() {
+  var file = getGreDir();
+  file.append("omni.jar");
+  setenv("MOZ_STARTUP_CACHE", file.path);
+  zipreader = openJar(file);
+
+  load_entries(zipreader.findEntries("components/*js"), "resource://gre/");
+  load_entries(zipreader.findEntries("modules/*jsm"), "resource://gre/");
+
+  // the sync part below doesn't work as smoothly
+  let ioService = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService);
+  let uri = ioService.newURI("resource:///modules/services-sync/",
+                             null, null);
+  let resProt = ioService.getProtocolHandler("resource")
+    .QueryInterface(Ci.nsIResProtocolHandler);
+  resProt.setSubstitution("services-sync", uri);
+
+  var entries = zipreader.findEntries("modules/services-sync/*js");
+  while(entries.hasMore()) {
+    var c = entries.getNext();
+    load("resource://services-sync/" + c.replace("modules/services-sync/", ""));
+  }
+  zipreader.close();
+}
+
+function extract_files(jar, pattern, dest) {
+  var entries = jar.findEntries(pattern);
+  while(entries.hasMore()) {
+    var c = entries.getNext();
+    var file = dest.clone();
+    for each(name in c.split("/"))
+      file.append(name);
+
+    if (!file.parent.exists()) { 
+      file.parent.create(1 /* Ci.nsIFile.DIRECTORY doesn't work*/, 0700);
+      print("Created " + file.parent.path)
+    }
+
+    if (jar.getEntry(c).isDirectory)
+      continue;
+    
+    try {
+      jar.extract(c, file);
+      print("extracted "+file.path+":"+file.fileSize);
+    }catch(e) {
+      // This shouldn't happen, but if it does it means the cache entry will be generated at runtime
+      // instead of at package-time.
+      print("Failed to extract " + file.path);
+      print(e)
+    }
+  }
+
+}
+
+function extract_jsloader_to_dist_bin() {
+  var dist_bin = getGreDir().parent;
+  dist_bin.append("bin");
+
+  var file = getGreDir();
+  file.append("omni.jar");
+
+  var zipReader = openJar(file);
+  // this should really be zipReader.extract(...), but that method is too broken
+  extract_files(zipReader, "jsloader/*", dist_bin);
+  zipReader.close();
+}
--- a/startupcache/StartupCache.cpp
+++ b/startupcache/StartupCache.cpp
@@ -58,17 +58,19 @@
 #include "nsIStringStream.h"
 #include "nsISupports.h"
 #include "nsITimer.h"
 #include "nsIZipWriter.h"
 #include "nsIZipReader.h"
 #include "nsWeakReference.h"
 #include "nsZipArchive.h"
 #include "mozilla/FunctionTimer.h"
-
+#include "mozilla/Omnijar.h"
+#include "prenv.h"
+ 
 #ifdef IS_BIG_ENDIAN
 #define SC_ENDIAN "big"
 #else
 #define SC_ENDIAN "little"
 #endif
 
 #if PR_BYTES_PER_WORD == 4
 #define SC_WORDSIZE "4"
@@ -137,36 +139,45 @@ nsresult
 StartupCache::Init() 
 {
   nsresult rv;
   mTable.Init();
 #ifdef DEBUG
   mWriteObjectMap.Init();
 #endif
 
-  nsCOMPtr<nsIFile> file;
-  rv = NS_GetSpecialDirectory("ProfLDS",
-                              getter_AddRefs(file));
-  if (NS_FAILED(rv)) {
-    // return silently, this will fail in mochitests's xpcshell process.
-    return rv;
+  // This allows to override the startup cache filename
+  // which is useful from xpcshell, when there is no ProfLDS directory to keep cache in.
+  char *env = PR_GetEnv("MOZ_STARTUP_CACHE");
+  if (env) {
+    rv = NS_NewLocalFile(NS_ConvertUTF8toUTF16(env), PR_FALSE, getter_AddRefs(mFile));
+  } else {
+    nsCOMPtr<nsIFile> file;
+    rv = NS_GetSpecialDirectory("ProfLDS",
+                                getter_AddRefs(file));
+    if (NS_FAILED(rv)) {
+      // return silently, this will fail in mochitests's xpcshell process.
+      return rv;
+    }
+
+    rv = file->AppendNative(NS_LITERAL_CSTRING("startupCache"));
+    NS_ENSURE_SUCCESS(rv, rv);
+
+    // Try to create the directory if it's not there yet
+    rv = file->Create(nsIFile::DIRECTORY_TYPE, 0777);
+    if (NS_FAILED(rv) && rv != NS_ERROR_FILE_ALREADY_EXISTS)
+      return rv;
+
+    rv = file->AppendNative(NS_LITERAL_CSTRING(sStartupCacheName));
+
+    NS_ENSURE_SUCCESS(rv, rv);
+    
+    mFile = do_QueryInterface(file);
   }
 
-  rv = file->AppendNative(NS_LITERAL_CSTRING("startupCache"));
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  // Try to create the directory if it's not there yet
-  rv = file->Create(nsIFile::DIRECTORY_TYPE, 0777);
-  if (NS_FAILED(rv) && rv != NS_ERROR_FILE_ALREADY_EXISTS)
-    return rv;
-
-  rv = file->AppendNative(NS_LITERAL_CSTRING(sStartupCacheName));
-  NS_ENSURE_SUCCESS(rv, rv);
-  
-  mFile = do_QueryInterface(file);
   NS_ENSURE_TRUE(mFile, NS_ERROR_UNEXPECTED);
 
   mObserverService = do_GetService("@mozilla.org/observer-service;1");
   
   if (!mObserverService) {
     NS_WARNING("Could not get observerService.");
     return NS_ERROR_UNEXPECTED;
   }
@@ -226,16 +237,25 @@ StartupCache::GetBuffer(const char* id, 
     nsZipItemPtr<char> zipItem(mArchive, id, true);
     if (zipItem) {
       *outbuf = zipItem.Forget();
       *length = zipItem.Length();
       return NS_OK;
     } 
   }
 
+  if (mozilla::OmnijarReader()) {
+    // no need to checksum omnijarred entries
+    nsZipItemPtr<char> zipItem(mozilla::OmnijarReader(), id);
+    if (zipItem) {
+      *outbuf = zipItem.Forget();
+      *length = zipItem.Length();
+      return NS_OK;
+    } 
+  }
   return NS_ERROR_NOT_AVAILABLE;
 }
 
 // Makes a copy of the buffer, client retains ownership of inbuf.
 nsresult
 StartupCache::PutBuffer(const char* id, const char* inbuf, PRUint32 len) 
 {
   WaitOnWriteThread();
--- a/toolkit/mozapps/installer/packager.mk
+++ b/toolkit/mozapps/installer/packager.mk
@@ -302,16 +302,17 @@ OMNIJAR_FILES	= \
   chrome.manifest \
   components/*.js \
   components/*.xpt \
   components/*.manifest \
   modules \
   res \
   defaults \
   greprefs.js \
+  jsloader \
   $(NULL)
 
 NON_OMNIJAR_FILES += \
   chrome/icons/\* \
   defaults/pref/channel-prefs.js \
   res/cursors/\* \
   res/MainMenu.nib/\* \
   $(NULL)