Bug 1276696 - Introduce new LauncherActivity that will handle all incoming Intents. r?mcomella draft
authorSebastian Kaspari <s.kaspari@gmail.com>
Sun, 15 May 2016 14:25:12 +0200
changeset 378039 75ac3cb1c42ce962a476b053f892b92006e518f8
parent 378038 5003caf3aa25dad509e53c68d2ee39de58fe5ec5
child 378040 dc34035e535bc3c357f1a9c709ea4085ca9aed1a
push id20919
push users.kaspari@gmail.com
push dateTue, 14 Jun 2016 12:28:54 +0000
reviewersmcomella
bugs1276696
milestone50.0a1
Bug 1276696 - Introduce new LauncherActivity that will handle all incoming Intents. r?mcomella We will need to dispatch Intent objects to different destinations (Browser, Custom Tab and eventually progressive web apps). The logic of TabQueueDispatcher is folded into this new activity. MozReview-Commit-ID: 3P4eIvtAKEW
mobile/android/base/AndroidManifest.xml.in
mobile/android/base/java/org/mozilla/gecko/LauncherActivity.java
mobile/android/base/java/org/mozilla/gecko/tabqueue/TabQueueDispatcher.java
mobile/android/base/moz.build
--- a/mobile/android/base/AndroidManifest.xml.in
+++ b/mobile/android/base/AndroidManifest.xml.in
@@ -39,16 +39,20 @@
 
         <meta-data android:name="com.sec.android.support.multiwindow" android:value="true"/>
 
 #ifdef MOZ_NATIVE_DEVICES
         <!-- This resources comes from Google Play Services. Required for casting support. -->
         <meta-data android:name="com.google.android.gms.version" android:value="@integer/google_play_services_version" />
 #endif
 
+        <!-- This activity handles all incoming Intents and dispatches them to other activities. -->
+        <activity android:name="org.mozilla.gecko.LauncherActivity"
+            android:theme="@android:style/Theme.Translucent.NoTitleBar" />
+
         <!-- Fennec is shipped as the Android package named
              org.mozilla.{fennec,firefox,firefox_beta}.  The internal Java
              package hierarchy inside the Android package used to have an
              org.mozilla.{fennec,firefox,firefox_beta} subtree *and* an
              org.mozilla.gecko subtree; it now only has org.mozilla.gecko. -->
         <activity android:name="@MOZ_ANDROID_BROWSER_INTENT_CLASS@"
                   android:label="@string/moz_app_displayname"
                   android:taskAffinity="@ANDROID_PACKAGE_NAME@.BROWSER"
@@ -59,29 +63,50 @@
                   android:exported="true"
                   android:theme="@style/Gecko.App" />
 
         <!-- Bug 1256615 / Bug 1268455: We published an .App alias and we need to maintain it
              forever.  If we don't, home screen shortcuts will disappear because the intent
              filter details change. -->
         <activity-alias android:name=".App"
                         android:label="@MOZ_APP_DISPLAYNAME@"
-                        android:targetActivity="@MOZ_ANDROID_BROWSER_INTENT_CLASS@">
+                        android:targetActivity="org.mozilla.gecko.LauncherActivity">
 
             <!-- android:priority ranges between -1000 and 1000.  We never want
                  another activity to usurp the MAIN action, so we ratchet our
                  priority up. -->
             <intent-filter android:priority="999">
                 <action android:name="android.intent.action.MAIN" />
                 <category android:name="android.intent.category.LAUNCHER" />
                 <category android:name="android.intent.category.MULTIWINDOW_LAUNCHER"/>
                 <category android:name="android.intent.category.APP_BROWSER" />
                 <category android:name="android.intent.category.DEFAULT" />
             </intent-filter>
 
+            <intent-filter>
+                <action android:name="android.intent.action.VIEW" />
+                <category android:name="android.intent.category.DEFAULT" />
+                <category android:name="android.intent.category.BROWSABLE" />
+                <data android:scheme="http" />
+                <data android:scheme="https" />
+                <data android:scheme="about" />
+                <data android:scheme="javascript" />
+            </intent-filter>
+            <intent-filter>
+                <action android:name="android.intent.action.VIEW" />
+                <category android:name="android.intent.category.BROWSABLE" />
+                <category android:name="android.intent.category.DEFAULT" />
+                <data android:scheme="file" />
+                <data android:scheme="http" />
+                <data android:scheme="https" />
+                <data android:mimeType="text/html"/>
+                <data android:mimeType="text/plain"/>
+                <data android:mimeType="application/xhtml+xml"/>
+            </intent-filter>
+
             <meta-data android:name="com.sec.minimode.icon.portrait.normal"
                        android:resource="@drawable/icon"/>
 
             <meta-data android:name="com.sec.minimode.icon.landscape.normal"
                        android:resource="@drawable/icon" />
 
             <intent-filter>
                 <action android:name="org.mozilla.gecko.ACTION_ALERT_CALLBACK" />
