Bug 1293713 - Make new tab action respect HomePage preference. r?sebastian,mkaply draft
authornechen <cnevinc@livemail.tw>
Mon, 13 Mar 2017 16:13:18 +0800
changeset 558821 08e82e35d2647e70235e0a6e6bf493aa5645a230
parent 558673 35c7be9c2db288d1d449e3cc586c4164d642c5fd
child 623269 4921ee71322dab826763da1e924f962dd6380b8a
push id52955
push userbmo:cnevinchen@gmail.com
push dateSat, 08 Apr 2017 01:44:08 +0000
reviewerssebastian, mkaply
bugs1293713
milestone55.0a1
Bug 1293713 - Make new tab action respect HomePage preference. r?sebastian,mkaply MozReview-Commit-ID: 9N7tLrr20nv
mobile/android/base/java/org/mozilla/gecko/BrowserApp.java
mobile/android/base/java/org/mozilla/gecko/GeckoApp.java
mobile/android/base/java/org/mozilla/gecko/Tabs.java
mobile/android/base/java/org/mozilla/gecko/preferences/GeckoPreferences.java
mobile/android/base/locales/en-US/android_strings.dtd
mobile/android/base/resources/xml/preferences_home.xml
mobile/android/base/strings.xml.in
--- a/mobile/android/base/java/org/mozilla/gecko/BrowserApp.java
+++ b/mobile/android/base/java/org/mozilla/gecko/BrowserApp.java
@@ -9,19 +9,16 @@ import android.Manifest;
 import android.annotation.TargetApi;
 import android.app.DownloadManager;
 import android.content.ContentProviderClient;
 import android.os.Environment;
 import android.os.Process;
 import android.support.annotation.NonNull;
 import android.support.annotation.UiThread;
 
-import android.graphics.Rect;
-
-import org.mozilla.gecko.GeckoSharedPrefs;
 import org.mozilla.gecko.activitystream.ActivityStream;
 import org.mozilla.gecko.adjust.AdjustBrowserAppDelegate;
 import org.mozilla.gecko.annotation.RobocopTarget;
 import org.mozilla.gecko.AppConstants.Versions;
 import org.mozilla.gecko.DynamicToolbar.VisibilityTransition;
 import org.mozilla.gecko.Tabs.TabEvents;
 import org.mozilla.gecko.animation.PropertyAnimator;
 import org.mozilla.gecko.animation.ViewHelper;
@@ -29,17 +26,16 @@ import org.mozilla.gecko.cleanup.FileCle
 import org.mozilla.gecko.db.BrowserContract;
 import org.mozilla.gecko.db.BrowserDB;
 import org.mozilla.gecko.db.SuggestedSites;
 import org.mozilla.gecko.delegates.BrowserAppDelegate;
 import org.mozilla.gecko.delegates.OfflineTabStatusDelegate;
 import org.mozilla.gecko.delegates.ScreenshotDelegate;
 import org.mozilla.gecko.distribution.Distribution;
 import org.mozilla.gecko.distribution.DistributionStoreCallback;
-import org.mozilla.gecko.distribution.PartnerBrowserCustomizationsClient;
 import org.mozilla.gecko.dlc.DownloadContentService;
 import org.mozilla.gecko.icons.IconsHelper;
 import org.mozilla.gecko.icons.decoders.IconDirectoryEntry;
 import org.mozilla.gecko.icons.decoders.FaviconDecoder;
 import org.mozilla.gecko.feeds.ContentNotificationsDelegate;
 import org.mozilla.gecko.feeds.FeedService;
 import org.mozilla.gecko.firstrun.FirstrunAnimationContainer;
 import org.mozilla.gecko.gfx.DynamicToolbarAnimator;
