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