Skip to content

Commit

Permalink
Move DocumentTabModelSelector and related classes upstream
Browse files Browse the repository at this point in the history
* Moves various classes upstream.
* Changes ActivityDelegate to use the DocumentUtils to access
  the task's baseIntent instead of calling getTaskInfo() directly.
* Findbugs file changed for fields that are only read downstream.

Submitting with NOTRY as true to get around findbugs submission issues.

BUG=443773
NOTRY=true

Review URL: https://codereview.chromium.org/821063002

Cr-Commit-Position: refs/heads/master@{#309473}
  • Loading branch information
dfalcantara authored and Commit bot committed Dec 22, 2014
1 parent b3361bc commit df1702e
Show file tree
Hide file tree
Showing 5 changed files with 464 additions and 5 deletions.
6 changes: 3 additions & 3 deletions build/android/findbugs_filter/findbugs_known_bugs.txt
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@ M M LI: Incorrect lazy initialization of static field org.chromium.chrome.browse
M V EI2: org.chromium.content_public.browser.LoadUrlParams.setPostData(byte[]) may expose internal representation by storing an externally mutable object into LoadUrlParams.mPostData At LoadUrlParams.java
M V EI: org.chromium.content_public.browser.LoadUrlParams.getPostData() may expose internal representation by returning LoadUrlParams.mPostData At LoadUrlParams.java
M V EI2: org.chromium.net.ChromiumUrlRequest.setUploadData(String, byte[]) may expose internal representation by storing an externally mutable object into ChromiumUrlRequest.mUploadData At ChromiumUrlRequest.java
M D UuF: Unused public or protected field: org.chromium.chrome.browser.document.PendingDocumentData.extraHeaders In PendingDocumentData.java
M D UrF: Unread public/protected field: org.chromium.chrome.browser.document.PendingDocumentData.extraHeaders At DocumentTabModelSelector.java
M D UrF: Unread public/protected field: org.chromium.chrome.browser.document.PendingDocumentData.postData At DocumentTabModelSelector.java
M D UrF: Unread public/protected field: org.chromium.chrome.browser.document.PendingDocumentData.referrer At DocumentTabModelSelector.java
M D UuF: Unused public or protected field: org.chromium.chrome.browser.document.PendingDocumentData.nativeWebContents In PendingDocumentData.java
M D UuF: Unused public or protected field: org.chromium.chrome.browser.document.PendingDocumentData.originalIntent In PendingDocumentData.java
M D UuF: Unused public or protected field: org.chromium.chrome.browser.document.PendingDocumentData.postData In PendingDocumentData.java
M D UuF: Unused public or protected field: org.chromium.chrome.browser.document.PendingDocumentData.referrer In PendingDocumentData.java
M D UuF: Unused public or protected field: org.chromium.chrome.browser.document.PendingDocumentData.url In PendingDocumentData.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
// 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.graphics.Color;

/**
* Utilities for brand color related properties.
*/
public class BrandColorUtils {
private static final float CONTRAST_LIGHT_TEXT_THRESHOLD = 3f;
private static final float LIGHTNESS_OPAQUE_BOX_THRESHOLD = 0.82f;

/** Percentage to darken the brand color by when setting the status bar color. */
private static final float DARKEN_COLOR_FRACTION = 0.6f;

/**
* Computes the lightness value in HSL standard for the given color.
*/
private static float getLightnessForColor(int color) {
int red = Color.red(color);
int green = Color.green(color);
int blue = Color.blue(color);
int largest = Math.max(red, Math.max(green, blue));
int smallest = Math.min(red, Math.min(green, blue));
int average = (largest + smallest) / 2;
return average / 255.0f;
}

/** Calculates the contrast between the given color and white, using the algorithm provided by
* the WCAG v2 in http://www.w3.org/TR/WCAG20/#contrast-ratiodef.
*/
private static float getContrastForColor(int color) {
float bgR = Color.red(color) / 255f;
float bgG = Color.green(color) / 255f;
float bgB = Color.blue(color) / 255f;
bgR = (bgR < 0.03928f) ? bgR / 12.92f : (float) Math.pow((bgR + 0.055f) / 1.055f, 2.4f);
bgG = (bgG < 0.03928f) ? bgG / 12.92f : (float) Math.pow((bgG + 0.055f) / 1.055f, 2.4f);
bgB = (bgB < 0.03928f) ? bgB / 12.92f : (float) Math.pow((bgB + 0.055f) / 1.055f, 2.4f);
float bgL = 0.2126f * bgR + 0.7152f * bgG + 0.0722f * bgB;
return Math.abs((1.05f) / (bgL + 0.05f));
}

/**
* Darkens the given color to use on the status bar.
* @param color Brand color of the website.
* @return Color that should be used for Android status bar.
*/
public static int computeStatusBarColor(int color) {
float[] hsv = new float[3];
Color.colorToHSV(color, hsv);
hsv[2] *= DARKEN_COLOR_FRACTION;
return Color.HSVToColor(hsv);
}

/**
* Check which version of the drawables should be used depending on the given primary color.
* @param color The primary color value we are querying for.
* @return Whether the light colored text and drawable set should be used.
*/
public static boolean shouldUseLightDrawablesForToolbar(int color) {
return getContrastForColor(color) >= CONTRAST_LIGHT_TEXT_THRESHOLD;
}

/**
* Check which version of the textbox background should be used depending on the given
* primary color.
* @param color The primary color value we are querying for.
* @return Whether the transparent version of the background should be used.
*/
public static boolean shouldUseOpaqueTextboxBackground(int color) {
return getLightnessForColor(color) > LIGHTNESS_OPAQUE_BOX_THRESHOLD;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
// 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.Activity;
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.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.net.Uri;
import android.os.Build;
import android.text.TextUtils;
import android.util.Log;

import org.chromium.base.ApiCompatibilityUtils;
import org.chromium.base.ApplicationStatus;

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";

/**
* Update the Recents entry for the Activity.
* @param activity Activity to change the entry for.
* @param title Title to show on the card.
* @param icon Icon to show on the card.
* @param color Color to use for the card's bar.
* @param useDefaultStatusBarColor Whether status bar should be set to default color.
*/
public static void updateTaskDescription(Activity activity, String title, Bitmap icon,
int color, boolean useDefaultStatusBarColor) {
ApiCompatibilityUtils.setTaskDescription(activity, title, icon, color);
int statusBarColor = useDefaultStatusBarColor
? Color.BLACK : BrandColorUtils.computeStatusBarColor(color);
ApiCompatibilityUtils.setStatusBarColor(activity, statusBarColor);
}

/**
* 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 = ApplicationStatus.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)) continue;
if (taskId == -1 || taskId != canonicalTaskId) {
tasksToFinish.add(task);
}
}

Intent removedIntent = null;
for (ActivityManager.AppTask task : tasksToFinish) {
removedIntent = getBaseIntentFromTask(task);
Log.d(TAG, "Removing duplicated task: " + 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;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import org.chromium.base.ApplicationStatus;
import org.chromium.chrome.browser.Tab;
import org.chromium.chrome.browser.UrlConstants;
import org.chromium.chrome.browser.document.DocumentUtils;
import org.chromium.chrome.browser.tabmodel.document.DocumentTabModel.Entry;

import java.util.ArrayList;
Expand Down Expand Up @@ -84,7 +85,7 @@ public List<Entry> getTasksFromRecents(boolean isIncognito) {
ActivityManager activityManager =
(ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
for (ActivityManager.AppTask task : activityManager.getAppTasks()) {
Intent intent = task.getTaskInfo().baseIntent;
Intent intent = DocumentUtils.getBaseIntentFromTask(task);
if (!isValidActivity(isIncognito, intent)) continue;

int tabId = getTabIdFromIntent(intent);
Expand Down Expand Up @@ -120,7 +121,7 @@ private final ActivityManager.AppTask getTask(boolean isIncognito, int tabId) {
ActivityManager activityManager =
(ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
for (ActivityManager.AppTask task : activityManager.getAppTasks()) {
Intent intent = task.getTaskInfo().baseIntent;
Intent intent = DocumentUtils.getBaseIntentFromTask(task);
int taskId = getTabIdFromIntent(intent);
if (taskId == tabId && isValidActivity(isIncognito, intent)) return task;
}
Expand Down
Loading

0 comments on commit df1702e

Please sign in to comment.