@@ -166,44 +191,16 @@
              before the rest of the plumbing is in place -->
 
         <service android:name="org.mozilla.gecko.tabqueue.TabQueueService" />
 
         <activity android:name="org.mozilla.gecko.tabqueue.TabQueuePrompt"
                   android:launchMode="singleTop"
                   android:theme="@style/OverlayActivity" />
 
-        <activity android:name="org.mozilla.gecko.tabqueue.TabQueueDispatcher"
-                  android:label="@MOZ_APP_DISPLAYNAME@"
-                  android:launchMode="singleTask"
-                  android:excludeFromRecents="true"
-                  android:taskAffinity="@ANDROID_PACKAGE_NAME@.TABQUEUE"
-                  android:theme="@style/TabQueueActivity">
-            <intent-filter>
-                <action android:name="android.intent.action.VIEW" />
-                <category android:name="android.intent.category.DEFAULT" />
-                <category android:name="android.intent.category.BROWSABLE" />
-                <data android:scheme="http" />
-                <data android:scheme="https" />
-                <data android:scheme="about" />
-                <data android:scheme="javascript" />
-            </intent-filter>
-            <intent-filter>
-                <action android:name="android.intent.action.VIEW" />
-                <category android:name="android.intent.category.BROWSABLE" />
-                <category android:name="android.intent.category.DEFAULT" />
-                <data android:scheme="file" />
-                <data android:scheme="http" />
-                <data android:scheme="https" />
-                <data android:mimeType="text/html"/>
-                <data android:mimeType="text/plain"/>
-                <data android:mimeType="application/xhtml+xml"/>
-            </intent-filter>
-        </activity>
-
         <receiver android:name="org.mozilla.gecko.restrictions.RestrictionProvider">
           <intent-filter>
             <action android:name="android.intent.action.GET_RESTRICTION_ENTRIES" />
           </intent-filter>
         </receiver>
 
         <!-- Masquerade as the Resolver so that we can be opened from the Marketplace. -->
         <activity-alias
new file mode 100644
--- /dev/null
+++ b/mobile/android/base/java/org/mozilla/gecko/LauncherActivity.java
@@ -0,0 +1,71 @@
+/* -*- Mode: Java; c-basic-offset: 4; tab-width: 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/. */
+
+package org.mozilla.gecko;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+import android.text.TextUtils;
+
+import org.mozilla.gecko.db.BrowserContract;
+import org.mozilla.gecko.tabqueue.TabQueueHelper;
+import org.mozilla.gecko.tabqueue.TabQueueService;
+
+/**
+ * Activity that receives incoming Intents and dispatches them to the appropriate activities (e.g. browser, custom tabs, web app).
+ */
+public class LauncherActivity extends Activity {
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        GeckoAppShell.ensureCrashHandling();
+
+        if (isViewIntent()) {
+            dispatchViewIntent();
+        } else {
+            dispatchNormalIntent();
+        }
+
+        finish();
+    }
+
+    /**
+     * Dispatch a VIEW action intent; either to the browser or to the tab queue service.
+     */
+    private void dispatchViewIntent() {
+        if (TabQueueHelper.TAB_QUEUE_ENABLED
+                && TabQueueHelper.isTabQueueEnabled(this)
+                && !getIntent().getBooleanExtra(BrowserContract.SKIP_TAB_QUEUE_FLAG, false)) {
+            dispatchTabQueueIntent();
+        } else {
+            dispatchNormalIntent();
+        }
+    }
+
+    /**
+     * Launch tab queue service to display overlay.
+     */
+    private void dispatchTabQueueIntent() {
+        Intent intent = new Intent(getIntent());
+        intent.setClass(getApplicationContext(), TabQueueService.class);
+        startService(intent);
+    }
+
+    /**
+     * Launch the browser activity.
+     */
+    private void dispatchNormalIntent() {
+        Intent intent = new Intent(getIntent());
+        intent.setClassName(getApplicationContext(), AppConstants.MOZ_ANDROID_BROWSER_INTENT_CLASS);
+        startActivity(intent);
+    }
+
+    private boolean isViewIntent() {
+        final String action = getIntent().getAction();
+        return Intent.ACTION_VIEW.equals(action);
+    }
+}
deleted file mode 100644
--- a/mobile/android/base/java/org/mozilla/gecko/tabqueue/TabQueueDispatcher.java
+++ /dev/null
@@ -1,100 +0,0 @@
-/* -*- Mode: Java; c-basic-offset: 4; tab-width: 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/. */
-
-package org.mozilla.gecko.tabqueue;
-
-import org.mozilla.gecko.AppConstants;
-import org.mozilla.gecko.GeckoAppShell;
-import org.mozilla.gecko.Locales;
-import org.mozilla.gecko.Telemetry;
-import org.mozilla.gecko.TelemetryContract;
-import org.mozilla.gecko.db.BrowserContract;
-
-import android.content.Intent;
-import android.os.Bundle;
-import android.text.TextUtils;
-import android.util.Log;
-import org.mozilla.gecko.mozglue.SafeIntent;
-
-/**
- * This class takes over external url loads (Intent.VIEW) from the BrowserApp class.  It determines if
- * the tab queue functionality is enabled and forwards the intent to the TabQueueService to process if it is.
- *
- * If the tab queue functionality is not enabled then it forwards the intent to BrowserApp to handle as normal.
- */
-public class TabQueueDispatcher extends Locales.LocaleAwareActivity {
-    private static final String LOGTAG = "Gecko" + TabQueueDispatcher.class.getSimpleName();
-
-    @Override
-    protected void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-
-        GeckoAppShell.ensureCrashHandling();
-
-        // The EXCLUDE_FROM_RECENTS flag is sticky
-        // (see http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/5.1.0_r1/com/android/server/am/ActivityRecord.java/#468)
-        // So let's remove this whilst keeping all other flags the same, otherwise BrowserApp will vanish from Recents!
-        Intent intent = getIntent();
-        int flags = intent.getFlags() & ~Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS;
-        intent.setFlags(flags);
-
-        SafeIntent safeIntent = new SafeIntent(intent);
-
-        // For the moment lets exit early and start fennec as normal if we're not in nightly with
-        // the tab queue build flag.
-        if (!TabQueueHelper.TAB_QUEUE_ENABLED) {
-            loadNormally(safeIntent.getUnsafe());
-            return;
-        }
-
-        // Skip the Tab Queue if instructed.
-        boolean shouldSkipTabQueue = safeIntent.getBooleanExtra(BrowserContract.SKIP_TAB_QUEUE_FLAG, false);
-        if (shouldSkipTabQueue) {
-            loadNormally(safeIntent.getUnsafe());
-            return;
-        }
-
-        // The URL is usually hiding somewhere in the extra text. Extract it.
-        final String dataString = safeIntent.getDataString();
-        if (TextUtils.isEmpty(dataString)) {
-            abortDueToNoURL(dataString);
-            return;
-        }
-
-        boolean shouldShowOpenInBackgroundToast = TabQueueHelper.isTabQueueEnabled(this);
-
-        if (shouldShowOpenInBackgroundToast) {
-            showToast(safeIntent.getUnsafe());
-        } else {
-            loadNormally(safeIntent.getUnsafe());
-        }
-    }
-
-    private void showToast(Intent intent) {
-        intent.setClass(getApplicationContext(), TabQueueService.class);
-        startService(intent);
-        finish();
-    }
-
-    /**
-     * Start fennec with the supplied intent.
-     */
-    private void loadNormally(Intent intent) {
-        intent.setClassName(getApplicationContext(), AppConstants.MOZ_ANDROID_BROWSER_INTENT_CLASS);
-        startActivity(intent);
-        Telemetry.sendUIEvent(TelemetryContract.Event.LOAD_URL, TelemetryContract.Method.INTENT, "");
-        finish();
-    }
-
-    /**
-     * Abort as we were started with no URL.
-     * @param dataString
-     */
-    private void abortDueToNoURL(String dataString) {
-        // TODO: Lets decide what to do here in bug 1134148
-        Log.w(LOGTAG, "Unable to process tab queue insertion. No URL found! - passed data string: " + dataString);
-        finish();
-    }
-}
--- a/mobile/android/base/moz.build
+++ b/mobile/android/base/moz.build
@@ -447,16 +447,17 @@ gbjar.sources += ['java/org/mozilla/geck
     'home/TopSitesPanel.java',
     'home/TopSitesThumbnailView.java',
     'home/TwoLinePageRow.java',
     'InputConnectionListener.java',
     'InputMethods.java',
     'IntentHelper.java',
     'javaaddons/JavaAddonManager.java',
     'javaaddons/JavaAddonManagerV1.java',
+    'LauncherActivity.java',
     'lwt/LightweightTheme.java',
     'lwt/LightweightThemeDrawable.java',
     'mdns/MulticastDNSManager.java',
     'media/AudioFocusAgent.java',
     'media/MediaControlService.java',
     'MediaCastingBar.java',
     'MemoryMonitor.java',
     'menu/GeckoMenu.java',
@@ -556,17 +557,16 @@ gbjar.sources += ['java/org/mozilla/geck
     'SnackbarHelper.java',
     'sqlite/ByteBufferInputStream.java',
     'sqlite/MatrixBlobCursor.java',
     'sqlite/SQLiteBridge.java',
     'sqlite/SQLiteBridgeException.java',
     'SuggestClient.java',
     'SurfaceBits.java',
     'Tab.java',
-    'tabqueue/TabQueueDispatcher.java',
     'tabqueue/TabQueueHelper.java',
     'tabqueue/TabQueuePrompt.java',
     'tabqueue/TabQueueService.java',
     'tabqueue/TabReceivedService.java',
     'Tabs.java',
     'tabs/PrivateTabsPanel.java',
     'tabs/TabCurve.java',
     'tabs/TabHistoryController.java',