Upstream version 8.37.180.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 "chrome/browser/bookmarks/bookmark_model_factory.h"
12 #include "chrome/browser/common/cancelable_request.h"
13 #include "chrome/browser/extensions/extension_service.h"
14 #include "chrome/browser/history/history_backend.h"
15 #include "chrome/browser/history/history_db_task.h"
16 #include "chrome/browser/history/history_service.h"
17 #include "chrome/browser/history/history_service_factory.h"
18 #include "chrome/browser/history/history_types.h"
19 #include "chrome/browser/profiles/profile.h"
20 #include "chrome/common/extensions/extension_constants.h"
21 #include "chrome/common/extensions/sync_helper.h"
22 #include "components/bookmarks/browser/bookmark_model.h"
23 #include "extensions/browser/extension_system.h"
24 #include "extensions/common/extension.h"
25 #include "extensions/common/extension_set.h"
26 #include "ui/gfx/color_utils.h"
27 #include "ui/native_theme/native_theme.h"
28
29 namespace {
30
31 const int kHistoryEntriesBeforeNewProfilePrompt = 10;
32
33 // Determines whether a profile has any typed URLs in its history.
34 class HasTypedURLsTask : public history::HistoryDBTask {
35  public:
36   HasTypedURLsTask(const base::Callback<void(bool)>& cb)
37       : has_typed_urls_(false), cb_(cb) {
38   }
39
40   virtual bool RunOnDBThread(history::HistoryBackend* backend,
41                              history::HistoryDatabase* db) OVERRIDE {
42     history::URLRows rows;
43     backend->GetAllTypedURLs(&rows);
44     if (!rows.empty()) {
45       DVLOG(1) << "ProfileSigninConfirmationHelper: profile contains "
46                << rows.size() << " typed URLs";
47       has_typed_urls_ = true;
48     }
49     return true;
50   }
51
52   virtual void DoneRunOnMainThread() OVERRIDE {
53     cb_.Run(has_typed_urls_);
54   }
55
56  private:
57   virtual ~HasTypedURLsTask() {}
58   bool has_typed_urls_;
59   base::Callback<void(bool)> cb_;
60 };
61
62 bool HasBookmarks(Profile* profile) {
63   BookmarkModel* bookmarks = BookmarkModelFactory::GetForProfile(profile);
64   bool has_bookmarks = bookmarks && bookmarks->HasBookmarks();
65   if (has_bookmarks)
66     DVLOG(1) << "ProfileSigninConfirmationHelper: profile contains bookmarks";
67   return has_bookmarks;
68 }
69
70 // Helper functions for Chrome profile signin.
71 class ProfileSigninConfirmationHelper
72     : public base::RefCounted<ProfileSigninConfirmationHelper> {
73  public:
74   ProfileSigninConfirmationHelper(
75       Profile* profile,
76       const base::Callback<void(bool)>& return_result);
77   void CheckHasHistory(int max_entries);
78   void CheckHasTypedURLs();
79   void set_pending_requests(int requests);
80
81  private:
82   friend class base::RefCounted<ProfileSigninConfirmationHelper>;
83
84   ~ProfileSigninConfirmationHelper();
85
86   void OnHistoryQueryResults(size_t max_entries,
87                              CancelableRequestProvider::Handle handle,
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   CancelableRequestConsumer request_consumer_;
96
97   // Keep track of how many async requests are pending.
98   int pending_requests_;
99
100   // Indicates whether the result has already been returned to caller.
101   bool result_returned_;
102
103   // Callback to pass the result back to the caller.
104   const base::Callback<void(bool)> return_result_;
105
106   DISALLOW_COPY_AND_ASSIGN(ProfileSigninConfirmationHelper);
107 };
108
109 ProfileSigninConfirmationHelper::ProfileSigninConfirmationHelper(
110     Profile* profile,
111     const base::Callback<void(bool)>& return_result)
112     : profile_(profile),
113       pending_requests_(0),
114       result_returned_(false),
115       return_result_(return_result) {
116 }
117
118 ProfileSigninConfirmationHelper::~ProfileSigninConfirmationHelper() {
119 }
120
121 void ProfileSigninConfirmationHelper::OnHistoryQueryResults(
122     size_t max_entries,
123     CancelableRequestProvider::Handle handle,
124     history::QueryResults* results) {
125   history::QueryResults owned_results;
126   results->Swap(&owned_results);
127   bool too_much_history = owned_results.size() >= max_entries;
128   if (too_much_history) {
129     DVLOG(1) << "ProfileSigninConfirmationHelper: profile contains "
130              << owned_results.size() << " history entries";
131   }
132   ReturnResult(too_much_history);
133 }
134
135 void ProfileSigninConfirmationHelper::CheckHasHistory(int max_entries) {
136   HistoryService* service =
137       HistoryServiceFactory::GetForProfileWithoutCreating(profile_);
138   if (!service) {
139     ReturnResult(false);
140     return;
141   }
142   history::QueryOptions opts;
143   opts.max_count = max_entries;
144   service->QueryHistory(
145       base::string16(), opts, &request_consumer_,
146       base::Bind(&ProfileSigninConfirmationHelper::OnHistoryQueryResults,
147                  this,
148                  max_entries));
149 }
150
151 void ProfileSigninConfirmationHelper::CheckHasTypedURLs() {
152   HistoryService* service =
153       HistoryServiceFactory::GetForProfileWithoutCreating(profile_);
154   if (!service) {
155     ReturnResult(false);
156     return;
157   }
158   service->ScheduleDBTask(
159       new HasTypedURLsTask(
160           base::Bind(
161               &ProfileSigninConfirmationHelper::ReturnResult,
162               this)),
163       &request_consumer_);
164 }
165
166 void ProfileSigninConfirmationHelper::set_pending_requests(int requests) {
167   pending_requests_ = requests;
168 }
169
170 void ProfileSigninConfirmationHelper::ReturnResult(bool result) {
171   // Pass |true| into the callback as soon as one of the tasks passes a
172   // result of |true|, otherwise pass the last returned result.
173   if (!result_returned_ && (--pending_requests_ == 0 || result)) {
174     result_returned_ = true;
175     request_consumer_.CancelAllRequests();
176     return_result_.Run(result);
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   bool has_been_shutdown = !profile->IsNewProfile();
193   if (has_been_shutdown)
194     DVLOG(1) << "ProfileSigninConfirmationHelper: profile is not new";
195   return has_been_shutdown;
196 }
197
198 bool HasSyncedExtensions(Profile* profile) {
199   extensions::ExtensionSystem* system =
200       extensions::ExtensionSystem::Get(profile);
201   if (system && system->extension_service()) {
202     const extensions::ExtensionSet* extensions =
203         system->extension_service()->extensions();
204     for (extensions::ExtensionSet::const_iterator iter = extensions->begin();
205          iter != extensions->end(); ++iter) {
206       // The webstore is synced so that it stays put on the new tab
207       // page, but since it's installed by default we don't want to
208       // consider it when determining if the profile is dirty.
209       if (extensions::sync_helper::IsSyncable(iter->get()) &&
210           (*iter)->id() != extension_misc::kWebStoreAppId &&
211           (*iter)->id() != extension_misc::kChromeAppId) {
212         DVLOG(1) << "ProfileSigninConfirmationHelper: "
213                  << "profile contains a synced extension: " << (*iter)->id();
214         return true;
215       }
216     }
217   }
218   return false;
219 }
220
221 void CheckShouldPromptForNewProfile(
222     Profile* profile,
223     const base::Callback<void(bool)>& return_result) {
224   if (HasBeenShutdown(profile) ||
225       HasBookmarks(profile) ||
226       HasSyncedExtensions(profile)) {
227     return_result.Run(true);
228     return;
229   }
230   // Fire asynchronous queries for profile data.
231   scoped_refptr<ProfileSigninConfirmationHelper> helper =
232       new ProfileSigninConfirmationHelper(profile, return_result);
233   const int requests = 2;
234   helper->set_pending_requests(requests);
235   helper->CheckHasHistory(kHistoryEntriesBeforeNewProfilePrompt);
236   helper->CheckHasTypedURLs();
237 }
238
239 }  // namespace ui