| OLD | NEW |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 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/webapk/webapk_update_data_fetcher.h" | 5 #include "chrome/browser/android/webapk/webapk_update_data_fetcher.h" |
| 6 | 6 |
| 7 #include <jni.h> | 7 #include <jni.h> |
| 8 #include <vector> | 8 #include <vector> |
| 9 | 9 |
| 10 #include "base/android/jni_array.h" | 10 #include "base/android/jni_array.h" |
| (...skipping 12 matching lines...) Expand all Loading... |
| 23 #include "url/gurl.h" | 23 #include "url/gurl.h" |
| 24 | 24 |
| 25 using base::android::JavaParamRef; | 25 using base::android::JavaParamRef; |
| 26 using base::android::ScopedJavaLocalRef; | 26 using base::android::ScopedJavaLocalRef; |
| 27 | 27 |
| 28 namespace { | 28 namespace { |
| 29 | 29 |
| 30 // Returns whether the given |url| is within the scope of the |scope| url. | 30 // Returns whether the given |url| is within the scope of the |scope| url. |
| 31 bool IsInScope(const GURL& url, const GURL& scope) { | 31 bool IsInScope(const GURL& url, const GURL& scope) { |
| 32 return base::StartsWith(url.spec(), scope.spec(), | 32 return base::StartsWith(url.spec(), scope.spec(), |
| 33 base::CompareCase::SENSITIVE); | 33 base::CompareCase::SENSITIVE); |
| 34 } | 34 } |
| 35 | 35 |
| 36 } // anonymous namespace | 36 } // anonymous namespace |
| 37 | 37 |
| 38 jlong Initialize(JNIEnv* env, | 38 jlong Initialize(JNIEnv* env, |
| 39 const JavaParamRef<jobject>& obj, | 39 const JavaParamRef<jobject>& obj, |
| 40 const JavaParamRef<jstring>& java_scope_url, | 40 const JavaParamRef<jstring>& java_scope_url, |
| 41 const JavaParamRef<jstring>& java_web_manifest_url) { | 41 const JavaParamRef<jstring>& java_web_manifest_url) { |
| 42 GURL scope(base::android::ConvertJavaStringToUTF8(env, java_scope_url)); | 42 GURL scope(base::android::ConvertJavaStringToUTF8(env, java_scope_url)); |
| 43 GURL web_manifest_url(base::android::ConvertJavaStringToUTF8( | 43 GURL web_manifest_url( |
| 44 env, java_web_manifest_url)); | 44 base::android::ConvertJavaStringToUTF8(env, java_web_manifest_url)); |
| 45 WebApkUpdateDataFetcher* fetcher = | 45 WebApkUpdateDataFetcher* fetcher = |
| 46 new WebApkUpdateDataFetcher(env, obj, scope, web_manifest_url); | 46 new WebApkUpdateDataFetcher(env, obj, scope, web_manifest_url); |
| 47 return reinterpret_cast<intptr_t>(fetcher); | 47 return reinterpret_cast<intptr_t>(fetcher); |
| 48 } | 48 } |
| 49 | 49 |
| 50 WebApkUpdateDataFetcher::WebApkUpdateDataFetcher( | 50 WebApkUpdateDataFetcher::WebApkUpdateDataFetcher(JNIEnv* env, |
| 51 JNIEnv* env, | 51 jobject obj, |
| 52 jobject obj, | 52 const GURL& scope, |
| 53 const GURL& scope, | 53 const GURL& web_manifest_url) |
| 54 const GURL& web_manifest_url) | |
| 55 : content::WebContentsObserver(nullptr), | 54 : content::WebContentsObserver(nullptr), |
| 56 scope_(scope), | 55 scope_(scope), |
| 57 web_manifest_url_(web_manifest_url), | 56 web_manifest_url_(web_manifest_url), |
| 58 is_initial_fetch_(false), | 57 is_initial_fetch_(false), |
| 59 info_(GURL()), | 58 info_(GURL()), |
| 60 weak_ptr_factory_(this) { | 59 weak_ptr_factory_(this) { |
| 61 java_ref_.Reset(env, obj); | 60 java_ref_.Reset(env, obj); |
| 62 } | 61 } |
| 63 | 62 |
| 64 WebApkUpdateDataFetcher::~WebApkUpdateDataFetcher() { | 63 WebApkUpdateDataFetcher::~WebApkUpdateDataFetcher() {} |
| 65 } | |
| 66 | 64 |
| 67 // static | 65 // static |
| 68 bool WebApkUpdateDataFetcher::Register(JNIEnv* env) { | 66 bool WebApkUpdateDataFetcher::Register(JNIEnv* env) { |
| 69 return RegisterNativesImpl(env); | 67 return RegisterNativesImpl(env); |
| 70 } | 68 } |
| 71 | 69 |
| 72 void WebApkUpdateDataFetcher::ReplaceWebContents( | 70 void WebApkUpdateDataFetcher::ReplaceWebContents( |
| 73 JNIEnv* env, | 71 JNIEnv* env, |
| 74 const JavaParamRef<jobject>& obj, | 72 const JavaParamRef<jobject>& obj, |
| 75 const JavaParamRef<jobject>& java_web_contents) { | 73 const JavaParamRef<jobject>& java_web_contents) { |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 115 params.ideal_primary_icon_size_in_px = | 113 params.ideal_primary_icon_size_in_px = |
| 116 ShortcutHelper::GetIdealHomescreenIconSizeInPx(); | 114 ShortcutHelper::GetIdealHomescreenIconSizeInPx(); |
| 117 params.minimum_primary_icon_size_in_px = | 115 params.minimum_primary_icon_size_in_px = |
| 118 ShortcutHelper::GetMinimumHomescreenIconSizeInPx(); | 116 ShortcutHelper::GetMinimumHomescreenIconSizeInPx(); |
| 119 params.check_installable = true; | 117 params.check_installable = true; |
| 120 params.fetch_valid_primary_icon = true; | 118 params.fetch_valid_primary_icon = true; |
| 121 InstallableManager::CreateForWebContents(web_contents()); | 119 InstallableManager::CreateForWebContents(web_contents()); |
| 122 InstallableManager* installable_manager = | 120 InstallableManager* installable_manager = |
| 123 InstallableManager::FromWebContents(web_contents()); | 121 InstallableManager::FromWebContents(web_contents()); |
| 124 installable_manager->GetData( | 122 installable_manager->GetData( |
| 125 params, | 123 params, base::Bind(&WebApkUpdateDataFetcher::OnDidGetInstallableData, |
| 126 base::Bind(&WebApkUpdateDataFetcher::OnDidGetInstallableData, | 124 weak_ptr_factory_.GetWeakPtr())); |
| 127 weak_ptr_factory_.GetWeakPtr())); | |
| 128 } | 125 } |
| 129 | 126 |
| 130 void WebApkUpdateDataFetcher::OnDidGetInstallableData( | 127 void WebApkUpdateDataFetcher::OnDidGetInstallableData( |
| 131 const InstallableData& data) { | 128 const InstallableData& data) { |
| 132 // Determine whether or not the manifest is WebAPK-compatible. There are 3 | 129 // Determine whether or not the manifest is WebAPK-compatible. There are 3 |
| 133 // cases: | 130 // cases: |
| 134 // 1. the site isn't installable. | 131 // 1. the site isn't installable. |
| 135 // 2. the URLs in the manifest expose passwords. | 132 // 2. the URLs in the manifest expose passwords. |
| 136 // 3. there is no manifest or the manifest is different to the one we're | 133 // 3. there is no manifest or the manifest is different to the one we're |
| 137 // expecting. | 134 // expecting. |
| 138 // For case 3, if the manifest is empty, it means the current WebContents | 135 // For case 3, if the manifest is empty, it means the current WebContents |
| 139 // doesn't associate with a Web Manifest. In such case, we ignore the empty | 136 // doesn't associate with a Web Manifest. In such case, we ignore the empty |
| 140 // manifest and continue observing the WebContents's loading until we find a | 137 // manifest and continue observing the WebContents's loading until we find a |
| 141 // page that links to the Web Manifest that we are looking for. | 138 // page that links to the Web Manifest that we are looking for. |
| 142 // If the manifest URL is different from the current one, we will continue | 139 // If the manifest URL is different from the current one, we will continue |
| 143 // observing too. It is based on our assumption that it is invalid for | 140 // observing too. It is based on our assumption that it is invalid for |
| 144 // web developers to change the Web Manifest location. When it does | 141 // web developers to change the Web Manifest location. When it does |
| 145 // change, we will treat the new Web Manifest as the one of another WebAPK. | 142 // change, we will treat the new Web Manifest as the one of another WebAPK. |
| 146 if (data.error_code != NO_ERROR_DETECTED || | 143 if (data.error_code != NO_ERROR_DETECTED || data.manifest.IsEmpty() || |
| 147 data.manifest.IsEmpty() || web_manifest_url_ != data.manifest_url || | 144 web_manifest_url_ != data.manifest_url || |
| 148 !AreWebManifestUrlsWebApkCompatible(data.manifest)) { | 145 !AreWebManifestUrlsWebApkCompatible(data.manifest)) { |
| 149 OnWebManifestNotWebApkCompatible(); | 146 OnWebManifestNotWebApkCompatible(); |
| 150 return; | 147 return; |
| 151 } | 148 } |
| 152 | 149 |
| 153 info_.UpdateFromManifest(data.manifest); | 150 info_.UpdateFromManifest(data.manifest); |
| 154 info_.manifest_url = data.manifest_url; | 151 info_.manifest_url = data.manifest_url; |
| 155 info_.best_icon_url = data.primary_icon_url; | 152 info_.best_primary_icon_url = data.primary_icon_url; |
| 156 best_icon_ = *data.primary_icon; | 153 best_primary_icon_ = *data.primary_icon; |
| 157 | 154 |
| 158 icon_hasher_.reset(new WebApkIconHasher()); | 155 icon_hasher_.reset(new WebApkIconHasher()); |
| 159 Profile* profile = | 156 Profile* profile = |
| 160 Profile::FromBrowserContext(web_contents()->GetBrowserContext()); | 157 Profile::FromBrowserContext(web_contents()->GetBrowserContext()); |
| 161 icon_hasher_->DownloadAndComputeMurmur2Hash( | 158 icon_hasher_->DownloadAndComputeMurmur2Hash( |
| 162 profile->GetRequestContext(), | 159 profile->GetRequestContext(), data.primary_icon_url, |
| 163 data.primary_icon_url, | |
| 164 base::Bind(&WebApkUpdateDataFetcher::OnGotIconMurmur2Hash, | 160 base::Bind(&WebApkUpdateDataFetcher::OnGotIconMurmur2Hash, |
| 165 weak_ptr_factory_.GetWeakPtr())); | 161 weak_ptr_factory_.GetWeakPtr())); |
| 166 } | 162 } |
| 167 | 163 |
| 168 void WebApkUpdateDataFetcher::OnGotIconMurmur2Hash( | 164 void WebApkUpdateDataFetcher::OnGotIconMurmur2Hash( |
| 169 const std::string& best_icon_murmur2_hash) { | 165 const std::string& best_primary_icon_murmur2_hash) { |
| 170 icon_hasher_.reset(); | 166 icon_hasher_.reset(); |
| 171 | 167 |
| 172 if (best_icon_murmur2_hash.empty()) { | 168 if (best_primary_icon_murmur2_hash.empty()) { |
| 173 OnWebManifestNotWebApkCompatible(); | 169 OnWebManifestNotWebApkCompatible(); |
| 174 return; | 170 return; |
| 175 } | 171 } |
| 176 | 172 |
| 177 OnDataAvailable(info_, best_icon_murmur2_hash, best_icon_); | 173 OnDataAvailable(info_, best_primary_icon_murmur2_hash, best_primary_icon_); |
| 178 } | 174 } |
| 179 | 175 |
| 180 void WebApkUpdateDataFetcher::OnDataAvailable( | 176 void WebApkUpdateDataFetcher::OnDataAvailable( |
| 181 const ShortcutInfo& info, | 177 const ShortcutInfo& info, |
| 182 const std::string& best_icon_murmur2_hash, | 178 const std::string& best_primary_icon_murmur2_hash, |
| 183 const SkBitmap& best_icon_bitmap) { | 179 const SkBitmap& best_primary_icon) { |
| 184 JNIEnv* env = base::android::AttachCurrentThread(); | 180 JNIEnv* env = base::android::AttachCurrentThread(); |
| 185 | 181 |
| 186 ScopedJavaLocalRef<jstring> java_url = | 182 ScopedJavaLocalRef<jstring> java_url = |
| 187 base::android::ConvertUTF8ToJavaString(env, info.url.spec()); | 183 base::android::ConvertUTF8ToJavaString(env, info.url.spec()); |
| 188 ScopedJavaLocalRef<jstring> java_scope = | 184 ScopedJavaLocalRef<jstring> java_scope = |
| 189 base::android::ConvertUTF8ToJavaString(env, info.scope.spec()); | 185 base::android::ConvertUTF8ToJavaString(env, info.scope.spec()); |
| 190 ScopedJavaLocalRef<jstring> java_name = | 186 ScopedJavaLocalRef<jstring> java_name = |
| 191 base::android::ConvertUTF16ToJavaString(env, info.name); | 187 base::android::ConvertUTF16ToJavaString(env, info.name); |
| 192 ScopedJavaLocalRef<jstring> java_short_name = | 188 ScopedJavaLocalRef<jstring> java_short_name = |
| 193 base::android::ConvertUTF16ToJavaString(env, info.short_name); | 189 base::android::ConvertUTF16ToJavaString(env, info.short_name); |
| 194 ScopedJavaLocalRef<jstring> java_best_icon_url = | 190 ScopedJavaLocalRef<jstring> java_best_primary_icon_url = |
| 195 base::android::ConvertUTF8ToJavaString(env, info.best_icon_url.spec()); | 191 base::android::ConvertUTF8ToJavaString(env, |
| 196 ScopedJavaLocalRef<jstring> java_best_icon_murmur2_hash = | 192 info.best_primary_icon_url.spec()); |
| 197 base::android::ConvertUTF8ToJavaString(env, best_icon_murmur2_hash); | 193 ScopedJavaLocalRef<jstring> java_best_primary_icon_murmur2_hash = |
| 198 ScopedJavaLocalRef<jobject> java_best_bitmap = | 194 base::android::ConvertUTF8ToJavaString(env, |
| 199 gfx::ConvertToJavaBitmap(&best_icon_bitmap); | 195 best_primary_icon_murmur2_hash); |
| 196 ScopedJavaLocalRef<jobject> java_best_primary_icon = |
| 197 gfx::ConvertToJavaBitmap(&best_primary_icon); |
| 200 | 198 |
| 201 ScopedJavaLocalRef<jobjectArray> java_icon_urls = | 199 ScopedJavaLocalRef<jobjectArray> java_icon_urls = |
| 202 base::android::ToJavaArrayOfStrings(env, info.icon_urls); | 200 base::android::ToJavaArrayOfStrings(env, info.icon_urls); |
| 203 | 201 |
| 204 Java_WebApkUpdateDataFetcher_onDataAvailable( | 202 Java_WebApkUpdateDataFetcher_onDataAvailable( |
| 205 env, java_ref_, java_url, java_scope, java_name, java_short_name, | 203 env, java_ref_, java_url, java_scope, java_name, java_short_name, |
| 206 java_best_icon_url, java_best_icon_murmur2_hash, java_best_bitmap, | 204 java_best_primary_icon_url, java_best_primary_icon_murmur2_hash, |
| 207 java_icon_urls, info.display, info.orientation, info.theme_color, | 205 java_best_primary_icon, java_icon_urls, info.display, info.orientation, |
| 208 info.background_color); | 206 info.theme_color, info.background_color); |
| 209 } | 207 } |
| 210 | 208 |
| 211 void WebApkUpdateDataFetcher::OnWebManifestNotWebApkCompatible() { | 209 void WebApkUpdateDataFetcher::OnWebManifestNotWebApkCompatible() { |
| 212 if (!is_initial_fetch_) | 210 if (!is_initial_fetch_) |
| 213 return; | 211 return; |
| 214 | 212 |
| 215 Java_WebApkUpdateDataFetcher_onWebManifestForInitialUrlNotWebApkCompatible( | 213 Java_WebApkUpdateDataFetcher_onWebManifestForInitialUrlNotWebApkCompatible( |
| 216 base::android::AttachCurrentThread(), java_ref_); | 214 base::android::AttachCurrentThread(), java_ref_); |
| 217 } | 215 } |
| OLD | NEW |