Chromium Code Reviews| OLD | NEW |
|---|---|
| 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" |
| (...skipping 25 matching lines...) Expand all Loading... | |
| 36 using base::android::ConvertUTF16ToJavaString; | 36 using base::android::ConvertUTF16ToJavaString; |
| 37 using base::android::JavaParamRef; | 37 using base::android::JavaParamRef; |
| 38 using base::android::ScopedJavaLocalRef; | 38 using base::android::ScopedJavaLocalRef; |
| 39 | 39 |
| 40 namespace { | 40 namespace { |
| 41 | 41 |
| 42 bool IsInfoEmpty(const ShortcutInfo* info) { | 42 bool IsInfoEmpty(const ShortcutInfo* info) { |
| 43 return !info || info->url.is_empty(); | 43 return !info || info->url.is_empty(); |
| 44 } | 44 } |
| 45 | 45 |
| 46 void TrackWebApkInstallationDismissEvents(webapk::InstallState install_state) { | |
| 47 if (install_state == webapk::WAIT_FOR_START) | |
| 48 webapk::TrackInstallEvent(webapk::INSTALL_EVENT_ADD_TO_HOME_SCREEN_DISMISS); | |
| 49 else if (install_state == webapk::INSTALLING) | |
| 50 webapk::TrackInstallEvent(webapk::INSTALL_EVENT_ADDING_DISMISS); | |
| 51 else if (install_state == webapk::INSTALLED) | |
| 52 webapk::TrackUserAction(webapk::USER_ACTION_INSTALLED_OPEN_DISMISS); | |
| 46 } | 53 } |
| 47 | 54 |
| 55 } // namespace | |
| 56 | |
| 48 namespace banners { | 57 namespace banners { |
| 49 | 58 |
| 50 // static | 59 // static |
| 51 bool AppBannerInfoBarDelegateAndroid::Create( | 60 bool AppBannerInfoBarDelegateAndroid::Create( |
| 52 content::WebContents* web_contents, | 61 content::WebContents* web_contents, |
| 53 base::WeakPtr<AppBannerManager> weak_manager, | 62 base::WeakPtr<AppBannerManager> weak_manager, |
| 54 const base::string16& app_title, | 63 const base::string16& app_title, |
| 55 std::unique_ptr<ShortcutInfo> shortcut_info, | 64 std::unique_ptr<ShortcutInfo> shortcut_info, |
| 56 std::unique_ptr<SkBitmap> icon, | 65 std::unique_ptr<SkBitmap> icon, |
| 57 int event_request_id, | 66 int event_request_id, |
| 58 bool is_webapk, | 67 bool is_webapk, |
| 59 bool start_install_webapk) { | 68 bool start_install_webapk) { |
| 60 const GURL& url = shortcut_info->url; | 69 const GURL& url = shortcut_info->url; |
| 61 auto infobar_delegate = | 70 auto infobar_delegate = |
| 62 base::WrapUnique(new banners::AppBannerInfoBarDelegateAndroid( | 71 base::WrapUnique(new banners::AppBannerInfoBarDelegateAndroid( |
| 63 weak_manager, app_title, std::move(shortcut_info), std::move(icon), | 72 weak_manager, app_title, std::move(shortcut_info), std::move(icon), |
| 64 event_request_id, is_webapk)); | 73 event_request_id, is_webapk)); |
| 65 auto raw_delegate = infobar_delegate.get(); | 74 auto raw_delegate = infobar_delegate.get(); |
| 66 auto infobar = base::MakeUnique<AppBannerInfoBarAndroid>( | 75 auto infobar = base::MakeUnique<AppBannerInfoBarAndroid>( |
| 67 std::move(infobar_delegate), url, is_webapk); | 76 std::move(infobar_delegate), url, is_webapk); |
| 68 if (!InfoBarService::FromWebContents(web_contents) | 77 if (!InfoBarService::FromWebContents(web_contents) |
| 69 ->AddInfoBar(std::move(infobar))) | 78 ->AddInfoBar(std::move(infobar))) |
| 70 return false; | 79 return false; |
| 71 | 80 |
| 72 if (is_webapk && start_install_webapk) | 81 if (is_webapk) { |
| 73 raw_delegate->AcceptWebApk(web_contents); | 82 if (start_install_webapk) { |
| 83 raw_delegate->AcceptWebApk(web_contents); | |
| 84 webapk::TrackStartType(webapk::STARTED_FROM_ADD_TO_HOME_SCREEN_MENU); | |
| 85 } else { | |
| 86 webapk::TrackStartType(webapk::TRIGGERED_FROM_BANNER); | |
| 87 } | |
| 88 } | |
| 74 | 89 |
| 75 return true; | 90 return true; |
| 76 } | 91 } |
| 77 | 92 |
| 78 // static | 93 // static |
| 79 bool AppBannerInfoBarDelegateAndroid::Create( | 94 bool AppBannerInfoBarDelegateAndroid::Create( |
| 80 content::WebContents* web_contents, | 95 content::WebContents* web_contents, |
| 81 const base::string16& app_title, | 96 const base::string16& app_title, |
| 82 const base::android::ScopedJavaGlobalRef<jobject>& native_app_data, | 97 const base::android::ScopedJavaGlobalRef<jobject>& native_app_data, |
| 83 std::unique_ptr<SkBitmap> icon, | 98 std::unique_ptr<SkBitmap> icon, |
| 84 const std::string& native_app_package, | 99 const std::string& native_app_package, |
| 85 const std::string& referrer, | 100 const std::string& referrer, |
| 86 int event_request_id) { | 101 int event_request_id) { |
| 87 auto infobar_delegate = base::WrapUnique(new AppBannerInfoBarDelegateAndroid( | 102 auto infobar_delegate = base::WrapUnique(new AppBannerInfoBarDelegateAndroid( |
| 88 app_title, native_app_data, std::move(icon), native_app_package, referrer, | 103 app_title, native_app_data, std::move(icon), native_app_package, referrer, |
| 89 event_request_id)); | 104 event_request_id)); |
| 90 return InfoBarService::FromWebContents(web_contents) | 105 return InfoBarService::FromWebContents(web_contents) |
| 91 ->AddInfoBar(base::MakeUnique<AppBannerInfoBarAndroid>( | 106 ->AddInfoBar(base::MakeUnique<AppBannerInfoBarAndroid>( |
| 92 std::move(infobar_delegate), native_app_data)); | 107 std::move(infobar_delegate), native_app_data)); |
| 93 } | 108 } |
| 94 | 109 |
| 95 AppBannerInfoBarDelegateAndroid::~AppBannerInfoBarDelegateAndroid() { | 110 AppBannerInfoBarDelegateAndroid::~AppBannerInfoBarDelegateAndroid() { |
| 96 weak_ptr_factory_.InvalidateWeakPtrs(); | 111 weak_ptr_factory_.InvalidateWeakPtrs(); |
| 97 | 112 |
| 98 if (!has_user_interaction_) { | 113 if (!has_user_interaction_) { |
| 99 if (!native_app_data_.is_null()) | 114 if (!native_app_data_.is_null()) { |
| 100 TrackUserResponse(USER_RESPONSE_NATIVE_APP_IGNORED); | 115 TrackUserResponse(USER_RESPONSE_NATIVE_APP_IGNORED); |
| 101 else if (!IsInfoEmpty(shortcut_info_.get())) | 116 } else if (!IsInfoEmpty(shortcut_info_.get())) { |
| 102 TrackUserResponse(USER_RESPONSE_WEB_APP_IGNORED); | 117 TrackUserResponse(USER_RESPONSE_WEB_APP_IGNORED); |
| 118 if (is_webapk_) | |
| 119 webapk::TrackInstallEvent(webapk::INSTALL_EVENT_BANNER_IGNORED); | |
| 120 } | |
| 103 } | 121 } |
| 104 | 122 |
| 105 TrackDismissEvent(DISMISS_EVENT_DISMISSED); | 123 TrackDismissEvent(DISMISS_EVENT_DISMISSED); |
| 106 JNIEnv* env = base::android::AttachCurrentThread(); | 124 JNIEnv* env = base::android::AttachCurrentThread(); |
| 107 Java_AppBannerInfoBarDelegateAndroid_destroy(env, java_delegate_); | 125 Java_AppBannerInfoBarDelegateAndroid_destroy(env, java_delegate_); |
| 108 java_delegate_.Reset(); | 126 java_delegate_.Reset(); |
| 109 } | 127 } |
| 110 | 128 |
| 111 void AppBannerInfoBarDelegateAndroid::UpdateInstallState( | 129 void AppBannerInfoBarDelegateAndroid::UpdateInstallState( |
| 112 JNIEnv* env, | 130 JNIEnv* env, |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 169 // |webapk_package_name_| is set when the WebAPK has finished installing. | 187 // |webapk_package_name_| is set when the WebAPK has finished installing. |
| 170 // If the |webapk_package_name_| is empty, it means the "Add to Homescreen" | 188 // If the |webapk_package_name_| is empty, it means the "Add to Homescreen" |
| 171 // button is pressed, so request WebAPK installation. Otherwise, it means | 189 // button is pressed, so request WebAPK installation. Otherwise, it means |
| 172 // the "Open" button is pressed, so open the installed WebAPK. | 190 // the "Open" button is pressed, so open the installed WebAPK. |
| 173 if (!webapk_package_name_.empty()) { | 191 if (!webapk_package_name_.empty()) { |
| 174 // Open the WebAPK. | 192 // Open the WebAPK. |
| 175 ScopedJavaLocalRef<jstring> java_webapk_package_name = | 193 ScopedJavaLocalRef<jstring> java_webapk_package_name = |
| 176 base::android::ConvertUTF8ToJavaString(env, webapk_package_name_); | 194 base::android::ConvertUTF8ToJavaString(env, webapk_package_name_); |
| 177 Java_AppBannerInfoBarDelegateAndroid_openWebApk(env, java_delegate_, | 195 Java_AppBannerInfoBarDelegateAndroid_openWebApk(env, java_delegate_, |
| 178 java_webapk_package_name); | 196 java_webapk_package_name); |
| 179 | 197 webapk::TrackUserAction(webapk::USER_ACTION_INSTALLED_OPEN); |
| 180 SendBannerAccepted(web_contents, "web"); | 198 SendBannerAccepted(web_contents, "web"); |
| 181 return true; | 199 return true; |
| 182 } | 200 } |
| 183 | 201 |
| 184 // Request install the WebAPK. | 202 // Request install the WebAPK. |
| 203 install_state_ = webapk::INSTALLING; | |
| 185 TrackUserResponse(USER_RESPONSE_WEB_APP_ACCEPTED); | 204 TrackUserResponse(USER_RESPONSE_WEB_APP_ACCEPTED); |
| 186 AppBannerSettingsHelper::RecordBannerInstallEvent( | 205 AppBannerSettingsHelper::RecordBannerInstallEvent( |
| 187 web_contents, shortcut_info_->url.spec(), AppBannerSettingsHelper::WEB); | 206 web_contents, shortcut_info_->url.spec(), AppBannerSettingsHelper::WEB); |
| 188 | 207 |
| 189 Java_AppBannerInfoBarDelegateAndroid_setWebApkInstallingState( | 208 Java_AppBannerInfoBarDelegateAndroid_setWebApkInstallingState( |
| 190 env, java_delegate_, true); | 209 env, java_delegate_, true); |
| 191 UpdateInstallState(env, nullptr); | 210 UpdateInstallState(env, nullptr); |
| 192 WebApkInstaller::FinishCallback callback = | 211 WebApkInstaller::FinishCallback callback = |
| 193 base::Bind(&AppBannerInfoBarDelegateAndroid::OnWebApkInstallFinished, | 212 base::Bind(&AppBannerInfoBarDelegateAndroid::OnWebApkInstallFinished, |
| 194 weak_ptr_factory_.GetWeakPtr()); | 213 weak_ptr_factory_.GetWeakPtr()); |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 274 web_contents->GetMainFrame()->Send( | 293 web_contents->GetMainFrame()->Send( |
| 275 new ChromeViewMsg_AppBannerDismissed( | 294 new ChromeViewMsg_AppBannerDismissed( |
| 276 web_contents->GetMainFrame()->GetRoutingID(), | 295 web_contents->GetMainFrame()->GetRoutingID(), |
| 277 event_request_id_)); | 296 event_request_id_)); |
| 278 | 297 |
| 279 if (!native_app_data_.is_null()) { | 298 if (!native_app_data_.is_null()) { |
| 280 TrackUserResponse(USER_RESPONSE_NATIVE_APP_DISMISSED); | 299 TrackUserResponse(USER_RESPONSE_NATIVE_APP_DISMISSED); |
| 281 AppBannerSettingsHelper::RecordBannerDismissEvent( | 300 AppBannerSettingsHelper::RecordBannerDismissEvent( |
| 282 web_contents, native_app_package_, AppBannerSettingsHelper::NATIVE); | 301 web_contents, native_app_package_, AppBannerSettingsHelper::NATIVE); |
| 283 } else { | 302 } else { |
| 303 if (is_webapk_) | |
| 304 TrackWebApkInstallationDismissEvents(install_state_); | |
| 284 TrackUserResponse(USER_RESPONSE_WEB_APP_DISMISSED); | 305 TrackUserResponse(USER_RESPONSE_WEB_APP_DISMISSED); |
| 285 AppBannerSettingsHelper::RecordBannerDismissEvent( | 306 AppBannerSettingsHelper::RecordBannerDismissEvent( |
| 286 web_contents, shortcut_info_->url.spec(), AppBannerSettingsHelper::WEB); | 307 web_contents, shortcut_info_->url.spec(), AppBannerSettingsHelper::WEB); |
| 287 } | 308 } |
| 288 } | 309 } |
| 289 | 310 |
| 290 base::string16 AppBannerInfoBarDelegateAndroid::GetMessageText() const { | 311 base::string16 AppBannerInfoBarDelegateAndroid::GetMessageText() const { |
| 291 return app_title_; | 312 return app_title_; |
| 292 } | 313 } |
| 293 | 314 |
| 294 int AppBannerInfoBarDelegateAndroid::GetButtons() const { | 315 int AppBannerInfoBarDelegateAndroid::GetButtons() const { |
| 295 return BUTTON_OK; | 316 return BUTTON_OK; |
| 296 } | 317 } |
| 297 | 318 |
| 298 bool AppBannerInfoBarDelegateAndroid::Accept() { | 319 bool AppBannerInfoBarDelegateAndroid::Accept() { |
| 299 has_user_interaction_ = true; | 320 has_user_interaction_ = true; |
| 300 | 321 |
| 301 content::WebContents* web_contents = | 322 content::WebContents* web_contents = |
| 302 InfoBarService::WebContentsFromInfoBar(infobar()); | 323 InfoBarService::WebContentsFromInfoBar(infobar()); |
| 303 if (!web_contents) { | 324 if (!web_contents) { |
| 304 TrackDismissEvent(DISMISS_EVENT_ERROR); | 325 TrackDismissEvent(DISMISS_EVENT_ERROR); |
| 305 return true; | 326 return true; |
| 306 } | 327 } |
| 307 | 328 |
| 308 if (!native_app_data_.is_null()) | 329 if (!native_app_data_.is_null()) |
| 309 return AcceptNativeApp(web_contents); | 330 return AcceptNativeApp(web_contents); |
| 310 | 331 |
| 311 if (is_webapk_) | 332 if (is_webapk_) { |
| 333 webapk::TrackStartType(webapk::STARTED_FROM_BANNER); | |
|
dominickn
2016/09/09 08:14:11
Won't this metric be hit at least twice when the u
Xi Han
2016/09/09 15:37:32
No, it is only hit here, not by AppBannerInfoBarDe
| |
| 312 return AcceptWebApk(web_contents); | 334 return AcceptWebApk(web_contents); |
| 335 } | |
| 313 | 336 |
| 314 return AcceptWebApp(web_contents); | 337 return AcceptWebApp(web_contents); |
| 315 } | 338 } |
| 316 | 339 |
| 317 bool AppBannerInfoBarDelegateAndroid::AcceptNativeApp( | 340 bool AppBannerInfoBarDelegateAndroid::AcceptNativeApp( |
| 318 content::WebContents* web_contents) { | 341 content::WebContents* web_contents) { |
| 319 TrackUserResponse(USER_RESPONSE_NATIVE_APP_ACCEPTED); | 342 TrackUserResponse(USER_RESPONSE_NATIVE_APP_ACCEPTED); |
| 320 JNIEnv* env = base::android::AttachCurrentThread(); | 343 JNIEnv* env = base::android::AttachCurrentThread(); |
| 321 | 344 |
| 322 TabAndroid* tab = TabAndroid::FromWebContents(web_contents); | 345 TabAndroid* tab = TabAndroid::FromWebContents(web_contents); |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 361 void AppBannerInfoBarDelegateAndroid::OnWebApkInstallFinished( | 384 void AppBannerInfoBarDelegateAndroid::OnWebApkInstallFinished( |
| 362 bool success, | 385 bool success, |
| 363 const std::string& webapk_package_name) { | 386 const std::string& webapk_package_name) { |
| 364 JNIEnv* env = base::android::AttachCurrentThread(); | 387 JNIEnv* env = base::android::AttachCurrentThread(); |
| 365 if (!success) { | 388 if (!success) { |
| 366 // The installation failed. | 389 // The installation failed. |
| 367 if (infobar()) | 390 if (infobar()) |
| 368 infobar()->RemoveSelf(); | 391 infobar()->RemoveSelf(); |
| 369 Java_AppBannerInfoBarDelegateAndroid_showWebApkInstallFailureToast(env); | 392 Java_AppBannerInfoBarDelegateAndroid_showWebApkInstallFailureToast(env); |
| 370 DVLOG(1) << "The WebAPK installation failed."; | 393 DVLOG(1) << "The WebAPK installation failed."; |
| 394 webapk::TrackInstallEvent(webapk::INSTALL_EVENT_FAILED); | |
| 371 return; | 395 return; |
| 372 } | 396 } |
| 373 | 397 |
| 374 webapk_package_name_ = webapk_package_name; | 398 webapk_package_name_ = webapk_package_name; |
| 375 ScopedJavaLocalRef<jstring> java_webapk_package_name = | 399 ScopedJavaLocalRef<jstring> java_webapk_package_name = |
| 376 base::android::ConvertUTF8ToJavaString(env, webapk_package_name); | 400 base::android::ConvertUTF8ToJavaString(env, webapk_package_name); |
| 377 Java_AppBannerInfoBarDelegateAndroid_setWebApkInstallingState( | 401 Java_AppBannerInfoBarDelegateAndroid_setWebApkInstallingState( |
| 378 env, java_delegate_, false); | 402 env, java_delegate_, false); |
| 379 Java_AppBannerInfoBarDelegateAndroid_setWebApkPackageName( | 403 Java_AppBannerInfoBarDelegateAndroid_setWebApkPackageName( |
| 380 env, java_delegate_, java_webapk_package_name); | 404 env, java_delegate_, java_webapk_package_name); |
| 381 UpdateInstallState(env, nullptr); | 405 UpdateInstallState(env, nullptr); |
| 406 install_state_ = webapk::INSTALLED; | |
| 407 webapk::TrackInstallEvent(webapk::INSTALL_EVENT_COMPLETED); | |
| 382 } | 408 } |
| 383 | 409 |
| 384 bool AppBannerInfoBarDelegateAndroid::LinkClicked( | 410 bool AppBannerInfoBarDelegateAndroid::LinkClicked( |
| 385 WindowOpenDisposition disposition) { | 411 WindowOpenDisposition disposition) { |
| 386 if (native_app_data_.is_null()) | 412 if (native_app_data_.is_null()) |
| 387 return false; | 413 return false; |
| 388 | 414 |
| 389 // Try to show the details for the native app. | 415 // Try to show the details for the native app. |
| 390 JNIEnv* env = base::android::AttachCurrentThread(); | 416 JNIEnv* env = base::android::AttachCurrentThread(); |
| 391 | 417 |
| 392 content::WebContents* web_contents = | 418 content::WebContents* web_contents = |
| 393 InfoBarService::WebContentsFromInfoBar(infobar()); | 419 InfoBarService::WebContentsFromInfoBar(infobar()); |
| 394 TabAndroid* tab = TabAndroid::FromWebContents(web_contents); | 420 TabAndroid* tab = TabAndroid::FromWebContents(web_contents); |
| 395 DCHECK(tab); | 421 DCHECK(tab); |
| 396 | 422 |
| 397 Java_AppBannerInfoBarDelegateAndroid_showAppDetails( | 423 Java_AppBannerInfoBarDelegateAndroid_showAppDetails( |
| 398 env, java_delegate_, tab->GetJavaObject(), native_app_data_); | 424 env, java_delegate_, tab->GetJavaObject(), native_app_data_); |
| 399 | 425 |
| 400 TrackDismissEvent(DISMISS_EVENT_BANNER_CLICK); | 426 TrackDismissEvent(DISMISS_EVENT_BANNER_CLICK); |
| 401 return true; | 427 return true; |
| 402 } | 428 } |
| 403 | 429 |
| 404 bool RegisterAppBannerInfoBarDelegateAndroid(JNIEnv* env) { | 430 bool RegisterAppBannerInfoBarDelegateAndroid(JNIEnv* env) { |
| 405 return RegisterNativesImpl(env); | 431 return RegisterNativesImpl(env); |
| 406 } | 432 } |
| 407 | 433 |
| 408 } // namespace banners | 434 } // namespace banners |
| OLD | NEW |