| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 "chrome/browser/android/banners/app_banner_manager.h" | 5 #include "chrome/browser/android/banners/app_banner_manager.h" |
| 6 | 6 |
| 7 #include "base/android/jni_android.h" | 7 #include "base/android/jni_android.h" |
| 8 #include "base/android/jni_string.h" | 8 #include "base/android/jni_string.h" |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/command_line.h" | 10 #include "base/command_line.h" |
| 11 #include "base/metrics/histogram.h" | 11 #include "base/metrics/histogram.h" |
| 12 #include "chrome/browser/android/banners/app_banner_infobar_delegate.h" |
| 12 #include "chrome/browser/android/banners/app_banner_metrics_ids.h" | 13 #include "chrome/browser/android/banners/app_banner_metrics_ids.h" |
| 13 #include "chrome/browser/android/banners/app_banner_settings_helper.h" | 14 #include "chrome/browser/android/banners/app_banner_settings_helper.h" |
| 14 #include "chrome/browser/android/banners/app_banner_utilities.h" | 15 #include "chrome/browser/android/banners/app_banner_utilities.h" |
| 15 #include "chrome/browser/bitmap_fetcher/bitmap_fetcher.h" | 16 #include "chrome/browser/bitmap_fetcher/bitmap_fetcher.h" |
| 17 #include "chrome/browser/infobars/infobar_service.h" |
| 16 #include "chrome/browser/profiles/profile.h" | 18 #include "chrome/browser/profiles/profile.h" |
| 17 #include "chrome/common/chrome_constants.h" | 19 #include "chrome/common/chrome_constants.h" |
| 18 #include "chrome/common/chrome_switches.h" | 20 #include "chrome/common/chrome_switches.h" |
| 19 #include "chrome/common/render_messages.h" | 21 #include "chrome/common/render_messages.h" |
| 20 #include "content/public/browser/android/content_view_core.h" | 22 #include "content/public/browser/android/content_view_core.h" |
| 21 #include "content/public/browser/navigation_details.h" | 23 #include "content/public/browser/navigation_details.h" |
| 22 #include "content/public/browser/render_frame_host.h" | 24 #include "content/public/browser/render_frame_host.h" |
| 23 #include "content/public/browser/web_contents.h" | 25 #include "content/public/browser/web_contents.h" |
| 24 #include "content/public/common/frame_navigate_params.h" | 26 #include "content/public/common/frame_navigate_params.h" |
| 25 #include "content/public/common/manifest.h" | 27 #include "content/public/common/manifest.h" |
| 26 #include "jni/AppBannerManager_jni.h" | 28 #include "jni/AppBannerManager_jni.h" |
| 27 #include "net/base/load_flags.h" | 29 #include "net/base/load_flags.h" |
| 28 #include "ui/gfx/android/java_bitmap.h" | 30 #include "ui/gfx/android/java_bitmap.h" |
| 29 | 31 |
| 30 using base::android::ConvertJavaStringToUTF8; | 32 using base::android::ConvertJavaStringToUTF8; |
| 31 using base::android::ConvertUTF8ToJavaString; | 33 using base::android::ConvertUTF8ToJavaString; |
| 34 using base::android::ConvertUTF16ToJavaString; |
| 32 | 35 |
| 33 namespace { | 36 namespace { |
| 34 const char kBannerTag[] = "google-play-id"; | 37 const char kBannerTag[] = "google-play-id"; |
| 35 } | 38 } |
| 36 | 39 |
| 37 namespace banners { | 40 namespace banners { |
| 38 | 41 |
| 39 AppBannerManager::AppBannerManager(JNIEnv* env, jobject obj) | 42 AppBannerManager::AppBannerManager(JNIEnv* env, jobject obj) |
| 40 : weak_java_banner_view_manager_(env, obj) {} | 43 : weak_java_banner_view_manager_(env, obj) {} |
| 41 | 44 |
| 42 AppBannerManager::~AppBannerManager() { | 45 AppBannerManager::~AppBannerManager() { |
| 43 } | 46 } |
| 44 | 47 |
| 45 void AppBannerManager::Destroy(JNIEnv* env, jobject obj) { | 48 void AppBannerManager::Destroy(JNIEnv* env, jobject obj) { |
| 46 delete this; | 49 delete this; |
| 47 } | 50 } |
| 48 | 51 |
| 49 void AppBannerManager::BlockBanner(JNIEnv* env, | 52 void AppBannerManager::BlockBanner(JNIEnv* env, |
| 50 jobject obj, | 53 jobject obj, |
| 51 jstring jurl, | 54 jstring jurl, |
| 52 jstring jpackage) { | 55 jstring jpackage) { |
| 53 if (!web_contents()) | 56 if (!web_contents()) |
| 54 return; | 57 return; |
| 55 | 58 |
| 56 GURL url(ConvertJavaStringToUTF8(env, jurl)); | 59 GURL url(ConvertJavaStringToUTF8(env, jurl)); |
| 57 std::string package_name = ConvertJavaStringToUTF8(env, jpackage); | 60 std::string package_name = ConvertJavaStringToUTF8(env, jpackage); |
| 58 AppBannerSettingsHelper::Block(web_contents(), url, package_name); | 61 AppBannerSettingsHelper::Block(web_contents(), url, package_name); |
| 59 } | 62 } |
| 60 | 63 |
| 64 void AppBannerManager::Block() const { |
| 65 if (!web_contents() || manifest_.IsEmpty()) |
| 66 return; |
| 67 |
| 68 AppBannerSettingsHelper::Block(web_contents(), |
| 69 web_contents()->GetURL(), |
| 70 manifest_.start_url.spec()); |
| 71 } |
| 72 |
| 73 void AppBannerManager::Install() const { |
| 74 if (!web_contents()) |
| 75 return; |
| 76 |
| 77 if (!manifest_.IsEmpty()) { |
| 78 // TODO(dfalcantara): Trigger shortcut creation. |
| 79 } |
| 80 } |
| 81 |
| 82 gfx::Image AppBannerManager::GetIcon() const { |
| 83 return gfx::Image::CreateFrom1xBitmap(*app_icon_.get()); |
| 84 } |
| 85 |
| 61 void AppBannerManager::ReplaceWebContents(JNIEnv* env, | 86 void AppBannerManager::ReplaceWebContents(JNIEnv* env, |
| 62 jobject obj, | 87 jobject obj, |
| 63 jobject jweb_contents) { | 88 jobject jweb_contents) { |
| 64 content::WebContents* web_contents = | 89 content::WebContents* web_contents = |
| 65 content::WebContents::FromJavaWebContents(jweb_contents); | 90 content::WebContents::FromJavaWebContents(jweb_contents); |
| 66 Observe(web_contents); | 91 Observe(web_contents); |
| 67 } | 92 } |
| 68 | 93 |
| 69 void AppBannerManager::DidNavigateMainFrame( | 94 void AppBannerManager::DidNavigateMainFrame( |
| 70 const content::LoadCommittedDetails& details, | 95 const content::LoadCommittedDetails& details, |
| 71 const content::FrameNavigateParams& params) { | 96 const content::FrameNavigateParams& params) { |
| 97 // Clear current state. |
| 98 fetcher_.reset(); |
| 99 manifest_ = content::Manifest(); |
| 100 app_icon_.reset(); |
| 101 |
| 72 // Get rid of the current banner. | 102 // Get rid of the current banner. |
| 73 JNIEnv* env = base::android::AttachCurrentThread(); | 103 JNIEnv* env = base::android::AttachCurrentThread(); |
| 74 ScopedJavaLocalRef<jobject> jobj = weak_java_banner_view_manager_.get(env); | 104 ScopedJavaLocalRef<jobject> jobj = weak_java_banner_view_manager_.get(env); |
| 75 if (jobj.is_null()) | 105 if (jobj.is_null()) |
| 76 return; | 106 return; |
| 77 Java_AppBannerManager_dismissCurrentBanner(env, jobj.obj(), DISMISS_NAVIGATE); | 107 Java_AppBannerManager_dismissCurrentBanner(env, jobj.obj(), DISMISS_NAVIGATE); |
| 78 } | 108 } |
| 79 | 109 |
| 80 void AppBannerManager::DidFinishLoad( | 110 void AppBannerManager::DidFinishLoad( |
| 81 content::RenderFrameHost* render_frame_host, | 111 content::RenderFrameHost* render_frame_host, |
| (...skipping 16 matching lines...) Expand all Loading... |
| 98 if (manifest.IsEmpty()) { | 128 if (manifest.IsEmpty()) { |
| 99 // No manifest, see if there is a play store meta tag. | 129 // No manifest, see if there is a play store meta tag. |
| 100 Send(new ChromeViewMsg_RetrieveMetaTagContent(routing_id(), | 130 Send(new ChromeViewMsg_RetrieveMetaTagContent(routing_id(), |
| 101 validated_url_, | 131 validated_url_, |
| 102 kBannerTag)); | 132 kBannerTag)); |
| 103 return; | 133 return; |
| 104 } | 134 } |
| 105 | 135 |
| 106 // TODO(benwells): Check triggering parameters here and if there is a meta | 136 // TODO(benwells): Check triggering parameters here and if there is a meta |
| 107 // tag. | 137 // tag. |
| 108 // TODO(dfalcantara): Show banner for web site with manifest. | 138 |
| 139 // Create an infobar to promote the manifest's app. |
| 140 manifest_ = manifest; |
| 141 |
| 142 /* TODO(dfalcantara): Use after landing https://crrev.com/880203004. |
| 143 GURL icon_url = |
| 144 ManifestIconSelector::FindBestMatchingIcon(manifest.icons, |
| 145 GetPreferredIconSize(), |
| 146 web_contents()); |
| 147 if (icon_url.is_empty()) |
| 148 return; |
| 149 */ |
| 150 if (manifest.icons.empty()) |
| 151 return; |
| 152 GURL icon_url = manifest.icons.back().src; |
| 153 |
| 154 FetchIcon(icon_url); |
| 109 } | 155 } |
| 110 | 156 |
| 111 bool AppBannerManager::OnMessageReceived(const IPC::Message& message) { | 157 bool AppBannerManager::OnMessageReceived(const IPC::Message& message) { |
| 112 bool handled = true; | 158 bool handled = true; |
| 113 IPC_BEGIN_MESSAGE_MAP(AppBannerManager, message) | 159 IPC_BEGIN_MESSAGE_MAP(AppBannerManager, message) |
| 114 IPC_MESSAGE_HANDLER(ChromeViewHostMsg_DidRetrieveMetaTagContent, | 160 IPC_MESSAGE_HANDLER(ChromeViewHostMsg_DidRetrieveMetaTagContent, |
| 115 OnDidRetrieveMetaTagContent) | 161 OnDidRetrieveMetaTagContent) |
| 116 IPC_MESSAGE_UNHANDLED(handled = false) | 162 IPC_MESSAGE_UNHANDLED(handled = false) |
| 117 IPC_END_MESSAGE_MAP() | 163 IPC_END_MESSAGE_MAP() |
| 118 return handled; | 164 return handled; |
| 119 } | 165 } |
| 120 | 166 |
| 121 void AppBannerManager::OnFetchComplete(const GURL url, const SkBitmap* bitmap) { | 167 void AppBannerManager::OnFetchComplete(const GURL url, const SkBitmap* bitmap) { |
| 122 if (bitmap) { | 168 if (bitmap) { |
| 123 JNIEnv* env = base::android::AttachCurrentThread(); | 169 JNIEnv* env = base::android::AttachCurrentThread(); |
| 124 | 170 |
| 125 ScopedJavaLocalRef<jobject> jobj = weak_java_banner_view_manager_.get(env); | 171 ScopedJavaLocalRef<jobject> jobj = weak_java_banner_view_manager_.get(env); |
| 126 if (jobj.is_null()) | 172 if (jobj.is_null()) |
| 127 return; | 173 return; |
| 128 | 174 |
| 129 ScopedJavaLocalRef<jstring> jimage_url( | 175 bool displayed; |
| 130 ConvertUTF8ToJavaString(env, url.spec())); | 176 if (manifest_.IsEmpty()) { |
| 131 ScopedJavaLocalRef<jobject> jimage = gfx::ConvertToJavaBitmap(bitmap); | 177 ScopedJavaLocalRef<jobject> jimage = gfx::ConvertToJavaBitmap(bitmap); |
| 132 bool displayed = Java_AppBannerManager_createBanner(env, | 178 ScopedJavaLocalRef<jstring> jimage_url( |
| 133 jobj.obj(), | 179 ConvertUTF8ToJavaString(env, url.spec())); |
| 134 jimage_url.obj(), | 180 |
| 135 jimage.obj()); | 181 displayed = Java_AppBannerManager_createBanner(env, |
| 182 jobj.obj(), |
| 183 jimage_url.obj(), |
| 184 jimage.obj()); |
| 185 } else { |
| 186 app_icon_.reset(new SkBitmap(*bitmap)); |
| 187 InfoBarService* service = InfoBarService::FromWebContents(web_contents()); |
| 188 displayed = AppBannerInfoBarDelegate::CreateForWebApp( |
| 189 service, |
| 190 this, |
| 191 manifest_.name.string(), |
| 192 manifest_.start_url) != NULL; |
| 193 } |
| 194 |
| 136 if (displayed) | 195 if (displayed) |
| 137 banners::TrackDisplayEvent(DISPLAY_CREATED); | 196 banners::TrackDisplayEvent(DISPLAY_CREATED); |
| 138 } else { | 197 } else { |
| 139 DVLOG(1) << "Failed to retrieve image: " << url; | 198 DVLOG(1) << "Failed to retrieve image: " << url; |
| 140 } | 199 } |
| 141 | 200 |
| 142 fetcher_.reset(); | 201 fetcher_.reset(); |
| 143 } | 202 } |
| 144 | 203 |
| 145 void AppBannerManager::OnDidRetrieveMetaTagContent( | 204 void AppBannerManager::OnDidRetrieveMetaTagContent( |
| (...skipping 28 matching lines...) Expand all Loading... |
| 174 Java_AppBannerManager_prepareBanner(env, | 233 Java_AppBannerManager_prepareBanner(env, |
| 175 jobj.obj(), | 234 jobj.obj(), |
| 176 jurl.obj(), | 235 jurl.obj(), |
| 177 jpackage.obj()); | 236 jpackage.obj()); |
| 178 } | 237 } |
| 179 | 238 |
| 180 bool AppBannerManager::FetchIcon(JNIEnv* env, | 239 bool AppBannerManager::FetchIcon(JNIEnv* env, |
| 181 jobject obj, | 240 jobject obj, |
| 182 jstring jimage_url) { | 241 jstring jimage_url) { |
| 183 std::string image_url = ConvertJavaStringToUTF8(env, jimage_url); | 242 std::string image_url = ConvertJavaStringToUTF8(env, jimage_url); |
| 243 return FetchIcon(GURL(image_url)); |
| 244 } |
| 245 |
| 246 bool AppBannerManager::FetchIcon(const GURL& image_url) { |
| 184 if (!web_contents()) | 247 if (!web_contents()) |
| 185 return false; | 248 return false; |
| 186 | 249 |
| 187 // Begin asynchronously fetching the app icon. | 250 // Begin asynchronously fetching the app icon. |
| 188 Profile* profile = | 251 Profile* profile = |
| 189 Profile::FromBrowserContext(web_contents()->GetBrowserContext()); | 252 Profile::FromBrowserContext(web_contents()->GetBrowserContext()); |
| 190 fetcher_.reset(new chrome::BitmapFetcher(GURL(image_url), this)); | 253 fetcher_.reset(new chrome::BitmapFetcher(image_url, this)); |
| 191 fetcher_.get()->Start( | 254 fetcher_.get()->Start( |
| 192 profile->GetRequestContext(), | 255 profile->GetRequestContext(), |
| 193 std::string(), | 256 std::string(), |
| 194 net::URLRequest::CLEAR_REFERRER_ON_TRANSITION_FROM_SECURE_TO_INSECURE, | 257 net::URLRequest::CLEAR_REFERRER_ON_TRANSITION_FROM_SECURE_TO_INSECURE, |
| 195 net::LOAD_NORMAL); | 258 net::LOAD_NORMAL); |
| 196 return true; | 259 return true; |
| 197 } | 260 } |
| 198 | 261 |
| 262 int AppBannerManager::GetPreferredIconSize() { |
| 263 JNIEnv* env = base::android::AttachCurrentThread(); |
| 264 ScopedJavaLocalRef<jobject> jobj = weak_java_banner_view_manager_.get(env); |
| 265 if (jobj.is_null()) |
| 266 return 0; |
| 267 |
| 268 return Java_AppBannerManager_getPreferredIconSize(env, jobj.obj()); |
| 269 } |
| 270 |
| 199 void RecordDismissEvent(JNIEnv* env, jclass clazz, jint metric) { | 271 void RecordDismissEvent(JNIEnv* env, jclass clazz, jint metric) { |
| 200 banners::TrackDismissEvent(metric); | 272 banners::TrackDismissEvent(metric); |
| 201 } | 273 } |
| 202 | 274 |
| 203 void RecordInstallEvent(JNIEnv* env, jclass clazz, jint metric) { | 275 void RecordInstallEvent(JNIEnv* env, jclass clazz, jint metric) { |
| 204 banners::TrackInstallEvent(metric); | 276 banners::TrackInstallEvent(metric); |
| 205 } | 277 } |
| 206 | 278 |
| 207 jlong Init(JNIEnv* env, jobject obj) { | 279 jlong Init(JNIEnv* env, jobject obj) { |
| 208 AppBannerManager* manager = new AppBannerManager(env, obj); | 280 AppBannerManager* manager = new AppBannerManager(env, obj); |
| 209 return reinterpret_cast<intptr_t>(manager); | 281 return reinterpret_cast<intptr_t>(manager); |
| 210 } | 282 } |
| 211 | 283 |
| 212 jboolean IsEnabled(JNIEnv* env, jclass clazz) { | 284 jboolean IsEnabled(JNIEnv* env, jclass clazz) { |
| 213 return base::CommandLine::ForCurrentProcess()->HasSwitch( | 285 return base::CommandLine::ForCurrentProcess()->HasSwitch( |
| 214 switches::kEnableAppInstallAlerts); | 286 switches::kEnableAppInstallAlerts); |
| 215 } | 287 } |
| 216 | 288 |
| 217 // Register native methods | 289 // Register native methods |
| 218 bool RegisterAppBannerManager(JNIEnv* env) { | 290 bool RegisterAppBannerManager(JNIEnv* env) { |
| 219 return RegisterNativesImpl(env); | 291 return RegisterNativesImpl(env); |
| 220 } | 292 } |
| 221 | 293 |
| 222 } // namespace banners | 294 } // namespace banners |
| OLD | NEW |