blob: d13461613544711899672cc1ebfb73ebb6193ea6 [file] [log] [blame]
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package org.chromium.chrome.browser;
import android.annotation.TargetApi;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.ShortcutInfo;
import android.content.pm.ShortcutManager;
import android.graphics.drawable.Icon;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.StrictMode;
import android.provider.Browser;
import android.support.annotation.VisibleForTesting;
import org.chromium.base.ContextUtils;
import org.chromium.chrome.R;
import org.chromium.chrome.browser.document.ChromeLauncherActivity;
import org.chromium.chrome.browser.preferences.PrefServiceBridge;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* A helper activity for routing launcher shortcut intents.
*/
public class LauncherShortcutActivity extends Activity {
public static final String ACTION_OPEN_NEW_TAB = "chromium.shortcut.action.OPEN_NEW_TAB";
public static final String ACTION_OPEN_NEW_INCOGNITO_TAB =
"chromium.shortcut.action.OPEN_NEW_INCOGNITO_TAB";
private static final String DYNAMIC_OPEN_NEW_INCOGNITO_TAB_ID =
"dynamic-new-incognito-tab-shortcut";
private static final String INCOGNITO_SHORTCUT_ADDED_PREF = "incognito-shortcut-added";
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
String intentAction = getIntent().getAction();
// Exit early if the original intent action isn't for opening a new tab.
if (!intentAction.equals(ACTION_OPEN_NEW_TAB)
&& !intentAction.equals(ACTION_OPEN_NEW_INCOGNITO_TAB)) {
finish();
return;
}
Intent newIntent = getChromeLauncherActivityIntent(this, intentAction);
// This system call is often modified by OEMs and not actionable. http://crbug.com/619646.
StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskWrites();
try {
startActivity(newIntent);
} finally {
StrictMode.setThreadPolicy(oldPolicy);
}
finish();
}
/**
* Adds or removes the "New incognito tab" launcher shortcut based on whether incognito mode
* is enabled.
* @param context The context used to retrieve the system {@link ShortcutManager}.
*/
public static void updateIncognitoShortcut(Context context) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N_MR1) return;
SharedPreferences preferences = ContextUtils.getAppSharedPreferences();
if (PrefServiceBridge.getInstance().isIncognitoModeEnabled()) {
boolean success = LauncherShortcutActivity.addIncognitoLauncherShortcut(context);
// Save a shared preference indicating the incognito shortcut has been added.
if (success) {
preferences.edit().putBoolean(INCOGNITO_SHORTCUT_ADDED_PREF, true).apply();
}
} else if (preferences.getBoolean(INCOGNITO_SHORTCUT_ADDED_PREF, false)
&& !PrefServiceBridge.getInstance().isIncognitoModeEnabled()) {
LauncherShortcutActivity.removeIncognitoLauncherShortcut(context);
preferences.edit().putBoolean(INCOGNITO_SHORTCUT_ADDED_PREF, false).apply();
}
}
/**
* Adds a "New incognito tab" dynamic launcher shortcut.
* @param context The context used to retrieve the system {@link ShortcutManager}.
* @return True if addint the shortcut has succeeded. False if the call fails due to rate
* limiting. See {@link ShortcutManager#addDynamicShortcuts}.
*/
@TargetApi(Build.VERSION_CODES.N_MR1)
private static boolean addIncognitoLauncherShortcut(Context context) {
Intent intent = new Intent(LauncherShortcutActivity.ACTION_OPEN_NEW_INCOGNITO_TAB);
intent.setPackage(context.getPackageName());
intent.setClass(context, LauncherShortcutActivity.class);
boolean useAlternativeIncognitoStrings =
ChromeFeatureList.isEnabled(ChromeFeatureList.INCOGNITO_STRINGS);
ShortcutInfo shortcut =
new ShortcutInfo.Builder(context, DYNAMIC_OPEN_NEW_INCOGNITO_TAB_ID)
.setShortLabel(context.getResources().getString(
useAlternativeIncognitoStrings
? R.string.accessibility_tabstrip_private_identifier
: R.string.accessibility_tabstrip_incognito_identifier))
.setLongLabel(context.getResources().getString(
useAlternativeIncognitoStrings ? R.string.menu_new_private_tab
: R.string.menu_new_incognito_tab))
.setIcon(Icon.createWithResource(context, R.drawable.shortcut_incognito))
.setIntent(intent)
.build();
ShortcutManager shortcutManager = context.getSystemService(ShortcutManager.class);
return shortcutManager.addDynamicShortcuts(Arrays.asList(shortcut));
}
/**
* Removes the dynamic "New incognito tab" launcher shortcut.
* @param context The context used to retrieve the system {@link ShortcutManager}.
*/
@TargetApi(Build.VERSION_CODES.N_MR1)
private static void removeIncognitoLauncherShortcut(Context context) {
List<String> shortcutList = new ArrayList<>();
shortcutList.add(DYNAMIC_OPEN_NEW_INCOGNITO_TAB_ID);
ShortcutManager shortcutManager = context.getSystemService(ShortcutManager.class);
shortcutManager.disableShortcuts(shortcutList);
shortcutManager.removeDynamicShortcuts(shortcutList);
}
/**
* @param context The context used to get the package and set the intent class.
* @param launcherShortcutIntentAction The intent action that launched the
* LauncherShortcutActivity.
* @return An intent for ChromeLauncherActivity that will open a new regular or incognito tab.
*/
@VisibleForTesting
public static Intent getChromeLauncherActivityIntent(
Context context, String launcherShortcutIntentAction) {
Intent newIntent = new Intent();
newIntent.setAction(Intent.ACTION_VIEW);
newIntent.setData(Uri.parse(UrlConstants.NTP_URL));
newIntent.setClass(context, ChromeLauncherActivity.class);
newIntent.putExtra(IntentHandler.EXTRA_INVOKED_FROM_SHORTCUT, true);
newIntent.putExtra(Browser.EXTRA_CREATE_NEW_TAB, true);
newIntent.putExtra(Browser.EXTRA_APPLICATION_ID, context.getPackageName());
IntentHandler.addTrustedIntentExtras(newIntent);
if (launcherShortcutIntentAction.equals(ACTION_OPEN_NEW_INCOGNITO_TAB)) {
newIntent.putExtra(IntentHandler.EXTRA_OPEN_NEW_INCOGNITO_TAB, true);
}
return newIntent;
}
}