- add sources.
[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.h"
12 #include "chrome/browser/bookmarks/bookmark_model_factory.h"
13 #include "chrome/browser/common/cancelable_request.h"
14 #include "chrome/browser/extensions/extension_service.h"
15 #include "chrome/browser/extensions/extension_system.h"
16 #include "chrome/browser/history/history_backend.h"
17 #include "chrome/browser/history/history_db_task.h"
18 #include "chrome/browser/history/history_service.h"
19 #include "chrome/browser/history/history_service_factory.h"
20 #include "chrome/browser/history/history_types.h"
21 #include "chrome/browser/profiles/profile.h"
22 #include "chrome/common/extensions/extension.h"
23 #include "chrome/common/extensions/extension_set.h"
24 #include "chrome/common/extensions/sync_helper.h"
25 #include "ui/gfx/color_utils.h"
26 #include "ui/native_theme/native_theme.h"
27
28 // TODO(dconnelly): change VLOG to DVLOG (crbug.com/240195)
29
30 namespace {
31
32 const int kHistoryEntriesBeforeNewProfilePrompt = 10;
33
34 // Determines whether a profile has any typed URLs in its history.
35 class HasTypedURLsTask : public history::HistoryDBTask {
36  public:
37   HasTypedURLsTask(const base::Callback<void(bool)>& cb)
38       : has_typed_urls_(false), cb_(cb) {
39   }
40
41   virtual bool RunOnDBThread(history::HistoryBackend* backend,
42                              history::HistoryDatabase* db) OVERRIDE {
43     history::URLRows rows;
44     backend->GetAllTypedURLs(&rows);
45     if (!rows.empty()) {
46       VLOG(1) << "ProfileSigninConfirmationHelper: profile contains "
47               << rows.size() << " typed URLs";
48       has_typed_urls_ = true;
49     }
50     return true;
51   }
52
53   virtual void DoneRunOnMainThread() OVERRIDE {
54     cb_.Run(has_typed_urls_);
55   }
56
57  private:
58   virtual ~HasTypedURLsTask() {}
59   bool has_typed_urls_;
60   base::Callback<void(bool)> cb_;
61 };
62
63 bool HasBookmarks(Profile* profile) {
64   BookmarkModel* bookmarks = BookmarkModelFactory::GetForProfile(profile);
65   bool has_bookmarks = bookmarks && bookmarks->HasBookmarks();
66   if (has_bookmarks)
67     VLOG(1) << "ProfileSigninConfirmationHelper: profile contains bookmarks";
68   return has_bookmarks;
69 }
70
71 // Helper functions for Chrome profile signin.
72 class ProfileSigninConfirmationHelper
73     : public base::RefCounted<ProfileSigninConfirmationHelper> {
74  public:
75   ProfileSigninConfirmationHelper(
76       Profile* profile,
77       const base::Callback<void(bool)>& return_result);
78   void CheckHasHistory(int max_entries);
79   void CheckHasTypedURLs();
80   void set_pending_requests(int requests);
81
82  private:
83   friend class base::RefCounted<ProfileSigninConfirmationHelper>;
84
85   ~ProfileSigninConfirmationHelper();
86
87   void OnHistoryQueryResults(size_t max_entries,
88                              CancelableRequestProvider::Handle handle,
89                              history::QueryResults* results);
90   void ReturnResult(bool result);
91
92   // Weak pointer to the profile being signed-in.
93   Profile* profile_;
94
95   // Used for async tasks.
96   CancelableRequestConsumer request_consumer_;
97
98   // Keep track of how many async requests are pending.
99   int pending_requests_;
100
101   // Indicates whether the result has already been returned to caller.
102   bool result_returned_;
103
104   // Callback to pass the result back to the caller.
105   const base::Callback<void(bool)> return_result_;
106
107   DISALLOW_COPY_AND_ASSIGN(ProfileSigninConfirmationHelper);
108 };
109
110 ProfileSigninConfirmationHelper::ProfileSigninConfirmationHelper(
111     Profile* profile,
112     const base::Callback<void(bool)>& return_result)
113     : profile_(profile),
114       pending_requests_(0),
115       result_returned_(false),
116       return_result_(return_result) {
117 }
118
119 ProfileSigninConfirmationHelper::~ProfileSigninConfirmationHelper() {
120 }
121
122 void ProfileSigninConfirmationHelper::OnHistoryQueryResults(
123     size_t max_entries,
124     CancelableRequestProvider::Handle handle,
125     history::QueryResults* results) {
126   history::QueryResults owned_results;
127   results->Swap(&owned_results);
128   bool too_much_history = owned_results.size() >= max_entries;
129   if (too_much_history) {
130     VLOG(1) << "ProfileSigninConfirmationHelper: profile contains "
131             << owned_results.size() << " history entries";
132   }
133   ReturnResult(too_much_history);
134 }
135
136 void ProfileSigninConfirmationHelper::CheckHasHistory(int max_entries) {
137   HistoryService* service =
138       HistoryServiceFactory::GetForProfileWithoutCreating(profile_);
139   if (!service) {
140     ReturnResult(false);
141     return;
142   }
143   history::QueryOptions opts;
144   opts.max_count = max_entries;
145   service->QueryHistory(
146       string16(), opts, &request_consumer_,
147       base::Bind(&ProfileSigninConfirmationHelper::OnHistoryQueryResults,
148                  this,
149                  max_entries));
150 }
151
152 void ProfileSigninConfirmationHelper::CheckHasTypedURLs() {
153   HistoryService* service =
154       HistoryServiceFactory::GetForProfileWithoutCreating(profile_);
155   if (!service) {
156     ReturnResult(false);
157     return;
158   }
159   service->ScheduleDBTask(
160       new HasTypedURLsTask(
161           base::Bind(
162               &ProfileSigninConfirmationHelper::ReturnResult,
163               this)),
164       &request_consumer_);
165 }
166
167 void ProfileSigninConfirmationHelper::set_pending_requests(int requests) {
168   pending_requests_ = requests;
169 }
170
171 void ProfileSigninConfirmationHelper::ReturnResult(bool result) {
172   // Pass |true| into the callback as soon as one of the tasks passes a
173   // result of |true|, otherwise pass the last returned result.
174   if (!result_returned_ && (--pending_requests_ == 0 || result)) {
175     result_returned_ = true;
176     request_consumer_.CancelAllRequests();
177     return_result_.Run(result);
178   }
179 }
180
181 }  // namespace
182
183 namespace ui {
184
185 SkColor GetSigninConfirmationPromptBarColor(SkAlpha alpha) {
186   static const SkColor kBackgroundColor =
187       ui::NativeTheme::instance()->GetSystemColor(
188           ui::NativeTheme::kColorId_DialogBackground);
189   return color_utils::BlendTowardOppositeLuminance(kBackgroundColor, alpha);
190 }
191
192 bool HasBeenShutdown(Profile* profile) {
193   bool has_been_shutdown = !profile->IsNewProfile();
194   if (has_been_shutdown)
195     VLOG(1) << "ProfileSigninConfirmationHelper: profile is not new";
196   return has_been_shutdown;
197 }
198
199 bool HasSyncedExtensions(Profile* profile) {
200   extensions::ExtensionSystem* system =
201       extensions::ExtensionSystem::Get(profile);
202   if (system && system->extension_service()) {
203     const ExtensionSet* extensions = system->extension_service()->extensions();
204     for (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         VLOG(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