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

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, 4 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 // Returns true if a WebAPK is installed. Does not check whether a non-WebAPK
133 // web app is installed: this is detected by the content settings check in
134 // AppBannerSettingsHelper::ShouldShowBanner (due to the lack of an API to
135 // detect what is and isn't on the Android homescreen).
136 // This method will still detect the presence of a WebAPK even if Chrome's
137 // data is cleared.
138 return ShortcutHelper::IsWebApkInstalled(start_url);
139 }
140
141 void AppBannerManagerAndroid::ContinueInstallableCheck() {
142 // Check if the manifest prefers that we show a native app banner. If so, call
143 // to Java to verify the details.
144 if (manifest_.prefer_related_applications &&
145 manifest_.related_applications.size()) {
146 for (const auto& application : manifest_.related_applications) {
147 std::string platform = base::UTF16ToUTF8(application.platform.string());
148 std::string id = base::UTF16ToUTF8(application.id.string());
149 if (CanHandleNonWebApp(platform, application.url, id))
150 return;
151 }
152 }
153
154 // No native app banner was requested. Continue checking for a web app banner.
155 AppBannerManager::ContinueInstallableCheck();
156 }
157
158 void AppBannerManagerAndroid::OnAppIconFetched(const SkBitmap& bitmap) {
159 if (bitmap.drawsNothing()) {
160 ReportError(web_contents(), NO_ICON_AVAILABLE);
161 Stop();
162 }
163
164 if (!is_active())
165 return;
166
167 icon_.reset(new SkBitmap(bitmap));
168 SendBannerPromptRequest();
169 }
170
171 void AppBannerManagerAndroid::ShowBanner() {
172 content::WebContents* contents = web_contents();
173 DCHECK(contents);
174
175 infobars::InfoBar* infobar = nullptr;
176 if (native_app_data_.is_null()) {
177 std::unique_ptr<AppBannerInfoBarDelegateAndroid> delegate(
178 new AppBannerInfoBarDelegateAndroid(
179 GetWeakPtr(), app_title_, manifest_url_, manifest_, icon_url_,
180 std::move(icon_), event_request_id()));
181
182 infobar = new AppBannerInfoBarAndroid(std::move(delegate),
183 manifest_.start_url);
184 if (infobar) {
185 RecordDidShowBanner("AppBanner.WebApp.Shown");
186 TrackDisplayEvent(DISPLAY_EVENT_WEB_APP_BANNER_CREATED);
187 }
188 } else {
189 std::unique_ptr<AppBannerInfoBarDelegateAndroid> delegate(
190 new AppBannerInfoBarDelegateAndroid(
191 app_title_, native_app_data_, std::move(icon_), native_app_package_,
192 referrer_, event_request_id()));
193 infobar =
194 new AppBannerInfoBarAndroid(std::move(delegate), native_app_data_);
195 if (infobar) {
196 RecordDidShowBanner("AppBanner.NativeApp.Shown");
197 TrackDisplayEvent(DISPLAY_EVENT_NATIVE_APP_BANNER_CREATED);
198 }
199 }
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.
200 InfoBarService::FromWebContents(contents)->AddInfoBar(
201 base::WrapUnique(infobar));
202 }
203
204 bool AppBannerManagerAndroid::CanHandleNonWebApp(const std::string& platform,
98 const GURL& url, 205 const GURL& url,
99 const std::string& id, 206 const std::string& id) {
100 bool is_debug_mode) { 207 if (!CheckPlatformAndId(platform, id))
101 if (!CheckPlatformAndId(platform, id, is_debug_mode))
102 return false; 208 return false;
103 209
104 banners::TrackDisplayEvent(DISPLAY_EVENT_NATIVE_APP_BANNER_REQUESTED); 210 banners::TrackDisplayEvent(DISPLAY_EVENT_NATIVE_APP_BANNER_REQUESTED);
105 211
106 // Send the info to the Java side to get info about the app. 212 // Send the info to the Java side to get info about the app.
107 JNIEnv* env = base::android::AttachCurrentThread(); 213 JNIEnv* env = base::android::AttachCurrentThread();
108 if (java_banner_manager_.is_null()) 214 if (java_banner_manager_.is_null())
109 return false; 215 return false;
110 216
111 std::string id_from_app_url = ExtractQueryValueForName(url, kIdName); 217 std::string id_from_app_url = ExtractQueryValueForName(url, kIdName);
112 if (id_from_app_url.size() && id != id_from_app_url) { 218 if (id_from_app_url.size() && id != id_from_app_url) {
113 banners::OutputDeveloperNotShownMessage( 219 ReportError(web_contents(), IDS_DO_NOT_MATCH);
114 web_contents(), banners::kIgnoredIdsDoNotMatch, is_debug_mode);
115 return false; 220 return false;
116 } 221 }
117 222
118 std::string referrer = 223 std::string referrer = ExtractQueryValueForName(url, kReferrerName);
119 ExtractQueryValueForName(url, kReferrerName);
120 224
121 // Attach the chrome_inline referrer value, prefixed with "&" if the referrer 225 // Attach the chrome_inline referrer value, prefixed with "&" if the referrer
122 // is non empty. 226 // is non empty.
123 if (referrer.empty()) 227 if (referrer.empty())
124 referrer = kPlayInlineReferrer; 228 referrer = kPlayInlineReferrer;
125 else 229 else
126 referrer.append("&").append(kPlayInlineReferrer); 230 referrer.append("&").append(kPlayInlineReferrer);
127 231
128 ScopedJavaLocalRef<jstring> jurl( 232 ScopedJavaLocalRef<jstring> jurl(
129 ConvertUTF8ToJavaString(env, data_fetcher()->validated_url().spec())); 233 ConvertUTF8ToJavaString(env, validated_url_.spec()));
130 ScopedJavaLocalRef<jstring> jpackage( 234 ScopedJavaLocalRef<jstring> jpackage(ConvertUTF8ToJavaString(env, id));
131 ConvertUTF8ToJavaString(env, id)); 235 ScopedJavaLocalRef<jstring> jreferrer(ConvertUTF8ToJavaString(env, referrer));
132 ScopedJavaLocalRef<jstring> jreferrer(
133 ConvertUTF8ToJavaString(env, referrer));
134 Java_AppBannerManager_fetchAppDetails( 236 Java_AppBannerManager_fetchAppDetails(
135 env, java_banner_manager_.obj(), jurl.obj(), 237 env, java_banner_manager_.obj(), jurl.obj(), jpackage.obj(),
136 jpackage.obj(), jreferrer.obj(), 238 jreferrer.obj(), GetIdealIconSizeInDp());
137 ShortcutHelper::GetIdealHomescreenIconSizeInDp());
138 return true; 239 return true;
139 } 240 }
140 241
141 void AppBannerManagerAndroid::CreateJavaBannerManager() { 242 void AppBannerManagerAndroid::CreateJavaBannerManager() {
142 JNIEnv* env = base::android::AttachCurrentThread(); 243 JNIEnv* env = base::android::AttachCurrentThread();
143 java_banner_manager_.Reset( 244 java_banner_manager_.Reset(
144 Java_AppBannerManager_create(env, reinterpret_cast<intptr_t>(this))); 245 Java_AppBannerManager_create(env, reinterpret_cast<intptr_t>(this)));
145 } 246 }
146 247
147 bool AppBannerManagerAndroid::CheckFetcherMatchesContents(bool is_debug_mode) { 248 bool AppBannerManagerAndroid::CheckPlatformAndId(const std::string& platform,
148 if (!web_contents()) 249 const std::string& id) {
250 if (platform != kPlayPlatform) {
251 ReportError(web_contents(), PLATFORM_NOT_SUPPORTED_ON_ANDROID);
149 return false; 252 return false;
150 253 }
151 if (!data_fetcher() || 254 if (id.empty()) {
152 data_fetcher()->validated_url() != web_contents()->GetURL()) { 255 ReportError(web_contents(), NO_ID_SPECIFIED);
153 banners::OutputDeveloperNotShownMessage(
154 web_contents(), banners::kUserNavigatedBeforeBannerShown,
155 is_debug_mode);
156 return false; 256 return false;
157 } 257 }
158 return true; 258 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 } 259 }
177 260
178 std::string AppBannerManagerAndroid::ExtractQueryValueForName( 261 std::string AppBannerManagerAndroid::ExtractQueryValueForName(
179 const GURL& url, 262 const GURL& url,
180 const std::string& name) { 263 const std::string& name) {
181 url::Component query = url.parsed_for_possibly_invalid_spec().query; 264 url::Component query = url.parsed_for_possibly_invalid_spec().query;
182 url::Component key, value; 265 url::Component key, value;
183 const char* url_spec = url.spec().c_str(); 266 const char* url_spec = url.spec().c_str();
184 267
185 while (url::ExtractQueryKeyValue(url_spec, &query, &key, &value)) { 268 while (url::ExtractQueryKeyValue(url_spec, &query, &key, &value)) {
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
221 jdouble direct_engagement, 304 jdouble direct_engagement,
222 jdouble indirect_engagement) { 305 jdouble indirect_engagement) {
223 AppBannerManager::SetEngagementWeights(direct_engagement, 306 AppBannerManager::SetEngagementWeights(direct_engagement,
224 indirect_engagement); 307 indirect_engagement);
225 } 308 }
226 309
227 // static 310 // static
228 void SetTimeDeltaForTesting(JNIEnv* env, 311 void SetTimeDeltaForTesting(JNIEnv* env,
229 const JavaParamRef<jclass>& clazz, 312 const JavaParamRef<jclass>& clazz,
230 jint days) { 313 jint days) {
231 AppBannerDataFetcher::SetTimeDeltaForTesting(days); 314 AppBannerManager::SetTimeDeltaForTesting(days);
232 } 315 }
233 316
234 } // namespace banners 317 } // namespace banners
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698