Bug 715347 - Add basic Download Manager support [r=mbrubeck]
authorMark Finkle <mfinkle@mozilla.com>
Fri, 06 Jan 2012 09:34:34 -0500
changeset 85163 8522883040c0afc619cd05161d9b36c439136cb2
parent 85162 6b1628d598550d6a8d38f922f6fefeeef7a13eba
child 85164 347c13fd3e43e9a5d84f3703fe735e8335410a46
push id805
push userakeybl@mozilla.com
push dateWed, 01 Feb 2012 18:17:35 +0000
treeherdermozilla-aurora@6fb3bf232436 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmbrubeck
bugs715347
milestone12.0a1
Bug 715347 - Add basic Download Manager support [r=mbrubeck]
mobile/android/base/GeckoApp.java
mobile/android/base/locales/en-US/android_strings.dtd
mobile/android/base/resources/layout/gecko_menu.xml
mobile/android/base/strings.xml.in
mobile/android/chrome/content/downloads.js
--- a/mobile/android/base/GeckoApp.java
+++ b/mobile/android/base/GeckoApp.java
@@ -432,16 +432,17 @@ abstract public class GeckoApp
             aMenu.findItem(R.id.settings).setEnabled(false);
 
         Tab tab = Tabs.getInstance().getSelectedTab();
         MenuItem bookmark = aMenu.findItem(R.id.bookmark);
         MenuItem forward = aMenu.findItem(R.id.forward);
         MenuItem share = aMenu.findItem(R.id.share);
         MenuItem agentMode = aMenu.findItem(R.id.agent_mode);
         MenuItem saveAsPDF = aMenu.findItem(R.id.save_as_pdf);
+        MenuItem downloads = aMenu.findItem(R.id.downloads);
 
         if (tab == null) {
             bookmark.setEnabled(false);
             forward.setEnabled(false);
             share.setEnabled(false);
             saveAsPDF.setEnabled(false);
             agentMode.setEnabled(false);
             return true;
@@ -468,16 +469,20 @@ abstract public class GeckoApp
                             scheme.equals("file"));
         share.setEnabled(enabled);
         agentMode.setEnabled(enabled);
 
         // Disable save as PDF for about:home and xul pages
         saveAsPDF.setEnabled(!(tab.getURL().equals("about:home") ||
                                tab.getContentType().equals("application/vnd.mozilla.xul+xml")));
 
+        // DownloadManager support is tied to level 12 and higher
+        if (Build.VERSION.SDK_INT < 12)
+            downloads.setVisible(false);
+
         return true;
     }
 
     @Override
     public boolean onOptionsItemSelected(MenuItem item) {
         Tab tab = null;
         Intent intent = null;
         switch (item.getItemId()) {
@@ -528,16 +533,20 @@ abstract public class GeckoApp
                 startActivity(intent);
                 return true;
             case R.id.site_settings:
                 GeckoAppShell.sendEventToGecko(new GeckoEvent("Permissions:Get", null));
                 return true;
             case R.id.addons:
                 loadUrlInTab("about:addons");
                 return true;
+            case R.id.downloads:
+                intent = new Intent(DownloadManager.ACTION_VIEW_DOWNLOADS);
+                startActivity(intent);
+                return true;
             case R.id.agent_mode:
                 Tab selectedTab = Tabs.getInstance().getSelectedTab();
                 if (selectedTab == null)
                     return true;
                 JSONObject args = new JSONObject();
                 try {
                     args.put("agent", selectedTab.getAgentMode() == Tab.AgentMode.MOBILE ? "desktop" : "mobile");
                     args.put("tabId", selectedTab.getId());
@@ -970,16 +979,23 @@ abstract public class GeckoApp
 
                 tab.setAgentMode(agentMode);
                 if (tab == Tabs.getInstance().getSelectedTab())
                     updateAgentModeMenuItem(tab, agentMode);
             } else if (event.equals("Permissions:Data")) {
                 String host = message.getString("host");
                 JSONArray permissions = message.getJSONArray("permissions");
                 showSiteSettingsDialog(host, permissions);
+            } else if (event.equals("Downloads:Done")) {
+                String displayName = message.getString("displayName");
+                String path = message.getString("path");
+                String mimeType = message.getString("mimeType");
+                int size = message.getInt("size");
+
+                handleDownloadDone(displayName, path, mimeType, size);
             }
         } catch (Exception e) {
             Log.e(LOGTAG, "Exception handling message \"" + event + "\":", e);
         }
     }
 
     public void showAboutHome() {
         Runnable r = new AboutHomeRunnable(true);
@@ -1297,16 +1313,27 @@ abstract public class GeckoApp
     }
 
     void handleWindowClose(final int tabId) {
         Tabs tabs = Tabs.getInstance();
         Tab tab = tabs.getTab(tabId);
         tabs.closeTab(tab);
     }
 
