Bug 745069 - Add methods to DOMApplicationRegistry for AitC support; r=fabrice
authorAnant Narayanan <anant@kix.in>
Sat, 28 Apr 2012 00:10:08 -0700
changeset 95735 8e59a61ca83136b880fe273dfa7ac69f2cb36cd2
parent 95734 31faeb7325134829e50aaa4f725f04c59b9f725f
child 95736 005a5bfe547406d6cb7d76b90dabd56ee65fc036
push id1439
push userlsblakk@mozilla.com
push dateMon, 04 Jun 2012 20:19:22 +0000
treeherdermozilla-aurora@ea74834dccd3 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersfabrice
bugs745069
milestone15.0a1
Bug 745069 - Add methods to DOMApplicationRegistry for AitC support; r=fabrice
dom/base/Webapps.jsm
services/sync/modules/engines/apps.js
--- a/dom/base/Webapps.jsm
+++ b/dom/base/Webapps.jsm
@@ -1,13 +1,13 @@
 /* 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/. */
 
-const Cu = Components.utils; 
+const Cu = Components.utils;
 const Cc = Components.classes;
 const Ci = Components.interfaces;
 
 let EXPORTED_SYMBOLS = ["DOMApplicationRegistry", "DOMApplicationManifest"];
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/FileUtils.jsm");
@@ -171,48 +171,51 @@ let DOMApplicationRegistry = {
 
     // install an application again is considered as an update
     if (id) {
       let dir = FileUtils.getDir(DIRECTORY_NAME, ["webapps", id], true, true);
       try {
         dir.remove(true);
       } catch(e) {
       }
-    }
-    else {
-      let uuidGenerator = Cc["@mozilla.org/uuid-generator;1"].getService(Ci.nsIUUIDGenerator);
-      id = uuidGenerator.generateUUID().toString();
+    } else {
+      id = this.makeAppId();
     }
 
+    let appObject = this._cloneAppObject(app);
+    appObject.installTime = (new Date()).getTime();
+    let appNote = JSON.stringify(appObject);
+    appNote.id = id;
+
     let dir = FileUtils.getDir(DIRECTORY_NAME, ["webapps", id], true, true);
-
     let manFile = dir.clone();
     manFile.append("manifest.json");
     this._writeFile(manFile, JSON.stringify(app.manifest));
+    this.webapps[id] = appObject;
 
-    this.webapps[id] = this._cloneAppObject(app);
-    delete this.webapps[id].manifest;
-    this.webapps[id].installTime = (new Date()).getTime()
-
-    
     if (!aFromSync)
       this._saveApps((function() {
         ppmm.sendAsyncMessage("Webapps:Install:Return:OK", aData);
-        Services.obs.notifyObservers(this, "webapps-sync-install", id);
+        Services.obs.notifyObservers(this, "webapps-sync-install", appNote);
       }).bind(this));
   },
 
   _appId: function(aURI) {
     for (let id in this.webapps) {
       if (this.webapps[id].origin == aURI)
         return id;
     }
     return null;
   },
 
+  makeAppId: function() {
+    let uuidGenerator = Cc["@mozilla.org/uuid-generator;1"].getService(Ci.nsIUUIDGenerator);
+    return uuidGenerator.generateUUID().toString();
+  },
+
   _saveApps: function(aCallback) {
     this._writeFile(this.appsFile, JSON.stringify(this.webapps), function() {
       if (aCallback)
         aCallback();
     });
   },
 
   /**
@@ -228,34 +231,38 @@ let DOMApplicationRegistry = {
     let id = aData[index].id;
     let file = FileUtils.getFile(DIRECTORY_NAME, ["webapps", id, "manifest.json"], true);
     this._loadJSONAsync(file, (function(aJSON) {
       aData[index].manifest = aJSON;
       if (index == aData.length - 1)
         aFinalCallback(aData);
       else
         this._readManifests(aData, aFinalCallback, index + 1);
-    }).bind(this)); 
+    }).bind(this));
   },
 
   uninstall: function(aData) {
     let found = false;
     for (let id in this.webapps) {
       let app = this.webapps[id];
       if (app.origin == aData.origin) {
         found = true;
+        let appNote = JSON.stringify(this._cloneAppObject(app));
+        appNote.id = id;
+
         delete this.webapps[id];
         let dir = FileUtils.getDir(DIRECTORY_NAME, ["webapps", id], true, true);
         try {
           dir.remove(true);
         } catch (e) {
         }
+
         this._saveApps((function() {
           ppmm.sendAsyncMessage("Webapps:Uninstall:Return:OK", aData);
-          Services.obs.notifyObservers(this, "webapps-sync-uninstall", id);
+          Services.obs.notifyObservers(this, "webapps-sync-uninstall", appNote);
         }).bind(this));
       }
     }
     if (!found)
       ppmm.sendAsyncMessage("Webapps:Uninstall:Return:KO", aData);
   },
 
   getSelf: function(aData) {
@@ -294,17 +301,17 @@ let DOMApplicationRegistry = {
       ppmm.sendAsyncMessage("Webapps:GetInstalled:Return:OK", aData);
     }).bind(this));
   },
 
   getAll: function(aData) {
     aData.apps = [];
     let tmp = [];
 
-    for (id in this.webapps) {
+    for (let id in this.webapps) {
       let app = this._cloneAppObject(this.webapps[id]);
       aData.apps.push(app);
       tmp.push({ id: id });
     }
 
     this._readManifests(tmp, (function(aResult) {
       for (let i = 0; i < aResult.length; i++)
         aData.apps[i].manifest = aResult[i].manifest;
@@ -322,28 +329,36 @@ let DOMApplicationRegistry = {
       return;
     }
 
     this._readManifests([{ id: id }], function(aResult) {
       aCallback(aResult[0].manifest);
     });
   },
 
-  /** added to support the sync engine */
+  /** Added to support AITC and classic sync */
+  itemExists: function(aId) {
+    return !!this.webapps[aId];
+  },
 
   getAppById: function(aId) {
     if (!this.webapps[aId])
       return null;
-
+    
     let app = this._cloneAppObject(this.webapps[aId]);
     return app;
   },
   
