Chromium Code Reviews| 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 usec (between 0 and 8.192ms). | |
|
palmer
2017/04/07 18:56:33
Pico-nit: Use "ms" consistently (not "usec").
Matt Giuca
2017/04/10 08:33:40
Not sure what you mean by this. Are you asking me
| |
| 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); | |
| 273 } catch (InterruptedException e) { | |
| 274 // Continue to interrupt the thread after this completes. | |
| 275 Thread.currentThread().interrupt(); | |
| 276 } | |
| 277 } | |
| 250 } | 278 } |
| OLD | NEW |