@@ -2028,17 +2024,17 @@ public class BrowserApp extends GeckoApp
                 final BrowserDB db = BrowserDB.from(getProfile());
                 final ContentResolver cr = getContentResolver();
 
                 Telemetry.addToHistogram("PLACES_PAGES_COUNT", db.getCount(cr, "history"));
                 Telemetry.addToHistogram("FENNEC_BOOKMARKS_COUNT", db.getCount(cr, "bookmarks"));
                 Telemetry.addToHistogram("BROWSER_IS_USER_DEFAULT",
                         (isDefaultBrowser(Intent.ACTION_VIEW) ? 1 : 0));
                 Telemetry.addToHistogram("FENNEC_CUSTOM_HOMEPAGE",
-                        (TextUtils.isEmpty(getHomepage()) ? 0 : 1));
+                        (TextUtils.isEmpty(Tabs.getHomepage(this)) ? 0 : 1));
 
                 final SharedPreferences prefs = GeckoSharedPrefs.forProfile(getContext());
                 final boolean hasCustomHomepanels =
                         prefs.contains(HomeConfigPrefsBackend.PREFS_CONFIG_KEY) ||
                         prefs.contains(HomeConfigPrefsBackend.PREFS_CONFIG_KEY_OLD);
 
                 Telemetry.addToHistogram("FENNEC_HOMEPANELS_CUSTOM", hasCustomHomepanels ? 1 : 0);
 
@@ -2287,56 +2283,16 @@ public class BrowserApp extends GeckoApp
         return false;
     }
 
     @Override
     public boolean areTabsShown() {
         return (mTabsPanel != null && mTabsPanel.isShown());
     }
 
-    @Override
-    public String getHomepage() {
-        final SharedPreferences preferences = GeckoSharedPrefs.forProfile(this);
-        final String homepagePreference = preferences.getString(GeckoPreferences.PREFS_HOMEPAGE, null);
-
-        final boolean readFromPartnerProvider = preferences.getBoolean(
-                GeckoPreferences.PREFS_READ_PARTNER_CUSTOMIZATIONS_PROVIDER, false);
-
-        if (!readFromPartnerProvider) {
-            // Just return homepage as set by the user (or null).
-            return homepagePreference;
-        }
-
-
-        final String homepagePrevious = preferences.getString(GeckoPreferences.PREFS_HOMEPAGE_PARTNER_COPY, null);
-        if (homepagePrevious != null && !homepagePrevious.equals(homepagePreference)) {
-            // We have read the homepage once and the user has changed it since then. Just use the
-            // value the user has set.
-            return homepagePreference;
-        }
-
-        // This is the first time we read the partner provider or the value has not been altered by the user
-        final String homepagePartner = PartnerBrowserCustomizationsClient.getHomepage(this);
-
-        if (homepagePartner == null) {
-            // We didn't get anything from the provider. Let's just use what we have locally.
-            return homepagePreference;
-        }
-
-        if (!homepagePartner.equals(homepagePrevious)) {
-            // We have a new value. Update the preferences.
-            preferences.edit()
-                    .putString(GeckoPreferences.PREFS_HOMEPAGE, homepagePartner)
-                    .putString(GeckoPreferences.PREFS_HOMEPAGE_PARTNER_COPY, homepagePartner)
-                    .apply();
-        }
-
-        return homepagePartner;
-    }
-
     @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
     @Override
     public void onTabsLayoutChange(int width, int height) {
         int animationLength = TABS_ANIMATION_DURATION;
 
         if (mMainLayoutAnimator != null) {
             animationLength = Math.max(1, animationLength - (int)mMainLayoutAnimator.getRemainingTime());
             mMainLayoutAnimator.stop(false);
@@ -2842,17 +2798,17 @@ public class BrowserApp extends GeckoApp
         if (mFirstrunAnimationContainer == null) {
             final ViewStub firstrunPagerStub = (ViewStub) findViewById(R.id.firstrun_pager_stub);
             mFirstrunAnimationContainer = (FirstrunAnimationContainer) firstrunPagerStub.inflate();
             mFirstrunAnimationContainer.load(getApplicationContext(), getSupportFragmentManager());
             mFirstrunAnimationContainer.registerOnFinishListener(new FirstrunAnimationContainer.OnFinishListener() {
                 @Override
                 public void onFinish() {
                     if (mFirstrunAnimationContainer.showBrowserHint() &&
-                        TextUtils.isEmpty(getHomepage())) {
+                        TextUtils.isEmpty(Tabs.getHomepage(BrowserApp.this))) {
                         enterEditingMode();
                     }
                 }
             });
         }
 
         mHomeScreenContainer.setVisibility(View.VISIBLE);
     }
--- a/mobile/android/base/java/org/mozilla/gecko/GeckoApp.java
+++ b/mobile/android/base/java/org/mozilla/gecko/GeckoApp.java
@@ -18,17 +18,16 @@ import org.mozilla.gecko.health.SessionI
 import org.mozilla.gecko.health.StubbedHealthRecorder;
 import org.mozilla.gecko.home.HomeConfig.PanelType;
 import org.mozilla.gecko.icons.IconCallback;
 import org.mozilla.gecko.icons.IconResponse;
 import org.mozilla.gecko.icons.Icons;
 import org.mozilla.gecko.menu.GeckoMenu;
 import org.mozilla.gecko.menu.GeckoMenuInflater;
 import org.mozilla.gecko.menu.MenuPanel;
-import org.mozilla.gecko.notifications.NotificationClient;
 import org.mozilla.gecko.notifications.NotificationHelper;
 import org.mozilla.gecko.util.IntentUtils;
 import org.mozilla.gecko.mozglue.SafeIntent;
 import org.mozilla.gecko.mozglue.GeckoLoader;
 import org.mozilla.gecko.permissions.Permissions;
 import org.mozilla.gecko.preferences.ClearOnShutdownPref;
 import org.mozilla.gecko.preferences.GeckoPreferences;
 import org.mozilla.gecko.prompts.PromptService;
@@ -61,24 +60,22 @@ import android.content.pm.PackageManager
 import android.content.res.Configuration;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
 import android.graphics.Canvas;
 import android.graphics.Color;
 import android.graphics.Paint;
 import android.graphics.Rect;
 import android.graphics.RectF;
-import android.hardware.Sensor;
 import android.net.Uri;
 import android.os.Build;
 import android.os.Bundle;
 import android.os.Environment;
 import android.os.Handler;
 import android.os.PowerManager;
-import android.os.Process;
 import android.os.StrictMode;
 import android.provider.ContactsContract;
 import android.provider.MediaStore.Images.Media;
 import android.support.annotation.NonNull;
 import android.support.annotation.WorkerThread;
 import android.support.design.widget.Snackbar;
 import android.text.TextUtils;
 import android.util.AttributeSet;
@@ -1582,17 +1579,17 @@ public abstract class GeckoApp
      */
     protected void loadStartupTab(final int flags, String action) {
         if (!mShouldRestore || Intent.ACTION_VIEW.equals(action)) {
             if (mLastSessionCrashed) {
                 // The Recent Tabs panel no longer exists, but BrowserApp will redirect us
                 // to the Recent Tabs folder of the Combined History panel.
                 Tabs.getInstance().loadUrl(AboutPages.getURLForBuiltinPanelType(PanelType.DEPRECATED_RECENT_TABS), flags);
             } else {
-                final String homepage = getHomepage();
+                final String homepage = Tabs.getHomepage(this);
                 Tabs.getInstance().loadUrl(!TextUtils.isEmpty(homepage) ? homepage : AboutPages.HOME, flags);
             }
         }
     }
 
     /**
      * Loads the initial tab at Fennec startup. This tab will load with the given
      * external URL. If that URL is invalid, a startup tab will be loaded.
@@ -1606,20 +1603,16 @@ public abstract class GeckoApp
         if (url == null) {
             loadStartupTab(flags, intent.getAction());
             return;
         }
 
         Tabs.getInstance().loadUrlWithIntentExtras(url, intent, flags);
     }
 
-    public String getHomepage() {
-        return null;
-    }
-
     private String getIntentURI(SafeIntent intent) {
         final String passedUri;
         final String uri = getURIFromIntent(intent);
 
         if (!TextUtils.isEmpty(uri)) {
             passedUri = uri;
         } else {
             passedUri = null;
--- a/mobile/android/base/java/org/mozilla/gecko/Tabs.java
+++ b/mobile/android/base/java/org/mozilla/gecko/Tabs.java
@@ -7,24 +7,28 @@ package org.mozilla.gecko;
 
 import java.util.Arrays;
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.List;
 import java.util.concurrent.CopyOnWriteArrayList;
 import java.util.concurrent.atomic.AtomicInteger;
 
+import android.content.SharedPreferences;
+import android.support.annotation.NonNull;
 import android.support.annotation.Nullable;
 
 import org.mozilla.gecko.annotation.JNITarget;
 import org.mozilla.gecko.annotation.RobocopTarget;
 import org.mozilla.gecko.db.BrowserDB;
+import org.mozilla.gecko.distribution.PartnerBrowserCustomizationsClient;
 import org.mozilla.gecko.gfx.LayerView;
 import org.mozilla.gecko.mozglue.SafeIntent;
 import org.mozilla.gecko.notifications.WhatsNewReceiver;
+import org.mozilla.gecko.preferences.GeckoPreferences;
 import org.mozilla.gecko.reader.ReaderModeUtils;
 import org.mozilla.gecko.util.BundleEventListener;
 import org.mozilla.gecko.util.EventCallback;
 import org.mozilla.gecko.util.GeckoBundle;
 import org.mozilla.gecko.util.JavaUtil;
 import org.mozilla.gecko.util.ThreadUtils;
 
 import android.accounts.Account;
@@ -35,16 +39,17 @@ import android.content.Context;
 import android.database.ContentObserver;
 import android.database.sqlite.SQLiteException;
 import android.graphics.Color;
 import android.net.Uri;
 import android.os.Handler;
 import android.provider.Browser;
 import android.support.annotation.UiThread;
 import android.support.v4.content.ContextCompat;
+import android.text.TextUtils;
 import android.util.Log;
 
 import static org.mozilla.gecko.Tab.TabType;
 
 public class Tabs implements BundleEventListener {
     private static final String LOGTAG = "GeckoTabs";
 
     // mOrder and mTabs are always of the same cardinality, and contain the same values.
@@ -427,17 +432,17 @@ public class Tabs implements BundleEvent
     public synchronized void closeTab(final Tab tab, Tab nextTab, boolean showUndoToast) {
         if (tab == null)
             return;
 
         int tabId = tab.getId();
         removeTab(tabId);
 
         if (nextTab == null) {
-            nextTab = loadUrl(AboutPages.HOME, LOADURL_NEW_TAB);
+            nextTab = loadUrl(getHomepageForNewTab(mAppContext), LOADURL_NEW_TAB);
         }
 
         selectTab(nextTab.getId());
 
         tab.onDestroy();
 
         // Pass a message to Gecko to update tab state in BrowserApp
         final GeckoBundle data = new GeckoBundle(2);
@@ -1057,17 +1062,17 @@ public class Tabs implements BundleEvent
         if (AboutPages.isBuiltinIconPage(url)) {
             tabToSelect.loadFavicon();
         }
 
         return tabToSelect;
     }
 
     public Tab addTab() {
-        return loadUrl(AboutPages.HOME, Tabs.LOADURL_NEW_TAB);
+        return loadUrl(getHomepageForNewTab(mAppContext), Tabs.LOADURL_NEW_TAB);
     }
 
     public Tab addPrivateTab() {
         return loadUrl(AboutPages.PRIVATEBROWSING, Tabs.LOADURL_NEW_TAB | Tabs.LOADURL_PRIVATE);
     }
 
     /**
      * Open the url as a new tab, and mark the selected tab as its "parent".
@@ -1221,9 +1226,65 @@ public class Tabs implements BundleEvent
 
         final GeckoBundle data = new GeckoBundle();
         data.putInt("fromTabId", fromTabId);
         data.putInt("fromPosition", fromPosition);
         data.putInt("toTabId", toTabId);
         data.putInt("toPosition", toPosition);
         EventDispatcher.getInstance().dispatch("Tab:Move", data);
     }
+
+    @NonNull
+    public static String getHomepageForNewTab(Context context) {
+        final SharedPreferences preferences = GeckoSharedPrefs.forApp(context);
+        final boolean forEveryNewTab = preferences.getBoolean(GeckoPreferences.PREFS_HOMEPAGE_FOR_EVERY_NEW_TAB, false);
+
+        if (forEveryNewTab) {
+            final String homePage = getHomepage(context);
+            if (TextUtils.isEmpty(homePage)) {
+                return AboutPages.HOME;
+            } else {
+                return homePage;
+            }
+        }
+        return AboutPages.HOME;
+    }
+
+    @Nullable
+    public static String getHomepage(Context context) {
+        final SharedPreferences preferences = GeckoSharedPrefs.forProfile(context);
+        final String homepagePreference = preferences.getString(GeckoPreferences.PREFS_HOMEPAGE, AboutPages.HOME);
+
+        final boolean readFromPartnerProvider = preferences.getBoolean(
+                GeckoPreferences.PREFS_READ_PARTNER_CUSTOMIZATIONS_PROVIDER, false);
+
+        if (!readFromPartnerProvider) {
+            // Just return homepage as set by the user (or null).
+            return homepagePreference;
+        }
+
+
+        final String homepagePrevious = preferences.getString(GeckoPreferences.PREFS_HOMEPAGE_PARTNER_COPY, null);
+        if (homepagePrevious != null && !homepagePrevious.equals(homepagePreference)) {
+            // We have read the homepage once and the user has changed it since then. Just use the
+            // value the user has set.
+            return homepagePreference;
+        }
+
+        // This is the first time we read the partner provider or the value has not been altered by the user
+        final String homepagePartner = PartnerBrowserCustomizationsClient.getHomepage(context);
+
+        if (homepagePartner == null) {
+            // We didn't get anything from the provider. Let's just use what we have locally.
+            return homepagePreference;
+        }
+
+        if (!homepagePartner.equals(homepagePrevious)) {
+            // We have a new value. Update the preferences.
+            preferences.edit()
+                    .putString(GeckoPreferences.PREFS_HOMEPAGE, homepagePartner)
+                    .putString(GeckoPreferences.PREFS_HOMEPAGE_PARTNER_COPY, homepagePartner)
+                    .apply();
+        }
+
+        return homepagePartner;
+    }
 }
--- a/mobile/android/base/java/org/mozilla/gecko/preferences/GeckoPreferences.java
+++ b/mobile/android/base/java/org/mozilla/gecko/preferences/GeckoPreferences.java
@@ -152,16 +152,17 @@ public class GeckoPreferences
     public static final String PREFS_VOICE_INPUT_ENABLED = NON_PREF_PREFIX + "voice_input_enabled";
     public static final String PREFS_QRCODE_ENABLED = NON_PREF_PREFIX + "qrcode_enabled";
     private static final String PREFS_TRACKING_PROTECTION_PRIVATE_BROWSING = "privacy.trackingprotection.pbmode.enabled";
     private static final String PREFS_TRACKING_PROTECTION_LEARN_MORE = NON_PREF_PREFIX + "trackingprotection.learn_more";
     private static final String PREFS_CLEAR_PRIVATE_DATA = NON_PREF_PREFIX + "privacy.clear";
     private static final String PREFS_CLEAR_PRIVATE_DATA_EXIT = NON_PREF_PREFIX + "history.clear_on_exit";
     private static final String PREFS_SCREEN_ADVANCED = NON_PREF_PREFIX + "advanced_screen";
     public static final String PREFS_HOMEPAGE = NON_PREF_PREFIX + "homepage";
+    public static final String PREFS_HOMEPAGE_FOR_EVERY_NEW_TAB = NON_PREF_PREFIX + "newtab.load_homepage";
     public static final String PREFS_HOMEPAGE_PARTNER_COPY = GeckoPreferences.PREFS_HOMEPAGE + ".partner";
     public static final String PREFS_HISTORY_SAVED_SEARCH = NON_PREF_PREFIX + "search.search_history.enabled";
     private static final String PREFS_FAQ_LINK = NON_PREF_PREFIX + "faq.link";
     private static final String PREFS_FEEDBACK_LINK = NON_PREF_PREFIX + "feedback.link";
     public static final String PREFS_NOTIFICATIONS_CONTENT = NON_PREF_PREFIX + "notifications.content";
     public static final String PREFS_NOTIFICATIONS_CONTENT_LEARN_MORE = NON_PREF_PREFIX + "notifications.content.learn_more";
     public static final String PREFS_NOTIFICATIONS_WHATS_NEW = NON_PREF_PREFIX + "notifications.whats_new";
     public static final String PREFS_APP_UPDATE_LAST_BUILD_ID = "app.update.last_build_id";
--- a/mobile/android/base/locales/en-US/android_strings.dtd
+++ b/mobile/android/base/locales/en-US/android_strings.dtd
@@ -209,16 +209,19 @@
 <!ENTITY pref_category_home "Home">
 <!ENTITY pref_category_home_summary "Customize your homepage">
 <!ENTITY pref_category_home_panels "Panels">
 <!ENTITY pref_category_home_add_ons "Add-ons">
 <!ENTITY pref_home_updates2 "Content updates">
 <!ENTITY pref_home_updates_enabled "Enabled">
 <!ENTITY pref_home_updates_wifi "Only over Wi-Fi">
 <!ENTITY pref_category_home_homepage "Homepage">
+<!-- Localization note (home_homepage_every_new_tab): The user will see a switch to determine if the
+     home page will be use in every new tab. -->
+<!ENTITY home_homepage_every_new_tab "Also use for new tabs">
 <!ENTITY home_homepage_title "Set a Homepage">
 <!-- Localization note (home_homepage_radio_user_address): The user will see a series of radio
      buttons to choose the homepage they'd like to start on. When they click the radio
      button for this string, they will use the built-in default Firefox homepage (about:home). -->
 <!ENTITY home_homepage_radio_default "&brandShortName; Home">
 <!-- Localization note (home_homepage_radio_user_address): The user will see a series of radio
      buttons to choose the homepage they'd like to start on. When they click the radio
      button for this string, a text field will appear below the radio button and allow the
--- a/mobile/android/base/resources/xml/preferences_home.xml
+++ b/mobile/android/base/resources/xml/preferences_home.xml
@@ -11,16 +11,22 @@
                         android:key="android.not_a_preference.category_homepage">
 
         <org.mozilla.gecko.preferences.SetHomepagePreference
                 android:key="android.not_a_preference.homepage"
                 android:title="@string/home_homepage_title"
                 android:persistent="false"
                 android:dialogLayout="@layout/preference_set_homepage"/>
 
+        <SwitchPreference
+            android:key="android.not_a_preference.newtab.load_homepage"
+            android:title="@string/home_homepage_every_new_tab"
+            android:defaultValue="false"
+            android:persistent="true"/>
+
     </PreferenceCategory>
 
     <org.mozilla.gecko.preferences.PanelsPreferenceCategory
         android:title="@string/pref_category_home_panels"/>
 
     <PreferenceCategory android:title="@string/pref_category_home_add_ons">
 
         <ListPreference android:key="home.sync.updateMode"
--- a/mobile/android/base/strings.xml.in
+++ b/mobile/android/base/strings.xml.in
@@ -183,16 +183,17 @@
   <string name="pref_category_home_summary">&pref_category_home_summary;</string>
   <string name="pref_category_home_panels">&pref_category_home_panels;</string>
   <string name="pref_home_updates_wifi">&pref_home_updates_wifi;</string>
   <string name="pref_category_home_add_ons">&pref_category_home_add_ons;</string>
   <string name="pref_home_updates">&pref_home_updates2;</string>
   <string name="pref_home_updates_enabled">&pref_home_updates_enabled;</string>
   <string name="pref_category_home_homepage">&pref_category_home_homepage;</string>
   <string name="home_homepage_title">&home_homepage_title;</string>
+  <string name="home_homepage_every_new_tab">&home_homepage_every_new_tab;</string>
   <string name="home_homepage_radio_default">&home_homepage_radio_default;</string>
   <string name="home_homepage_radio_user_address">&home_homepage_radio_user_address;</string>
   <string name="home_homepage_hint_user_address">&home_homepage_hint_user_address;</string>
 
   <string name="pref_header_general">&pref_header_general;</string>
   <string name="pref_header_search">&pref_header_search;</string>
   <string name="pref_header_accessibility">&pref_header_accessibility;</string>
   <string name="pref_header_privacy_short">&pref_header_privacy_short;</string>