Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / ui / sync / profile_signin_confirmation_helper.cc
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.
4
5 #include "chrome/browser/ui/sync/profile_signin_confirmation_helper.h"
6
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_backend.h"
14 #include "chrome/browser/history/history_db_task.h"
15 #include "chrome/browser/history/history_service.h"
16 #include "chrome/browser/history/history_service_factory.h"
17 #include "chrome/browser/profiles/profile.h"
18 #include "components/bookmarks/browser/bookmark_model.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"
23
24 #if defined(ENABLE_EXTENSIONS)
25 #include "chrome/browser/extensions/extension_service.h"
26 #include "chrome/common/extensions/extension_constants.h"
27 #include "chrome/common/extensions/sync_helper.h"
28 #include "extensions/browser/extension_system.h"
29 #include "extensions/common/constants.h"
30 #include "extensions/common/extension.h"
31 #include "extensions/common/extension_set.h"
32 #endif
33
34 namespace {
35
36 const int kHistoryEntriesBeforeNewProfilePrompt = 10;
37
38 // Determines whether a profile has any typed URLs in its history.
39 class HasTypedURLsTask : public history::HistoryDBTask {
40  public:
41   explicit HasTypedURLsTask(const base::Callback<void(bool)>& cb)
42       : has_typed_urls_(false), cb_(cb) {
43   }
44
45   bool RunOnDBThread(history::HistoryBackend* backend,
46                      history::HistoryDatabase* db) override {
47     history::URLRows rows;
48     backend->GetAllTypedURLs(&rows);
49     if (!rows.empty()) {
50       DVLOG(1) << "ProfileSigninConfirmationHelper: profile contains "
51                << rows.size() << " typed URLs";
52       has_typed_urls_ = true;
53     }
54     return true;
55   }
56
57   void DoneRunOnMainThread() override { cb_.Run(has_typed_urls_); }
58
59  private:
60   ~HasTypedURLsTask() override {}
61
62   bool has_typed_urls_;
63   base::Callback<void(bool)> cb_;
64 };
65
66 bool HasBookmarks(Profile* profile) {
67   BookmarkModel* bookmarks = BookmarkModelFactory::GetForProfile(profile);
68   bool has_bookmarks = bookmarks && bookmarks->HasBookmarks();
69   if (has_bookmarks)
70     DVLOG(1) << "ProfileSigninConfirmationHelper: profile contains bookmarks";
71   return has_bookmarks;
72 }
73
74 // Helper functions for Chrome profile signin.
75 class ProfileSigninConfirmationHelper {
76  public:
77   ProfileSigninConfirmationHelper(
78       Profile* profile,
79       const base::Callback<void(bool)>& return_result);
80   void CheckHasHistory(int max_entries);
81   void CheckHasTypedURLs();
82
83  private:
84   // Deletes itself.
85   ~ProfileSigninConfirmationHelper();
86
87   void OnHistoryQueryResults(size_t max_entries,
88                              history::QueryResults* results);
89   void ReturnResult(bool result);
90
91   // Weak pointer to the profile being signed-in.
92   Profile* profile_;
93
94   // Used for async tasks.
95   base::CancelableTaskTracker task_tracker_;
96
97   // Keep track of how many async requests are pending.
98   int pending_requests_;
99
100   // Callback to pass the result back to the caller.
101   const base::Callback<void(bool)> return_result_;
102
103   DISALLOW_COPY_AND_ASSIGN(ProfileSigninConfirmationHelper);
104 };
105
106 ProfileSigninConfirmationHelper::ProfileSigninConfirmationHelper(
107     Profile* profile,
108     const base::Callback<void(bool)>& return_result)
109     : profile_(profile),
110       pending_requests_(0),
111       return_result_(return_result) {
112 }
113
114 ProfileSigninConfirmationHelper::~ProfileSigninConfirmationHelper() {
115   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
116 }
117
118 void ProfileSigninConfirmationHelper::OnHistoryQueryResults(
119     size_t max_entries,
120     history::QueryResults* results) {
121   history::QueryResults owned_results;
122   results->Swap(&owned_results);
123   bool too_much_history = owned_results.size() >= max_entries;
124   if (too_much_history) {
125     DVLOG(1) << "ProfileSigninConfirmationHelper: profile contains "
126              << owned_results.size() << " history entries";
127   }
128   ReturnResult(too_much_history);
129 }
130
131 void ProfileSigninConfirmationHelper::CheckHasHistory(int max_entries) {
132   HistoryService* service =
133       HistoryServiceFactory::GetForProfileWithoutCreating(profile_);
134   pending_requests_++;
135   if (!service) {
136     ReturnResult(false);
137     return;
138   }
139   history::QueryOptions opts;
140   opts.max_count = max_entries;
141   service->QueryHistory(
142       base::string16(),
143       opts,
144       base::Bind(&ProfileSigninConfirmationHelper::OnHistoryQueryResults,
145                  base::Unretained(this),
146                  max_entries),
147       &task_tracker_);
148 }
149
150 void ProfileSigninConfirmationHelper::CheckHasTypedURLs() {
151   HistoryService* service =
152       HistoryServiceFactory::GetForProfileWithoutCreating(profile_);
153   pending_requests_++;
154   if (!service) {
155     ReturnResult(false);
156     return;
157   }
158   service->ScheduleDBTask(
159       scoped_ptr<history::HistoryDBTask>(new HasTypedURLsTask(
160           base::Bind(&ProfileSigninConfirmationHelper::ReturnResult,
161                      base::Unretained(this)))),
162       &task_tracker_);
163 }
164
165 void ProfileSigninConfirmationHelper::ReturnResult(bool result) {
166   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
167   // Pass |true| into the callback as soon as one of the tasks passes a
168   // result of |true|, otherwise pass the last returned result.
169   if (--pending_requests_ == 0 || result) {
170     return_result_.Run(result);
171
172     // This leaks at shutdown if the HistoryService is destroyed, but
173     // the process is going to die anyway.
174     delete this;
175   }
176 }
177
178 }  // namespace
179
180 namespace ui {
181
182 SkColor GetSigninConfirmationPromptBarColor(SkAlpha alpha) {
183   static const SkColor kBackgroundColor =
184       ui::NativeTheme::instance()->GetSystemColor(
185           ui::NativeTheme::kColorId_DialogBackground);
186   return color_utils::BlendTowardOppositeLuminance(kBackgroundColor, alpha);
187 }
188
189 bool HasBeenShutdown(Profile* profile) {
190 #if defined(OS_IOS)
191   // This check is not useful on iOS: the browser can be shut down without
192   // explicit user action (for example, in response to memory pressure), and
193   // this should be invisible to the user. The desktop assumption that the
194   // profile going through a restart indicates something about user intention
195   // does not hold. We rely on the other profile dirtiness checks.
196   return false;
197 #else
198   bool has_been_shutdown = !profile->IsNewProfile();
199   if (has_been_shutdown)
200     DVLOG(1) << "ProfileSigninConfirmationHelper: profile is not new";
201   return has_been_shutdown;
202 #endif
203 }
204
205 bool HasSyncedExtensions(Profile* profile) {
206 #if defined(ENABLE_EXTENSIONS)
207   extensions::ExtensionSystem* system =
208       extensions::ExtensionSystem::Get(profile);
209   if (system && system->extension_service()) {
210     const extensions::ExtensionSet* extensions =
211         system->extension_service()->extensions();
212     for (extensions::ExtensionSet::const_iterator iter = extensions->begin();
213          iter != extensions->end(); ++iter) {
214       // The webstore is synced so that it stays put on the new tab
215       // page, but since it's installed by default we don't want to
216       // consider it when determining if the profile is dirty.
217       if (extensions::sync_helper::IsSyncable(iter->get()) &&
218           (*iter)->id() != extensions::kWebStoreAppId &&
219           (*iter)->id() != extension_misc::kChromeAppId) {
220         DVLOG(1) << "ProfileSigninConfirmationHelper: "
221                  << "profile contains a synced extension: " << (*iter)->id();
222         return true;
223       }
224     }
225   }
226 #endif
227   return false;
228 }
229
230 void CheckShouldPromptForNewProfile(
231     Profile* profile,
232     const base::Callback<void(bool)>& return_result) {
233   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
234
235   if (HasBeenShutdown(profile) ||
236       HasBookmarks(profile) ||
237       HasSyncedExtensions(profile)) {
238     return_result.Run(true);
239     return;
240   }
241   // Fire asynchronous queries for profile data.
242   ProfileSigninConfirmationHelper* helper =
243       new ProfileSigninConfirmationHelper(profile, return_result);
244   helper->CheckHasHistory(kHistoryEntriesBeforeNewProfilePrompt);
245   helper->CheckHasTypedURLs();
246 }
247
248 }  // namespace ui