Chromium Code Reviews| 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 5c8c44d9a4f8be2aee9ec6888bad5ccda83fd5ce..58951ab69b9a11218dd5351a15ff4a68335f18d1 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; |
| DEFINE_WEB_CONTENTS_USER_DATA_KEY(banners::AppBannerManagerAndroid); |
| @@ -44,15 +52,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( |
| @@ -62,16 +88,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, |
| @@ -83,22 +108,103 @@ 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::ContinueInstallableCheck() { |
| + // 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::ContinueInstallableCheck(); |
| +} |
| + |
| +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(); |
| } |
| -bool AppBannerManagerAndroid::HandleNonWebApp(const std::string& platform, |
| +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); |
| + } |
| + } |
|
gone
2016/08/03 19:33:08
Shouldn't this check if the infobar is null before
dominickn
2016/08/04 02:51:07
Done.
|
| + InfoBarService::FromWebContents(contents)->AddInfoBar( |
| + base::WrapUnique(infobar)); |
| +} |
| + |
| +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); |
| @@ -110,13 +216,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. |
| @@ -126,15 +230,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; |
| } |
| @@ -144,32 +245,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; |
| @@ -228,7 +311,7 @@ void SetEngagementWeights(JNIEnv* env, |
| void SetTimeDeltaForTesting(JNIEnv* env, |
| const JavaParamRef<jclass>& clazz, |
| jint days) { |
| - AppBannerDataFetcher::SetTimeDeltaForTesting(days); |
| + AppBannerManager::SetTimeDeltaForTesting(days); |
| } |
| } // namespace banners |