OSDN Git Service

Use the system downloads UI, instead of browser specific 1.
[android-x86/packages-apps-Browser.git] / src / com / android / browser / BrowserActivity.java
index ca5d79b..101157c 100644 (file)
@@ -47,6 +47,7 @@ import android.graphics.PixelFormat;
 import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
 import android.net.ConnectivityManager;
+import android.net.DownloadManager;
 import android.net.NetworkInfo;
 import android.net.Uri;
 import android.net.WebAddress;
@@ -111,6 +112,7 @@ import android.accounts.AuthenticatorException;
 import android.accounts.OperationCanceledException;
 import android.accounts.AccountManagerCallback;
 
+import com.android.browser.search.SearchEngine;
 import com.android.common.Search;
 import com.android.common.speech.LoggingEvents;
 
@@ -190,6 +192,9 @@ public class BrowserActivity extends Activity
 
         mResolver = getContentResolver();
 
+        // Keep a settings instance handy.
+        mSettings = BrowserSettings.getInstance();
+
         // If this was a web search request, pass it on to the default web
         // search provider and finish this activity.
         if (handleWebSearchIntent(getIntent())) {
@@ -224,8 +229,6 @@ public class BrowserActivity extends Activity
         // Open the icon database and retain all the bookmark urls for favicons
         retainIconsOnStartup();
 
-        // Keep a settings instance handy.
-        mSettings = BrowserSettings.getInstance();
         mSettings.setTabControl(mTabControl);
 
         PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
@@ -358,6 +361,15 @@ public class BrowserActivity extends Activity
             attachTabToContentView(mTabControl.getCurrentTab());
         }
 
+        // Delete old thumbnails to save space
+        File dir = mTabControl.getThumbnailDir();
+        if (dir.exists()) {
+            for (String child : dir.list()) {
+                File f = new File(dir, child);
+                f.delete();
+            }
+        }
+
         // Read JavaScript flags if it exists.
         String jsFlags = mSettings.getJsFlags();
         if (jsFlags.trim().length() != 0) {
@@ -365,6 +377,11 @@ public class BrowserActivity extends Activity
         }
         // Work out which packages are installed on the system.
         getInstalledPackages();
