merge from open-source master

Change-Id: Idcbf7a3a8e9c171b62c210ad174b63dfed3ed42c
diff --git a/Android.mk b/Android.mk
index 6e20ab8..e015dda 100644
--- a/Android.mk
+++ b/Android.mk
@@ -12,6 +12,8 @@
 
 LOCAL_PACKAGE_NAME := Browser
 
+LOCAL_EMMA_COVERAGE_FILTER := *,-com.android.common.*
+
 include $(BUILD_PACKAGE)
 
 # additionally, build tests in sub-folders in a separate .apk
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 18a2144..07c2eb9 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -450,12 +450,16 @@
         <item>Android</item>
         <item>Desktop</item>
         <item>iPhone</item>
+        <item>iPad</item>
+        <item>Froyo-N1</item>
     </string-array>
     <!-- Do not tranlsate.  Development option -->
     <string-array name="pref_development_ua_values" translatable="false">
         <item>0</item>
         <item>1</item>
         <item>2</item>
+        <item>3</item>
+        <item>4</item>
     </string-array>
     <string name="pref_development_error_console" translatable="false">Show JavaScript Console</string>
     <!-- Settings screen, setting option name -->
diff --git a/src/com/android/browser/BrowserSettings.java b/src/com/android/browser/BrowserSettings.java
index 3d5ca03..769dfca 100644
--- a/src/com/android/browser/BrowserSettings.java
+++ b/src/com/android/browser/BrowserSettings.java
@@ -137,12 +137,20 @@
             "privacy_clear_geolocation_access";
 
     private static final String DESKTOP_USERAGENT = "Mozilla/5.0 (Macintosh; " +
-            "U; Intel Mac OS X 10_5_7; en-us) AppleWebKit/530.17 (KHTML, " +
-            "like Gecko) Version/4.0 Safari/530.17";
+            "U; Intel Mac OS X 10_6_3; en-us) AppleWebKit/533.16 (KHTML, " +
+            "like Gecko) Version/5.0 Safari/533.16";
 
     private static final String IPHONE_USERAGENT = "Mozilla/5.0 (iPhone; U; " +
-            "CPU iPhone OS 3_0 like Mac OS X; en-us) AppleWebKit/528.18 " +
-            "(KHTML, like Gecko) Version/4.0 Mobile/7A341 Safari/528.16";
+            "CPU iPhone OS 4_0 like Mac OS X; en-us) AppleWebKit/532.9 " +
+            "(KHTML, like Gecko) Version/4.0.5 Mobile/8A293 Safari/6531.22.7";
+
+    private static final String IPAD_USERAGENT = "Mozilla/5.0 (iPad; U; " +
+            "CPU OS 3_2 like Mac OS X; en-us) AppleWebKit/531.21.10 " +
+            "(KHTML, like Gecko) Version/4.0.4 Mobile/7B367 Safari/531.21.10";
+
+    private static final String FROYO_USERAGENT = "Mozilla/5.0 (Linux; U; " +
+            "Android 2.2; en-us; Nexus One Build/FRF91) AppleWebKit/533.1 " +
+            "(KHTML, like Gecko) Version/4.0 Mobile Safari/533.1";
 
     // Value to truncate strings when adding them to a TextView within
     // a ListView
@@ -182,6 +190,10 @@
                 s.setUserAgentString(DESKTOP_USERAGENT);
             } else if (b.userAgent == 2) {
                 s.setUserAgentString(IPHONE_USERAGENT);
+            } else if (b.userAgent == 3) {
+                s.setUserAgentString(IPAD_USERAGENT);
+            } else if (b.userAgent == 4) {
+                s.setUserAgentString(FROYO_USERAGENT);
             }
             s.setUseWideViewPort(b.useWideViewPort);
             s.setLoadsImagesAutomatically(b.loadsImagesAutomatically);
diff --git a/src/com/android/browser/Tab.java b/src/com/android/browser/Tab.java
index b31abc2..5795b05 100644
--- a/src/com/android/browser/Tab.java
+++ b/src/com/android/browser/Tab.java
@@ -171,8 +171,8 @@
         return mVoiceSearchData != null;
     }
     /**
-     * Return true if the voice search Intent came with a String identifying
-     * that Google provided the Intent.
+     * Return true if the Tab is in voice search mode and the voice search
+     * Intent came with a String identifying that Google provided the Intent.
      */
     public boolean voiceSearchSourceIsGoogle() {
         return mVoiceSearchData != null && mVoiceSearchData.mSourceIsGoogle;
@@ -529,6 +529,18 @@
         // return true if want to hijack the url to let another app to handle it
         @Override
         public boolean shouldOverrideUrlLoading(WebView view, String url) {
+            if (voiceSearchSourceIsGoogle()) {
+                // This method is called when the user clicks on a link.
+                // VoiceSearchMode is turned off when the user leaves the
+                // Google results page, so at this point the user must be on
+                // that page.  If the user clicked a link on that page, assume
+                // that the voice search was effective, and broadcast an Intent
+                // so a receiver can take note of that fact.
+                Intent logIntent = new Intent(LoggingEvents.ACTION_LOG_EVENT);
+                logIntent.putExtra(LoggingEvents.EXTRA_EVENT,
+                        LoggingEvents.VoiceSearch.RESULT_CLICKED);
+                mActivity.sendBroadcast(logIntent);
+            }
             if (mInForeground) {
                 return mActivity.shouldOverrideUrlLoading(view, url);
             } else {
@@ -1433,7 +1445,7 @@
                     if (mSubView.copyBackForwardList().getSize() == 0) {
                         // This subwindow was opened for the sole purpose of
                         // downloading a file. Remove it.
-                        dismissSubWindow();
+                        mActivity.dismissSubWindow(Tab.this);
                     }
                 }
             });
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/PopularUrlsTest.java b/tests/src/com/android/browser/PopularUrlsTest.java
index d3806a0..5b8cb86 100644
--- a/tests/src/com/android/browser/PopularUrlsTest.java
+++ b/tests/src/com/android/browser/PopularUrlsTest.java
@@ -16,19 +16,6 @@
 
 package com.android.browser;
 
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.FileReader;
-import java.io.FileWriter;
-import java.io.IOException;
-import java.io.OutputStreamWriter;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
-
 import android.app.Instrumentation;
 import android.content.Intent;
 import android.net.Uri;
@@ -42,6 +29,19 @@
 import android.webkit.SslErrorHandler;
 import android.webkit.WebView;
 
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.OutputStreamWriter;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
 /**
  *
  * Iterates over a list of URLs from a file and outputs the time to load each.
@@ -423,6 +423,9 @@
                     bufferedReader.close();
                 }
             }
+        } catch (FileNotFoundException fnfe) {
+            Log.e(TAG, fnfe.getMessage(), fnfe);
+            fail("Test environment not setup correctly");
         } finally {
             if (writer != null) {
                 writer.close();
@@ -436,6 +439,9 @@
         BufferedReader bufferedReader = getInputStream();
         try {
             loopUrls(bufferedReader, null, true, STABILITY_LOOPCOUNT);
+        } catch (FileNotFoundException fnfe) {
+            Log.e(TAG, fnfe.getMessage(), fnfe);
+            fail("Test environment not setup correctly");
         } finally {
             if (bufferedReader != null) {
                 bufferedReader.close();