am 0df0a2a2: merge from froyo-plus-aosp
Merge commit '0df0a2a20a4e1418983126e72af0e62ebc0cc8f3'
* commit '0df0a2a20a4e1418983126e72af0e62ebc0cc8f3':
diff --git a/res/anim/find_dialog_enter.xml b/res/anim/find_dialog_enter.xml
index 5e597a4..6fbcb9e 100644
--- a/res/anim/find_dialog_enter.xml
+++ b/res/anim/find_dialog_enter.xml
@@ -16,6 +16,6 @@
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="@android:anim/decelerate_interpolator">
- <translate android:fromYDelta="25%" android:toYDelta="0" android:duration="75"/>
- <alpha android:fromAlpha="0.0" android:toAlpha="1.0" android:duration="75" />
+ <translate android:fromYDelta="-25%" android:toYDelta="0" android:duration="75"/>
+ <alpha android:fromAlpha="0.0" android:toAlpha="1.0" android:duration="75" />
</set>
diff --git a/res/anim/find_dialog_exit.xml b/res/anim/find_dialog_exit.xml
index 854abd0..9845849 100644
--- a/res/anim/find_dialog_exit.xml
+++ b/res/anim/find_dialog_exit.xml
@@ -16,7 +16,7 @@
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="@android:anim/accelerate_interpolator">
- <translate android:fromYDelta="0" android:toYDelta="50%" android:duration="50"/>
- <alpha android:fromAlpha="1.0" android:toAlpha="0.0" android:duration="50" />
+ <translate android:fromYDelta="0" android:toYDelta="-50%" android:duration="50"/>
+ <alpha android:fromAlpha="1.0" android:toAlpha="0.0" android:duration="50" />
</set>
diff --git a/res/layout/browser_subwindow.xml b/res/layout/browser_subwindow.xml
index 76d72d5..adf3284 100644
--- a/res/layout/browser_subwindow.xml
+++ b/res/layout/browser_subwindow.xml
@@ -23,6 +23,7 @@
android:layout_height="match_parent"
android:padding="10dip" >
<LinearLayout
+ android:id="@+id/inner_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
diff --git a/res/layout/custom_screen.xml b/res/layout/custom_screen.xml
index 90dc324..525f30c 100644
--- a/res/layout/custom_screen.xml
+++ b/res/layout/custom_screen.xml
@@ -22,6 +22,7 @@
android:layout_height="match_parent"
/>
<LinearLayout android:orientation="vertical"
+ android:id="@+id/vertical_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 18a2144..a30a399 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -50,17 +50,16 @@
<!-- Label for a confirm button. Used in multiple contexts. -->
<string name="ok">OK</string>
- <!-- Displayed on the Find dialog to display the number of matches
- found in the current page. -->
+ <!-- Displayed on the Find dialog when there are no matches -->
+ <string name="no_matches">No matches</string>
+
+ <!-- Displayed on the Find dialog to display the index of the highlighted
+ match and total number of matches found in the current page. -->
<plurals name="matches_found">
- <!-- Case of no matches -->
- <item quantity="zero">No matches</item>
<!-- Case of one match -->
<item quantity="one">1 match</item>
- <!-- Case of "few" (two) matches -->
- <item quantity="few"><xliff:g id="number" example="2">%d</xliff:g> matches</item>
- <!-- Case of several matches -->
- <item quantity="other"><xliff:g id="number" example="137">%d</xliff:g> matches</item>
+ <!-- Case of multiple total matches -->
+ <item quantity="other"><xliff:g id="index" example="2">%d</xliff:g> of <xliff:g id="total" example="137">%d</xliff:g></item>
</plurals>
<!-- Displayed on the title bar while the page is loading -->
diff --git a/res/values/styles.xml b/res/values/styles.xml
index 4779aa1..2e8510a 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -30,11 +30,6 @@
<item name="android:windowContentOverlay">@null</item>
</style>
- <style name="FindDialog">
- <item name="android:windowEnterAnimation">@anim/find_dialog_enter</item>
- <item name="android:windowExitAnimation">@anim/find_dialog_exit</item>
- </style>
-
<style name="TitleBar">
<item name="android:windowEnterAnimation">@anim/title_bar_enter</item>
<item name="android:windowExitAnimation">@anim/title_bar_exit</item>
diff --git a/res/values/themes.xml b/res/values/themes.xml
deleted file mode 100644
index bb922dd..0000000
--- a/res/values/themes.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2008 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<resources>
- <style name="FindDialogTheme">
- <item name="android:windowFrame">@null</item>
- <item name="android:windowIsFloating">true</item>
- <item name="android:windowIsTranslucent">true</item>
- <item name="android:windowNoTitle">true</item>
- <item name="android:background">@null</item>
- <item name="android:windowBackground">@null</item>
- <item name="android:windowAnimationStyle">@style/FindDialog</item>
- <item name="android:backgroundDimEnabled">false</item>
- </style>
-</resources>
diff --git a/src/com/android/browser/ActiveTabsPage.java b/src/com/android/browser/ActiveTabsPage.java
index 2de7787..52828b3 100644
--- a/src/com/android/browser/ActiveTabsPage.java
+++ b/src/com/android/browser/ActiveTabsPage.java
@@ -20,6 +20,7 @@
import android.graphics.Bitmap;
import android.os.Handler;
import android.util.AttributeSet;
+import android.util.Log;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
@@ -32,6 +33,7 @@
import android.widget.TextView;
public class ActiveTabsPage extends LinearLayout {
+ private static final String LOGTAG = "TabPicker";
private final BrowserActivity mBrowserActivity;
private final LayoutInflater mFactory;
private final TabControl mControl;
@@ -152,7 +154,19 @@
(ImageView) convertView.findViewById(R.id.favicon);
View close = convertView.findViewById(R.id.close);
Tab tab = mControl.getTab(position);
+ if (tab.getWebView() == null) {
+ // This means that populatePickerData will have to use the
+ // saved state.
+ Log.w(LOGTAG, "Tab " + position + " has a null WebView and "
+ + (tab.getSavedState() == null ? "null" : "non-null")
+ + " saved state ");
+ }
tab.populatePickerData();
+ if (tab.getTitle() == null || tab.getTitle().length() == 0) {
+ Log.w(LOGTAG, "Tab " + position + " has no title. "
+ + "Check above in the Logs to see whether it has a "
+ + "null WebView or null WebHistoryItem");
+ }
title.setText(tab.getTitle());
url.setText(tab.getUrl());
Bitmap icon = tab.getFavicon();
diff --git a/src/com/android/browser/BrowserActivity.java b/src/com/android/browser/BrowserActivity.java
index 5e55789..b2d7d82 100644
--- a/src/com/android/browser/BrowserActivity.java
+++ b/src/com/android/browser/BrowserActivity.java
@@ -87,6 +87,7 @@
import android.view.WindowManager;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.MenuItem.OnMenuItemClickListener;
+import android.view.accessibility.AccessibilityManager;
import android.webkit.CookieManager;
import android.webkit.CookieSyncManager;
import android.webkit.DownloadListener;
@@ -171,6 +172,8 @@
*/
private FrameLayout mBrowserFrameLayout;
+ private boolean mXLargeScreenSize;
+
@Override
public void onCreate(Bundle icicle) {
if (LOGV_ENABLED) {
@@ -186,7 +189,11 @@
BitmapFactory.setDefaultConfig(Bitmap.Config.ARGB_8888);
}
- setDefaultKeyMode(DEFAULT_KEYS_SEARCH_LOCAL);
+ if (AccessibilityManager.getInstance(this).isEnabled()) {
+ setDefaultKeyMode(DEFAULT_KEYS_DISABLE);
+ } else {
+ setDefaultKeyMode(DEFAULT_KEYS_SEARCH_LOCAL);
+ }
mResolver = getContentResolver();
@@ -214,9 +221,22 @@
.findViewById(R.id.fullscreen_custom_content);
frameLayout.addView(mBrowserFrameLayout, COVER_SCREEN_PARAMS);
mTitleBar = new TitleBar(this);
- // mTitleBar will be always shown in the fully loaded mode
- mTitleBar.setProgress(100);
- mFakeTitleBar = new TitleBar(this);
+ mXLargeScreenSize = (getResources().getConfiguration().screenLayout
+ & Configuration.SCREENLAYOUT_SIZE_MASK)
+ == Configuration.SCREENLAYOUT_SIZE_XLARGE;
+ if (mXLargeScreenSize) {
+ LinearLayout layout = (LinearLayout) mBrowserFrameLayout.
+ findViewById(R.id.vertical_layout);
+ layout.addView(mTitleBar, 0, new LinearLayout.LayoutParams(
+ ViewGroup.LayoutParams.MATCH_PARENT,
+ ViewGroup.LayoutParams.WRAP_CONTENT));
+ } else {
+ // mTitleBar will be always be shown in the fully loaded mode on
+ // phone
+ mTitleBar.setProgress(100);
+ // Fake title bar is not needed in xlarge layout
+ mFakeTitleBar = new TitleBar(this);
+ }
// Create the tab control and our initial tab
mTabControl = new TabControl(this);
@@ -305,9 +325,7 @@
}
if (permissionOk) {
PluginManager.getInstance(BrowserActivity.this)
- .refreshPlugins(
- Intent.ACTION_PACKAGE_ADDED
- .equals(action));
+ .refreshPlugins(true);
}
}
}
@@ -697,17 +715,21 @@
}
/* package */ void showVoiceTitleBar(String title) {
mTitleBar.setInVoiceMode(true);
- mFakeTitleBar.setInVoiceMode(true);
-
mTitleBar.setDisplayTitle(title);
- mFakeTitleBar.setDisplayTitle(title);
+
+ if (!mXLargeScreenSize) {
+ mFakeTitleBar.setInVoiceMode(true);
+ mFakeTitleBar.setDisplayTitle(title);
+ }
}
/* package */ void revertVoiceTitleBar() {
mTitleBar.setInVoiceMode(false);
- mFakeTitleBar.setInVoiceMode(false);
-
mTitleBar.setDisplayTitle(mUrl);
- mFakeTitleBar.setDisplayTitle(mUrl);
+
+ if (!mXLargeScreenSize) {
+ mFakeTitleBar.setInVoiceMode(false);
+ mFakeTitleBar.setDisplayTitle(mUrl);
+ }
}
/* package */ static String fixUrl(String inUrl) {
// FIXME: Converting the url to lower case
@@ -827,6 +849,7 @@
}
private void showFakeTitleBar() {
+ if (mXLargeScreenSize) return;
if (mFakeTitleBar.getParent() == null && mActiveTabsPage == null
&& !mActivityInPause) {
WebView mainView = mTabControl.getCurrentWebView();
@@ -834,6 +857,13 @@
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 (getTopWindow().getFindIsUp()) {
+ // Do not show the fake title bar, which would cover up the
+ // FindDialog.
+ return;
+ }
WindowManager manager
= (WindowManager) getSystemService(Context.WINDOW_SERVICE);
@@ -868,7 +898,7 @@
}
private void hideFakeTitleBar() {
- if (mFakeTitleBar.getParent() == null) return;
+ if (mXLargeScreenSize || mFakeTitleBar.getParent() == null) return;
WindowManager.LayoutParams params = (WindowManager.LayoutParams)
mFakeTitleBar.getLayoutParams();
WebView mainView = mTabControl.getCurrentWebView();
@@ -1145,7 +1175,6 @@
break;
// -- Browser context menu
case R.id.open_context_menu_id:
- case R.id.open_newtab_context_menu_id:
case R.id.bookmark_context_menu_id:
case R.id.save_link_context_menu_id:
case R.id.share_link_context_menu_id:
@@ -1263,6 +1292,7 @@
*/
/* package */ void removeActiveTabPage(boolean needToAttach) {
mContentView.removeView(mActiveTabsPage);
+ mTitleBar.setVisibility(View.VISIBLE);
mActiveTabsPage = null;
mMenuState = R.id.MAIN_MENU;
if (needToAttach) {
@@ -1305,6 +1335,7 @@
case R.id.active_tabs_menu_id:
mActiveTabsPage = new ActiveTabsPage(this, mTabControl);
removeTabFromContentView(mTabControl.getCurrentTab());
+ mTitleBar.setVisibility(View.GONE);
hideFakeTitleBar();
mContentView.addView(mActiveTabsPage, COVER_SCREEN_PARAMS);
mActiveTabsPage.requestFocus();
@@ -1367,9 +1398,18 @@
if (null == mFindDialog) {
mFindDialog = new FindDialog(this);
}
- mFindDialog.setWebView(getTopWindow());
- mFindDialog.show();
- getTopWindow().setFindIsUp(true);
+ // Need to do something special for Tablet
+ Tab tab = mTabControl.getCurrentTab();
+ if (tab.getSubWebView() == null) {
+ // If the Find is being performed on the main webview,
+ // remove the embedded title bar.
+ WebView mainView = tab.getWebView();
+ if (mainView != null) {
+ mainView.setEmbeddedTitleBar(null);
+ }
+ }
+ hideFakeTitleBar();
+ tab.showFind(mFindDialog);
mMenuState = EMPTY_MENU;
break;
@@ -1450,8 +1490,32 @@
return true;
}
+ /*
+ * Remove the FindDialog.
+ */
public void closeFind() {
+ Tab currentTab = mTabControl.getCurrentTab();
+ if (mFindDialog != null) {
+ currentTab.closeFind(mFindDialog);
+ mFindDialog.dismiss();
+ }
+ if (!mXLargeScreenSize) {
+ // If the Find was being performed in the main WebView, replace the
+ // embedded title bar.
+ 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 dialog. Now that the dialog has been removed, show the fake
+ // title bar once again.
+ showFakeTitleBar();
+ }
}
@Override
@@ -1551,7 +1615,7 @@
inflater.inflate(R.menu.browsercontext, menu);
// Show the correct menu group
- String extra = result.getExtra();
+ final String extra = result.getExtra();
menu.setGroupVisible(R.id.PHONE_MENU,
type == WebView.HitTestResult.PHONE_TYPE);
menu.setGroupVisible(R.id.EMAIL_MENU,
@@ -1608,8 +1672,23 @@
titleView.setText(extra);
menu.setHeaderView(titleView);
// decide whether to show the open link in new tab option
- menu.findItem(R.id.open_newtab_context_menu_id).setVisible(
- mTabControl.canCreateNewTab());
+ boolean showNewTab = mTabControl.canCreateNewTab();
+ MenuItem newTabItem
+ = menu.findItem(R.id.open_newtab_context_menu_id);
+ newTabItem.setVisible(showNewTab);
+ if (showNewTab) {
+ newTabItem.setOnMenuItemClickListener(
+ new MenuItem.OnMenuItemClickListener() {
+ public boolean onMenuItemClick(MenuItem item) {
+ final Tab parent = mTabControl.getCurrentTab();
+ final Tab newTab = openTab(extra);
+ if (newTab != parent) {
+ parent.addChildTab(newTab);
+ }
+ return true;
+ }
+ });
+ }
menu.findItem(R.id.bookmark_context_menu_id).setVisible(
Bookmarks.urlHasAcceptableScheme(extra));
PackageManager pm = getPackageManager();
@@ -1660,8 +1739,10 @@
ViewGroup.LayoutParams.WRAP_CONTENT));
}
- WebView view = t.getWebView();
- view.setEmbeddedTitleBar(mTitleBar);
+ if (!mXLargeScreenSize){
+ WebView view = t.getWebView();
+ view.setEmbeddedTitleBar(mTitleBar);
+ }
if (t.isInVoiceSearchMode()) {
showVoiceTitleBar(t.getVoiceDisplayTitle());
} else {
@@ -1687,9 +1768,11 @@
mErrorConsoleContainer.removeView(errorConsole);
}
- WebView view = t.getWebView();
- if (view != null) {
- view.setEmbeddedTitleBar(null);
+ if (!mXLargeScreenSize) {
+ WebView view = t.getWebView();
+ if (view != null) {
+ view.setEmbeddedTitleBar(null);
+ }
}
}
@@ -1919,7 +2002,9 @@
// If we are in voice search mode, the title has already been set.
if (mTabControl.getCurrentTab().isInVoiceSearchMode()) return;
mTitleBar.setDisplayTitle(url);
- mFakeTitleBar.setDisplayTitle(url);
+ if (!mXLargeScreenSize) {
+ mFakeTitleBar.setDisplayTitle(url);
+ }
}
/**
@@ -1962,7 +2047,9 @@
// Set the favicon in the title bar.
void setFavicon(Bitmap icon) {
mTitleBar.setFavicon(icon);
- mFakeTitleBar.setFavicon(icon);
+ if (!mXLargeScreenSize) {
+ mFakeTitleBar.setFavicon(icon);
+ }
}
/**
@@ -2192,13 +2279,6 @@
case R.id.view_image_context_menu_id:
loadUrlFromContext(getTopWindow(), url);
break;
- case R.id.open_newtab_context_menu_id:
- final Tab parent = mTabControl.getCurrentTab();
- final Tab newTab = openTab(url);
- if (newTab != parent) {
- parent.addChildTab(newTab);
- }
- break;
case R.id.bookmark_context_menu_id:
Intent intent = new Intent(BrowserActivity.this,
AddBookmarkPage.class);
@@ -2207,41 +2287,8 @@
startActivity(intent);
break;
case R.id.share_link_context_menu_id:
- // See if this site has been visited before
- StringBuilder sb = new StringBuilder(
- Browser.BookmarkColumns.URL + " = ");
- DatabaseUtils.appendEscapedSQLString(sb, url);
- Cursor c = mResolver.query(Browser.BOOKMARKS_URI,
- Browser.HISTORY_PROJECTION,
- sb.toString(),
- null,
+ sharePage(BrowserActivity.this, title, url, null,
null);
- if (c.moveToFirst()) {
- // The site has been visited before, so grab the
- // info from the database.
- Bitmap favicon = null;
- Bitmap thumbnail = null;
- String linkTitle = c.getString(Browser.
- HISTORY_PROJECTION_TITLE_INDEX);
- byte[] data = c.getBlob(Browser.
- HISTORY_PROJECTION_FAVICON_INDEX);
- if (data != null) {
- favicon = BitmapFactory.decodeByteArray(
- data, 0, data.length);
- }
- data = c.getBlob(Browser.
- HISTORY_PROJECTION_THUMBNAIL_INDEX);
- if (data != null) {
- thumbnail = BitmapFactory.decodeByteArray(
- data, 0, data.length);
- }
- sharePage(BrowserActivity.this,
- linkTitle, url, favicon, thumbnail);
- } else {
- Browser.sendString(BrowserActivity.this, url,
- getString(
- R.string.choosertitle_sharevia));
- }
break;
case R.id.copy_link_context_menu_id:
copy(url);
@@ -2462,7 +2509,9 @@
onProgressChanged(view, INITIAL_PROGRESS);
mDidStopLoad = false;
if (!mIsNetworkUp) createAndShowNetworkDialog();
-
+ if (view.getFindIsUp()) {
+ closeFind();
+ }
if (mSettings.isTracing()) {
String host;
try {
@@ -2642,7 +2691,14 @@
// -------------------------------------------------------------------------
void onProgressChanged(WebView view, int newProgress) {
- mFakeTitleBar.setProgress(newProgress);
+ if (mXLargeScreenSize) {
+ mTitleBar.setProgress(newProgress);
+ } else {
+ // On the phone, the fake title bar will always cover up the
+ // regular title bar (or the regular one is offscreen), so only the
+ // fake title bar needs to change its progress
+ mFakeTitleBar.setProgress(newProgress);
+ }
if (newProgress == 100) {
// onProgressChanged() may continue to be called after the main
@@ -2743,15 +2799,85 @@
* The Object used to inform the WebView of the file to upload.
*/
private ValueCallback<Uri> mUploadMessage;
+ private String mCameraFilePath;
- void openFileChooser(ValueCallback<Uri> uploadMsg) {
+ void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType) {
+
+ final String imageMimeType = "image/*";
+ final String imageSourceKey = "source";
+ final String imageSourceValueCamera = "camera";
+ final String imageSourceValueGallery = "gallery";
+
+ // image source can be 'gallery' or 'camera'.
+ String imageSource = "";
+
+ // We add the camera intent if there was no accept type (or '*/*') or 'image/*'.
+ boolean addCameraIntent = true;
+
if (mUploadMessage != null) return;
mUploadMessage = uploadMsg;
+
+ // Parse the accept type.
+ String params[] = acceptType.split(";");
+ String mimeType = params[0];
+
+ for (String p : params) {
+ String[] keyValue = p.split("=");
+ if (keyValue.length == 2) {
+ // Process key=value parameters.
+ if (imageSourceKey.equals(keyValue[0])) {
+ imageSource = keyValue[1];
+ }
+ }
+ }
+
+ // This intent will display the standard OPENABLE file picker.
Intent i = new Intent(Intent.ACTION_GET_CONTENT);
i.addCategory(Intent.CATEGORY_OPENABLE);
- i.setType("*/*");
- BrowserActivity.this.startActivityForResult(Intent.createChooser(i,
- getString(R.string.choose_upload)), FILE_SELECTED);
+
+ // Create an intent to add to the standard file picker that will
+ // capture an image from the camera. We'll combine this intent with
+ // the standard OPENABLE picker unless the web developer specifically
+ // requested the camera or gallery be opened by passing a parameter
+ // in the accept type.
+ Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
+ File externalDataDir = Environment.getExternalStoragePublicDirectory(
+ Environment.DIRECTORY_DCIM);
+ File cameraDataDir = new File(externalDataDir.getAbsolutePath() +
+ File.separator + "browser-photos");
+ cameraDataDir.mkdirs();
+ mCameraFilePath = cameraDataDir.getAbsolutePath() + File.separator +
+ System.currentTimeMillis() + ".jpg";
+ cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(new File(mCameraFilePath)));
+
+ if (mimeType.equals(imageMimeType)) {
+ i.setType(imageMimeType);
+ if (imageSource.equals(imageSourceValueCamera)) {
+ // Specified 'image/*' and requested the camera, so go ahead and launch the camera
+ // directly.
+ BrowserActivity.this.startActivityForResult(cameraIntent, FILE_SELECTED);
+ return;
+ } else if (imageSource.equals(imageSourceValueGallery)) {
+ // Specified gallery as the source, so don't want to consider the camera.
+ addCameraIntent = false;
+ }
+ } else {
+ i.setType("*/*");
+ }
+
+ // Combine the chooser and the extra choices (like camera)
+ Intent chooser = new Intent(Intent.ACTION_CHOOSER);
+ chooser.putExtra(Intent.EXTRA_INTENT, i);
+
+ if (addCameraIntent) {
+ // Add the camera Intent
+ Intent[] choices = new Intent[1];
+ choices[0] = cameraIntent;
+ chooser.putExtra(Intent.EXTRA_INITIAL_INTENTS, choices);
+ }
+
+ chooser.putExtra(Intent.EXTRA_TITLE, getString(R.string.choose_upload));
+ BrowserActivity.this.startActivityForResult(chooser, FILE_SELECTED);
}
// -------------------------------------------------------------------------
@@ -2952,7 +3078,9 @@
d = mMixLockIcon;
}
mTitleBar.setLock(d);
- mFakeTitleBar.setLock(d);
+ if (!mXLargeScreenSize) {
+ mFakeTitleBar.setLock(d);
+ }
}
/**
@@ -3468,8 +3596,26 @@
if (null == mUploadMessage) break;
Uri result = intent == null || resultCode != RESULT_OK ? null
: intent.getData();
+
+ // As we ask the camera to save the result of the user taking
+ // a picture, the camera application does not return anything other
+ // than RESULT_OK. So we need to check whether the file we expected
+ // was written to disk in the in the case that we
+ // did not get an intent returned but did get a RESULT_OK. If it was,
+ // we assume that this result has came back from the camera.
+ if (result == null && intent == null && resultCode == RESULT_OK) {
+ File cameraFile = new File(mCameraFilePath);
+ if (cameraFile.exists()) {
+ result = Uri.fromFile(cameraFile);
+ // Broadcast to the media scanner that we have a new photo
+ // so it will be added into the gallery for the user.
+ sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, result));
+ }
+ }
+
mUploadMessage.onReceiveValue(result);
mUploadMessage = null;
+ mCameraFilePath = null;
break;
default:
break;
diff --git a/src/com/android/browser/BrowserDownloadAdapter.java b/src/com/android/browser/BrowserDownloadAdapter.java
index 0f8f721..f22c9fe 100644
--- a/src/com/android/browser/BrowserDownloadAdapter.java
+++ b/src/com/android/browser/BrowserDownloadAdapter.java
@@ -26,6 +26,7 @@
import android.drm.mobile1.DrmRawContent;
import android.graphics.drawable.Drawable;
import android.net.Uri;
+import android.os.Handler;
import android.provider.Downloads;
import android.text.format.Formatter;
import android.view.LayoutInflater;
@@ -55,8 +56,9 @@
private int mMimetypeColumnId;
private int mDateColumnId;
- public BrowserDownloadAdapter(Context context, Cursor c, int index) {
- super(context, c, index);
+ public BrowserDownloadAdapter(Context context, Cursor c, int index,
+ Handler handler) {
+ super(context, c, index, handler);
mTitleColumnId = c.getColumnIndexOrThrow(Downloads.Impl.COLUMN_TITLE);
mDescColumnId = c.getColumnIndexOrThrow(Downloads.Impl.COLUMN_DESCRIPTION);
mStatusColumnId = c.getColumnIndexOrThrow(Downloads.Impl.COLUMN_STATUS);
diff --git a/src/com/android/browser/BrowserDownloadPage.java b/src/com/android/browser/BrowserDownloadPage.java
index 18faf8b..bbf1191 100644
--- a/src/com/android/browser/BrowserDownloadPage.java
+++ b/src/com/android/browser/BrowserDownloadPage.java
@@ -63,6 +63,7 @@
// Only meaningful while a ContentObserver is registered. The ContextMenu
// will be reopened on this View.
private View mSelectedView;
+ private Handler mHandler;
private final static String LOGTAG = "BrowserDownloadPage";
@Override
@@ -85,7 +86,7 @@
Downloads.Impl._DATA,
Downloads.Impl.COLUMN_MIME_TYPE},
null, Downloads.Impl.COLUMN_LAST_MODIFICATION + " DESC");
-
+ mHandler = new Handler();
// only attach everything to the listbox if we can access
// the download database. Otherwise, just show it empty
if (mDownloadCursor != null) {
@@ -99,7 +100,7 @@
// Create a list "controller" for the data
mDownloadAdapter = new BrowserDownloadAdapter(this,
mDownloadCursor, mDownloadCursor.getColumnIndexOrThrow(
- Downloads.Impl.COLUMN_LAST_MODIFICATION));
+ Downloads.Impl.COLUMN_LAST_MODIFICATION), mHandler);
setListAdapter(mDownloadAdapter);
mListView.setOnCreateContextMenuListener(this);
@@ -241,8 +242,8 @@
*/
private class ChangeObserver extends ContentObserver {
private final Uri mTrack;
- public ChangeObserver(Uri track) {
- super(new Handler());
+ public ChangeObserver(Uri track, Handler handler) {
+ super(handler);
mTrack = track;
}
@@ -313,7 +314,7 @@
getContentResolver().unregisterContentObserver(
mContentObserver);
}
- mContentObserver = new ChangeObserver(track);
+ mContentObserver = new ChangeObserver(track, mHandler);
mSelectedView = v;
getContentResolver().registerContentObserver(track, false,
mContentObserver);
diff --git a/src/com/android/browser/BrowserHistoryPage.java b/src/com/android/browser/BrowserHistoryPage.java
index 23080f8..0281087 100644
--- a/src/com/android/browser/BrowserHistoryPage.java
+++ b/src/com/android/browser/BrowserHistoryPage.java
@@ -25,7 +25,10 @@
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
+import android.os.AsyncTask;
import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
import android.os.ServiceManager;
import android.provider.Browser;
import android.text.IClipboard;
@@ -92,47 +95,75 @@
}
}
+ private static final int ADAPTER_CREATED = 1000;
+ private Handler mHandler = new Handler() {
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case ADAPTER_CREATED:
+ mAdapter = (HistoryAdapter) msg.obj;
+ setListAdapter(mAdapter);
+ final ExpandableListView list = getExpandableListView();
+ // Add an empty view late, so it does not claim an empty
+ // history before the adapter is present
+ View v = new ViewStub(BrowserHistoryPage.this,
+ R.layout.empty_history);
+ addContentView(v, new LayoutParams(
+ LayoutParams.MATCH_PARENT,
+ LayoutParams.MATCH_PARENT));
+ list.setEmptyView(v);
+ list.setOnCreateContextMenuListener(
+ BrowserHistoryPage.this);
+ // Do not post the runnable if there is nothing in the list.
+ if (list.getExpandableListAdapter().getGroupCount() > 0) {
+ list.post(new Runnable() {
+ public void run() {
+ // In case the history gets cleared before this
+ // event happens
+ if (list.getExpandableListAdapter()
+ .getGroupCount() > 0) {
+ list.expandGroup(0);
+ }
+ }
+ });
+ }
+ break;
+ }
+ }
+ };
+
@Override
protected void onCreate(Bundle icicle) {
super.onCreate(icicle);
setTitle(R.string.browser_history);
- final String whereClause = Browser.BookmarkColumns.VISITS + " > 0"
- // In AddBookmarkPage, where we save new bookmarks, we add
- // three visits to newly created bookmarks, so that
- // bookmarks that have not been visited will show up in the
- // most visited, and higher in the goto search box.
- // However, this puts the site in the history, unless we
- // ignore sites with a DATE of 0, which the next line does.
- + " AND " + Browser.BookmarkColumns.DATE + " > 0";
- final String orderBy = Browser.BookmarkColumns.DATE + " DESC";
+ new AsyncTask<Void, Void, Void>() {
+ @Override
+ protected Void doInBackground(Void... unused) {
+ final String whereClause = Browser.BookmarkColumns.VISITS
+ + " > 0"
+ // In AddBookmarkPage, where we save new bookmarks, we
+ // add three visits to newly created bookmarks, so that
+ // bookmarks that have not been visited will show up in
+ // the most visited, and higher in the goto search box.
+ // However, this puts the site in the history, unless
+ // we ignore sites with a DATE of 0, which the next
+ // line does.
+ + " AND " + Browser.BookmarkColumns.DATE + " > 0";
+ final String orderBy = Browser.BookmarkColumns.DATE + " DESC";
- Cursor cursor = managedQuery(
- Browser.BOOKMARKS_URI,
- Browser.HISTORY_PROJECTION,
- whereClause, null, orderBy);
+ Cursor cursor = managedQuery(
+ Browser.BOOKMARKS_URI,
+ Browser.HISTORY_PROJECTION,
+ whereClause, null, orderBy);
- mAdapter = new HistoryAdapter(this, cursor,
- Browser.HISTORY_PROJECTION_DATE_INDEX);
- setListAdapter(mAdapter);
- final ExpandableListView list = getExpandableListView();
- list.setOnCreateContextMenuListener(this);
- View v = new ViewStub(this, R.layout.empty_history);
- addContentView(v, new LayoutParams(LayoutParams.MATCH_PARENT,
- LayoutParams.MATCH_PARENT));
- list.setEmptyView(v);
- // Do not post the runnable if there is nothing in the list.
- if (list.getExpandableListAdapter().getGroupCount() > 0) {
- list.post(new Runnable() {
- public void run() {
- // In case the history gets cleared before this event
- // happens.
- if (list.getExpandableListAdapter().getGroupCount() > 0) {
- list.expandGroup(0);
- }
- }
- });
- }
+ HistoryAdapter adapter = new HistoryAdapter(
+ BrowserHistoryPage.this, cursor,
+ Browser.HISTORY_PROJECTION_DATE_INDEX, mHandler);
+ mHandler.obtainMessage(ADAPTER_CREATED, adapter).sendToTarget();
+ return null;
+ }
+ }.execute();
mDisableNewWindow = getIntent().getBooleanExtra("disable_new_window",
false);
@@ -153,6 +184,7 @@
@Override
protected void onDestroy() {
+ mHandler.removeCallbacksAndMessages(null);
super.onDestroy();
CombinedBookmarkHistoryActivity.getIconListenerSet()
.removeListener(mIconReceiver);
@@ -181,7 +213,7 @@
// CombinedBookmarkHistoryActivity
((CombinedBookmarkHistoryActivity) getParent())
.removeParentChildRelationShips();
- mAdapter.refreshData();
+ if (mAdapter != null) mAdapter.refreshData();
return true;
default:
@@ -265,7 +297,7 @@
return true;
case R.id.delete_context_menu_id:
Browser.deleteFromHistory(getContentResolver(), url);
- mAdapter.refreshData();
+ if (mAdapter != null) mAdapter.refreshData();
return true;
case R.id.homepage_context_menu_id:
BrowserSettings.getInstance().setHomePage(this, url);
@@ -297,8 +329,9 @@
}
private class HistoryAdapter extends DateSortedExpandableListAdapter {
- HistoryAdapter(Context context, Cursor cursor, int index) {
- super(context, cursor, index);
+ HistoryAdapter(Context context, Cursor cursor, int index,
+ Handler handler) {
+ super(context, cursor, index, handler);
}
diff --git a/src/com/android/browser/DateSortedExpandableListAdapter.java b/src/com/android/browser/DateSortedExpandableListAdapter.java
index 1d04493..f8261d8 100644
--- a/src/com/android/browser/DateSortedExpandableListAdapter.java
+++ b/src/com/android/browser/DateSortedExpandableListAdapter.java
@@ -51,8 +51,8 @@
private Context mContext;
private class ChangeObserver extends ContentObserver {
- public ChangeObserver() {
- super(new Handler());
+ public ChangeObserver(Handler handler) {
+ super(handler);
}
@Override
@@ -67,13 +67,13 @@
}
public DateSortedExpandableListAdapter(Context context, Cursor cursor,
- int dateIndex) {
+ int dateIndex, Handler handler) {
mContext = context;
mDateSorter = new DateSorter(context);
mObservers = new Vector<DataSetObserver>();
mCursor = cursor;
mIdIndex = cursor.getColumnIndexOrThrow(BaseColumns._ID);
- cursor.registerContentObserver(new ChangeObserver());
+ cursor.registerContentObserver(new ChangeObserver(handler));
mDateIndex = dateIndex;
buildMap();
}
diff --git a/src/com/android/browser/FindDialog.java b/src/com/android/browser/FindDialog.java
index 45c8016..bcd5bb7 100644
--- a/src/com/android/browser/FindDialog.java
+++ b/src/com/android/browser/FindDialog.java
@@ -16,24 +16,24 @@
package com.android.browser;
-import android.app.Dialog;
import android.content.Context;
-import android.os.Bundle;
import android.text.Editable;
+import android.text.Selection;
import android.text.Spannable;
import android.text.TextWatcher;
import android.view.Gravity;
import android.view.KeyEvent;
+import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
-import android.view.Window;
-import android.view.WindowManager;
+import android.view.animation.AnimationUtils;
import android.view.inputmethod.InputMethodManager;
import android.webkit.WebView;
import android.widget.EditText;
+import android.widget.LinearLayout;
import android.widget.TextView;
-/* package */ class FindDialog extends Dialog implements TextWatcher {
+/* package */ class FindDialog extends LinearLayout implements TextWatcher {
private WebView mWebView;
private TextView mMatches;
private BrowserActivity mBrowserActivity;
@@ -44,6 +44,11 @@
private View mPrevButton;
private View mMatchesView;
+ // When the dialog is opened up with old text, enter needs to be pressed
+ // (or the text needs to be changed) before WebView.findAll can be called.
+ // Once it has been called, enter should move to the next match.
+ private boolean mMatchesFound;
+ private int mNumberOfMatches;
private View.OnClickListener mFindListener = new View.OnClickListener() {
public void onClick(View v) {
findNext();
@@ -53,7 +58,7 @@
private View.OnClickListener mFindCancelListener =
new View.OnClickListener() {
public void onClick(View v) {
- dismiss();
+ mBrowserActivity.closeFind();
}
};
@@ -64,6 +69,7 @@
throw new AssertionError("No WebView for FindDialog::onClick");
}
mWebView.findNext(false);
+ updateMatchesString();
hideSoftInput();
}
};
@@ -89,22 +95,11 @@
}
/* package */ FindDialog(BrowserActivity context) {
- super(context, R.style.FindDialogTheme);
+ super(context);
mBrowserActivity = context;
- setCanceledOnTouchOutside(true);
- }
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- Window theWindow = getWindow();
- theWindow.setGravity(Gravity.BOTTOM|Gravity.FILL_HORIZONTAL);
-
- setContentView(R.layout.browser_find);
-
- theWindow.setLayout(ViewGroup.LayoutParams.MATCH_PARENT,
- ViewGroup.LayoutParams.WRAP_CONTENT);
+ LayoutInflater factory = LayoutInflater.from(context);
+ factory.inflate(R.layout.browser_find, this);
mEditText = (EditText) findViewById(R.id.edit);
@@ -122,23 +117,57 @@
mMatches = (TextView) findViewById(R.id.matches);
mMatchesView = findViewById(R.id.matches_view);
disableButtons();
- theWindow.setSoftInputMode(
- WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE);
+
}
-
+
+ /**
+ * Called by BrowserActivity.closeFind. Start the animation to hide
+ * the dialog, inform the WebView that the dialog is being dismissed,
+ * and hide the soft keyboard.
+ */
public void dismiss() {
- super.dismiss();
- mBrowserActivity.closeFind();
mWebView.notifyFindDialogDismissed();
+ startAnimation(AnimationUtils.loadAnimation(mBrowserActivity,
+ R.anim.find_dialog_exit));
+ hideSoftInput();
+ }
+
+ @Override
+ public boolean dispatchKeyEventPreIme(KeyEvent event) {
+ if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
+ KeyEvent.DispatcherState state = getKeyDispatcherState();
+ if (state != null) {
+ int action = event.getAction();
+ if (KeyEvent.ACTION_DOWN == action
+ && event.getRepeatCount() == 0) {
+ state.startTracking(event, this);
+ return true;
+ } else if (KeyEvent.ACTION_UP == action
+ && !event.isCanceled() && state.isTracking(event)) {
+ mBrowserActivity.closeFind();
+ return true;
+ }
+ }
+ }
+ return super.dispatchKeyEventPreIme(event);
}
@Override
public boolean dispatchKeyEvent(KeyEvent event) {
- if (event.getKeyCode() == KeyEvent.KEYCODE_ENTER
- && event.getAction() == KeyEvent.ACTION_UP
- && mEditText.hasFocus()) {
- findNext();
- return true;
+ int keyCode = event.getKeyCode();
+ if (event.getAction() == KeyEvent.ACTION_UP) {
+ if (keyCode == KeyEvent.KEYCODE_ENTER
+ && mEditText.hasFocus()) {
+ if (mMatchesFound) {
+ findNext();
+ } else {
+ findAll();
+ // Set the selection to the end.
+ Spannable span = (Spannable) mEditText.getText();
+ Selection.setSelection(span, span.length());
+ }
+ return true;
+ }
}
return super.dispatchKeyEvent(event);
}
@@ -148,18 +177,27 @@
throw new AssertionError("No WebView for FindDialog::findNext");
}
mWebView.findNext(true);
+ updateMatchesString();
hideSoftInput();
}
public void show() {
- super.show();
+ // In case the matches view is showing from a previous search
+ mMatchesView.setVisibility(View.INVISIBLE);
+ mMatchesFound = false;
+ // This text is only here to ensure that mMatches has a height.
+ mMatches.setText("0");
mEditText.requestFocus();
- mEditText.setText("");
Spannable span = (Spannable) mEditText.getText();
- span.setSpan(this, 0, span.length(),
- Spannable.SPAN_INCLUSIVE_INCLUSIVE);
- setMatchesFound(0);
+ int length = span.length();
+ Selection.setSelection(span, 0, length);
+ span.setSpan(this, 0, length, Spannable.SPAN_INCLUSIVE_INCLUSIVE);
disableButtons();
+ startAnimation(AnimationUtils.loadAnimation(mBrowserActivity,
+ R.anim.find_dialog_enter));
+ InputMethodManager imm = (InputMethodManager)
+ mBrowserActivity.getSystemService(Context.INPUT_METHOD_SERVICE);
+ imm.showSoftInput(mEditText, 0);
}
// TextWatcher methods
@@ -173,9 +211,13 @@
int start,
int before,
int count) {
+ findAll();
+ }
+
+ private void findAll() {
if (mWebView == null) {
throw new AssertionError(
- "No WebView for FindDialog::onTextChanged");
+ "No WebView for FindDialog::findAll");
}
CharSequence find = mEditText.getText();
if (0 == find.length()) {
@@ -184,14 +226,16 @@
mMatchesView.setVisibility(View.INVISIBLE);
} else {
mMatchesView.setVisibility(View.VISIBLE);
- mWebView.setFindDialogHeight(
- getWindow().getDecorView().getHeight());
int found = mWebView.findAll(find.toString());
+ mMatchesFound = true;
setMatchesFound(found);
if (found < 2) {
disableButtons();
if (found == 0) {
- setMatchesFound(0);
+ // Cannot use getQuantityString, which ignores the "zero"
+ // quantity.
+ mMatches.setText(mBrowserActivity.getResources().getString(
+ R.string.no_matches));
}
} else {
mPrevButton.setFocusable(true);
@@ -203,8 +247,16 @@
}
private void setMatchesFound(int found) {
+ mNumberOfMatches = found;
+ updateMatchesString();
+ }
+
+ private void updateMatchesString() {
+ // Note: updateMatchesString is only called by methods that have already
+ // checked mWebView for null.
String template = mBrowserActivity.getResources().
- getQuantityString(R.plurals.matches_found, found, found);
+ getQuantityString(R.plurals.matches_found, mNumberOfMatches,
+ mWebView.findIndex() + 1, mNumberOfMatches);
mMatches.setText(template);
}
diff --git a/src/com/android/browser/Tab.java b/src/com/android/browser/Tab.java
index 5350a18..79c4574 100644
--- a/src/com/android/browser/Tab.java
+++ b/src/com/android/browser/Tab.java
@@ -87,7 +87,7 @@
// The Geolocation permissions prompt
private GeolocationPermissionsPrompt mGeolocationPermissionsPrompt;
// Main WebView wrapper
- private View mContainer;
+ private LinearLayout mContainer;
// Main WebView
private WebView mMainView;
// Subwindow container
@@ -1173,9 +1173,9 @@
}
@Override
- public void openFileChooser(ValueCallback<Uri> uploadMsg) {
+ public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType) {
if (mInForeground) {
- mActivity.openFileChooser(uploadMsg);
+ mActivity.openFileChooser(uploadMsg, acceptType);
} else {
uploadMsg.onReceiveValue(null);
}
@@ -1208,9 +1208,18 @@
private static class SubWindowClient extends WebViewClient {
// The main WebViewClient.
private final WebViewClient mClient;
+ private final BrowserActivity mBrowserActivity;
- SubWindowClient(WebViewClient client) {
+ SubWindowClient(WebViewClient client, BrowserActivity activity) {
mClient = client;
+ mBrowserActivity = activity;
+ }
+ @Override
+ public void onPageStarted(WebView view, String url, Bitmap favicon) {
+ // Unlike the others, do not call mClient's version, which would
+ // change the progress bar. However, we do want to remove the
+ // find dialog.
+ if (view.getFindIsUp()) mBrowserActivity.closeFind();
}
@Override
public void doUpdateVisitedHistory(WebView view, String url,
@@ -1300,7 +1309,7 @@
// The tab consists of a container view, which contains the main
// WebView, as well as any other UI elements associated with the tab.
- mContainer = mInflateService.inflate(R.layout.tab, null);
+ mContainer = (LinearLayout) mInflateService.inflate(R.layout.tab, null);
mDownloadListener = new DownloadListener() {
public void onDownloadStart(String url, String userAgent,
@@ -1411,6 +1420,7 @@
*/
boolean createSubWindow() {
if (mSubView == null) {
+ if (mMainView.getFindIsUp()) mActivity.closeFind();
mSubViewContainer = mInflateService.inflate(
R.layout.browser_subwindow, null);
mSubView = (WebView) mSubViewContainer.findViewById(R.id.webview);
@@ -1419,7 +1429,8 @@
mSubView.setMapTrackballToArrowKeys(false);
// Enable the built-in zoom
mSubView.getSettings().setBuiltInZoomControls(true);
- mSubView.setWebViewClient(new SubWindowClient(mWebViewClient));
+ mSubView.setWebViewClient(new SubWindowClient(mWebViewClient,
+ mActivity));
mSubView.setWebChromeClient(new SubWindowChromeClient(
mWebChromeClient));
// Set a different DownloadListener for the mSubView, since it will
@@ -1457,6 +1468,9 @@
*/
void dismissSubWindow() {
if (mSubView != null) {
+ if (mSubView.getFindIsUp()) {
+ mActivity.closeFind();
+ }
BrowserSettings.getInstance().deleteObserver(
mSubView.getSettings());
mSubView.destroy();
@@ -1481,6 +1495,7 @@
void removeSubWindow(ViewGroup content) {
if (mSubView != null) {
content.removeView(mSubViewContainer);
+ if (mSubView.getFindIsUp()) mActivity.closeFind();
}
}
@@ -1539,6 +1554,7 @@
(FrameLayout) mContainer.findViewById(R.id.webview_wrapper);
wrapper.removeView(mMainView);
content.removeView(mContainer);
+ if (mMainView.getFindIsUp()) mActivity.closeFind();
removeSubWindow(content);
}
@@ -1812,6 +1828,9 @@
// FIXME: The only place we cared about subwindow was for
// bookmarking (i.e. not when saving state). Was this deliberate?
final WebBackForwardList list = mMainView.copyBackForwardList();
+ if (list == null) {
+ Log.w(LOGTAG, "populatePickerData called and WebBackForwardList is null");
+ }
final WebHistoryItem item = list != null ? list.getCurrentItem() : null;
populatePickerData(item);
}
@@ -1820,7 +1839,9 @@
// WebView.
private void populatePickerData(WebHistoryItem item) {
mPickerData = new PickerData();
- if (item != null) {
+ if (item == null) {
+ Log.w(LOGTAG, "populatePickerData called with a null WebHistoryItem");
+ } else {
mPickerData.mUrl = item.getUrl();
mPickerData.mTitle = item.getTitle();
mPickerData.mFavicon = item.getFavicon();
@@ -1934,4 +1955,36 @@
}
return true;
}
+
+ /*
+ * Open the find dialog. Called by BrowserActivity.
+ */
+ void showFind(FindDialog dialog) {
+ LinearLayout container;
+ WebView view;
+ if (mSubView != null) {
+ view = mSubView;
+ container = (LinearLayout) mSubViewContainer.findViewById(
+ R.id.inner_container);
+ } else {
+ view = mMainView;
+ container = mContainer;
+ }
+ dialog.show();
+ container.addView(dialog, 0, new LinearLayout.LayoutParams(
+ ViewGroup.LayoutParams.MATCH_PARENT,
+ ViewGroup.LayoutParams.WRAP_CONTENT));
+ dialog.setWebView(view);
+ view.setFindIsUp(true);
+ }
+
+ /*
+ * Close the find dialog. Called by BrowserActivity.closeFind.
+ */
+ void closeFind(FindDialog dialog) {
+ // The dialog may be attached to the subwindow. Ensure that the
+ // correct parent has it removed.
+ LinearLayout parent = (LinearLayout) dialog.getParent();
+ if (parent != null) parent.removeView(dialog);
+ }
}
diff --git a/tests/assets/bindings_test.html b/tests/assets/bindings_test.html
index c20ccec..71f3438 100755
--- a/tests/assets/bindings_test.html
+++ b/tests/assets/bindings_test.html
@@ -175,7 +175,7 @@
function runTests() {
// Assume that if the test isn't done after 10s that we failed.
- window.setTimeout(function() { JNIBindingsTest.testComplete(); }, 10000);
+ window.setTimeout(function() { JNIBindingsTest.notifyComplete(); }, 10000);
if (testPrimitiveTypes()) {
appendLog("testPrimitiveTypes passed!");
@@ -231,7 +231,7 @@
appendLog("testParameterTypeMismatch failed!");
}
- JNIBindingsTest.testComplete();
+ JNIBindingsTest.notifyComplete();
}
</script>
diff --git a/tests/src/com/android/browser/JNIBindingsTest.java b/tests/src/com/android/browser/JNIBindingsTest.java
index bfa3ac1..ba3c66a 100644
--- a/tests/src/com/android/browser/JNIBindingsTest.java
+++ b/tests/src/com/android/browser/JNIBindingsTest.java
@@ -20,6 +20,7 @@
import android.util.Log;
import java.util.Arrays;
+
import junit.framework.AssertionFailedError;
public class JNIBindingsTest extends AndroidTestCase {
@@ -34,9 +35,9 @@
mTestApp = testApp;
}
- public void testComplete() {
+ public void notifyComplete() {
Log.v(LOGTAG, "Completing the test.");
- mTestApp.testComplete();
+ mTestApp.notifyComplete();
}
public void printAssertionFailed(AssertionFailedError e) {
@@ -232,7 +233,7 @@
assertEquals(expectedIntParam, intParam);
assertEquals(expectedDoubleParam, doubleParam);
assertEquals(expectedBooleanParam, booleanParam);
- assertEquals(expectedCharParam, charParam);;
+ assertEquals(expectedCharParam, charParam);
// EMULATE_JSC_BINDINGS JSC passes "undefined" for undefined types.
assertEquals(expectedUndefinedParam, undefinedParam);
diff --git a/tests/src/com/android/browser/JNIBindingsTestApp.java b/tests/src/com/android/browser/JNIBindingsTestApp.java
index e01aca2..4f083f6 100644
--- a/tests/src/com/android/browser/JNIBindingsTestApp.java
+++ b/tests/src/com/android/browser/JNIBindingsTestApp.java
@@ -18,7 +18,6 @@
import android.app.Instrumentation;
import android.net.http.SslError;
-import android.os.Environment;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
@@ -29,6 +28,12 @@
import android.webkit.SslErrorHandler;
import android.webkit.WebView;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
/**
* Adds a JavaScript interface to the webview and calls functions on it to verify variables
* are passed from JS to Java correctly.
@@ -37,6 +42,8 @@
private final static String TAG = "JNIBindingsTest";
+ private static final String SDCARD_BINDINGS_TEST_HTML = "/sdcard/bindings_test.html";
+
private static final int MSG_WEBKIT_DATA_READY = 101;
private BrowserActivity mActivity = null;
@@ -67,9 +74,11 @@
mWebView = webView;
}
+ @Override
public void run() {
Looper.prepare();
mHandler = new Handler() {
+ @Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_WEBKIT_DATA_READY: {
@@ -102,6 +111,32 @@
mInst = getInstrumentation();
mInst.waitForIdleSync();
+ extractAsset();
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ removeAsset();
+ super.tearDown();
+ }
+
+ protected void extractAsset() throws IOException {
+ InputStream in = getInstrumentation().getContext().getAssets().open("bindings_test.html");
+ OutputStream out = new FileOutputStream(SDCARD_BINDINGS_TEST_HTML);
+
+ byte[] buf = new byte[2048];
+ int len;
+
+ while ((len = in.read(buf)) >= 0 ) {
+ out.write(buf, 0, len);
+ }
+ out.close();
+ in.close();
+ }
+
+ protected void removeAsset(){
+ File fileToDelete = new File(SDCARD_BINDINGS_TEST_HTML);
+ fileToDelete.delete();
}
/**
@@ -183,7 +218,7 @@
});
}
- public synchronized void testComplete() {
+ public synchronized void notifyComplete() {
mTestDone = true;
notify();
}
@@ -193,7 +228,7 @@
Tab tab = mActivity.getTabControl().getCurrentTab();
WebView webView = tab.getWebView();
- webView.loadUrl("file:///sdcard/bindings_test.html");
+ webView.loadUrl("file://" + SDCARD_BINDINGS_TEST_HTML);
synchronized(this) {
while(!mTestDone) {
try {
diff --git a/tests/src/com/android/browser/TestWebChromeClient.java b/tests/src/com/android/browser/TestWebChromeClient.java
index d78eaed..53f8db3 100644
--- a/tests/src/com/android/browser/TestWebChromeClient.java
+++ b/tests/src/com/android/browser/TestWebChromeClient.java
@@ -195,7 +195,7 @@
/** {@inheritDoc} */
@Override
- public void openFileChooser(ValueCallback<Uri> uploadFile) {
- mWrappedClient.openFileChooser(uploadFile);
+ public void openFileChooser(ValueCallback<Uri> uploadFile, String acceptType) {
+ mWrappedClient.openFileChooser(uploadFile, acceptType);
}
}