Add UMA to track app install banner outcomes.
[chromium-blink-merge.git] / chrome / browser / android / banners / app_banner_infobar_delegate_android.cc
blobe1a247133029165def9718937c149060889d3a4a
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
3 // found in the LICENSE file.
5 #include "chrome/browser/android/banners/app_banner_infobar_delegate_android.h"
7 #include "base/android/jni_android.h"
8 #include "base/android/jni_string.h"
9 #include "base/location.h"
10 #include "base/strings/string16.h"
11 #include "base/strings/utf_string_conversions.h"
12 #include "chrome/browser/android/shortcut_helper.h"
13 #include "chrome/browser/android/shortcut_info.h"
14 #include "chrome/browser/android/tab_android.h"
15 #include "chrome/browser/banners/app_banner_data_fetcher.h"
16 #include "chrome/browser/banners/app_banner_metrics.h"
17 #include "chrome/browser/banners/app_banner_settings_helper.h"
18 #include "chrome/browser/browser_process.h"
19 #include "chrome/browser/infobars/infobar_service.h"
20 #include "chrome/browser/ui/android/infobars/app_banner_infobar_android.h"
21 #include "chrome/common/render_messages.h"
22 #include "chrome/grit/generated_resources.h"
23 #include "components/rappor/rappor_utils.h"
24 #include "content/public/browser/browser_thread.h"
25 #include "content/public/browser/render_frame_host.h"
26 #include "content/public/browser/web_contents.h"
27 #include "content/public/common/manifest.h"
28 #include "jni/AppBannerInfoBarDelegateAndroid_jni.h"
29 #include "ui/gfx/android/java_bitmap.h"
31 using base::android::ConvertJavaStringToUTF8;
32 using base::android::ConvertJavaStringToUTF16;
33 using base::android::ConvertUTF8ToJavaString;
34 using base::android::ConvertUTF16ToJavaString;
36 namespace banners {
38 AppBannerInfoBarDelegateAndroid::AppBannerInfoBarDelegateAndroid(
39 int event_request_id,
40 const base::string16& app_title,
41 SkBitmap* app_icon,
42 const content::Manifest& web_app_data)
43 : app_title_(app_title),
44 app_icon_(app_icon),
45 event_request_id_(event_request_id),
46 web_app_data_(web_app_data),
47 has_user_interaction_(false) {
48 DCHECK(!web_app_data.IsEmpty());
49 CreateJavaDelegate();
52 AppBannerInfoBarDelegateAndroid::AppBannerInfoBarDelegateAndroid(
53 int event_request_id,
54 const base::string16& app_title,
55 SkBitmap* app_icon,
56 const base::android::ScopedJavaGlobalRef<jobject>& native_app_data,
57 const std::string& native_app_package)
58 : app_title_(app_title),
59 app_icon_(app_icon),
60 event_request_id_(event_request_id),
61 native_app_data_(native_app_data),
62 native_app_package_(native_app_package),
63 has_user_interaction_(false) {
64 DCHECK(!native_app_data_.is_null());
65 CreateJavaDelegate();
68 AppBannerInfoBarDelegateAndroid::~AppBannerInfoBarDelegateAndroid() {
69 if (!has_user_interaction_) {
70 if (!native_app_data_.is_null())
71 TrackUserResponse(USER_RESPONSE_NATIVE_APP_IGNORED);
72 else if (!web_app_data_.IsEmpty())
73 TrackUserResponse(USER_RESPONSE_WEB_APP_IGNORED);
76 TrackDismissEvent(DISMISS_EVENT_DISMISSED);
77 JNIEnv* env = base::android::AttachCurrentThread();
78 Java_AppBannerInfoBarDelegateAndroid_destroy(env,
79 java_delegate_.obj());
80 java_delegate_.Reset();
83 void AppBannerInfoBarDelegateAndroid::UpdateInstallState(JNIEnv* env,
84 jobject obj) {
85 if (native_app_data_.is_null())
86 return;
88 int newState = Java_AppBannerInfoBarDelegateAndroid_determineInstallState(
89 env,
90 java_delegate_.obj(),
91 native_app_data_.obj());
92 static_cast<AppBannerInfoBarAndroid*>(infobar())
93 ->OnInstallStateChanged(newState);
96 void AppBannerInfoBarDelegateAndroid::OnInstallIntentReturned(
97 JNIEnv* env,
98 jobject obj,
99 jboolean jis_installing) {
100 if (!infobar())
101 return;
103 content::WebContents* web_contents =
104 InfoBarService::WebContentsFromInfoBar(infobar());
105 if (!web_contents)
106 return;
108 if (jis_installing) {
109 AppBannerSettingsHelper::RecordBannerEvent(
110 web_contents,
111 web_contents->GetURL(),
112 native_app_package_,
113 AppBannerSettingsHelper::APP_BANNER_EVENT_DID_ADD_TO_HOMESCREEN,
114 AppBannerDataFetcher::GetCurrentTime());
116 TrackInstallEvent(INSTALL_EVENT_NATIVE_APP_INSTALL_STARTED);
117 rappor::SampleDomainAndRegistryFromGURL(g_browser_process->rappor_service(),
118 "AppBanner.NativeApp.Installed",
119 web_contents->GetURL());
122 UpdateInstallState(env, obj);
125 void AppBannerInfoBarDelegateAndroid::OnInstallFinished(JNIEnv* env,
126 jobject obj,
127 jboolean success) {
128 if (!infobar())
129 return;
131 if (success) {
132 TrackInstallEvent(INSTALL_EVENT_NATIVE_APP_INSTALL_COMPLETED);
133 UpdateInstallState(env, obj);
134 } else if (infobar()->owner()) {
135 TrackDismissEvent(DISMISS_EVENT_INSTALL_TIMEOUT);
136 infobar()->owner()->RemoveInfoBar(infobar());
140 void AppBannerInfoBarDelegateAndroid::CreateJavaDelegate() {
141 JNIEnv* env = base::android::AttachCurrentThread();
142 java_delegate_.Reset(Java_AppBannerInfoBarDelegateAndroid_create(
143 env,
144 reinterpret_cast<intptr_t>(this)));
147 void AppBannerInfoBarDelegateAndroid::SendBannerAccepted(
148 content::WebContents* web_contents,
149 const std::string& platform) {
150 web_contents->GetMainFrame()->Send(
151 new ChromeViewMsg_AppBannerAccepted(
152 web_contents->GetMainFrame()->GetRoutingID(),
153 event_request_id_,
154 platform));
157 gfx::Image AppBannerInfoBarDelegateAndroid::GetIcon() const {
158 return gfx::Image::CreateFrom1xBitmap(*app_icon_.get());
161 void AppBannerInfoBarDelegateAndroid::InfoBarDismissed() {
162 has_user_interaction_ = true;
164 content::WebContents* web_contents =
165 InfoBarService::WebContentsFromInfoBar(infobar());
166 if (!web_contents)
167 return;
169 web_contents->GetMainFrame()->Send(
170 new ChromeViewMsg_AppBannerDismissed(
171 web_contents->GetMainFrame()->GetRoutingID(),
172 event_request_id_));
174 if (!native_app_data_.is_null()) {
175 TrackUserResponse(USER_RESPONSE_NATIVE_APP_DISMISSED);
176 AppBannerSettingsHelper::RecordBannerDismissEvent(
177 web_contents, native_app_package_, AppBannerSettingsHelper::NATIVE);
178 } else if (!web_app_data_.IsEmpty()) {
179 TrackUserResponse(USER_RESPONSE_WEB_APP_DISMISSED);
180 AppBannerSettingsHelper::RecordBannerDismissEvent(
181 web_contents, web_app_data_.start_url.spec(),
182 AppBannerSettingsHelper::WEB);
186 base::string16 AppBannerInfoBarDelegateAndroid::GetMessageText() const {
187 return app_title_;
190 int AppBannerInfoBarDelegateAndroid::GetButtons() const {
191 return BUTTON_OK;
194 bool AppBannerInfoBarDelegateAndroid::Accept() {
195 has_user_interaction_ = true;
197 content::WebContents* web_contents =
198 InfoBarService::WebContentsFromInfoBar(infobar());
199 if (!web_contents) {
200 TrackDismissEvent(DISMISS_EVENT_ERROR);
201 return true;
204 if (!native_app_data_.is_null()) {
205 TrackUserResponse(USER_RESPONSE_NATIVE_APP_ACCEPTED);
206 JNIEnv* env = base::android::AttachCurrentThread();
208 TabAndroid* tab = TabAndroid::FromWebContents(web_contents);
209 if (tab == nullptr) {
210 TrackDismissEvent(DISMISS_EVENT_ERROR);
211 return true;
214 bool was_opened = Java_AppBannerInfoBarDelegateAndroid_installOrOpenNativeApp(
215 env,
216 java_delegate_.obj(),
217 tab->GetJavaObject().obj(),
218 native_app_data_.obj());
220 if (was_opened) {
221 TrackDismissEvent(DISMISS_EVENT_APP_OPEN);
222 } else {
223 TrackInstallEvent(INSTALL_EVENT_NATIVE_APP_INSTALL_TRIGGERED);
225 SendBannerAccepted(web_contents, "play");
226 return was_opened;
227 } else if (!web_app_data_.IsEmpty()) {
228 TrackUserResponse(USER_RESPONSE_WEB_APP_ACCEPTED);
230 AppBannerSettingsHelper::RecordBannerInstallEvent(
231 web_contents, web_app_data_.start_url.spec(),
232 AppBannerSettingsHelper::WEB);
234 ShortcutInfo info;
235 info.UpdateFromManifest(web_app_data_);
236 info.UpdateSource(ShortcutInfo::SOURCE_APP_BANNER);
237 content::BrowserThread::PostTask(
238 content::BrowserThread::IO,
239 FROM_HERE,
240 base::Bind(&ShortcutHelper::AddShortcutInBackgroundWithSkBitmap,
241 info,
242 *app_icon_.get()));
244 SendBannerAccepted(web_contents, "web");
245 return true;
248 return true;
251 bool AppBannerInfoBarDelegateAndroid::LinkClicked(
252 WindowOpenDisposition disposition) {
253 if (native_app_data_.is_null())
254 return false;
256 // Try to show the details for the native app.
257 JNIEnv* env = base::android::AttachCurrentThread();
259 content::WebContents* web_contents =
260 InfoBarService::WebContentsFromInfoBar(infobar());
261 TabAndroid* tab = web_contents ? TabAndroid::FromWebContents(web_contents)
262 : nullptr;
263 if (tab == nullptr) {
264 TrackDismissEvent(DISMISS_EVENT_ERROR);
265 return true;
268 Java_AppBannerInfoBarDelegateAndroid_showAppDetails(env,
269 java_delegate_.obj(),
270 tab->GetJavaObject().obj(),
271 native_app_data_.obj());
273 TrackDismissEvent(DISMISS_EVENT_BANNER_CLICK);
274 return true;
277 bool RegisterAppBannerInfoBarDelegateAndroid(JNIEnv* env) {
278 return RegisterNativesImpl(env);
281 } // namespace banners