ozone: evdev: Sync caps lock LED state to evdev
[chromium-blink-merge.git] / chrome / browser / android / compositor / tab_content_manager.cc
blob4a8691b0241ac24fb637657e3eb84691f4c2d4eb
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.
5 #include "chrome/browser/android/compositor/tab_content_manager.h"
7 #include <android/bitmap.h>
9 #include "base/android/jni_android.h"
10 #include "base/android/jni_string.h"
11 #include "base/android/scoped_java_ref.h"
12 #include "base/bind.h"
13 #include "base/bind_helpers.h"
14 #include "cc/layers/layer.h"
15 #include "chrome/browser/android/compositor/layer/thumbnail_layer.h"
16 #include "chrome/browser/android/tab_android.h"
17 #include "chrome/browser/android/thumbnail/thumbnail.h"
18 #include "content/public/browser/android/content_view_core.h"
19 #include "content/public/browser/readback_types.h"
20 #include "content/public/browser/render_view_host.h"
21 #include "content/public/browser/web_contents.h"
22 #include "jni/TabContentManager_jni.h"
23 #include "ui/android/resources/ui_resource_provider.h"
24 #include "ui/gfx/android/java_bitmap.h"
25 #include "ui/gfx/geometry/rect.h"
26 #include "url/gurl.h"
28 namespace {
30 const size_t kMaxReadbacks = 1;
31 typedef base::Callback<void(float, const SkBitmap&)> TabReadbackCallback;
33 } // namespace
35 namespace chrome {
36 namespace android {
38 class TabContentManager::TabReadbackRequest {
39 public:
40 TabReadbackRequest(jobject content_view_core,
41 float thumbnail_scale,
42 const TabReadbackCallback& end_callback)
43 : thumbnail_scale_(thumbnail_scale),
44 end_callback_(end_callback),
45 drop_after_readback_(false),
46 weak_factory_(this) {
47 JNIEnv* env = base::android::AttachCurrentThread();
48 j_content_view_core_.Reset(env, content_view_core);
51 virtual ~TabReadbackRequest() {}
53 void Run() {
54 JNIEnv* env = base::android::AttachCurrentThread();
55 content::ReadbackRequestCallback result_callback =
56 base::Bind(&TabReadbackRequest::OnFinishGetTabThumbnailBitmap,
57 weak_factory_.GetWeakPtr());
59 if (j_content_view_core_.is_null()) {
60 result_callback.Run(SkBitmap(), content::READBACK_FAILED);
61 return;
64 content::ContentViewCore* view =
65 content::ContentViewCore::GetNativeContentViewCore(
66 env, j_content_view_core_.obj());
68 if (!view) {
69 result_callback.Run(SkBitmap(), content::READBACK_FAILED);
70 return;
73 DCHECK(view->GetWebContents());
74 view->GetWebContents()->GetRenderViewHost()->LockBackingStore();
76 SkColorType color_type = kN32_SkColorType;
78 // Calling this method with an empty rect will return a bitmap of the size
79 // of the content.
80 view->GetScaledContentBitmap(thumbnail_scale_, color_type, gfx::Rect(),
81 result_callback);
84 void OnFinishGetTabThumbnailBitmap(const SkBitmap& bitmap,
85 content::ReadbackResponse response) {
86 DCHECK(!j_content_view_core_.is_null());
87 JNIEnv* env = base::android::AttachCurrentThread();
88 content::ContentViewCore* view =
89 content::ContentViewCore::GetNativeContentViewCore(
90 env, j_content_view_core_.obj());
92 if (view) {
93 DCHECK(view->GetWebContents());
94 view->GetWebContents()->GetRenderViewHost()->UnlockBackingStore();
97 // TODO(jdduke): Tailor response to different failure values appropriately.
98 if (response != content::READBACK_SUCCESS || drop_after_readback_) {
99 end_callback_.Run(0.f, SkBitmap());
100 return;
103 SkBitmap result_bitmap = bitmap;
104 result_bitmap.setImmutable();
105 end_callback_.Run(thumbnail_scale_, bitmap);
108 void SetToDropAfterReadback() { drop_after_readback_ = true; }
110 private:
111 base::android::ScopedJavaGlobalRef<jobject> j_content_view_core_;
112 const float thumbnail_scale_;
113 TabReadbackCallback end_callback_;
114 bool drop_after_readback_;
116 base::WeakPtrFactory<TabReadbackRequest> weak_factory_;
118 DISALLOW_COPY_AND_ASSIGN(TabReadbackRequest);
121 // static
122 TabContentManager* TabContentManager::FromJavaObject(jobject jobj) {
123 if (!jobj)
124 return NULL;
125 return reinterpret_cast<TabContentManager*>(
126 Java_TabContentManager_getNativePtr(base::android::AttachCurrentThread(),
127 jobj));
130 TabContentManager::TabContentManager(JNIEnv* env,
131 jobject obj,
132 jstring disk_cache_path,
133 jint default_cache_size,
134 jint approximation_cache_size,
135 jint compression_queue_max_size,
136 jint write_queue_max_size,
137 jboolean use_approximation_thumbnail)
138 : weak_java_tab_content_manager_(env, obj), weak_factory_(this) {
139 std::string disk_cache_path_str =
140 base::android::ConvertJavaStringToUTF8(env, disk_cache_path);
141 thumbnail_cache_ = make_scoped_ptr(new ThumbnailCache(
142 disk_cache_path_str, (size_t)default_cache_size,
143 (size_t)approximation_cache_size, (size_t)compression_queue_max_size,
144 (size_t)write_queue_max_size, use_approximation_thumbnail));
145 thumbnail_cache_->AddThumbnailStoreObserver(this);
148 TabContentManager::~TabContentManager() {
151 void TabContentManager::Destroy(JNIEnv* env, jobject obj) {
152 thumbnail_cache_->RemoveThumbnailStoreObserver(this);
153 delete this;
156 void TabContentManager::SetUIResourceProvider(JNIEnv* env,
157 jobject obj,
158 jlong ui_resource_provider_ptr) {
159 ui::UIResourceProvider* ui_resource_provider =
160 reinterpret_cast<ui::UIResourceProvider*>(ui_resource_provider_ptr);
161 SetUIResourceProvider(ui_resource_provider);
164 void TabContentManager::SetUIResourceProvider(
165 ui::UIResourceProvider* ui_resource_provider) {
166 thumbnail_cache_->SetUIResourceProvider(ui_resource_provider);
169 scoped_refptr<cc::Layer> TabContentManager::GetLiveLayer(int tab_id) {
170 scoped_refptr<cc::Layer> layer = live_layer_list_[tab_id];
171 if (!layer.get())
172 return NULL;
174 return layer;
177 scoped_refptr<ThumbnailLayer> TabContentManager::GetStaticLayer(
178 int tab_id,
179 bool force_disk_read) {
180 Thumbnail* thumbnail = thumbnail_cache_->Get(tab_id, force_disk_read, true);
181 scoped_refptr<ThumbnailLayer> static_layer = static_layer_cache_[tab_id];
183 if (!thumbnail || !thumbnail->ui_resource_id()) {
184 if (static_layer.get()) {
185 static_layer->layer()->RemoveFromParent();
186 static_layer_cache_.erase(tab_id);
188 return NULL;
191 if (!static_layer.get()) {
192 static_layer = ThumbnailLayer::Create();
193 static_layer_cache_[tab_id] = static_layer;
196 static_layer->SetThumbnail(thumbnail);
197 return static_layer;
200 void TabContentManager::AttachLiveLayer(int tab_id,
201 scoped_refptr<cc::Layer> layer) {
202 if (!layer.get())
203 return;
205 scoped_refptr<cc::Layer> cached_layer = live_layer_list_[tab_id];
206 if (cached_layer != layer)
207 live_layer_list_[tab_id] = layer;
210 void TabContentManager::DetachLiveLayer(int tab_id,
211 scoped_refptr<cc::Layer> layer) {
212 scoped_refptr<cc::Layer> current_layer = live_layer_list_[tab_id];
213 if (!current_layer.get()) {
214 // Empty cached layer should not exist but it is ok if it happens.
215 return;
218 // We need to remove if we're getting a detach for our current layer or we're
219 // getting a detach with NULL and we have a current layer, which means remove
220 // all layers.
221 if (current_layer.get() &&
222 (layer.get() == current_layer.get() || !layer.get())) {
223 live_layer_list_.erase(tab_id);
227 void TabContentManager::OnFinishDecompressThumbnail(int tab_id,
228 bool success,
229 SkBitmap bitmap) {
230 JNIEnv* env = base::android::AttachCurrentThread();
231 ScopedJavaLocalRef<jobject> java_bitmap;
232 if (success)
233 java_bitmap = gfx::ConvertToJavaBitmap(&bitmap);
235 Java_TabContentManager_notifyDecompressBitmapFinished(
236 env, weak_java_tab_content_manager_.get(env).obj(), tab_id,
237 java_bitmap.obj());
240 jboolean TabContentManager::HasFullCachedThumbnail(JNIEnv* env,
241 jobject obj,
242 jint tab_id) {
243 return thumbnail_cache_->Get(tab_id, false, false) != nullptr;
246 void TabContentManager::CacheTab(JNIEnv* env,
247 jobject obj,
248 jobject tab,
249 jobject content_view_core,
250 jfloat thumbnail_scale) {
251 TabAndroid* tab_android = TabAndroid::GetNativeTab(env, tab);
252 DCHECK(tab_android);
253 int tab_id = tab_android->GetAndroidId();
254 GURL url = tab_android->GetURL();
256 content::ContentViewCore* view =
257 content::ContentViewCore::GetNativeContentViewCore(env,
258 content_view_core);
260 if (thumbnail_cache_->CheckAndUpdateThumbnailMetaData(tab_id, url)) {
261 if (!view ||
262 !view->GetWebContents()
263 ->GetRenderViewHost()
264 ->CanCopyFromBackingStore() ||
265 pending_tab_readbacks_.find(tab_id) != pending_tab_readbacks_.end() ||
266 pending_tab_readbacks_.size() >= kMaxReadbacks) {
267 thumbnail_cache_->Remove(tab_id);
268 return;
271 TabReadbackCallback readback_done_callback =
272 base::Bind(&TabContentManager::PutThumbnailIntoCache,
273 weak_factory_.GetWeakPtr(), tab_id);
274 scoped_ptr<TabReadbackRequest> readback_request =
275 make_scoped_ptr(new TabReadbackRequest(
276 content_view_core, thumbnail_scale, readback_done_callback));
277 pending_tab_readbacks_.set(tab_id, readback_request.Pass());
278 pending_tab_readbacks_.get(tab_id)->Run();
282 void TabContentManager::CacheTabWithBitmap(JNIEnv* env,
283 jobject obj,
284 jobject tab,
285 jobject bitmap,
286 jfloat thumbnail_scale) {
287 TabAndroid* tab_android = TabAndroid::GetNativeTab(env, tab);
288 DCHECK(tab_android);
289 int tab_id = tab_android->GetAndroidId();
290 GURL url = tab_android->GetURL();
292 gfx::JavaBitmap java_bitmap_lock(bitmap);
293 SkBitmap skbitmap = gfx::CreateSkBitmapFromJavaBitmap(java_bitmap_lock);
294 skbitmap.setImmutable();
296 if (thumbnail_cache_->CheckAndUpdateThumbnailMetaData(tab_id, url))
297 PutThumbnailIntoCache(tab_id, thumbnail_scale, skbitmap);
300 void TabContentManager::InvalidateIfChanged(JNIEnv* env,
301 jobject obj,
302 jint tab_id,
303 jstring jurl) {
304 thumbnail_cache_->InvalidateThumbnailIfChanged(
305 tab_id, GURL(base::android::ConvertJavaStringToUTF8(env, jurl)));
308 void TabContentManager::UpdateVisibleIds(JNIEnv* env,
309 jobject obj,
310 jintArray priority) {
311 std::list<int> priority_ids;
312 jsize length = env->GetArrayLength(priority);
313 jint* ints = env->GetIntArrayElements(priority, NULL);
314 for (jsize i = 0; i < length; ++i)
315 priority_ids.push_back(static_cast<int>(ints[i]));
317 env->ReleaseIntArrayElements(priority, ints, JNI_ABORT);
318 thumbnail_cache_->UpdateVisibleIds(priority_ids);
321 void TabContentManager::RemoveTabThumbnail(JNIEnv* env,
322 jobject obj,
323 jint tab_id) {
324 TabReadbackRequestMap::iterator readback_iter =
325 pending_tab_readbacks_.find(tab_id);
326 if (readback_iter != pending_tab_readbacks_.end())
327 readback_iter->second->SetToDropAfterReadback();
328 thumbnail_cache_->Remove(tab_id);
331 void TabContentManager::RemoveTabThumbnailFromDiskAtAndAboveId(
332 JNIEnv* env,
333 jobject obj,
334 jint min_forbidden_id) {
335 thumbnail_cache_->RemoveFromDiskAtAndAboveId(min_forbidden_id);
338 void TabContentManager::GetDecompressedThumbnail(JNIEnv* env,
339 jobject obj,
340 jint tab_id) {
341 base::Callback<void(bool, SkBitmap)> decompress_done_callback =
342 base::Bind(&TabContentManager::OnFinishDecompressThumbnail,
343 weak_factory_.GetWeakPtr(), reinterpret_cast<int>(tab_id));
344 thumbnail_cache_->DecompressThumbnailFromFile(reinterpret_cast<int>(tab_id),
345 decompress_done_callback);
348 void TabContentManager::OnFinishedThumbnailRead(int tab_id) {
349 JNIEnv* env = base::android::AttachCurrentThread();
350 Java_TabContentManager_notifyListenersOfThumbnailChange(
351 env, weak_java_tab_content_manager_.get(env).obj(), tab_id);
354 void TabContentManager::PutThumbnailIntoCache(int tab_id,
355 float thumbnail_scale,
356 const SkBitmap& bitmap) {
357 TabReadbackRequestMap::iterator readback_iter =
358 pending_tab_readbacks_.find(tab_id);
360 if (readback_iter != pending_tab_readbacks_.end())
361 pending_tab_readbacks_.erase(tab_id);
363 if (thumbnail_scale > 0 && !bitmap.empty())
364 thumbnail_cache_->Put(tab_id, bitmap, thumbnail_scale);
367 bool RegisterTabContentManager(JNIEnv* env) {
368 return RegisterNativesImpl(env);
371 // ----------------------------------------------------------------------------
372 // Native JNI methods
373 // ----------------------------------------------------------------------------
375 jlong Init(JNIEnv* env,
376 jobject obj,
377 jstring disk_cache_path,
378 jint default_cache_size,
379 jint approximation_cache_size,
380 jint compression_queue_max_size,
381 jint write_queue_max_size,
382 jboolean use_approximation_thumbnail) {
383 TabContentManager* manager = new TabContentManager(
384 env, obj, disk_cache_path, default_cache_size, approximation_cache_size,
385 compression_queue_max_size, write_queue_max_size,
386 use_approximation_thumbnail);
387 return reinterpret_cast<intptr_t>(manager);
390 } // namespace android
391 } // namespace chrome