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.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 "base/threading/worker_pool.h"
13 #include "chrome/browser/android/banners/app_banner_manager.h"
14 #include "chrome/browser/android/shortcut_helper.h"
15 #include "chrome/browser/android/shortcut_info.h"
16 #include "chrome/browser/android/tab_android.h"
17 #include "chrome/browser/banners/app_banner_metrics.h"
18 #include "chrome/browser/banners/app_banner_settings_helper.h"
19 #include "chrome/browser/infobars/infobar_service.h"
20 #include "chrome/browser/metrics/rappor/sampling.h"
21 #include "chrome/browser/ui/android/infobars/app_banner_infobar.h"
22 #include "chrome/grit/generated_resources.h"
23 #include "components/infobars/core/infobar.h"
24 #include "components/infobars/core/infobar_manager.h"
25 #include "content/public/common/manifest.h"
26 #include "jni/AppBannerInfoBarDelegate_jni.h"
27 #include "ui/gfx/android/java_bitmap.h"
29 using base::android::ConvertJavaStringToUTF8
;
30 using base::android::ConvertJavaStringToUTF16
;
31 using base::android::ConvertUTF8ToJavaString
;
32 using base::android::ConvertUTF16ToJavaString
;
37 AppBannerInfoBar
* AppBannerInfoBarDelegate::CreateForNativeApp(
38 infobars::InfoBarManager
* infobar_manager
,
39 const base::string16
& app_title
,
41 const base::android::ScopedJavaGlobalRef
<jobject
>& app_data
,
42 const std::string
& app_package
) {
43 scoped_ptr
<AppBannerInfoBarDelegate
> delegate(new AppBannerInfoBarDelegate(
49 AppBannerInfoBar
* infobar
= new AppBannerInfoBar(delegate
.Pass(),
51 return infobar_manager
->AddInfoBar(make_scoped_ptr(infobar
))
56 AppBannerInfoBar
* AppBannerInfoBarDelegate::CreateForWebApp(
57 infobars::InfoBarManager
* infobar_manager
,
58 const base::string16
& app_title
,
60 const content::Manifest
& web_app_data
) {
61 scoped_ptr
<AppBannerInfoBarDelegate
> delegate(new AppBannerInfoBarDelegate(
65 base::android::ScopedJavaGlobalRef
<jobject
>(),
67 AppBannerInfoBar
* infobar
= new AppBannerInfoBar(delegate
.Pass(),
68 web_app_data
.start_url
);
69 return infobar_manager
->AddInfoBar(make_scoped_ptr(infobar
))
73 AppBannerInfoBarDelegate::~AppBannerInfoBarDelegate() {
74 TrackDismissEvent(DISMISS_EVENT_DISMISSED
);
75 JNIEnv
* env
= base::android::AttachCurrentThread();
76 Java_AppBannerInfoBarDelegate_destroy(env
,
77 java_delegate_
.obj());
78 java_delegate_
.Reset();
81 void AppBannerInfoBarDelegate::UpdateInstallState(JNIEnv
* env
, jobject obj
) {
82 if (native_app_data_
.is_null())
85 int newState
= Java_AppBannerInfoBarDelegate_determineInstallState(
88 native_app_data_
.obj());
89 static_cast<AppBannerInfoBar
*>(infobar())->OnInstallStateChanged(newState
);
92 void AppBannerInfoBarDelegate::OnInstallIntentReturned(
95 jboolean jis_installing
) {
99 content::WebContents
* web_contents
=
100 InfoBarService::WebContentsFromInfoBar(infobar());
104 if (jis_installing
) {
105 AppBannerSettingsHelper::RecordBannerEvent(
107 web_contents
->GetURL(),
109 AppBannerSettingsHelper::APP_BANNER_EVENT_DID_ADD_TO_HOMESCREEN
,
110 AppBannerManager::GetCurrentTime());
112 TrackInstallEvent(INSTALL_EVENT_NATIVE_APP_INSTALL_STARTED
);
113 rappor::SampleDomainAndRegistryFromGURL("AppBanner.NativeApp.Installed",
114 web_contents
->GetURL());
117 UpdateInstallState(env
, obj
);
120 void AppBannerInfoBarDelegate::OnInstallFinished(JNIEnv
* env
,
127 TrackInstallEvent(INSTALL_EVENT_NATIVE_APP_INSTALL_COMPLETED
);
128 UpdateInstallState(env
, obj
);
129 } else if (infobar()->owner()) {
130 TrackDismissEvent(DISMISS_EVENT_INSTALL_TIMEOUT
);
131 infobar()->owner()->RemoveInfoBar(infobar());
135 AppBannerInfoBarDelegate::AppBannerInfoBarDelegate(
136 const base::string16
& app_title
,
138 const content::Manifest
& web_app_data
,
139 const base::android::ScopedJavaGlobalRef
<jobject
>& native_app_data
,
140 const std::string
& native_app_package
)
141 : app_title_(app_title
),
143 web_app_data_(web_app_data
),
144 native_app_data_(native_app_data
),
145 native_app_package_(native_app_package
) {
146 DCHECK(native_app_data_
.is_null() ^ web_app_data_
.IsEmpty());
147 JNIEnv
* env
= base::android::AttachCurrentThread();
148 java_delegate_
.Reset(Java_AppBannerInfoBarDelegate_create(
150 reinterpret_cast<intptr_t>(this)));
153 gfx::Image
AppBannerInfoBarDelegate::GetIcon() const {
154 return gfx::Image::CreateFrom1xBitmap(*app_icon_
.get());
157 void AppBannerInfoBarDelegate::InfoBarDismissed() {
158 content::WebContents
* web_contents
=
159 InfoBarService::WebContentsFromInfoBar(infobar());
163 TrackDismissEvent(DISMISS_EVENT_CLOSE_BUTTON
);
165 if (!native_app_data_
.is_null()) {
166 AppBannerSettingsHelper::RecordBannerEvent(
167 web_contents
, web_contents
->GetURL(),
169 AppBannerSettingsHelper::APP_BANNER_EVENT_DID_BLOCK
,
170 AppBannerManager::GetCurrentTime());
172 rappor::SampleDomainAndRegistryFromGURL("AppBanner.NativeApp.Dismissed",
173 web_contents
->GetURL());
174 } else if (!web_app_data_
.IsEmpty()) {
175 AppBannerSettingsHelper::RecordBannerEvent(
176 web_contents
, web_contents
->GetURL(),
177 web_app_data_
.start_url
.spec(),
178 AppBannerSettingsHelper::APP_BANNER_EVENT_DID_BLOCK
,
179 AppBannerManager::GetCurrentTime());
181 rappor::SampleDomainAndRegistryFromGURL("AppBanner.WebApp.Dismissed",
182 web_contents
->GetURL());
186 base::string16
AppBannerInfoBarDelegate::GetMessageText() const {
190 int AppBannerInfoBarDelegate::GetButtons() const {
194 bool AppBannerInfoBarDelegate::Accept() {
195 content::WebContents
* web_contents
=
196 InfoBarService::WebContentsFromInfoBar(infobar());
198 TrackDismissEvent(DISMISS_EVENT_ERROR
);
202 if (!native_app_data_
.is_null()) {
203 JNIEnv
* env
= base::android::AttachCurrentThread();
205 TabAndroid
* tab
= TabAndroid::FromWebContents(web_contents
);
206 if (tab
== nullptr) {
207 TrackDismissEvent(DISMISS_EVENT_ERROR
);
211 bool was_opened
= Java_AppBannerInfoBarDelegate_installOrOpenNativeApp(
213 java_delegate_
.obj(),
214 tab
->GetJavaObject().obj(),
215 native_app_data_
.obj());
218 TrackDismissEvent(DISMISS_EVENT_APP_OPEN
);
220 TrackInstallEvent(INSTALL_EVENT_NATIVE_APP_INSTALL_TRIGGERED
);
223 } else if (!web_app_data_
.IsEmpty()) {
224 AppBannerSettingsHelper::RecordBannerEvent(
225 web_contents
, web_contents
->GetURL(),
226 web_app_data_
.start_url
.spec(),
227 AppBannerSettingsHelper::APP_BANNER_EVENT_DID_ADD_TO_HOMESCREEN
,
228 AppBannerManager::GetCurrentTime());
231 info
.UpdateFromManifest(web_app_data_
);
232 base::WorkerPool::PostTask(
234 base::Bind(&ShortcutHelper::AddShortcutInBackgroundWithSkBitmap
,
240 TrackInstallEvent(INSTALL_EVENT_WEB_APP_INSTALLED
);
241 rappor::SampleDomainAndRegistryFromGURL("AppBanner.WebApp.Installed",
242 web_contents
->GetURL());
249 bool AppBannerInfoBarDelegate::LinkClicked(WindowOpenDisposition disposition
) {
250 if (native_app_data_
.is_null())
253 // Try to show the details for the native app.
254 JNIEnv
* env
= base::android::AttachCurrentThread();
256 content::WebContents
* web_contents
=
257 InfoBarService::WebContentsFromInfoBar(infobar());
258 TabAndroid
* tab
= web_contents
? TabAndroid::FromWebContents(web_contents
)
260 if (tab
== nullptr) {
261 TrackDismissEvent(DISMISS_EVENT_ERROR
);
265 Java_AppBannerInfoBarDelegate_showAppDetails(env
,
266 java_delegate_
.obj(),
267 tab
->GetJavaObject().obj(),
268 native_app_data_
.obj());
270 TrackDismissEvent(DISMISS_EVENT_BANNER_CLICK
);
274 bool RegisterAppBannerInfoBarDelegate(JNIEnv
* env
) {
275 return RegisterNativesImpl(env
);
278 } // namespace banners