1// Copyright 2014 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "chrome/browser/android/profiles/profile_downloader_android.h"
6
7#include "base/android/jni_android.h"
8#include "base/android/jni_string.h"
9#include "chrome/browser/browser_process.h"
10#include "chrome/browser/profiles/profile_android.h"
11#include "chrome/browser/profiles/profile_avatar_icon_util.h"
12#include "chrome/browser/profiles/profile_downloader.h"
13#include "chrome/browser/profiles/profile_downloader_delegate.h"
14#include "chrome/browser/profiles/profile_manager.h"
15#include "jni/ProfileDownloader_jni.h"
16#include "third_party/skia/include/core/SkBitmap.h"
17#include "ui/gfx/android/java_bitmap.h"
18#include "ui/gfx/image/image_skia.h"
19#include "ui/gfx/screen.h"
20
21namespace {
22
23// An account fetcher callback.
24class AccountInfoRetriever : public ProfileDownloaderDelegate {
25 public:
26  explicit AccountInfoRetriever(Profile* profile,
27                                const std::string& account_id,
28                                const int desired_image_side_pixels)
29      : profile_(profile),
30        account_id_(account_id),
31        desired_image_side_pixels_(desired_image_side_pixels) {}
32
33  void Start() {
34    profile_image_downloader_.reset(new ProfileDownloader(this));
35    profile_image_downloader_->StartForAccount(account_id_);
36  }
37
38  void Shutdown() {
39    profile_image_downloader_.reset();
40    delete this;
41  }
42
43  // ProfileDownloaderDelegate implementation:
44  virtual bool NeedsProfilePicture() const OVERRIDE {
45    return desired_image_side_pixels_ > 0;
46  }
47
48  virtual int GetDesiredImageSideLength() const OVERRIDE {
49    return desired_image_side_pixels_;
50  }
51
52  virtual Profile* GetBrowserProfile() OVERRIDE {
53    return profile_;
54  }
55
56  virtual std::string GetCachedPictureURL() const OVERRIDE {
57    return std::string();
58  }
59
60  virtual void OnProfileDownloadSuccess(
61      ProfileDownloader* downloader) OVERRIDE {
62    ProfileDownloaderAndroid::OnProfileDownloadSuccess(
63        account_id_,
64        downloader->GetProfileFullName(),
65        downloader->GetProfilePicture());
66    Shutdown();
67  }
68
69  virtual void OnProfileDownloadFailure(
70      ProfileDownloader* downloader,
71      ProfileDownloaderDelegate::FailureReason reason) OVERRIDE {
72    LOG(ERROR) << "Failed to download the profile information: " << reason;
73    Shutdown();
74  }
75
76  // The profile image downloader instance.
77  scoped_ptr<ProfileDownloader> profile_image_downloader_;
78
79  // The browser profile associated with this download request.
80  Profile* profile_;
81
82  // The account ID (email address) to be loaded.
83  const std::string account_id_;
84
85  // Desired side length of the profile image (in pixels).
86  const int desired_image_side_pixels_;
87
88  DISALLOW_COPY_AND_ASSIGN(AccountInfoRetriever);
89};
90
91}  // namespace
92
93// static
94void ProfileDownloaderAndroid::OnProfileDownloadSuccess(
95    const std::string& account_id,
96    const base::string16& full_name,
97    const SkBitmap& bitmap) {
98  JNIEnv* env = base::android::AttachCurrentThread();
99  ScopedJavaLocalRef<jobject> jbitmap;
100  if (!bitmap.isNull() && bitmap.bytesPerPixel() != 0)
101    jbitmap = gfx::ConvertToJavaBitmap(&bitmap);
102  Java_ProfileDownloader_onProfileDownloadSuccess(
103      env,
104      base::android::ConvertUTF8ToJavaString(env, account_id).obj(),
105      base::android::ConvertUTF16ToJavaString(env, full_name).obj(),
106      jbitmap.obj());
107}
108
109// static
110jstring GetCachedNameForPrimaryAccount(JNIEnv* env,
111                                       jclass clazz,
112                                       jobject jprofile) {
113  Profile* profile = ProfileAndroid::FromProfileAndroid(jprofile);
114  ProfileInfoInterface& info =
115      g_browser_process->profile_manager()->GetProfileInfoCache();
116  const size_t index = info.GetIndexOfProfileWithPath(profile->GetPath());
117
118  base::string16 name;
119  if (index != std::string::npos)
120    name = info.GetGAIANameOfProfileAtIndex(index);
121
122  return base::android::ConvertUTF16ToJavaString(env, name).Release();
123}
124
125// static
126jobject GetCachedAvatarForPrimaryAccount(JNIEnv* env,
127                                         jclass clazz,
128                                         jobject jprofile) {
129  Profile* profile = ProfileAndroid::FromProfileAndroid(jprofile);
130  ProfileInfoInterface& info =
131      g_browser_process->profile_manager()->GetProfileInfoCache();
132  const size_t index = info.GetIndexOfProfileWithPath(profile->GetPath());
133
134  ScopedJavaLocalRef<jobject> jbitmap;
135  if (index != std::string::npos) {
136    gfx::Image avatar_image = info.GetAvatarIconOfProfileAtIndex(index);
137    if (!avatar_image.IsEmpty() &&
138        avatar_image.Width() > profiles::kAvatarIconWidth &&
139        avatar_image.Height() > profiles::kAvatarIconHeight &&
140        avatar_image.AsImageSkia().bitmap()) {
141      jbitmap = gfx::ConvertToJavaBitmap(avatar_image.AsImageSkia().bitmap());
142    }
143  }
144
145  return jbitmap.Release();
146}
147
148// static
149void StartFetchingAccountInfoFor(
150    JNIEnv* env,
151    jclass clazz,
152    jobject jprofile,
153    jstring jaccount_id,
154    jint image_side_pixels) {
155  Profile* profile = ProfileAndroid::FromProfileAndroid(jprofile);
156  const std::string account_id =
157      base::android::ConvertJavaStringToUTF8(env, jaccount_id);
158  AccountInfoRetriever* retriever =
159      new AccountInfoRetriever(profile, account_id, image_side_pixels);
160  retriever->Start();
161}
162
163// static
164bool ProfileDownloaderAndroid::Register(JNIEnv* env) {
165  return RegisterNativesImpl(env);
166}
167