Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(127)

Side by Side Diff: chrome/browser/android/banners/app_banner_infobar_delegate_android.cc

Issue 2301263004: Add WebAPK installation metrics. (Closed)
Patch Set: Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 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 #include "chrome/browser/android/banners/app_banner_infobar_delegate_android.h" 5 #include "chrome/browser/android/banners/app_banner_infobar_delegate_android.h"
6 6
7 #include "base/android/jni_android.h" 7 #include "base/android/jni_android.h"
8 #include "base/android/jni_string.h" 8 #include "base/android/jni_string.h"
9 #include "base/guid.h" 9 #include "base/guid.h"
10 #include "base/location.h" 10 #include "base/location.h"
11 #include "base/memory/ptr_util.h" 11 #include "base/memory/ptr_util.h"
12 #include "base/strings/string16.h" 12 #include "base/strings/string16.h"
13 #include "base/strings/utf_string_conversions.h" 13 #include "base/strings/utf_string_conversions.h"
14 #include "chrome/browser/android/shortcut_helper.h" 14 #include "chrome/browser/android/shortcut_helper.h"
15 #include "chrome/browser/android/shortcut_info.h" 15 #include "chrome/browser/android/shortcut_info.h"
16 #include "chrome/browser/android/tab_android.h" 16 #include "chrome/browser/android/tab_android.h"
17 #include "chrome/browser/android/webapk/webapk_installer.h" 17 #include "chrome/browser/android/webapk/webapk_installer.h"
18 #include "chrome/browser/android/webapk/webapk_metrics.h"
18 #include "chrome/browser/banners/app_banner_manager.h" 19 #include "chrome/browser/banners/app_banner_manager.h"
19 #include "chrome/browser/banners/app_banner_metrics.h" 20 #include "chrome/browser/banners/app_banner_metrics.h"
20 #include "chrome/browser/banners/app_banner_settings_helper.h" 21 #include "chrome/browser/banners/app_banner_settings_helper.h"
21 #include "chrome/browser/browser_process.h" 22 #include "chrome/browser/browser_process.h"
22 #include "chrome/browser/infobars/infobar_service.h" 23 #include "chrome/browser/infobars/infobar_service.h"
23 #include "chrome/browser/ui/android/infobars/app_banner_infobar_android.h" 24 #include "chrome/browser/ui/android/infobars/app_banner_infobar_android.h"
24 #include "chrome/common/render_messages.h" 25 #include "chrome/common/render_messages.h"
25 #include "components/rappor/rappor_utils.h" 26 #include "components/rappor/rappor_utils.h"
26 #include "content/public/browser/render_frame_host.h" 27 #include "content/public/browser/render_frame_host.h"
27 #include "content/public/browser/web_contents.h" 28 #include "content/public/browser/web_contents.h"
28 #include "content/public/common/manifest.h" 29 #include "content/public/common/manifest.h"
29 #include "jni/AppBannerInfoBarDelegateAndroid_jni.h" 30 #include "jni/AppBannerInfoBarDelegateAndroid_jni.h"
30 #include "ui/gfx/android/java_bitmap.h" 31 #include "ui/gfx/android/java_bitmap.h"
31 #include "url/gurl.h" 32 #include "url/gurl.h"
32 33
33 using base::android::ConvertJavaStringToUTF8; 34 using base::android::ConvertJavaStringToUTF8;
34 using base::android::ConvertJavaStringToUTF16; 35 using base::android::ConvertJavaStringToUTF16;
35 using base::android::ConvertUTF8ToJavaString; 36 using base::android::ConvertUTF8ToJavaString;
36 using base::android::ConvertUTF16ToJavaString; 37 using base::android::ConvertUTF16ToJavaString;
37 using base::android::JavaParamRef; 38 using base::android::JavaParamRef;
38 using base::android::ScopedJavaLocalRef; 39 using base::android::ScopedJavaLocalRef;
39 40
40 namespace { 41 namespace {
41 42
42 bool IsInfoEmpty(const ShortcutInfo* info) { 43 bool IsInfoEmpty(const ShortcutInfo* info) {
43 return !info || info->url.is_empty(); 44 return !info || info->url.is_empty();
44 } 45 }
45 46
47 void TrackWebApkDismissEvents(banners::InstallState install_state) {
48 if (install_state == banners::WAIT_FOR_START)
49 webapk::TrackDismissEvent(webapk::DISMISS_EVENT_ADD_TO_HOMESCREEN);
50 else if (install_state == banners::INSTALLING)
51 webapk::TrackDismissEvent(webapk::DISMISS_EVENT_ADDING);
52 else if (install_state == banners::INSTALLED)
53 webapk::TrackDismissEvent(webapk::DISMISS_EVENT_OPEN);
54 }
55
46 } // anonymous namespace 56 } // anonymous namespace
47 57
48 namespace banners { 58 namespace banners {
49 59
50 AppBannerInfoBarDelegateAndroid::AppBannerInfoBarDelegateAndroid( 60 AppBannerInfoBarDelegateAndroid::AppBannerInfoBarDelegateAndroid(
51 base::WeakPtr<AppBannerManager> weak_manager, 61 base::WeakPtr<AppBannerManager> weak_manager,
52 const base::string16& app_title, 62 const base::string16& app_title,
53 const GURL& manifest_url, 63 const GURL& manifest_url,
54 std::unique_ptr<ShortcutInfo> shortcut_info, 64 std::unique_ptr<ShortcutInfo> shortcut_info,
55 const GURL& icon_url, 65 const GURL& icon_url,
56 std::unique_ptr<SkBitmap> icon, 66 std::unique_ptr<SkBitmap> icon,
57 int event_request_id, 67 int event_request_id,
58 bool is_webapk) 68 bool is_webapk)
59 : weak_manager_(weak_manager), 69 : weak_manager_(weak_manager),
60 app_title_(app_title), 70 app_title_(app_title),
61 manifest_url_(manifest_url), 71 manifest_url_(manifest_url),
62 shortcut_info_(std::move(shortcut_info)), 72 shortcut_info_(std::move(shortcut_info)),
63 icon_url_(icon_url), 73 icon_url_(icon_url),
64 icon_(std::move(icon)), 74 icon_(std::move(icon)),
65 event_request_id_(event_request_id), 75 event_request_id_(event_request_id),
66 has_user_interaction_(false), 76 has_user_interaction_(false),
67 is_webapk_(is_webapk), 77 is_webapk_(is_webapk),
78 install_state_(WAIT_FOR_START),
68 weak_ptr_factory_(this) { 79 weak_ptr_factory_(this) {
69 DCHECK(!IsInfoEmpty(shortcut_info_.get())); 80 DCHECK(!IsInfoEmpty(shortcut_info_.get()));
70 CreateJavaDelegate(); 81 CreateJavaDelegate();
71 } 82 }
72 83
73 AppBannerInfoBarDelegateAndroid::AppBannerInfoBarDelegateAndroid( 84 AppBannerInfoBarDelegateAndroid::AppBannerInfoBarDelegateAndroid(
74 const base::string16& app_title, 85 const base::string16& app_title,
75 const base::android::ScopedJavaGlobalRef<jobject>& native_app_data, 86 const base::android::ScopedJavaGlobalRef<jobject>& native_app_data,
76 std::unique_ptr<SkBitmap> icon, 87 std::unique_ptr<SkBitmap> icon,
77 const std::string& native_app_package, 88 const std::string& native_app_package,
78 const std::string& referrer, 89 const std::string& referrer,
79 int event_request_id) 90 int event_request_id)
80 : app_title_(app_title), 91 : app_title_(app_title),
81 native_app_data_(native_app_data), 92 native_app_data_(native_app_data),
82 icon_(std::move(icon)), 93 icon_(std::move(icon)),
83 native_app_package_(native_app_package), 94 native_app_package_(native_app_package),
84 referrer_(referrer), 95 referrer_(referrer),
85 event_request_id_(event_request_id), 96 event_request_id_(event_request_id),
86 has_user_interaction_(false), 97 has_user_interaction_(false),
87 weak_ptr_factory_(this) { 98 weak_ptr_factory_(this) {
88 DCHECK(!native_app_data_.is_null()); 99 DCHECK(!native_app_data_.is_null());
89 CreateJavaDelegate(); 100 CreateJavaDelegate();
90 } 101 }
91 102
92 AppBannerInfoBarDelegateAndroid::~AppBannerInfoBarDelegateAndroid() { 103 AppBannerInfoBarDelegateAndroid::~AppBannerInfoBarDelegateAndroid() {
93 weak_ptr_factory_.InvalidateWeakPtrs(); 104 weak_ptr_factory_.InvalidateWeakPtrs();
94 105
95 if (!has_user_interaction_) { 106 if (!has_user_interaction_) {
96 if (!native_app_data_.is_null()) 107 if (!native_app_data_.is_null()) {
97 TrackUserResponse(USER_RESPONSE_NATIVE_APP_IGNORED); 108 TrackUserResponse(USER_RESPONSE_NATIVE_APP_IGNORED);
98 else if (!IsInfoEmpty(shortcut_info_.get())) 109 } else if (!IsInfoEmpty(shortcut_info_.get())) {
99 TrackUserResponse(USER_RESPONSE_WEB_APP_IGNORED); 110 TrackUserResponse(USER_RESPONSE_WEB_APP_IGNORED);
111 if (is_webapk_)
112 webapk::TrackUserAction(webapk::USER_ACTION_BANNER_IGNORED);
113 }
100 } 114 }
101 115
102 TrackDismissEvent(DISMISS_EVENT_DISMISSED); 116 TrackDismissEvent(DISMISS_EVENT_DISMISSED);
103 JNIEnv* env = base::android::AttachCurrentThread(); 117 JNIEnv* env = base::android::AttachCurrentThread();
104 Java_AppBannerInfoBarDelegateAndroid_destroy(env, java_delegate_); 118 Java_AppBannerInfoBarDelegateAndroid_destroy(env, java_delegate_);
105 java_delegate_.Reset(); 119 java_delegate_.Reset();
106 } 120 }
107 121
108 void AppBannerInfoBarDelegateAndroid::UpdateInstallState( 122 void AppBannerInfoBarDelegateAndroid::UpdateInstallState(
109 JNIEnv* env, 123 JNIEnv* env,
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
162 } 176 }
163 } 177 }
164 178
165 void AppBannerInfoBarDelegateAndroid::InstallWebApk( 179 void AppBannerInfoBarDelegateAndroid::InstallWebApk(
166 content::WebContents* web_contents) { 180 content::WebContents* web_contents) {
167 if (!web_contents) { 181 if (!web_contents) {
168 LOG(ERROR) << "Failed to create infobar to install the WebAPK: " 182 LOG(ERROR) << "Failed to create infobar to install the WebAPK: "
169 << "the associated WebContents is null."; 183 << "the associated WebContents is null.";
170 return; 184 return;
171 } 185 }
186 install_state_ = INSTALLING;
187 webapk::TrackInstallEvent(webapk::INSTALL_EVENT_ADD_FROM_MENU_STARTED);
188 webapk::TrackUserAction(webapk::USER_ACTION_ADD_FROM_MENU);
172 AcceptWebApk(web_contents); 189 AcceptWebApk(web_contents);
173 } 190 }
174 191
175 void AppBannerInfoBarDelegateAndroid::CreateJavaDelegate() { 192 void AppBannerInfoBarDelegateAndroid::CreateJavaDelegate() {
176 JNIEnv* env = base::android::AttachCurrentThread(); 193 JNIEnv* env = base::android::AttachCurrentThread();
177 java_delegate_.Reset(Java_AppBannerInfoBarDelegateAndroid_create( 194 java_delegate_.Reset(Java_AppBannerInfoBarDelegateAndroid_create(
178 env, 195 env,
179 reinterpret_cast<intptr_t>(this))); 196 reinterpret_cast<intptr_t>(this)));
180 } 197 }
181 198
(...skipping 27 matching lines...) Expand all
209 web_contents->GetMainFrame()->Send( 226 web_contents->GetMainFrame()->Send(
210 new ChromeViewMsg_AppBannerDismissed( 227 new ChromeViewMsg_AppBannerDismissed(
211 web_contents->GetMainFrame()->GetRoutingID(), 228 web_contents->GetMainFrame()->GetRoutingID(),
212 event_request_id_)); 229 event_request_id_));
213 230
214 if (!native_app_data_.is_null()) { 231 if (!native_app_data_.is_null()) {
215 TrackUserResponse(USER_RESPONSE_NATIVE_APP_DISMISSED); 232 TrackUserResponse(USER_RESPONSE_NATIVE_APP_DISMISSED);
216 AppBannerSettingsHelper::RecordBannerDismissEvent( 233 AppBannerSettingsHelper::RecordBannerDismissEvent(
217 web_contents, native_app_package_, AppBannerSettingsHelper::NATIVE); 234 web_contents, native_app_package_, AppBannerSettingsHelper::NATIVE);
218 } else if (!IsInfoEmpty(shortcut_info_.get())) { 235 } else if (!IsInfoEmpty(shortcut_info_.get())) {
236 if (is_webapk_)
237 TrackWebApkDismissEvents(install_state_);
219 TrackUserResponse(USER_RESPONSE_WEB_APP_DISMISSED); 238 TrackUserResponse(USER_RESPONSE_WEB_APP_DISMISSED);
220 AppBannerSettingsHelper::RecordBannerDismissEvent( 239 AppBannerSettingsHelper::RecordBannerDismissEvent(
221 web_contents, shortcut_info_->url.spec(), 240 web_contents, shortcut_info_->url.spec(),
222 AppBannerSettingsHelper::WEB); 241 AppBannerSettingsHelper::WEB);
223 } 242 }
224 } 243 }
225 244
226 base::string16 AppBannerInfoBarDelegateAndroid::GetMessageText() const { 245 base::string16 AppBannerInfoBarDelegateAndroid::GetMessageText() const {
227 return app_title_; 246 return app_title_;
228 } 247 }
229 248
230 int AppBannerInfoBarDelegateAndroid::GetButtons() const { 249 int AppBannerInfoBarDelegateAndroid::GetButtons() const {
231 return BUTTON_OK; 250 return BUTTON_OK;
232 } 251 }
233 252
234 bool AppBannerInfoBarDelegateAndroid::Accept() { 253 bool AppBannerInfoBarDelegateAndroid::Accept() {
235 has_user_interaction_ = true; 254 has_user_interaction_ = true;
236 255
237 content::WebContents* web_contents = 256 content::WebContents* web_contents =
238 InfoBarService::WebContentsFromInfoBar(infobar()); 257 InfoBarService::WebContentsFromInfoBar(infobar());
239 if (!web_contents) { 258 if (!web_contents) {
240 TrackDismissEvent(DISMISS_EVENT_ERROR); 259 TrackDismissEvent(DISMISS_EVENT_ERROR);
241 return true; 260 return true;
242 } 261 }
243 262
244 if (!native_app_data_.is_null()) { 263 if (!native_app_data_.is_null()) {
245 return AcceptNativeApp(web_contents); 264 return AcceptNativeApp(web_contents);
246 } else if (is_webapk_) { 265 } else if (is_webapk_) {
266 webapk::TrackInstallEvent(webapk::INSTALL_EVENT_ADD_FROM_BANNER_STARTED);
267 webapk::TrackUserAction(webapk::USER_ACTION_ADD_FROM_BANNER_ACCEPTED);
247 return AcceptWebApk(web_contents); 268 return AcceptWebApk(web_contents);
248 } 269 }
249 return AcceptWebApp(web_contents); 270 return AcceptWebApp(web_contents);
250 } 271 }
251 272
252 bool AppBannerInfoBarDelegateAndroid::AcceptNativeApp( 273 bool AppBannerInfoBarDelegateAndroid::AcceptNativeApp(
253 content::WebContents* web_contents) { 274 content::WebContents* web_contents) {
254 TrackUserResponse(USER_RESPONSE_NATIVE_APP_ACCEPTED); 275 TrackUserResponse(USER_RESPONSE_NATIVE_APP_ACCEPTED);
255 JNIEnv* env = base::android::AttachCurrentThread(); 276 JNIEnv* env = base::android::AttachCurrentThread();
256 277
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
302 content::WebContents* web_contents) { 323 content::WebContents* web_contents) {
303 if (IsInfoEmpty(shortcut_info_.get())) 324 if (IsInfoEmpty(shortcut_info_.get()))
304 return true; 325 return true;
305 326
306 JNIEnv* env = base::android::AttachCurrentThread(); 327 JNIEnv* env = base::android::AttachCurrentThread();
307 // |webapk_package_name_| is set when the WebAPK has finished installing. 328 // |webapk_package_name_| is set when the WebAPK has finished installing.
308 // If the |webapk_package_name_| is empty, it means the "Add to Homescreen" 329 // If the |webapk_package_name_| is empty, it means the "Add to Homescreen"
309 // button is pressed, so request WebAPK installation. Otherwise, it means 330 // button is pressed, so request WebAPK installation. Otherwise, it means
310 // the "Open" button is pressed, then open the installed WebAPK. 331 // the "Open" button is pressed, then open the installed WebAPK.
311 if (webapk_package_name_.empty()) { 332 if (webapk_package_name_.empty()) {
333 install_state_ = INSTALLING;
312 // Request install the WebAPK. 334 // Request install the WebAPK.
313 TrackUserResponse(USER_RESPONSE_WEB_APP_ACCEPTED); 335 TrackUserResponse(USER_RESPONSE_WEB_APP_ACCEPTED);
314 336
315 AppBannerSettingsHelper::RecordBannerInstallEvent( 337 AppBannerSettingsHelper::RecordBannerInstallEvent(
316 web_contents, shortcut_info_->url.spec(), 338 web_contents, shortcut_info_->url.spec(),
317 AppBannerSettingsHelper::WEB); 339 AppBannerSettingsHelper::WEB);
318 340
319 Java_AppBannerInfoBarDelegateAndroid_setWebApkInstallingState( 341 Java_AppBannerInfoBarDelegateAndroid_setWebApkInstallingState(
320 env, java_delegate_, true); 342 env, java_delegate_, true);
321 UpdateInstallState(env, nullptr); 343 UpdateInstallState(env, nullptr);
(...skipping 11 matching lines...) Expand all
333 return false; 355 return false;
334 } 356 }
335 357
336 // Open the WebAPK. 358 // Open the WebAPK.
337 ScopedJavaLocalRef<jstring> java_webapk_package_name = 359 ScopedJavaLocalRef<jstring> java_webapk_package_name =
338 base::android::ConvertUTF8ToJavaString(env, webapk_package_name_); 360 base::android::ConvertUTF8ToJavaString(env, webapk_package_name_);
339 Java_AppBannerInfoBarDelegateAndroid_openWebApk( 361 Java_AppBannerInfoBarDelegateAndroid_openWebApk(
340 env, java_delegate_, java_webapk_package_name); 362 env, java_delegate_, java_webapk_package_name);
341 363
342 SendBannerAccepted(web_contents, "web"); 364 SendBannerAccepted(web_contents, "web");
365 webapk::TrackUserAction(webapk::USER_ACTION_INSTALLED_OPEN);
343 return true; 366 return true;
344 } 367 }
345 368
346 void AppBannerInfoBarDelegateAndroid::OnWebApkInstallFinished( 369 void AppBannerInfoBarDelegateAndroid::OnWebApkInstallFinished(
347 bool success, 370 bool success,
348 const std::string& webapk_package_name) { 371 const std::string& webapk_package_name) {
349 JNIEnv* env = base::android::AttachCurrentThread(); 372 JNIEnv* env = base::android::AttachCurrentThread();
350 if (!success) { 373 if (!success) {
351 // The installation failed. 374 // The installation failed.
352 if (infobar()) 375 if (infobar())
353 infobar()->RemoveSelf(); 376 infobar()->RemoveSelf();
354 Java_AppBannerInfoBarDelegateAndroid_showWebApkInstallFailureToast(env); 377 Java_AppBannerInfoBarDelegateAndroid_showWebApkInstallFailureToast(env);
355 DVLOG(1) << "The WebAPK installation failed."; 378 webapk::TrackInstallEvent(webapk::INSTALL_EVENT_FAILED);
dominickn 2016/09/05 07:34:31 Not sure if you want to remove the DVLOG here - re
Xi Han 2016/09/07 20:58:52 Good point, add the LOG back.
356 return; 379 return;
357 } 380 }
358 381
359 webapk_package_name_ = webapk_package_name; 382 webapk_package_name_ = webapk_package_name;
360 ScopedJavaLocalRef<jstring> java_webapk_package_name = 383 ScopedJavaLocalRef<jstring> java_webapk_package_name =
361 base::android::ConvertUTF8ToJavaString(env, webapk_package_name); 384 base::android::ConvertUTF8ToJavaString(env, webapk_package_name);
362 Java_AppBannerInfoBarDelegateAndroid_setWebApkInstallingState( 385 Java_AppBannerInfoBarDelegateAndroid_setWebApkInstallingState(
363 env, java_delegate_, false); 386 env, java_delegate_, false);
364 Java_AppBannerInfoBarDelegateAndroid_setWebApkPackageName( 387 Java_AppBannerInfoBarDelegateAndroid_setWebApkPackageName(
365 env, java_delegate_, java_webapk_package_name); 388 env, java_delegate_, java_webapk_package_name);
366 UpdateInstallState(env, nullptr); 389 UpdateInstallState(env, nullptr);
390 install_state_ = INSTALLED;
391 webapk::TrackInstallEvent(webapk::INSTALL_EVENT_COMPLETED);
367 } 392 }
368 393
369 bool AppBannerInfoBarDelegateAndroid::LinkClicked( 394 bool AppBannerInfoBarDelegateAndroid::LinkClicked(
370 WindowOpenDisposition disposition) { 395 WindowOpenDisposition disposition) {
371 if (native_app_data_.is_null()) 396 if (native_app_data_.is_null())
372 return false; 397 return false;
373 398
374 // Try to show the details for the native app. 399 // Try to show the details for the native app.
375 JNIEnv* env = base::android::AttachCurrentThread(); 400 JNIEnv* env = base::android::AttachCurrentThread();
376 401
(...skipping 16 matching lines...) Expand all
393 AppBannerInfoBarDelegateAndroid* 418 AppBannerInfoBarDelegateAndroid*
394 AppBannerInfoBarDelegateAndroid::AsAppBannerInfoBarDelegateAndroid() { 419 AppBannerInfoBarDelegateAndroid::AsAppBannerInfoBarDelegateAndroid() {
395 return this; 420 return this;
396 } 421 }
397 422
398 bool RegisterAppBannerInfoBarDelegateAndroid(JNIEnv* env) { 423 bool RegisterAppBannerInfoBarDelegateAndroid(JNIEnv* env) {
399 return RegisterNativesImpl(env); 424 return RegisterNativesImpl(env);
400 } 425 }
401 426
402 } // namespace banners 427 } // namespace banners
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698