OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #import "ios/chrome/browser/ui/activity_services/activity_type_util.h" | 5 #import "ios/chrome/browser/ui/activity_services/activity_type_util.h" |
6 | 6 |
7 #include "base/logging.h" | 7 #include "base/logging.h" |
8 #include "base/metrics/user_metrics.h" | 8 #include "base/metrics/user_metrics.h" |
9 #include "base/metrics/user_metrics_action.h" | 9 #include "base/metrics/user_metrics_action.h" |
| 10 #include "base/strings/sys_string_conversions.h" |
10 #import "ios/chrome/browser/ui/activity_services/appex_constants.h" | 11 #import "ios/chrome/browser/ui/activity_services/appex_constants.h" |
11 #import "ios/chrome/browser/ui/activity_services/print_activity.h" | 12 #import "ios/chrome/browser/ui/activity_services/print_activity.h" |
12 #include "ios/chrome/grit/ios_strings.h" | 13 #include "ios/chrome/grit/ios_strings.h" |
13 #include "ui/base/l10n/l10n_util_mac.h" | 14 #include "ui/base/l10n/l10n_util_mac.h" |
14 | 15 |
15 #if !defined(__has_feature) || !__has_feature(objc_arc) | 16 #if !defined(__has_feature) || !__has_feature(objc_arc) |
16 #error "This file requires ARC support." | 17 #error "This file requires ARC support." |
17 #endif | 18 #endif |
18 | 19 |
19 namespace { | 20 namespace { |
| 21 |
20 // A substring to identify activity strings that are from Password Management | 22 // A substring to identify activity strings that are from Password Management |
21 // App Extensions. This string is intentionally without the leading and | 23 // App Extensions. This string is intentionally without the leading and |
22 // trailing "." so it can be used as a prefix, suffix, or substring of the | 24 // trailing "." so it can be used as a prefix, suffix, or substring of the |
23 // App Extension's bundle ID. | 25 // App Extension's bundle ID. |
24 NSString* const kFindLoginActionBundleSubstring = @"find-login-action"; | 26 NSString* const kFindLoginActionBundleSubstring = @"find-login-action"; |
| 27 |
| 28 // Returns whether |activity_string| refers to a supported Password Management |
| 29 // App Extension. Supported extensions are listed in kAllPasswordManagerApps. |
| 30 // The |exact_match| field defines whether an exact match of bundle_id is |
| 31 // required to consider activity_string a match. To add more Password Manager |
| 32 // extensions, add more entries to the static array. |
| 33 bool IsPasswordManagerActivity(NSString* activity_string) { |
| 34 static struct { |
| 35 const char* bundle_id; |
| 36 bool exact_match; |
| 37 } kAllPasswordManagerApps[] = { |
| 38 // 1Password |
| 39 {"com.agilebits.onepassword-ios.extension", true}, |
| 40 // LastPass |
| 41 {"com.lastpass.ilastpass.LastPassExt", true}, |
| 42 // Dashlane |
| 43 {"com.dashlane.dashlanephonefinal.", false}}; |
| 44 |
| 45 std::string activity = base::SysNSStringToUTF8(activity_string); |
| 46 for (const auto& app : kAllPasswordManagerApps) { |
| 47 std::string bundle_id(app.bundle_id); |
| 48 if (app.exact_match) { |
| 49 if (activity == bundle_id) |
| 50 return true; |
| 51 } else { |
| 52 if (activity.find(bundle_id) == 0) |
| 53 return true; |
| 54 } |
| 55 } |
| 56 return false; |
25 } | 57 } |
26 | 58 |
| 59 } // namespace |
| 60 |
27 namespace activity_type_util { | 61 namespace activity_type_util { |
28 | 62 |
29 struct PrefixTypeAssociation { | 63 struct PrefixTypeAssociation { |
30 activity_type_util::ActivityType type_; | 64 activity_type_util::ActivityType type_; |
31 NSString* const prefix_; | 65 NSString* const prefix_; |
32 bool requiresExactMatch_; | 66 bool requiresExactMatch_; |
33 }; | 67 }; |
34 | 68 |
35 const PrefixTypeAssociation prefixTypeAssociations[] = { | 69 const PrefixTypeAssociation prefixTypeAssociations[] = { |
36 {NATIVE_FACEBOOK, @"com.apple.UIKit.activity.PostToFacebook", true}, | 70 {NATIVE_FACEBOOK, @"com.apple.UIKit.activity.PostToFacebook", true}, |
(...skipping 16 matching lines...) Expand all Loading... |
53 {THIRD_PARTY_WHATS_APP, @"net.whatsapp.WhatsApp.", false}, | 87 {THIRD_PARTY_WHATS_APP, @"net.whatsapp.WhatsApp.", false}, |
54 {THIRD_PARTY_LINE, @"jp.naver.line.", false}, | 88 {THIRD_PARTY_LINE, @"jp.naver.line.", false}, |
55 {THIRD_PARTY_VIBER, @"com.viber.", false}, | 89 {THIRD_PARTY_VIBER, @"com.viber.", false}, |
56 {THIRD_PARTY_SKYPE, @"com.skype.", false}, | 90 {THIRD_PARTY_SKYPE, @"com.skype.", false}, |
57 {THIRD_PARTY_TANGO, @"com.sgiggle.Tango.", false}, | 91 {THIRD_PARTY_TANGO, @"com.sgiggle.Tango.", false}, |
58 {THIRD_PARTY_WECHAT, @"com.tencent.xin.", false}, | 92 {THIRD_PARTY_WECHAT, @"com.tencent.xin.", false}, |
59 {THIRD_PARTY_EVERNOTE, @"com.evernote.", false}, | 93 {THIRD_PARTY_EVERNOTE, @"com.evernote.", false}, |
60 {THIRD_PARTY_PINTEREST, @"pinterest.", false}, | 94 {THIRD_PARTY_PINTEREST, @"pinterest.", false}, |
61 {THIRD_PARTY_POCKET, @"com.ideashower.ReadItLaterPro.", false}, | 95 {THIRD_PARTY_POCKET, @"com.ideashower.ReadItLaterPro.", false}, |
62 {THIRD_PARTY_READABILITY, @"com.readability.ReadabilityMobile.", false}, | 96 {THIRD_PARTY_READABILITY, @"com.readability.ReadabilityMobile.", false}, |
63 {THIRD_PARTY_INSTAPAPER, @"com.marcoarment.instapaperpro.", false}, | 97 {THIRD_PARTY_INSTAPAPER, @"com.marcoarment.instapaperpro.", false}}; |
64 {APPEX_PASSWORD_MANAGEMENT_1PASSWORD, | |
65 activity_services::kAppExtensionOnePassword, true}, | |
66 {APPEX_PASSWORD_MANAGEMENT_LASTPASS, | |
67 activity_services::kAppExtensionLastPass, true}, | |
68 {APPEX_PASSWORD_MANAGEMENT_DASHLANE, | |
69 activity_services::kAppExtensionDashlanePrefix, false}}; | |
70 | 98 |
71 ActivityType TypeFromString(NSString* activityString) { | 99 ActivityType TypeFromString(NSString* activityString) { |
72 DCHECK(activityString); | 100 DCHECK(activityString); |
73 // Checks for the special case first so the more general patterns in | 101 // Checks for the special case first so the more general patterns in |
74 // prefixTypeAssociations would not prematurely trapped them. | 102 // prefixTypeAssociations would not prematurely trapped them. |
75 NSRange found = | 103 NSRange found = |
76 [activityString rangeOfString:kFindLoginActionBundleSubstring]; | 104 [activityString rangeOfString:kFindLoginActionBundleSubstring]; |
77 if (found.length) | 105 if (found.length) |
78 return APPEX_PASSWORD_MANAGEMENT_OTHERS; | 106 return APPEX_PASSWORD_MANAGEMENT; |
79 for (auto const& assocation : prefixTypeAssociations) { | 107 for (auto const& assocation : prefixTypeAssociations) { |
80 if (assocation.requiresExactMatch_) { | 108 if (assocation.requiresExactMatch_) { |
81 if ([activityString isEqualToString:assocation.prefix_]) | 109 if ([activityString isEqualToString:assocation.prefix_]) |
82 return assocation.type_; | 110 return assocation.type_; |
83 } else { | 111 } else { |
84 if ([activityString hasPrefix:assocation.prefix_]) | 112 if ([activityString hasPrefix:assocation.prefix_]) |
85 return assocation.type_; | 113 return assocation.type_; |
86 } | 114 } |
87 } | 115 } |
| 116 if (IsPasswordManagerActivity(activityString)) { |
| 117 return APPEX_PASSWORD_MANAGEMENT; |
| 118 } |
88 return UNKNOWN; | 119 return UNKNOWN; |
89 } | 120 } |
90 | 121 |
91 NSNumber* PasswordAppExActivityVersion(NSString* activityString) { | 122 NSNumber* PasswordAppExActivityVersion(NSString* activityString) { |
92 switch (TypeFromString(activityString)) { | 123 switch (TypeFromString(activityString)) { |
93 case APPEX_PASSWORD_MANAGEMENT_1PASSWORD: | 124 case APPEX_PASSWORD_MANAGEMENT: |
94 case APPEX_PASSWORD_MANAGEMENT_LASTPASS: | |
95 case APPEX_PASSWORD_MANAGEMENT_DASHLANE: | |
96 case APPEX_PASSWORD_MANAGEMENT_OTHERS: | |
97 return activity_services::kPasswordAppExVersionNumber; | 125 return activity_services::kPasswordAppExVersionNumber; |
98 default: | 126 default: |
99 return nil; | 127 return nil; |
100 } | 128 } |
101 } | 129 } |
102 | 130 |
103 bool IsPasswordAppExActivity(NSString* activityString) { | 131 bool IsPasswordAppExActivity(NSString* activityString) { |
104 return PasswordAppExActivityVersion(activityString) != nil; | 132 return PasswordAppExActivityVersion(activityString) != nil; |
105 } | 133 } |
106 | 134 |
107 NSString* CompletionMessageForActivity(ActivityType type) { | 135 NSString* CompletionMessageForActivity(ActivityType type) { |
108 // Some activities can be reported as completed even if not successful. | 136 // Some activities can be reported as completed even if not successful. |
109 // Make sure that the message is meaningful even if the activity completed | 137 // Make sure that the message is meaningful even if the activity completed |
110 // unsuccessfully. | 138 // unsuccessfully. |
111 switch (type) { | 139 switch (type) { |
112 case NATIVE_CLIPBOARD: | 140 case NATIVE_CLIPBOARD: |
113 return l10n_util::GetNSString(IDS_IOS_SHARE_TO_CLIPBOARD_SUCCESS); | 141 return l10n_util::GetNSString(IDS_IOS_SHARE_TO_CLIPBOARD_SUCCESS); |
114 case APPEX_PASSWORD_MANAGEMENT_1PASSWORD: | 142 case APPEX_PASSWORD_MANAGEMENT: |
115 case APPEX_PASSWORD_MANAGEMENT_LASTPASS: | |
116 case APPEX_PASSWORD_MANAGEMENT_DASHLANE: | |
117 case APPEX_PASSWORD_MANAGEMENT_OTHERS: | |
118 return l10n_util::GetNSString(IDS_IOS_APPEX_PASSWORD_FORM_FILLED_SUCCESS); | 143 return l10n_util::GetNSString(IDS_IOS_APPEX_PASSWORD_FORM_FILLED_SUCCESS); |
119 default: | 144 default: |
120 return nil; | 145 return nil; |
121 } | 146 } |
122 } | 147 } |
123 | 148 |
124 void RecordMetricForActivity(ActivityType type) { | 149 void RecordMetricForActivity(ActivityType type) { |
125 switch (type) { | 150 switch (type) { |
126 case UNKNOWN: | 151 case UNKNOWN: |
127 base::RecordAction(base::UserMetricsAction("MobileShareMenuUnknown")); | 152 base::RecordAction(base::UserMetricsAction("MobileShareMenuUnknown")); |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
175 base::UserMetricsAction("MobileShareMenuToInstantMessagingApp")); | 200 base::UserMetricsAction("MobileShareMenuToInstantMessagingApp")); |
176 break; | 201 break; |
177 case THIRD_PARTY_EVERNOTE: | 202 case THIRD_PARTY_EVERNOTE: |
178 case THIRD_PARTY_PINTEREST: | 203 case THIRD_PARTY_PINTEREST: |
179 case THIRD_PARTY_POCKET: | 204 case THIRD_PARTY_POCKET: |
180 case THIRD_PARTY_READABILITY: | 205 case THIRD_PARTY_READABILITY: |
181 case THIRD_PARTY_INSTAPAPER: | 206 case THIRD_PARTY_INSTAPAPER: |
182 base::RecordAction( | 207 base::RecordAction( |
183 base::UserMetricsAction("MobileShareMenuToContentApp")); | 208 base::UserMetricsAction("MobileShareMenuToContentApp")); |
184 break; | 209 break; |
185 case APPEX_PASSWORD_MANAGEMENT_1PASSWORD: | 210 case APPEX_PASSWORD_MANAGEMENT: |
186 case APPEX_PASSWORD_MANAGEMENT_LASTPASS: | |
187 case APPEX_PASSWORD_MANAGEMENT_DASHLANE: | |
188 case APPEX_PASSWORD_MANAGEMENT_OTHERS: | |
189 base::RecordAction( | 211 base::RecordAction( |
190 base::UserMetricsAction("MobileAppExFormFilledByPasswordManager")); | 212 base::UserMetricsAction("MobileAppExFormFilledByPasswordManager")); |
191 break; | 213 break; |
192 } | 214 } |
193 } | 215 } |
194 | 216 |
195 } // activity_type_util | 217 } // activity_type_util |
OLD | NEW |