Commit a7dc4074 authored by Mehran Mahmoudi's avatar Mehran Mahmoudi Committed by Commit Bot

Move AddToHomescreen to MVC (Part 3)

This is the third part in a series of CLs for moving the
AddToHomescreen component to MVC in Android.

In this CL the AddToHomescreenInstaller and
AddToHomescreenParams classes are added.
AppBannerUiDelegateAndroid and AddToHomescreenManager classes are
edited to use these new classes.

Design doc: http://go/a2hs-mvc

A subsequient CL will implement the coordinator and the mediator classes
and remove the AppBannerUiDelegateAndroid and AddToHomescreenManager
classes.

Bug: 994759
Change-Id: Iaaa0b714d4aac9c3d348348a972b937bdaa246c6
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1864568
Auto-Submit: Mehran Mahmoudi <mahmoudi@chromium.org>
Reviewed-by: default avatarPeter Kotwicz <pkotwicz@chromium.org>
Reviewed-by: default avatarDominick Ng <dominickn@chromium.org>
Reviewed-by: default avatarMichael Thiessen <mthiesse@chromium.org>
Commit-Queue: Mehran Mahmoudi <mahmoudi@chromium.org>
Cr-Commit-Position: refs/heads/master@{#711258}
parent 4c57052c
......@@ -587,6 +587,7 @@ java_cpp_enum("chrome_android_java_enums_srcjar") {
"//chrome/browser/android/webapk/webapk_install_service.h",
"//chrome/browser/android/webapk/webapk_installer.h",
"//chrome/browser/android/webapk/webapk_types.h",
"//chrome/browser/android/webapps/add_to_homescreen_params.h",
"//chrome/browser/banners/app_banner_settings_helper.h",
"//chrome/browser/download/android/download_open_source.h",
"//chrome/browser/notifications/notification_channels_provider_android.h",
......@@ -2796,6 +2797,7 @@ generate_jni("chrome_jni_headers") {
"java/src/org/chromium/chrome/browser/webapps/WebApkUpdateDataFetcher.java",
"java/src/org/chromium/chrome/browser/webapps/WebApkUpdateManager.java",
"java/src/org/chromium/chrome/browser/webapps/WebappRegistry.java",
"java/src/org/chromium/chrome/browser/webapps/addtohomescreen/AddToHomescreenInstaller.java",
"java/src/org/chromium/chrome/browser/webapps/addtohomescreen/AddToHomescreenManager.java",
"java/src/org/chromium/chrome/browser/widget/ThumbnailGenerator.java",
]
......
......@@ -1797,6 +1797,7 @@ chrome_java_sources = [
"java/src/org/chromium/chrome/browser/webapps/WebappRegistry.java",
"java/src/org/chromium/chrome/browser/webapps/WebappScopePolicy.java",
"java/src/org/chromium/chrome/browser/webapps/WebappTabDelegate.java",
"java/src/org/chromium/chrome/browser/webapps/addtohomescreen/AddToHomescreenInstaller.java",
"java/src/org/chromium/chrome/browser/webapps/addtohomescreen/AddToHomescreenManager.java",
"java/src/org/chromium/chrome/browser/webapps/addtohomescreen/AddToHomescreenProperties.java",
"java/src/org/chromium/chrome/browser/webapps/addtohomescreen/AddToHomescreenDialogView.java",
......
......@@ -4,15 +4,9 @@
package org.chromium.chrome.browser.banners;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.util.Pair;
import org.chromium.base.ContextUtils;
import org.chromium.base.Log;
import org.chromium.base.PackageUtils;
import org.chromium.base.annotations.CalledByNative;
import org.chromium.base.annotations.JNINamespace;
import org.chromium.base.annotations.NativeMethods;
......@@ -22,6 +16,7 @@ import org.chromium.chrome.browser.webapps.addtohomescreen.AddToHomescreenDialog
import org.chromium.chrome.browser.webapps.addtohomescreen.AddToHomescreenProperties;
import org.chromium.chrome.browser.webapps.addtohomescreen.AddToHomescreenViewBinder;
import org.chromium.chrome.browser.webapps.addtohomescreen.AddToHomescreenViewDelegate;
import org.chromium.chrome.browser.webapps.addtohomescreen.AppType;
import org.chromium.ui.modelutil.PropertyModel;
import org.chromium.ui.modelutil.PropertyModelChangeProcessor;
......@@ -83,27 +78,6 @@ public class AppBannerUiDelegateAndroid implements AddToHomescreenViewDelegate {
mAddedToHomescreen = false;
}
@CalledByNative
private boolean installOrOpenNativeApp(AppData appData) {
Context context = ContextUtils.getApplicationContext();
Intent launchIntent;
if (PackageUtils.isPackageInstalled(context, appData.packageName())) {
launchIntent =
context.getPackageManager().getLaunchIntentForPackage(appData.packageName());
} else {
launchIntent = appData.installIntent();
}
if (launchIntent != null && mTab.getActivity() != null) {
try {
mTab.getActivity().startActivity(launchIntent);
} catch (ActivityNotFoundException e) {
Log.e(TAG, "Failed to install or open app : %s!", appData.packageName(), e);
return false;
}
}
return true;
}
@CalledByNative
private void showAppDetails(AppData appData) {
mTab.getWindowAndroid().showIntent(appData.detailsIntent(), null, null);
......@@ -125,11 +99,11 @@ public class AppBannerUiDelegateAndroid implements AddToHomescreenViewDelegate {
}
@CalledByNative
private boolean showNativeAppDialog(String title, Bitmap iconBitmap, AppData appData) {
private boolean showNativeAppDialog(Bitmap iconBitmap, AppData appData) {
mViewModel = createViewModel();
mViewModel.set(AddToHomescreenProperties.TITLE, title);
mViewModel.set(AddToHomescreenProperties.TITLE, appData.title());
mViewModel.set(AddToHomescreenProperties.ICON, new Pair<>(iconBitmap, false));
mViewModel.set(AddToHomescreenProperties.TYPE, AddToHomescreenProperties.AppType.NATIVE);
mViewModel.set(AddToHomescreenProperties.TYPE, AppType.NATIVE);
mViewModel.set(AddToHomescreenProperties.CAN_SUBMIT, true);
mViewModel.set(AddToHomescreenProperties.NATIVE_APP_RATING, appData.rating());
mViewModel.set(
......@@ -142,7 +116,7 @@ public class AppBannerUiDelegateAndroid implements AddToHomescreenViewDelegate {
String title, Bitmap iconBitmap, String url, boolean maskable) {
mViewModel = createViewModel();
mViewModel.set(AddToHomescreenProperties.TITLE, title);
mViewModel.set(AddToHomescreenProperties.TYPE, AddToHomescreenProperties.AppType.WEB_APK);
mViewModel.set(AddToHomescreenProperties.TYPE, AppType.WEBAPK);
mViewModel.set(AddToHomescreenProperties.CAN_SUBMIT, true);
mViewModel.set(AddToHomescreenProperties.URL, url);
......
......@@ -25,7 +25,6 @@ import android.widget.TextView;
import org.chromium.base.ContextUtils;
import org.chromium.base.VisibleForTesting;
import org.chromium.chrome.R;
import org.chromium.chrome.browser.webapps.addtohomescreen.AddToHomescreenProperties.AppType;
import org.chromium.ui.modaldialog.DialogDismissalCause;
import org.chromium.ui.modaldialog.ModalDialogManager;
import org.chromium.ui.modaldialog.ModalDialogProperties;
......@@ -159,7 +158,7 @@ public class AddToHomescreenDialogView
mShortcutTitleInput.setVisibility(type == AppType.SHORTCUT ? View.VISIBLE : View.GONE);
mAppLayout.setVisibility(type != AppType.SHORTCUT ? View.VISIBLE : View.GONE);
mAppOriginView.setVisibility(type == AppType.WEB_APK ? View.VISIBLE : View.GONE);
mAppOriginView.setVisibility(type == AppType.WEBAPK ? View.VISIBLE : View.GONE);
mAppRatingBar.setVisibility(type == AppType.NATIVE ? View.VISIBLE : View.GONE);
mPlayLogoView.setVisibility(type == AppType.NATIVE ? View.VISIBLE : View.GONE);
}
......
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package org.chromium.chrome.browser.webapps.addtohomescreen;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
import org.chromium.base.ContextUtils;
import org.chromium.base.Log;
import org.chromium.base.PackageUtils;
import org.chromium.base.annotations.CalledByNative;
import org.chromium.chrome.browser.banners.AppData;
import org.chromium.chrome.browser.tab.Tab;
/**
* Provides functionality related to native Android apps for its C++ counterpart,
* add_to_homescreen_installer.cc.
*/
class AddToHomescreenInstaller {
private static final String TAG = "AddToHomescreen";
@CalledByNative
private static boolean installOrOpenNativeApp(Tab tab, AppData appData) {
Context context = ContextUtils.getApplicationContext();
Intent launchIntent;
if (PackageUtils.isPackageInstalled(context, appData.packageName())) {
launchIntent =
context.getPackageManager().getLaunchIntentForPackage(appData.packageName());
} else {
launchIntent = appData.installIntent();
}
if (launchIntent != null && tab.getActivity() != null) {
try {
tab.getActivity().startActivity(launchIntent);
} catch (ActivityNotFoundException e) {
Log.e(TAG, "Failed to install or open app : %s!", appData.packageName(), e);
return false;
}
}
return true;
}
}
......@@ -94,9 +94,8 @@ public class AddToHomescreenManager implements AddToHomescreenViewDelegate {
// let users change them.
mViewModel.set(AddToHomescreenProperties.TITLE, title);
mViewModel.set(AddToHomescreenProperties.URL, url);
mViewModel.set(AddToHomescreenProperties.TYPE,
isWebapp ? AddToHomescreenProperties.AppType.WEB_APK
: AddToHomescreenProperties.AppType.SHORTCUT);
mViewModel.set(
AddToHomescreenProperties.TYPE, isWebapp ? AppType.WEBAPK : AppType.SHORTCUT);
}
@CalledByNative
......
......@@ -5,27 +5,15 @@
package org.chromium.chrome.browser.webapps.addtohomescreen;
import android.graphics.Bitmap;
import android.support.annotation.IntDef;
import android.util.Pair;
import org.chromium.ui.modelutil.PropertyKey;
import org.chromium.ui.modelutil.PropertyModel;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
/**
* Contains the properties that an add-to-homescreen {@link PropertyModel} can have.
*/
public class AddToHomescreenProperties {
@IntDef({AppType.NATIVE, AppType.WEB_APK, AppType.SHORTCUT})
@Retention(RetentionPolicy.SOURCE)
public @interface AppType {
int NATIVE = 0;
int WEB_APK = 1;
int SHORTCUT = 2;
}
public static final PropertyModel.WritableObjectPropertyKey<String> TITLE =
new PropertyModel.WritableObjectPropertyKey<>();
public static final PropertyModel.WritableObjectPropertyKey<String> URL =
......
......@@ -20,7 +20,6 @@ import org.chromium.base.test.BaseRobolectricTestRunner;
import org.chromium.base.test.util.CallbackHelper;
import org.chromium.base.test.util.Feature;
import org.chromium.chrome.R;
import org.chromium.chrome.browser.webapps.addtohomescreen.AddToHomescreenProperties.AppType;
import org.chromium.ui.modaldialog.DialogDismissalCause;
import org.chromium.ui.modaldialog.ModalDialogManager;
import org.chromium.ui.modaldialog.ModalDialogProperties;
......@@ -136,12 +135,12 @@ public class AddToHomescreenDialogViewTest {
}
/**
* Tests the view for {@link AppType#WEB_APK}.
* Tests the view for {@link AppType#WEBAPK}.
*/
@Test
@Feature({"Webapp"})
public void testWebAPK() {
initDialogView(AppType.WEB_APK);
initDialogView(AppType.WEBAPK);
mAddToHomescreenDialogView.setUrl(TEST_URL);
assertVisibility(R.id.spinny, false);
......@@ -205,8 +204,8 @@ public class AddToHomescreenDialogViewTest {
public void testAddButtonState() {
PropertyModel shownDialogModel = mModalDialogManager.getShownDialogModel();
// Assert 'Add' will be enabled for AppType#WEB_APK after #setCanSubmit(true) is called.
mAddToHomescreenDialogView.setType(AppType.WEB_APK);
// Assert 'Add' will be enabled for AppType#WEBAPK after #setCanSubmit(true) is called.
mAddToHomescreenDialogView.setType(AppType.WEBAPK);
Assert.assertTrue(shownDialogModel.get(ModalDialogProperties.POSITIVE_BUTTON_DISABLED));
mAddToHomescreenDialogView.setCanSubmit(true);
Assert.assertFalse(shownDialogModel.get(ModalDialogProperties.POSITIVE_BUTTON_DISABLED));
......@@ -279,7 +278,7 @@ public class AddToHomescreenDialogViewTest {
@Test
@Feature({"Webapp"})
public void testInstallCallback() {
initDialogView(AppType.WEB_APK);
initDialogView(AppType.WEBAPK);
PropertyModel shownDialogModel = mModalDialogManager.getShownDialogModel();
Assert.assertEquals(0, mAddCallback.getCallCount());
shownDialogModel.get(ModalDialogProperties.CONTROLLER)
......
......@@ -33,7 +33,7 @@ public class AddToHomescreenViewBinderTest {
viewModel.set(AddToHomescreenProperties.NATIVE_INSTALL_BUTTON_TEXT, "Install");
viewModel.set(AddToHomescreenProperties.NATIVE_APP_RATING, 3.4f);
viewModel.set(AddToHomescreenProperties.TITLE, "My App");
viewModel.set(AddToHomescreenProperties.TYPE, AddToHomescreenProperties.AppType.NATIVE);
viewModel.set(AddToHomescreenProperties.TYPE, AppType.NATIVE);
viewModel.set(AddToHomescreenProperties.URL, "google.com");
// Invoke the binder.
......@@ -45,7 +45,7 @@ public class AddToHomescreenViewBinderTest {
Mockito.verify(view, Mockito.times(1)).setNativeInstallButtonText("Install");
Mockito.verify(view, Mockito.times(1)).setNativeAppRating(3.4f);
Mockito.verify(view, Mockito.times(1)).setTitle("My App");
Mockito.verify(view, Mockito.times(1)).setType(AddToHomescreenProperties.AppType.NATIVE);
Mockito.verify(view, Mockito.times(1)).setType(AppType.NATIVE);
Mockito.verify(view, Mockito.times(1)).setUrl("google.com");
}
}
......@@ -2655,8 +2655,12 @@ jumbo_static_library("browser") {
"android/webapk/webapk_web_manifest_checker.h",
"android/webapps/add_to_homescreen_data_fetcher.cc",
"android/webapps/add_to_homescreen_data_fetcher.h",
"android/webapps/add_to_homescreen_installer.cc",
"android/webapps/add_to_homescreen_installer.h",
"android/webapps/add_to_homescreen_manager.cc",
"android/webapps/add_to_homescreen_manager.h",
"android/webapps/add_to_homescreen_params.cc",
"android/webapps/add_to_homescreen_params.h",
"android/webapps/webapp_registry.cc",
"android/webapps/webapp_registry.h",
"android/widget/thumbnail_generator.cc",
......
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/android/webapps/add_to_homescreen_installer.h"
#include <utility>
#include "base/callback.h"
#include "chrome/android/chrome_jni_headers/AddToHomescreenInstaller_jni.h"
#include "chrome/browser/android/shortcut_helper.h"
#include "chrome/browser/android/tab_android.h"
#include "chrome/browser/android/webapk/webapk_install_service.h"
#include "content/public/browser/web_contents.h"
// static
void AddToHomescreenInstaller::Install(
content::WebContents* web_contents,
const AddToHomescreenParams& params,
const base::RepeatingCallback<void(Event, const AddToHomescreenParams&)>&
event_callback) {
if (!web_contents) {
event_callback.Run(Event::INSTALL_FAILED, params);
return;
}
event_callback.Run(Event::INSTALL_STARTED, params);
switch (params.app_type) {
case AddToHomescreenParams::AppType::NATIVE:
InstallOrOpenNativeApp(web_contents, params, event_callback);
break;
case AddToHomescreenParams::AppType::WEBAPK:
InstallWebApk(web_contents, params);
break;
case AddToHomescreenParams::AppType::SHORTCUT:
InstallShortcut(web_contents, params);
break;
}
event_callback.Run(Event::INSTALL_REQUEST_FINISHED, params);
}
// static
void AddToHomescreenInstaller::InstallOrOpenNativeApp(
content::WebContents* web_contents,
const AddToHomescreenParams& params,
const base::RepeatingCallback<void(Event, const AddToHomescreenParams&)>&
event_callback) {
JNIEnv* env = base::android::AttachCurrentThread();
TabAndroid* tab = TabAndroid::FromWebContents(web_contents);
if (tab == nullptr) {
event_callback.Run(Event::INSTALL_FAILED, params);
return;
}
bool was_successful = Java_AddToHomescreenInstaller_installOrOpenNativeApp(
env, tab->GetJavaObject(), params.native_app_data);
event_callback.Run(was_successful ? Event::NATIVE_INSTALL_OR_OPEN_SUCCEEDED
: Event::NATIVE_INSTALL_OR_OPEN_FAILED,
params);
}
// static
void AddToHomescreenInstaller::InstallWebApk(
content::WebContents* web_contents,
const AddToHomescreenParams& params) {
WebApkInstallService::Get(web_contents->GetBrowserContext())
->InstallAsync(web_contents, *(params.shortcut_info), params.primary_icon,
params.has_maskable_primary_icon, params.badge_icon,
params.install_source);
}
// static
void AddToHomescreenInstaller::InstallShortcut(
content::WebContents* web_contents,
const AddToHomescreenParams& params) {
ShortcutHelper::AddToLauncherWithSkBitmap(
web_contents, *(params.shortcut_info), params.primary_icon,
params.has_maskable_primary_icon);
}
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_ANDROID_WEBAPPS_ADD_TO_HOMESCREEN_INSTALLER_H_
#define CHROME_BROWSER_ANDROID_WEBAPPS_ADD_TO_HOMESCREEN_INSTALLER_H_
#include "base/callback_forward.h"
#include "base/macros.h"
#include "chrome/browser/android/webapps/add_to_homescreen_params.h"
namespace content {
class WebContents;
}
// Helper class for installing a web app or an Android native app and recording
// related UMA.
class AddToHomescreenInstaller {
public:
enum class Event {
INSTALL_STARTED,
INSTALL_FAILED,
INSTALL_REQUEST_FINISHED,
NATIVE_INSTALL_OR_OPEN_FAILED,
NATIVE_INSTALL_OR_OPEN_SUCCEEDED,
NATIVE_DETAILS_SHOWN,
UI_SHOWN,
UI_DISMISSED,
};
// Installs the app referenced by the data in this object.
// |event_callback| will be run to inform the caller of the progress of the
// installation. It is guaranteed that |event_callback| will only be called
// before the add-to-homescreen prompt is dismissed.
static void Install(
content::WebContents* web_contents,
const AddToHomescreenParams& params,
const base::RepeatingCallback<void(Event, const AddToHomescreenParams&)>&
event_callback);
private:
static void InstallOrOpenNativeApp(
content::WebContents* web_contents,
const AddToHomescreenParams& params,
const base::RepeatingCallback<void(Event, const AddToHomescreenParams&)>&
event_callback);
static void InstallWebApk(content::WebContents* web_contents,
const AddToHomescreenParams& params);
static void InstallShortcut(content::WebContents* web_contents,
const AddToHomescreenParams& params);
DISALLOW_IMPLICIT_CONSTRUCTORS(AddToHomescreenInstaller);
};
#endif // CHROME_BROWSER_ANDROID_WEBAPPS_ADD_TO_HOMESCREEN_INSTALLER_H_
......@@ -12,6 +12,7 @@
#include "chrome/android/chrome_jni_headers/AddToHomescreenManager_jni.h"
#include "chrome/browser/android/shortcut_helper.h"
#include "chrome/browser/android/webapk/webapk_install_service.h"
#include "chrome/browser/android/webapps/add_to_homescreen_installer.h"
#include "chrome/browser/banners/app_banner_manager_android.h"
#include "chrome/browser/banners/app_banner_settings_helper.h"
#include "chrome/browser/installable/installable_manager.h"
......@@ -65,29 +66,61 @@ void AddToHomescreenManager::AddToHomescreen(
if (!web_contents)
return;
RecordAddToHomescreen();
if (is_webapk_compatible_) {
WebApkInstallService::Get(web_contents->GetBrowserContext())
->InstallAsync(web_contents, data_fetcher_->shortcut_info(),
data_fetcher_->primary_icon(),
data_fetcher_->has_maskable_primary_icon(),
data_fetcher_->badge_icon(),
InstallableMetrics::GetInstallSource(
web_contents, InstallTrigger::MENU));
} else {
base::string16 user_title =
AddToHomescreenParams params;
params.app_type = data_fetcher_->shortcut_info().source ==
ShortcutInfo::SOURCE_ADD_TO_HOMESCREEN_PWA
? AddToHomescreenParams::AppType::WEBAPK
: AddToHomescreenParams::AppType::SHORTCUT;
params.shortcut_info =
std::make_unique<ShortcutInfo>(data_fetcher_->shortcut_info());
params.primary_icon = data_fetcher_->primary_icon();
params.badge_icon = data_fetcher_->badge_icon();
params.has_maskable_primary_icon = data_fetcher_->has_maskable_primary_icon();
params.install_source = InstallableMetrics::GetInstallSource(
data_fetcher_->web_contents(), InstallTrigger::MENU);
if (!is_webapk_compatible_) {
params.shortcut_info->user_title =
base::android::ConvertJavaStringToUTF16(env, j_user_title);
data_fetcher_->shortcut_info().user_title = user_title;
ShortcutHelper::AddToLauncherWithSkBitmap(
web_contents, data_fetcher_->shortcut_info(),
data_fetcher_->primary_icon(),
data_fetcher_->has_maskable_primary_icon());
}
// Fire the appinstalled event and do install time logging.
banners::AppBannerManagerAndroid* app_banner_manager =
banners::AppBannerManagerAndroid::FromWebContents(web_contents);
app_banner_manager->OnInstall(data_fetcher_->shortcut_info().display);
// base::Unretained() is safe because the lifetime of this object is
// controlled by its Java counterpart. It will be destroyed when the add to
// home screen prompt is dismissed, which occurs after the last time
// RecordEventForAppMenu can be called.
AddToHomescreenInstaller::Install(
data_fetcher_->web_contents(), params,
base::Bind(&AddToHomescreenManager::RecordEventForAppMenu,
base::Unretained(this)));
}
void AddToHomescreenManager::RecordEventForAppMenu(
AddToHomescreenInstaller::Event event,
const AddToHomescreenParams& a2hs_params) {
DCHECK_NE(a2hs_params.app_type, AddToHomescreenParams::AppType::NATIVE);
if (!data_fetcher_->web_contents())
return;
switch (event) {
case AddToHomescreenInstaller::Event::INSTALL_STARTED:
AppBannerSettingsHelper::RecordBannerEvent(
data_fetcher_->web_contents(),
data_fetcher_->web_contents()->GetURL(),
a2hs_params.shortcut_info->url.spec(),
AppBannerSettingsHelper::APP_BANNER_EVENT_DID_ADD_TO_HOMESCREEN,
base::Time::Now());
break;
case AddToHomescreenInstaller::Event::INSTALL_REQUEST_FINISHED: {
banners::AppBannerManagerAndroid* app_banner_manager =
banners::AppBannerManagerAndroid::FromWebContents(
data_fetcher_->web_contents());
// Fire the appinstalled event and do install time logging.
if (app_banner_manager)
app_banner_manager->OnInstall(a2hs_params.shortcut_info->display);
break;
}
default:
break;
}
}
void AddToHomescreenManager::Start(content::WebContents* web_contents) {
......@@ -103,20 +136,6 @@ void AddToHomescreenManager::Start(content::WebContents* web_contents) {
AddToHomescreenManager::~AddToHomescreenManager() {}
void AddToHomescreenManager::RecordAddToHomescreen() {
// Record that the shortcut has been added, so no banners will be shown
// for this app.
content::WebContents* web_contents = data_fetcher_->web_contents();
if (!web_contents)
return;
AppBannerSettingsHelper::RecordBannerEvent(
web_contents, web_contents->GetURL(),
data_fetcher_->shortcut_info().url.spec(),
AppBannerSettingsHelper::APP_BANNER_EVENT_DID_ADD_TO_HOMESCREEN,
base::Time::Now());
}
void AddToHomescreenManager::OnUserTitleAvailable(
const base::string16& user_title,
const GURL& url,
......
......@@ -11,6 +11,7 @@
#include "base/android/scoped_java_ref.h"
#include "base/macros.h"
#include "chrome/browser/android/webapps/add_to_homescreen_data_fetcher.h"
#include "chrome/browser/android/webapps/add_to_homescreen_installer.h"
namespace content {
class WebContents;
......@@ -18,6 +19,7 @@ class WebContents;
class SkBitmap;
struct ShortcutInfo;
struct AddToHomescreenParams;
// AddToHomescreenManager is the C++ counterpart of
// org.chromium.chrome.browser's AddToHomescreenManager in Java. This object
......@@ -44,7 +46,8 @@ class AddToHomescreenManager : public AddToHomescreenDataFetcher::Observer {
private:
~AddToHomescreenManager() override;
void RecordAddToHomescreen();
void RecordEventForAppMenu(AddToHomescreenInstaller::Event event,
const AddToHomescreenParams& a2hs_params);
// AddToHomescreenDataFetcher::Observer:
void OnUserTitleAvailable(const base::string16& user_title,
......
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/android/webapps/add_to_homescreen_params.h"
AddToHomescreenParams::AddToHomescreenParams() = default;
AddToHomescreenParams::~AddToHomescreenParams() = default;
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_ANDROID_WEBAPPS_ADD_TO_HOMESCREEN_PARAMS_H_
#define CHROME_BROWSER_ANDROID_WEBAPPS_ADD_TO_HOMESCREEN_PARAMS_H_
#include <memory>
#include <string>
#include "base/android/scoped_java_ref.h"
#include "chrome/browser/android/shortcut_info.h"
#include "chrome/browser/installable/installable_metrics.h"
#include "third_party/skia/include/core/SkBitmap.h"
struct AddToHomescreenParams {
// A Java counterpart will be generated for this enum.
// GENERATED_JAVA_ENUM_PACKAGE: (
// org.chromium.chrome.browser.webapps.addtohomescreen)
enum class AppType {
NATIVE,
WEBAPK,
SHORTCUT,
};
AppType app_type;
SkBitmap primary_icon;
SkBitmap badge_icon;
bool has_maskable_primary_icon = false;
std::unique_ptr<ShortcutInfo> shortcut_info;
WebappInstallSource install_source;
std::string native_app_package_name;
base::android::ScopedJavaGlobalRef<jobject> native_app_data;
AddToHomescreenParams();
~AddToHomescreenParams();
};
#endif // CHROME_BROWSER_ANDROID_WEBAPPS_ADD_TO_HOMESCREEN_PARAMS_H_
......@@ -15,7 +15,10 @@
#include "chrome/browser/android/tab_android.h"
#include "chrome/browser/android/tab_web_contents_delegate_android.h"
#include "chrome/browser/android/webapk/chrome_webapk_host.h"
#include "chrome/browser/android/webapk/webapk_metrics.h"
#include "chrome/browser/android/webapk/webapk_web_manifest_checker.h"
#include "chrome/browser/android/webapps/add_to_homescreen_installer.h"
#include "chrome/browser/android/webapps/add_to_homescreen_params.h"
#include "chrome/browser/banners/app_banner_metrics.h"
#include "chrome/browser/banners/app_banner_settings_helper.h"
#include "chrome/browser/banners/app_banner_ui_delegate_android.h"
......@@ -210,20 +213,28 @@ void AppBannerManagerAndroid::ShowBannerUi(WebappInstallSource install_source) {
content::WebContents* contents = web_contents();
DCHECK(contents);
auto a2hs_params = std::make_unique<AddToHomescreenParams>();
a2hs_params->primary_icon = primary_icon_;
if (native_app_data_.is_null()) {
ui_delegate_ = AppBannerUiDelegateAndroid::Create(
weak_factory_.GetWeakPtr(),
ShortcutHelper::CreateShortcutInfo(manifest_url_, manifest_,
primary_icon_url_, badge_icon_url_),
primary_icon_, badge_icon_, install_source, can_install_webapk_,
has_maskable_primary_icon_);
a2hs_params->app_type = can_install_webapk_
? AddToHomescreenParams::AppType::WEBAPK
: AddToHomescreenParams::AppType::SHORTCUT;
a2hs_params->shortcut_info = ShortcutHelper::CreateShortcutInfo(
manifest_url_, manifest_, primary_icon_url_, badge_icon_url_);
a2hs_params->install_source = install_source;
a2hs_params->badge_icon = badge_icon_;
a2hs_params->has_maskable_primary_icon = has_maskable_primary_icon_;
} else {
ui_delegate_ = AppBannerUiDelegateAndroid::Create(
weak_factory_.GetWeakPtr(), native_app_title_,
base::android::ScopedJavaLocalRef<jobject>(native_app_data_),
primary_icon_, native_app_package_);
a2hs_params->app_type = AddToHomescreenParams::AppType::NATIVE;
a2hs_params->native_app_data = native_app_data_;
a2hs_params->native_app_package_name = native_app_package_;
}
ui_delegate_ = AppBannerUiDelegateAndroid::Create(
weak_factory_.GetWeakPtr(), std::move(a2hs_params),
base::Bind(&AppBannerManagerAndroid::RecordEventForAppBanner,
weak_factory_.GetWeakPtr()));
// If we are installing from the ambient badge, it will remove itself.
if (install_source != WebappInstallSource::AMBIENT_BADGE_CUSTOM_TAB &&
install_source != WebappInstallSource::AMBIENT_BADGE_BROWSER_TAB) {
......@@ -232,12 +243,8 @@ void AppBannerManagerAndroid::ShowBannerUi(WebappInstallSource install_source) {
if (ui_delegate_->ShowDialog()) {
if (native_app_data_.is_null()) {
RecordDidShowBanner("AppBanner.WebApp.Shown");
TrackDisplayEvent(DISPLAY_EVENT_WEB_APP_BANNER_CREATED);
ReportStatus(SHOWING_WEB_APP_BANNER);
} else {
RecordDidShowBanner("AppBanner.NativeApp.Shown");
TrackDisplayEvent(DISPLAY_EVENT_NATIVE_APP_BANNER_CREATED);
ReportStatus(SHOWING_NATIVE_APP_BANNER);
}
} else {
......@@ -245,6 +252,88 @@ void AppBannerManagerAndroid::ShowBannerUi(WebappInstallSource install_source) {
}
}
void AppBannerManagerAndroid::RecordEventForAppBanner(
AddToHomescreenInstaller::Event event,
const AddToHomescreenParams& a2hs_params) {
switch (event) {
case AddToHomescreenInstaller::Event::INSTALL_STARTED:
TrackDismissEvent(DISMISS_EVENT_DISMISSED);
switch (a2hs_params.app_type) {
case AddToHomescreenParams::AppType::NATIVE:
TrackUserResponse(USER_RESPONSE_NATIVE_APP_ACCEPTED);
break;
case AddToHomescreenParams::AppType::WEBAPK:
FALLTHROUGH;
case AddToHomescreenParams::AppType::SHORTCUT:
TrackUserResponse(USER_RESPONSE_WEB_APP_ACCEPTED);
AppBannerSettingsHelper::RecordBannerInstallEvent(
web_contents(), a2hs_params.shortcut_info->url.spec(),
AppBannerSettingsHelper::WEB);
break;
default:
NOTREACHED();
}
break;
case AddToHomescreenInstaller::Event::INSTALL_FAILED:
TrackDismissEvent(DISMISS_EVENT_ERROR);
break;
case AddToHomescreenInstaller::Event::NATIVE_INSTALL_OR_OPEN_FAILED:
DCHECK_EQ(a2hs_params.app_type, AddToHomescreenParams::AppType::NATIVE);
TrackInstallEvent(INSTALL_EVENT_NATIVE_APP_INSTALL_TRIGGERED);
break;
case AddToHomescreenInstaller::Event::NATIVE_INSTALL_OR_OPEN_SUCCEEDED:
DCHECK_EQ(a2hs_params.app_type, AddToHomescreenParams::AppType::NATIVE);
TrackDismissEvent(DISMISS_EVENT_APP_OPEN);
break;
case AddToHomescreenInstaller::Event::INSTALL_REQUEST_FINISHED:
SendBannerAccepted();
if (a2hs_params.app_type == AddToHomescreenParams::AppType::WEBAPK ||
a2hs_params.app_type == AddToHomescreenParams::AppType::SHORTCUT) {
OnInstall(a2hs_params.shortcut_info->display);
}
break;
case AddToHomescreenInstaller::Event::NATIVE_DETAILS_SHOWN:
TrackDismissEvent(DISMISS_EVENT_BANNER_CLICK);
break;
case AddToHomescreenInstaller::Event::UI_SHOWN:
if (a2hs_params.app_type == AddToHomescreenParams::AppType::NATIVE) {
RecordDidShowBanner("AppBanner.NativeApp.Shown");
TrackDisplayEvent(DISPLAY_EVENT_NATIVE_APP_BANNER_CREATED);
} else {
RecordDidShowBanner("AppBanner.WebApp.Shown");
TrackDisplayEvent(DISPLAY_EVENT_WEB_APP_BANNER_CREATED);
}
break;
case AddToHomescreenInstaller::Event::UI_DISMISSED:
TrackDismissEvent(DISMISS_EVENT_DISMISSED);
SendBannerDismissed();
if (a2hs_params.app_type == AddToHomescreenParams::AppType::NATIVE) {
DCHECK(!a2hs_params.native_app_package_name.empty());
TrackUserResponse(USER_RESPONSE_NATIVE_APP_DISMISSED);
AppBannerSettingsHelper::RecordBannerDismissEvent(
web_contents(), a2hs_params.native_app_package_name,
AppBannerSettingsHelper::NATIVE);
} else {
if (a2hs_params.app_type == AddToHomescreenParams::AppType::WEBAPK)
webapk::TrackInstallEvent(
webapk::ADD_TO_HOMESCREEN_DIALOG_DISMISSED_BEFORE_INSTALLATION);
TrackUserResponse(USER_RESPONSE_WEB_APP_DISMISSED);
AppBannerSettingsHelper::RecordBannerDismissEvent(
web_contents(), a2hs_params.shortcut_info->url.spec(),
AppBannerSettingsHelper::WEB);
}
break;
}
}
void AppBannerManagerAndroid::CreateJavaBannerManager(
content::WebContents* web_contents) {
JNIEnv* env = base::android::AttachCurrentThread();
......@@ -266,8 +355,8 @@ bool AppBannerManagerAndroid::ShouldPerformInstallableNativeAppCheck() {
if (!manifest_.prefer_related_applications || java_banner_manager_.is_null())
return false;
// Ensure there is at least one related app specified that is supported on the
// current platform.
// Ensure there is at least one related app specified that is supported on
// the current platform.
for (const auto& application : manifest_.related_applications) {
if (base::EqualsASCII(application.platform.string(), kPlatformPlay))
return true;
......@@ -305,8 +394,8 @@ InstallableStatusCode AppBannerManagerAndroid::QueryNativeApp(
if (id_from_app_url.size() && id != id_from_app_url)
return IDS_DO_NOT_MATCH;
// Attach the chrome_inline referrer value, prefixed with "&" if the referrer
// is non empty.
// Attach the chrome_inline referrer value, prefixed with "&" if the
// referrer is non empty.
std::string referrer = ExtractQueryValueForName(url, "referrer");
if (!referrer.empty())
referrer += "&";
......
......@@ -12,12 +12,15 @@
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/strings/string16.h"
#include "chrome/browser/android/webapps/add_to_homescreen_installer.h"
#include "chrome/browser/banners/app_banner_manager.h"
#include "chrome/browser/installable/installable_ambient_badge_infobar_delegate.h"
#include "content/public/browser/web_contents_user_data.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "url/gurl.h"
struct AddToHomescreenParams;
namespace banners {
class AppBannerUiDelegateAndroid;
......@@ -128,6 +131,10 @@ class AppBannerManagerAndroid
// Hides the ambient badge if it is showing.
void HideAmbientBadge();
// Called for recording metrics.
void RecordEventForAppBanner(AddToHomescreenInstaller::Event event,
const AddToHomescreenParams& a2hs_params);
std::unique_ptr<AppBannerUiDelegateAndroid> ui_delegate_;
// The URL of the badge icon.
......
......@@ -9,18 +9,10 @@
#include <string>
#include "base/android/scoped_java_ref.h"
#include "base/callback.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/strings/string16.h"
#include "chrome/browser/installable/installable_metrics.h"
#include "components/infobars/core/confirm_infobar_delegate.h"
#include "third_party/skia/include/core/SkBitmap.h"
namespace content {
class WebContents;
}
struct ShortcutInfo;
#include "chrome/browser/android/webapps/add_to_homescreen_installer.h"
#include "chrome/browser/android/webapps/add_to_homescreen_params.h"
namespace banners {
......@@ -30,50 +22,21 @@ class AppBannerManager;
// native app.
class AppBannerUiDelegateAndroid {
public:
// Describes the type of app for which this class holds data.
enum class AppType {
NATIVE,
WEBAPK,
LEGACY_WEBAPP,
};
// Creates a delegate for promoting the installation of a web app.
static std::unique_ptr<AppBannerUiDelegateAndroid> Create(
base::WeakPtr<AppBannerManager> weak_manager,
std::unique_ptr<ShortcutInfo> info,
const SkBitmap& primary_icon,
const SkBitmap& badge_icon,
WebappInstallSource install_source,
bool is_webapk,
bool has_primary_maskable_icon);
// Creates a delegate for promoting the installation of an Android app.
static std::unique_ptr<AppBannerUiDelegateAndroid> Create(
base::WeakPtr<AppBannerManager> weak_manager,
const base::string16& app_title,
const base::android::ScopedJavaLocalRef<jobject>& native_app_data,
const SkBitmap& icon,
const std::string& native_app_package_name);
std::unique_ptr<AddToHomescreenParams> params,
base::RepeatingCallback<void(AddToHomescreenInstaller::Event,
const AddToHomescreenParams&)>
event_callback);
~AppBannerUiDelegateAndroid();
const base::string16& GetAppTitle() const;
base::android::ScopedJavaLocalRef<jobject> GetJavaObject();
const base::android::ScopedJavaLocalRef<jobject> GetNativeAppData() const;
const SkBitmap& GetPrimaryIcon() const;
AppType GetType() const;
const GURL& GetWebAppUrl() const;
// Called through the JNI to add the app described by this class to home
// screen.
void AddToHomescreen(JNIEnv* env,
const base::android::JavaParamRef<jobject>& obj);
// Installs the app referenced by the data in this object. Returns |true| if
// the installation UI should be dismissed.
bool InstallApp(content::WebContents* web_contents);
// Called through the JNI to indicate that the user has dismissed the
// installation UI.
void OnUiCancelled(JNIEnv* env,
......@@ -94,53 +57,25 @@ class AppBannerUiDelegateAndroid {
const base::android::JavaParamRef<jobject>& obj);
private:
// Delegate for promoting a web app.
AppBannerUiDelegateAndroid(base::WeakPtr<AppBannerManager> weak_manager,
std::unique_ptr<ShortcutInfo> info,
const SkBitmap& primary_icon,
const SkBitmap& badge_icon,
WebappInstallSource install_source,
bool is_webapk,
bool has_primary_maskable_icon);
// Delegate for promoting an Android app.
// Delegate for promoting a web or Android app.
AppBannerUiDelegateAndroid(
base::WeakPtr<AppBannerManager> weak_manager,
const base::string16& app_title,
const base::android::ScopedJavaLocalRef<jobject>& native_app_data,
const SkBitmap& icon,
const std::string& native_app_package_name);
bool IsForNativeApp() const { return GetType() == AppType::NATIVE; }
std::unique_ptr<AddToHomescreenParams> params,
base::RepeatingCallback<void(AddToHomescreenInstaller::Event,
const AddToHomescreenParams&)>
event_callback);
void CreateJavaDelegate();
bool InstallOrOpenNativeApp();
void InstallWebApk(content::WebContents* web_contents);
void InstallLegacyWebApp(content::WebContents* web_contents);
// Called when the user accepts the banner to install the app. (Not called
// when the "Open" button is pressed on the banner that is shown after
// installation for WebAPK banners.)
void SendBannerAccepted();
base::android::ScopedJavaGlobalRef<jobject> java_delegate_;
base::WeakPtr<AppBannerManager> weak_manager_;
base::string16 app_title_;
std::unique_ptr<ShortcutInfo> shortcut_info_;
base::android::ScopedJavaGlobalRef<jobject> native_app_data_;
const SkBitmap primary_icon_;
const SkBitmap badge_icon_;
bool has_primary_maskable_icon_;
std::string package_name_;
AppType type_;
WebappInstallSource install_source_;
std::unique_ptr<AddToHomescreenParams> params_;
const base::RepeatingCallback<void(AddToHomescreenInstaller::Event,
const AddToHomescreenParams&)>
event_callback_;
DISALLOW_COPY_AND_ASSIGN(AppBannerUiDelegateAndroid);
};
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment