Fix IntentHandler behavior

 Bug: 4473779
 Plus, TESTS! Huzzah!

Change-Id: I043e100d99d4653b7fb7885217d7fb305930a137
diff --git a/src/com/android/browser/BookmarkUtils.java b/src/com/android/browser/BookmarkUtils.java
index 491c16c..23765f4 100644
--- a/src/com/android/browser/BookmarkUtils.java
+++ b/src/com/android/browser/BookmarkUtils.java
@@ -115,10 +115,7 @@
     static Intent createAddToHomeIntent(Context context, String url, String title,
             Bitmap touchIcon, Bitmap favicon) {
         Intent i = new Intent(INSTALL_SHORTCUT);
-        Intent shortcutIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
-        long urlHash = url.hashCode();
-        long uniqueId = (urlHash << 32) | shortcutIntent.hashCode();
-        shortcutIntent.putExtra(Browser.EXTRA_APPLICATION_ID, Long.toString(uniqueId));
+        Intent shortcutIntent = createShortcutIntent(url);
         i.putExtra(Intent.EXTRA_SHORTCUT_INTENT, shortcutIntent);
         i.putExtra(Intent.EXTRA_SHORTCUT_NAME, title);
         i.putExtra(Intent.EXTRA_SHORTCUT_ICON, createIcon(context, touchIcon, favicon,
@@ -129,6 +126,14 @@
         return i;
     }
 
+    static Intent createShortcutIntent(String url) {
+        Intent shortcutIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
+        long urlHash = url.hashCode();
+        long uniqueId = (urlHash << 32) | shortcutIntent.hashCode();
+        shortcutIntent.putExtra(Browser.EXTRA_APPLICATION_ID, Long.toString(uniqueId));
+        return shortcutIntent;
+    }
+
     private static Bitmap getIconBackground(Context context, BookmarkIconType type, int density) {
         if (type == BookmarkIconType.ICON_HOME_SHORTCUT) {
             // Want to create a shortcut icon on the homescreen, so the icon
diff --git a/src/com/android/browser/Controller.java b/src/com/android/browser/Controller.java
index 9a015b2..1f376d2 100644
--- a/src/com/android/browser/Controller.java
+++ b/src/com/android/browser/Controller.java
@@ -338,6 +338,8 @@
             // TabControl.restoreState() will create a new tab even if
             // restoring the state fails.
             setActiveTab(mTabControl.getCurrentTab());
+            // Handle the intent
+            mIntentHandler.onNewIntent(intent);
         }
         // clear up the thumbnail directory, which is no longer used;
         // ideally this should only be run once after an upgrade from
diff --git a/src/com/android/browser/IntentHandler.java b/src/com/android/browser/IntentHandler.java
index 54711d9..088a788 100644
--- a/src/com/android/browser/IntentHandler.java
+++ b/src/com/android/browser/IntentHandler.java
@@ -139,6 +139,15 @@
                 mController.openTab(urlData);
                 return;
             }
+            /*
+             * TODO: Don't allow javascript URIs
+             * 0) If this is a javascript: URI, *always* open a new tab
+             * 1) If this is a voice search, re-use tab for appId
+             *    If there is no appId, use current tab
+             * 2) If the URL is already opened, switch to that tab
+             * 3-phone) Reuse tab with same appId
+             * 3-tablet) Open new tab
+             */
             final String appId = intent
                     .getStringExtra(Browser.EXTRA_APPLICATION_ID);
             if (!TextUtils.isEmpty(urlData.mUrl) &&
@@ -151,38 +160,33 @@
                     // If a voice search has no appId, it means that it came
                     // from the browser.  In that case, reuse the current tab.
                     || (activateVoiceSearch && appId != null))
-                    && !mActivity.getPackageName().equals(appId)
-                    && (flags & Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT) != 0) {
-                if (activateVoiceSearch) {
+                    && !mActivity.getPackageName().equals(appId)) {
+                if (activateVoiceSearch || !BrowserActivity.isTablet(mActivity)) {
                     Tab appTab = mTabControl.getTabFromAppId(appId);
                     if (appTab != null) {
                         mController.reuseTab(appTab, urlData);
                         return;
-                    } else {
-                        Tab tab = mController.openTab(urlData);
-                        if (tab != null) {
-                            tab.setAppId(appId);
-                        }
                     }
+                }
+                // No matching application tab, try to find a regular tab
+                // with a matching url.
+                Tab appTab = mTabControl.findTabWithUrl(urlData.mUrl);
+                if (appTab != null) {
+                    // Transfer ownership
+                    appTab.setAppId(appId);
+                    if (current != appTab) {
+                        mController.switchToTab(appTab);
+                    }
+                    // Otherwise, we are already viewing the correct tab.
                 } else {
-                    // No matching application tab, try to find a regular tab
-                    // with a matching url.
-                    Tab appTab = mTabControl.findUnusedTabWithUrl(urlData.mUrl);
-                    if (appTab != null) {
-                        if (current != appTab) {
-                            mController.switchToTab(appTab);
-                        }
-                        // Otherwise, we are already viewing the correct tab.
-                    } else {
-                        // if FLAG_ACTIVITY_BROUGHT_TO_FRONT flag is on, the url
-                        // will be opened in a new tab unless we have reached
-                        // MAX_TABS. Then the url will be opened in the current
-                        // tab. If a new tab is created, it will have "true" for
-                        // exit on close.
-                        Tab tab = mController.openTab(urlData);
-                        if (tab != null) {
-                            tab.setAppId(appId);
-                        }
+                    // if FLAG_ACTIVITY_BROUGHT_TO_FRONT flag is on, the url
+                    // will be opened in a new tab unless we have reached
+                    // MAX_TABS. Then the url will be opened in the current
+                    // tab. If a new tab is created, it will have "true" for
+                    // exit on close.
+                    Tab tab = mController.openTab(urlData);
+                    if (tab != null) {
+                        tab.setAppId(appId);
                     }
                 }
             } else {
diff --git a/src/com/android/browser/Tab.java b/src/com/android/browser/Tab.java
index c78b562..e672e2b 100644
--- a/src/com/android/browser/Tab.java
+++ b/src/com/android/browser/Tab.java
@@ -152,6 +152,7 @@
     // All the state needed for a page
     protected static class PageState {
         String mUrl;
+        String mOriginalUrl;
         String mTitle;
         LockIcon mLockIcon;
         Bitmap mFavicon;
@@ -159,10 +160,10 @@
 
         PageState(Context c, boolean incognito) {
             if (incognito) {
-                mUrl = "browser:incognito";
+                mOriginalUrl = mUrl = "browser:incognito";
                 mTitle = c.getString(R.string.new_incognito_tab);
             } else {
-                mUrl = "";
+                mOriginalUrl = mUrl = "";
                 mTitle = c.getString(R.string.new_tab);
             }
             mFavicon = BitmapFactory.decodeResource(
@@ -171,7 +172,7 @@
         }
 
         PageState(Context c, boolean incognito, String url, Bitmap favicon) {
-            mUrl = url;
+            mOriginalUrl = mUrl = url;
             mTitle = null;
             if (URLUtil.isHttpsUrl(url)) {
                 mLockIcon = LockIcon.LOCK_ICON_SECURE;
@@ -562,6 +563,7 @@
             if (mCurrentState.mUrl == null) {
                 mCurrentState.mUrl = url != null ? url : "";
             }
+            mCurrentState.mOriginalUrl = view.getOriginalUrl();
             mCurrentState.mTitle = view.getTitle();
             mCurrentState.mFavicon = view.getFavicon();
             if (!URLUtil.isHttpsUrl(mCurrentState.mUrl)) {
@@ -1677,10 +1679,10 @@
     }
 
     String getOriginalUrl() {
-        if (mMainView == null) {
-            return "";
+        if (mCurrentState.mOriginalUrl == null) {
+            return getUrl();
         }
-        return UrlUtils.filteredUrl(mMainView.getOriginalUrl());
+        return UrlUtils.filteredUrl(mCurrentState.mOriginalUrl);
     }
 
     /**
diff --git a/src/com/android/browser/TabControl.java b/src/com/android/browser/TabControl.java
index 1367ba2..2eb24e9 100644
--- a/src/com/android/browser/TabControl.java
+++ b/src/com/android/browser/TabControl.java
@@ -551,40 +551,28 @@
         }
     }
 
-    // This method checks if a non-app tab (one created within the browser)
-    // matches the given url.
+    // This method checks if a tab matches the given url.
     private boolean tabMatchesUrl(Tab t, String url) {
-        if (t.getAppId() != null) {
-            return false;
-        }
-        WebView webview = t.getWebView();
-        if (webview == null) {
-            return false;
-        } else if (url.equals(webview.getUrl())
-                || url.equals(webview.getOriginalUrl())) {
-            return true;
-        }
-        return false;
+        return url.equals(t.getUrl()) || url.equals(t.getOriginalUrl());
     }
 
     /**
-     * Return the tab that has no app id associated with it and the url of the
-     * tab matches the given url.
+     * Return the tab that matches the given url.
      * @param url The url to search for.
      */
-    Tab findUnusedTabWithUrl(String url) {
+    Tab findTabWithUrl(String url) {
         if (url == null) {
             return null;
         }
         // Check the current tab first.
-        Tab t = getCurrentTab();
-        if (t != null && tabMatchesUrl(t, url)) {
-            return t;
+        Tab currentTab = getCurrentTab();
+        if (currentTab != null && tabMatchesUrl(currentTab, url)) {
+            return currentTab;
         }
         // Now check all the rest.
         for (Tab tab : mTabs) {
             if (tabMatchesUrl(tab, url)) {
-                return t;
+                return tab;
             }
         }
         return null;