Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / chrome / browser / ui / sync / profile_signin_confirmation_helper.cc
blob38f3462f74ecd0e8da596e0253bfa3d385fb0fd0
1 // Copyright 2013 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/ui/sync/profile_signin_confirmation_helper.h"
7 #include "base/bind.h"
8 #include "base/memory/ref_counted.h"
9 #include "base/prefs/pref_service.h"
10 #include "base/strings/string16.h"
11 #include "base/task/cancelable_task_tracker.h"
12 #include "chrome/browser/bookmarks/bookmark_model_factory.h"
13 #include "chrome/browser/history/history_service_factory.h"
14 #include "chrome/browser/profiles/profile.h"
15 #include "components/bookmarks/browser/bookmark_model.h"
16 #include "components/history/core/browser/history_backend.h"
17 #include "components/history/core/browser/history_db_task.h"
18 #include "components/history/core/browser/history_service.h"
19 #include "components/history/core/browser/history_types.h"
20 #include "content/public/browser/browser_thread.h"
21 #include "ui/gfx/color_utils.h"
22 #include "ui/native_theme/native_theme.h"
24 #if defined(ENABLE_EXTENSIONS)
25 #include "chrome/common/extensions/extension_constants.h"
26 #include "chrome/common/extensions/sync_helper.h"
27 #include "extensions/browser/extension_registry.h"
28 #include "extensions/common/constants.h"
29 #include "extensions/common/extension.h"
30 #include "extensions/common/extension_set.h"
31 #endif
33 using bookmarks::BookmarkModel;
35 namespace {
37 const int kHistoryEntriesBeforeNewProfilePrompt = 10;
39 // Determines whether a profile has any typed URLs in its history.
40 class HasTypedURLsTask : public history::HistoryDBTask {
41 public:
42 explicit HasTypedURLsTask(const base::Callback<void(bool)>& cb)
43 : has_typed_urls_(false), cb_(cb) {
46 bool RunOnDBThread(history::HistoryBackend* backend,
47 history::HistoryDatabase* db) override {
48 history::URLRows rows;
49 backend->GetAllTypedURLs(&rows);
50 if (!rows.empty()) {
51 DVLOG(1) << "ProfileSigninConfirmationHelper: profile contains "
52 << rows.size() << " typed URLs";
53 has_typed_urls_ = true;
55 return true;
58 void DoneRunOnMainThread() override { cb_.Run(has_typed_urls_); }
60 private:
61 ~HasTypedURLsTask() override {}
63 bool has_typed_urls_;
64 base::Callback<void(bool)> cb_;
67 bool HasBookmarks(Profile* profile) {
68 BookmarkModel* bookmarks = BookmarkModelFactory::GetForProfile(profile);
69 bool has_bookmarks = bookmarks && bookmarks->HasBookmarks();
70 if (has_bookmarks)
71 DVLOG(1) << "ProfileSigninConfirmationHelper: profile contains bookmarks";
72 return has_bookmarks;
75 // Helper functions for Chrome profile signin.
76 class ProfileSigninConfirmationHelper {
77 public:
78 ProfileSigninConfirmationHelper(
79 Profile* profile,
80 const base::Callback<void(bool)>& return_result);
81 void CheckHasHistory(int max_entries);
82 void CheckHasTypedURLs();
84 private:
85 // Deletes itself.
86 ~ProfileSigninConfirmationHelper();
88 void OnHistoryQueryResults(size_t max_entries,
89 history::QueryResults* results);
90 void ReturnResult(bool result);
92 // Weak pointer to the profile being signed-in.
93 Profile* profile_;
95 // Used for async tasks.
96 base::CancelableTaskTracker task_tracker_;
98 // Keep track of how many async requests are pending.
99 int pending_requests_;
101 // Callback to pass the result back to the caller.
102 const base::Callback<void(bool)> return_result_;
104 DISALLOW_COPY_AND_ASSIGN(ProfileSigninConfirmationHelper);
107 ProfileSigninConfirmationHelper::ProfileSigninConfirmationHelper(
108 Profile* profile,
109 const base::Callback<void(bool)>& return_result)
110 : profile_(profile),
111 pending_requests_(0),
112 return_result_(return_result) {
115 ProfileSigninConfirmationHelper::~ProfileSigninConfirmationHelper() {
116 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
119 void ProfileSigninConfirmationHelper::OnHistoryQueryResults(
120 size_t max_entries,
121 history::QueryResults* results) {
122 history::QueryResults owned_results;
123 results->Swap(&owned_results);
124 bool too_much_history = owned_results.size() >= max_entries;
125 if (too_much_history) {
126 DVLOG(1) << "ProfileSigninConfirmationHelper: profile contains "
127 << owned_results.size() << " history entries";
129 ReturnResult(too_much_history);
132 void ProfileSigninConfirmationHelper::CheckHasHistory(int max_entries) {
133 history::HistoryService* service =
134 HistoryServiceFactory::GetForProfileWithoutCreating(profile_);
135 pending_requests_++;
136 if (!service) {
137 ReturnResult(false);
138 return;
140 history::QueryOptions opts;
141 opts.max_count = max_entries;
142 service->QueryHistory(
143 base::string16(),
144 opts,
145 base::Bind(&ProfileSigninConfirmationHelper::OnHistoryQueryResults,
146 base::Unretained(this),
147 max_entries),
148 &task_tracker_);
151 void ProfileSigninConfirmationHelper::CheckHasTypedURLs() {
152 history::HistoryService* service =
153 HistoryServiceFactory::GetForProfileWithoutCreating(profile_);
154 pending_requests_++;
155 if (!service) {
156 ReturnResult(false);
157 return;
159 service->ScheduleDBTask(
160 scoped_ptr<history::HistoryDBTask>(new HasTypedURLsTask(
161 base::Bind(&ProfileSigninConfirmationHelper::ReturnResult,
162 base::Unretained(this)))),
163 &task_tracker_);
166 void ProfileSigninConfirmationHelper::ReturnResult(bool result) {
167 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
168 // Pass |true| into the callback as soon as one of the tasks passes a
169 // result of |true|, otherwise pass the last returned result.
170 if (--pending_requests_ == 0 || result) {
171 return_result_.Run(result);
173 // This leaks at shutdown if the HistoryService is destroyed, but
174 // the process is going to die anyway.
175 delete this;
179 } // namespace
181 namespace ui {
183 SkColor GetSigninConfirmationPromptBarColor(SkAlpha alpha) {
184 static const SkColor kBackgroundColor =
185 ui::NativeTheme::instance()->GetSystemColor(
186 ui::NativeTheme::kColorId_DialogBackground);
187 return color_utils::BlendTowardOppositeLuminance(kBackgroundColor, alpha);
190 bool HasBeenShutdown(Profile* profile) {
191 #if defined(OS_IOS)
192 // This check is not useful on iOS: the browser can be shut down without
193 // explicit user action (for example, in response to memory pressure), and
194 // this should be invisible to the user. The desktop assumption that the
195 // profile going through a restart indicates something about user intention
196 // does not hold. We rely on the other profile dirtiness checks.
197 return false;
198 #else
199 bool has_been_shutdown = !profile->IsNewProfile();
200 if (has_been_shutdown)
201 DVLOG(1) << "ProfileSigninConfirmationHelper: profile is not new";
202 return has_been_shutdown;
203 #endif
206 bool HasSyncedExtensions(Profile* profile) {
207 #if defined(ENABLE_EXTENSIONS)
208 extensions::ExtensionRegistry* registry =
209 extensions::ExtensionRegistry::Get(profile);
210 if (registry) {
211 for (const scoped_refptr<const extensions::Extension>& extension :
212 registry->enabled_extensions()) {
213 // The webstore is synced so that it stays put on the new tab
214 // page, but since it's installed by default we don't want to
215 // consider it when determining if the profile is dirty.
216 if (extensions::sync_helper::IsSyncable(extension.get()) &&
217 !extensions::sync_helper::IsSyncableComponentExtension(
218 extension.get())) {
219 DVLOG(1) << "ProfileSigninConfirmationHelper: "
220 << "profile contains a synced extension: " << extension->id();
221 return true;
225 #endif
226 return false;
229 void CheckShouldPromptForNewProfile(
230 Profile* profile,
231 const base::Callback<void(bool)>& return_result) {
232 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
234 if (HasBeenShutdown(profile) ||
235 HasBookmarks(profile) ||
236 HasSyncedExtensions(profile)) {
237 return_result.Run(true);
238 return;
240 // Fire asynchronous queries for profile data.
241 ProfileSigninConfirmationHelper* helper =
242 new ProfileSigninConfirmationHelper(profile, return_result);
243 helper->CheckHasHistory(kHistoryEntriesBeforeNewProfilePrompt);
244 helper->CheckHasTypedURLs();
247 } // namespace ui