1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/prefs/session_startup_pref.h"
9 #include "base/metrics/histogram.h"
10 #include "base/prefs/pref_service.h"
11 #include "base/prefs/scoped_user_pref_update.h"
12 #include "base/time/time.h"
13 #include "base/values.h"
14 #include "base/version.h"
15 #include "chrome/browser/profiles/profile.h"
16 #include "chrome/common/pref_names.h"
17 #include "components/pref_registry/pref_registry_syncable.h"
18 #include "components/url_fixer/url_fixer.h"
20 #if defined(OS_MACOSX)
21 #include "chrome/browser/ui/cocoa/window_restore_utils.h"
26 enum StartupURLsMigrationMetrics
{
27 STARTUP_URLS_MIGRATION_METRICS_PERFORMED
,
28 STARTUP_URLS_MIGRATION_METRICS_NOT_PRESENT
,
29 STARTUP_URLS_MIGRATION_METRICS_RESET
,
30 STARTUP_URLS_MIGRATION_METRICS_MAX
,
33 // Converts a SessionStartupPref::Type to an integer written to prefs.
34 int TypeToPrefValue(SessionStartupPref::Type type
) {
36 case SessionStartupPref::LAST
: return SessionStartupPref::kPrefValueLast
;
37 case SessionStartupPref::URLS
: return SessionStartupPref::kPrefValueURLs
;
38 default: return SessionStartupPref::kPrefValueNewTab
;
42 void SetNewURLList(PrefService
* prefs
) {
43 if (prefs
->IsUserModifiablePreference(prefs::kURLsToRestoreOnStartup
)) {
44 base::ListValue new_url_pref_list
;
45 base::StringValue
* home_page
=
46 new base::StringValue(prefs
->GetString(prefs::kHomePage
));
47 new_url_pref_list
.Append(home_page
);
48 prefs
->Set(prefs::kURLsToRestoreOnStartup
, new_url_pref_list
);
52 void URLListToPref(const base::ListValue
* url_list
, SessionStartupPref
* pref
) {
54 for (size_t i
= 0; i
< url_list
->GetSize(); ++i
) {
56 if (url_list
->GetString(i
, &url_text
)) {
57 GURL fixed_url
= url_fixer::FixupURL(url_text
, std::string());
58 pref
->urls
.push_back(fixed_url
);
66 void SessionStartupPref::RegisterProfilePrefs(
67 user_prefs::PrefRegistrySyncable
* registry
) {
68 registry
->RegisterIntegerPref(
69 prefs::kRestoreOnStartup
,
70 TypeToPrefValue(GetDefaultStartupType()),
71 user_prefs::PrefRegistrySyncable::SYNCABLE_PREF
);
72 registry
->RegisterListPref(prefs::kURLsToRestoreOnStartup
,
73 user_prefs::PrefRegistrySyncable::SYNCABLE_PREF
);
74 registry
->RegisterListPref(prefs::kURLsToRestoreOnStartupOld
);
75 registry
->RegisterBooleanPref(prefs::kRestoreOnStartupMigrated
, false);
76 registry
->RegisterInt64Pref(prefs::kRestoreStartupURLsMigrationTime
, false);
80 SessionStartupPref::Type
SessionStartupPref::GetDefaultStartupType() {
81 #if defined(OS_CHROMEOS)
82 return SessionStartupPref::LAST
;
84 return SessionStartupPref::DEFAULT
;
89 void SessionStartupPref::SetStartupPref(
91 const SessionStartupPref
& pref
) {
93 SetStartupPref(profile
->GetPrefs(), pref
);
97 void SessionStartupPref::SetStartupPref(PrefService
* prefs
,
98 const SessionStartupPref
& pref
) {
101 if (!SessionStartupPref::TypeIsManaged(prefs
))
102 prefs
->SetInteger(prefs::kRestoreOnStartup
, TypeToPrefValue(pref
.type
));
104 if (!SessionStartupPref::URLsAreManaged(prefs
)) {
105 // Always save the URLs, that way the UI can remain consistent even if the
106 // user changes the startup type pref.
107 // Ownership of the ListValue retains with the pref service.
108 ListPrefUpdate
update(prefs
, prefs::kURLsToRestoreOnStartup
);
109 base::ListValue
* url_pref_list
= update
.Get();
110 DCHECK(url_pref_list
);
111 url_pref_list
->Clear();
112 for (size_t i
= 0; i
< pref
.urls
.size(); ++i
) {
113 url_pref_list
->Set(static_cast<int>(i
),
114 new base::StringValue(pref
.urls
[i
].spec()));
120 SessionStartupPref
SessionStartupPref::GetStartupPref(Profile
* profile
) {
122 return GetStartupPref(profile
->GetPrefs());
126 SessionStartupPref
SessionStartupPref::GetStartupPref(PrefService
* prefs
) {
129 MigrateIfNecessary(prefs
);
130 MigrateMacDefaultPrefIfNecessary(prefs
);
132 SessionStartupPref
pref(
133 PrefValueToType(prefs
->GetInteger(prefs::kRestoreOnStartup
)));
135 // Always load the urls, even if the pref type isn't URLS. This way the
136 // preferences panels can show the user their last choice.
137 const base::ListValue
* url_list
=
138 prefs
->GetList(prefs::kURLsToRestoreOnStartup
);
139 URLListToPref(url_list
, &pref
);
145 void SessionStartupPref::MigrateIfNecessary(PrefService
* prefs
) {
148 // Check if we need to migrate the old version of the startup URLs preference
149 // to the new name, and also send metrics about the migration.
150 StartupURLsMigrationMetrics metrics_result
=
151 STARTUP_URLS_MIGRATION_METRICS_MAX
;
152 const base::ListValue
* old_startup_urls
=
153 prefs
->GetList(prefs::kURLsToRestoreOnStartupOld
);
154 if (!prefs
->GetUserPrefValue(prefs::kRestoreStartupURLsMigrationTime
)) {
155 // Record the absence of the migration timestamp, this will get overwritten
156 // below if migration occurs now.
157 metrics_result
= STARTUP_URLS_MIGRATION_METRICS_NOT_PRESENT
;
159 // Seems like we never migrated, do it if necessary.
160 if (!prefs
->GetUserPrefValue(prefs::kURLsToRestoreOnStartup
)) {
161 if (old_startup_urls
&& !old_startup_urls
->empty()) {
162 prefs
->Set(prefs::kURLsToRestoreOnStartup
, *old_startup_urls
);
163 prefs
->ClearPref(prefs::kURLsToRestoreOnStartupOld
);
165 metrics_result
= STARTUP_URLS_MIGRATION_METRICS_PERFORMED
;
168 prefs
->SetInt64(prefs::kRestoreStartupURLsMigrationTime
,
169 base::Time::Now().ToInternalValue());
170 } else if (old_startup_urls
&& !old_startup_urls
->empty()) {
171 // Migration needs to be reset.
172 prefs
->ClearPref(prefs::kURLsToRestoreOnStartupOld
);
173 base::Time last_migration_time
= base::Time::FromInternalValue(
174 prefs
->GetInt64(prefs::kRestoreStartupURLsMigrationTime
));
175 base::Time now
= base::Time::Now();
176 prefs
->SetInt64(prefs::kRestoreStartupURLsMigrationTime
,
177 now
.ToInternalValue());
178 if (now
< last_migration_time
)
179 last_migration_time
= now
;
180 UMA_HISTOGRAM_CUSTOM_TIMES("Settings.StartupURLsResetTime",
181 now
- last_migration_time
,
182 base::TimeDelta::FromDays(0),
183 base::TimeDelta::FromDays(7),
185 metrics_result
= STARTUP_URLS_MIGRATION_METRICS_RESET
;
188 // Record a metric migration event if something interesting happened.
189 if (metrics_result
!= STARTUP_URLS_MIGRATION_METRICS_MAX
) {
190 UMA_HISTOGRAM_ENUMERATION(
191 "Settings.StartupURLsMigration",
193 STARTUP_URLS_MIGRATION_METRICS_MAX
);
196 if (!prefs
->GetBoolean(prefs::kRestoreOnStartupMigrated
)) {
197 // Read existing values.
198 const base::Value
* homepage_is_new_tab_page_value
=
199 prefs
->GetUserPrefValue(prefs::kHomePageIsNewTabPage
);
200 bool homepage_is_new_tab_page
= true;
201 if (homepage_is_new_tab_page_value
) {
202 if (!homepage_is_new_tab_page_value
->GetAsBoolean(
203 &homepage_is_new_tab_page
))
207 const base::Value
* restore_on_startup_value
=
208 prefs
->GetUserPrefValue(prefs::kRestoreOnStartup
);
209 int restore_on_startup
= -1;
210 if (restore_on_startup_value
) {
211 if (!restore_on_startup_value
->GetAsInteger(&restore_on_startup
))
215 // If restore_on_startup has the deprecated value kPrefValueHomePage,
216 // migrate it to open the homepage on startup. If 'homepage is NTP' is set,
217 // that means just opening the NTP. If not, it means opening a one-item URL
218 // list containing the homepage.
219 if (restore_on_startup
== kPrefValueHomePage
) {
220 if (homepage_is_new_tab_page
) {
221 prefs
->SetInteger(prefs::kRestoreOnStartup
, kPrefValueNewTab
);
223 prefs
->SetInteger(prefs::kRestoreOnStartup
, kPrefValueURLs
);
224 SetNewURLList(prefs
);
226 } else if (!restore_on_startup_value
&& !homepage_is_new_tab_page
&&
227 GetDefaultStartupType() == DEFAULT
) {
228 // kRestoreOnStartup was never set by the user, but the homepage was set.
229 // Migrate to the list of URLs. (If restore_on_startup was never set,
230 // and homepage_is_new_tab_page is true, no action is needed. The new
231 // default value is "open the new tab page" which is what we want.)
232 prefs
->SetInteger(prefs::kRestoreOnStartup
, kPrefValueURLs
);
233 SetNewURLList(prefs
);
236 prefs
->SetBoolean(prefs::kRestoreOnStartupMigrated
, true);
241 void SessionStartupPref::MigrateMacDefaultPrefIfNecessary(PrefService
* prefs
) {
242 #if defined(OS_MACOSX)
244 if (!restore_utils::IsWindowRestoreEnabled())
246 // The default startup pref used to be LAST, now it is DEFAULT. Don't change
247 // the setting for existing profiles (even if the user has never changed it),
248 // but make new profiles default to DEFAULT.
249 bool old_profile_version
=
250 !prefs
->FindPreference(
251 prefs::kProfileCreatedByVersion
)->IsDefaultValue() &&
252 Version(prefs
->GetString(prefs::kProfileCreatedByVersion
)).IsOlderThan(
254 if (old_profile_version
&& TypeIsDefault(prefs
))
255 prefs
->SetInteger(prefs::kRestoreOnStartup
, kPrefValueLast
);
260 bool SessionStartupPref::TypeIsManaged(PrefService
* prefs
) {
262 const PrefService::Preference
* pref_restore
=
263 prefs
->FindPreference(prefs::kRestoreOnStartup
);
264 DCHECK(pref_restore
);
265 return pref_restore
->IsManaged();
269 bool SessionStartupPref::URLsAreManaged(PrefService
* prefs
) {
271 const PrefService::Preference
* pref_urls
=
272 prefs
->FindPreference(prefs::kURLsToRestoreOnStartup
);
274 return pref_urls
->IsManaged();
278 bool SessionStartupPref::TypeIsDefault(PrefService
* prefs
) {
280 const PrefService::Preference
* pref_restore
=
281 prefs
->FindPreference(prefs::kRestoreOnStartup
);
282 DCHECK(pref_restore
);
283 return pref_restore
->IsDefaultValue();
287 SessionStartupPref::Type
SessionStartupPref::PrefValueToType(int pref_value
) {
288 switch (pref_value
) {
289 case kPrefValueLast
: return SessionStartupPref::LAST
;
290 case kPrefValueURLs
: return SessionStartupPref::URLS
;
291 case kPrefValueHomePage
: return SessionStartupPref::HOMEPAGE
;
292 default: return SessionStartupPref::DEFAULT
;
296 SessionStartupPref::SessionStartupPref(Type type
) : type(type
) {}
298 SessionStartupPref::~SessionStartupPref() {}