| Index: chrome/browser/android/banners/app_banner_manager_android.cc
|
| diff --git a/chrome/browser/android/banners/app_banner_manager_android.cc b/chrome/browser/android/banners/app_banner_manager_android.cc
|
| index 7a4617411d494d20464bc6e91d874c73baf29b90..a0456b2d6bd4bc4bac4ef582710e1c24332d843e 100644
|
| --- a/chrome/browser/android/banners/app_banner_manager_android.cc
|
| +++ b/chrome/browser/android/banners/app_banner_manager_android.cc
|
| @@ -2,22 +2,30 @@
|
| // Use of this source code is governed by a BSD-style license that can be
|
| // found in the LICENSE file.
|
|
|
| +#include <utility>
|
| +
|
| #include "chrome/browser/android/banners/app_banner_manager_android.h"
|
|
|
| #include "base/android/jni_android.h"
|
| #include "base/android/jni_string.h"
|
| -#include "chrome/browser/android/banners/app_banner_data_fetcher_android.h"
|
| +#include "base/memory/ptr_util.h"
|
| +#include "base/strings/utf_string_conversions.h"
|
| +#include "chrome/browser/android/banners/app_banner_infobar_delegate_android.h"
|
| #include "chrome/browser/android/shortcut_helper.h"
|
| #include "chrome/browser/banners/app_banner_metrics.h"
|
| +#include "chrome/browser/infobars/infobar_service.h"
|
| +#include "chrome/browser/manifest/manifest_icon_downloader.h"
|
| +#include "chrome/browser/manifest/manifest_icon_selector.h"
|
| +#include "chrome/browser/ui/android/infobars/app_banner_infobar_android.h"
|
| #include "chrome/common/chrome_constants.h"
|
| #include "content/public/browser/web_contents.h"
|
| #include "content/public/common/frame_navigate_params.h"
|
| #include "jni/AppBannerManager_jni.h"
|
| +#include "third_party/skia/include/core/SkBitmap.h"
|
|
|
| using base::android::ConvertJavaStringToUTF8;
|
| using base::android::ConvertJavaStringToUTF16;
|
| using base::android::ConvertUTF8ToJavaString;
|
| -using base::android::ConvertUTF16ToJavaString;
|
| using base::android::JavaParamRef;
|
| using base::android::ScopedJavaLocalRef;
|
|
|
| @@ -46,15 +54,33 @@ AppBannerManagerAndroid::~AppBannerManagerAndroid() {
|
| java_banner_manager_.Reset();
|
| }
|
|
|
| +base::Closure AppBannerManagerAndroid::FetchWebappSplashScreenImageCallback(
|
| + const std::string& webapp_id) {
|
| + content::WebContents* contents = web_contents();
|
| + DCHECK(contents);
|
| +
|
| + int ideal_splash_image_size_in_dp =
|
| + ShortcutHelper::GetIdealSplashImageSizeInDp();
|
| + int minimum_splash_image_size_in_dp =
|
| + ShortcutHelper::GetMinimumSplashImageSizeInDp();
|
| + GURL image_url = ManifestIconSelector::FindBestMatchingIcon(
|
| + manifest_.icons, ideal_splash_image_size_in_dp,
|
| + minimum_splash_image_size_in_dp);
|
| +
|
| + return base::Bind(&ShortcutHelper::FetchSplashScreenImage, contents,
|
| + image_url, ideal_splash_image_size_in_dp,
|
| + minimum_splash_image_size_in_dp, webapp_id);
|
| +}
|
| +
|
| const base::android::ScopedJavaGlobalRef<jobject>&
|
| AppBannerManagerAndroid::GetJavaBannerManager() const {
|
| return java_banner_manager_;
|
| }
|
|
|
| -bool AppBannerManagerAndroid::IsFetcherActive(
|
| +bool AppBannerManagerAndroid::IsActiveForTesting(
|
| JNIEnv* env,
|
| const JavaParamRef<jobject>& obj) {
|
| - return AppBannerManager::IsFetcherActive();
|
| + return is_active();
|
| }
|
|
|
| bool AppBannerManagerAndroid::OnAppDetailsRetrieved(
|
| @@ -64,16 +90,15 @@ bool AppBannerManagerAndroid::OnAppDetailsRetrieved(
|
| const JavaParamRef<jstring>& japp_title,
|
| const JavaParamRef<jstring>& japp_package,
|
| const JavaParamRef<jstring>& jicon_url) {
|
| - AppBannerDataFetcherAndroid* android_fetcher =
|
| - static_cast<AppBannerDataFetcherAndroid*>(data_fetcher().get());
|
| - if (!CheckFetcherMatchesContents(android_fetcher->is_debug_mode()))
|
| - return false;
|
| -
|
| - GURL image_url = GURL(ConvertJavaStringToUTF8(env, jicon_url));
|
| -
|
| - return android_fetcher->ContinueFetching(
|
| - ConvertJavaStringToUTF16(env, japp_title),
|
| - ConvertJavaStringToUTF8(env, japp_package), japp_data, image_url);
|
| + native_app_data_.Reset(japp_data);
|
| + app_title_ = ConvertJavaStringToUTF16(env, japp_title);
|
| + native_app_package_ = ConvertJavaStringToUTF8(env, japp_package);
|
| + icon_url_ = GURL(ConvertJavaStringToUTF8(env, jicon_url));
|
| +
|
| + return ManifestIconDownloader::Download(
|
| + web_contents(), icon_url_, GetIdealIconSizeInDp(),
|
| + GetMinimumIconSizeInDp(),
|
| + base::Bind(&AppBannerManager::OnAppIconFetched, GetWeakPtr()));
|
| }
|
|
|
| void AppBannerManagerAndroid::RequestAppBanner(const GURL& validated_url,
|
| @@ -85,22 +110,106 @@ void AppBannerManagerAndroid::RequestAppBanner(const GURL& validated_url,
|
| AppBannerManager::RequestAppBanner(validated_url, is_debug_mode);
|
| }
|
|
|
| -AppBannerDataFetcher* AppBannerManagerAndroid::CreateAppBannerDataFetcher(
|
| - base::WeakPtr<Delegate> weak_delegate,
|
| - bool is_debug_mode) {
|
| - return new AppBannerDataFetcherAndroid(
|
| - web_contents(), weak_delegate,
|
| - ShortcutHelper::GetIdealHomescreenIconSizeInDp(),
|
| - ShortcutHelper::GetMinimumHomescreenIconSizeInDp(),
|
| - ShortcutHelper::GetIdealSplashImageSizeInDp(),
|
| - ShortcutHelper::GetMinimumSplashImageSizeInDp(), is_debug_mode);
|
| +std::string AppBannerManagerAndroid::GetAppIdentifier() {
|
| + return native_app_data_.is_null() ? AppBannerManager::GetAppIdentifier()
|
| + : native_app_package_;
|
| +}
|
| +
|
| +std::string AppBannerManagerAndroid::GetBannerType() {
|
| + return native_app_data_.is_null() ? AppBannerManager::GetBannerType()
|
| + : "android";
|
| +}
|
| +
|
| +int AppBannerManagerAndroid::GetIdealIconSizeInDp() {
|
| + return ShortcutHelper::GetIdealHomescreenIconSizeInDp();
|
| +}
|
| +
|
| +int AppBannerManagerAndroid::GetMinimumIconSizeInDp() {
|
| + return ShortcutHelper::GetMinimumHomescreenIconSizeInDp();
|
| +}
|
| +
|
| +bool AppBannerManagerAndroid::IsWebAppInstalled(
|
| + content::BrowserContext* browser_context,
|
| + const GURL& start_url) {
|
| + // Returns true if a WebAPK is installed. Does not check whether a non-WebAPK
|
| + // web app is installed: this is detected by the content settings check in
|
| + // AppBannerSettingsHelper::ShouldShowBanner (due to the lack of an API to
|
| + // detect what is and isn't on the Android homescreen).
|
| + // This method will still detect the presence of a WebAPK even if Chrome's
|
| + // data is cleared.
|
| + return ShortcutHelper::IsWebApkInstalled(start_url);
|
| +}
|
| +
|
| +void AppBannerManagerAndroid::PerformInstallableCheck() {
|
| + // Check if the manifest prefers that we show a native app banner. If so, call
|
| + // to Java to verify the details.
|
| + if (manifest_.prefer_related_applications &&
|
| + manifest_.related_applications.size()) {
|
| + for (const auto& application : manifest_.related_applications) {
|
| + std::string platform = base::UTF16ToUTF8(application.platform.string());
|
| + std::string id = base::UTF16ToUTF8(application.id.string());
|
| + if (CanHandleNonWebApp(platform, application.url, id))
|
| + return;
|
| + }
|
| + }
|
| +
|
| + // No native app banner was requested. Continue checking for a web app banner.
|
| + AppBannerManager::PerformInstallableCheck();
|
| +}
|
| +
|
| +void AppBannerManagerAndroid::OnAppIconFetched(const SkBitmap& bitmap) {
|
| + if (bitmap.drawsNothing()) {
|
| + ReportError(web_contents(), NO_ICON_AVAILABLE);
|
| + Stop();
|
| + }
|
| +
|
| + if (!is_active())
|
| + return;
|
| +
|
| + icon_.reset(new SkBitmap(bitmap));
|
| + SendBannerPromptRequest();
|
| +}
|
| +
|
| +void AppBannerManagerAndroid::ShowBanner() {
|
| + content::WebContents* contents = web_contents();
|
| + DCHECK(contents);
|
| +
|
| + infobars::InfoBar* infobar = nullptr;
|
| + if (native_app_data_.is_null()) {
|
| + std::unique_ptr<AppBannerInfoBarDelegateAndroid> delegate(
|
| + new AppBannerInfoBarDelegateAndroid(
|
| + GetWeakPtr(), app_title_, manifest_url_, manifest_, icon_url_,
|
| + std::move(icon_), event_request_id()));
|
| +
|
| + infobar = new AppBannerInfoBarAndroid(std::move(delegate),
|
| + manifest_.start_url);
|
| + if (infobar) {
|
| + RecordDidShowBanner("AppBanner.WebApp.Shown");
|
| + TrackDisplayEvent(DISPLAY_EVENT_WEB_APP_BANNER_CREATED);
|
| + }
|
| + } else {
|
| + std::unique_ptr<AppBannerInfoBarDelegateAndroid> delegate(
|
| + new AppBannerInfoBarDelegateAndroid(
|
| + app_title_, native_app_data_, std::move(icon_), native_app_package_,
|
| + referrer_, event_request_id()));
|
| + infobar =
|
| + new AppBannerInfoBarAndroid(std::move(delegate), native_app_data_);
|
| + if (infobar) {
|
| + RecordDidShowBanner("AppBanner.NativeApp.Shown");
|
| + TrackDisplayEvent(DISPLAY_EVENT_NATIVE_APP_BANNER_CREATED);
|
| + }
|
| + }
|
| +
|
| + if (infobar) {
|
| + InfoBarService::FromWebContents(contents)->AddInfoBar(
|
| + base::WrapUnique(infobar));
|
| + }
|
| }
|
|
|
| -bool AppBannerManagerAndroid::HandleNonWebApp(const std::string& platform,
|
| +bool AppBannerManagerAndroid::CanHandleNonWebApp(const std::string& platform,
|
| const GURL& url,
|
| - const std::string& id,
|
| - bool is_debug_mode) {
|
| - if (!CheckPlatformAndId(platform, id, is_debug_mode))
|
| + const std::string& id) {
|
| + if (!CheckPlatformAndId(platform, id))
|
| return false;
|
|
|
| banners::TrackDisplayEvent(DISPLAY_EVENT_NATIVE_APP_BANNER_REQUESTED);
|
| @@ -112,13 +221,11 @@ bool AppBannerManagerAndroid::HandleNonWebApp(const std::string& platform,
|
|
|
| std::string id_from_app_url = ExtractQueryValueForName(url, kIdName);
|
| if (id_from_app_url.size() && id != id_from_app_url) {
|
| - banners::OutputDeveloperNotShownMessage(
|
| - web_contents(), banners::kIgnoredIdsDoNotMatch, is_debug_mode);
|
| + ReportError(web_contents(), IDS_DO_NOT_MATCH);
|
| return false;
|
| }
|
|
|
| - std::string referrer =
|
| - ExtractQueryValueForName(url, kReferrerName);
|
| + std::string referrer = ExtractQueryValueForName(url, kReferrerName);
|
|
|
| // Attach the chrome_inline referrer value, prefixed with "&" if the referrer
|
| // is non empty.
|
| @@ -128,15 +235,12 @@ bool AppBannerManagerAndroid::HandleNonWebApp(const std::string& platform,
|
| referrer.append("&").append(kPlayInlineReferrer);
|
|
|
| ScopedJavaLocalRef<jstring> jurl(
|
| - ConvertUTF8ToJavaString(env, data_fetcher()->validated_url().spec()));
|
| - ScopedJavaLocalRef<jstring> jpackage(
|
| - ConvertUTF8ToJavaString(env, id));
|
| - ScopedJavaLocalRef<jstring> jreferrer(
|
| - ConvertUTF8ToJavaString(env, referrer));
|
| + ConvertUTF8ToJavaString(env, validated_url_.spec()));
|
| + ScopedJavaLocalRef<jstring> jpackage(ConvertUTF8ToJavaString(env, id));
|
| + ScopedJavaLocalRef<jstring> jreferrer(ConvertUTF8ToJavaString(env, referrer));
|
| Java_AppBannerManager_fetchAppDetails(
|
| - env, java_banner_manager_.obj(), jurl.obj(),
|
| - jpackage.obj(), jreferrer.obj(),
|
| - ShortcutHelper::GetIdealHomescreenIconSizeInDp());
|
| + env, java_banner_manager_.obj(), jurl.obj(), jpackage.obj(),
|
| + jreferrer.obj(), GetIdealIconSizeInDp());
|
| return true;
|
| }
|
|
|
| @@ -146,32 +250,14 @@ void AppBannerManagerAndroid::CreateJavaBannerManager() {
|
| Java_AppBannerManager_create(env, reinterpret_cast<intptr_t>(this)));
|
| }
|
|
|
| -bool AppBannerManagerAndroid::CheckFetcherMatchesContents(bool is_debug_mode) {
|
| - if (!web_contents())
|
| - return false;
|
| -
|
| - if (!data_fetcher() ||
|
| - data_fetcher()->validated_url() != web_contents()->GetURL()) {
|
| - banners::OutputDeveloperNotShownMessage(
|
| - web_contents(), banners::kUserNavigatedBeforeBannerShown,
|
| - is_debug_mode);
|
| - return false;
|
| - }
|
| - return true;
|
| -}
|
| -
|
| bool AppBannerManagerAndroid::CheckPlatformAndId(const std::string& platform,
|
| - const std::string& id,
|
| - bool is_debug_mode) {
|
| + const std::string& id) {
|
| if (platform != kPlayPlatform) {
|
| - banners::OutputDeveloperNotShownMessage(
|
| - web_contents(), banners::kIgnoredNotSupportedOnAndroid, platform,
|
| - is_debug_mode);
|
| + ReportError(web_contents(), PLATFORM_NOT_SUPPORTED_ON_ANDROID);
|
| return false;
|
| }
|
| if (id.empty()) {
|
| - banners::OutputDeveloperNotShownMessage(
|
| - web_contents(), banners::kIgnoredNoId, is_debug_mode);
|
| + ReportError(web_contents(), NO_ID_SPECIFIED);
|
| return false;
|
| }
|
| return true;
|
| @@ -230,7 +316,7 @@ void SetEngagementWeights(JNIEnv* env,
|
| void SetTimeDeltaForTesting(JNIEnv* env,
|
| const JavaParamRef<jclass>& clazz,
|
| jint days) {
|
| - AppBannerDataFetcher::SetTimeDeltaForTesting(days);
|
| + AppBannerManager::SetTimeDeltaForTesting(days);
|
| }
|
|
|
| } // namespace banners
|
|
|