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