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

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

Issue 2156113002: Replace AppBannerDataFetcher with InstallableManager. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@banner-refactor
Patch Set: Rebase Created 4 years, 5 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 <utility>
6
5 #include "chrome/browser/android/banners/app_banner_manager_android.h" 7 #include "chrome/browser/android/banners/app_banner_manager_android.h"
6 8
7 #include "base/android/jni_android.h" 9 #include "base/android/jni_android.h"
8 #include "base/android/jni_string.h" 10 #include "base/android/jni_string.h"
9 #include "chrome/browser/android/banners/app_banner_data_fetcher_android.h" 11 #include "base/memory/ptr_util.h"
12 #include "base/strings/utf_string_conversions.h"
13 #include "chrome/browser/android/banners/app_banner_infobar_delegate_android.h"
10 #include "chrome/browser/android/shortcut_helper.h" 14 #include "chrome/browser/android/shortcut_helper.h"
11 #include "chrome/browser/banners/app_banner_metrics.h" 15 #include "chrome/browser/banners/app_banner_metrics.h"
16 #include "chrome/browser/infobars/infobar_service.h"
17 #include "chrome/browser/manifest/manifest_icon_downloader.h"
18 #include "chrome/browser/manifest/manifest_icon_selector.h"
19 #include "chrome/browser/ui/android/infobars/app_banner_infobar_android.h"
12 #include "chrome/common/chrome_constants.h" 20 #include "chrome/common/chrome_constants.h"
13 #include "content/public/browser/web_contents.h" 21 #include "content/public/browser/web_contents.h"
14 #include "content/public/common/frame_navigate_params.h" 22 #include "content/public/common/frame_navigate_params.h"
15 #include "jni/AppBannerManager_jni.h" 23 #include "jni/AppBannerManager_jni.h"
24 #include "third_party/skia/include/core/SkBitmap.h"
16 25
17 using base::android::ConvertJavaStringToUTF8; 26 using base::android::ConvertJavaStringToUTF8;
18 using base::android::ConvertJavaStringToUTF16; 27 using base::android::ConvertJavaStringToUTF16;
19 using base::android::ConvertUTF8ToJavaString; 28 using base::android::ConvertUTF8ToJavaString;
20 using base::android::ConvertUTF16ToJavaString;
21 29
22 DEFINE_WEB_CONTENTS_USER_DATA_KEY(banners::AppBannerManagerAndroid); 30 DEFINE_WEB_CONTENTS_USER_DATA_KEY(banners::AppBannerManagerAndroid);
23 31
24 namespace { 32 namespace {
25 33
26 const char kPlayPlatform[] = "play"; 34 const char kPlayPlatform[] = "play";
27 const char kReferrerName[] = "referrer"; 35 const char kReferrerName[] = "referrer";
28 const char kIdName[] = "id"; 36 const char kIdName[] = "id";
29 const char kPlayInlineReferrer[] = "playinline=chrome_inline"; 37 const char kPlayInlineReferrer[] = "playinline=chrome_inline";
30 38
31 } // anonymous namespace 39 } // anonymous namespace
32 40
33 namespace banners { 41 namespace banners {
34 42
35 AppBannerManagerAndroid::AppBannerManagerAndroid( 43 AppBannerManagerAndroid::AppBannerManagerAndroid(
36 content::WebContents* web_contents) 44 content::WebContents* web_contents)
37 : AppBannerManager(web_contents) { 45 : AppBannerManager(web_contents) {
38 CreateJavaBannerManager(); 46 CreateJavaBannerManager();
39 } 47 }
40 48
41 AppBannerManagerAndroid::~AppBannerManagerAndroid() { 49 AppBannerManagerAndroid::~AppBannerManagerAndroid() {
42 JNIEnv* env = base::android::AttachCurrentThread(); 50 JNIEnv* env = base::android::AttachCurrentThread();
43 Java_AppBannerManager_destroy(env, java_banner_manager_.obj()); 51 Java_AppBannerManager_destroy(env, java_banner_manager_.obj());
44 java_banner_manager_.Reset(); 52 java_banner_manager_.Reset();
45 } 53 }
46 54
55 base::Closure AppBannerManagerAndroid::FetchWebappSplashScreenImageCallback(
56 const std::string& webapp_id) {
57 content::WebContents* contents = web_contents();
58 DCHECK(contents);
59
60 int ideal_splash_image_size_in_dp =
61 ShortcutHelper::GetIdealSplashImageSizeInDp();
62 int minimum_splash_image_size_in_dp =
63 ShortcutHelper::GetMinimumSplashImageSizeInDp();
64 GURL image_url = ManifestIconSelector::FindBestMatchingIcon(
65 manifest_.icons, ideal_splash_image_size_in_dp,
66 minimum_splash_image_size_in_dp);
67
68 return base::Bind(&ShortcutHelper::FetchSplashScreenImage, contents,
69 image_url, ideal_splash_image_size_in_dp,
70 minimum_splash_image_size_in_dp, webapp_id);
71 }
72
47 const base::android::ScopedJavaGlobalRef<jobject>& 73 const base::android::ScopedJavaGlobalRef<jobject>&
48 AppBannerManagerAndroid::GetJavaBannerManager() const { 74 AppBannerManagerAndroid::GetJavaBannerManager() const {
49 return java_banner_manager_; 75 return java_banner_manager_;
50 } 76 }
51 77
52 bool AppBannerManagerAndroid::IsFetcherActive( 78 bool AppBannerManagerAndroid::IsActiveForTesting(
53 JNIEnv* env, 79 JNIEnv* env,
54 const JavaParamRef<jobject>& obj) { 80 const JavaParamRef<jobject>& obj) {
55 return AppBannerManager::IsFetcherActive(); 81 return is_active();
56 } 82 }
57 83
58 bool AppBannerManagerAndroid::OnAppDetailsRetrieved( 84 bool AppBannerManagerAndroid::OnAppDetailsRetrieved(
59 JNIEnv* env, 85 JNIEnv* env,
60 const JavaParamRef<jobject>& obj, 86 const JavaParamRef<jobject>& obj,
61 const JavaParamRef<jobject>& japp_data, 87 const JavaParamRef<jobject>& japp_data,
62 const JavaParamRef<jstring>& japp_title, 88 const JavaParamRef<jstring>& japp_title,
63 const JavaParamRef<jstring>& japp_package, 89 const JavaParamRef<jstring>& japp_package,
64 const JavaParamRef<jstring>& jicon_url) { 90 const JavaParamRef<jstring>& jicon_url) {
65 AppBannerDataFetcherAndroid* android_fetcher = 91 native_app_data_.Reset(japp_data);
66 static_cast<AppBannerDataFetcherAndroid*>(data_fetcher().get()); 92 app_title_ = ConvertJavaStringToUTF16(env, japp_title);
67 if (!CheckFetcherMatchesContents(android_fetcher->is_debug_mode())) 93 native_app_package_ = ConvertJavaStringToUTF8(env, japp_package);
68 return false; 94 icon_url_ = GURL(ConvertJavaStringToUTF8(env, jicon_url));
69 95
70 GURL image_url = GURL(ConvertJavaStringToUTF8(env, jicon_url)); 96 return ManifestIconDownloader::Download(
71 97 web_contents(), icon_url_, GetIdealIconSizeInDp(),
72 return android_fetcher->ContinueFetching( 98 GetMinimumIconSizeInDp(),
73 ConvertJavaStringToUTF16(env, japp_title), 99 base::Bind(&AppBannerManager::OnAppIconFetched, GetWeakPtr()));
74 ConvertJavaStringToUTF8(env, japp_package), japp_data, image_url);
75 } 100 }
76 101
77 void AppBannerManagerAndroid::RequestAppBanner(const GURL& validated_url, 102 void AppBannerManagerAndroid::RequestAppBanner(const GURL& validated_url,
78 bool is_debug_mode) { 103 bool is_debug_mode) {
79 JNIEnv* env = base::android::AttachCurrentThread(); 104 JNIEnv* env = base::android::AttachCurrentThread();
80 if (!Java_AppBannerManager_isEnabledForTab(env, java_banner_manager_.obj())) 105 if (!Java_AppBannerManager_isEnabledForTab(env, java_banner_manager_.obj()))
81 return; 106 return;
82 107
83 AppBannerManager::RequestAppBanner(validated_url, is_debug_mode); 108 AppBannerManager::RequestAppBanner(validated_url, is_debug_mode);
84 } 109 }
85 110
86 AppBannerDataFetcher* AppBannerManagerAndroid::CreateAppBannerDataFetcher( 111 std::string AppBannerManagerAndroid::GetAppIdentifier() {
87 base::WeakPtr<Delegate> weak_delegate, 112 return native_app_data_.is_null() ? AppBannerManager::GetAppIdentifier()
88 bool is_debug_mode) { 113 : native_app_package_;
89 return new AppBannerDataFetcherAndroid(
90 web_contents(), weak_delegate,
91 ShortcutHelper::GetIdealHomescreenIconSizeInDp(),
92 ShortcutHelper::GetMinimumHomescreenIconSizeInDp(),
93 ShortcutHelper::GetIdealSplashImageSizeInDp(),
94 ShortcutHelper::GetMinimumSplashImageSizeInDp(), is_debug_mode);
95 } 114 }
96 115
97 bool AppBannerManagerAndroid::HandleNonWebApp(const std::string& platform, 116 std::string AppBannerManagerAndroid::GetBannerType() {
117 return native_app_data_.is_null() ? AppBannerManager::GetBannerType()
118 : "android";
119 }
120
121 int AppBannerManagerAndroid::GetIdealIconSizeInDp() {
122 return ShortcutHelper::GetIdealHomescreenIconSizeInDp();
123 }
124
125 int AppBannerManagerAndroid::GetMinimumIconSizeInDp() {
126 return ShortcutHelper::GetMinimumHomescreenIconSizeInDp();
127 }
128
129 bool AppBannerManagerAndroid::IsWebAppInstalled(
130 content::BrowserContext* browser_context,
131 const GURL& start_url) {
132 // Check whether a WebAPK is installed in order to block showing the app
133 // banner if a WebAPK is installed even after a user clears Chrome's data.
134 // This function does not check whether a non-WebAPK web app is installed.
gone 2016/07/23 23:39:23 Seems like this comment should be flipped so that
dominickn 2016/07/25 00:23:51 Done.
135 return ShortcutHelper::IsWebApkInstalled(start_url);
136 }
137
138 void AppBannerManagerAndroid::ContinueInstallableCheck() {
139 // Check if the manifest prefers that we show a native app banner. If so, call
140 // to Java to verify the details.
141 if (manifest_.prefer_related_applications &&
142 manifest_.related_applications.size()) {
143 for (const auto& application : manifest_.related_applications) {
144 std::string platform = base::UTF16ToUTF8(application.platform.string());
145 std::string id = base::UTF16ToUTF8(application.id.string());
146 if (CanHandleNonWebApp(platform, application.url, id))
147 return;
148 }
149 }
150
151 // No native app banner was requested. Continue checking for a web app banner.
152 AppBannerManager::ContinueInstallableCheck();
153 }
154
155 void AppBannerManagerAndroid::OnAppIconFetched(const SkBitmap& bitmap) {
156 if (bitmap.drawsNothing()) {
157 ReportError(web_contents(), installable::NO_ICON_AVAILABLE);
158 Stop();
159 }
160
161 if (!is_active())
162 return;
163
164 icon_.reset(new SkBitmap(bitmap));
165 SendBannerPromptRequest();
166 }
167
168 void AppBannerManagerAndroid::ShowBanner() {
169 content::WebContents* contents = web_contents();
170 DCHECK(contents);
171
172 infobars::InfoBar* infobar = nullptr;
173 if (native_app_data_.is_null()) {
174 std::unique_ptr<AppBannerInfoBarDelegateAndroid> delegate(
175 new AppBannerInfoBarDelegateAndroid(
176 GetWeakPtr(), app_title_, manifest_url_, manifest_, icon_url_,
177 std::move(icon_), event_request_id()));
178
179 infobar = new AppBannerInfoBarAndroid(std::move(delegate),
180 manifest_.start_url);
181 if (infobar) {
182 RecordDidShowBanner("AppBanner.WebApp.Shown");
183 TrackDisplayEvent(DISPLAY_EVENT_WEB_APP_BANNER_CREATED);
184 }
185 } else {
186 std::unique_ptr<AppBannerInfoBarDelegateAndroid> delegate(
187 new AppBannerInfoBarDelegateAndroid(
188 app_title_, native_app_data_, std::move(icon_), native_app_package_,
189 referrer_, event_request_id()));
190 infobar =
191 new AppBannerInfoBarAndroid(std::move(delegate), native_app_data_);
192 if (infobar) {
193 RecordDidShowBanner("AppBanner.NativeApp.Shown");
194 TrackDisplayEvent(DISPLAY_EVENT_NATIVE_APP_BANNER_CREATED);
195 }
196 }
197 InfoBarService::FromWebContents(contents)->AddInfoBar(
198 base::WrapUnique(infobar));
199 }
200
201 bool AppBannerManagerAndroid::CanHandleNonWebApp(const std::string& platform,
98 const GURL& url, 202 const GURL& url,
99 const std::string& id, 203 const std::string& id) {
100 bool is_debug_mode) { 204 if (!CheckPlatformAndId(platform, id))
101 if (!CheckPlatformAndId(platform, id, is_debug_mode))
102 return false; 205 return false;
103 206
104 banners::TrackDisplayEvent(DISPLAY_EVENT_NATIVE_APP_BANNER_REQUESTED); 207 banners::TrackDisplayEvent(DISPLAY_EVENT_NATIVE_APP_BANNER_REQUESTED);
105 208
106 // Send the info to the Java side to get info about the app. 209 // Send the info to the Java side to get info about the app.
107 JNIEnv* env = base::android::AttachCurrentThread(); 210 JNIEnv* env = base::android::AttachCurrentThread();
108 if (java_banner_manager_.is_null()) 211 if (java_banner_manager_.is_null())
109 return false; 212 return false;
110 213
111 std::string id_from_app_url = ExtractQueryValueForName(url, kIdName); 214 std::string id_from_app_url = ExtractQueryValueForName(url, kIdName);
112 if (id_from_app_url.size() && id != id_from_app_url) { 215 if (id_from_app_url.size() && id != id_from_app_url) {
113 banners::OutputDeveloperNotShownMessage( 216 ReportError(web_contents(), installable::IDS_DO_NOT_MATCH);
114 web_contents(), banners::kIgnoredIdsDoNotMatch, is_debug_mode);
115 return false; 217 return false;
116 } 218 }
117 219
118 std::string referrer = 220 std::string referrer = ExtractQueryValueForName(url, kReferrerName);
119 ExtractQueryValueForName(url, kReferrerName);
120 221
121 // Attach the chrome_inline referrer value, prefixed with "&" if the referrer 222 // Attach the chrome_inline referrer value, prefixed with "&" if the referrer
122 // is non empty. 223 // is non empty.
123 if (referrer.empty()) 224 if (referrer.empty())
124 referrer = kPlayInlineReferrer; 225 referrer = kPlayInlineReferrer;
125 else 226 else
126 referrer.append("&").append(kPlayInlineReferrer); 227 referrer.append("&").append(kPlayInlineReferrer);
127 228
128 ScopedJavaLocalRef<jstring> jurl( 229 ScopedJavaLocalRef<jstring> jurl(
129 ConvertUTF8ToJavaString(env, data_fetcher()->validated_url().spec())); 230 ConvertUTF8ToJavaString(env, validated_url_.spec()));
130 ScopedJavaLocalRef<jstring> jpackage( 231 ScopedJavaLocalRef<jstring> jpackage(ConvertUTF8ToJavaString(env, id));
131 ConvertUTF8ToJavaString(env, id)); 232 ScopedJavaLocalRef<jstring> jreferrer(ConvertUTF8ToJavaString(env, referrer));
132 ScopedJavaLocalRef<jstring> jreferrer(
133 ConvertUTF8ToJavaString(env, referrer));
134 Java_AppBannerManager_fetchAppDetails( 233 Java_AppBannerManager_fetchAppDetails(
135 env, java_banner_manager_.obj(), jurl.obj(), 234 env, java_banner_manager_.obj(), jurl.obj(), jpackage.obj(),
136 jpackage.obj(), jreferrer.obj(), 235 jreferrer.obj(), GetIdealIconSizeInDp());
137 ShortcutHelper::GetIdealHomescreenIconSizeInDp());
138 return true; 236 return true;
139 } 237 }
140 238
141 void AppBannerManagerAndroid::CreateJavaBannerManager() { 239 void AppBannerManagerAndroid::CreateJavaBannerManager() {
142 JNIEnv* env = base::android::AttachCurrentThread(); 240 JNIEnv* env = base::android::AttachCurrentThread();
143 java_banner_manager_.Reset( 241 java_banner_manager_.Reset(
144 Java_AppBannerManager_create(env, reinterpret_cast<intptr_t>(this))); 242 Java_AppBannerManager_create(env, reinterpret_cast<intptr_t>(this)));
145 } 243 }
146 244
147 bool AppBannerManagerAndroid::CheckFetcherMatchesContents(bool is_debug_mode) { 245 bool AppBannerManagerAndroid::CheckPlatformAndId(const std::string& platform,
148 if (!web_contents()) 246 const std::string& id) {
247 if (platform != kPlayPlatform) {
248 ReportError(web_contents(), installable::PLATFORM_NOT_SUPPORTED_ON_ANDROID);
149 return false; 249 return false;
150 250 }
151 if (!data_fetcher() || 251 if (id.empty()) {
152 data_fetcher()->validated_url() != web_contents()->GetURL()) { 252 ReportError(web_contents(), installable::NO_ID_SPECIFIED);
153 banners::OutputDeveloperNotShownMessage(
154 web_contents(), banners::kUserNavigatedBeforeBannerShown,
155 is_debug_mode);
156 return false; 253 return false;
157 } 254 }
158 return true; 255 return true;
159 }
160
161 bool AppBannerManagerAndroid::CheckPlatformAndId(const std::string& platform,
162 const std::string& id,
163 bool is_debug_mode) {
164 if (platform != kPlayPlatform) {
165 banners::OutputDeveloperNotShownMessage(
166 web_contents(), banners::kIgnoredNotSupportedOnAndroid, platform,
167 is_debug_mode);
168 return false;
169 }
170 if (id.empty()) {
171 banners::OutputDeveloperNotShownMessage(
172 web_contents(), banners::kIgnoredNoId, is_debug_mode);
173 return false;
174 }
175 return true;
176 } 256 }
177 257
178 std::string AppBannerManagerAndroid::ExtractQueryValueForName( 258 std::string AppBannerManagerAndroid::ExtractQueryValueForName(
179 const GURL& url, 259 const GURL& url,
180 const std::string& name) { 260 const std::string& name) {
181 url::Component query = url.parsed_for_possibly_invalid_spec().query; 261 url::Component query = url.parsed_for_possibly_invalid_spec().query;
182 url::Component key, value; 262 url::Component key, value;
183 const char* url_spec = url.spec().c_str(); 263 const char* url_spec = url.spec().c_str();
184 264
185 while (url::ExtractQueryKeyValue(url_spec, &query, &key, &value)) { 265 while (url::ExtractQueryKeyValue(url_spec, &query, &key, &value)) {
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
221 jdouble direct_engagement, 301 jdouble direct_engagement,
222 jdouble indirect_engagement) { 302 jdouble indirect_engagement) {
223 AppBannerManager::SetEngagementWeights(direct_engagement, 303 AppBannerManager::SetEngagementWeights(direct_engagement,
224 indirect_engagement); 304 indirect_engagement);
225 } 305 }
226 306
227 // static 307 // static
228 void SetTimeDeltaForTesting(JNIEnv* env, 308 void SetTimeDeltaForTesting(JNIEnv* env,
229 const JavaParamRef<jclass>& clazz, 309 const JavaParamRef<jclass>& clazz,
230 jint days) { 310 jint days) {
231 AppBannerDataFetcher::SetTimeDeltaForTesting(days); 311 AppBannerManager::SetTimeDeltaForTesting(days);
232 } 312 }
233 313
234 } // namespace banners 314 } // namespace banners
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698