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;
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;
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())) {
// 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);
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) {
}
// Work out which packages are installed on the system.
getInstalledPackages();
+
+ // Start watching the default geolocation permissions
+ mSystemAllowGeolocationOrigins
+ = new SystemAllowGeolocationOrigins(getApplicationContext());
+ mSystemAllowGeolocationOrigins.start();
}
/**
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);
}
// 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);
}
}
}
}.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;
}
}
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;
}
= 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);
}
}
WebIconDatabase.getInstance().close();
unregisterReceiver(mPackageInstallationReceiver);
+
+ // Stop watching the default geolocation permissions
+ mSystemAllowGeolocationOrigins.stop();
+ mSystemAllowGeolocationOrigins = null;
}
@Override
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();
if (w != null) {
w.resumeTimers();
}
- return true;
- } else {
- return false;
}
}
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);
}
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) {
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;
break;
case R.id.view_downloads_menu_id:
- viewDownloads(null);
+ viewDownloads();
break;
case R.id.window_one_menu_id:
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
// 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();
}
/**
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
onProgressChanged(view, INITIAL_PROGRESS);
mDidStopLoad = false;
if (!mIsNetworkUp) createAndShowNetworkDialog();
-
+ closeDialogs();
if (mSettings.isTracing()) {
String host;
try {
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.
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;
}
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);
}
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);
}
* 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);
}
/**
// 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.
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;
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;