Bug 252830: Blocked XPI install should have allow once feature. r+sr=dveditz, r=gavin.sharp, a=bzbarsky
authordtownsend@oxymoronical.com
Fri, 31 Aug 2007 12:29:18 -0700
changeset 5514 7fcf7dd292a84b00dd7c2b8a1fffadbe84349ee1
parent 5513 5e596e7ec18b0554f91716015ac19512f8e50329
child 5515 ed85f79beabbee14f55071ff4a5fe2be157cf2f0
push idunknown
push userunknown
push dateunknown
reviewersgavin.sharp, bzbarsky
bugs252830
milestone1.9a8pre
Bug 252830: Blocked XPI install should have allow once feature. r+sr=dveditz, r=gavin.sharp, a=bzbarsky
browser/base/content/browser.js
browser/locales/en-US/chrome/browser/browser.properties
xpinstall/public/Makefile.in
xpinstall/public/nsIDOMInstallTriggerGlobal.h
xpinstall/public/nsIXPIInstallInfo.idl
xpinstall/public/nsIXPInstallManager.idl
xpinstall/src/Makefile.in
xpinstall/src/nsInstallTrigger.cpp
xpinstall/src/nsInstallTrigger.h
xpinstall/src/nsJSInstallTriggerGlobal.cpp
xpinstall/src/nsXPIInstallInfo.cpp
xpinstall/src/nsXPIInstallInfo.h
xpinstall/src/nsXPInstallManager.cpp
xpinstall/src/nsXPInstallManager.h
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -657,23 +657,26 @@ const gXPInstallObserver = {
     }
     return null;
   },
 
   observe: function (aSubject, aTopic, aData)
   {
     var brandBundle = document.getElementById("bundle_brand");
     var browserBundle = document.getElementById("bundle_browser");
-    var browser, webNav, wm;
     switch (aTopic) {
     case "xpinstall-install-blocked":
-      var shell = aSubject.QueryInterface(Components.interfaces.nsIDocShell);
-      browser = this._getBrowser(shell);
+      var installInfo = aSubject.QueryInterface(Components.interfaces.nsIXPIInstallInfo);
+      var win = installInfo.originatingWindow;
+      var shell = win.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
+                     .getInterface(Components.interfaces.nsIWebNavigation)
+                     .QueryInterface(Components.interfaces.nsIDocShell);
+      var browser = this._getBrowser(shell);
       if (browser) {
-        var host = aData;
+        var host = installInfo.originatingURI.host;
         var brandShortName = brandBundle.getString("brandShortName");
         var notificationName, messageString, buttons;
         if (!gPrefService.getBoolPref("xpinstall.enabled")) {
           notificationName = "xpinstall-disabled"
           if (gPrefService.prefIsLocked("xpinstall.enabled")) {
             messageString = browserBundle.getString("xpinstallDisabledMessageLocked");
             buttons = [];
           }
@@ -693,64 +696,41 @@ const gXPInstallObserver = {
           }
         }
         else {
           notificationName = "xpinstall"
           messageString = browserBundle.getFormattedString("xpinstallPromptWarning",
                                                            [brandShortName, host]);
 
           buttons = [{
-            label: browserBundle.getString("xpinstallPromptWarningButton"),
-            accessKey: browserBundle.getString("xpinstallPromptWarningButton.accesskey"),
+            label: browserBundle.getString("xpinstallPromptAllowButton"),
+            accessKey: browserBundle.getString("xpinstallPromptAllowButton.accesskey"),
             popup: null,
-            callback: function() { return xpinstallEditPermissions(shell, host); }
+            callback: function() {
+              var mgr = Components.classes["@mozilla.org/xpinstall/install-manager;1"]
+                                  .createInstance(Components.interfaces.nsIXPInstallManager);
+              mgr.initManagerWithInstallInfo(installInfo);
+              return false;
+            }
           }];
         }
 
         var notificationBox = gBrowser.getNotificationBox(browser);
         if (!notificationBox.getNotificationWithValue(notificationName)) {
           const priority = notificationBox.PRIORITY_WARNING_MEDIUM;
           const iconURL = "chrome://mozapps/skin/xpinstall/xpinstallItemGeneric.png";
           notificationBox.appendNotification(messageString, notificationName,
                                              iconURL, priority, buttons);
         }
       }
       break;
     }
   }
 };
 
-function xpinstallEditPermissions(aDocShell, aHost)
-{
-  var browser = gXPInstallObserver._getBrowser(aDocShell);
-  if (browser) {
-    var bundlePreferences = document.getElementById("bundle_preferences");
-    var params = { blockVisible   : false,
-                   sessionVisible : false,
-                   allowVisible   : true,
-                   prefilledHost  : aHost,
-                   permissionType : "install",
-                   windowTitle    : bundlePreferences.getString("addons_permissions_title"),
-                   introText      : bundlePreferences.getString("addonspermissionstext") };
-    var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"]
-                   .getService(Components.interfaces.nsIWindowMediator);
-    var existingWindow = wm.getMostRecentWindow("Browser:Permissions");
-    if (existingWindow) {
-      existingWindow.initWithParams(params);
-      existingWindow.focus();
-    }
-    else
-      window.openDialog("chrome://browser/content/preferences/permissions.xul",
-                        "_blank", "resizable,dialog=no,centerscreen", params);
-    return false;
-  }
-
-  return true;
-}
-
 function BrowserStartup()
 {
   gBrowser = document.getElementById("content");
 
   var uriToLoad = null;
   // Check for window.arguments[0]. If present, use that for uriToLoad.
   if ("arguments" in window && window.arguments[0])
     uriToLoad = window.arguments[0];
--- a/browser/locales/en-US/chrome/browser/browser.properties
+++ b/browser/locales/en-US/chrome/browser/browser.properties
@@ -23,21 +23,21 @@ bookmarkAllTabs_accesskey=T
 bookmarkCurTab_label=Bookmark This Tab...
 bookmarkCurTab_accesskey=B
 
 # bookmark dialog strings
 
 bookmarkAllTabsDefault=[Folder Name]
 
 xpinstallPromptWarning=%S prevented this site (%S) from asking you to install software on your computer.
-xpinstallPromptWarningButton=Edit Options...
+xpinstallPromptAllowButton=Allow
 # Accessibility Note:
 # Be sure you do not choose an accesskey that is used elsewhere in the active context (e.g. main menu bar, submenu of the warning popup button)
 # See http://www.mozilla.org/access/keyboard/accesskey for details
-xpinstallPromptWarningButton.accesskey=O
+xpinstallPromptAllowButton.accesskey=A
 xpinstallDisabledMessageLocked=Software installation has been disabled by your system administrator.
 xpinstallDisabledMessage=Software installation is currently disabled. Click Enable and try again.
 xpinstallDisabledButton=Enable
 xpinstallDisabledButton.accesskey=n
 popupWarning=%S prevented this site from opening a popup window.
 popupWarningMultiple=%S prevented this site from opening %S popup windows.
 popupWarningButton=Options
 popupWarningButton.accesskey=O
--- a/xpinstall/public/Makefile.in
+++ b/xpinstall/public/Makefile.in
@@ -48,16 +48,17 @@ include $(DEPTH)/config/autoconf.mk
 MODULE		= xpinstall
 GRE_MODULE	= 1
 
 XPIDLSRCS	= \
 		nsIXPIDialogService.idl \
 		nsIXPIProgressDialog.idl \
 		nsIXPINotifier.idl \
 		nsIXPInstallManager.idl \
+		nsIXPIInstallInfo.idl \
 		nsPIXPIProxy.idl \
 		nsPIXPIStubHook.idl \
 		nsPICertNotification.idl \
 		$(NULL)
 
 EXPORTS		= \
 		nsIDOMInstallTriggerGlobal.h \
 		nsIDOMInstallVersion.h \
--- a/xpinstall/public/nsIDOMInstallTriggerGlobal.h
+++ b/xpinstall/public/nsIDOMInstallTriggerGlobal.h
@@ -37,36 +37,43 @@
 
 #ifndef nsIDOMInstallTriggerGlobal_h__
 #define nsIDOMInstallTriggerGlobal_h__
 
 #include "nsISupports.h"
 #include "nsString.h"
 #include "nsIScriptContext.h"
 #include "nsXPITriggerInfo.h"
+#include "nsIXPIInstallInfo.h"
 
 
 #define NS_IDOMINSTALLTRIGGERGLOBAL_IID \
- { 0x18c2f987, 0xb09f, 0x11d2, \
-  {0xbc, 0xde, 0x00, 0x80, 0x5f, 0x0e, 0x13, 0x53}}
+ { 0xe8c7941c, 0xaaa0, 0x4faf, \
+  {0x83, 0xe8, 0x01, 0xbe, 0x8b, 0xbe, 0x8a, 0x57}}
 
 class nsIDOMInstallTriggerGlobal : public nsISupports {
 public:
   NS_DECLARE_STATIC_IID_ACCESSOR(NS_IDOMINSTALLTRIGGERGLOBAL_IID)
   enum {
     NOT_FOUND = -5,
     MAJOR_DIFF = 4,
     MINOR_DIFF = 3,
     REL_DIFF = 2,
     BLD_DIFF = 1,
     EQUAL = 0
   };
 
+  NS_IMETHOD    GetOriginatingURI(nsIScriptGlobalObject* aGlobalObject, nsIURI * *aUri)=0;
+
   NS_IMETHOD    UpdateEnabled(nsIScriptGlobalObject* aGlobalObject, PRBool aUseWhitelist, PRBool* aReturn)=0;
 
+  NS_IMETHOD    UpdateEnabled(nsIURI* aURI, PRBool aUseWhitelist, PRBool* aReturn)=0;
+
+  NS_IMETHOD    StartInstall(nsIXPIInstallInfo* aInstallInfo, PRBool* aReturn)=0;
+
   NS_IMETHOD    Install(nsIScriptGlobalObject* globalObject, nsXPITriggerInfo* aInfo, PRBool* aReturn)=0;
 
   NS_IMETHOD    InstallChrome(nsIScriptGlobalObject* globalObject, PRUint32 aType, nsXPITriggerItem* aItem, PRBool* aReturn)=0;
 
   NS_IMETHOD    StartSoftwareUpdate(nsIScriptGlobalObject* globalObject, const nsString& aURL, PRInt32 aFlags, PRBool* aReturn)=0;
 
   NS_IMETHOD    CompareVersion(const nsString& aRegName, PRInt32 aMajor, PRInt32 aMinor, PRInt32 aRelease, PRInt32 aBuild, PRInt32* aReturn)=0;
   NS_IMETHOD    CompareVersion(const nsString& aRegName, const nsString& aVersion, PRInt32* aReturn)=0;
new file mode 100644
--- /dev/null
+++ b/xpinstall/public/nsIXPIInstallInfo.idl
@@ -0,0 +1,74 @@
+/* ***** 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 XPInstall.
+ *
+ * The Initial Developer of the Original Code is
+ * Dave Townsend <dtownsend@oxymoronical.com>.
+ *
+ * Portions created by the Initial Developer are Copyright (C) 2007
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * 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 *****
+ */
+
+#include "nsISupports.idl"
+
+[ptr] native triggerInfoPtr(nsXPITriggerInfo);
+
+interface nsIDOMWindowInternal;
+interface nsIDocShell;
+interface nsIURI;
+
+/**
+ * Interface holding information about a triggered install that can be passed
+ * to and from script.
+ */
+[scriptable, uuid(5a4a775c-e452-4cf2-8ff8-d327ae24aec6)]
+interface nsIXPIInstallInfo : nsISupports
+{
+  /**
+   * The install triggers supplied by the install.
+   */
+  [noscript, notxpcom] attribute triggerInfoPtr triggerInfo;
+  
+  /**
+   * The original window that initiated the install.
+   */
+  readonly attribute nsIDOMWindowInternal originatingWindow;
+  
+  /**
+   * The original URI calling the install. This is the URI that would have been
+   * checked against the whitelist if necessary.
+   */
+  readonly attribute nsIURI originatingURI;
+  
+  /**
+   * The chome type of the install.
+   */
+  readonly attribute PRUint32 chromeType;
+};
--- a/xpinstall/public/nsIXPInstallManager.idl
+++ b/xpinstall/public/nsIXPInstallManager.idl
@@ -32,21 +32,22 @@
  * 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 ***** */
 
 #include "nsISupports.idl"
 
 interface nsIXPIProgressDialog;
+interface nsIXPIInstallInfo;
 
 /**
  * Interface to XPInstallManager - manages download and install operations.
  */
-[scriptable, uuid(566689cb-9926-4bec-a66e-a034e364ad2c)]
+[scriptable, uuid(83fdd52f-2d34-4e22-981d-cf3c4ae76faa)]
 interface nsIXPInstallManager : nsISupports
 {
     /** 
      * Initiates a download and install operation of the supplied URLs
      * and sends notifications to the supplied listener.
      * @param aURLs     array of XPI urls to download and install
      * @param aURLCount number of XPI urls in aURLs
      * @param aListener a listener to receive status notifications
@@ -65,10 +66,19 @@ interface nsIXPInstallManager : nsISuppo
      *                  Supports the types in nsICryptoHash
      * @param aURLCount number of XPI urls in aURLs and aHashes
      * @param aListener a listener to receive status notifications
      */
     void initManagerWithHashes([array, size_is(aURLCount)] in wstring aURLs,
                                [array, size_is(aURLCount)] in string aHashes,
                                in unsigned long aURLCount,
                                in nsIXPIProgressDialog aListener);
+    
+    /**
+     * Initiates a set of downloads based on an install info object. Will
+     * display confirmation dialog as if the install info had been supplied
+     * by content.
+     * @param aInstallInfo The install info object providing install triggers
+     *                     and script context for the install.
+     */
+    void initManagerWithInstallInfo(in nsIXPIInstallInfo aInstallInfo);
 };
 
--- a/xpinstall/src/Makefile.in
+++ b/xpinstall/src/Makefile.in
@@ -119,16 +119,17 @@ CPPSRCS		= \
 		ScheduledTasks.cpp \
 		nsXPIProxy.cpp \
 		nsXPITriggerInfo.cpp \
 		nsXPInstallManager.cpp \
 		nsInstallFileOpItem.cpp \
 		nsJSFileSpecObj.cpp \
 		nsInstallLogComment.cpp \
 		nsInstallBitwise.cpp \
+		nsXPIInstallInfo.cpp \
 		$(NULL)
 
 ifeq ($(OS_ARCH),WINNT)
 CPPSRCS		+= \
 		nsWinReg.cpp \
 		nsJSWinReg.cpp \
 		nsWinRegItem.cpp \
 		nsWinProfile.cpp \
--- a/xpinstall/src/nsInstallTrigger.cpp
+++ b/xpinstall/src/nsInstallTrigger.cpp
@@ -38,16 +38,17 @@
 
 #include "nsSoftwareUpdate.h"
 #include "nsXPInstallManager.h"
 #include "nsInstallTrigger.h"
 #include "nsInstallVersion.h"
 #include "nsIDOMInstallTriggerGlobal.h"
 
 #include "nscore.h"
+#include "nsAutoPtr.h"
 #include "netCore.h"
 #include "nsIFactory.h"
 #include "nsISupports.h"
 #include "nsPIDOMWindow.h"
 #include "nsIScriptGlobalObject.h"
 #include "nsIScriptGlobalObjectOwner.h"
 
 #include "nsIPrefBranch.h"
@@ -64,17 +65,17 @@
 #include "nsIComponentManager.h"
 #include "nsIServiceManager.h"
 
 #include "VerReg.h"
 
 #include "nsIContentHandler.h"
 #include "nsIChannel.h"
 #include "nsIURI.h"
-
+#include "nsXPIInstallInfo.h"
 
 
 nsInstallTrigger::nsInstallTrigger()
 {
     mScriptObject   = nsnull;
 
     // make sure all the SoftwareUpdate initialization has happened
     nsCOMPtr<nsISoftwareUpdate> svc (do_GetService(NS_IXPINSTALLCOMPONENT_CONTRACTID));
@@ -185,37 +186,29 @@ nsInstallTrigger::HandleContent(const ch
     nsCOMPtr<nsIScriptGlobalObjectOwner> globalObjectOwner = 
                                          do_QueryInterface(aWindowContext);
     nsIScriptGlobalObject* globalObject =
       globalObjectOwner ? globalObjectOwner->GetScriptGlobalObject() : nsnull;
     if ( !globalObject )
         return NS_ERROR_INVALID_ARG;
 
 
-    // We have what we need to start an XPInstall, now figure out if we are
-    // going to honor this request based on PermissionManager settings
-    PRBool enabled = PR_FALSE;
-    // Keep the host so that it can be sent to the
-    // xpinstall-install-blocked observers to display the host to be
-    // whitelisted
-    nsCAutoString host;
+    nsCOMPtr<nsIURI> checkuri;
 
     if ( useReferrer )
     {
         // easiest and most common case: base decision on the page that
         // contained the link
         //
         // NOTE: the XPI itself may be from elsewhere; the user can decide if
         // they trust the actual source when they get the install confirmation
         // dialog. The decision we're making here is whether the triggering
         // site is one which is allowed to annoy the user with modal dialogs.
-
-        enabled = AllowInstall( referringURI );
-        if (referringURI)
-            referringURI->GetHost(host);
+        
+        checkuri = referringURI;
     }
     else
     {
         // Now we're stumbing in the dark. In the most likely case the user
         // simply clicked on an FTP link (no referrer) and it's perfectly
         // sane to use the current window.
         //
         // On the other hand the user might be opening a non-http XPI link
@@ -241,41 +234,49 @@ nsInstallTrigger::HandleContent(const ch
         //
         // If a trusted site hosts an install with an exploitable flaw it
         // might be possible that a malicious site would attempt to trick
         // people into installing it, hoping to turn around and exploit it.
         // This is not entirely far-fetched (it's been done with ActiveX
         // controls) and will require community policing of the default
         // trusted sites.
 
-        enabled = AllowInstall( uri );
-        uri->GetHost(host);
+        checkuri = uri;
     }
 
-
-    if ( enabled )
-    {
-        rv = StartSoftwareUpdate( globalObject,
-                                  NS_ConvertUTF8toUTF16(urispec),
-                                  0,
-                                  &enabled);
-    }
-    else
+    nsAutoPtr<nsXPITriggerInfo> trigger(new nsXPITriggerInfo());
+    nsAutoPtr<nsXPITriggerItem> item(new nsXPITriggerItem(0, NS_ConvertUTF8toUTF16(urispec).get(),
+                                                          nsnull));
+    if (trigger && item)
     {
-        nsCOMPtr<nsPIDOMWindow> win(do_QueryInterface(globalObject));
-        nsCOMPtr<nsIObserverService> os(do_GetService("@mozilla.org/observer-service;1"));
-        if (os) {
-            os->NotifyObservers(win->GetDocShell(),
-                                "xpinstall-install-blocked",
-                                NS_ConvertUTF8toUTF16(host).get());
+        // trigger will own the item now
+        trigger->Add(item.forget());
+        nsCOMPtr<nsIDOMWindowInternal> win(do_QueryInterface(globalObject));
+        nsCOMPtr<nsIXPIInstallInfo> installInfo =
+                              new nsXPIInstallInfo(win, checkuri, trigger, 0);
+        if (installInfo)
+        {
+            // From here trigger is owned by installInfo until passed on to nsXPInstallManager
+            trigger.forget();
+            if (AllowInstall(checkuri))
+            {
+                return StartInstall(installInfo, nsnull);
+            }
+            else
+            {
+                nsCOMPtr<nsIObserverService> os(do_GetService("@mozilla.org/observer-service;1"));
+                if (os)
+                    os->NotifyObservers(installInfo,
+                                        "xpinstall-install-blocked",
+                                        nsnull);
+                return NS_ERROR_ABORT;
+            }
         }
-        rv = NS_ERROR_ABORT;
     }
-    
-    return rv;
+    return NS_ERROR_OUT_OF_MEMORY;
 }
 
 
 // updateWhitelist
 //
 // Helper function called by nsInstallTrigger::AllowInstall().
 // Interprets the pref as a comma-delimited list of hosts and adds each one
 // to the permission manager using the given action. Clear pref when done.
@@ -380,62 +381,99 @@ nsInstallTrigger::AllowInstall(nsIURI* a
         }
     }
 
     return xpiEnabled;
 }
 
 
 NS_IMETHODIMP
+nsInstallTrigger::GetOriginatingURI(nsIScriptGlobalObject* aGlobalObject, nsIURI * *aUri)
+{
+    NS_ENSURE_ARG_POINTER(aGlobalObject);
+
+    *aUri = nsnull;
+    
+    // find the current site
+    nsCOMPtr<nsIDOMDocument> domdoc;
+    nsCOMPtr<nsIDOMWindow> window(do_QueryInterface(aGlobalObject));
+    if ( window )
+    {
+        window->GetDocument(getter_AddRefs(domdoc));
+        nsCOMPtr<nsIDocument> doc(do_QueryInterface(domdoc));
+        if ( doc )
+            NS_ADDREF(*aUri = doc->GetDocumentURI());
+    }
+    return NS_OK;
+}
+
+NS_IMETHODIMP
 nsInstallTrigger::UpdateEnabled(nsIScriptGlobalObject* aGlobalObject, PRBool aUseWhitelist, PRBool* aReturn)
 {
+    nsCOMPtr<nsIURI> uri;
+    nsresult rv = GetOriginatingURI(aGlobalObject, getter_AddRefs(uri));
+    NS_ENSURE_SUCCESS(rv, rv);
+    return UpdateEnabled(uri, aUseWhitelist, aReturn);
+}
+
+NS_IMETHODIMP
+nsInstallTrigger::UpdateEnabled(nsIURI* aURI, PRBool aUseWhitelist, PRBool* aReturn)
+{
     // disallow unless we successfully find otherwise
     *aReturn = PR_FALSE;
 
     if (!aUseWhitelist)
     {
         // simple global pref check
         nsCOMPtr<nsIPrefBranch> prefBranch(do_GetService(NS_PREFSERVICE_CONTRACTID));
         if (prefBranch)
             prefBranch->GetBoolPref( XPINSTALL_ENABLE_PREF, aReturn);
     }
-    else
+    else if (aURI)
     {
-        NS_ENSURE_ARG_POINTER(aGlobalObject);
-
-        // find the current site
-        nsCOMPtr<nsIDOMDocument> domdoc;
-        nsCOMPtr<nsIDOMWindow> window(do_QueryInterface(aGlobalObject));
-        if ( window )
-        {
-            window->GetDocument(getter_AddRefs(domdoc));
-            nsCOMPtr<nsIDocument> doc(do_QueryInterface(domdoc));
-            if ( doc )
-            {
-                *aReturn = AllowInstall( doc->GetDocumentURI() );
-            }
-        }
+        *aReturn = AllowInstall(aURI);
     }
 
     return NS_OK;
 }
 
 
 NS_IMETHODIMP
+nsInstallTrigger::StartInstall(nsIXPIInstallInfo* aInstallInfo, PRBool* aReturn)
+{
+    if (aReturn)
+        *aReturn = PR_FALSE;
+    
+    nsXPInstallManager *mgr = new nsXPInstallManager();
+    if (mgr)
+    {
+        nsresult rv = mgr->InitManagerWithInstallInfo(aInstallInfo);
+        if (NS_SUCCEEDED(rv) && aReturn)
+            *aReturn = PR_TRUE;
+        return rv;
+    }
+    else
+    {
+        return NS_ERROR_OUT_OF_MEMORY;
+    }
+}
+
+NS_IMETHODIMP
 nsInstallTrigger::Install(nsIScriptGlobalObject* aGlobalObject, nsXPITriggerInfo* aTrigger, PRBool* aReturn)
 {
     NS_ASSERTION(aReturn, "Invalid pointer arg");
     *aReturn = PR_FALSE;
 
     nsresult rv;
     nsXPInstallManager *mgr = new nsXPInstallManager();
     if (mgr)
     {
+        nsCOMPtr<nsIDOMWindowInternal> win(do_QueryInterface(aGlobalObject));
         // The Install manager will delete itself when done
-        rv = mgr->InitManager( aGlobalObject, aTrigger, 0 );
+        rv = mgr->InitManager( win, aTrigger, 0 );
         if (NS_SUCCEEDED(rv))
             *aReturn = PR_TRUE;
     }
     else
     {
         delete aTrigger;
         rv = NS_ERROR_OUT_OF_MEMORY;
     }
@@ -459,26 +497,32 @@ nsInstallTrigger::InstallChrome(nsIScrip
     nsXPInstallManager *mgr = new nsXPInstallManager();
     if (mgr)
     {
         nsXPITriggerInfo* trigger = new nsXPITriggerInfo();
         if ( trigger )
         {
             trigger->Add( aItem );
 
+            nsCOMPtr<nsIDOMWindowInternal> win(do_QueryInterface(aGlobalObject));
             // The Install manager will delete itself when done
-            rv = mgr->InitManager( aGlobalObject, trigger, aType );
+            rv = mgr->InitManager( win, trigger, aType );
             *aReturn = PR_TRUE;
         }
         else
         {
             rv = NS_ERROR_OUT_OF_MEMORY;
             delete mgr;
+            delete aItem;
         }
     }
+    else
+    {
+        delete aItem;
+    }
 
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsInstallTrigger::StartSoftwareUpdate(nsIScriptGlobalObject* aGlobalObject, const nsString& aURL, PRInt32 aFlags, PRBool* aReturn)
 {
     nsresult rv = NS_ERROR_OUT_OF_MEMORY;
@@ -491,18 +535,19 @@ nsInstallTrigger::StartSoftwareUpdate(ns
     {
         nsXPITriggerInfo* trigger = new nsXPITriggerInfo();
         if ( trigger )
         {
             nsXPITriggerItem* item = new nsXPITriggerItem(0,aURL.get(),nsnull);
             if (item)
             {
                 trigger->Add( item );
+                nsCOMPtr<nsIDOMWindowInternal> win(do_QueryInterface(aGlobalObject));
                 // The Install manager will delete itself when done
-                rv = mgr->InitManager(aGlobalObject, trigger, 0 );
+                rv = mgr->InitManager(win, trigger, 0 );
                 *aReturn = PR_TRUE;
             }
             else
             {
                 rv = NS_ERROR_OUT_OF_MEMORY;
                 delete trigger;
                 delete mgr;
             }
--- a/xpinstall/src/nsInstallTrigger.h
+++ b/xpinstall/src/nsInstallTrigger.h
@@ -42,17 +42,20 @@ class nsInstallTrigger: public nsIScript
         virtual ~nsInstallTrigger();
 
         NS_DECL_ISUPPORTS
         NS_DECL_NSICONTENTHANDLER
 
         NS_IMETHOD    GetScriptObject(nsIScriptContext *aContext, void** aScriptObject);
         NS_IMETHOD    SetScriptObject(void* aScriptObject);
 
+        NS_IMETHOD    GetOriginatingURI(nsIScriptGlobalObject* aGlobalObject, nsIURI * *aUri);
         NS_IMETHOD    UpdateEnabled(nsIScriptGlobalObject* aGlobalObject, PRBool aUseWhitelist, PRBool* aReturn);
+        NS_IMETHOD    UpdateEnabled(nsIURI* aURI, PRBool aUseWhitelist, PRBool* aReturn);
+        NS_IMETHOD    StartInstall(nsIXPIInstallInfo* aInstallInfo, PRBool* aReturn);
         NS_IMETHOD    Install(nsIScriptGlobalObject* aGlobalObject, nsXPITriggerInfo *aInfo, PRBool* aReturn);
         NS_IMETHOD    InstallChrome(nsIScriptGlobalObject* aGlobalObject, PRUint32 aType, nsXPITriggerItem* aItem, PRBool* aReturn);
         NS_IMETHOD    StartSoftwareUpdate(nsIScriptGlobalObject* aGlobalObject, const nsString& aURL, PRInt32 aFlags, PRInt32* aReturn);
         NS_IMETHOD    CompareVersion(const nsString& aRegName, PRInt32 aMajor, PRInt32 aMinor, PRInt32 aRelease, PRInt32 aBuild, PRInt32* aReturn);
         NS_IMETHOD    CompareVersion(const nsString& aRegName, const nsString& aVersion, PRInt32* aReturn);
         NS_IMETHOD    CompareVersion(const nsString& aRegName, nsIDOMInstallVersion* aVersion, PRInt32* aReturn);
         NS_IMETHOD    GetVersion(const nsString& component, nsString& version);
 
--- a/xpinstall/src/nsJSInstallTriggerGlobal.cpp
+++ b/xpinstall/src/nsJSInstallTriggerGlobal.cpp
@@ -32,31 +32,33 @@
  * 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 ***** */
 
 #include "jsapi.h"
 #include "nscore.h"
+#include "nsAutoPtr.h"
 #include "nsIScriptContext.h"
 #include "nsIScriptObjectOwner.h"
 #include "nsIScriptGlobalObject.h"
 #include "nsCRT.h"
 #include "nsString.h"
 #include "nsIDOMInstallVersion.h"
 #include "nsIDOMInstallTriggerGlobal.h"
 #include "nsPIDOMWindow.h"
 #include "nsIDOMDocument.h"
 #include "nsIDocument.h"
 #include "nsIDocShell.h"
 #include "nsIObserverService.h"
 #include "nsInstallTrigger.h"
 #include "nsXPITriggerInfo.h"
 #include "nsDOMJSUtils.h"
+#include "nsXPIInstallInfo.h"
 
 #include "nsIComponentManager.h"
 #include "nsNetUtil.h"
 #include "nsIScriptSecurityManager.h"
 
 #include "nsSoftwareUpdateIIDs.h"
 
 extern void ConvertJSValToStr(nsString&  aString,
@@ -233,31 +235,19 @@ InstallTriggerGlobalInstall(JSContext *c
   *rval = JSVAL_FALSE;
 
   // make sure XPInstall is enabled, return false if not
   nsIScriptGlobalObject *globalObject = nsnull;
   nsIScriptContext *scriptContext = GetScriptContextFromJSContext(cx);
   if (scriptContext)
     globalObject = scriptContext->GetGlobalObject();
 
-  PRBool enabled = PR_FALSE;
-  nativeThis->UpdateEnabled(globalObject, XPI_WHITELIST, &enabled);
-  if (!enabled || !globalObject)
-  {
-    nsCOMPtr<nsPIDOMWindow> win(do_QueryInterface(globalObject));
-    nsCOMPtr<nsIObserverService> os(do_GetService("@mozilla.org/observer-service;1"));
-    if (os)
-    {
-      os->NotifyObservers(win->GetDocShell(), "xpinstall-install-blocked", 
-                          NS_LITERAL_STRING("install").get());
-    }
-    return JS_TRUE;
-  }
-
-
+  if (!globalObject)
+      return JS_TRUE;
+  
   nsCOMPtr<nsIScriptSecurityManager> secman(do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID));
   if (!secman)
   {
     JS_ReportError(cx, "Could not the script security manager service.");
     return JS_FALSE;
   }
   // get the principal.  if it doesn't exist, die.
   nsCOMPtr<nsIPrincipal> principal;
@@ -389,20 +379,46 @@ InstallTriggerGlobalInstall(JSContext *c
     {
         trigger->SaveCallback( cx, argv[1] );
     }
 
 
     // pass on only if good stuff found
     if (!abortLoad && trigger->Size() > 0)
     {
-        PRBool result;
-        nativeThis->Install(globalObject, trigger, &result);
-        *rval = BOOLEAN_TO_JSVAL(result);
-        return JS_TRUE;
+        nsCOMPtr<nsIURI> checkuri;
+        nsresult rv = nativeThis->GetOriginatingURI(globalObject,
+                                                    getter_AddRefs(checkuri));
+        if (NS_SUCCEEDED(rv))
+        {
+            nsCOMPtr<nsIDOMWindowInternal> win(do_QueryInterface(globalObject));
+            nsCOMPtr<nsIXPIInstallInfo> installInfo =
+                new nsXPIInstallInfo(win, checkuri, trigger, 0);
+            if (installInfo)
+            {
+                // installInfo now owns triggers
+                PRBool enabled = PR_FALSE;
+                nativeThis->UpdateEnabled(checkuri, XPI_WHITELIST, &enabled);
+                if (!enabled)
+                {
+                    nsCOMPtr<nsIObserverService> os(do_GetService("@mozilla.org/observer-service;1"));
+                    if (os)
+                        os->NotifyObservers(installInfo,
+                                            "xpinstall-install-blocked", 
+                                            nsnull);
+                }
+                else
+                {
+                    PRBool result;
+                    nativeThis->StartInstall(installInfo, &result);
+                    *rval = BOOLEAN_TO_JSVAL(result);
+                }
+                return JS_TRUE;
+            }
+        }
     }
     // didn't pass it on so we must delete trigger
     delete trigger;
   }
 
   JS_ReportError(cx, "Incorrect arguments to InstallTrigger.Install()");
   return JS_FALSE;
 }
@@ -429,31 +445,19 @@ InstallTriggerGlobalInstallChrome(JSCont
       JS_ValueToECMAUint32(cx, argv[0], &chromeType);
 
   // make sure XPInstall is enabled, return if not
   nsIScriptGlobalObject *globalObject = nsnull;
   nsIScriptContext *scriptContext = GetScriptContextFromJSContext(cx);
   if (scriptContext)
       globalObject = scriptContext->GetGlobalObject();
 
-  PRBool enabled = PR_FALSE;
-  nativeThis->UpdateEnabled(globalObject, XPI_WHITELIST, &enabled);
-  if (!enabled || !globalObject)
-  {
-    nsCOMPtr<nsPIDOMWindow> win(do_QueryInterface(globalObject));
-    nsCOMPtr<nsIObserverService> os(do_GetService("@mozilla.org/observer-service;1"));
-    if (os)
-    {
-      os->NotifyObservers(win->GetDocShell(), "xpinstall-install-blocked", 
-                          NS_LITERAL_STRING("install").get());
-    }
-    return JS_TRUE;
-  }
-
-
+  if (!globalObject)
+      return JS_TRUE;
+  
   // get window.location to construct relative URLs
   nsCOMPtr<nsIURI> baseURL;
   JSObject* global = JS_GetGlobalObject(cx);
   if (global)
   {
     jsval v;
     if (JS_GetProperty(cx,global,"location",&v))
     {
@@ -479,23 +483,56 @@ InstallTriggerGlobalInstallChrome(JSCont
     // Make sure caller is allowed to load this url.
     nsresult rv = InstallTriggerCheckLoadURIFromScript(cx, sourceURL);
     if (NS_FAILED(rv))
         return JS_FALSE;
 
     if ( chromeType & CHROME_ALL )
     {
         // there's at least one known chrome type
-        nsXPITriggerItem* item = new nsXPITriggerItem(name.get(),
-                                                      sourceURL.get(), 
-                                                      nsnull);
-
-        PRBool nativeRet = PR_FALSE;
-        nativeThis->InstallChrome(globalObject, chromeType, item, &nativeRet);
-        *rval = BOOLEAN_TO_JSVAL(nativeRet);
+        nsCOMPtr<nsIURI> checkuri;
+        nsresult rv = nativeThis->GetOriginatingURI(globalObject,
+                                                    getter_AddRefs(checkuri));
+        if (NS_SUCCEEDED(rv))
+        {
+            nsAutoPtr<nsXPITriggerInfo> trigger(new nsXPITriggerInfo());
+            nsAutoPtr<nsXPITriggerItem> item(new nsXPITriggerItem(name.get(),
+                                                                  sourceURL.get(),
+                                                                  nsnull));
+            if (trigger && item)
+            {
+                // trigger will free item when complete
+                trigger->Add(item.forget());
+                nsCOMPtr<nsIDOMWindowInternal> win(do_QueryInterface(globalObject));
+                nsCOMPtr<nsIXPIInstallInfo> installInfo =
+                    new nsXPIInstallInfo(win, checkuri, trigger, chromeType);
+                if (installInfo)
+                {
+                    // installInfo owns trigger now
+                    trigger.forget();
+                    PRBool enabled = PR_FALSE;
+                    nativeThis->UpdateEnabled(checkuri, XPI_WHITELIST,
+                                              &enabled);
+                    if (!enabled)
+                    {
+                        nsCOMPtr<nsIObserverService> os(do_GetService("@mozilla.org/observer-service;1"));
+                        if (os)
+                            os->NotifyObservers(installInfo,
+                                                "xpinstall-install-blocked", 
+                                                nsnull);
+                    }
+                    else
+                    {
+                        PRBool nativeRet = PR_FALSE;
+                        nativeThis->StartInstall(installInfo, &nativeRet);
+                        *rval = BOOLEAN_TO_JSVAL(nativeRet);
+                    }
+                }
+            }
+        }
     }
   }
   return JS_TRUE;
 }
 
 
 //
 // Native method StartSoftwareUpdate
@@ -507,36 +544,24 @@ InstallTriggerGlobalStartSoftwareUpdate(
   if (!nativeThis)
     return JS_FALSE;
 
   PRBool       nativeRet;
   PRInt32      flags = 0;
 
   *rval = JSVAL_FALSE;
 
-  // make sure XPInstall is enabled, return if not
   nsIScriptGlobalObject *globalObject = nsnull;
   nsIScriptContext *scriptContext = GetScriptContextFromJSContext(cx);
   if (scriptContext)
       globalObject = scriptContext->GetGlobalObject();
 
-  PRBool enabled = PR_FALSE;
-  nativeThis->UpdateEnabled(globalObject, XPI_WHITELIST, &enabled);
-  if (!enabled || !globalObject)
-  {
-    nsCOMPtr<nsPIDOMWindow> win(do_QueryInterface(globalObject));
-    nsCOMPtr<nsIObserverService> os(do_GetService("@mozilla.org/observer-service;1"));
-    if (os)
-    {
-      os->NotifyObservers(win->GetDocShell(), "xpinstall-install-blocked", 
-                          NS_LITERAL_STRING("install").get());
-    }
-    return JS_TRUE;
-  }
-
+  if (!globalObject)
+      return JS_TRUE;
+  
   // get window.location to construct relative URLs
   nsCOMPtr<nsIURI> baseURL;
   JSObject* global = JS_GetGlobalObject(cx);
   if (global)
   {
     jsval v;
     if (JS_GetProperty(cx,global,"location",&v))
     {
@@ -564,19 +589,52 @@ InstallTriggerGlobalStartSoftwareUpdate(
         return JS_FALSE;
 
     if (argc >= 2 && !JS_ValueToInt32(cx, argv[1], (int32 *)&flags))
     {
         JS_ReportError(cx, "StartSoftwareUpdate() 2nd parameter must be a number");
         return JS_FALSE;
     }
 
-    if(NS_OK == nativeThis->StartSoftwareUpdate(globalObject, xpiURL, flags, &nativeRet))
+    nsCOMPtr<nsIURI> checkuri;
+    rv = nativeThis->GetOriginatingURI(globalObject, getter_AddRefs(checkuri));
+    if (NS_SUCCEEDED(rv))
     {
-        *rval = BOOLEAN_TO_JSVAL(nativeRet);
+        nsAutoPtr<nsXPITriggerInfo> trigger(new nsXPITriggerInfo());
+        nsAutoPtr<nsXPITriggerItem> item(new nsXPITriggerItem(0,
+                                                              xpiURL.get(),
+                                                              nsnull));
+        if (trigger && item)
+        {
+            // trigger will free item when complete
+            trigger->Add(item.forget());
+            nsCOMPtr<nsIDOMWindowInternal> win(do_QueryInterface(globalObject));
+            nsCOMPtr<nsIXPIInstallInfo> installInfo =
+                                new nsXPIInstallInfo(win, checkuri, trigger, 0);
+            if (installInfo)
+            {
+                // From here trigger is owned by installInfo until passed on to nsXPInstallManager
+                trigger.forget();
+                PRBool enabled = PR_FALSE;
+                nativeThis->UpdateEnabled(checkuri, XPI_WHITELIST, &enabled);
+                if (!enabled)
+                {
+                    nsCOMPtr<nsIObserverService> os(do_GetService("@mozilla.org/observer-service;1"));
+                    if (os)
+                        os->NotifyObservers(installInfo,
+                                            "xpinstall-install-blocked",
+                                            nsnull);
+                }
+                else
+                {
+                    nativeThis->StartInstall(installInfo, &nativeRet);
+                    *rval = BOOLEAN_TO_JSVAL(nativeRet);
+                }
+            }
+        }
     }
   }
   else
   {
     JS_ReportError(cx, "Function StartSoftwareUpdate requires 2 parameters");
     return JS_FALSE;
   }
 
new file mode 100644
--- /dev/null
+++ b/xpinstall/src/nsXPIInstallInfo.cpp
@@ -0,0 +1,94 @@
+/* ***** 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 XPInstall.
+ *
+ * The Initial Developer of the Original Code is
+ * Dave Townsend <dtownsend@oxymoronical.com>.
+ *
+ * Portions created by the Initial Developer are Copyright (C) 2007
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * 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 *****
+ */
+
+#include "nsXPIInstallInfo.h"
+
+NS_IMPL_ISUPPORTS1(nsXPIInstallInfo, nsIXPIInstallInfo)
+
+nsXPIInstallInfo::nsXPIInstallInfo(nsIDOMWindowInternal *aOriginatingWindow,
+                                   nsIURI *aOriginatingURI,
+                                   nsXPITriggerInfo *aTriggerInfo,
+                                   PRUint32 aChromeType)
+  : mOriginatingWindow(aOriginatingWindow), mOriginatingURI(aOriginatingURI),
+    mTriggerInfo(aTriggerInfo), mChromeType(aChromeType)
+{
+}
+
+nsXPIInstallInfo::~nsXPIInstallInfo()
+{
+    delete mTriggerInfo;
+}
+
+/* [noscript, notxpcom] attribute triggerInfoPtr triggerInfo; */
+NS_IMETHODIMP
+nsXPIInstallInfo::GetTriggerInfo(nsXPITriggerInfo * *aTriggerInfo)
+{
+    *aTriggerInfo = mTriggerInfo;
+    return NS_OK;
+}
+
+NS_IMETHODIMP
+nsXPIInstallInfo::SetTriggerInfo(nsXPITriggerInfo * aTriggerInfo)
+{
+    mTriggerInfo = aTriggerInfo;
+    return NS_OK;
+}
+
+/* readonly attribute nsIDOMWindowInternal originatingWindow; */
+NS_IMETHODIMP
+nsXPIInstallInfo::GetOriginatingWindow(nsIDOMWindowInternal * *aOriginatingWindow)
+{
+    NS_IF_ADDREF(*aOriginatingWindow = mOriginatingWindow);
+    return NS_OK;
+}
+
+/* readonly attribute nsIURI uri; */
+NS_IMETHODIMP
+nsXPIInstallInfo::GetOriginatingURI(nsIURI * *aOriginatingURI)
+{
+    NS_IF_ADDREF(*aOriginatingURI = mOriginatingURI);
+    return NS_OK;
+}
+
+/* readonly attribute PRUint32 type; */
+NS_IMETHODIMP
+nsXPIInstallInfo::GetChromeType(PRUint32 *aChromeType)
+{
+    *aChromeType = mChromeType;
+    return NS_OK;
+}
new file mode 100644
--- /dev/null
+++ b/xpinstall/src/nsXPIInstallInfo.h
@@ -0,0 +1,62 @@
+/* ***** 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 XPInstall.
+ *
+ * The Initial Developer of the Original Code is
+ * Dave Townsend <dtownsend@oxymoronical.com>.
+ *
+ * Portions created by the Initial Developer are Copyright (C) 2007
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * 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 *****
+ */
+
+#include "nsXPITriggerInfo.h"
+#include "nsIXPIInstallInfo.h"
+#include "nsIDOMWindowInternal.h"
+#include "nsIDocShell.h"
+#include "nsIURI.h"
+
+class nsXPIInstallInfo : public nsIXPIInstallInfo
+{
+public:
+  NS_DECL_ISUPPORTS
+  NS_DECL_NSIXPIINSTALLINFO
+
+  nsXPIInstallInfo(nsIDOMWindowInternal *aOriginatingWindow,
+                   nsIURI *aOriginatingURI, nsXPITriggerInfo *aTriggerInfo,
+                   PRUint32 aChromeType);
+
+private:
+  ~nsXPIInstallInfo();
+  
+  nsXPITriggerInfo* mTriggerInfo;
+  nsCOMPtr<nsIDOMWindowInternal> mOriginatingWindow;
+  nsCOMPtr<nsIURI> mOriginatingURI;
+  PRUint32 mChromeType;
+};
--- a/xpinstall/src/nsXPInstallManager.cpp
+++ b/xpinstall/src/nsXPInstallManager.cpp
@@ -207,34 +207,59 @@ nsXPInstallManager::InitManagerWithHashe
     mFromChrome = PR_TRUE;
     
     rv = Observe(aListener, XPI_PROGRESS_TOPIC, NS_LITERAL_STRING("open").get());
     if (NS_FAILED(rv))
         Shutdown();
     return rv;
 }
 
+NS_IMETHODIMP
+nsXPInstallManager::InitManagerWithInstallInfo(nsIXPIInstallInfo* aInstallInfo)
+{
+    nsXPITriggerInfo* triggers;
+    nsresult rv = aInstallInfo->GetTriggerInfo(&triggers);
+    NS_ENSURE_SUCCESS(rv, rv);
+
+    nsCOMPtr<nsIDOMWindowInternal> win;
+    rv = aInstallInfo->GetOriginatingWindow(getter_AddRefs(win));
+    if (NS_SUCCEEDED(rv))
+    {
+        PRUint32 type;
+        rv = aInstallInfo->GetChromeType(&type);
+        if (NS_SUCCEEDED(rv))
+        {
+            // Passing ownership onto InitManager which will free when necessary
+            aInstallInfo->SetTriggerInfo(nsnull);
+            return InitManager(win, triggers, type);
+        }
+    }
+
+    NS_RELEASE_THIS();
+    return rv;
+}
 
 NS_IMETHODIMP
-nsXPInstallManager::InitManager(nsIScriptGlobalObject* aGlobalObject, nsXPITriggerInfo* aTriggers, PRUint32 aChromeType)
+nsXPInstallManager::InitManager(nsIDOMWindowInternal* aParentWindow, nsXPITriggerInfo* aTriggers, PRUint32 aChromeType)
 {
     if ( !aTriggers || aTriggers->Size() == 0 )
     {
         NS_WARNING("XPInstallManager called with no trigger info!");
+        delete aTriggers;
         NS_RELEASE_THIS();
         return NS_ERROR_INVALID_POINTER;
     }
 
     nsresult rv = NS_OK;
 
     mTriggers = aTriggers;
     mChromeType = aChromeType;
     mNeedsShutdown = PR_TRUE;
 
-    mParentWindow = do_QueryInterface(aGlobalObject);
+    mParentWindow = aParentWindow;
 
     // Start downloading initial chunks looking for signatures,
     mOutstandingCertLoads = mTriggers->Size();
 
     nsXPITriggerItem *item = mTriggers->Get(--mOutstandingCertLoads);
 
     nsCOMPtr<nsIURI> uri;
     NS_NewURI(getter_AddRefs(uri), NS_ConvertUTF16toUTF8(item->mURL));
--- a/xpinstall/src/nsXPInstallManager.h
+++ b/xpinstall/src/nsXPInstallManager.h
@@ -53,16 +53,17 @@
 #include "nsIXPIDialogService.h"
 #include "nsXPITriggerInfo.h"
 #include "nsIXPIProgressDialog.h"
 #include "nsIChromeRegistry.h"
 #include "nsIDOMWindowInternal.h"
 #include "nsIObserver.h"
 #include "nsIBadCertListener.h"
 #include "nsIChannelEventSink.h"
+#include "nsIXPIInstallInfo.h"
 
 #include "nsISoftwareUpdate.h"
 
 #include "nsCOMPtr.h"
 
 #include "nsIProgressEventSink.h"
 #include "nsIInterfaceRequestor.h"
 #include "nsIInterfaceRequestorUtils.h"
@@ -101,17 +102,17 @@ class nsXPInstallManager : public nsIXPI
         NS_DECL_NSISTREAMLISTENER
         NS_DECL_NSIPROGRESSEVENTSINK
         NS_DECL_NSIREQUESTOBSERVER
         NS_DECL_NSIINTERFACEREQUESTOR
         NS_DECL_NSPICERTNOTIFICATION
         NS_DECL_NSIBADCERTLISTENER
         NS_DECL_NSICHANNELEVENTSINK
 
-        NS_IMETHOD InitManager(nsIScriptGlobalObject* aGlobalObject, nsXPITriggerInfo* aTrigger, PRUint32 aChromeType );
+        NS_IMETHOD InitManager(nsIDOMWindowInternal* aParentWindow, nsXPITriggerInfo* aTrigger, PRUint32 aChromeType );
 
     private:
         nsresult    InitManagerInternal();
         NS_IMETHOD  DownloadNext();
         void        Shutdown();
         NS_IMETHOD  GetDestinationFile(nsString& url, nsILocalFile* *file);
         NS_IMETHOD  LoadParams(PRUint32 aCount, const PRUnichar** aPackageList, nsIDialogParamBlock** aParams);
 #ifdef ENABLE_SKIN_SIMPLE_INSTALLATION_UI