OLD | NEW |
---|---|
1 // Copyright 2017 The Chromium Authors. All rights reserved. | 1 // Copyright 2017 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 package org.chromium.content.browser.installedapp; | 5 package org.chromium.content.browser.installedapp; |
6 | 6 |
7 import android.content.Context; | 7 import android.content.Context; |
8 import android.content.pm.ApplicationInfo; | 8 import android.content.pm.ApplicationInfo; |
9 import android.content.pm.PackageManager; | 9 import android.content.pm.PackageManager; |
10 import android.content.pm.PackageManager.NameNotFoundException; | 10 import android.content.pm.PackageManager.NameNotFoundException; |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
102 public void onConnectionError(MojoException e) {} | 102 public void onConnectionError(MojoException e) {} |
103 | 103 |
104 /** | 104 /** |
105 * Determines whether a particular app is installed and matches the origin. | 105 * Determines whether a particular app is installed and matches the origin. |
106 * | 106 * |
107 * @param packageName Name of the Android package to check if installed. Ret urns false if the | 107 * @param packageName Name of the Android package to check if installed. Ret urns false if the |
108 * app is not installed. | 108 * app is not installed. |
109 * @param frameUrl Returns false if the Android package does not declare ass ociation with the | 109 * @param frameUrl Returns false if the Android package does not declare ass ociation with the |
110 * origin of this URL. Can be null. | 110 * origin of this URL. Can be null. |
111 */ | 111 */ |
112 private static boolean isAppInstalledAndAssociatedWithOrigin( | 112 private boolean isAppInstalledAndAssociatedWithOrigin( |
113 String packageName, URI frameUrl, PackageManager pm) { | 113 String packageName, URI frameUrl, PackageManager pm) { |
114 if (frameUrl == null) return false; | 114 if (frameUrl == null) return false; |
115 | 115 |
116 // Important timing-attack prevention measure: delay by a pseudo-random amount of time, to | |
117 // add significant noise to the time taken to check whether this app is installed and | |
118 // related. Otherwise, it would be possible to tell whether a non-relate d app is installed, | |
119 // based on the time this operation takes. | |
120 // | |
121 // Generate a 16-bit hash based on a unique device ID + the package name . | |
122 short hash = PackageHash.hashForPackage(packageName); | |
123 | |
124 // The time delay is the low 13 bits of the hash in μs (between 0 and 8. 192ms). | |
125 int sleepUsec = hash & 0x1fff; | |
126 sleep(sleepUsec / 1000, (sleepUsec % 1000) * 1000); | |
127 | |
116 // Early-exit if the Android app is not installed. | 128 // Early-exit if the Android app is not installed. |
117 JSONArray statements; | 129 JSONArray statements; |
118 try { | 130 try { |
119 statements = getAssetStatements(packageName, pm); | 131 statements = getAssetStatements(packageName, pm); |
120 } catch (NameNotFoundException e) { | 132 } catch (NameNotFoundException e) { |
121 return false; | 133 return false; |
122 } | 134 } |
123 | 135 |
124 // The installed Android app has provided us with a list of asset statem ents. If any one of | 136 // The installed Android app has provided us with a list of asset statem ents. If any one of |
125 // those statements is a web asset that matches the given origin, return true. | 137 // those statements is a web asset that matches the given origin, return true. |
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
240 } | 252 } |
241 | 253 |
242 private static boolean statementTargetMatches(URI frameUrl, URI assetUrl) { | 254 private static boolean statementTargetMatches(URI frameUrl, URI assetUrl) { |
243 if (assetUrl.getScheme() == null || assetUrl.getAuthority() == null) { | 255 if (assetUrl.getScheme() == null || assetUrl.getAuthority() == null) { |
244 return false; | 256 return false; |
245 } | 257 } |
246 | 258 |
247 return assetUrl.getScheme().equals(frameUrl.getScheme()) | 259 return assetUrl.getScheme().equals(frameUrl.getScheme()) |
248 && assetUrl.getAuthority().equals(frameUrl.getAuthority()); | 260 && assetUrl.getAuthority().equals(frameUrl.getAuthority()); |
249 } | 261 } |
262 | |
263 /** | |
264 * Puts the current thread to sleep for a given amount of time. | |
265 * | |
266 * This is approximate but should at least be accurate to the millisecond. | |
267 * | |
268 * Protected and non-static for testing. | |
269 */ | |
270 protected void sleep(long millis, int nanos) { | |
271 try { | |
272 Thread.sleep(millis, nanos); | |
Matt Giuca
2017/04/11 08:34:08
tedchoc: I think this Thread.sleep might be bad (i
Ted C
2017/04/11 16:01:32
We definitely shouldn't sleep the UI thread. That
Matt Giuca
2017/04/12 01:05:58
Oh yeah, I saw that red flash and didn't know what
| |
273 } catch (InterruptedException e) { | |
274 // Continue to interrupt the thread after this completes. | |
275 Thread.currentThread().interrupt(); | |
276 } | |
277 } | |
250 } | 278 } |
OLD | NEW |