Re-implement UserAgent in browser

- Remove calls to SWE's WebSetting API and use the newer implementation of
  the engine. The newer implementation tracks UserAgent per navigation
  entry.
- Allow to override the UserAgent using command line switches.
- Remove debug option to change UserAgent string.
- BrowserConfig class cleanup.

Change-Id: Ib1cc4763e0cbf0207793d1f4e6b1644a9dbb5c08
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 190f690..61f4c36 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -587,23 +587,6 @@
     <!-- Do not tranlsate.  Development option -->
     <string name="pref_development_uastring" translatable="false">UAString</string>
     <!-- Do not tranlsate.  Development option -->
-    <string-array name="pref_development_ua_choices" translatable="false">
-        <item>Android</item>
-        <item>Desktop</item>
-        <item>iPhone</item>
-        <item>iPad</item>
-        <item>Froyo-N1</item>
-        <item>Honeycomb-Xoom</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>
-        <item>5</item>
-    </string-array>
     <string name="pref_development_error_console" translatable="false">Show JavaScript Console</string>
     <!-- Do not translate. Development option to reset the prologin time [CHAR LIMIT=20] -->
     <string name="pref_development_reset_prelogin" translatable="false">Reset prelogin</string>
diff --git a/res/xml/debug_preferences.xml b/res/xml/debug_preferences.xml
index 8e169bd..3ab9b90 100644
--- a/res/xml/debug_preferences.xml
+++ b/res/xml/debug_preferences.xml
@@ -14,7 +14,7 @@
      limitations under the License.
 -->
 
-<PreferenceScreen 
+<PreferenceScreen
         xmlns:android="http://schemas.android.com/apk/res/android" >
 
     <CheckBoxPreference
@@ -28,13 +28,6 @@
         android:title="@string/pref_development_hardware_accel_skia"
         android:enabled="false" />
 
-    <ListPreference
-        android:key="user_agent"
-        android:title="@string/pref_development_uastring"
-        android:entries="@array/pref_development_ua_choices"
-        android:entryValues="@array/pref_development_ua_values"
-        android:defaultValue="0"/>
-
     <CheckBoxPreference
         android:key="enable_visual_indicator"
         android:defaultValue="false"
diff --git a/src/com/android/browser/BrowserConfigBase.java b/src/com/android/browser/BrowserConfigBase.java
new file mode 100644
index 0000000..c81e593
--- /dev/null
+++ b/src/com/android/browser/BrowserConfigBase.java
@@ -0,0 +1,84 @@
+/*
+    * Copyright (c) 2014, The Linux Foundation. All rights reserved.
+    *
+    * Redistribution and use in source and binary forms, with or without
+    * modification, are permitted provided that the following conditions are
+    * met:
+    * * Redistributions of source code must retain the above copyright
+    * notice, this list of conditions and the following disclaimer.
+    * * Redistributions in binary form must reproduce the above
+    * copyright notice, this list of conditions and the following
+    * disclaimer in the documentation and/or other materials provided
+    * with the distribution.
+    * * Neither the name of The Linux Foundation nor the names of its
+    * contributors may be used to endorse or promote products derived
+    * from this software without specific prior written permission.
+    *
+    * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+    * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+    * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+    * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+    * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+    * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+    * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+    * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+    * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+    * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+    * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+    *
+    */
+
+package com.android.browser;
+
+import com.android.browser.R;
+
+import java.util.Locale;
+
+import android.os.Build;
+import android.content.Context;
+import android.text.TextUtils;
+
+import org.codeaurora.swe.BrowserCommandLine;
+
+abstract class BrowserConfigBase {
+
+    private static final String OVERRIDE_USER_AGENT = "user-agent";
+    private Context mContext;
+
+    public BrowserConfigBase(Context context) {
+        mContext = context;
+    }
+
+    public void overrideUserAgent() {
+        BrowserCommandLine bcl = BrowserCommandLine.getInstance();
+        // Check if the UA is already present using command line file
+        if (bcl.hasSwitch(OVERRIDE_USER_AGENT)) {
+            return;
+        }
+
+        String ua = mContext.getResources().getString(R.string.def_useragent);
+
+        if (TextUtils.isEmpty(ua))
+            return;
+
+        ua = constructUserAgent(ua);
+
+        if (!TextUtils.isEmpty(ua)){
+            bcl.appendSwitchWithValue(OVERRIDE_USER_AGENT, ua);
+        }
+    }
+
+    private String constructUserAgent(String userAgent) {
+        try {
+            userAgent = userAgent.replaceAll("<%build_model>", Build.MODEL);
+            userAgent = userAgent.replaceAll("<%build_version>", Build.VERSION.RELEASE);
+            userAgent = userAgent.replaceAll("<%build_id>", Build.ID);
+            userAgent = userAgent.replaceAll("<%language>", Locale.getDefault().getLanguage());
+            userAgent = userAgent.replaceAll("<%country>", Locale.getDefault().getCountry());
+            return userAgent;
+        } catch (Exception ex) {
+            return null;
+        }
+    }
+}
+
diff --git a/src/com/android/browser/BrowserPreferencesPage.java b/src/com/android/browser/BrowserPreferencesPage.java
index 09d815e..353a472 100644
--- a/src/com/android/browser/BrowserPreferencesPage.java
+++ b/src/com/android/browser/BrowserPreferencesPage.java
@@ -111,6 +111,7 @@
         "com.android.browser.preferences.LabPreferencesFragment",
         "com.android.browser.preferences.AboutPreferencesFragment",
         "com.android.browser.AutoFillSettingsFragment",
