merge fx-team to mozilla-central a=merge
authorCarsten "Tomcat" Book <cbook@mozilla.com>
Thu, 08 Jan 2015 14:36:19 +0100
changeset 248443 f90dccb788edcd7e311bc52986dbaa70668b776f
parent 248433 2880e05d5e3241105c1874fd364a7f50e0d334c3 (current diff)
parent 248442 5419d08cbe98e194eac13a9c03284a57ae71961a (diff)
child 248465 d480b3542cc24bf1b964469d790ed0ab69fda5cb
push id4489
push userraliiev@mozilla.com
push dateMon, 23 Feb 2015 15:17:55 +0000
treeherdermozilla-beta@fd7c3dc24146 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone37.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
merge fx-team to mozilla-central a=merge
--- a/browser/components/loop/standalone/content/libs/l10n-gaia-02ca67948fe8.js
+++ b/browser/components/loop/standalone/content/libs/l10n-gaia-02ca67948fe8.js
@@ -1236,21 +1236,29 @@
 
       return locales[code] = new Locale(code, this);
     };
 
 
     // Getting ready
 
     function negotiate(available, requested, defaultLocale) {
-      if (available.indexOf(requested[0]) === -1 ||
-          requested[0] === defaultLocale) {
+      var supportedLocale;
+      for (var i = 0; i < requested.length; ++i) {
+        var locale = requested[i];
+        if (available.indexOf(locale) !== -1) {
+          supportedLocale = locale;
+          break;
+        }
+      }
+      if (!supportedLocale ||
+          supportedLocale === defaultLocale) {
         return [defaultLocale];
       } else {
-        return [requested[0], defaultLocale];
+        return [supportedLocale, defaultLocale];
       }
     }
 
     function freeze(supported) {
       var locale = this.getLocale(supported[0]);
       if (locale.isReady) {
         setReady.call(this, supported);
       } else {
--- a/mobile/android/app/mobile.js
+++ b/mobile/android/app/mobile.js
@@ -731,16 +731,21 @@ pref("memory.free_dirty_pages", true);
 pref("layout.imagevisibility.numscrollportwidths", 1);
 pref("layout.imagevisibility.numscrollportheights", 1);
 
 pref("layers.enable-tiles", true);
 
 // Enable the dynamic toolbar
 pref("browser.chrome.dynamictoolbar", true);
 
+// The mode of browser titlebar
+// 0: Show a current page title.
+// 1: Show a current page url.
+pref("browser.chrome.titlebarMode", 1);
+
 // Hide common parts of URLs like "www." or "http://"
 pref("browser.urlbar.trimURLs", true);
 
 #ifdef MOZ_PKG_SPECIAL
 // Disable webgl on ARMv6 because running the reftests takes
 // too long for some reason (bug 843738)
 pref("webgl.disabled", true);
 #endif
--- a/mobile/android/base/BrowserApp.java
+++ b/mobile/android/base/BrowserApp.java
@@ -1195,23 +1195,23 @@ public class BrowserApp extends GeckoApp
         GeckoAppShell.openUriExternal(url, "text/plain", "", "",
                                       Intent.ACTION_SEND, tab.getDisplayTitle());
 
         // Context: Sharing via chrome list (no explicit session is active)
         Telemetry.sendUIEvent(TelemetryContract.Event.SHARE, TelemetryContract.Method.LIST);
     }
 
     @Override
-    protected void loadStartupTab(String url) {
+    protected void loadStartupTab(String url, int flags) {
         // We aren't showing about:home, so cancel the telemetry timer
         if (url != null || mShouldRestore) {
             mAboutHomeStartupTimer.cancel();
         }
 
-        super.loadStartupTab(url);
+        super.loadStartupTab(url, flags);
     }
 
     private void setToolbarMargin(int margin) {
         ((RelativeLayout.LayoutParams) mGeckoLayout.getLayoutParams()).topMargin = margin;
         mGeckoLayout.requestLayout();
     }
 
     @Override
--- a/mobile/android/base/GeckoApp.java
+++ b/mobile/android/base/GeckoApp.java
@@ -137,17 +137,16 @@ public abstract class GeckoApp
     }
 
     public static final String ACTION_ALERT_CALLBACK       = "org.mozilla.gecko.ACTION_ALERT_CALLBACK";
     public static final String ACTION_HOMESCREEN_SHORTCUT  = "org.mozilla.gecko.BOOKMARK";
     public static final String ACTION_DEBUG                = "org.mozilla.gecko.DEBUG";
     public static final String ACTION_LAUNCH_SETTINGS      = "org.mozilla.gecko.SETTINGS";
     public static final String ACTION_LOAD                 = "org.mozilla.gecko.LOAD";
     public static final String ACTION_INIT_PW              = "org.mozilla.gecko.INIT_PW";
-    public static final String ACTION_WEBAPP_PREFIX        = "org.mozilla.gecko.WEBAPP";
 
     public static final String EXTRA_STATE_BUNDLE          = "stateBundle";
 
     public static final String PREFS_ALLOW_STATE_BUNDLE    = "allowStateBundle";
     public static final String PREFS_OOM_EXCEPTION         = "OOMException";
     public static final String PREFS_VERSION_CODE          = "versionCode";
     public static final String PREFS_WAS_STOPPED           = "wasStopped";
     public static final String PREFS_CRASHED               = "crashed";
@@ -1434,26 +1433,25 @@ public abstract class GeckoApp
      * Loads the initial tab at Fennec startup.
      *
      * If Fennec was opened with an external URL, that URL will be loaded.
      * Otherwise, unless there was a session restore, the default URL
      * (about:home) be loaded.
      *
      * @param url External URL to load, or null to load the default URL
      */
-    protected void loadStartupTab(String url) {
+    protected void loadStartupTab(String url, int flags) {
         if (url == null) {
             if (!mShouldRestore) {
                 // Show about:home if we aren't restoring previous session and
                 // there's no external URL.
-                Tabs.getInstance().loadUrl(AboutPages.HOME, Tabs.LOADURL_NEW_TAB);
+                Tabs.getInstance().loadUrl(AboutPages.HOME, flags);
             }
         } else {
             // If given an external URL, load it
-            int flags = Tabs.LOADURL_NEW_TAB | Tabs.LOADURL_USER_ENTERED | Tabs.LOADURL_EXTERNAL;
             Tabs.getInstance().loadUrl(url, flags);
         }
     }
 
     private void initialize() {
         mInitialized = true;
 
         final SafeIntent intent = new SafeIntent(getIntent());
@@ -1510,20 +1508,24 @@ public abstract class GeckoApp
         }
 
         // External URLs should always be loaded regardless of whether Gecko is
         // already running.
         if (isExternalURL) {
             // Restore tabs before opening an external URL so that the new tab
             // is animated properly.
             Tabs.getInstance().notifyListeners(null, Tabs.TabEvents.RESTORED);
-            loadStartupTab(passedUri);
+            int flags = Tabs.LOADURL_NEW_TAB | Tabs.LOADURL_USER_ENTERED | Tabs.LOADURL_EXTERNAL;
+            if (ACTION_HOMESCREEN_SHORTCUT.equals(action)) {
+                flags |= Tabs.LOADURL_PINNED;
+            }
+            loadStartupTab(passedUri, flags);
         } else {
             if (!mIsRestoringActivity) {
-                loadStartupTab(null);
+                loadStartupTab(null, Tabs.LOADURL_NEW_TAB);
             }
 
             Tabs.getInstance().notifyListeners(null, Tabs.TabEvents.RESTORED);
         }
 
         // If we're not restoring, move the session file so it can be read for
         // the last tabs section.
         if (!mShouldRestore) {
@@ -1844,22 +1846,16 @@ public abstract class GeckoApp
         if (ACTION_LOAD.equals(action)) {
             String uri = intent.getDataString();
             Tabs.getInstance().loadUrl(uri);
         } else if (Intent.ACTION_VIEW.equals(action)) {
             String uri = intent.getDataString();
             Tabs.getInstance().loadUrl(uri, Tabs.LOADURL_NEW_TAB |
                                             Tabs.LOADURL_USER_ENTERED |
                                             Tabs.LOADURL_EXTERNAL);
-        } else if (action != null && action.startsWith(ACTION_WEBAPP_PREFIX)) {
-            // A lightweight mechanism for loading a web page as a webapp
-            // without installing the app natively nor registering it in the DOM
-            // application registry.
-            String uri = getURIFromIntent(intent);
-            GeckoAppShell.sendEventToGecko(GeckoEvent.createWebappLoadEvent(uri));
         } else if (ACTION_HOMESCREEN_SHORTCUT.equals(action)) {
             String uri = getURIFromIntent(intent);
             GeckoAppShell.sendEventToGecko(GeckoEvent.createBookmarkLoadEvent(uri));
         } else if (Intent.ACTION_SEARCH.equals(action)) {
             String uri = getURIFromIntent(intent);
             GeckoAppShell.sendEventToGecko(GeckoEvent.createURILoadEvent(uri));
         } else if (ACTION_ALERT_CALLBACK.equals(action)) {
             processAlertCallback(intent);
--- a/mobile/android/base/GeckoEvent.java
+++ b/mobile/android/base/GeckoEvent.java
@@ -714,23 +714,16 @@ public class GeckoEvent {
 
     public static GeckoEvent createURILoadEvent(String uri) {
         GeckoEvent event = GeckoEvent.get(NativeGeckoEvent.LOAD_URI);
         event.mCharacters = uri;
         event.mCharactersExtra = "";
         return event;
     }
 
-    public static GeckoEvent createWebappLoadEvent(String uri) {
-        GeckoEvent event = GeckoEvent.get(NativeGeckoEvent.LOAD_URI);
-        event.mCharacters = uri;
-        event.mCharactersExtra = "-webapp";
-        return event;
-    }
-
     public static GeckoEvent createBookmarkLoadEvent(String uri) {
         GeckoEvent event = GeckoEvent.get(NativeGeckoEvent.LOAD_URI);
         event.mCharacters = uri;
         event.mCharactersExtra = "-bookmark";
         return event;
     }
 
     public static GeckoEvent createVisitedEvent(String data) {
--- a/mobile/android/base/GeckoThread.java
+++ b/mobile/android/base/GeckoThread.java
@@ -115,19 +115,16 @@ public class GeckoThread extends Thread 
         GeckoLoader.loadNSSLibs(context, resourcePath);
         GeckoLoader.loadGeckoLibs(context, resourcePath);
         GeckoJavaSampler.setLibsLoaded();
 
         return resourcePath;
     }
 
     private String getTypeFromAction(String action) {
-        if (action != null && action.startsWith(GeckoApp.ACTION_WEBAPP_PREFIX)) {
-            return "-webapp";
-        }
         if (GeckoApp.ACTION_HOMESCREEN_SHORTCUT.equals(action)) {
             return "-bookmark";
         }
         return null;
     }
 
     private String addCustomProfileArg(String args) {
         String profileArg = "";
--- a/mobile/android/base/locales/en-US/android_strings.dtd
+++ b/mobile/android/base/locales/en-US/android_strings.dtd
@@ -113,17 +113,17 @@
 <!ENTITY overlay_share_send_tab_btn_label "Send to another device">
 <!ENTITY overlay_share_no_url "No link found in this share">
 <!ENTITY overlay_share_retry "Try again">
 <!ENTITY overlay_share_select_device "Select device">
 
 <!ENTITY pref_category_search3 "Search">
 <!ENTITY pref_category_search_summary "Customize your search providers">
 <!ENTITY pref_category_display "Display">
-<!ENTITY pref_category_display_summary2 "Text, full-screen browsing">
+<!ENTITY pref_category_display_summary "Text, title bar, full-screen browsing">
 <!ENTITY pref_category_privacy_short "Privacy">
 <!ENTITY pref_category_privacy_summary "Control passwords, cookies, tracking, data">
 <!ENTITY pref_category_vendor "&vendorShortName;">
 <!ENTITY pref_category_vendor_summary "About &brandShortName;, FAQs, data choices">
 <!ENTITY pref_category_datareporting "Data choices">
 <!ENTITY pref_learn_more "Learn more">
 <!ENTITY pref_category_installed_search_engines "Installed search engines">
 <!ENTITY pref_category_add_search_providers "Add more search providers">
@@ -332,16 +332,20 @@ size. -->
 <!ENTITY contextmenu_edit_bookmark "Edit">
 <!ENTITY contextmenu_subscribe "Subscribe to Page">
 <!ENTITY contextmenu_site_settings "Edit Site Settings">
 <!ENTITY contextmenu_top_sites_edit "Edit">
 <!ENTITY contextmenu_top_sites_pin "Pin Site">
 <!ENTITY contextmenu_top_sites_unpin "Unpin Site">
 <!ENTITY contextmenu_add_search_engine "Add a Search Engine">
 
+<!ENTITY pref_titlebar_mode "Title bar">
+<!ENTITY pref_titlebar_mode_title "Show page title">
+<!ENTITY pref_titlebar_mode_url "Show page address">
+
 <!-- Localization note (pref_scroll_title_bar2): Label for setting that controls
      whether or not the dynamic toolbar is enabled. -->
 <!ENTITY pref_scroll_title_bar2 "Full-screen browsing">
 <!ENTITY pref_scroll_title_bar_summary "Hide the &brandShortName; title bar when scrolling down a page">
 
 <!-- Localization note (page_removed): This string appears in a toast message when
      any page is removed frome about:home. This includes pages that are in history,
      bookmarks, or reading list. -->
--- a/mobile/android/base/preferences/GeckoPreferences.java
+++ b/mobile/android/base/preferences/GeckoPreferences.java
@@ -24,17 +24,16 @@ import org.mozilla.gecko.GeckoActivitySt
 import org.mozilla.gecko.GeckoAppShell;
 import org.mozilla.gecko.GeckoApplication;
 import org.mozilla.gecko.GeckoEvent;
 import org.mozilla.gecko.GeckoProfile;
 import org.mozilla.gecko.GeckoSharedPrefs;
 import org.mozilla.gecko.GuestSession;
 import org.mozilla.gecko.LocaleManager;
 import org.mozilla.gecko.Locales;
-import org.mozilla.gecko.NewTabletUI;
 import org.mozilla.gecko.PrefsHelper;
 import org.mozilla.gecko.R;
 import org.mozilla.gecko.RestrictedProfiles;
 import org.mozilla.gecko.Telemetry;
 import org.mozilla.gecko.TelemetryContract;
 import org.mozilla.gecko.TelemetryContract.Method;
 import org.mozilla.gecko.background.common.GlobalConstants;
 import org.mozilla.gecko.background.healthreport.HealthReportConstants;
@@ -116,16 +115,17 @@ OnSharedPreferenceChangeListener
     private static final String PREFS_MENU_CHAR_ENCODING = "browser.menu.showCharacterEncoding";
     private static final String PREFS_MP_ENABLED = "privacy.masterpassword.enabled";
     private static final String PREFS_UPDATER_AUTODOWNLOAD = "app.update.autodownload";
     private static final String PREFS_GEO_REPORTING = NON_PREF_PREFIX + "app.geo.reportdata";
     private static final String PREFS_GEO_LEARN_MORE = NON_PREF_PREFIX + "geo.learn_more";
     private static final String PREFS_HEALTHREPORT_LINK = NON_PREF_PREFIX + "healthreport.link";
     private static final String PREFS_DEVTOOLS_REMOTE_ENABLED = "devtools.debugger.remote-enabled";
     private static final String PREFS_DISPLAY_REFLOW_ON_ZOOM = "browser.zoom.reflowOnZoom";
+    private static final String PREFS_DISPLAY_TITLEBAR_MODE = "browser.chrome.titlebarMode";
     private static final String PREFS_SYNC = NON_PREF_PREFIX + "sync";
     private static final String PREFS_TRACKING_PROTECTION = "privacy.trackingprotection.enabled";
     private static final String PREFS_TRACKING_PROTECTION_LEARN_MORE = NON_PREF_PREFIX + "trackingprotection.learn_more";
 
     private static final String ACTION_STUMBLER_UPLOAD_PREF = AppConstants.ANDROID_PACKAGE_NAME + ".STUMBLER_PREF";
 
     // This isn't a Gecko pref, even if it looks like one.
     private static final String PREFS_BROWSER_LOCALE = "locale";
@@ -727,16 +727,22 @@ OnSharedPreferenceChangeListener
                     pref.setOnPreferenceClickListener(new OnPreferenceClickListener() {
                         @Override
                         public boolean onPreferenceClick(Preference preference) {
                             GeckoPreferences.this.restoreDefaultSearchEngines();
                             Telemetry.sendUIEvent(TelemetryContract.Event.SEARCH_RESTORE_DEFAULTS, Method.LIST_ITEM);
                             return true;
                         }
                     });
+                } else if (PREFS_DISPLAY_TITLEBAR_MODE.equals(key) &&
+                           HardwareUtils.isTablet()) {
+                    // New tablet always shows URLS, not titles.
+                    preferences.removePreference(pref);
+                    i--;
+                    continue;
                 } else if (handlers.containsKey(key)) {
                     PrefHandler handler = handlers.get(key);
                     if (!handler.setupPref(this, pref)) {
                         preferences.removePreference(pref);
                         i--;
                         continue;
                     }
                 }
--- a/mobile/android/base/resources/values/arrays.xml
+++ b/mobile/android/base/resources/values/arrays.xml
@@ -133,17 +133,25 @@
         <item>@string/pref_update_autodownload_enabled</item>
         <item>@string/pref_update_autodownload_wifi</item>
         <item>@string/pref_update_autodownload_disabled</item>
     </string-array>
     <string-array name="pref_update_autodownload_values">
         <item>enabled</item>
         <item>wifi</item>
         <item>disabled</item>
-     </string-array>
+    </string-array>
+    <string-array name="pref_titlebar_mode_entries">
+        <item>@string/pref_titlebar_mode_title</item>
+        <item>@string/pref_titlebar_mode_url</item>
+    </string-array>
+    <string-array name="pref_titlebar_mode_values">
+        <item>0</item>
+        <item>1</item>
+    </string-array>
     <!-- This value is similar to config_longPressVibePattern in android frameworks/base/core/res/res/values/config.xml-->
     <integer-array name="long_press_vibrate_msec">
         <item>0</item>
         <item>1</item>
         <item>20</item>
         <item>21</item>
     </integer-array>
 </resources>
--- a/mobile/android/base/resources/xml/preferences_display.xml
+++ b/mobile/android/base/resources/xml/preferences_display.xml
@@ -10,16 +10,22 @@
 
     <org.mozilla.gecko.preferences.FontSizePreference
                     android:key="font.size.inflation.minTwips"
                     android:title="@string/pref_text_size"
                     android:positiveButtonText="@string/pref_font_size_set"
                     android:negativeButtonText="@string/button_cancel"
                     android:persistent="false" />
 
+    <ListPreference android:key="browser.chrome.titlebarMode"
+                    android:title="@string/pref_titlebar_mode"
+                    android:entries="@array/pref_titlebar_mode_entries"
+                    android:entryValues="@array/pref_titlebar_mode_values"
+                    android:persistent="false" />
+
     <CheckBoxPreference android:key="browser.chrome.dynamictoolbar"
                         android:title="@string/pref_scroll_title_bar2"
                         android:summary="@string/pref_scroll_title_bar_summary" />
 
     <CheckBoxPreference android:key="media.autoplay.enabled"
                         android:title="@string/pref_media_autoplay_enabled"
                         android:summary="@string/pref_media_autoplay_enabled_summary" />
 
--- a/mobile/android/base/strings.xml.in
+++ b/mobile/android/base/strings.xml.in
@@ -121,17 +121,17 @@
   <string name="settings">&settings;</string>
   <string name="settings_title">&settings_title;</string>
   <string name="pref_category_advanced">&pref_category_advanced;</string>
   <string name="pref_category_customize">&pref_category_customize;</string>
   <string name="pref_category_customize_summary">&pref_category_customize_summary;</string>
   <string name="pref_category_search">&pref_category_search3;</string>
   <string name="pref_category_search_summary">&pref_category_search_summary;</string>
   <string name="pref_category_display">&pref_category_display;</string>
-  <string name="pref_category_display_summary">&pref_category_display_summary2;</string>
+  <string name="pref_category_display_summary">&pref_category_display_summary;</string>
   <string name="pref_category_privacy_short">&pref_category_privacy_short;</string>
   <string name="pref_category_privacy_summary">&pref_category_privacy_summary;</string>
   <string name="pref_category_vendor">&pref_category_vendor;</string>
   <string name="pref_category_vendor_summary">&pref_category_vendor_summary;</string>
   <string name="pref_category_datareporting">&pref_category_datareporting;</string>
   <string name="pref_category_installed_search_engines">&pref_category_installed_search_engines;</string>
   <string name="pref_category_add_search_providers">&pref_category_add_search_providers;</string>
   <string name="pref_category_search_restore_defaults">&pref_category_search_restore_defaults;</string>
@@ -312,16 +312,20 @@
   <string name="contextmenu_edit_bookmark">&contextmenu_edit_bookmark;</string>
   <string name="contextmenu_subscribe">&contextmenu_subscribe;</string>
   <string name="contextmenu_site_settings">&contextmenu_site_settings;</string>
   <string name="contextmenu_top_sites_edit">&contextmenu_top_sites_edit;</string>
   <string name="contextmenu_top_sites_pin">&contextmenu_top_sites_pin;</string>
   <string name="contextmenu_top_sites_unpin">&contextmenu_top_sites_unpin;</string>
   <string name="contextmenu_add_search_engine">&contextmenu_add_search_engine;</string>
 
+  <string name="pref_titlebar_mode">&pref_titlebar_mode;</string>
+  <string name="pref_titlebar_mode_title">&pref_titlebar_mode_title;</string>
+  <string name="pref_titlebar_mode_url">&pref_titlebar_mode_url;</string>
+
   <string name="pref_scroll_title_bar2">&pref_scroll_title_bar2;</string>
   <string name="pref_scroll_title_bar_summary">&pref_scroll_title_bar_summary;</string>
 
   <string name="page_removed">&page_removed;</string>
 
   <string name="bookmark_edit_title">&bookmark_edit_title;</string>
   <string name="bookmark_edit_name">&bookmark_edit_name;</string>
   <string name="bookmark_edit_location">&bookmark_edit_location;</string>
--- a/mobile/android/base/sync/MigrationSentinelSyncStage.java
+++ b/mobile/android/base/sync/MigrationSentinelSyncStage.java
@@ -227,16 +227,18 @@ public class MigrationSentinelSyncStage 
     final InfoCollections infoCollections = session.config.infoCollections;
     if (infoCollections == null) {
       session.abort(null, "No info/collections set in MigrationSentinelSyncStage.");
       return;
     }
 
     final long lastModified = session.config.getLastMigrationSentinelCheckTimestamp();
     if (!infoCollections.updateNeeded(META_COLLECTION, lastModified)) {
+      Logger.info(LOG_TAG, "No need to check fresh meta/fxa_credentials.");
+      session.advance();
       return;
     }
 
     // Let's try a fetch.
     Logger.info(LOG_TAG, "Fetching meta/fxa_credentials to check for migration sentinel.");
     new MigrationChecker(session).check();
   }
 }
--- a/mobile/android/base/tests/robocop.ini
+++ b/mobile/android/base/tests/robocop.ini
@@ -88,16 +88,19 @@ skip-if = android_version == "10"
 [testSettingsMenuItems]
 # disabled on Android 2.3; bug 979552
 skip-if = android_version == "10"
 # [testShareLink] # see bug 915897
 [testSystemPages]
 # disabled on x86 and 2.3; bug 907383, 979603
 skip-if = android_version == "10" || processor == "x86"
 # [testThumbnails] # see bug 813107
+[testTitleBar]
+# disabled on Android 2.3; bug 979552
+skip-if = android_version == "10"
 # [testVkbOverlap] # see bug 907274
 
 # Using JavascriptTest
 [testAccounts]
 [testAndroidLog]
 [testBrowserDiscovery]
 [testDebuggerServer]
 [testDeviceSearchEngine]
new file mode 100644
--- /dev/null
+++ b/mobile/android/base/tests/testTitleBar.java
@@ -0,0 +1,58 @@
+package org.mozilla.gecko.tests;
+
+import org.mozilla.gecko.Actions;
+import org.mozilla.gecko.util.HardwareUtils;
+
+/**
+ * This patch tests the option that shows the full URL and title in the URL Bar
+ */
+
+public class testTitleBar extends PixelTest {
+    public void testTitleBar() {
+        // Because there is no title bar option on new tablet, we don't need to run this test.
+        if (HardwareUtils.isTablet()) {
+            return;
+        }
+
+        blockForGeckoReady();
+        checkOption();
+    }
+
+    public void checkOption() {
+
+        String blank1 = getAbsoluteUrl(StringHelper.ROBOCOP_BLANK_PAGE_01_URL);
+        String title = StringHelper.ROBOCOP_BLANK_PAGE_01_TITLE;
+
+        // Loading a page
+        inputAndLoadUrl(blank1);
+        verifyUrlBarTitle(blank1);
+
+        // Ensure the title is displayed in the URL Bar
+        selectOption(StringHelper.SHOW_PAGE_TITLE_LABEL);
+        inputAndLoadUrl(blank1);
+        verifyUrlBarTitle(title);
+
+        // Ensure the full URL is displayed in the URL Bar
+        selectOption(StringHelper.SHOW_PAGE_ADDRESS_LABEL);
+        inputAndLoadUrl(blank1);
+        verifyUrlBarTitle(blank1);
+    }
+
+    // Entering settings, changing the options: show title/page address option and verifing the device type because for phone there is an extra back action to exit the settings menu
+    public void selectOption(String option) {
+        selectSettingsItem(StringHelper.DISPLAY_SECTION_LABEL, StringHelper.TITLE_BAR_LABEL);
+        mAsserter.ok(waitForText(StringHelper.SHOW_PAGE_TITLE_LABEL), "Waiting for the pop-up to open", "Pop up with the options was openend");
+        mSolo.clickOnText(option);
+        mAsserter.ok(waitForText(StringHelper.CHARACTER_ENCODING_LABEL), "Waiting to press the option", "The pop-up is dismissed once clicked");
+        if (mDevice.type.equals("phone")) {
+            mActions.sendSpecialKey(Actions.SpecialKey.BACK);
+            mAsserter.ok(waitForText(StringHelper.CUSTOMIZE_SECTION_LABEL), "Waiting to perform one back", "One back performed");
+            mActions.sendSpecialKey(Actions.SpecialKey.BACK);
+            mAsserter.ok(waitForText(StringHelper.ROBOCOP_BLANK_PAGE_01_URL), "Waiting to exit settings", "Exit settings done");
+        }
+        else {
+            mActions.sendSpecialKey(Actions.SpecialKey.BACK);
+            mAsserter.ok(waitForText(StringHelper.ROBOCOP_BLANK_PAGE_01_URL), "Waiting to exit settings", "Exit settings done");
+        }
+    }
+}
--- a/mobile/android/base/toolbar/ToolbarDisplayLayout.java
+++ b/mobile/android/base/toolbar/ToolbarDisplayLayout.java
@@ -352,16 +352,22 @@ public class ToolbarDisplayLayout extend
 
             final SpannableStringBuilder builder = new SpannableStringBuilder(title);
             builder.setSpan(mBlockedColor, 0, title.length(), Spannable.SPAN_INCLUSIVE_INCLUSIVE);
 
             setTitle(builder);
             return;
         }
 
+        // If the pref to show the title is set, use the tab's display title.
+        if (!mPrefs.shouldShowUrl(mActivity) || url == null) {
+            setTitle(tab.getDisplayTitle());
+            return;
+        }
+
         CharSequence title = url;
         if (mPrefs.shouldTrimUrls()) {
             title = StringUtils.stripCommonSubdomains(StringUtils.stripScheme(url));
         }
 
         final String baseDomain = tab.getBaseDomain();
         if (!TextUtils.isEmpty(baseDomain)) {
             final SpannableStringBuilder builder = new SpannableStringBuilder(title);
--- a/mobile/android/base/toolbar/ToolbarPrefs.java
+++ b/mobile/android/base/toolbar/ToolbarPrefs.java
@@ -10,41 +10,48 @@ import org.mozilla.gecko.PrefsHelper;
 import org.mozilla.gecko.Tab;
 import org.mozilla.gecko.Tabs;
 import org.mozilla.gecko.util.ThreadUtils;
 
 import android.content.Context;
 
 class ToolbarPrefs {
     private static final String PREF_AUTOCOMPLETE_ENABLED = "browser.urlbar.autocomplete.enabled";
+    private static final String PREF_TITLEBAR_MODE = "browser.chrome.titlebarMode";
     private static final String PREF_TRIM_URLS = "browser.urlbar.trimURLs";
 
     private static final String[] PREFS = {
         PREF_AUTOCOMPLETE_ENABLED,
+        PREF_TITLEBAR_MODE,
         PREF_TRIM_URLS
     };
 
     private final TitlePrefsHandler HANDLER = new TitlePrefsHandler();
 
     private volatile boolean enableAutocomplete;
+    private volatile boolean showUrl;
     private volatile boolean trimUrls;
 
     private Integer prefObserverId;
 
     ToolbarPrefs() {
         // Skip autocompletion while Gecko is loading.
         // We will get the correct pref value once Gecko is loaded.
         enableAutocomplete = false;
         trimUrls = true;
     }
 
     boolean shouldAutocomplete() {
         return enableAutocomplete;
     }
 
+    boolean shouldShowUrl(final Context context) {
+        return showUrl || NewTabletUI.isEnabled(context);
+    }
+
     boolean shouldTrimUrls() {
         return trimUrls;
     }
 
     void open() {
         if (prefObserverId == null) {
             prefObserverId = PrefsHelper.getPrefs(PREFS, HANDLER);
         }
@@ -67,16 +74,30 @@ class ToolbarPrefs {
                     tabs.notifyListeners(tab, Tabs.TabEvents.TITLE);
                 }
             }
         });
     }
 
     private class TitlePrefsHandler extends PrefsHelper.PrefHandlerBase {
         @Override
+        public void prefValue(String pref, String str) {
+            if (PREF_TITLEBAR_MODE.equals(pref)) {
+                // Handles PREF_TITLEBAR_MODE, which is always a string.
+                int value = Integer.parseInt(str);
+                boolean shouldShowUrl = (value == 1);
+
+                if (shouldShowUrl != showUrl) {
+                    showUrl = shouldShowUrl;
+                    triggerTitleChangeListener();
+                }
+            }
+        }
+
+        @Override
         public void prefValue(String pref, boolean value) {
             if (PREF_AUTOCOMPLETE_ENABLED.equals(pref)) {
                 enableAutocomplete = value;
 
             } else if (PREF_TRIM_URLS.equals(pref)) {
                 // Handles PREF_TRIM_URLS, which should usually be a boolean.
                 if (value != trimUrls) {
                     trimUrls = value;
--- a/mobile/android/base/webapp/WebappImpl.java
+++ b/mobile/android/base/webapp/WebappImpl.java
@@ -174,20 +174,21 @@ public class WebappImpl extends GeckoApp
         // If this is a legacy shortcut, then we should have been able to get
         // the URI from the intent data.  Otherwise, we should have been able
         // to get it from the APK resources.  So we should never get here.
         Log.wtf(LOGTAG, "Couldn't get URI from intent nor APK resources");
         return null;
     }
 
     @Override
-    protected void loadStartupTab(String uri) {
+    protected void loadStartupTab(String uri, int flags) {
         // Load a tab so it's available for any code that assumes a tab
         // before the app tab itself is loaded in BrowserApp._loadWebapp.
-        super.loadStartupTab("about:blank");
+        flags = Tabs.LOADURL_NEW_TAB | Tabs.LOADURL_USER_ENTERED | Tabs.LOADURL_EXTERNAL;
+        super.loadStartupTab("about:blank", flags);
     }
 
     private void showSplash() {
 
         // get the favicon dominant color, stored when the app was installed
         int dominantColor = Allocator.getInstance().getColor(getIndex());
 
         setBackgroundGradient(dominantColor);
--- a/mobile/android/chrome/content/browser.js
+++ b/mobile/android/chrome/content/browser.js
@@ -473,56 +473,50 @@ var BrowserApp = {
     // TODO: replace with Android implementation of WebappOSUtils.isLaunchable.
     Cu.import("resource://gre/modules/Webapps.jsm");
     DOMApplicationRegistry.allAppsLaunchable = true;
     RemoteDebugger.init();
     UserAgentOverrides.init();
     DesktopUserAgent.init();
     Distribution.init();
     Tabs.init();
+    SearchEngines.init();
 #ifdef ACCESSIBILITY
     AccessFu.attach(window);
 #endif
 #ifdef NIGHTLY_BUILD
     ShumwayUtils.init();
 #endif
 
     let url = null;
-    let pinned = false;
     if ("arguments" in window) {
       if (window.arguments[0])
         url = window.arguments[0];
       if (window.arguments[1])
         gScreenWidth = window.arguments[1];
       if (window.arguments[2])
         gScreenHeight = window.arguments[2];
-      if (window.arguments[3])
-        pinned = window.arguments[3];
-    }
-
-    if (pinned) {
-      this._initRuntime(this._startupStatus, url, aUrl => this.addTab(aUrl));
-    } else {
-      SearchEngines.init();
-      this.initContextMenu();
-    }
+    }
+
     // The order that context menu items are added is important
     // Make sure the "Open in App" context menu item appears at the bottom of the list
+    this.initContextMenu();
     ExternalApps.init();
 
     // XXX maybe we don't do this if the launch was kicked off from external
     Services.io.offline = false;
 
     // Broadcast a UIReady message so add-ons know we are finished with startup
     let event = document.createEvent("Events");
     event.initEvent("UIReady", true, false);
     window.dispatchEvent(event);
 
-    if (this._startupStatus)
+    if (this._startupStatus) {
       this.onAppUpdated();
+    }
 
     if (!ParentalControls.isAllowed(ParentalControls.INSTALL_EXTENSION)) {
       // Disable extension installs
       Services.prefs.setIntPref("extensions.enabledScopes", 1);
       Services.prefs.setIntPref("extensions.autoDisableScopes", 1);
       Services.prefs.setBoolPref("xpinstall.enabled", false);
     }
 
@@ -1098,17 +1092,18 @@ var BrowserApp = {
     let message = {
       type: "Tab:Close",
       tabID: aTab.id
     };
     Messaging.sendRequest(message);
   },
 
   _loadWebapp: function(aMessage) {
-
+    // Entry point for WebApps. This is the point in which we know
+    // the code is being used as a WebApp runtime.
     this._initRuntime(this._startupStatus, aMessage.url, aUrl => {
       this.manifestUrl = aMessage.url;
       this.addTab(aUrl, { title: aMessage.name });
     });
   },
 
   // Calling this will update the state in BrowserApp after a tab has been
   // closed in the Java UI.
@@ -1375,16 +1370,17 @@ var BrowserApp = {
 
       // Some Gecko preferences use integers or strings to reference
       // state instead of directly representing the value.
       // Since the Java UI uses the type to determine which ui elements
       // to show and how to handle them, we need to normalize these
       // preferences to the correct type.
       switch (prefName) {
         // (string) index for determining which multiple choice value to display.
+        case "browser.chrome.titlebarMode":
         case "network.cookie.cookieBehavior":
         case "font.size.inflation.minTwips":
         case "home.sync.updateMode":
           pref.type = "string";
           pref.value = pref.value.toString();
           break;
       }
 
@@ -1425,16 +1421,17 @@ var BrowserApp = {
       // Crash reporter preference is in a service; set and return.
       case "datareporting.crashreporter.submitEnabled":
         CrashReporter.submitReports = json.value;
         return;
 #endif
       // When sending to Java, we normalized special preferences that use
       // integers and strings to represent booleans. Here, we convert them back
       // to their actual types so we can store them.
+      case "browser.chrome.titlebarMode":
       case "network.cookie.cookieBehavior":
       case "font.size.inflation.minTwips":
       case "home.sync.updateMode":
         json.type = "int";
         json.value = parseInt(json.value);
         break;
     }
 
@@ -3173,16 +3170,18 @@ nsBrowserAccess.prototype = {
         if (appOrigin == spec) {
           let tab = tabs[i];
           BrowserApp.selectTab(tab);
           return tab.browser;
         }
       }
     }
 
+    // If OPEN_SWITCHTAB was not handled above, we need to open a new tab,
+    // along with other OPEN_ values that create a new tab.
     let newTab = (aWhere == Ci.nsIBrowserDOMWindow.OPEN_NEWWINDOW ||
                   aWhere == Ci.nsIBrowserDOMWindow.OPEN_NEWTAB ||
                   aWhere == Ci.nsIBrowserDOMWindow.OPEN_SWITCHTAB);
     let isPrivate = false;
 
     if (newTab) {
       let parentId = -1;
       if (!isExternal && aOpener) {
@@ -3202,18 +3201,19 @@ nsBrowserAccess.prototype = {
                                                                       isPrivate: isPrivate,
                                                                       pinned: pinned });
 
       return tab.browser;
     }
 
     // OPEN_CURRENTWINDOW and illegal values
     let browser = BrowserApp.selectedBrowser;
-    if (aURI && browser)
+    if (aURI && browser) {
       browser.loadURIWithFlags(aURI.spec, loadflags, referrer, null, null);
+    }
 
     return browser;
   },
 
   openURI: function browser_openURI(aURI, aOpener, aWhere, aContext) {
     let browser = this._getBrowser(aURI, aOpener, aWhere, aContext);
     return browser ? browser.contentWindow : null;
   },
--- a/mobile/android/components/BrowserCLH.js
+++ b/mobile/android/components/BrowserCLH.js
@@ -12,32 +12,29 @@ Cu.import("resource://gre/modules/Servic
 
 function dump(a) {
   Cc["@mozilla.org/consoleservice;1"].getService(Ci.nsIConsoleService).logStringMessage(a);
 }
 
 function openWindow(aParent, aURL, aTarget, aFeatures, aArgs) {
   let argsArray = Cc["@mozilla.org/supports-array;1"].createInstance(Ci.nsISupportsArray);
   let urlString = null;
-  let pinnedBool = Cc["@mozilla.org/supports-PRBool;1"].createInstance(Ci.nsISupportsPRBool);
   let widthInt = Cc["@mozilla.org/supports-PRInt32;1"].createInstance(Ci.nsISupportsPRInt32);
   let heightInt = Cc["@mozilla.org/supports-PRInt32;1"].createInstance(Ci.nsISupportsPRInt32);
 
   if ("url" in aArgs) {
     urlString = Cc["@mozilla.org/supports-string;1"].createInstance(Ci.nsISupportsString);
     urlString.data = aArgs.url;
   }
   widthInt.data = "width" in aArgs ? aArgs.width : 1;
   heightInt.data = "height" in aArgs ? aArgs.height : 1;
-  pinnedBool.data = "pinned" in aArgs ? aArgs.pinned : false;
 
   argsArray.AppendElement(urlString, false);
   argsArray.AppendElement(widthInt, false);
   argsArray.AppendElement(heightInt, false);
-  argsArray.AppendElement(pinnedBool, false);
   return Services.ww.openWindow(aParent, aURL, aTarget, aFeatures, argsArray);
 }
 
 
 function resolveURIInternal(aCmdLine, aArgument) {
   let uri = aCmdLine.resolveURI(aArgument);
   if (uri)
     return uri;
@@ -61,17 +58,17 @@ BrowserCLH.prototype = {
 
     let width = 1;
     let height = 1;
 
     try {
       openURL = aCmdLine.handleFlagWithParam("url", false);
     } catch (e) { /* Optional */ }
     try {
-      pinned = aCmdLine.handleFlag("webapp", false);
+      pinned = aCmdLine.handleFlag("bookmark", false);
     } catch (e) { /* Optional */ }
 
     try {
       width = aCmdLine.handleFlagWithParam("width", false);
     } catch (e) { /* Optional */ }
     try {
       height = aCmdLine.handleFlagWithParam("height", false);
     } catch (e) { /* Optional */ }
@@ -81,32 +78,26 @@ BrowserCLH.prototype = {
       if (!uri)
         return;
 
       // Let's get a head start on opening the network connection to the URI we are about to load
       Services.io.QueryInterface(Ci.nsISpeculativeConnect).speculativeConnect(uri, null);
 
       let browserWin = Services.wm.getMostRecentWindow("navigator:browser");
       if (browserWin) {
-        if (!pinned) {
-          browserWin.browserDOMWindow.openURI(uri, null, Ci.nsIBrowserDOMWindow.OPEN_NEWTAB, Ci.nsIBrowserDOMWindow.OPEN_EXTERNAL);
-        }
+        let whereFlags = pinned ? Ci.nsIBrowserDOMWindow.OPEN_SWITCHTAB : Ci.nsIBrowserDOMWindow.OPEN_NEWTAB;
+        browserWin.browserDOMWindow.openURI(uri, null, whereFlags, Ci.nsIBrowserDOMWindow.OPEN_EXTERNAL);
       } else {
         let args = {
           url: openURL,
-          pinned: pinned,
           width: width,
           height: height,
         };
 
-        // Make sure webapps do not have: locationbar, personalbar, menubar, statusbar, and toolbar
-        let flags = "chrome,dialog=no";
-        if (!pinned)
-          flags += ",all";
-
+        let flags = "chrome,dialog=no,all";
         browserWin = openWindow(null, "chrome://browser/content/browser.xul", "_blank", flags, args);
       }
 
       aCmdLine.preventDefault = true;
     } catch (x) {
       dump("BrowserCLH.handle: " + x);
     }
   },
--- a/services/sync/modules/browserid_identity.js
+++ b/services/sync/modules/browserid_identity.js
@@ -395,16 +395,26 @@ this.BrowserIDManager.prototype = {
   resetSyncKey: function() {
     this._syncKey = null;
     this._syncKeyBundle = null;
     this._syncKeyUpdated = true;
     this._shouldHaveSyncKeyBundle = false;
   },
 
   /**
+   * Pre-fetches any information that might help with migration away from this
+   * identity.  Called after every sync and is really just an optimization that
+   * allows us to avoid a network request for when we actually need the
+   * migration info.
+   */
+  prefetchMigrationSentinel: function(service) {
+    // nothing to do here until we decide to migrate away from FxA.
+  },
+
+  /**
     * Return credentials hosts for this identity only.
     */
   _getSyncCredentialsHosts: function() {
     return Utils.getSyncCredentialsHostsFxA();
   },
 
   /**
    * The current state of the auth credentials.
--- a/services/sync/modules/identity.js
+++ b/services/sync/modules/identity.js
@@ -442,16 +442,32 @@ IdentityManager.prototype = {
   },
 
   hasBasicCredentials: function hasBasicCredentials() {
     // Because JavaScript.
     return this.username && this.basicPassword && true;
   },
 
   /**
+   * Pre-fetches any information that might help with migration away from this
+   * identity.  Called after every sync and is really just an optimization that
+   * allows us to avoid a network request for when we actually need the
+   * migration info.
+   */
+  prefetchMigrationSentinel: function(service) {
+    // Try and fetch the migration sentinel - it will end up in the recordManager
+    // cache.
+    try {
+      service.recordManager.get(service.storageURL + "meta/fxa_credentials");
+    } catch (ex) {
+      this._log.warn("Failed to pre-fetch the migration sentinel", ex);
+    }
+  },
+
+  /**
    * Obtains the array of basic logins from nsiPasswordManager.
    */
   _getLogins: function _getLogins(realm) {
     return Services.logins.findLogins({}, PWDMGR_HOST, null, realm);
   },
 
   /**
    * Set a login in the password manager.
--- a/services/sync/modules/service.js
+++ b/services/sync/modules/service.js
@@ -1276,22 +1276,22 @@ Sync11Service.prototype = {
       // wait() throws if the first argument is truthy, which is exactly what
       // we want.
       let result = cb.wait();
 
       histogram = Services.telemetry.getHistogramById("WEAVE_COMPLETE_SUCCESS_COUNT");
       histogram.add(1);
 
       // We successfully synchronized.
-      // Try and fetch the migration sentinel - it will end up in the recordManager
-      // cache, so a sync migration doesn't need a server round-trip.
+      // Check if the identity wants to pre-fetch a migration sentinel from
+      // the server.
       // If we have no clusterURL, we are probably doing a node reassignment
-      // do don't attempt to get the credentials.
+      // so don't attempt to get it in that case.
       if (this.clusterURL) {
-        this.recordManager.get(this.storageURL + "meta/fxa_credentials");
+        this.identity.prefetchMigrationSentinel(this);
       }
 
       // Now let's update our declined engines.
       let meta = this.recordManager.get(this.metaURL);
       if (!meta) {
         this._log.warn("No meta/global; can't update declined state.");
         return;
       }