| 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" |
| (...skipping 17 matching lines...) Expand all Loading... |
| 28 #include "content/public/browser/render_frame_host.h" | 28 #include "content/public/browser/render_frame_host.h" |
| 29 #include "content/public/browser/web_contents.h" | 29 #include "content/public/browser/web_contents.h" |
| 30 #include "content/public/common/frame_navigate_params.h" | 30 #include "content/public/common/frame_navigate_params.h" |
| 31 #include "content/public/common/manifest.h" | 31 #include "content/public/common/manifest.h" |
| 32 #include "jni/AppBannerManager_jni.h" | 32 #include "jni/AppBannerManager_jni.h" |
| 33 #include "net/base/load_flags.h" | 33 #include "net/base/load_flags.h" |
| 34 #include "ui/gfx/android/java_bitmap.h" | 34 #include "ui/gfx/android/java_bitmap.h" |
| 35 #include "ui/gfx/screen.h" | 35 #include "ui/gfx/screen.h" |
| 36 | 36 |
| 37 using base::android::ConvertJavaStringToUTF8; | 37 using base::android::ConvertJavaStringToUTF8; |
| 38 using base::android::ConvertJavaStringToUTF16; |
| 38 using base::android::ConvertUTF8ToJavaString; | 39 using base::android::ConvertUTF8ToJavaString; |
| 39 using base::android::ConvertUTF16ToJavaString; | 40 using base::android::ConvertUTF16ToJavaString; |
| 40 | 41 |
| 41 namespace { | 42 namespace { |
| 42 const char kBannerTag[] = "google-play-id"; | 43 const char kBannerTag[] = "google-play-id"; |
| 43 } | 44 } |
| 44 | 45 |
| 45 namespace banners { | 46 namespace banners { |
| 46 | 47 |
| 47 AppBannerManager::AppBannerManager(JNIEnv* env, jobject obj) | 48 AppBannerManager::AppBannerManager(JNIEnv* env, jobject obj) |
| (...skipping 12 matching lines...) Expand all Loading... |
| 60 jstring jpackage) { | 61 jstring jpackage) { |
| 61 if (!web_contents()) | 62 if (!web_contents()) |
| 62 return; | 63 return; |
| 63 | 64 |
| 64 GURL url(ConvertJavaStringToUTF8(env, jurl)); | 65 GURL url(ConvertJavaStringToUTF8(env, jurl)); |
| 65 std::string package_name = ConvertJavaStringToUTF8(env, jpackage); | 66 std::string package_name = ConvertJavaStringToUTF8(env, jpackage); |
| 66 AppBannerSettingsHelper::Block(web_contents(), url, package_name); | 67 AppBannerSettingsHelper::Block(web_contents(), url, package_name); |
| 67 } | 68 } |
| 68 | 69 |
| 69 void AppBannerManager::Block() const { | 70 void AppBannerManager::Block() const { |
| 70 if (!web_contents() || manifest_.IsEmpty()) | |
| 71 return; | |
| 72 | |
| 73 AppBannerSettingsHelper::Block(web_contents(), | |
| 74 web_contents()->GetURL(), | |
| 75 manifest_.start_url.spec()); | |
| 76 } | |
| 77 | |
| 78 void AppBannerManager::Install() const { | |
| 79 if (!web_contents()) | 71 if (!web_contents()) |
| 80 return; | 72 return; |
| 81 | 73 |
| 82 if (!manifest_.IsEmpty()) { | 74 if (!web_app_data_.IsEmpty()) { |
| 83 InstallManifestApp(manifest_, *app_icon_.get()); | 75 AppBannerSettingsHelper::Block(web_contents(), |
| 76 web_contents()->GetURL(), |
| 77 web_app_data_.start_url.spec()); |
| 84 } | 78 } |
| 85 } | 79 } |
| 86 | 80 |
| 81 void AppBannerManager::OnInfoBarDestroyed() { |
| 82 weak_infobar_ptr_ = nullptr; |
| 83 } |
| 84 |
| 85 bool AppBannerManager::OnButtonClicked() const { |
| 86 if (!web_contents()) |
| 87 return true; |
| 88 |
| 89 if (!web_app_data_.IsEmpty()) { |
| 90 InstallManifestApp(web_app_data_, *app_icon_.get()); |
| 91 return true; |
| 92 } |
| 93 |
| 94 return true; |
| 95 } |
| 96 |
| 97 base::string16 AppBannerManager::GetTitle() const { |
| 98 return app_title_; |
| 99 } |
| 100 |
| 87 gfx::Image AppBannerManager::GetIcon() const { | 101 gfx::Image AppBannerManager::GetIcon() const { |
| 88 return gfx::Image::CreateFrom1xBitmap(*app_icon_.get()); | 102 return gfx::Image::CreateFrom1xBitmap(*app_icon_.get()); |
| 89 } | 103 } |
| 90 | 104 |
| 91 void AppBannerManager::ReplaceWebContents(JNIEnv* env, | 105 void AppBannerManager::ReplaceWebContents(JNIEnv* env, |
| 92 jobject obj, | 106 jobject obj, |
| 93 jobject jweb_contents) { | 107 jobject jweb_contents) { |
| 94 content::WebContents* web_contents = | 108 content::WebContents* web_contents = |
| 95 content::WebContents::FromJavaWebContents(jweb_contents); | 109 content::WebContents::FromJavaWebContents(jweb_contents); |
| 96 Observe(web_contents); | 110 Observe(web_contents); |
| 97 } | 111 } |
| 98 | 112 |
| 99 void AppBannerManager::DidNavigateMainFrame( | 113 void AppBannerManager::DidNavigateMainFrame( |
| 100 const content::LoadCommittedDetails& details, | 114 const content::LoadCommittedDetails& details, |
| 101 const content::FrameNavigateParams& params) { | 115 const content::FrameNavigateParams& params) { |
| 102 // Clear current state. | 116 // Clear current state. |
| 103 fetcher_.reset(); | 117 fetcher_.reset(); |
| 104 manifest_ = content::Manifest(); | 118 app_title_ = base::string16(); |
| 105 app_icon_.reset(); | 119 app_icon_.reset(); |
| 106 | 120 web_app_data_ = content::Manifest(); |
| 107 // Get rid of the current banner. | |
| 108 JNIEnv* env = base::android::AttachCurrentThread(); | |
| 109 ScopedJavaLocalRef<jobject> jobj = weak_java_banner_view_manager_.get(env); | |
| 110 if (jobj.is_null()) | |
| 111 return; | |
| 112 Java_AppBannerManager_dismissCurrentBanner(env, jobj.obj(), DISMISS_NAVIGATE); | |
| 113 } | 121 } |
| 114 | 122 |
| 115 void AppBannerManager::DidFinishLoad( | 123 void AppBannerManager::DidFinishLoad( |
| 116 content::RenderFrameHost* render_frame_host, | 124 content::RenderFrameHost* render_frame_host, |
| 117 const GURL& validated_url) { | 125 const GURL& validated_url) { |
| 118 if (render_frame_host->GetParent()) | 126 if (render_frame_host->GetParent()) |
| 119 return; | 127 return; |
| 120 validated_url_ = validated_url; | 128 validated_url_ = validated_url; |
| 121 | 129 |
| 122 // See if the page has a manifest. Using Unretained(this) here is safe as the | 130 // See if the page has a manifest. Using Unretained(this) here is safe as the |
| (...skipping 14 matching lines...) Expand all Loading... |
| 137 Send(new ChromeViewMsg_RetrieveMetaTagContent(routing_id(), | 145 Send(new ChromeViewMsg_RetrieveMetaTagContent(routing_id(), |
| 138 validated_url_, | 146 validated_url_, |
| 139 kBannerTag)); | 147 kBannerTag)); |
| 140 return; | 148 return; |
| 141 } | 149 } |
| 142 | 150 |
| 143 // TODO(benwells): Check triggering parameters here and if there is a meta | 151 // TODO(benwells): Check triggering parameters here and if there is a meta |
| 144 // tag. | 152 // tag. |
| 145 | 153 |
| 146 // Create an infobar to promote the manifest's app. | 154 // Create an infobar to promote the manifest's app. |
| 147 manifest_ = manifest; | 155 web_app_data_ = manifest; |
| 148 | 156 app_title_ = web_app_data_.name.string(); |
| 149 GURL icon_url = | 157 GURL icon_url = |
| 150 ManifestIconSelector::FindBestMatchingIcon( | 158 ManifestIconSelector::FindBestMatchingIcon( |
| 151 manifest.icons, | 159 manifest.icons, |
| 152 GetPreferredIconSize(), | 160 GetPreferredIconSize(), |
| 153 gfx::Screen::GetScreenFor(web_contents()->GetNativeView())); | 161 gfx::Screen::GetScreenFor(web_contents()->GetNativeView())); |
| 154 if (icon_url.is_empty()) | 162 if (icon_url.is_empty()) |
| 155 return; | 163 return; |
| 156 | 164 |
| 157 FetchIcon(icon_url); | 165 FetchIcon(icon_url); |
| 158 } | 166 } |
| 159 | 167 |
| 160 bool AppBannerManager::OnMessageReceived(const IPC::Message& message) { | 168 bool AppBannerManager::OnMessageReceived(const IPC::Message& message) { |
| 161 bool handled = true; | 169 bool handled = true; |
| 162 IPC_BEGIN_MESSAGE_MAP(AppBannerManager, message) | 170 IPC_BEGIN_MESSAGE_MAP(AppBannerManager, message) |
| 163 IPC_MESSAGE_HANDLER(ChromeViewHostMsg_DidRetrieveMetaTagContent, | 171 IPC_MESSAGE_HANDLER(ChromeViewHostMsg_DidRetrieveMetaTagContent, |
| 164 OnDidRetrieveMetaTagContent) | 172 OnDidRetrieveMetaTagContent) |
| 165 IPC_MESSAGE_UNHANDLED(handled = false) | 173 IPC_MESSAGE_UNHANDLED(handled = false) |
| 166 IPC_END_MESSAGE_MAP() | 174 IPC_END_MESSAGE_MAP() |
| 167 return handled; | 175 return handled; |
| 168 } | 176 } |
| 169 | 177 |
| 170 void AppBannerManager::OnFetchComplete(const GURL url, const SkBitmap* bitmap) { | 178 void AppBannerManager::OnFetchComplete(const GURL url, const SkBitmap* bitmap) { |
| 171 if (bitmap) { | 179 fetcher_.reset(); |
| 172 JNIEnv* env = base::android::AttachCurrentThread(); | 180 if (!bitmap || url != app_icon_url_) { |
| 173 | |
| 174 ScopedJavaLocalRef<jobject> jobj = weak_java_banner_view_manager_.get(env); | |
| 175 if (jobj.is_null()) | |
| 176 return; | |
| 177 | |
| 178 bool displayed; | |
| 179 if (manifest_.IsEmpty()) { | |
| 180 ScopedJavaLocalRef<jobject> jimage = gfx::ConvertToJavaBitmap(bitmap); | |
| 181 ScopedJavaLocalRef<jstring> jimage_url( | |
| 182 ConvertUTF8ToJavaString(env, url.spec())); | |
| 183 | |
| 184 displayed = Java_AppBannerManager_createBanner(env, | |
| 185 jobj.obj(), | |
| 186 jimage_url.obj(), | |
| 187 jimage.obj()); | |
| 188 } else { | |
| 189 app_icon_.reset(new SkBitmap(*bitmap)); | |
| 190 InfoBarService* service = InfoBarService::FromWebContents(web_contents()); | |
| 191 displayed = AppBannerInfoBarDelegate::CreateForWebApp( | |
| 192 service, | |
| 193 this, | |
| 194 manifest_.name.string(), | |
| 195 manifest_.start_url) != NULL; | |
| 196 } | |
| 197 | |
| 198 if (displayed) | |
| 199 banners::TrackDisplayEvent(DISPLAY_CREATED); | |
| 200 } else { | |
| 201 DVLOG(1) << "Failed to retrieve image: " << url; | 181 DVLOG(1) << "Failed to retrieve image: " << url; |
| 182 return; |
| 202 } | 183 } |
| 203 | 184 |
| 204 fetcher_.reset(); | 185 JNIEnv* env = base::android::AttachCurrentThread(); |
| 186 ScopedJavaLocalRef<jobject> jobj = weak_java_banner_view_manager_.get(env); |
| 187 if (jobj.is_null()) |
| 188 return; |
| 189 |
| 190 app_icon_.reset(new SkBitmap(*bitmap)); |
| 191 InfoBarService* service = InfoBarService::FromWebContents(web_contents()); |
| 192 |
| 193 weak_infobar_ptr_ = nullptr; |
| 194 if (!web_app_data_.IsEmpty()){ |
| 195 weak_infobar_ptr_ = AppBannerInfoBarDelegate::CreateForWebApp( |
| 196 service, |
| 197 this, |
| 198 web_app_data_.start_url); |
| 199 } |
| 200 |
| 201 if (weak_infobar_ptr_ != nullptr) |
| 202 banners::TrackDisplayEvent(DISPLAY_CREATED); |
| 205 } | 203 } |
| 206 | 204 |
| 207 void AppBannerManager::OnDidRetrieveMetaTagContent( | 205 void AppBannerManager::OnDidRetrieveMetaTagContent( |
| 208 bool success, | 206 bool success, |
| 209 const std::string& tag_name, | 207 const std::string& tag_name, |
| 210 const std::string& tag_content, | 208 const std::string& tag_content, |
| 211 const GURL& expected_url) { | 209 const GURL& expected_url) { |
| 212 DCHECK(web_contents()); | 210 DCHECK(web_contents()); |
| 213 if (!success || tag_name != kBannerTag || validated_url_ != expected_url || | 211 if (!success || tag_name != kBannerTag || validated_url_ != expected_url || |
| 214 tag_content.size() >= chrome::kMaxMetaTagAttributeLength) { | 212 tag_content.size() >= chrome::kMaxMetaTagAttributeLength) { |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 252 | 250 |
| 253 // Begin asynchronously fetching the app icon. | 251 // Begin asynchronously fetching the app icon. |
| 254 Profile* profile = | 252 Profile* profile = |
| 255 Profile::FromBrowserContext(web_contents()->GetBrowserContext()); | 253 Profile::FromBrowserContext(web_contents()->GetBrowserContext()); |
| 256 fetcher_.reset(new chrome::BitmapFetcher(image_url, this)); | 254 fetcher_.reset(new chrome::BitmapFetcher(image_url, this)); |
| 257 fetcher_.get()->Start( | 255 fetcher_.get()->Start( |
| 258 profile->GetRequestContext(), | 256 profile->GetRequestContext(), |
| 259 std::string(), | 257 std::string(), |
| 260 net::URLRequest::CLEAR_REFERRER_ON_TRANSITION_FROM_SECURE_TO_INSECURE, | 258 net::URLRequest::CLEAR_REFERRER_ON_TRANSITION_FROM_SECURE_TO_INSECURE, |
| 261 net::LOAD_NORMAL); | 259 net::LOAD_NORMAL); |
| 260 app_icon_url_ = image_url; |
| 262 return true; | 261 return true; |
| 263 } | 262 } |
| 264 | 263 |
| 265 int AppBannerManager::GetPreferredIconSize() { | 264 int AppBannerManager::GetPreferredIconSize() { |
| 266 JNIEnv* env = base::android::AttachCurrentThread(); | 265 JNIEnv* env = base::android::AttachCurrentThread(); |
| 267 ScopedJavaLocalRef<jobject> jobj = weak_java_banner_view_manager_.get(env); | 266 ScopedJavaLocalRef<jobject> jobj = weak_java_banner_view_manager_.get(env); |
| 268 if (jobj.is_null()) | 267 if (jobj.is_null()) |
| 269 return 0; | 268 return 0; |
| 270 | 269 |
| 271 return Java_AppBannerManager_getPreferredIconSize(env, jobj.obj()); | 270 return Java_AppBannerManager_getPreferredIconSize(env, jobj.obj()); |
| (...skipping 30 matching lines...) Expand all Loading... |
| 302 return base::CommandLine::ForCurrentProcess()->HasSwitch( | 301 return base::CommandLine::ForCurrentProcess()->HasSwitch( |
| 303 switches::kEnableAppInstallAlerts); | 302 switches::kEnableAppInstallAlerts); |
| 304 } | 303 } |
| 305 | 304 |
| 306 // Register native methods | 305 // Register native methods |
| 307 bool RegisterAppBannerManager(JNIEnv* env) { | 306 bool RegisterAppBannerManager(JNIEnv* env) { |
| 308 return RegisterNativesImpl(env); | 307 return RegisterNativesImpl(env); |
| 309 } | 308 } |
| 310 | 309 |
| 311 } // namespace banners | 310 } // namespace banners |
| OLD | NEW |