+        "com.android.browser.preferences.DebugPreferencesFragment",
         "com.android.browser.preferences.WebsiteSettingsFragment"));
 
     @Override
diff --git a/src/com/android/browser/BrowserSettings.java b/src/com/android/browser/BrowserSettings.java
index 255aaf8..7e07721 100644
--- a/src/com/android/browser/BrowserSettings.java
+++ b/src/com/android/browser/BrowserSettings.java
@@ -40,7 +40,6 @@
 import java.lang.ref.WeakReference;
 import java.util.Iterator;
 import java.util.LinkedList;
-import java.util.Locale;
 import java.util.WeakHashMap;
 
 import org.codeaurora.swe.AutoFillProfile;
@@ -60,35 +59,6 @@
 public class BrowserSettings implements OnSharedPreferenceChangeListener,
         PreferenceKeys {
 
-    // TODO: Do something with this UserAgent stuff
-    private static final String DESKTOP_USERAGENT = "Mozilla/5.0 (X11; " +
-        "Linux x86_64) AppleWebKit/534.24 (KHTML, like Gecko) " +
-        "Chrome/11.0.696.34 Safari/534.24";
-
-    private static final String IPHONE_USERAGENT = "Mozilla/5.0 (iPhone; U; " +
-        "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";
-
-    private static final String HONEYCOMB_USERAGENT = "Mozilla/5.0 (Linux; U; " +
-        "Android 3.1; en-us; Xoom Build/HMJ25) AppleWebKit/534.13 " +
-        "(KHTML, like Gecko) Version/4.0 Safari/534.13";
-
-    private static final String USER_AGENTS[] = { null,
-            DESKTOP_USERAGENT,
-            IPHONE_USERAGENT,
-            IPAD_USERAGENT,
-            FROYO_USERAGENT,
-            HONEYCOMB_USERAGENT,
-    };
-
     private static final String TAG = "BrowserSettings";
     // The minimum min font size
     // Aka, the lower bounds for the min font size range
@@ -113,7 +83,6 @@
     private Controller mController;
     private WebStorageSizeManager mWebStorageSizeManager;
     private AutofillHandler mAutofillHandler;
-    private WeakHashMap<WebSettings, String> mCustomUserAgents;
     private static boolean sInitialized = false;
     private boolean mNeedsSharedSync = true;
     private float mFontSizeMult = 1.0f;
@@ -146,7 +115,6 @@
         mContext = context.getApplicationContext();
         mPrefs = PreferenceManager.getDefaultSharedPreferences(mContext);
         mManagedSettings = new LinkedList<WeakReference<WebSettings>>();
-        mCustomUserAgents = new WeakHashMap<WebSettings, String>();
         BackgroundHandler.execute(mSetup);
     }
 
