Commit 0bcaa8e5 authored by mlerman's avatar mlerman Committed by Commit bot

Profile_Metrics integration with Keystone

Chromium side of the implementation of tracking profile stats (number of profiles, number of signed in profiles) through the Omaha channel for Mac. Design doc: https://docs.google.com/a/google.com/document/d/15Ou8VCYNCZvke8Bw9bF3vYqD67voJBPyx_GBR8ONcCw/edit?disco=AAAAAKU7Zzg (Googler Only)

BUG=409895

Review URL: https://codereview.chromium.org/593243002

Cr-Commit-Position: refs/heads/master@{#318729}
parent 3e658b23
...@@ -87,6 +87,7 @@ enum BrandFileType { ...@@ -87,6 +87,7 @@ enum BrandFileType {
// And the Keystone registration itself, with the active timer // And the Keystone registration itself, with the active timer
KSRegistration* registration_; // strong KSRegistration* registration_; // strong
NSTimer* timer_; // strong NSTimer* timer_; // strong
Class ksUnsignedReportingAttributeClass_;
// The most recent kAutoupdateStatusNotification notification posted. // The most recent kAutoupdateStatusNotification notification posted.
base::scoped_nsobject<NSNotification> recentNotification_; base::scoped_nsobject<NSNotification> recentNotification_;
...@@ -101,6 +102,10 @@ enum BrandFileType { ...@@ -101,6 +102,10 @@ enum BrandFileType {
// YES if an update was ever successfully installed by -installUpdate. // YES if an update was ever successfully installed by -installUpdate.
BOOL updateSuccessfullyInstalled_; BOOL updateSuccessfullyInstalled_;
// Profile count information.
uint32_t numProfiles_;
uint32_t numSignedInProfiles_;
} }
// Return the default Keystone Glue object. // Return the default Keystone Glue object.
...@@ -172,6 +177,10 @@ enum BrandFileType { ...@@ -172,6 +177,10 @@ enum BrandFileType {
// at the installed copy. // at the installed copy.
- (void)setAppPath:(NSString*)appPath; - (void)setAppPath:(NSString*)appPath;
// Sets the total number of profiles and the number of signed in profiles.
- (void)updateProfileCountsWithNumProfiles:(uint32_t)profiles
numSignedInProfiles:(uint32_t)signedInProfiles;
@end // @interface KeystoneGlue @end // @interface KeystoneGlue
@interface KeystoneGlue(ExposedForTesting) @interface KeystoneGlue(ExposedForTesting)
......
...@@ -119,6 +119,9 @@ class PerformBridge : public base::RefCountedThreadSafe<PerformBridge> { ...@@ -119,6 +119,9 @@ class PerformBridge : public base::RefCountedThreadSafe<PerformBridge> {
// Called when Keystone registration completes. // Called when Keystone registration completes.
- (void)registrationComplete:(NSNotification*)notification; - (void)registrationComplete:(NSNotification*)notification;
// Set the registration active and pass profile count parameters.
- (void)setRegistrationActive;
// Called periodically to announce activity by pinging the Keystone server. // Called periodically to announce activity by pinging the Keystone server.
- (void)markActive:(NSTimer*)timer; - (void)markActive:(NSTimer*)timer;
...@@ -445,6 +448,8 @@ NSString* const kVersionKey = @"KSVersion"; ...@@ -445,6 +448,8 @@ NSString* const kVersionKey = @"KSVersion";
return NO; return NO;
registration_ = [ksr retain]; registration_ = [ksr retain];
ksUnsignedReportingAttributeClass_ =
[ksrBundle classNamed:@"KSUnsignedReportingAttribute"];
return YES; return YES;
} }
...@@ -491,6 +496,47 @@ NSString* const kVersionKey = @"KSVersion"; ...@@ -491,6 +496,47 @@ NSString* const kVersionKey = @"KSVersion";
nil]; nil];
} }
- (void)setRegistrationActive {
if (!registration_)
return;
// Should never have zero profiles. Do not report this value.
if (!numProfiles_) {
[registration_ setActive];
return;
}
NSError* reportingError = nil;
KSReportingAttribute* numAccountsAttr =
[ksUnsignedReportingAttributeClass_
reportingAttributeWithValue:numProfiles_
name:@"_NumAccounts"
aggregationType:kKSReportingAggregationSum
error:&reportingError];
if (reportingError != nil)
VLOG(1) << [reportingError localizedDescription];
reportingError = nil;
KSReportingAttribute* numSignedInAccountsAttr =
[ksUnsignedReportingAttributeClass_
reportingAttributeWithValue:numSignedInProfiles_
name:@"_NumSignedIn"
aggregationType:kKSReportingAggregationSum
error:&reportingError];
if (reportingError != nil)
VLOG(1) << [reportingError localizedDescription];
reportingError = nil;
NSArray* profileCountsInformation =
[NSArray arrayWithObjects:numAccountsAttr, numSignedInAccountsAttr, nil];
if (![registration_ setActiveWithReportingAttributes:profileCountsInformation
error:&reportingError]) {
VLOG(1) << [reportingError localizedDescription];
}
}
- (void)registerWithKeystone { - (void)registerWithKeystone {
[self updateStatus:kAutoupdateRegistering version:nil]; [self updateStatus:kAutoupdateRegistering version:nil];
...@@ -512,13 +558,13 @@ NSString* const kVersionKey = @"KSVersion"; ...@@ -512,13 +558,13 @@ NSString* const kVersionKey = @"KSVersion";
// posted, and -registrationComplete: will be called. // posted, and -registrationComplete: will be called.
// Mark an active RIGHT NOW; don't wait an hour for the first one. // Mark an active RIGHT NOW; don't wait an hour for the first one.
[registration_ setActive]; [self setRegistrationActive];
// Set up hourly activity pings. // Set up hourly activity pings.
timer_ = [NSTimer scheduledTimerWithTimeInterval:60 * 60 // One hour timer_ = [NSTimer scheduledTimerWithTimeInterval:60 * 60 // One hour
target:self target:self
selector:@selector(markActive:) selector:@selector(markActive:)
userInfo:registration_ userInfo:nil
repeats:YES]; repeats:YES];
} }
...@@ -541,8 +587,7 @@ NSString* const kVersionKey = @"KSVersion"; ...@@ -541,8 +587,7 @@ NSString* const kVersionKey = @"KSVersion";
} }
- (void)markActive:(NSTimer*)timer { - (void)markActive:(NSTimer*)timer {
KSRegistration* ksr = [timer userInfo]; [self setRegistrationActive];
[ksr setActive];
} }
- (void)checkForUpdate { - (void)checkForUpdate {
...@@ -1049,6 +1094,13 @@ NSString* const kVersionKey = @"KSVersion"; ...@@ -1049,6 +1094,13 @@ NSString* const kVersionKey = @"KSVersion";
return tagSuffix; return tagSuffix;
} }
- (void)updateProfileCountsWithNumProfiles:(uint32_t)profiles
numSignedInProfiles:(uint32_t)signedInProfiles {
numProfiles_ = profiles;
numSignedInProfiles_ = signedInProfiles;
}
@end // @implementation KeystoneGlue @end // @implementation KeystoneGlue
namespace { namespace {
......
...@@ -39,6 +39,11 @@ namespace ksr = keystone_registration; ...@@ -39,6 +39,11 @@ namespace ksr = keystone_registration;
return NO; return NO;
} }
- (BOOL)setActiveWithReportingAttributes:(NSArray*)reportingAttributes
error:(NSError**)error {
return NO;
}
- (void)checkForUpdateWasUserInitiated:(BOOL)userInitiated { - (void)checkForUpdateWasUserInitiated:(BOOL)userInitiated {
} }
......
...@@ -48,10 +48,19 @@ extern NSString* KSUpdateCheckSuccessfulKey; ...@@ -48,10 +48,19 @@ extern NSString* KSUpdateCheckSuccessfulKey;
extern NSString* KSUpdateCheckSuccessfullyInstalledKey; extern NSString* KSUpdateCheckSuccessfullyInstalledKey;
extern NSString* KSRegistrationRemoveExistingTag; extern NSString* KSRegistrationRemoveExistingTag;
extern NSString* KSReportingAttributeValueKey;
extern NSString* KSReportingAttributeExpirationDateKey;
extern NSString* KSReportingAttributeAggregationTypeKey;
#define KSRegistrationPreserveExistingTag nil #define KSRegistrationPreserveExistingTag nil
} // namespace keystone_registration } // namespace keystone_registration
typedef enum {
kKSReportingAggregationSum = 0, // Adds attribute value across user accounts
kKSReportingAggregationDefault = kKSReportingAggregationSum,
} KSReportingAggregationType;
@interface KSRegistration : NSObject @interface KSRegistration : NSObject
+ (id)registrationWithProductID:(NSString*)productID; + (id)registrationWithProductID:(NSString*)productID;
...@@ -62,10 +71,30 @@ extern NSString* KSRegistrationRemoveExistingTag; ...@@ -62,10 +71,30 @@ extern NSString* KSRegistrationRemoveExistingTag;
authorization:(AuthorizationRef)authorization; authorization:(AuthorizationRef)authorization;
- (BOOL)setActive; - (BOOL)setActive;
- (BOOL)setActiveWithReportingAttributes:(NSArray*)reportingAttributes
error:(NSError**)error;
- (void)checkForUpdateWasUserInitiated:(BOOL)userInitiated; - (void)checkForUpdateWasUserInitiated:(BOOL)userInitiated;
- (void)startUpdate; - (void)startUpdate;
- (keystone_registration::KSRegistrationTicketType)ticketType; - (keystone_registration::KSRegistrationTicketType)ticketType;
@end // @interface KSRegistration @end // @interface KSRegistration
// Declarations of the Keystone attribute reporting bits needed here.
// Full definition is at:
// //depot/googlemac/opensource/update-engine/Common/KSReportingAttribute.h
@interface KSReportingAttribute : NSObject
@end // @interface KSReportingAttribute
@interface KSUnsignedReportingAttribute : KSReportingAttribute
+ (KSUnsignedReportingAttribute *)reportingAttributeWithValue:(uint32_t)value
name:(NSString *)name
aggregationType:(KSReportingAggregationType)aggregationType
error:(NSError **)error;
@end // @interface KSUnsignedReportingAttribute
#endif // CHROME_BROWSER_MAC_KEYSTONE_REGISTRATION_H_ #endif // CHROME_BROWSER_MAC_KEYSTONE_REGISTRATION_H_
...@@ -39,4 +39,8 @@ NSString* KSUpdateCheckSuccessfullyInstalledKey = @"SuccessfullyInstalled"; ...@@ -39,4 +39,8 @@ NSString* KSUpdateCheckSuccessfullyInstalledKey = @"SuccessfullyInstalled";
NSString* KSRegistrationRemoveExistingTag = @""; NSString* KSRegistrationRemoveExistingTag = @"";
NSString* KSReportingAttributeValueKey = @"value";
NSString* KSReportingAttributeExpirationDateKey = @"expiresAt";
NSString* KSReportingAttributeAggregationTypeKey = @"aggregation";
} // namespace keystone_registration } // namespace keystone_registration
...@@ -20,7 +20,10 @@ ...@@ -20,7 +20,10 @@
namespace { namespace {
#if defined(OS_WIN) || defined(OS_MACOSX)
const int kMaximumReportedProfileCount = 5; const int kMaximumReportedProfileCount = 5;
#endif
const int kMaximumDaysOfDisuse = 4 * 7; // Should be integral number of weeks. const int kMaximumDaysOfDisuse = 4 * 7; // Should be integral number of weeks.
size_t number_of_profile_switches_ = 0; size_t number_of_profile_switches_ = 0;
...@@ -67,12 +70,6 @@ ProfileMetrics::ProfileType GetProfileType( ...@@ -67,12 +70,6 @@ ProfileMetrics::ProfileType GetProfileType(
return metric; return metric;
} }
void UpdateReportedOSProfileStatistics(int active, int signedin) {
#if defined(OS_WIN)
GoogleUpdateSettings::UpdateProfileCounts(active, signedin);
#endif
}
void LogLockedProfileInformation(ProfileManager* manager) { void LogLockedProfileInformation(ProfileManager* manager) {
const ProfileInfoCache& info_cache = manager->GetProfileInfoCache(); const ProfileInfoCache& info_cache = manager->GetProfileInfoCache();
size_t number_of_profiles = info_cache.GetNumberOfProfiles(); size_t number_of_profiles = info_cache.GetNumberOfProfiles();
...@@ -177,10 +174,11 @@ bool ProfileMetrics::CountProfileInformation(ProfileManager* manager, ...@@ -177,10 +174,11 @@ bool ProfileMetrics::CountProfileInformation(ProfileManager* manager,
} }
void ProfileMetrics::UpdateReportedProfilesStatistics(ProfileManager* manager) { void ProfileMetrics::UpdateReportedProfilesStatistics(ProfileManager* manager) {
#if defined(OS_WIN) || defined(OS_MACOSX)
ProfileCounts counts; ProfileCounts counts;
if (CountProfileInformation(manager, &counts)) { if (CountProfileInformation(manager, &counts)) {
int limited_total = counts.total; size_t limited_total = counts.total;
int limited_signedin = counts.signedin; size_t limited_signedin = counts.signedin;
if (limited_total > kMaximumReportedProfileCount) { if (limited_total > kMaximumReportedProfileCount) {
limited_total = kMaximumReportedProfileCount + 1; limited_total = kMaximumReportedProfileCount + 1;
limited_signedin = limited_signedin =
...@@ -189,6 +187,7 @@ void ProfileMetrics::UpdateReportedProfilesStatistics(ProfileManager* manager) { ...@@ -189,6 +187,7 @@ void ProfileMetrics::UpdateReportedProfilesStatistics(ProfileManager* manager) {
} }
UpdateReportedOSProfileStatistics(limited_total, limited_signedin); UpdateReportedOSProfileStatistics(limited_total, limited_signedin);
} }
#endif
} }
void ProfileMetrics::LogNumberOfProfileSwitches() { void ProfileMetrics::LogNumberOfProfileSwitches() {
...@@ -196,6 +195,14 @@ void ProfileMetrics::LogNumberOfProfileSwitches() { ...@@ -196,6 +195,14 @@ void ProfileMetrics::LogNumberOfProfileSwitches() {
number_of_profile_switches_); number_of_profile_switches_);
} }
// The OS_MACOSX implementation of this function is in profile_metrics_mac.mm.
#if defined(OS_WIN)
void ProfileMetrics::UpdateReportedOSProfileStatistics(
size_t active, size_t signedin) {
GoogleUpdateSettings::UpdateProfileCounts(active, signedin);
}
#endif
void ProfileMetrics::LogNumberOfProfiles(ProfileManager* manager) { void ProfileMetrics::LogNumberOfProfiles(ProfileManager* manager) {
ProfileCounts counts; ProfileCounts counts;
bool success = CountProfileInformation(manager, &counts); bool success = CountProfileInformation(manager, &counts);
...@@ -217,7 +224,10 @@ void ProfileMetrics::LogNumberOfProfiles(ProfileManager* manager) { ...@@ -217,7 +224,10 @@ void ProfileMetrics::LogNumberOfProfiles(ProfileManager* manager) {
counts.auth_errors); counts.auth_errors);
LogLockedProfileInformation(manager); LogLockedProfileInformation(manager);
#if defined(OS_WIN) || defined(OS_MACOSX)
UpdateReportedOSProfileStatistics(counts.total, counts.signedin); UpdateReportedOSProfileStatistics(counts.total, counts.signedin);
#endif
} }
} }
......
...@@ -208,6 +208,11 @@ class ProfileMetrics { ...@@ -208,6 +208,11 @@ class ProfileMetrics {
ProfileCounts* counts); ProfileCounts* counts);
static void LogNumberOfProfileSwitches(); static void LogNumberOfProfileSwitches();
#if defined(OS_WIN) || defined(OS_MACOSX)
// Update OS level tracking of profile counts.
static void UpdateReportedOSProfileStatistics(size_t active, size_t signedin);
#endif
static void LogNumberOfProfiles(ProfileManager* manager); static void LogNumberOfProfiles(ProfileManager* manager);
static void LogProfileAddNewUser(ProfileAdd metric); static void LogProfileAddNewUser(ProfileAdd metric);
static void LogProfileAvatarSelection(size_t icon_index); static void LogProfileAvatarSelection(size_t icon_index);
......
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/profiles/profile_metrics.h"
#include "base/numerics/safe_conversions.h"
#include "chrome/browser/mac/keystone_glue.h"
void ProfileMetrics::UpdateReportedOSProfileStatistics(
size_t active, size_t signedin) {
if (base::IsValueInRangeForNumericType<uint32_t>(active) &&
base::IsValueInRangeForNumericType<uint32_t>(signedin)) {
[[KeystoneGlue defaultKeystoneGlue]
updateProfileCountsWithNumProfiles:active
numSignedInProfiles:signedin];
}
}
...@@ -2244,6 +2244,7 @@ ...@@ -2244,6 +2244,7 @@
'browser/profiles/profile_metrics.cc', 'browser/profiles/profile_metrics.cc',
'browser/profiles/profile_metrics.h', 'browser/profiles/profile_metrics.h',
'browser/profiles/profile_metrics_list.h', 'browser/profiles/profile_metrics_list.h',
'browser/profiles/profile_metrics_mac.mm',
'browser/profiles/profile_shortcut_manager_win.cc', 'browser/profiles/profile_shortcut_manager_win.cc',
'browser/profiles/profile_shortcut_manager_win.h', 'browser/profiles/profile_shortcut_manager_win.h',
'browser/profiles/profiles_state.cc', 'browser/profiles/profiles_state.cc',
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#include "chrome/installer/util/google_update_settings.h" #include "chrome/installer/util/google_update_settings.h"
#include <algorithm> #include <algorithm>
#include <limits>
#include "base/command_line.h" #include "base/command_line.h"
#include "base/files/file_path.h" #include "base/files/file_path.h"
...@@ -70,7 +71,7 @@ bool ReadGoogleUpdateStrKey(const wchar_t* const name, base::string16* value) { ...@@ -70,7 +71,7 @@ bool ReadGoogleUpdateStrKey(const wchar_t* const name, base::string16* value) {
bool WriteGoogleUpdateAggregateNumKeyInternal( bool WriteGoogleUpdateAggregateNumKeyInternal(
const AppRegistrationData& app_reg_data, const AppRegistrationData& app_reg_data,
const wchar_t* const name, const wchar_t* const name,
int value, size_t value,
const wchar_t* const aggregate) { const wchar_t* const aggregate) {
DCHECK(aggregate); DCHECK(aggregate);
DCHECK(GoogleUpdateSettings::IsSystemInstall()); DCHECK(GoogleUpdateSettings::IsSystemInstall());
...@@ -90,7 +91,11 @@ bool WriteGoogleUpdateAggregateNumKeyInternal( ...@@ -90,7 +91,11 @@ bool WriteGoogleUpdateAggregateNumKeyInternal(
reg_path.append(name); reg_path.append(name);
RegKey key(HKEY_LOCAL_MACHINE, reg_path.c_str(), kAccess); RegKey key(HKEY_LOCAL_MACHINE, reg_path.c_str(), kAccess);
key.WriteValue(google_update::kRegAggregateMethod, aggregate); key.WriteValue(google_update::kRegAggregateMethod, aggregate);
return (key.WriteValue(uniquename.c_str(), value) == ERROR_SUCCESS);
DWORD dword_value = (value > std::numeric_limits<DWORD>::max() ?
std::numeric_limits<DWORD>::max() :
static_cast<DWORD>(value));
return (key.WriteValue(uniquename.c_str(), dword_value) == ERROR_SUCCESS);
} }
// Updates a registry key |name| to be |value| for the given |app_reg_data|. // Updates a registry key |name| to be |value| for the given |app_reg_data|.
...@@ -546,8 +551,8 @@ bool GoogleUpdateSettings::UpdateGoogleUpdateApKey( ...@@ -546,8 +551,8 @@ bool GoogleUpdateSettings::UpdateGoogleUpdateApKey(
return modified; return modified;
} }
void GoogleUpdateSettings::UpdateProfileCounts(int profiles_active, void GoogleUpdateSettings::UpdateProfileCounts(size_t profiles_active,
int profiles_signedin) { size_t profiles_signedin) {
BrowserDistribution* dist = BrowserDistribution::GetDistribution(); BrowserDistribution* dist = BrowserDistribution::GetDistribution();
// System-level installs must write into the ClientStateMedium key shared by // System-level installs must write into the ClientStateMedium key shared by
// all users. Special treatment is used to aggregate across those users. // all users. Special treatment is used to aggregate across those users.
...@@ -569,10 +574,10 @@ void GoogleUpdateSettings::UpdateProfileCounts(int profiles_active, ...@@ -569,10 +574,10 @@ void GoogleUpdateSettings::UpdateProfileCounts(int profiles_active,
// user-level installs. // user-level installs.
WriteGoogleUpdateStrKeyInternal(dist->GetAppRegistrationData(), WriteGoogleUpdateStrKeyInternal(dist->GetAppRegistrationData(),
google_update::kRegProfilesActive, google_update::kRegProfilesActive,
base::IntToString16(profiles_active)); base::SizeTToString16(profiles_active));
WriteGoogleUpdateStrKeyInternal(dist->GetAppRegistrationData(), WriteGoogleUpdateStrKeyInternal(dist->GetAppRegistrationData(),
google_update::kRegProfilesSignedIn, google_update::kRegProfilesSignedIn,
base::IntToString16(profiles_signedin)); base::SizeTToString16(profiles_signedin));
} }
} }
......
...@@ -218,7 +218,8 @@ class GoogleUpdateSettings { ...@@ -218,7 +218,8 @@ class GoogleUpdateSettings {
// This method updates the values that report how many profiles are in use // This method updates the values that report how many profiles are in use
// and how many of those are signed-in. // and how many of those are signed-in.
static void UpdateProfileCounts(int profiles_active, int profiles_signedin); static void UpdateProfileCounts(size_t profiles_active,
size_t profiles_signedin);
// For system-level installs, we need to be able to communicate the results // For system-level installs, we need to be able to communicate the results
// of the Toast Experiments back to Google Update. The problem is just that // of the Toast Experiments back to Google Update. The problem is just that
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment