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" |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |