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/manifest_upgrade_detector_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" |
11 #include "base/android/jni_string.h" | 11 #include "base/android/jni_string.h" |
12 #include "chrome/browser/android/shortcut_helper.h" | 12 #include "chrome/browser/android/shortcut_helper.h" |
13 #include "chrome/browser/android/webapk/webapk_icon_hasher.h" | 13 #include "chrome/browser/android/webapk/webapk_icon_hasher.h" |
14 #include "chrome/browser/android/webapk/webapk_web_manifest_checker.h" | 14 #include "chrome/browser/android/webapk/webapk_web_manifest_checker.h" |
15 #include "chrome/browser/installable/installable_manager.h" | 15 #include "chrome/browser/installable/installable_manager.h" |
16 #include "chrome/browser/profiles/profile.h" | 16 #include "chrome/browser/profiles/profile.h" |
17 #include "content/public/browser/web_contents.h" | 17 #include "content/public/browser/web_contents.h" |
18 #include "content/public/common/manifest.h" | 18 #include "content/public/common/manifest.h" |
19 #include "jni/ManifestUpgradeDetectorFetcher_jni.h" | 19 #include "jni/WebApkUpdateDataFetcher_jni.h" |
20 #include "third_party/smhasher/src/MurmurHash2.h" | 20 #include "third_party/smhasher/src/MurmurHash2.h" |
21 #include "ui/gfx/android/java_bitmap.h" | 21 #include "ui/gfx/android/java_bitmap.h" |
22 #include "ui/gfx/codec/png_codec.h" | 22 #include "ui/gfx/codec/png_codec.h" |
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(base::android::ConvertJavaStringToUTF8( |
44 env, java_web_manifest_url)); | 44 env, java_web_manifest_url)); |
45 ManifestUpgradeDetectorFetcher* fetcher = | 45 WebApkUpdateDataFetcher* fetcher = |
46 new ManifestUpgradeDetectorFetcher(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 ManifestUpgradeDetectorFetcher::ManifestUpgradeDetectorFetcher( | 50 WebApkUpdateDataFetcher::WebApkUpdateDataFetcher( |
51 JNIEnv* env, | 51 JNIEnv* env, |
52 jobject obj, | 52 jobject obj, |
53 const GURL& scope, | 53 const GURL& scope, |
54 const GURL& web_manifest_url) | 54 const GURL& web_manifest_url) |
55 : content::WebContentsObserver(nullptr), | 55 : content::WebContentsObserver(nullptr), |
56 scope_(scope), | 56 scope_(scope), |
57 web_manifest_url_(web_manifest_url), | 57 web_manifest_url_(web_manifest_url), |
58 info_(GURL()), | 58 info_(GURL()), |
59 weak_ptr_factory_(this) { | 59 weak_ptr_factory_(this) { |
60 java_ref_.Reset(env, obj); | 60 java_ref_.Reset(env, obj); |
61 } | 61 } |
62 | 62 |
63 ManifestUpgradeDetectorFetcher::~ManifestUpgradeDetectorFetcher() { | 63 WebApkUpdateDataFetcher::~WebApkUpdateDataFetcher() { |
64 } | 64 } |
65 | 65 |
66 // static | 66 // static |
67 bool ManifestUpgradeDetectorFetcher::Register(JNIEnv* env) { | 67 bool WebApkUpdateDataFetcher::Register(JNIEnv* env) { |
68 return RegisterNativesImpl(env); | 68 return RegisterNativesImpl(env); |
69 } | 69 } |
70 | 70 |
71 void ManifestUpgradeDetectorFetcher::ReplaceWebContents( | 71 void WebApkUpdateDataFetcher::ReplaceWebContents( |
72 JNIEnv* env, | 72 JNIEnv* env, |
73 const JavaParamRef<jobject>& obj, | 73 const JavaParamRef<jobject>& obj, |
74 const JavaParamRef<jobject>& java_web_contents) { | 74 const JavaParamRef<jobject>& java_web_contents) { |
75 content::WebContents* web_contents = | 75 content::WebContents* web_contents = |
76 content::WebContents::FromJavaWebContents(java_web_contents); | 76 content::WebContents::FromJavaWebContents(java_web_contents); |
77 content::WebContentsObserver::Observe(web_contents); | 77 content::WebContentsObserver::Observe(web_contents); |
78 } | 78 } |
79 | 79 |
80 void ManifestUpgradeDetectorFetcher::Destroy(JNIEnv* env, | 80 void WebApkUpdateDataFetcher::Destroy(JNIEnv* env, |
81 const JavaParamRef<jobject>& obj) { | 81 const JavaParamRef<jobject>& obj) { |
82 delete this; | 82 delete this; |
83 } | 83 } |
84 | 84 |
85 void ManifestUpgradeDetectorFetcher::Start( | 85 void WebApkUpdateDataFetcher::Start( |
86 JNIEnv* env, | 86 JNIEnv* env, |
87 const JavaParamRef<jobject>& obj, | 87 const JavaParamRef<jobject>& obj, |
88 const JavaParamRef<jobject>& java_web_contents) { | 88 const JavaParamRef<jobject>& java_web_contents) { |
89 ReplaceWebContents(env, obj, java_web_contents); | 89 ReplaceWebContents(env, obj, java_web_contents); |
90 if (!web_contents()->IsLoading()) | 90 if (!web_contents()->IsLoading()) |
91 FetchInstallableData(); | 91 FetchInstallableData(); |
92 } | 92 } |
93 | 93 |
94 void ManifestUpgradeDetectorFetcher::DidStopLoading() { | 94 void WebApkUpdateDataFetcher::DidStopLoading() { |
95 FetchInstallableData(); | 95 FetchInstallableData(); |
96 } | 96 } |
97 | 97 |
98 void ManifestUpgradeDetectorFetcher::FetchInstallableData() { | 98 void WebApkUpdateDataFetcher::FetchInstallableData() { |
99 GURL url = web_contents()->GetLastCommittedURL(); | 99 GURL url = web_contents()->GetLastCommittedURL(); |
100 | 100 |
101 // DidStopLoading() can be called multiple times for a single URL. Only fetch | 101 // DidStopLoading() can be called multiple times for a single URL. Only fetch |
102 // installable data the first time. | 102 // installable data the first time. |
103 if (url == last_fetched_url_) | 103 if (url == last_fetched_url_) |
104 return; | 104 return; |
105 last_fetched_url_ = url; | 105 last_fetched_url_ = url; |
106 | 106 |
107 if (!IsInScope(url, scope_)) | 107 if (!IsInScope(url, scope_)) |
108 return; | 108 return; |
109 | 109 |
110 InstallableParams params; | 110 InstallableParams params; |
111 params.ideal_icon_size_in_dp = | 111 params.ideal_icon_size_in_dp = |
112 ShortcutHelper::GetIdealHomescreenIconSizeInDp(); | 112 ShortcutHelper::GetIdealHomescreenIconSizeInDp(); |
113 params.minimum_icon_size_in_dp = | 113 params.minimum_icon_size_in_dp = |
114 ShortcutHelper::GetMinimumHomescreenIconSizeInDp(); | 114 ShortcutHelper::GetMinimumHomescreenIconSizeInDp(); |
115 params.check_installable = true; | 115 params.check_installable = true; |
116 params.fetch_valid_icon = true; | 116 params.fetch_valid_icon = true; |
117 InstallableManager::CreateForWebContents(web_contents()); | 117 InstallableManager::CreateForWebContents(web_contents()); |
118 InstallableManager* installable_manager = | 118 InstallableManager* installable_manager = |
119 InstallableManager::FromWebContents(web_contents()); | 119 InstallableManager::FromWebContents(web_contents()); |
120 installable_manager->GetData( | 120 installable_manager->GetData( |
121 params, | 121 params, |
122 base::Bind(&ManifestUpgradeDetectorFetcher::OnDidGetInstallableData, | 122 base::Bind(&WebApkUpdateDataFetcher::OnDidGetInstallableData, |
123 weak_ptr_factory_.GetWeakPtr())); | 123 weak_ptr_factory_.GetWeakPtr())); |
124 } | 124 } |
125 | 125 |
126 void ManifestUpgradeDetectorFetcher::OnDidGetInstallableData( | 126 void WebApkUpdateDataFetcher::OnDidGetInstallableData( |
127 const InstallableData& data) { | 127 const InstallableData& data) { |
128 // If the manifest is empty, it means the current WebContents doesn't | 128 // If the manifest is empty, it means the current WebContents doesn't |
129 // associate with a Web Manifest. In such case, we ignore the empty manifest | 129 // associate with a Web Manifest. In such case, we ignore the empty manifest |
130 // and continue observing the WebContents's loading until we find a page that | 130 // and continue observing the WebContents's loading until we find a page that |
131 // links to the Web Manifest that we are looking for. | 131 // links to the Web Manifest that we are looking for. |
132 // If the manifest URL is different from the current one, we will continue | 132 // If the manifest URL is different from the current one, we will continue |
133 // observing too. It is based on our assumption that it is invalid for | 133 // observing too. It is based on our assumption that it is invalid for |
134 // web developers to change the Web Manifest location. When it does | 134 // web developers to change the Web Manifest location. When it does |
135 // change, we will treat the new Web Manifest as the one of another WebAPK. | 135 // change, we will treat the new Web Manifest as the one of another WebAPK. |
136 if (data.manifest.IsEmpty() || web_manifest_url_ != data.manifest_url) | 136 if (data.manifest.IsEmpty() || web_manifest_url_ != data.manifest_url) |
(...skipping 10 matching lines...) Expand all Loading... |
147 info_.manifest_url = data.manifest_url; | 147 info_.manifest_url = data.manifest_url; |
148 info_.best_icon_url = data.icon_url; | 148 info_.best_icon_url = data.icon_url; |
149 best_icon_ = *data.icon; | 149 best_icon_ = *data.icon; |
150 | 150 |
151 icon_hasher_.reset(new WebApkIconHasher()); | 151 icon_hasher_.reset(new WebApkIconHasher()); |
152 Profile* profile = | 152 Profile* profile = |
153 Profile::FromBrowserContext(web_contents()->GetBrowserContext()); | 153 Profile::FromBrowserContext(web_contents()->GetBrowserContext()); |
154 icon_hasher_->DownloadAndComputeMurmur2Hash( | 154 icon_hasher_->DownloadAndComputeMurmur2Hash( |
155 profile->GetRequestContext(), | 155 profile->GetRequestContext(), |
156 data.icon_url, | 156 data.icon_url, |
157 base::Bind(&ManifestUpgradeDetectorFetcher::OnGotIconMurmur2Hash, | 157 base::Bind(&WebApkUpdateDataFetcher::OnGotIconMurmur2Hash, |
158 weak_ptr_factory_.GetWeakPtr())); | 158 weak_ptr_factory_.GetWeakPtr())); |
159 } | 159 } |
160 | 160 |
161 void ManifestUpgradeDetectorFetcher::OnGotIconMurmur2Hash( | 161 void WebApkUpdateDataFetcher::OnGotIconMurmur2Hash( |
162 const std::string& best_icon_murmur2_hash) { | 162 const std::string& best_icon_murmur2_hash) { |
163 icon_hasher_.reset(); | 163 icon_hasher_.reset(); |
164 | 164 |
165 if (best_icon_murmur2_hash.empty()) { | 165 if (best_icon_murmur2_hash.empty()) { |
166 // TODO(pkotwicz): Tell Java side that the Web Manifest was fetched but the | 166 // TODO(pkotwicz): Tell Java side that the Web Manifest was fetched but the |
167 // Web Manifest is not WebAPK-compatible. (http://crbug.com/639536) | 167 // Web Manifest is not WebAPK-compatible. (http://crbug.com/639536) |
168 return; | 168 return; |
169 } | 169 } |
170 | 170 |
171 OnDataAvailable(info_, best_icon_murmur2_hash, best_icon_); | 171 OnDataAvailable(info_, best_icon_murmur2_hash, best_icon_); |
172 } | 172 } |
173 | 173 |
174 void ManifestUpgradeDetectorFetcher::OnDataAvailable( | 174 void WebApkUpdateDataFetcher::OnDataAvailable( |
175 const ShortcutInfo& info, | 175 const ShortcutInfo& info, |
176 const std::string& best_icon_murmur2_hash, | 176 const std::string& best_icon_murmur2_hash, |
177 const SkBitmap& best_icon_bitmap) { | 177 const SkBitmap& best_icon_bitmap) { |
178 JNIEnv* env = base::android::AttachCurrentThread(); | 178 JNIEnv* env = base::android::AttachCurrentThread(); |
179 | 179 |
180 ScopedJavaLocalRef<jstring> java_url = | 180 ScopedJavaLocalRef<jstring> java_url = |
181 base::android::ConvertUTF8ToJavaString(env, info.url.spec()); | 181 base::android::ConvertUTF8ToJavaString(env, info.url.spec()); |
182 ScopedJavaLocalRef<jstring> java_scope = | 182 ScopedJavaLocalRef<jstring> java_scope = |
183 base::android::ConvertUTF8ToJavaString(env, info.scope.spec()); | 183 base::android::ConvertUTF8ToJavaString(env, info.scope.spec()); |
184 ScopedJavaLocalRef<jstring> java_name = | 184 ScopedJavaLocalRef<jstring> java_name = |
185 base::android::ConvertUTF16ToJavaString(env, info.name); | 185 base::android::ConvertUTF16ToJavaString(env, info.name); |
186 ScopedJavaLocalRef<jstring> java_short_name = | 186 ScopedJavaLocalRef<jstring> java_short_name = |
187 base::android::ConvertUTF16ToJavaString(env, info.short_name); | 187 base::android::ConvertUTF16ToJavaString(env, info.short_name); |
188 ScopedJavaLocalRef<jstring> java_best_icon_url = | 188 ScopedJavaLocalRef<jstring> java_best_icon_url = |
189 base::android::ConvertUTF8ToJavaString(env, info.best_icon_url.spec()); | 189 base::android::ConvertUTF8ToJavaString(env, info.best_icon_url.spec()); |
190 ScopedJavaLocalRef<jstring> java_best_icon_murmur2_hash = | 190 ScopedJavaLocalRef<jstring> java_best_icon_murmur2_hash = |
191 base::android::ConvertUTF8ToJavaString(env, best_icon_murmur2_hash); | 191 base::android::ConvertUTF8ToJavaString(env, best_icon_murmur2_hash); |
192 ScopedJavaLocalRef<jobject> java_best_bitmap = | 192 ScopedJavaLocalRef<jobject> java_best_bitmap = |
193 gfx::ConvertToJavaBitmap(&best_icon_bitmap); | 193 gfx::ConvertToJavaBitmap(&best_icon_bitmap); |
194 | 194 |
195 ScopedJavaLocalRef<jobjectArray> java_icon_urls = | 195 ScopedJavaLocalRef<jobjectArray> java_icon_urls = |
196 base::android::ToJavaArrayOfStrings(env, info.icon_urls); | 196 base::android::ToJavaArrayOfStrings(env, info.icon_urls); |
197 | 197 |
198 Java_ManifestUpgradeDetectorFetcher_onDataAvailable( | 198 Java_WebApkUpdateDataFetcher_onDataAvailable( |
199 env, java_ref_, java_url, java_scope, java_name, java_short_name, | 199 env, java_ref_, java_url, java_scope, java_name, java_short_name, |
200 java_best_icon_url, java_best_icon_murmur2_hash, java_best_bitmap, | 200 java_best_icon_url, java_best_icon_murmur2_hash, java_best_bitmap, |
201 java_icon_urls, info.display, info.orientation, info.theme_color, | 201 java_icon_urls, info.display, info.orientation, info.theme_color, |
202 info.background_color); | 202 info.background_color); |
203 } | 203 } |
OLD | NEW |