+
+        // Start watching the default geolocation permissions
+        mSystemAllowGeolocationOrigins
+                = new SystemAllowGeolocationOrigins(getApplicationContext());
+        mSystemAllowGeolocationOrigins.start();
     }
 
     /**
@@ -455,7 +472,10 @@ public class BrowserActivity extends Activity
 
             final String appId = intent
                     .getStringExtra(Browser.EXTRA_APPLICATION_ID);
-            if ((Intent.ACTION_VIEW.equals(action) || activateVoiceSearch)
+            if ((Intent.ACTION_VIEW.equals(action)
+                    // 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))
                     && !getPackageName().equals(appId)
                     && (flags & Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT) != 0) {
                 Tab appTab = mTabControl.getTabFromId(appId);
@@ -531,6 +551,10 @@ public class BrowserActivity extends Activity
                 }
                 // Get rid of the subwindow if it exists
                 dismissSubWindow(current);
+                // If the current Tab is being used as an application tab,
+                // remove the association, since the new Intent means that it is
+                // no longer associated with that application.
+                current.setAppId(null);
                 loadUrlDataIn(current, urlData);
             }
         }
@@ -597,20 +621,19 @@ public class BrowserActivity extends Activity
             return false;
         }
 
-        Browser.updateVisitedHistory(mResolver, url, false);
-        Browser.addSearchUrl(mResolver, url);
+        final ContentResolver cr = mResolver;
+        final String newUrl = url;
+        new AsyncTask<Void, Void, Void>() {
+            protected Void doInBackground(Void... unused) {
+                Browser.updateVisitedHistory(cr, newUrl, false);
+                Browser.addSearchUrl(cr, newUrl);
+                return null;
+            }
+        }.execute();
 
-        Intent intent = new Intent(Intent.ACTION_WEB_SEARCH);
-        intent.addCategory(Intent.CATEGORY_DEFAULT);
-        intent.putExtra(SearchManager.QUERY, url);
-        if (appData != null) {
-            intent.putExtra(SearchManager.APP_DATA, appData);
-        }
-        if (extraData != null) {
-            intent.putExtra(SearchManager.EXTRA_DATA_KEY, extraData);
-        }
-        intent.putExtra(Browser.EXTRA_APPLICATION_ID, getPackageName());
-        startActivity(intent);
+        SearchEngine searchEngine = mSettings.getSearchEngine();
+        if (searchEngine == null) return false;
+        searchEngine.startSearch(this, url, appData, extraData);
 
         return true;
     }
@@ -651,7 +674,14 @@ public class BrowserActivity extends Activity
                     // But currently, we get the user-typed URL from search box as well.
                     url = fixUrl(url);
                     url = smartUrlFilter(url);
-                    Browser.updateVisitedHistory(mResolver, url, false);
+                    final ContentResolver cr = mResolver;
+                    final String newUrl = url;
+                    new AsyncTask<Void, Void, Void>() {
+                        protected Void doInBackground(Void... unused) {
+                            Browser.updateVisitedHistory(cr, newUrl, false);
+                            return null;
+                        }
+                    }.execute();
                     String searchSource = "&source=android-" + GOOGLE_SEARCH_SOURCE_SUGGEST + "&";
                     if (url.contains(searchSource)) {
                         String source = null;
@@ -801,15 +831,18 @@ public class BrowserActivity extends Activity
     }
 
     private void showFakeTitleBar() {
-        final View decor = getWindow().peekDecorView();
         if (mFakeTitleBar.getParent() == null && mActiveTabsPage == null
-                && !mActivityInPause && decor != null
-                && decor.getWindowToken() != null) {
-            Rect visRect = new Rect();
-            if (!mBrowserFrameLayout.getGlobalVisibleRect(visRect)) {
-                if (LOGD_ENABLED) {
-                    Log.d(LOGTAG, "showFakeTitleBar visRect failed");
-                }
+                && !mActivityInPause) {
+            WebView mainView = mTabControl.getCurrentWebView();
+            // if there is no current WebView, don't show the faked title bar;
+            if (mainView == null) {
+                return;
+            }
+            // Do not need to check for null, since the current tab will have
+            // at least a main WebView, or we would have returned above.
+            if (dialogIsUp()) {
+                // Do not show the fake title bar, which would cover up the
+                // find or select dialog.
                 return;
             }
 
@@ -822,17 +855,12 @@ public class BrowserActivity extends Activity
                     = new WindowManager.LayoutParams(
                     ViewGroup.LayoutParams.MATCH_PARENT,
                     ViewGroup.LayoutParams.WRAP_CONTENT,
-                    WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL,
+                    WindowManager.LayoutParams.TYPE_APPLICATION,
                     WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
                     PixelFormat.TRANSLUCENT);
             params.gravity = Gravity.TOP;
-            WebView mainView = mTabControl.getCurrentWebView();
-            boolean atTop = mainView != null && mainView.getScrollY() == 0;
+            boolean atTop = mainView.getScrollY() == 0;
             params.windowAnimations = atTop ? 0 : R.style.TitleBar;
-            // XXX : Without providing an offset, the fake title bar will be
-            // placed underneath the status bar.  Use the global visible rect
-            // of mBrowserFrameLayout to determine the bottom of the status bar
-            params.y = visRect.top;
             manager.addView(mFakeTitleBar, params);
         }
     }
@@ -967,6 +995,10 @@ public class BrowserActivity extends Activity
         WebIconDatabase.getInstance().close();
 
         unregisterReceiver(mPackageInstallationReceiver);
+
+        // Stop watching the default geolocation permissions
+        mSystemAllowGeolocationOrigins.stop();
+        mSystemAllowGeolocationOrigins = null;
     }
 
     @Override
@@ -1014,8 +1046,9 @@ public class BrowserActivity extends Activity
         mTabControl.freeMemory();
     }
 
-    private boolean resumeWebViewTimers() {
+    private void resumeWebViewTimers() {
         Tab tab = mTabControl.getCurrentTab();
+        if (tab == null) return; // monkey can trigger this
         boolean inLoad = tab.inLoad();
         if ((!mActivityInPause && !inLoad) || (mActivityInPause && inLoad)) {
             CookieSyncManager.getInstance().startSync();
@@ -1023,9 +1056,6 @@ public class BrowserActivity extends Activity
             if (w != null) {
                 w.resumeTimers();
             }
-            return true;
-        } else {
-            return false;
         }
     }
 
@@ -1173,6 +1203,12 @@ public class BrowserActivity extends Activity
         if (appSearchData == null) {
             appSearchData = createGoogleSearchSourceBundle(GOOGLE_SEARCH_SOURCE_TYPE);
         }
+
+        SearchEngine searchEngine = mSettings.getSearchEngine();
+        if (searchEngine != null && !searchEngine.supportsVoiceSearch()) {
+            appSearchData.putBoolean(SearchManager.DISABLE_VOICE_SEARCH, true);
+        }
+
         super.startSearch(initialQuery, selectInitialQuery, appSearchData, globalSearch);
     }
 
@@ -1252,6 +1288,21 @@ public class BrowserActivity extends Activity
         getTopWindow().requestFocus();
     }
 
+    private WebView showDialog(WebDialog dialog) {
+        Tab tab = mTabControl.getCurrentTab();
+        if (tab.getSubWebView() == null) {
+            // If the find or select is being performed on the main webview,
+            // remove the embedded title bar.
+            WebView mainView = tab.getWebView();
+            if (mainView != null) {
+                mainView.setEmbeddedTitleBar(null);
+            }
+        }
+        hideFakeTitleBar();
+        mMenuState = EMPTY_MENU;
+        return tab.showDialog(dialog);
+    }
+
     @Override
     public boolean onOptionsItemSelected(MenuItem item) {
         if (!mCanChord) {
@@ -1345,18 +1396,20 @@ public class BrowserActivity extends Activity
                 break;
 
             case R.id.find_menu_id:
-                if (null == mFindDialog) {
-                    mFindDialog = new FindDialog(this);
-                }
-                mFindDialog.setWebView(getTopWindow());
-                mFindDialog.show();
-                getTopWindow().setFindIsUp(true);
-                mMenuState = EMPTY_MENU;
+                showFindDialog();
                 break;
 
             case R.id.select_text_id:
-                getTopWindow().emulateShiftHeld();
+                if (true) {
+                    Tab currentTab = mTabControl.getCurrentTab();
+                    if (currentTab != null) {
+                        currentTab.getWebView().setUpSelect();
+                    }
+                } else {
+                    showSelectDialog();
+                }
                 break;
+
             case R.id.page_info_menu_id:
                 showPageInfo(mTabControl.getCurrentTab(), false);
                 break;
@@ -1395,7 +1448,7 @@ public class BrowserActivity extends Activity
                 break;
 
             case R.id.view_downloads_menu_id:
-                viewDownloads(null);
+                viewDownloads();
                 break;
 
             case R.id.window_one_menu_id:
@@ -1431,8 +1484,59 @@ public class BrowserActivity extends Activity
         return true;
     }
 
-    public void closeFind() {
+    private boolean dialogIsUp() {
+        return null != mFindDialog && mFindDialog.isVisible() ||
+            null != mSelectDialog && mSelectDialog.isVisible();
+    }
+
+    private boolean closeDialog(WebDialog dialog) {
+        if (null == dialog || !dialog.isVisible()) return false;
+        Tab currentTab = mTabControl.getCurrentTab();
+        currentTab.closeDialog(dialog);
+        dialog.dismiss();
+        return true;
+    }
+
+    /*
+     * Remove the find dialog or select dialog.
+     */
+    public void closeDialogs() {
+        if (!(closeDialog(mFindDialog) || closeDialog(mSelectDialog))) return;
+        // If the Find was being performed in the main WebView, replace the
+        // embedded title bar.
+        Tab currentTab = mTabControl.getCurrentTab();
+        if (currentTab.getSubWebView() == null) {
+            WebView mainView = currentTab.getWebView();
+            if (mainView != null) {
+                mainView.setEmbeddedTitleBar(mTitleBar);
+            }
+        }
         mMenuState = R.id.MAIN_MENU;
+        if (mInLoad) {
+            // The title bar was hidden, because otherwise it would cover up the
+            // find or select dialog.  Now that the dialog has been removed,
+            // show the fake title bar once again.
+            showFakeTitleBar();
+        }
+    }
+
+    public void showFindDialog() {
+        if (null == mFindDialog) {
+            mFindDialog = new FindDialog(this);
+        }
+        showDialog(mFindDialog).setFindIsUp(true);
+    }
+
+    public void setFindDialogText(String text) {
+        mFindDialog.setText(text);
+    }
+
+    public void showSelectDialog() {
+        if (null == mSelectDialog) {
+            mSelectDialog = new SelectDialog(this);
+        }
+        showDialog(mSelectDialog).setUpSelect();
+        mSelectDialog.hideSoftInput();
     }
 
     @Override
