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

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: Naming, includes 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 using base::android::JavaParamRef; 29 using base::android::JavaParamRef;
22 using base::android::ScopedJavaLocalRef; 30 using base::android::ScopedJavaLocalRef;
23 31
24 DEFINE_WEB_CONTENTS_USER_DATA_KEY(banners::AppBannerManagerAndroid); 32 DEFINE_WEB_CONTENTS_USER_DATA_KEY(banners::AppBannerManagerAndroid);
25 33
26 namespace { 34 namespace {
27 35
28 const char kPlayPlatform[] = "play"; 36 const char kPlayPlatform[] = "play";
29 const char kReferrerName[] = "referrer"; 37 const char kReferrerName[] = "referrer";
30 const char kIdName[] = "id"; 38 const char kIdName[] = "id";
31 const char kPlayInlineReferrer[] = "playinline=chrome_inline"; 39 const char kPlayInlineReferrer[] = "playinline=chrome_inline";
32 40
33 } // anonymous namespace 41 } // anonymous namespace
34 42
35 namespace banners { 43 namespace banners {
36 44
37 AppBannerManagerAndroid::AppBannerManagerAndroid( 45 AppBannerManagerAndroid::AppBannerManagerAndroid(
38 content::WebContents* web_contents) 46 content::WebContents* web_contents)
39 : AppBannerManager(web_contents) { 47 : AppBannerManager(web_contents) {
40 CreateJavaBannerManager(); 48 CreateJavaBannerManager();
41 } 49 }
42 50
43 AppBannerManagerAndroid::~AppBannerManagerAndroid() { 51 AppBannerManagerAndroid::~AppBannerManagerAndroid() {
44 JNIEnv* env = base::android::AttachCurrentThread(); 52 JNIEnv* env = base::android::AttachCurrentThread();
45 Java_AppBannerManager_destroy(env, java_banner_manager_.obj()); 53 Java_AppBannerManager_destroy(env, java_banner_manager_.obj());
46 java_banner_manager_.Reset(); 54 java_banner_manager_.Reset();
47 } 55 }
48 56
57 base::Closure AppBannerManagerAndroid::FetchWebappSplashScreenImageCallback(
58 const std::string& webapp_id) {
59 content::WebContents* contents = web_contents();
60 DCHECK(contents);
61
62 int ideal_splash_image_size_in_dp =
63 ShortcutHelper::GetIdealSplashImageSizeInDp();
64 int minimum_splash_image_size_in_dp =
65 ShortcutHelper::GetMinimumSplashImageSizeInDp();
66 GURL image_url = ManifestIconSelector::FindBestMatchingIcon(
67 manifest_.icons, ideal_splash_image_size_in_dp,
68 minimum_splash_image_size_in_dp);
69
70 return base::Bind(&ShortcutHelper::FetchSplashScreenImage, contents,
71 image_url, ideal_splash_image_size_in_dp,
72 minimum_splash_image_size_in_dp, webapp_id);
73 }
74
49 const base::android::ScopedJavaGlobalRef<jobject>& 75 const base::android::ScopedJavaGlobalRef<jobject>&
50 AppBannerManagerAndroid::GetJavaBannerManager() const { 76 AppBannerManagerAndroid::GetJavaBannerManager() const {
51 return java_banner_manager_; 77 return java_banner_manager_;
52 } 78 }
53 79
54 bool AppBannerManagerAndroid::IsFetcherActive( 80 bool AppBannerManagerAndroid::IsActiveForTesting(
55 JNIEnv* env, 81 JNIEnv* env,
56 const JavaParamRef<jobject>& obj) { 82 const JavaParamRef<jobject>& obj) {
57 return AppBannerManager::IsFetcherActive(); 83 return is_active();
58 } 84 }
59 85
60 bool AppBannerManagerAndroid::OnAppDetailsRetrieved( 86 bool AppBannerManagerAndroid::OnAppDetailsRetrieved(
61 JNIEnv* env, 87 JNIEnv* env,
62 const JavaParamRef<jobject>& obj, 88 const JavaParamRef<jobject>& obj,
63 const JavaParamRef<jobject>& japp_data, 89 const JavaParamRef<jobject>& japp_data,
64 const JavaParamRef<jstring>& japp_title, 90 const JavaParamRef<jstring>& japp_title,
65 const JavaParamRef<jstring>& japp_package, 91 const JavaParamRef<jstring>& japp_package,
66 const JavaParamRef<jstring>& jicon_url) { 92 const JavaParamRef<jstring>& jicon_url) {
67 AppBannerDataFetcherAndroid* android_fetcher = 93 native_app_data_.Reset(japp_data);
68 static_cast<AppBannerDataFetcherAndroid*>(data_fetcher().get()); 94 app_title_ = ConvertJavaStringToUTF16(env, japp_title);
69 if (!CheckFetcherMatchesContents(android_fetcher->is_debug_mode())) 95 native_app_package_ = ConvertJavaStringToUTF8(env, japp_package);
70 return false; 96 icon_url_ = GURL(ConvertJavaStringToUTF8(env, jicon_url));
71 97
72 GURL image_url = GURL(ConvertJavaStringToUTF8(env, jicon_url)); 98 return ManifestIconDownloader::Download(
73 99 web_contents(), icon_url_, GetIdealIconSizeInDp(),
74 return android_fetcher->ContinueFetching( 100 GetMinimumIconSizeInDp(),
75 ConvertJavaStringToUTF16(env, japp_title), 101 base::Bind(&AppBannerManager::OnAppIconFetched, GetWeakPtr()));
76 ConvertJavaStringToUTF8(env, japp_package), japp_data, image_url);
77 } 102 }
78 103
79 void AppBannerManagerAndroid::RequestAppBanner(const GURL& validated_url, 104 void AppBannerManagerAndroid::RequestAppBanner(const GURL& validated_url,
80 bool is_debug_mode) { 105 bool is_debug_mode) {
81 JNIEnv* env = base::android::AttachCurrentThread(); 106 JNIEnv* env = base::android::AttachCurrentThread();
82 if (!Java_AppBannerManager_isEnabledForTab(env, java_banner_manager_.obj())) 107 if (!Java_AppBannerManager_isEnabledForTab(env, java_banner_manager_.obj()))
83 return; 108 return;
84 109
85 AppBannerManager::RequestAppBanner(validated_url, is_debug_mode); 110 AppBannerManager::RequestAppBanner(validated_url, is_debug_mode);
86 } 111 }
87 112
88 AppBannerDataFetcher* AppBannerManagerAndroid::CreateAppBannerDataFetcher( 113 std::string AppBannerManagerAndroid::GetAppIdentifier() {
89 base::WeakPtr<Delegate> weak_delegate, 114 return native_app_data_.is_null() ? AppBannerManager::GetAppIdentifier()
90 bool is_debug_mode) { 115 : native_app_package_;
91 return new AppBannerDataFetcherAndroid(
92 web_contents(), weak_delegate,
93 ShortcutHelper::GetIdealHomescreenIconSizeInDp(),
94 ShortcutHelper::GetMinimumHomescreenIconSizeInDp(),
95 ShortcutHelper::GetIdealSplashImageSizeInDp(),
96 ShortcutHelper::GetMinimumSplashImageSizeInDp(), is_debug_mode);
97 } 116 }
98 117
99 bool AppBannerManagerAndroid::HandleNonWebApp(const std::string& platform, 118 std::string AppBannerManagerAndroid::GetBannerType() {
119 return native_app_data_.is_null() ? AppBannerManager::GetBannerType()
120 : "android";
121 }
122
123 int AppBannerManagerAndroid::GetIdealIconSizeInDp() {
124 return ShortcutHelper::GetIdealHomescreenIconSizeInDp();
125 }
126
127 int AppBannerManagerAndroid::GetMinimumIconSizeInDp() {
128 return ShortcutHelper::GetMinimumHomescreenIconSizeInDp();
129 }
130
131 bool AppBannerManagerAndroid::IsWebAppInstalled(
132 content::BrowserContext* browser_context,
133 const GURL& start_url) {
134 // Returns true if a WebAPK is installed. Does not check whether a non-WebAPK
135 // web app is installed: this is detected by the content settings check in
136 // AppBannerSettingsHelper::ShouldShowBanner (due to the lack of an API to
137 // detect what is and isn't on the Android homescreen).
138 // This method will still detect the presence of a WebAPK even if Chrome's
139 // data is cleared.
140 return ShortcutHelper::IsWebApkInstalled(start_url);
141 }
142
143 void AppBannerManagerAndroid::PerformInstallableCheck() {
144 // Check if the manifest prefers that we show a native app banner. If so, call
145 // to Java to verify the details.
146 if (manifest_.prefer_related_applications &&
147 manifest_.related_applications.size()) {
148 for (const auto& application : manifest_.related_applications) {
149 std::string platform = base::UTF16ToUTF8(application.platform.string());
150 std::string id = base::UTF16ToUTF8(application.id.string());
151 if (CanHandleNonWebApp(platform, application.url, id))
152 return;
153 }
154 }
155
156 // No native app banner was requested. Continue checking for a web app banner.
157 AppBannerManager::PerformInstallableCheck();
158 }
159
160 void AppBannerManagerAndroid::OnAppIconFetched(const SkBitmap& bitmap) {
161 if (bitmap.drawsNothing()) {
162 ReportError(web_contents(), NO_ICON_AVAILABLE);
163 Stop();
164 }
165
166 if (!is_active())
167 return;
168
169 icon_.reset(new SkBitmap(bitmap));
170 SendBannerPromptRequest();
171 }
172
173 void AppBannerManagerAndroid::ShowBanner() {
174 content::WebContents* contents = web_contents();
175 DCHECK(contents);
176
177 infobars::InfoBar* infobar = nullptr;
178 if (native_app_data_.is_null()) {
179 std::unique_ptr<AppBannerInfoBarDelegateAndroid> delegate(
180 new AppBannerInfoBarDelegateAndroid(
181 GetWeakPtr(), app_title_, manifest_url_, manifest_, icon_url_,
182 std::move(icon_), event_request_id()));
183
184 infobar = new AppBannerInfoBarAndroid(std::move(delegate),
185 manifest_.start_url);
186 if (infobar) {
187 RecordDidShowBanner("AppBanner.WebApp.Shown");
188 TrackDisplayEvent(DISPLAY_EVENT_WEB_APP_BANNER_CREATED);
189 }
190 } else {
191 std::unique_ptr<AppBannerInfoBarDelegateAndroid> delegate(
192 new AppBannerInfoBarDelegateAndroid(
193 app_title_, native_app_data_, std::move(icon_), native_app_package_,
194 referrer_, event_request_id()));
195 infobar =
196 new AppBannerInfoBarAndroid(std::move(delegate), native_app_data_);
197 if (infobar) {
198 RecordDidShowBanner("AppBanner.NativeApp.Shown");
199 TrackDisplayEvent(DISPLAY_EVENT_NATIVE_APP_BANNER_CREATED);
200 }
201 }
202
203 if (infobar) {
204 InfoBarService::FromWebContents(contents)->AddInfoBar(
205 base::WrapUnique(infobar));
206 }
207 }
208
209 bool AppBannerManagerAndroid::CanHandleNonWebApp(const std::string& platform,
100 const GURL& url, 210 const GURL& url,
101 const std::string& id, 211 const std::string& id) {
102 bool is_debug_mode) { 212 if (!CheckPlatformAndId(platform, id))
103 if (!CheckPlatformAndId(platform, id, is_debug_mode))
104 return false; 213 return false;
105 214
106 banners::TrackDisplayEvent(DISPLAY_EVENT_NATIVE_APP_BANNER_REQUESTED); 215 banners::TrackDisplayEvent(DISPLAY_EVENT_NATIVE_APP_BANNER_REQUESTED);
107 216
108 // Send the info to the Java side to get info about the app. 217 // Send the info to the Java side to get info about the app.
109 JNIEnv* env = base::android::AttachCurrentThread(); 218 JNIEnv* env = base::android::AttachCurrentThread();
110 if (java_banner_manager_.is_null()) 219 if (java_banner_manager_.is_null())
111 return false; 220 return false;
112 221
113 std::string id_from_app_url = ExtractQueryValueForName(url, kIdName); 222 std::string id_from_app_url = ExtractQueryValueForName(url, kIdName);
114 if (id_from_app_url.size() && id != id_from_app_url) { 223 if (id_from_app_url.size() && id != id_from_app_url) {
115 banners::OutputDeveloperNotShownMessage( 224 ReportError(web_contents(), IDS_DO_NOT_MATCH);
116 web_contents(), banners::kIgnoredIdsDoNotMatch, is_debug_mode);
117 return false; 225 return false;
118 } 226 }
119 227
120 std::string referrer = 228 std::string referrer = ExtractQueryValueForName(url, kReferrerName);
121 ExtractQueryValueForName(url, kReferrerName);
122 229
123 // Attach the chrome_inline referrer value, prefixed with "&" if the referrer 230 // Attach the chrome_inline referrer value, prefixed with "&" if the referrer
124 // is non empty. 231 // is non empty.
125 if (referrer.empty()) 232 if (referrer.empty())
126 referrer = kPlayInlineReferrer; 233 referrer = kPlayInlineReferrer;
127 else 234 else
128 referrer.append("&").append(kPlayInlineReferrer); 235 referrer.append("&").append(kPlayInlineReferrer);
129 236
130 ScopedJavaLocalRef<jstring> jurl( 237 ScopedJavaLocalRef<jstring> jurl(
131 ConvertUTF8ToJavaString(env, data_fetcher()->validated_url().spec())); 238 ConvertUTF8ToJavaString(env, validated_url_.spec()));
132 ScopedJavaLocalRef<jstring> jpackage( 239 ScopedJavaLocalRef<jstring> jpackage(ConvertUTF8ToJavaString(env, id));
133 ConvertUTF8ToJavaString(env, id)); 240 ScopedJavaLocalRef<jstring> jreferrer(ConvertUTF8ToJavaString(env, referrer));
134 ScopedJavaLocalRef<jstring> jreferrer(
135 ConvertUTF8ToJavaString(env, referrer));
136 Java_AppBannerManager_fetchAppDetails( 241 Java_AppBannerManager_fetchAppDetails(
137 env, java_banner_manager_.obj(), jurl.obj(), 242 env, java_banner_manager_.obj(), jurl.obj(), jpackage.obj(),
138 jpackage.obj(), jreferrer.obj(), 243 jreferrer.obj(), GetIdealIconSizeInDp());
139 ShortcutHelper::GetIdealHomescreenIconSizeInDp());
140 return true; 244 return true;
141 } 245 }
142 246
143 void AppBannerManagerAndroid::CreateJavaBannerManager() { 247 void AppBannerManagerAndroid::CreateJavaBannerManager() {
144 JNIEnv* env = base::android::AttachCurrentThread(); 248 JNIEnv* env = base::android::AttachCurrentThread();
145 java_banner_manager_.Reset( 249 java_banner_manager_.Reset(
146 Java_AppBannerManager_create(env, reinterpret_cast<intptr_t>(this))); 250 Java_AppBannerManager_create(env, reinterpret_cast<intptr_t>(this)));
147 } 251 }
148 252
149 bool AppBannerManagerAndroid::CheckFetcherMatchesContents(bool is_debug_mode) { 253 bool AppBannerManagerAndroid::CheckPlatformAndId(const std::string& platform,
150 if (!web_contents()) 254 const std::string& id) {
255 if (platform != kPlayPlatform) {
256 ReportError(web_contents(), PLATFORM_NOT_SUPPORTED_ON_ANDROID);
151 return false; 257 return false;
152 258 }
153 if (!data_fetcher() || 259 if (id.empty()) {
154 data_fetcher()->validated_url() != web_contents()->GetURL()) { 260 ReportError(web_contents(), NO_ID_SPECIFIED);
155 banners::OutputDeveloperNotShownMessage(
156 web_contents(), banners::kUserNavigatedBeforeBannerShown,
157 is_debug_mode);
158 return false; 261 return false;
159 } 262 }
160 return true; 263 return true;
161 }
162
163 bool AppBannerManagerAndroid::CheckPlatformAndId(const std::string& platform,
164 const std::string& id,
165 bool is_debug_mode) {
166 if (platform != kPlayPlatform) {
167 banners::OutputDeveloperNotShownMessage(
168 web_contents(), banners::kIgnoredNotSupportedOnAndroid, platform,
169 is_debug_mode);
170 return false;
171 }
172 if (id.empty()) {
173 banners::OutputDeveloperNotShownMessage(
174 web_contents(), banners::kIgnoredNoId, is_debug_mode);
175 return false;
176 }
177 return true;
178 } 264 }
179 265
180 std::string AppBannerManagerAndroid::ExtractQueryValueForName( 266 std::string AppBannerManagerAndroid::ExtractQueryValueForName(
181 const GURL& url, 267 const GURL& url,
182 const std::string& name) { 268 const std::string& name) {
183 url::Component query = url.parsed_for_possibly_invalid_spec().query; 269 url::Component query = url.parsed_for_possibly_invalid_spec().query;
184 url::Component key, value; 270 url::Component key, value;
185 const char* url_spec = url.spec().c_str(); 271 const char* url_spec = url.spec().c_str();
186 272
187 while (url::ExtractQueryKeyValue(url_spec, &query, &key, &value)) { 273 while (url::ExtractQueryKeyValue(url_spec, &query, &key, &value)) {
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
223 jdouble direct_engagement, 309 jdouble direct_engagement,
224 jdouble indirect_engagement) { 310 jdouble indirect_engagement) {
225 AppBannerManager::SetEngagementWeights(direct_engagement, 311 AppBannerManager::SetEngagementWeights(direct_engagement,
226 indirect_engagement); 312 indirect_engagement);
227 } 313 }
228 314
229 // static 315 // static
230 void SetTimeDeltaForTesting(JNIEnv* env, 316 void SetTimeDeltaForTesting(JNIEnv* env,
231 const JavaParamRef<jclass>& clazz, 317 const JavaParamRef<jclass>& clazz,
232 jint days) { 318 jint days) {
233 AppBannerDataFetcher::SetTimeDeltaForTesting(days); 319 AppBannerManager::SetTimeDeltaForTesting(days);
234 } 320 }
235 321
236 } // namespace banners 322 } // namespace banners
OLDNEW
« no previous file with comments | « chrome/browser/android/banners/app_banner_manager_android.h ('k') | chrome/browser/banners/app_banner_data_fetcher.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698