OLD | NEW |
(Empty) | |
| 1 // Copyright 2014 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 #import "ios/chrome/browser/ui/bookmarks/bookmark_promo_controller.h" |
| 6 |
| 7 #include <memory> |
| 8 |
| 9 #include "base/mac/scoped_nsobject.h" |
| 10 #include "base/metrics/histogram.h" |
| 11 #include "base/metrics/user_metrics.h" |
| 12 #include "components/pref_registry/pref_registry_syncable.h" |
| 13 #include "components/prefs/pref_service.h" |
| 14 #include "components/signin/core/browser/signin_manager.h" |
| 15 #include "google_apis/gaia/google_service_auth_error.h" |
| 16 #include "ios/chrome/browser/browser_state/chrome_browser_state.h" |
| 17 #include "ios/chrome/browser/pref_names.h" |
| 18 #include "ios/chrome/browser/signin/signin_manager_factory.h" |
| 19 #import "ios/chrome/browser/ui/commands/generic_chrome_command.h" |
| 20 #import "ios/chrome/browser/ui/commands/show_signin_command.h" |
| 21 #import "ios/chrome/browser/ui/ui_util.h" |
| 22 |
| 23 namespace { |
| 24 // Enum is used to record the actions performed by the user on the promo cell. |
| 25 // |Stars.PromoActions|. |
| 26 enum { |
| 27 // Recorded each time the promo cell is presented to the user. |
| 28 BOOKMARKS_PROMO_ACTION_DISPLAYED, |
| 29 // The user selected the NO THANKS button. |
| 30 BOOKMARKS_PROMO_ACTION_DISMISSED, |
| 31 // The user selected the SIGN-IN button. |
| 32 BOOKMARKS_PROMO_ACTION_COMPLETED, |
| 33 // NOTE: Add new promo actions in sources only immediately above this line. |
| 34 // Also, make sure the enum list for histogram |Stars.PromoActions| in |
| 35 // histograms.xml is updated with any change in here. |
| 36 BOOKMARKS_PROMO_ACTION_COUNT |
| 37 }; |
| 38 |
| 39 // The histogram used to record user actions performed on the promo cell. |
| 40 const char kBookmarksPromoActionsHistogram[] = "Stars.PromoActions"; |
| 41 |
| 42 class SignInObserver; |
| 43 } // namespace |
| 44 |
| 45 @interface BookmarkPromoController () { |
| 46 bool _isIncognito; |
| 47 ios::ChromeBrowserState* _browserState; |
| 48 std::unique_ptr<SignInObserver> _signinObserver; |
| 49 bool _promoDisplayedRecorded; |
| 50 } |
| 51 |
| 52 // Records that the promo was displayed. Can be called several times per |
| 53 // instance but will effectively record the histogram only once per instance. |
| 54 - (void)recordPromoDisplayed; |
| 55 |
| 56 // SignInObserver Callbacks |
| 57 |
| 58 // Called when a user signs into Google services such as sync. |
| 59 - (void)googleSigninSucceededWithAccountId:(const std::string&)account_id |
| 60 username:(const std::string&)username |
| 61 password:(const std::string&)password; |
| 62 |
| 63 // Called when the currently signed-in user for a user has been signed out. |
| 64 - (void)googleSignedOutWithAcountId:(const std::string&)account_id |
| 65 username:(const std::string&)username; |
| 66 |
| 67 @end |
| 68 |
| 69 namespace { |
| 70 class SignInObserver : public SigninManagerBase::Observer { |
| 71 public: |
| 72 SignInObserver(BookmarkPromoController* controller) |
| 73 : controller_(controller) {} |
| 74 |
| 75 void GoogleSigninSucceeded(const std::string& account_id, |
| 76 const std::string& username, |
| 77 const std::string& password) override { |
| 78 [controller_ googleSigninSucceededWithAccountId:account_id |
| 79 username:username |
| 80 password:password]; |
| 81 } |
| 82 |
| 83 void GoogleSignedOut(const std::string& account_id, |
| 84 const std::string& username) override { |
| 85 [controller_ googleSignedOutWithAcountId:account_id username:username]; |
| 86 } |
| 87 |
| 88 private: |
| 89 // Weak |
| 90 BookmarkPromoController* controller_; |
| 91 }; |
| 92 } // namespace |
| 93 |
| 94 @implementation BookmarkPromoController |
| 95 |
| 96 @synthesize delegate = _delegate; |
| 97 @synthesize promoState = _promoState; |
| 98 |
| 99 + (void)registerBrowserStatePrefs:(user_prefs::PrefRegistrySyncable*)registry { |
| 100 registry->RegisterBooleanPref(prefs::kIosBookmarkPromoAlreadySeen, false); |
| 101 } |
| 102 |
| 103 - (instancetype)initWithBrowserState:(ios::ChromeBrowserState*)browserState |
| 104 delegate: |
| 105 (id<BookmarkPromoControllerDelegate>)delegate { |
| 106 self = [super init]; |
| 107 if (self) { |
| 108 _delegate = delegate; |
| 109 // Incognito browserState can go away before this class is released, this |
| 110 // code avoids keeping a pointer to it. |
| 111 _isIncognito = browserState->IsOffTheRecord(); |
| 112 if (!_isIncognito) { |
| 113 _browserState = browserState; |
| 114 _signinObserver.reset(new SignInObserver(self)); |
| 115 SigninManager* signinManager = |
| 116 ios::SigninManagerFactory::GetForBrowserState(_browserState); |
| 117 signinManager->AddObserver(_signinObserver.get()); |
| 118 } |
| 119 [self updatePromoState]; |
| 120 } |
| 121 return self; |
| 122 } |
| 123 |
| 124 - (void)dealloc { |
| 125 if (!_isIncognito) { |
| 126 DCHECK(_browserState); |
| 127 SigninManager* signinManager = |
| 128 ios::SigninManagerFactory::GetForBrowserState(_browserState); |
| 129 signinManager->RemoveObserver(_signinObserver.get()); |
| 130 } |
| 131 [super dealloc]; |
| 132 } |
| 133 |
| 134 - (void)showSignIn { |
| 135 UMA_HISTOGRAM_ENUMERATION(kBookmarksPromoActionsHistogram, |
| 136 BOOKMARKS_PROMO_ACTION_COMPLETED, |
| 137 BOOKMARKS_PROMO_ACTION_COUNT); |
| 138 base::RecordAction( |
| 139 base::UserMetricsAction("Signin_Signin_FromBookmarkManager")); |
| 140 base::scoped_nsobject<ShowSigninCommand> command([[ShowSigninCommand alloc] |
| 141 initWithOperation:AUTHENTICATION_OPERATION_SIGNIN |
| 142 signInAccessPoint:signin_metrics::AccessPoint:: |
| 143 ACCESS_POINT_BOOKMARK_MANAGER]); |
| 144 [self chromeExecuteCommand:command]; |
| 145 } |
| 146 |
| 147 - (void)hidePromoCell { |
| 148 DCHECK(!_isIncognito); |
| 149 DCHECK(_browserState); |
| 150 |
| 151 UMA_HISTOGRAM_ENUMERATION(kBookmarksPromoActionsHistogram, |
| 152 BOOKMARKS_PROMO_ACTION_DISMISSED, |
| 153 BOOKMARKS_PROMO_ACTION_COUNT); |
| 154 PrefService* prefs = _browserState->GetPrefs(); |
| 155 prefs->SetBoolean(prefs::kIosBookmarkPromoAlreadySeen, true); |
| 156 self.promoState = NO; |
| 157 } |
| 158 |
| 159 - (void)setPromoState:(BOOL)promoState { |
| 160 if (_promoState != promoState) { |
| 161 _promoState = promoState; |
| 162 [self.delegate promoStateChanged:promoState]; |
| 163 } |
| 164 } |
| 165 |
| 166 - (void)updatePromoState { |
| 167 self.promoState = NO; |
| 168 if (_isIncognito) |
| 169 return; |
| 170 |
| 171 DCHECK(_browserState); |
| 172 PrefService* prefs = _browserState->GetPrefs(); |
| 173 if (!prefs->GetBoolean(prefs::kIosBookmarkPromoAlreadySeen)) { |
| 174 SigninManager* signinManager = |
| 175 ios::SigninManagerFactory::GetForBrowserState(_browserState); |
| 176 self.promoState = !signinManager->IsAuthenticated(); |
| 177 if (self.promoState) |
| 178 [self recordPromoDisplayed]; |
| 179 } |
| 180 } |
| 181 |
| 182 #pragma mark - Private |
| 183 |
| 184 - (void)chromeExecuteCommand:(id)sender { |
| 185 id delegate = [[UIApplication sharedApplication] delegate]; |
| 186 if ([delegate respondsToSelector:@selector(chromeExecuteCommand:)]) |
| 187 [delegate chromeExecuteCommand:sender]; |
| 188 } |
| 189 |
| 190 - (void)recordPromoDisplayed { |
| 191 if (_promoDisplayedRecorded) |
| 192 return; |
| 193 _promoDisplayedRecorded = YES; |
| 194 UMA_HISTOGRAM_ENUMERATION(kBookmarksPromoActionsHistogram, |
| 195 BOOKMARKS_PROMO_ACTION_DISPLAYED, |
| 196 BOOKMARKS_PROMO_ACTION_COUNT); |
| 197 base::RecordAction( |
| 198 base::UserMetricsAction("Signin_Impression_FromBookmarkManager")); |
| 199 } |
| 200 |
| 201 #pragma mark - SignInObserver |
| 202 |
| 203 // Called when a user signs into Google services such as sync. |
| 204 - (void)googleSigninSucceededWithAccountId:(const std::string&)account_id |
| 205 username:(const std::string&)username |
| 206 password:(const std::string&)password { |
| 207 self.promoState = NO; |
| 208 } |
| 209 |
| 210 // Called when the currently signed-in user for a user has been signed out. |
| 211 - (void)googleSignedOutWithAcountId:(const std::string&)account_id |
| 212 username:(const std::string&)username { |
| 213 [self updatePromoState]; |
| 214 } |
| 215 |
| 216 @end |
OLD | NEW |