// Copyright 2014 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.document;
import android.annotation.TargetApi;
import android.app.ActivityManager;
import android.app.ActivityManager.AppTask;
import android.app.ActivityManager.RecentTaskInfo;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.net.Uri;
import android.os.Build;
import android.text.TextUtils;
import android.util.Log;
import org.chromium.base.ContextUtils;
import org.chromium.chrome.browser.tab.Tab;
import org.chromium.chrome.browser.tabmodel.document.DocumentTabModelImpl;
import java.util.ArrayList;
import java.util.List;
/**
* Deals with Document-related API calls.
*/
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public class DocumentUtils {
public static final String TAG = "DocumentUtilities";
/**
* Finishes tasks other than the one with the given ID that were started with the given data
* in the Intent, removing those tasks from Recents and leaving a unique task with the data.
* @param data Passed in as part of the Intent's data when starting the Activity.
* @param canonicalTaskId ID of the task will be the only one left with the ID.
* @return Intent of one of the tasks that were finished.
*/
public static Intent finishOtherTasksWithData(Uri data, int canonicalTaskId) {
if (data == null || Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) return null;
String dataString = data.toString();
Context context = ContextUtils.getApplicationContext();
ActivityManager manager =
(ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
List<ActivityManager.AppTask> tasksToFinish = new ArrayList<ActivityManager.AppTask>();
for (ActivityManager.AppTask task : manager.getAppTasks()) {
RecentTaskInfo taskInfo = getTaskInfoFromTask(task);
if (taskInfo == null) continue;
int taskId = taskInfo.id;
Intent baseIntent = taskInfo.baseIntent;
String taskData = baseIntent == null ? null : taskInfo.baseIntent.getDataString();
if (TextUtils.equals(dataString, taskData)
&& (taskId == -1 || taskId != canonicalTaskId)) {
tasksToFinish.add(task);
}
}
return finishAndRemoveTasks(tasksToFinish);
}
private static Intent finishAndRemoveTasks(List<ActivityManager.AppTask> tasksToFinish) {
Intent removedIntent = null;
for (ActivityManager.AppTask task : tasksToFinish) {
Log.d(TAG, "Removing task with duplicated data: " + task);
removedIntent = getBaseIntentFromTask(task);
task.finishAndRemoveTask();
}
return removedIntent;
}
/**
* Returns the RecentTaskInfo for the task, if the ActivityManager succeeds in finding the task.
* @param task AppTask containing information about a task.
* @return The RecentTaskInfo associated with the task, or null if it couldn't be found.
*/
public static RecentTaskInfo getTaskInfoFromTask(AppTask task) {
RecentTaskInfo info = null;
try {
info = task.getTaskInfo();
} catch (IllegalArgumentException e) {
Log.e(TAG, "Failed to retrieve task info: ", e);
}
return info;
}
/**
* Returns the baseIntent of the RecentTaskInfo associated with the given task.
* @param task Task to get the baseIntent for.
* @return The baseIntent, or null if it couldn't be retrieved.
*/
public static Intent getBaseIntentFromTask(AppTask task) {
RecentTaskInfo info = getTaskInfoFromTask(task);
return info == null ? null : info.baseIntent;
}
/**
* Given an AppTask retrieves the task class name.
* @param task The app task to use.
* @param pm The package manager to use for resolving intent.
* @return Fully qualified class name or null if we were not able to
* determine it.
*/
public static String getTaskClassName(AppTask task, PackageManager pm) {
RecentTaskInfo info = getTaskInfoFromTask(task);
if (info == null) return null;
Intent baseIntent = info.baseIntent;
if (baseIntent == null) {
return null;
} else if (baseIntent.getComponent() != null) {
return baseIntent.getComponent().getClassName();
} else {
ResolveInfo resolveInfo = pm.resolveActivity(baseIntent, 0);
if (resolveInfo == null) return null;
return resolveInfo.activityInfo.name;
}
}
/**
* Returns the ID of the last shown Tab for the given DocumentTabModel type.
* @param context Context to pull SharedPrefs from.
* @param isIncognito Whether to get the ID for the regular or Incognito TabModel.
* @return ID of the last shown Tab for the given TabModel type.
*/
public static int getLastShownTabIdFromPrefs(Context context, boolean isIncognito) {
SharedPreferences prefs = context.getSharedPreferences(
DocumentTabModelImpl.PREF_PACKAGE, Context.MODE_PRIVATE);
String prefName = isIncognito
? DocumentTabModelImpl.PREF_LAST_SHOWN_TAB_ID_INCOGNITO
: DocumentTabModelImpl.PREF_LAST_SHOWN_TAB_ID_REGULAR;
return prefs.getInt(prefName, Tab.INVALID_TAB_ID);
}
}