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 |