@@ -290,7 +258,6 @@
         settings.setSaveFormData(saveFormdata());
         settings.setUseWideViewPort(isWideViewport());
         settings.setDoNotTrack(doNotTrack());
-        setUserAgent(settings);
         settings.setMediaPlaybackRequiresUserGesture(false);
         settings.setAllowMediaDownloads(allowMediaDownloads());
         setExtraHTTPRequestHeaders(settings);
@@ -318,22 +285,6 @@
         settingsClassic.setLinkPrefetchEnabled(mLinkPrefetchAllowed);
     }
 
-    private void setUserAgent(WebSettings settings){
-        String ua = mContext.getResources().getString(R.string.def_useragent);
-
-        if (!TextUtils.isEmpty(ua))
-            ua = constructUserAgent(ua);
-
-        if (TextUtils.isEmpty(ua))
-            ua = mCustomUserAgents.get(settings);
-
-        if (!TextUtils.isEmpty(ua)){
-            settings.setUserAgentString(ua);
-        } else {
-            settings.setUserAgentString(USER_AGENTS[getUserAgent()]);
-        }
-    }
-
     private void setExtraHTTPRequestHeaders(WebSettings settings){
         String headers = mContext.getResources().getString(R.string.def_extra_http_headers);
         if (!TextUtils.isEmpty(headers)){
@@ -341,19 +292,6 @@
         }
     }
 
