// 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.profiles;
import android.content.Context;
import android.graphics.Bitmap;
import org.chromium.base.ObserverList;
import org.chromium.base.ThreadUtils;
import org.chromium.base.annotations.CalledByNative;
import org.chromium.base.annotations.SuppressFBWarnings;
import org.chromium.chrome.browser.signin.AccountTrackerService;
import java.util.ArrayList;
/**
* Android wrapper of the ProfileDownloader which provides access from the Java layer.
* The native ProfileDownloader requires its access to be in the UI thread.
* See chrome/browser/profiles/profile_downloader.h/cc for more details.
*/
public class ProfileDownloader {
private static final ObserverList<Observer> sObservers = new ObserverList<Observer>();
/**
* Interface for receiving notifications on account information updates.
*/
public interface Observer {
/**
* Notifies that an account data in the profile has been updated.
* @param accountId An account ID.
* @param fullName A full name.
* @param givenName A given name.
* @param bitmap A user picture.
*/
void onProfileDownloaded(String accountId, String fullName, String givenName,
Bitmap bitmap);
}
/**
* Add an observer.
* @param observer An observer.
*/
public static void addObserver(Observer observer) {
sObservers.addObserver(observer);
}
/**
* Remove an observer.
* @param observer An observer.
*/
public static void removeObserver(Observer observer) {
sObservers.removeObserver(observer);
}
/**
* Private class to pend profile download requests when system accounts have not been seeded into
* AccountTrackerService. It listens onSystemAccountsSeedingComplete to finish pending requests
* and onSystemAccountsChanged to clear outdated pending requests.
*/
private static class PendingProfileDownloads
implements AccountTrackerService.OnSystemAccountsSeededListener {
private static PendingProfileDownloads sPendingProfileDownloads;
private final ArrayList<Profile> mProfiles;
private final ArrayList<String> mAccountIds;
private final ArrayList<Integer> mImageSidePixels;
private PendingProfileDownloads() {
mProfiles = new ArrayList<>();
mAccountIds = new ArrayList<>();
mImageSidePixels = new ArrayList<>();
}
@SuppressFBWarnings("LI_LAZY_INIT_UPDATE_STATIC")
public static PendingProfileDownloads get(Context context) {
ThreadUtils.assertOnUiThread();
if (sPendingProfileDownloads == null) {
sPendingProfileDownloads = new PendingProfileDownloads();
AccountTrackerService.get(context).addSystemAccountsSeededListener(
sPendingProfileDownloads);
}
return sPendingProfileDownloads;
}
public void pendProfileDownload(Profile profile, String accountId, int imageSidePixels) {
mProfiles.add(profile);
mAccountIds.add(accountId);
mImageSidePixels.add(imageSidePixels);
}
@Override
public void onSystemAccountsSeedingComplete() {
int numberOfPendingRequests = mAccountIds.size();
while (numberOfPendingRequests > 0) {
// Pending requests here must be pre-signin request since SigninManager will wait
// system accounts been seeded into AccountTrackerService before finishing sign in.
nativeStartFetchingAccountInfoFor(
mProfiles.get(0), mAccountIds.get(0), mImageSidePixels.get(0), true);
mProfiles.remove(0);
mAccountIds.remove(0);
mImageSidePixels.remove(0);
numberOfPendingRequests--;
}
}
@Override
public void onSystemAccountsChanged() {
mProfiles.clear();
mAccountIds.clear();
mImageSidePixels.clear();
}
}
/**
* Starts fetching the account information for a given account.
* @param context context associated with the request
* @param profile Profile associated with the request
* @param accountId Account name to fetch the information for
* @param imageSidePixels Request image side (in pixels)
*/
public static void startFetchingAccountInfoFor(Context context, Profile profile,
String accountId, int imageSidePixels, boolean isPreSignin) {
ThreadUtils.assertOnUiThread();
if (!AccountTrackerService.get(context).checkAndSeedSystemAccounts()) {
PendingProfileDownloads.get(context).pendProfileDownload(
profile, accountId, imageSidePixels);
return;
}
nativeStartFetchingAccountInfoFor(profile, accountId, imageSidePixels, isPreSignin);
}
@CalledByNative
private static void onProfileDownloadSuccess(String accountId, String fullName,
String givenName, Bitmap bitmap) {
ThreadUtils.assertOnUiThread();
for (Observer observer : sObservers) {
observer.onProfileDownloaded(accountId, fullName, givenName, bitmap);
}
}
/**
* @param profile Profile
* @return The profile full name if cached, or null.
*/
public static String getCachedFullName(Profile profile) {
return nativeGetCachedFullNameForPrimaryAccount(profile);
}
/**
* @param profile Profile
* @return The profile given name if cached, or null.
*/
public static String getCachedGivenName(Profile profile) {
return nativeGetCachedGivenNameForPrimaryAccount(profile);
}
/**
* @param profile Profile
* @return The profile avatar if cached, or null.
*/
public static Bitmap getCachedAvatar(Profile profile) {
return nativeGetCachedAvatarForPrimaryAccount(profile);
}
// Native methods.
private static native void nativeStartFetchingAccountInfoFor(
Profile profile, String accountId, int imageSidePixels, boolean isPreSignin);
private static native String nativeGetCachedFullNameForPrimaryAccount(Profile profile);
private static native String nativeGetCachedGivenNameForPrimaryAccount(Profile profile);
private static native Bitmap nativeGetCachedAvatarForPrimaryAccount(Profile profile);
}