Implement app banner info bars on desktop.
[chromium-blink-merge.git] / chrome / browser / android / banners / app_banner_infobar_delegate_android.cc
blob84a883f2b99d69356145d2367a4b24e1465e7a85
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 DCHECK(!web_app_data.IsEmpty());
48 CreateJavaDelegate();
51 AppBannerInfoBarDelegateAndroid::AppBannerInfoBarDelegateAndroid(
52 int event_request_id,
53 const base::string16& app_title,
54 SkBitmap* app_icon,
55 const base::android::ScopedJavaGlobalRef<jobject>& native_app_data,
56 const std::string& native_app_package)
57 : app_title_(app_title),
58 app_icon_(app_icon),
59 event_request_id_(event_request_id),
60 native_app_data_(native_app_data),
61 native_app_package_(native_app_package) {
62 DCHECK(!native_app_data_.is_null());
63 CreateJavaDelegate();
66 AppBannerInfoBarDelegateAndroid::~AppBannerInfoBarDelegateAndroid() {
67 TrackDismissEvent(DISMISS_EVENT_DISMISSED);
68 JNIEnv* env = base::android::AttachCurrentThread();
69 Java_AppBannerInfoBarDelegateAndroid_destroy(env,
70 java_delegate_.obj());
71 java_delegate_.Reset();
74 void AppBannerInfoBarDelegateAndroid::UpdateInstallState(JNIEnv* env,
75 jobject obj) {
76 if (native_app_data_.is_null())
77 return;
79 int newState = Java_AppBannerInfoBarDelegateAndroid_determineInstallState(
80 env,
81 java_delegate_.obj(),
82 native_app_data_.obj());
83 static_cast<AppBannerInfoBarAndroid*>(infobar())
84 ->OnInstallStateChanged(newState);
87 void AppBannerInfoBarDelegateAndroid::OnInstallIntentReturned(
88 JNIEnv* env,
89 jobject obj,
90 jboolean jis_installing) {
91 if (!infobar())
92 return;
94 content::WebContents* web_contents =
95 InfoBarService::WebContentsFromInfoBar(infobar());
96 if (!web_contents)
97 return;
99 if (jis_installing) {
100 AppBannerSettingsHelper::RecordBannerEvent(
101 web_contents,
102 web_contents->GetURL(),
103 native_app_package_,
104 AppBannerSettingsHelper::APP_BANNER_EVENT_DID_ADD_TO_HOMESCREEN,
105 AppBannerDataFetcher::GetCurrentTime());
107 TrackInstallEvent(INSTALL_EVENT_NATIVE_APP_INSTALL_STARTED);
108 rappor::SampleDomainAndRegistryFromGURL(g_browser_process->rappor_service(),
109 "AppBanner.NativeApp.Installed",
110 web_contents->GetURL());
113 UpdateInstallState(env, obj);
116 void AppBannerInfoBarDelegateAndroid::OnInstallFinished(JNIEnv* env,
117 jobject obj,
118 jboolean success) {
119 if (!infobar())
120 return;
122 if (success) {
123 TrackInstallEvent(INSTALL_EVENT_NATIVE_APP_INSTALL_COMPLETED);
124 UpdateInstallState(env, obj);
125 } else if (infobar()->owner()) {
126 TrackDismissEvent(DISMISS_EVENT_INSTALL_TIMEOUT);
127 infobar()->owner()->RemoveInfoBar(infobar());
131 void AppBannerInfoBarDelegateAndroid::CreateJavaDelegate() {
132 JNIEnv* env = base::android::AttachCurrentThread();
133 java_delegate_.Reset(Java_AppBannerInfoBarDelegateAndroid_create(
134 env,
135 reinterpret_cast<intptr_t>(this)));
138 void AppBannerInfoBarDelegateAndroid::SendBannerAccepted(
139 content::WebContents* web_contents,
140 const std::string& platform) {
141 web_contents->GetMainFrame()->Send(
142 new ChromeViewMsg_AppBannerAccepted(
143 web_contents->GetMainFrame()->GetRoutingID(),
144 event_request_id_,
145 platform));
148 gfx::Image AppBannerInfoBarDelegateAndroid::GetIcon() const {
149 return gfx::Image::CreateFrom1xBitmap(*app_icon_.get());
152 void AppBannerInfoBarDelegateAndroid::InfoBarDismissed() {
153 content::WebContents* web_contents =
154 InfoBarService::WebContentsFromInfoBar(infobar());
155 if (!web_contents)
156 return;
158 web_contents->GetMainFrame()->Send(
159 new ChromeViewMsg_AppBannerDismissed(
160 web_contents->GetMainFrame()->GetRoutingID(),
161 event_request_id_));
163 if (!native_app_data_.is_null()) {
164 AppBannerSettingsHelper::RecordBannerDismissEvent(
165 web_contents, native_app_package_, AppBannerSettingsHelper::NATIVE);
166 } else if (!web_app_data_.IsEmpty()) {
167 AppBannerSettingsHelper::RecordBannerDismissEvent(
168 web_contents, web_app_data_.start_url.spec(),
169 AppBannerSettingsHelper::WEB);
173 base::string16 AppBannerInfoBarDelegateAndroid::GetMessageText() const {
174 return app_title_;
177 int AppBannerInfoBarDelegateAndroid::GetButtons() const {
178 return BUTTON_OK;
181 bool AppBannerInfoBarDelegateAndroid::Accept() {
182 content::WebContents* web_contents =
183 InfoBarService::WebContentsFromInfoBar(infobar());
184 if (!web_contents) {
185 TrackDismissEvent(DISMISS_EVENT_ERROR);
186 return true;
189 if (!native_app_data_.is_null()) {
190 JNIEnv* env = base::android::AttachCurrentThread();
192 TabAndroid* tab = TabAndroid::FromWebContents(web_contents);
193 if (tab == nullptr) {
194 TrackDismissEvent(DISMISS_EVENT_ERROR);
195 return true;
198 bool was_opened = Java_AppBannerInfoBarDelegateAndroid_installOrOpenNativeApp(
199 env,
200 java_delegate_.obj(),
201 tab->GetJavaObject().obj(),
202 native_app_data_.obj());
204 if (was_opened) {
205 TrackDismissEvent(DISMISS_EVENT_APP_OPEN);
206 } else {
207 TrackInstallEvent(INSTALL_EVENT_NATIVE_APP_INSTALL_TRIGGERED);
209 SendBannerAccepted(web_contents, "play");
210 return was_opened;
211 } else if (!web_app_data_.IsEmpty()) {
212 AppBannerSettingsHelper::RecordBannerInstallEvent(
213 web_contents, web_app_data_.start_url.spec(),
214 AppBannerSettingsHelper::WEB);
216 ShortcutInfo info;
217 info.UpdateFromManifest(web_app_data_);
218 content::BrowserThread::PostTask(
219 content::BrowserThread::IO,
220 FROM_HERE,
221 base::Bind(&ShortcutHelper::AddShortcutInBackgroundWithSkBitmap,
222 info,
223 *app_icon_.get()));
225 SendBannerAccepted(web_contents, "web");
226 return true;
229 return true;
232 bool AppBannerInfoBarDelegateAndroid::LinkClicked(
233 WindowOpenDisposition disposition) {
234 if (native_app_data_.is_null())
235 return false;
237 // Try to show the details for the native app.
238 JNIEnv* env = base::android::AttachCurrentThread();
240 content::WebContents* web_contents =
241 InfoBarService::WebContentsFromInfoBar(infobar());
242 TabAndroid* tab = web_contents ? TabAndroid::FromWebContents(web_contents)
243 : nullptr;
244 if (tab == nullptr) {
245 TrackDismissEvent(DISMISS_EVENT_ERROR);
246 return true;
249 Java_AppBannerInfoBarDelegateAndroid_showAppDetails(env,
250 java_delegate_.obj(),
251 tab->GetJavaObject().obj(),
252 native_app_data_.obj());
254 TrackDismissEvent(DISMISS_EVENT_BANNER_CLICK);
255 return true;
258 bool RegisterAppBannerInfoBarDelegateAndroid(JNIEnv* env) {
259 return RegisterNativesImpl(env);
262 } // namespace banners