@@ -2299,32 +2403,45 @@ public class BrowserActivity extends Activity
         // draw, but the API for that (WebViewCore.pictureReady()) is not
         // currently accessible here.
 
-        ContentResolver cr = getContentResolver();
-        final Cursor c = BrowserBookmarksAdapter.queryBookmarksForUrl(
-                cr, view.getOriginalUrl(), view.getUrl(), true);
-        if (c != null) {
-            boolean succeed = c.moveToFirst();
-            ContentValues values = null;
-            while (succeed) {
-                if (values == null) {
-                    final ByteArrayOutputStream os
-                            = new ByteArrayOutputStream();
-                    Bitmap bm = createScreenshot(view);
-                    if (bm == null) {
-                        c.close();
-                        return;
+        final Bitmap bm = createScreenshot(view);
+        if (bm == null) {
+            return;
+        }
+
+        final ContentResolver cr = getContentResolver();
+        final String url = view.getUrl();
+        final String originalUrl = view.getOriginalUrl();
+
+        new AsyncTask<Void, Void, Void>() {
+            @Override
+            protected Void doInBackground(Void... unused) {
+                Cursor c = null;
+                try {
+                    c = BrowserBookmarksAdapter.queryBookmarksForUrl(
+                            cr, originalUrl, url, true);
+                    if (c != null) {
+                        if (c.moveToFirst()) {
+                            ContentValues values = new ContentValues();
+                            final ByteArrayOutputStream os
+                                    = new ByteArrayOutputStream();
+                            bm.compress(Bitmap.CompressFormat.PNG, 100, os);
+                            values.put(Browser.BookmarkColumns.THUMBNAIL,
+                                    os.toByteArray());
+                            do {
+                                cr.update(ContentUris.withAppendedId(
+                                        Browser.BOOKMARKS_URI, c.getInt(0)),
+                                        values, null, null);
+                            } while (c.moveToNext());
+                        }
                     }
-                    bm.compress(Bitmap.CompressFormat.PNG, 100, os);
-                    values = new ContentValues();
-                    values.put(Browser.BookmarkColumns.THUMBNAIL,
-                            os.toByteArray());
+                } catch (IllegalStateException e) {
+                    // Ignore
+                } finally {
+                    if (c != null) c.close();
                 }
-                cr.update(ContentUris.withAppendedId(Browser.BOOKMARKS_URI,
-                        c.getInt(0)), values, null, null);
-                succeed = c.moveToNext();
+                return null;
             }
-            c.close();
-        }
+        }.execute();
     }
 
     /**
@@ -2368,7 +2485,7 @@ public class BrowserActivity extends Activity
             return null;
         }
         Bitmap bm = Bitmap.createBitmap(getDesiredThumbnailWidth(this),
-                getDesiredThumbnailHeight(this), Bitmap.Config.ARGB_4444);
+                getDesiredThumbnailHeight(this), Bitmap.Config.RGB_565);
         Canvas canvas = new Canvas(bm);
         // May need to tweak these values to determine what is the
         // best scale factor
@@ -2430,7 +2547,7 @@ public class BrowserActivity extends Activity
         onProgressChanged(view, INITIAL_PROGRESS);
         mDidStopLoad = false;
         if (!mIsNetworkUp) createAndShowNetworkDialog();
-
+        closeDialogs();
         if (mSettings.isTracing()) {
             String host;
             try {
@@ -2776,6 +2893,36 @@ public class BrowserActivity extends Activity
         onDownloadStartNoStream(url, userAgent, contentDisposition, mimetype, contentLength);
     }
 
+    // This is to work around the fact that java.net.URI throws Exceptions
+    // instead of just encoding URL's properly
+    // Helper method for onDownloadStartNoStream
+    private static String encodePath(String path) {
+        char[] chars = path.toCharArray();
+
+        boolean needed = false;
+        for (char c : chars) {
+            if (c == '[' || c == ']') {
+                needed = true;
+                break;
+            }
+        }
+        if (needed == false) {
+            return path;
+        }
+
+        StringBuilder sb = new StringBuilder("");
+        for (char c : chars) {
+            if (c == '[' || c == ']') {
+                sb.append('%');
+                sb.append(Integer.toHexString(c));
+            } else {
+                sb.append(c);
+            }
+        }
+
+        return sb.toString();
+    }
+
     /**
      * Notify the host application a download should be done, even if there
      * is a streaming viewer available for thise type.
@@ -2815,35 +2962,16 @@ public class BrowserActivity extends Activity
             return;
         }
 
-        // java.net.URI is a lot stricter than KURL so we have to undo
-        // KURL's percent-encoding and redo the encoding using java.net.URI.
-        URI uri = null;
+        // java.net.URI is a lot stricter than KURL so we have to encode some
+        // extra characters. Fix for b 2538060 and b 1634719
+        WebAddress webAddress;
         try {
-            // Undo the percent-encoding that KURL may have done.
-            String newUrl = new String(URLUtil.decode(url.getBytes()));
-            // Parse the url into pieces
-            WebAddress w = new WebAddress(newUrl);
-            String frag = null;
-            String query = null;
-            String path = w.mPath;
-            // Break the path into path, query, and fragment
-            if (path.length() > 0) {
-                // Strip the fragment
-                int idx = path.lastIndexOf('#');
-                if (idx != -1) {
-                    frag = path.substring(idx + 1);
-                    path = path.substring(0, idx);
-                }
-                idx = path.lastIndexOf('?');
-                if (idx != -1) {
-                    query = path.substring(idx + 1);
-                    path = path.substring(0, idx);
-                }
-            }
-            uri = new URI(w.mScheme, w.mAuthInfo, w.mHost, w.mPort, path,
-                    query, frag);
+            webAddress = new WebAddress(url);
+            webAddress.mPath = encodePath(webAddress.mPath);
         } catch (Exception e) {
-            Log.e(LOGTAG, "Could not parse url for download: " + url, e);
+            // This only happens for very bad urls, we want to chatch the
+            // exception here
+            Log.e(LOGTAG, "Exception trying to parse url:" + url);
             return;
         }
 
@@ -2852,18 +2980,18 @@ public class BrowserActivity extends Activity
         String cookies = CookieManager.getInstance().getCookie(url);
 
         ContentValues values = new ContentValues();
-        values.put(Downloads.Impl.COLUMN_URI, uri.toString());
+        values.put(Downloads.Impl.COLUMN_URI, webAddress.toString());
         values.put(Downloads.Impl.COLUMN_COOKIE_DATA, cookies);
         values.put(Downloads.Impl.COLUMN_USER_AGENT, userAgent);
         values.put(Downloads.Impl.COLUMN_NOTIFICATION_PACKAGE,
                 getPackageName());
         values.put(Downloads.Impl.COLUMN_NOTIFICATION_CLASS,
-                BrowserDownloadPage.class.getCanonicalName());
+                OpenDownloadReceiver.class.getCanonicalName());
         values.put(Downloads.Impl.COLUMN_VISIBILITY,
                 Downloads.Impl.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
         values.put(Downloads.Impl.COLUMN_MIME_TYPE, mimetype);
         values.put(Downloads.Impl.COLUMN_FILE_NAME_HINT, filename);
-        values.put(Downloads.Impl.COLUMN_DESCRIPTION, uri.getHost());
+        values.put(Downloads.Impl.COLUMN_DESCRIPTION, webAddress.mHost);
         if (contentLength > 0) {
             values.put(Downloads.Impl.COLUMN_TOTAL_BYTES, contentLength);
         }
@@ -3342,7 +3470,7 @@ public class BrowserActivity extends Activity
     public void setHttpAuthUsernamePassword(String host, String realm,
                                             String username,
                                             String password) {
-        WebView w = mTabControl.getCurrentWebView();
+        WebView w = getTopWindow();
         if (w != null) {
             w.setHttpAuthUsernamePassword(host, realm, username, password);
         }
@@ -3439,12 +3567,9 @@ public class BrowserActivity extends Activity
      * menu to see the download window. It shows the download window on top of
      * the current window.
      */
-    private void viewDownloads(Uri downloadRecord) {
-        Intent intent = new Intent(this,
-                BrowserDownloadPage.class);
-        intent.setData(downloadRecord);
-        startActivityForResult(intent, BrowserActivity.DOWNLOAD_PAGE);
-
+    private void viewDownloads() {
+        Intent intent = new Intent(DownloadManager.ACTION_VIEW_DOWNLOADS);
+        startActivity(intent);
     }
 
     /**
@@ -3617,11 +3742,15 @@ public class BrowserActivity extends Activity
             // Nothing to do.
             return;
         }
+        Tab t = mTabControl.getCurrentTab();
+        if (t == null) {
+            // There is no current tab so we cannot toggle the error console
+            return;
+        }
 
         mShouldShowErrorConsole = flag;
 
-        ErrorConsoleView errorConsole = mTabControl.getCurrentTab()
-                .getErrorConsole(true);
+        ErrorConsoleView errorConsole = t.getErrorConsole(true);
 
         if (flag) {
             // Setting the show state of the console will cause it's the layout to be inflated.
@@ -3727,6 +3856,7 @@ public class BrowserActivity extends Activity
     private Menu mMenu;
 
     private FindDialog mFindDialog;
+    private SelectDialog mSelectDialog;
     // Used to prevent chording to result in firing two shortcuts immediately
     // one after another.  Fixes bug 1211714.
     boolean mCanChord;
@@ -3735,7 +3865,7 @@ public class BrowserActivity extends Activity
     private boolean mIsNetworkUp;
     private boolean mDidStopLoad;
 
-    private boolean mActivityInPause = true;
+    /* package */ boolean mActivityInPause = true;
 
     private boolean mMenuIsDown;
 
@@ -3858,9 +3988,10 @@ public class BrowserActivity extends Activity
 
     private BroadcastReceiver mPackageInstallationReceiver;
 
+    private SystemAllowGeolocationOrigins mSystemAllowGeolocationOrigins;
+
     // activity requestCode
     final static int COMBO_PAGE                 = 1;
-    final static int DOWNLOAD_PAGE              = 2;
     final static int PREFERENCES_PAGE           = 3;
     final static int FILE_SELECTED              = 4;