Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(286)

Side by Side Diff: chrome/browser/android/banners/app_banner_infobar_delegate_android.cc

Issue 2290603005: Trigger app banner when add to homescreen is pressed and WebAPKs are enabled. (Closed)
Patch Set: Nits. Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 19 matching lines...) Expand all
30 #include "ui/gfx/android/java_bitmap.h" 30 #include "ui/gfx/android/java_bitmap.h"
31 #include "url/gurl.h" 31 #include "url/gurl.h"
32 32
33 using base::android::ConvertJavaStringToUTF8; 33 using base::android::ConvertJavaStringToUTF8;
34 using base::android::ConvertJavaStringToUTF16; 34 using base::android::ConvertJavaStringToUTF16;
35 using base::android::ConvertUTF8ToJavaString; 35 using base::android::ConvertUTF8ToJavaString;
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 {
41
42 bool IsInfoEmpty(const ShortcutInfo* info) {
43 return !info || info->url.is_empty();
44 }
45
46 } // anonymous namespace
47
40 namespace banners { 48 namespace banners {
41 49
42 AppBannerInfoBarDelegateAndroid::AppBannerInfoBarDelegateAndroid( 50 AppBannerInfoBarDelegateAndroid::AppBannerInfoBarDelegateAndroid(
43 base::WeakPtr<AppBannerManager> weak_manager, 51 base::WeakPtr<AppBannerManager> weak_manager,
44 const base::string16& app_title, 52 const base::string16& app_title,
45 const GURL& manifest_url, 53 std::unique_ptr<ShortcutInfo> shortcut_info,
46 const content::Manifest& manifest,
47 const GURL& icon_url,
48 std::unique_ptr<SkBitmap> icon, 54 std::unique_ptr<SkBitmap> icon,
49 int event_request_id, 55 int event_request_id,
50 bool is_webapk) 56 bool is_webapk)
51 : weak_manager_(weak_manager), 57 : weak_manager_(weak_manager),
52 app_title_(app_title), 58 app_title_(app_title),
53 manifest_url_(manifest_url), 59 shortcut_info_(std::move(shortcut_info)),
54 manifest_(manifest),
55 icon_url_(icon_url),
56 icon_(std::move(icon)), 60 icon_(std::move(icon)),
57 event_request_id_(event_request_id), 61 event_request_id_(event_request_id),
58 has_user_interaction_(false), 62 has_user_interaction_(false),
59 is_webapk_(is_webapk), 63 is_webapk_(is_webapk),
60 weak_ptr_factory_(this) { 64 weak_ptr_factory_(this) {
61 DCHECK(!manifest.IsEmpty()); 65 DCHECK(!IsInfoEmpty(shortcut_info_.get()));
62 CreateJavaDelegate(); 66 CreateJavaDelegate();
63 } 67 }
64 68
65 AppBannerInfoBarDelegateAndroid::AppBannerInfoBarDelegateAndroid( 69 AppBannerInfoBarDelegateAndroid::AppBannerInfoBarDelegateAndroid(
66 const base::string16& app_title, 70 const base::string16& app_title,
67 const base::android::ScopedJavaGlobalRef<jobject>& native_app_data, 71 const base::android::ScopedJavaGlobalRef<jobject>& native_app_data,
68 std::unique_ptr<SkBitmap> icon, 72 std::unique_ptr<SkBitmap> icon,
69 const std::string& native_app_package, 73 const std::string& native_app_package,
70 const std::string& referrer, 74 const std::string& referrer,
71 int event_request_id) 75 int event_request_id)
72 : app_title_(app_title), 76 : app_title_(app_title),
73 native_app_data_(native_app_data), 77 native_app_data_(native_app_data),
74 icon_(std::move(icon)), 78 icon_(std::move(icon)),
75 native_app_package_(native_app_package), 79 native_app_package_(native_app_package),
76 referrer_(referrer), 80 referrer_(referrer),
77 event_request_id_(event_request_id), 81 event_request_id_(event_request_id),
78 has_user_interaction_(false), 82 has_user_interaction_(false),
79 weak_ptr_factory_(this) { 83 weak_ptr_factory_(this) {
80 DCHECK(!native_app_data_.is_null()); 84 DCHECK(!native_app_data_.is_null());
81 CreateJavaDelegate(); 85 CreateJavaDelegate();
82 } 86 }
83 87
84 AppBannerInfoBarDelegateAndroid::~AppBannerInfoBarDelegateAndroid() { 88 AppBannerInfoBarDelegateAndroid::~AppBannerInfoBarDelegateAndroid() {
85 weak_ptr_factory_.InvalidateWeakPtrs(); 89 weak_ptr_factory_.InvalidateWeakPtrs();
86 90
87 if (!has_user_interaction_) { 91 if (!has_user_interaction_) {
88 if (!native_app_data_.is_null()) 92 if (!native_app_data_.is_null())
89 TrackUserResponse(USER_RESPONSE_NATIVE_APP_IGNORED); 93 TrackUserResponse(USER_RESPONSE_NATIVE_APP_IGNORED);
90 else if (!manifest_.IsEmpty()) 94 else if (!IsInfoEmpty(shortcut_info_.get()))
91 TrackUserResponse(USER_RESPONSE_WEB_APP_IGNORED); 95 TrackUserResponse(USER_RESPONSE_WEB_APP_IGNORED);
92 } 96 }
93 97
94 TrackDismissEvent(DISMISS_EVENT_DISMISSED); 98 TrackDismissEvent(DISMISS_EVENT_DISMISSED);
95 JNIEnv* env = base::android::AttachCurrentThread(); 99 JNIEnv* env = base::android::AttachCurrentThread();
96 Java_AppBannerInfoBarDelegateAndroid_destroy(env, java_delegate_); 100 Java_AppBannerInfoBarDelegateAndroid_destroy(env, java_delegate_);
97 java_delegate_.Reset(); 101 java_delegate_.Reset();
98 } 102 }
99 103
100 void AppBannerInfoBarDelegateAndroid::UpdateInstallState( 104 void AppBannerInfoBarDelegateAndroid::UpdateInstallState(
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
147 151
148 if (success) { 152 if (success) {
149 TrackInstallEvent(INSTALL_EVENT_NATIVE_APP_INSTALL_COMPLETED); 153 TrackInstallEvent(INSTALL_EVENT_NATIVE_APP_INSTALL_COMPLETED);
150 UpdateInstallState(env, obj); 154 UpdateInstallState(env, obj);
151 } else if (infobar()->owner()) { 155 } else if (infobar()->owner()) {
152 TrackDismissEvent(DISMISS_EVENT_INSTALL_TIMEOUT); 156 TrackDismissEvent(DISMISS_EVENT_INSTALL_TIMEOUT);
153 infobar()->owner()->RemoveInfoBar(infobar()); 157 infobar()->owner()->RemoveInfoBar(infobar());
154 } 158 }
155 } 159 }
156 160
161 void AppBannerInfoBarDelegateAndroid::InstallWebApk(
Peter Kasting 2016/09/06 19:31:23 Nit: This function just wraps AcceptWebApk(). Mak
Xi Han 2016/09/07 15:53:17 Done.
162 content::WebContents* web_contents) {
163 if (!web_contents) {
Peter Kasting 2016/09/06 19:31:23 Will callers ever pass you null? If not, do nothi
Xi Han 2016/09/07 15:53:17 Move the extra logic to the callers.
164 LOG(ERROR) << "Failed to create infobar to install the WebAPK: "
165 << "the associated WebContents is null.";
166 return;
167 }
168 AcceptWebApk(web_contents);
169 }
170
157 void AppBannerInfoBarDelegateAndroid::CreateJavaDelegate() { 171 void AppBannerInfoBarDelegateAndroid::CreateJavaDelegate() {
158 JNIEnv* env = base::android::AttachCurrentThread(); 172 JNIEnv* env = base::android::AttachCurrentThread();
159 java_delegate_.Reset(Java_AppBannerInfoBarDelegateAndroid_create( 173 java_delegate_.Reset(Java_AppBannerInfoBarDelegateAndroid_create(
160 env, 174 env,
161 reinterpret_cast<intptr_t>(this))); 175 reinterpret_cast<intptr_t>(this)));
162 } 176 }
163 177
164 void AppBannerInfoBarDelegateAndroid::SendBannerAccepted( 178 void AppBannerInfoBarDelegateAndroid::SendBannerAccepted(
165 content::WebContents* web_contents, 179 content::WebContents* web_contents,
166 const std::string& platform) { 180 const std::string& platform) {
(...skipping 23 matching lines...) Expand all
190 204
191 web_contents->GetMainFrame()->Send( 205 web_contents->GetMainFrame()->Send(
192 new ChromeViewMsg_AppBannerDismissed( 206 new ChromeViewMsg_AppBannerDismissed(
193 web_contents->GetMainFrame()->GetRoutingID(), 207 web_contents->GetMainFrame()->GetRoutingID(),
194 event_request_id_)); 208 event_request_id_));
195 209
196 if (!native_app_data_.is_null()) { 210 if (!native_app_data_.is_null()) {
197 TrackUserResponse(USER_RESPONSE_NATIVE_APP_DISMISSED); 211 TrackUserResponse(USER_RESPONSE_NATIVE_APP_DISMISSED);
198 AppBannerSettingsHelper::RecordBannerDismissEvent( 212 AppBannerSettingsHelper::RecordBannerDismissEvent(
199 web_contents, native_app_package_, AppBannerSettingsHelper::NATIVE); 213 web_contents, native_app_package_, AppBannerSettingsHelper::NATIVE);
200 } else if (!manifest_.IsEmpty()) { 214 } else if (!IsInfoEmpty(shortcut_info_.get())) {
201 TrackUserResponse(USER_RESPONSE_WEB_APP_DISMISSED); 215 TrackUserResponse(USER_RESPONSE_WEB_APP_DISMISSED);
202 AppBannerSettingsHelper::RecordBannerDismissEvent( 216 AppBannerSettingsHelper::RecordBannerDismissEvent(
203 web_contents, manifest_.start_url.spec(), 217 web_contents, shortcut_info_->url.spec(),
204 AppBannerSettingsHelper::WEB); 218 AppBannerSettingsHelper::WEB);
205 } 219 }
206 } 220 }
207 221
208 base::string16 AppBannerInfoBarDelegateAndroid::GetMessageText() const { 222 base::string16 AppBannerInfoBarDelegateAndroid::GetMessageText() const {
209 return app_title_; 223 return app_title_;
210 } 224 }
211 225
212 int AppBannerInfoBarDelegateAndroid::GetButtons() const { 226 int AppBannerInfoBarDelegateAndroid::GetButtons() const {
213 return BUTTON_OK; 227 return BUTTON_OK;
214 } 228 }
215 229
216 bool AppBannerInfoBarDelegateAndroid::Accept() { 230 bool AppBannerInfoBarDelegateAndroid::Accept() {
217 has_user_interaction_ = true; 231 has_user_interaction_ = true;
218 232
219 content::WebContents* web_contents = 233 content::WebContents* web_contents =
220 InfoBarService::WebContentsFromInfoBar(infobar()); 234 InfoBarService::WebContentsFromInfoBar(infobar());
221 if (!web_contents) { 235 if (!web_contents) {
222 TrackDismissEvent(DISMISS_EVENT_ERROR); 236 TrackDismissEvent(DISMISS_EVENT_ERROR);
223 return true; 237 return true;
224 } 238 }
225 239
226 if (!native_app_data_.is_null()) { 240 if (!native_app_data_.is_null()) {
227 return AcceptNativeApp(web_contents); 241 return AcceptNativeApp(web_contents);
228 } else if (is_webapk_) { 242 } else if (is_webapk_) {
Peter Kasting 2016/09/06 19:31:23 Nit: No else after return
Xi Han 2016/09/07 15:53:17 Done.
229 return AcceptWebApk(web_contents); 243 return AcceptWebApk(web_contents);
230 } 244 }
231 return AcceptWebApp(web_contents); 245 return AcceptWebApp(web_contents);
232 } 246 }
233 247
234 bool AppBannerInfoBarDelegateAndroid::AcceptNativeApp( 248 bool AppBannerInfoBarDelegateAndroid::AcceptNativeApp(
235 content::WebContents* web_contents) { 249 content::WebContents* web_contents) {
236 TrackUserResponse(USER_RESPONSE_NATIVE_APP_ACCEPTED); 250 TrackUserResponse(USER_RESPONSE_NATIVE_APP_ACCEPTED);
237 JNIEnv* env = base::android::AttachCurrentThread(); 251 JNIEnv* env = base::android::AttachCurrentThread();
238 252
(...skipping 14 matching lines...) Expand all
253 TrackDismissEvent(DISMISS_EVENT_APP_OPEN); 267 TrackDismissEvent(DISMISS_EVENT_APP_OPEN);
254 } else { 268 } else {
255 TrackInstallEvent(INSTALL_EVENT_NATIVE_APP_INSTALL_TRIGGERED); 269 TrackInstallEvent(INSTALL_EVENT_NATIVE_APP_INSTALL_TRIGGERED);
256 } 270 }
257 SendBannerAccepted(web_contents, "play"); 271 SendBannerAccepted(web_contents, "play");
258 return was_opened; 272 return was_opened;
259 } 273 }
260 274
261 bool AppBannerInfoBarDelegateAndroid::AcceptWebApp( 275 bool AppBannerInfoBarDelegateAndroid::AcceptWebApp(
262 content::WebContents* web_contents) { 276 content::WebContents* web_contents) {
263 if (manifest_.IsEmpty()) 277 if (IsInfoEmpty(shortcut_info_.get()))
264 return true; 278 return true;
265 TrackUserResponse(USER_RESPONSE_WEB_APP_ACCEPTED); 279 TrackUserResponse(USER_RESPONSE_WEB_APP_ACCEPTED);
266 280
267 AppBannerSettingsHelper::RecordBannerInstallEvent( 281 AppBannerSettingsHelper::RecordBannerInstallEvent(
268 web_contents, manifest_.start_url.spec(), 282 web_contents, shortcut_info_->url.spec(),
269 AppBannerSettingsHelper::WEB); 283 AppBannerSettingsHelper::WEB);
270 284
271 if (weak_manager_) { 285 if (weak_manager_) {
272 ShortcutInfo info(GURL::EmptyGURL());
273 info.UpdateFromManifest(manifest_);
274 info.manifest_url = manifest_url_;
275 info.icon_url = icon_url_;
276 info.UpdateSource(ShortcutInfo::SOURCE_APP_BANNER);
277
278 const std::string& uid = base::GenerateGUID(); 286 const std::string& uid = base::GenerateGUID();
279 ShortcutHelper::AddToLauncherWithSkBitmap( 287 ShortcutHelper::AddToLauncherWithSkBitmap(
280 web_contents->GetBrowserContext(), info, uid, *icon_.get(), 288 web_contents->GetBrowserContext(),
289 *shortcut_info_.get(), uid, *icon_.get(),
281 weak_manager_->FetchWebappSplashScreenImageCallback(uid)); 290 weak_manager_->FetchWebappSplashScreenImageCallback(uid));
282 } 291 }
283 292
284 SendBannerAccepted(web_contents, "web"); 293 SendBannerAccepted(web_contents, "web");
285 return true; 294 return true;
286 } 295 }
287 296
288 bool AppBannerInfoBarDelegateAndroid::AcceptWebApk( 297 bool AppBannerInfoBarDelegateAndroid::AcceptWebApk(
289 content::WebContents* web_contents) { 298 content::WebContents* web_contents) {
290 if (manifest_.IsEmpty()) 299 if (IsInfoEmpty(shortcut_info_.get()))
291 return true; 300 return true;
292 301
293 JNIEnv* env = base::android::AttachCurrentThread(); 302 JNIEnv* env = base::android::AttachCurrentThread();
294 // |webapk_package_name_| is set when the WebAPK has finished installing. 303 // |webapk_package_name_| is set when the WebAPK has finished installing.
295 // If the |webapk_package_name_| is empty, it means the "Add to Homescreen" 304 // If the |webapk_package_name_| is empty, it means the "Add to Homescreen"
296 // button is pressed, so request WebAPK installation. Otherwise, it means 305 // button is pressed, so request WebAPK installation. Otherwise, it means
297 // the "Open" button is pressed, then open the installed WebAPK. 306 // the "Open" button is pressed, then open the installed WebAPK.
298 if (webapk_package_name_.empty()) { 307 if (webapk_package_name_.empty()) {
299 // Request install the WebAPK. 308 // Request install the WebAPK.
300 TrackUserResponse(USER_RESPONSE_WEB_APP_ACCEPTED); 309 TrackUserResponse(USER_RESPONSE_WEB_APP_ACCEPTED);
301 310
302 AppBannerSettingsHelper::RecordBannerInstallEvent( 311 AppBannerSettingsHelper::RecordBannerInstallEvent(
303 web_contents, manifest_.start_url.spec(), 312 web_contents, shortcut_info_->url.spec(),
304 AppBannerSettingsHelper::WEB); 313 AppBannerSettingsHelper::WEB);
305 314
306 ShortcutInfo info(GURL::EmptyGURL());
307 info.UpdateFromManifest(manifest_);
308 info.manifest_url = manifest_url_;
309 info.icon_url = icon_url_;
310 info.UpdateSource(ShortcutInfo::SOURCE_APP_BANNER);
311
312 Java_AppBannerInfoBarDelegateAndroid_setWebApkInstallingState( 315 Java_AppBannerInfoBarDelegateAndroid_setWebApkInstallingState(
313 env, java_delegate_, true); 316 env, java_delegate_, true);
314 UpdateInstallState(env, nullptr); 317 UpdateInstallState(env, nullptr);
315 318
316 WebApkInstaller::FinishCallback callback = base::Bind( 319 WebApkInstaller::FinishCallback callback = base::Bind(
317 &AppBannerInfoBarDelegateAndroid::OnWebApkInstallFinished, 320 &AppBannerInfoBarDelegateAndroid::OnWebApkInstallFinished,
318 weak_ptr_factory_.GetWeakPtr()); 321 weak_ptr_factory_.GetWeakPtr());
319 DVLOG(1) << "Trigger the installation of the WebAPK."; 322 DVLOG(1) << "Trigger the installation of the WebAPK.";
320 ShortcutHelper::InstallWebApkWithSkBitmap( 323 ShortcutHelper::InstallWebApkWithSkBitmap(
321 web_contents->GetBrowserContext(), info, *icon_.get(), callback); 324 web_contents->GetBrowserContext(), *shortcut_info_.get(),
325 *icon_.get(), callback);
322 326
323 SendBannerAccepted(web_contents, "web"); 327 SendBannerAccepted(web_contents, "web");
324 // Returns false to prevent the infobar from disappearing. 328 // Returns false to prevent the infobar from disappearing.
325 return false; 329 return false;
326 } 330 }
327 331
328 // Open the WebAPK. 332 // Open the WebAPK.
329 ScopedJavaLocalRef<jstring> java_webapk_package_name = 333 ScopedJavaLocalRef<jstring> java_webapk_package_name =
330 base::android::ConvertUTF8ToJavaString(env, webapk_package_name_); 334 base::android::ConvertUTF8ToJavaString(env, webapk_package_name_);
331 Java_AppBannerInfoBarDelegateAndroid_openWebApk( 335 Java_AppBannerInfoBarDelegateAndroid_openWebApk(
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
375 return true; 379 return true;
376 } 380 }
377 381
378 Java_AppBannerInfoBarDelegateAndroid_showAppDetails( 382 Java_AppBannerInfoBarDelegateAndroid_showAppDetails(
379 env, java_delegate_, tab->GetJavaObject(), native_app_data_); 383 env, java_delegate_, tab->GetJavaObject(), native_app_data_);
380 384
381 TrackDismissEvent(DISMISS_EVENT_BANNER_CLICK); 385 TrackDismissEvent(DISMISS_EVENT_BANNER_CLICK);
382 return true; 386 return true;
383 } 387 }
384 388
389 AppBannerInfoBarDelegateAndroid*
390 AppBannerInfoBarDelegateAndroid::AsAppBannerInfoBarDelegateAndroid() {
391 return this;
392 }
393
385 bool RegisterAppBannerInfoBarDelegateAndroid(JNIEnv* env) { 394 bool RegisterAppBannerInfoBarDelegateAndroid(JNIEnv* env) {
386 return RegisterNativesImpl(env); 395 return RegisterNativesImpl(env);
387 } 396 }
388 397
389 } // namespace banners 398 } // namespace banners
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698