+    void handleDownloadDone(String displayName, String path, String mimeType, int size) {
+        // DownloadManager.addCompletedDownload is supported in level 12 and higher
+        if (Build.VERSION.SDK_INT >= 12) {
+            DownloadManager dm = (DownloadManager) mAppContext.getSystemService(Context.DOWNLOAD_SERVICE);
+            dm.addCompletedDownload(displayName, displayName,
+                false /* do not use media scanner */,
+                mimeType, path, size,
+                false /* no notification */);
+        }
+    }
+
     void addPluginView(final View view,
                        final double x, final double y,
                        final double w, final double h) {
         mMainHandler.post(new Runnable() { 
             public void run() {
                 PluginLayoutParams lp;
 
                 ViewportMetrics geckoViewport = mSoftwareLayerClient.getGeckoViewportMetrics();
@@ -1554,16 +1581,17 @@ abstract public class GeckoApp
         GeckoAppShell.registerGeckoEventListener("Menu:Remove", GeckoApp.mAppContext);
         GeckoAppShell.registerGeckoEventListener("Gecko:Ready", GeckoApp.mAppContext);
         GeckoAppShell.registerGeckoEventListener("Toast:Show", GeckoApp.mAppContext);
         GeckoAppShell.registerGeckoEventListener("ToggleChrome:Hide", GeckoApp.mAppContext);
         GeckoAppShell.registerGeckoEventListener("ToggleChrome:Show", GeckoApp.mAppContext);
         GeckoAppShell.registerGeckoEventListener("AgentMode:Changed", GeckoApp.mAppContext);
         GeckoAppShell.registerGeckoEventListener("FormAssist:AutoComplete", GeckoApp.mAppContext);
         GeckoAppShell.registerGeckoEventListener("Permissions:Data", GeckoApp.mAppContext);
+        GeckoAppShell.registerGeckoEventListener("Downloads:Done", GeckoApp.mAppContext);
 
         mConnectivityFilter = new IntentFilter();
         mConnectivityFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
         mConnectivityReceiver = new GeckoConnectivityReceiver();
 
         IntentFilter batteryFilter = new IntentFilter();
         batteryFilter.addAction(Intent.ACTION_BATTERY_CHANGED);
         mBatteryReceiver = new GeckoBatteryManager();
@@ -1789,16 +1817,17 @@ abstract public class GeckoApp
         GeckoAppShell.unregisterGeckoEventListener("Menu:Remove", GeckoApp.mAppContext);
         GeckoAppShell.unregisterGeckoEventListener("Gecko:Ready", GeckoApp.mAppContext);
         GeckoAppShell.unregisterGeckoEventListener("Toast:Show", GeckoApp.mAppContext);
         GeckoAppShell.unregisterGeckoEventListener("ToggleChrome:Hide", GeckoApp.mAppContext);
         GeckoAppShell.unregisterGeckoEventListener("ToggleChrome:Show", GeckoApp.mAppContext);
         GeckoAppShell.unregisterGeckoEventListener("AgentMode:Changed", GeckoApp.mAppContext);
         GeckoAppShell.unregisterGeckoEventListener("FormAssist:AutoComplete", GeckoApp.mAppContext);
         GeckoAppShell.unregisterGeckoEventListener("Permissions:Data", GeckoApp.mAppContext);
+        GeckoAppShell.unregisterGeckoEventListener("Downloads:Done", GeckoApp.mAppContext);
 
         mFavicons.close();
 
         super.onDestroy();
 
         unregisterReceiver(mSmsReceiver);
         unregisterReceiver(mBatteryReceiver);
     }
--- a/mobile/android/base/locales/en-US/android_strings.dtd
+++ b/mobile/android/base/locales/en-US/android_strings.dtd
@@ -67,16 +67,17 @@
 <!ENTITY pref_font_size_medium "Medium">
 <!ENTITY pref_font_size_large "Large">
 <!ENTITY pref_font_size_xlarge "Extra Large">
 <!ENTITY pref_use_master_password "Use master password">
 
 <!ENTITY quit "Quit">
 
 <!ENTITY addons "Add-ons">
+<!ENTITY downloads "Downloads">
 
 <!ENTITY share "Share">
 <!ENTITY save_as_pdf "Save as PDF">
 <!ENTITY agent_request_desktop "Request Desktop Site">
 <!ENTITY agent_request_mobile "Request Mobile Site">
 
 <!ENTITY contextmenu_open_new_tab "Open in New Tab">
 <!ENTITY contextmenu_add_to_launcher "Add to Home Screen">
--- a/mobile/android/base/resources/layout/gecko_menu.xml
+++ b/mobile/android/base/resources/layout/gecko_menu.xml
@@ -28,11 +28,14 @@
           android:title="@string/settings" />
 
     <item android:id="@+id/site_settings"
           android:title="@string/site_settings_title" />
 
     <item android:id="@+id/addons"
           android:title="@string/addons"/>
 
+    <item android:id="@+id/downloads"
+          android:title="@string/downloads"/>
+
     <item android:id="@+id/quit"
           android:title="@string/quit" />
 </menu>
--- a/mobile/android/base/strings.xml.in
+++ b/mobile/android/base/strings.xml.in
@@ -75,16 +75,17 @@
   <string name="pref_font_size_medium">&pref_font_size_medium;</string>
   <string name="pref_font_size_large">&pref_font_size_large;</string>
   <string name="pref_font_size_xlarge">&pref_font_size_xlarge;</string>
 
   <string name="reload">&reload;</string>
   <string name="forward">&forward;</string>
   <string name="new_tab">&new_tab;</string>
   <string name="addons">&addons;</string>
+  <string name="downloads">&downloads;</string>
 
   <string name="site_settings_title">&site_settings_title;</string>
   <string name="site_settings_cancel">&site_settings_cancel;</string>
   <string name="site_settings_clear">&site_settings_clear;</string>
   <string name="site_settings_no_settings">&site_settings_no_settings;</string>
 
   <string name="contextmenu_open_new_tab">&contextmenu_open_new_tab;</string>
   <string name="contextmenu_add_to_launcher">&contextmenu_add_to_launcher;</string>
--- a/mobile/android/chrome/content/downloads.js
+++ b/mobile/android/chrome/content/downloads.js
@@ -120,35 +120,45 @@ var Downloads = {
       aIcon = URI_GENERIC_ICON_DOWNLOAD;
 
     var notifier = Cc["@mozilla.org/alerts-service;1"].getService(Ci.nsIAlertsService);
     notifier.showAlertNotification(aIcon, aTitle, aMessage, true, "", observer,
                                    aDownload.target.spec.replace("file:", "download:"));
   },
 
   observe: function dl_observe(aSubject, aTopic, aData) {
+    let download = aSubject.QueryInterface(Ci.nsIDownload);
     let msgKey = "";
     if (aTopic == "dl-start") {
       msgKey = "alertDownloadsStart";
       if (!this._progressAlert) {
         if (!this._dlmgr)
           this._dlmgr = Cc["@mozilla.org/download-manager;1"].getService(Ci.nsIDownloadManager);
         this._progressAlert = new AlertDownloadProgressListener();
         this._dlmgr.addListener(this._progressAlert);
       }
 
       NativeWindow.toast.show(Strings.browser.GetStringFromName("alertDownloadsToast"), "long");
     } else if (aTopic == "dl-done") {
       msgKey = "alertDownloadsDone";
+
+      let message = {
+        gecko: {
+          type: "Downloads:Done",
+          displayName: download.displayName,
+          path: download.targetFile.path,
+          size: download.size,
+          mimeType: download.MIMEInfo ? download.MIMEInfo.type : ""
+        }
+      };
+      sendMessageToJava(message);
     }
 
-    if (msgKey) {
-      let download = aSubject.QueryInterface(Ci.nsIDownload);
+    if (msgKey)
       this.showAlert(download, Strings.browser.formatStringFromName(msgKey, [download.displayName], 1));
-    }
   },
 
   QueryInterface: function (aIID) {
     if (!aIID.equals(Ci.nsIObserver) &&
         !aIID.equals(Ci.nsISupportsWeakReference) &&
         !aIID.equals(Ci.nsISupports))
       throw Components.results.NS_ERROR_NO_INTERFACE;
     return this;