-    private String constructUserAgent(String userAgent) {
-        try {
-            userAgent = userAgent.replaceAll("<%build_model>", Build.MODEL);
-            userAgent = userAgent.replaceAll("<%build_version>", Build.VERSION.RELEASE);
-            userAgent = userAgent.replaceAll("<%build_id>", Build.ID);
-            userAgent = userAgent.replaceAll("<%language>", Locale.getDefault().getLanguage());
-            userAgent = userAgent.replaceAll("<%country>", Locale.getDefault().getCountry());
-            return userAgent;
-        } catch (Exception ex) {
-            return null;
-        }
-    }
-
     /**
      * Syncs all the settings that have no UI
      * These cannot change, so we only need to set them once per WebSettings
@@ -650,21 +588,17 @@
     }
 
     public boolean hasDesktopUseragent(WebView view) {
-        return view != null && mCustomUserAgents.get(view.getSettings()) != null;
+        return view != null && view.getUseDesktopUserAgent();
     }
 
     public void toggleDesktopUseragent(WebView view) {
         if (view == null) {
             return;
         }
-        WebSettings settings = view.getSettings();
-        if (mCustomUserAgents.get(settings) != null) {
-            mCustomUserAgents.remove(settings);
-            setUserAgent(settings);
-        } else {
-            mCustomUserAgents.put(settings, DESKTOP_USERAGENT);
-            settings.setUserAgentString(DESKTOP_USERAGENT);
-        }
+        if (hasDesktopUseragent(view))
+            view.setUseDesktopUserAgent(false, true);
+        else
+            view.setUseDesktopUserAgent(true, true);
     }
 
     public static int getAdjustedMinimumFontSize(int rawValue) {
@@ -878,13 +812,6 @@
         return mPrefs.getBoolean(PREF_ENABLE_HARDWARE_ACCEL_SKIA, false);
     }
 
-    public int getUserAgent() {
-        if (!isDebugEnabled()) {
-            return 0;
-        }
-        return Integer.parseInt(mPrefs.getString(PREF_USER_AGENT, "0"));
-    }
-
     // -----------------------------
     // getter/setters for hidden_debug_preferences.xml
     // -----------------------------
diff --git a/src/com/android/browser/CrashLogExceptionHandler.java b/src/com/android/browser/CrashLogExceptionHandler.java
index 9207570..67beaab 100644
--- a/src/com/android/browser/CrashLogExceptionHandler.java
+++ b/src/com/android/browser/CrashLogExceptionHandler.java
@@ -82,7 +82,7 @@
 
     public CrashLogExceptionHandler(Context ctx) {
         mAppContext = ctx;
-        BrowserCommandLine cl = new BrowserCommandLine();
+        BrowserCommandLine cl = BrowserCommandLine.getInstance();
         if (cl.hasSwitch(CRASH_LOG_SERVER_CMD)) {
             mLogServer = cl.getSwitchValue(CRASH_LOG_SERVER_CMD);
             if (mLogServer != null) {
diff --git a/src/com/android/browser/EngineInitializer.java b/src/com/android/browser/EngineInitializer.java
index 10cbc0d..7fa7b2a 100644
--- a/src/com/android/browser/EngineInitializer.java
+++ b/src/com/android/browser/EngineInitializer.java
@@ -202,6 +202,8 @@
         if (!mInitializationCompleted) {
             // TODO: Evaluate the benefit of async Engine.initialize()
             Engine.initialize(ctx);
+            // Add the UA override
+            BrowserConfig.getInstance(ctx).overrideUserAgent();
             //Enable remote debugging by default
             Engine.setWebContentsDebuggingEnabled(true);
             mInitializationCompleted = true;
diff --git a/src/com/android/browser/PreferenceKeys.java b/src/com/android/browser/PreferenceKeys.java
index 6f2acd4..7dde8b2 100644
--- a/src/com/android/browser/PreferenceKeys.java
+++ b/src/com/android/browser/PreferenceKeys.java
@@ -55,7 +55,6 @@
     // ----------------------
     static final String PREF_ENABLE_HARDWARE_ACCEL = "enable_hardware_accel";
     static final String PREF_ENABLE_HARDWARE_ACCEL_SKIA = "enable_hardware_accel_skia";
-    static final String PREF_USER_AGENT = "user_agent";
 
     // ----------------------
     // Keys for general_preferences.xml
diff --git a/src_standalone/com/android/browser/BrowserConfig.java b/src_standalone/com/android/browser/BrowserConfig.java
index 6dce1e2..4b8b095 100644
--- a/src_standalone/com/android/browser/BrowserConfig.java
+++ b/src_standalone/com/android/browser/BrowserConfig.java
@@ -31,10 +31,25 @@
 
 package com.android.browser;
 
-public class BrowserConfig {
+import android.content.Context;
+
+public class BrowserConfig extends BrowserConfigBase {
 
     //Authority string used by different providers
     public final static String AUTHORITY = "com.android.swe.browser";
 
+    private static BrowserConfig sBrowserConfig;
+
+    private BrowserConfig(Context context) {
+        super(context);
+    }
+
+    public static BrowserConfig getInstance(Context context) {
+        if (sBrowserConfig == null) {
+            sBrowserConfig = new BrowserConfig(context);
+        }
+        return sBrowserConfig;
+    }
+
 }
 
diff --git a/src_system/com/android/browser/BrowserConfig.java b/src_system/com/android/browser/BrowserConfig.java
index 59d907c..10e30a9 100644
--- a/src_system/com/android/browser/BrowserConfig.java
+++ b/src_system/com/android/browser/BrowserConfig.java
@@ -30,9 +30,24 @@
 
 package com.android.browser;
 
-public class BrowserConfig {
+import android.content.Context;
+
+public class BrowserConfig extends BrowserConfigBase {
 
     public final static String AUTHORITY = "com.android.browser";
 
+    private static BrowserConfig sBrowserConfig;
+
+    private BrowserConfig(Context context) {
+        super(context);
+    }
+
+    public static BrowserConfig getInstance(Context context) {
+        if (sBrowserConfig == null) {
+            sBrowserConfig = new BrowserConfig(context);
+        }
+        return sBrowserConfig;
+    }
+
 }