Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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.chrome.browser; | 5 package org.chromium.chrome.browser; |
| 6 | 6 |
| 7 import android.app.KeyguardManager; | 7 import android.app.KeyguardManager; |
| 8 import android.app.PendingIntent; | 8 import android.app.PendingIntent; |
| 9 import android.app.SearchManager; | 9 import android.app.SearchManager; |
| 10 import android.content.ComponentName; | 10 import android.content.ComponentName; |
| 11 import android.content.Context; | 11 import android.content.Context; |
| 12 import android.content.Intent; | 12 import android.content.Intent; |
| 13 import android.content.IntentFilter; | |
| 13 import android.net.Uri; | 14 import android.net.Uri; |
| 14 import android.os.Bundle; | 15 import android.os.Bundle; |
| 15 import android.os.SystemClock; | 16 import android.os.SystemClock; |
| 16 import android.provider.Browser; | 17 import android.provider.Browser; |
| 17 import android.provider.MediaStore; | 18 import android.provider.MediaStore; |
| 18 import android.speech.RecognizerResultsIntent; | 19 import android.speech.RecognizerResultsIntent; |
| 19 import android.text.TextUtils; | 20 import android.text.TextUtils; |
| 20 import android.util.Pair; | 21 import android.util.Pair; |
| 21 | 22 |
| 22 import org.chromium.base.ApiCompatibilityUtils; | 23 import org.chromium.base.ApiCompatibilityUtils; |
| (...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 219 // publicly available. | 220 // publicly available. |
| 220 private static final String TAB_ACTIVITY_COMPONENT_CLASS_NAME = | 221 private static final String TAB_ACTIVITY_COMPONENT_CLASS_NAME = |
| 221 "com.google.android.apps.chrome.Main"; | 222 "com.google.android.apps.chrome.Main"; |
| 222 | 223 |
| 223 private static boolean sTestIntentsEnabled; | 224 private static boolean sTestIntentsEnabled; |
| 224 | 225 |
| 225 private final IntentHandlerDelegate mDelegate; | 226 private final IntentHandlerDelegate mDelegate; |
| 226 private final String mPackageName; | 227 private final String mPackageName; |
| 227 private KeyguardManager mKeyguardManager; | 228 private KeyguardManager mKeyguardManager; |
| 228 | 229 |
| 230 /** | |
| 231 * Receiver for screen unlock broadcast. | |
| 232 */ | |
| 233 private KeyguardBroadcastReceiver mKeyguardBroadcastReceiver; | |
| 234 | |
| 229 public static enum TabOpenType { | 235 public static enum TabOpenType { |
| 230 OPEN_NEW_TAB, | 236 OPEN_NEW_TAB, |
| 231 // Tab is reused only if the URLs perfectly match. | 237 // Tab is reused only if the URLs perfectly match. |
| 232 REUSE_URL_MATCHING_TAB_ELSE_NEW_TAB, | 238 REUSE_URL_MATCHING_TAB_ELSE_NEW_TAB, |
| 233 // Tab is reused only if there's an existing tab opened by the same app ID. | 239 // Tab is reused only if there's an existing tab opened by the same app ID. |
| 234 REUSE_APP_ID_MATCHING_TAB_ELSE_NEW_TAB, | 240 REUSE_APP_ID_MATCHING_TAB_ELSE_NEW_TAB, |
| 235 CLOBBER_CURRENT_TAB, | 241 CLOBBER_CURRENT_TAB, |
| 236 BRING_TAB_TO_FRONT, | 242 BRING_TAB_TO_FRONT, |
| 237 // Opens a new incognito tab. | 243 // Opens a new incognito tab. |
| 238 OPEN_NEW_INCOGNITO_TAB, | 244 OPEN_NEW_INCOGNITO_TAB, |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 324 List<String> packages = IntentUtils.safeGetStringArrayListExtra(intent, | 330 List<String> packages = IntentUtils.safeGetStringArrayListExtra(intent, |
| 325 IntentHandler.EXTRA_EXTERNAL_NAV_PACKAGES); | 331 IntentHandler.EXTRA_EXTERNAL_NAV_PACKAGES); |
| 326 if (packages != null && packages.size() > 0) { | 332 if (packages != null && packages.size() > 0) { |
| 327 RecordUserAction.record("MobileExternalNavigationReceived"); | 333 RecordUserAction.record("MobileExternalNavigationReceived"); |
| 328 for (String name : packages) { | 334 for (String name : packages) { |
| 329 RapporServiceBridge.sampleString("Android.ExternalNavigationNotC hosen", name); | 335 RapporServiceBridge.sampleString("Android.ExternalNavigationNotC hosen", name); |
| 330 } | 336 } |
| 331 } | 337 } |
| 332 } | 338 } |
| 333 | 339 |
| 340 @VisibleForTesting | |
| 341 void tryUnregisterLockscreenIntentReceiver(Context context, Intent intent) { | |
| 342 // Only unregister receiver when the intent was specially marked or the receiver no longer | |
| 343 // contain any valid deferred intent. | |
| 344 // If the intent does not contain the special mark, it should be treated as normal intent | |
| 345 // instead. This is helping the scenario when the screen is unlocked, an other intent is | |
| 346 // fired before the broadcast. | |
|
Maria
2016/12/13 21:36:09
I think that if another event was fired before the
Sherry
2016/12/13 22:13:54
If the deferred intent is still within the lifetim
Sherry
2016/12/13 22:32:29
My bad, you are right. If the new irrelevant inten
Ted C
2016/12/13 22:47:13
I agree with Maria. If another intent was receive
| |
| 347 if (mKeyguardBroadcastReceiver != null | |
| 348 && !mKeyguardBroadcastReceiver.hasValidDeferredIntent(intent)) { | |
| 349 context.unregisterReceiver(mKeyguardBroadcastReceiver); | |
| 350 mKeyguardBroadcastReceiver = null; | |
| 351 } | |
| 352 } | |
| 353 | |
| 334 /** | 354 /** |
| 335 * Handles an Intent after the ChromeTabbedActivity decides that it shouldn' t ignore the | 355 * Handles an Intent after the ChromeTabbedActivity decides that it shouldn' t ignore the |
| 336 * Intent. | 356 * Intent. |
| 337 * | 357 * @param context Android Context. |
| 358 * @param intent Target intent. | |
| 338 * @return Whether the Intent was successfully handled. | 359 * @return Whether the Intent was successfully handled. |
| 339 */ | 360 */ |
| 340 boolean onNewIntent(Context context, Intent intent) { | 361 boolean onNewIntent(Context context, Intent intent) { |
| 362 tryUnregisterLockscreenIntentReceiver(context, intent); | |
| 363 | |
| 341 assert intentHasValidUrl(intent); | 364 assert intentHasValidUrl(intent); |
| 342 String url = getUrlFromIntent(intent); | 365 String url = getUrlFromIntent(intent); |
| 343 boolean hasUserGesture = | 366 boolean hasUserGesture = |
| 344 IntentWithGesturesHandler.getInstance().getUserGestureAndClear(i ntent); | 367 IntentWithGesturesHandler.getInstance().getUserGestureAndClear(i ntent); |
| 345 TabOpenType tabOpenType = getTabOpenType(intent); | 368 TabOpenType tabOpenType = getTabOpenType(intent); |
| 346 int tabIdToBringToFront = IntentUtils.safeGetIntExtra( | 369 int tabIdToBringToFront = IntentUtils.safeGetIntExtra( |
| 347 intent, TabOpenType.BRING_TAB_TO_FRONT.name(), Tab.INVALID_TAB_I D); | 370 intent, TabOpenType.BRING_TAB_TO_FRONT.name(), Tab.INVALID_TAB_I D); |
| 348 if (url == null && tabIdToBringToFront == Tab.INVALID_TAB_ID | 371 if (url == null && tabIdToBringToFront == Tab.INVALID_TAB_ID |
| 349 && tabOpenType != TabOpenType.OPEN_NEW_INCOGNITO_TAB) { | 372 && tabOpenType != TabOpenType.OPEN_NEW_INCOGNITO_TAB) { |
| 350 return handleWebSearchIntent(intent); | 373 return handleWebSearchIntent(intent); |
| (...skipping 330 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 681 } | 704 } |
| 682 | 705 |
| 683 Log.w(TAG, "Ignoring internal Chrome URL from untrustworthy source."); | 706 Log.w(TAG, "Ignoring internal Chrome URL from untrustworthy source."); |
| 684 return true; | 707 return true; |
| 685 } | 708 } |
| 686 } | 709 } |
| 687 | 710 |
| 688 // We must check for screen state at this point. | 711 // We must check for screen state at this point. |
| 689 // These might be slow. | 712 // These might be slow. |
| 690 boolean internalOrVisible = isInternal || isIntentUserVisible(contex t); | 713 boolean internalOrVisible = isInternal || isIntentUserVisible(contex t); |
| 691 return !internalOrVisible; | 714 if (!internalOrVisible) { |
| 715 // Register keyguard broadcast receiver to receive ACTION_USER_P RESENT when the | |
| 716 // screen is unlocked. | |
| 717 // Avoid register KeyguardBroadcastReceiver if there is already one cached to allow | |
| 718 // unregister on the same instance. | |
| 719 // The ACTION_USER_PRESENT is sent by platform to indicates when user is present. | |
| 720 if (mKeyguardBroadcastReceiver == null) { | |
| 721 mKeyguardBroadcastReceiver = new KeyguardBroadcastReceiver(i ntent); | |
| 722 context.registerReceiver(mKeyguardBroadcastReceiver, | |
| 723 new IntentFilter(Intent.ACTION_USER_PRESENT)); | |
| 724 } else { | |
| 725 mKeyguardBroadcastReceiver.updateDeferredIntent(intent); | |
| 726 } | |
|
Maria
2016/12/13 21:36:09
maybe move these lines into a method registerLocks
Sherry
2016/12/13 22:13:54
Sounds good to me. Will update.
Ted C
2016/12/13 22:47:13
Also, I would have the receiver unregister itself
Sherry
2016/12/14 00:54:07
Then we need a background task that continuously c
| |
| 727 return true; | |
| 728 } | |
| 729 return false; | |
| 692 } catch (Throwable t) { | 730 } catch (Throwable t) { |
| 693 return true; | 731 return true; |
| 694 } | 732 } |
| 695 } | 733 } |
| 696 | 734 |
| 697 @VisibleForTesting | 735 @VisibleForTesting |
| 736 void setKeyguardBroadcastReceiverForTesting(KeyguardBroadcastReceiver receiv er) { | |
| 737 mKeyguardBroadcastReceiver = receiver; | |
| 738 } | |
| 739 | |
| 740 @VisibleForTesting | |
| 698 boolean intentHasValidUrl(Intent intent) { | 741 boolean intentHasValidUrl(Intent intent) { |
| 699 String url = getUrlFromIntent(intent); | 742 String url = getUrlFromIntent(intent); |
| 700 | 743 |
| 701 // Always drop insecure urls. | 744 // Always drop insecure urls. |
| 702 if (url != null && isJavascriptSchemeOrInvalidUrl(url)) { | 745 if (url != null && isJavascriptSchemeOrInvalidUrl(url)) { |
| 703 return false; | 746 return false; |
| 704 } | 747 } |
| 705 return true; | 748 return true; |
| 706 } | 749 } |
| 707 | 750 |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 754 if (isChromeToken(token, context)) { | 797 if (isChromeToken(token, context)) { |
| 755 return true; | 798 return true; |
| 756 } | 799 } |
| 757 if (ExternalAuthUtils.getInstance().isGoogleSigned( | 800 if (ExternalAuthUtils.getInstance().isGoogleSigned( |
| 758 context, ApiCompatibilityUtils.getCreatorPackage(token))) { | 801 context, ApiCompatibilityUtils.getCreatorPackage(token))) { |
| 759 return true; | 802 return true; |
| 760 } | 803 } |
| 761 return false; | 804 return false; |
| 762 } | 805 } |
| 763 | 806 |
| 764 private boolean isIntentUserVisible(Context context) { | 807 @VisibleForTesting |
| 808 boolean isIntentUserVisible(Context context) { | |
| 765 // Only process Intents if the screen is on and the device is unlocked; | 809 // Only process Intents if the screen is on and the device is unlocked; |
| 766 // i.e. the user will see what is going on. | 810 // i.e. the user will see what is going on. |
| 767 if (mKeyguardManager == null) { | 811 if (mKeyguardManager == null) { |
| 768 mKeyguardManager = (KeyguardManager) context.getSystemService(Contex t.KEYGUARD_SERVICE); | 812 mKeyguardManager = (KeyguardManager) context.getSystemService(Contex t.KEYGUARD_SERVICE); |
| 769 } | 813 } |
| 770 if (!ApiCompatibilityUtils.isInteractive(context)) return false; | 814 if (!ApiCompatibilityUtils.isInteractive(context)) return false; |
| 771 return !ApiCompatibilityUtils.isDeviceProvisioned(context) | 815 return !ApiCompatibilityUtils.isDeviceProvisioned(context) |
| 772 || !mKeyguardManager.inKeyguardRestrictedInputMode(); | 816 || !mKeyguardManager.inKeyguardRestrictedInputMode(); |
| 773 } | 817 } |
| 774 | 818 |
| (...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 978 if (transitionType == PageTransition.TYPED) { | 1022 if (transitionType == PageTransition.TYPED) { |
| 979 return transitionType; | 1023 return transitionType; |
| 980 } else if (transitionType != PageTransition.LINK | 1024 } else if (transitionType != PageTransition.LINK |
| 981 && isIntentChromeOrFirstParty(intent, context)) { | 1025 && isIntentChromeOrFirstParty(intent, context)) { |
| 982 // 1st party applications may specify any transition type. | 1026 // 1st party applications may specify any transition type. |
| 983 return transitionType; | 1027 return transitionType; |
| 984 } | 1028 } |
| 985 return defaultTransition; | 1029 return defaultTransition; |
| 986 } | 1030 } |
| 987 } | 1031 } |
| OLD | NEW |