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

Side by Side Diff: chrome/browser/android/webapk/manifest_upgrade_detector_fetcher.cc

Issue 2331773002: Take Murmur2 hash of untransformed icon when creating WebAPK part 2/2 (Closed)
Patch Set: Created 4 years, 3 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 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/manifest_upgrade_detector_fetcher.h" 5 #include "chrome/browser/android/webapk/manifest_upgrade_detector_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_string.h" 10 #include "base/android/jni_string.h"
11 #include "chrome/browser/android/shortcut_helper.h" 11 #include "chrome/browser/android/shortcut_helper.h"
12 #include "chrome/browser/android/shortcut_info.h" 12 #include "chrome/browser/android/webapk/webapk_icon_hasher.h"
13 #include "chrome/browser/android/webapk/webapk_web_manifest_checker.h" 13 #include "chrome/browser/android/webapk/webapk_web_manifest_checker.h"
14 #include "chrome/browser/installable/installable_manager.h" 14 #include "chrome/browser/installable/installable_manager.h"
15 #include "chrome/browser/profiles/profile.h"
15 #include "content/public/browser/render_frame_host.h" 16 #include "content/public/browser/render_frame_host.h"
16 #include "content/public/browser/web_contents.h" 17 #include "content/public/browser/web_contents.h"
17 #include "content/public/common/manifest.h" 18 #include "content/public/common/manifest.h"
18 #include "jni/ManifestUpgradeDetectorFetcher_jni.h" 19 #include "jni/ManifestUpgradeDetectorFetcher_jni.h"
19 #include "third_party/smhasher/src/MurmurHash2.h" 20 #include "third_party/smhasher/src/MurmurHash2.h"
20 #include "ui/gfx/android/java_bitmap.h" 21 #include "ui/gfx/android/java_bitmap.h"
21 #include "ui/gfx/codec/png_codec.h" 22 #include "ui/gfx/codec/png_codec.h"
22 #include "url/gurl.h" 23 #include "url/gurl.h"
23 24
24 using base::android::JavaParamRef; 25 using base::android::JavaParamRef;
25 using base::android::ScopedJavaLocalRef; 26 using base::android::ScopedJavaLocalRef;
26 27
27 namespace { 28 namespace {
28 29
29 // The seed to use for the murmur2 hash.
30 const uint64_t kMurmur2HashSeed = 0;
31
32 // Computes a murmur2 hash of |bitmap|'s PNG encoded bytes.
33 uint64_t ComputeBitmapHash(const SkBitmap& bitmap) {
34 std::vector<unsigned char> png_bytes;
35 gfx::PNGCodec::EncodeBGRASkBitmap(bitmap, false, &png_bytes);
36 return MurmurHash64B(&png_bytes.front(), png_bytes.size(), kMurmur2HashSeed);
37 }
38
39 // 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.
40 bool IsInScope(const GURL& url, const GURL& scope) { 31 bool IsInScope(const GURL& url, const GURL& scope) {
41 return base::StartsWith(url.spec(), scope.spec(), 32 return base::StartsWith(url.spec(), scope.spec(),
42 base::CompareCase::SENSITIVE); 33 base::CompareCase::SENSITIVE);
43 } 34 }
44 35
45 } // anonymous namespace 36 } // anonymous namespace
46 37
47 jlong Initialize(JNIEnv* env, 38 jlong Initialize(JNIEnv* env,
48 const JavaParamRef<jobject>& obj, 39 const JavaParamRef<jobject>& obj,
49 const JavaParamRef<jstring>& java_scope_url, 40 const JavaParamRef<jstring>& java_scope_url,
50 const JavaParamRef<jstring>& java_web_manifest_url) { 41 const JavaParamRef<jstring>& java_web_manifest_url) {
51 GURL scope(base::android::ConvertJavaStringToUTF8(env, java_scope_url)); 42 GURL scope(base::android::ConvertJavaStringToUTF8(env, java_scope_url));
52 GURL web_manifest_url(base::android::ConvertJavaStringToUTF8( 43 GURL web_manifest_url(base::android::ConvertJavaStringToUTF8(
53 env, java_web_manifest_url)); 44 env, java_web_manifest_url));
54 ManifestUpgradeDetectorFetcher* fetcher = 45 ManifestUpgradeDetectorFetcher* fetcher =
55 new ManifestUpgradeDetectorFetcher(env, obj, scope, web_manifest_url); 46 new ManifestUpgradeDetectorFetcher(env, obj, scope, web_manifest_url);
56 return reinterpret_cast<intptr_t>(fetcher); 47 return reinterpret_cast<intptr_t>(fetcher);
57 } 48 }
58 49
59 ManifestUpgradeDetectorFetcher::ManifestUpgradeDetectorFetcher( 50 ManifestUpgradeDetectorFetcher::ManifestUpgradeDetectorFetcher(
60 JNIEnv* env, 51 JNIEnv* env,
61 jobject obj, 52 jobject obj,
62 const GURL& scope, 53 const GURL& scope,
63 const GURL& web_manifest_url) 54 const GURL& web_manifest_url)
64 : content::WebContentsObserver(nullptr), 55 : content::WebContentsObserver(nullptr),
65 scope_(scope), 56 scope_(scope),
66 web_manifest_url_(web_manifest_url), 57 web_manifest_url_(web_manifest_url),
58 info_(GURL()),
67 weak_ptr_factory_(this) { 59 weak_ptr_factory_(this) {
68 java_ref_.Reset(env, obj); 60 java_ref_.Reset(env, obj);
69 } 61 }
70 62
71 ManifestUpgradeDetectorFetcher::~ManifestUpgradeDetectorFetcher() { 63 ManifestUpgradeDetectorFetcher::~ManifestUpgradeDetectorFetcher() {
72 } 64 }
73 65
74 // static 66 // static
75 bool ManifestUpgradeDetectorFetcher::Register(JNIEnv* env) { 67 bool ManifestUpgradeDetectorFetcher::Register(JNIEnv* env) {
76 return RegisterNativesImpl(env); 68 return RegisterNativesImpl(env);
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
127 // associate with a Web Manifest. In such case, we ignore the empty manifest 119 // associate with a Web Manifest. In such case, we ignore the empty manifest
128 // and continue observing the WebContents's loading until we find a page that 120 // and continue observing the WebContents's loading until we find a page that
129 // links to the Web Manifest that we are looking for. 121 // links to the Web Manifest that we are looking for.
130 // If the manifest URL is different from the current one, we will continue 122 // If the manifest URL is different from the current one, we will continue
131 // observing too. It is based on our assumption that it is invalid for 123 // observing too. It is based on our assumption that it is invalid for
132 // web developers to change the Web Manifest location. When it does 124 // web developers to change the Web Manifest location. When it does
133 // change, we will treat the new Web Manifest as the one of another WebAPK. 125 // change, we will treat the new Web Manifest as the one of another WebAPK.
134 if (data.manifest.IsEmpty() || web_manifest_url_ != data.manifest_url) 126 if (data.manifest.IsEmpty() || web_manifest_url_ != data.manifest_url)
135 return; 127 return;
136 128
137 // TODO(pkotwicz): Tell Java side that the Web Manifest was fetched but the 129 if (data.error_code != NO_ERROR_DETECTED ||
Xi Han 2016/09/12 19:19:05 Why don't check data.is_installable?
pkotwicz 2016/09/12 19:43:59 Because data.is_installable is true if there is a
Xi Han 2016/09/12 19:58:49 Got it, thanks!
138 // Web Manifest is not WebAPK-compatible. (http://crbug.com/639536)
139 if (!data.is_installable ||
140 !AreWebManifestUrlsWebApkCompatible(data.manifest)) { 130 !AreWebManifestUrlsWebApkCompatible(data.manifest)) {
131 OnGotNonWebApkCompatibleManifest();
141 return; 132 return;
142 } 133 }
143 134
144 ShortcutInfo info(GURL::EmptyGURL()); 135 info_.UpdateFromManifest(data.manifest);
145 info.UpdateFromManifest(data.manifest); 136 info_.manifest_url = data.manifest_url;
146 info.manifest_url = data.manifest_url; 137 info_.icon_url = data.icon_url;
147 info.icon_url = data.icon_url; 138 icon_ = *data.icon;
148 OnDataAvailable(info, (data.icon ? *data.icon : SkBitmap())); 139
140 icon_hasher_.reset(new WebApkIconHasher());
141 Profile* profile =
142 Profile::FromBrowserContext(web_contents()->GetBrowserContext());
143 icon_hasher_->DownloadAndComputeMurmur2Hash(
dominickn 2016/09/13 01:09:35 We already have the parsed icon in data.icon and i
pkotwicz 2016/09/13 22:23:33 An SkBitmap is a decoded icon. The SkBitmap does n
dominickn 2016/09/14 06:58:43 Acknowledged. I was worried that would be the case
144 profile->GetRequestContext(),
145 data.icon_url,
146 base::Bind(&ManifestUpgradeDetectorFetcher::OnGotIconMurmur2Hash,
147 weak_ptr_factory_.GetWeakPtr()));
149 } 148 }
150 149
151 void ManifestUpgradeDetectorFetcher::OnDataAvailable( 150 void ManifestUpgradeDetectorFetcher::OnGotIconMurmur2Hash(
151 const std::string& icon_murmur2_hash) {
152 icon_hasher_.reset();
153
154 if (icon_murmur2_hash.empty()) {
155 OnGotNonWebApkCompatibleManifest();
156 return;
157 }
158
159 OnGotWebApkCompatibleManifest(info_, icon_murmur2_hash, icon_);
160 }
161
162 void ManifestUpgradeDetectorFetcher::OnGotWebApkCompatibleManifest(
152 const ShortcutInfo& info, 163 const ShortcutInfo& info,
164 const std::string& icon_murmur2_hash,
153 const SkBitmap& icon_bitmap) { 165 const SkBitmap& icon_bitmap) {
154 JNIEnv* env = base::android::AttachCurrentThread(); 166 JNIEnv* env = base::android::AttachCurrentThread();
155 167
156 ScopedJavaLocalRef<jstring> java_url = 168 ScopedJavaLocalRef<jstring> java_url =
157 base::android::ConvertUTF8ToJavaString(env, info.url.spec()); 169 base::android::ConvertUTF8ToJavaString(env, info.url.spec());
158 ScopedJavaLocalRef<jstring> java_scope = 170 ScopedJavaLocalRef<jstring> java_scope =
159 base::android::ConvertUTF8ToJavaString(env, info.scope.spec()); 171 base::android::ConvertUTF8ToJavaString(env, info.scope.spec());
160 ScopedJavaLocalRef<jstring> java_name = 172 ScopedJavaLocalRef<jstring> java_name =
161 base::android::ConvertUTF16ToJavaString(env, info.name); 173 base::android::ConvertUTF16ToJavaString(env, info.name);
162 ScopedJavaLocalRef<jstring> java_short_name = 174 ScopedJavaLocalRef<jstring> java_short_name =
163 base::android::ConvertUTF16ToJavaString(env, info.short_name); 175 base::android::ConvertUTF16ToJavaString(env, info.short_name);
164 ScopedJavaLocalRef<jstring> java_icon_url = 176 ScopedJavaLocalRef<jstring> java_icon_url =
165 base::android::ConvertUTF8ToJavaString(env, info.icon_url.spec()); 177 base::android::ConvertUTF8ToJavaString(env, info.icon_url.spec());
166 ScopedJavaLocalRef<jobject> java_bitmap; 178 ScopedJavaLocalRef<jstring> java_icon_murmur2_hash =
167 uint64_t icon_murmur2_hash = 0; 179 base::android::ConvertUTF8ToJavaString(env, icon_murmur2_hash);
168 if (icon_bitmap.getSize()) { 180 ScopedJavaLocalRef<jobject> java_bitmap =
169 java_bitmap = gfx::ConvertToJavaBitmap(&icon_bitmap); 181 gfx::ConvertToJavaBitmap(&icon_bitmap);
170 // TODO(pkotwicz): Get hash of untransformed icon's bytes (with no
171 // encoding/decoding).
172 icon_murmur2_hash = ComputeBitmapHash(icon_bitmap);
173 }
174 182
175 Java_ManifestUpgradeDetectorFetcher_onDataAvailable( 183 Java_ManifestUpgradeDetectorFetcher_onGotWebApkCompatibleManifest(
176 env, java_ref_, java_url, java_scope, java_name, java_short_name, 184 env, java_ref_, java_url, java_scope, java_name, java_short_name,
177 java_icon_url, icon_murmur2_hash, java_bitmap, info.display, 185 java_icon_url, java_icon_murmur2_hash, java_bitmap, info.display,
178 info.orientation, info.theme_color, info.background_color); 186 info.orientation, info.theme_color, info.background_color);
179 } 187 }
188
189 void ManifestUpgradeDetectorFetcher::OnGotNonWebApkCompatibleManifest() {
190 JNIEnv* env = base::android::AttachCurrentThread();
191 Java_ManifestUpgradeDetectorFetcher_onGotNonWebApkCompatibleManifest(
192 env, java_ref_);
193 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698