-  itemExists: function(aId) {
-    return !!this.webapps[aId];
+  getAllWithoutManifests: function(aCallback) {
+    let result = {};
+    for (let id in this.webapps) {
+      let app = this._cloneAppObject(this.webapps[id]);
+      result[id] = app;
+    }
+    aCallback(result);
   },
 
   updateApps: function(aRecords, aCallback) {
     for (let i = 0; i < aRecords.length; i++) {
       let record = aRecords[i];
       if (record.deleted) {
         if (!this.webapps[record.id])
           continue;
@@ -351,33 +366,29 @@ let DOMApplicationRegistry = {
         delete this.webapps[record.id];
         let dir = FileUtils.getDir(DIRECTORY_NAME, ["webapps", record.id], true, true);
         try {
           dir.remove(true);
         } catch (e) {
         }
         ppmm.sendAsyncMessage("Webapps:Uninstall:Return:OK", { origin: origin });
       } else {
-        if (!!this.webapps[record.id]) {
+        if (this.webapps[record.id]) {
           this.webapps[record.id] = record.value;
           delete this.webapps[record.id].manifest;
-        }
-        else {
+        } else {
           let data = { app: record.value };
           this.confirmInstall(data, true);
           ppmm.sendAsyncMessage("Webapps:Install:Return:OK", data);
         }
       }
     }
     this._saveApps(aCallback);
   },
 
-  /*
-   * May be removed once sync API change
-   */
   getAllIDs: function() {
     let apps = {};
     for (let id in this.webapps) {
       // only sync http and https apps
       if (this.webapps[id].origin.indexOf("http") == 0)
         apps[id] = true;
     }
     return apps;
@@ -389,87 +400,87 @@ let DOMApplicationRegistry = {
       delete this.webapps[id];
       let dir = FileUtils.getDir(DIRECTORY_NAME, ["webapps", id], true, true);
       try {
         dir.remove(true);
       } catch (e) {
       }
     }
     this._saveApps(aCallback);
-   }
+  }
 };
 
 /**
  * Helper object to access manifest information with locale support
  */
 DOMApplicationManifest = function(aManifest, aOrigin) {
   this._origin = Services.io.newURI(aOrigin, null, null);
   this._manifest = aManifest;
   let chrome = Cc["@mozilla.org/chrome/chrome-registry;1"].getService(Ci.nsIXULChromeRegistry)
                                                           .QueryInterface(Ci.nsIToolkitChromeRegistry);
   let locale = chrome.getSelectedLocale("browser").toLowerCase();
   this._localeRoot = this._manifest;
-  
+
   if (this._manifest.locales && this._manifest.locales[locale]) {
     this._localeRoot = this._manifest.locales[locale];
   }
   else if (this._manifest.locales) {
     // try with the language part of the locale ("en" for en-GB) only
     let lang = locale.split('-')[0];
     if (lang != locale && this._manifest.locales[lang])
       this._localeRoot = this._manifest.locales[lang];
   }
-}
+};
 
 DOMApplicationManifest.prototype = {
   _localeProp: function(aProp) {
     if (this._localeRoot[aProp] != undefined)
       return this._localeRoot[aProp];
     return this._manifest[aProp];
   },
 
   get name() {
     return this._localeProp("name");
   },
-  
+
   get description() {
     return this._localeProp("description");
   },
-  
+
   get version() {
     return this._localeProp("version");
   },
-  
+
   get launch_path() {
     return this._localeProp("launch_path");
   },
-  
+
   get developer() {
     return this._localeProp("developer");
   },
-  
+
   get icons() {
     return this._localeProp("icons");
   },
-  
+
   iconURLForSize: function(aSize) {
     let icons = this._localeProp("icons");
     if (!icons)
       return null;
     let dist = 100000;
     let icon = null;
     for (let size in icons) {
       let iSize = parseInt(size);
       if (Math.abs(iSize - aSize) < dist) {
         icon = this._origin.resolve(icons[size]);
         dist = Math.abs(iSize - aSize);
       }
     }
     return icon;
   },
-  
+
   fullLaunchPath: function() {
     let launchPath = this._localeProp("launch_path");
     return this._origin.resolve(launchPath ? launchPath : "");
   }
-}
+};
 
 DOMApplicationRegistry.init();
--- a/services/sync/modules/engines/apps.js
+++ b/services/sync/modules/engines/apps.js
@@ -126,18 +126,25 @@ AppTracker.prototype = {
   _enabled: false,
 
   observe: function(aSubject, aTopic, aData) {
     switch (aTopic) {
       case "webapps-sync-install":
       case "webapps-sync-uninstall":
         // ask for immediate sync. not sure if we really need this or
         // if a lower score increment would be enough
+        let app;
         this.score += SCORE_INCREMENT_XLARGE;
-        this.addChangedID(aData);
+        try {
+          app = JSON.parse(aData);
+        } catch (e) {
+          this._log.error("JSON.parse failed in observer " + e);
+          return;
+        }
+        this.addChangedID(app.id);
         break;
       case "weave:engine:start-tracking":
         this._enabled = true;
         Svc.Obs.add("webapps-sync-install", this);
         Svc.Obs.add("webapps-sync-uninstall", this);
         break;
       case "weave:engine:stop-tracking":
         this._enabled = false;