chromium/chrome/browser/android/compositor/scene_layer/tab_list_scene_layer.cc

// Copyright 2015 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/android/compositor/scene_layer/tab_list_scene_layer.h"

#include <vector>

#include "base/android/jni_array.h"
#include "base/android/jni_string.h"
#include "chrome/browser/android/compositor/layer/content_layer.h"
#include "chrome/browser/android/compositor/layer/tab_layer.h"
#include "chrome/browser/android/compositor/tab_content_manager.h"
#include "ui/android/resources/resource_manager_impl.h"

// Must come after all headers that specialize FromJniType() / ToJniType().
#include "chrome/android/chrome_jni_headers/TabListSceneLayer_jni.h"

using base::android::JavaParamRef;
using base::android::JavaRef;

namespace android {

TabListSceneLayer::TabListSceneLayer(JNIEnv* env, const JavaRef<jobject>& jobj)
    : SceneLayer(env, jobj),
      content_obscures_self_(false),
      resource_manager_(nullptr),
      tab_content_manager_(nullptr),
      background_color_(SK_ColorWHITE),
      own_tree_(cc::slim::Layer::Create()) {
  layer()->AddChild(own_tree_);
}

TabListSceneLayer::~TabListSceneLayer() {}

void TabListSceneLayer::BeginBuildingFrame(JNIEnv* env,
                                           const JavaParamRef<jobject>& jobj) {
  content_obscures_self_ = false;

  // Remove (and re-add) all layers every frame to guarantee that z-order
  // matches PutTabLayer call order.
  for (auto tab : tab_map_) {
    tab.second->layer()->RemoveFromParent();
  }
}

void TabListSceneLayer::FinishBuildingFrame(JNIEnv* env,
                                            const JavaParamRef<jobject>& jobj) {
  // Destroy all tabs that weren't used this frame.
  for (auto it = tab_map_.cbegin(); it != tab_map_.cend();) {
    if (visible_tabs_this_frame_.find(it->first) ==
        visible_tabs_this_frame_.end()) {
      it = tab_map_.erase(it);
    } else {
      ++it;
    }
  }
  visible_tabs_this_frame_.clear();
}

void TabListSceneLayer::UpdateLayer(
    JNIEnv* env,
    const base::android::JavaParamRef<jobject>& jobj,
    jint background_color,
    jfloat viewport_x,
    jfloat viewport_y,
    jfloat viewport_width,
    jfloat viewport_height) {
  background_color_ = background_color;
  own_tree_->SetPosition(gfx::PointF(viewport_x, viewport_y));
  own_tree_->SetBounds(gfx::Size(viewport_width, viewport_height));
}

void TabListSceneLayer::PutTabLayer(JNIEnv* env,
                                    const JavaParamRef<jobject>& jobj,
                                    jint id,
                                    jint toolbar_resource_id,
                                    jint shadow_resource_id,
                                    jint contour_resource_id,
                                    jint border_resource_id,
                                    jint border_inner_shadow_resource_id,
                                    jboolean can_use_live_layer,
                                    jint tab_background_color,
                                    jboolean incognito,
                                    jfloat x,
                                    jfloat y,
                                    jfloat width,
                                    jfloat height,
                                    jfloat content_width,
                                    jfloat content_height,
                                    jfloat shadow_width,
                                    jfloat shadow_height,
                                    jfloat alpha,
                                    jfloat border_alpha,
                                    jfloat border_inner_shadow_alpha,
                                    jfloat contour_alpha,
                                    jfloat shadow_alpha,
                                    jfloat static_to_view_blend,
                                    jfloat border_scale,
                                    jfloat saturation,
                                    jboolean show_toolbar,
                                    jint default_theme_color,
                                    jint toolbar_background_color,
                                    jboolean anonymize_toolbar,
                                    jint toolbar_textbox_resource_id,
                                    jint toolbar_textbox_background_color,
                                    jfloat content_offset) {
  DCHECK(tab_content_manager_)
      << "TabContentManager must be set before updating the TabLayer";
  DCHECK(resource_manager_)
      << "ResourceManager must be set before updating the TabLayer";

  scoped_refptr<TabLayer> layer;
  auto iter = tab_map_.find(id);
  if (iter != tab_map_.end()) {
    layer = iter->second;
  } else {
    layer =
        TabLayer::Create(incognito, resource_manager_, tab_content_manager_);
    tab_map_.insert(TabMap::value_type(id, layer));
  }
  own_tree_->AddChild(layer->layer());
  visible_tabs_this_frame_.insert(id);

  DCHECK(layer);
  if (layer) {
    // TODO(meiliang): This method pass another argument, a resource that can be
    // used to indicate the currently selected tab for the TabLayer.
    layer->SetProperties(
        id, can_use_live_layer, toolbar_resource_id, shadow_resource_id,
        contour_resource_id, border_resource_id,
        border_inner_shadow_resource_id, tab_background_color, x, y, width,
        height, shadow_width, shadow_height, alpha, border_alpha,
        border_inner_shadow_alpha, contour_alpha, shadow_alpha, border_scale,
        saturation, static_to_view_blend, content_width, content_height,
        content_width, show_toolbar, default_theme_color,
        toolbar_background_color, anonymize_toolbar,
        toolbar_textbox_resource_id, toolbar_textbox_background_color,
        content_offset);
  }

  gfx::RectF self(own_tree_->position(), gfx::SizeF(own_tree_->bounds()));
  gfx::RectF content(x, y, width, height);

  content_obscures_self_ |= content.Contains(self);
}

void TabListSceneLayer::PutBackgroundLayer(
    JNIEnv* env,
    const base::android::JavaParamRef<jobject>& jobj,
    jint resource_id,
    jfloat alpha,
    jint top_offset) {
  int ui_resource_id = resource_manager_->GetUIResourceId(
      ui::ANDROID_RESOURCE_TYPE_DYNAMIC, resource_id);
  if (ui_resource_id == 0) {
    return;
  }

  if (!background_layer_) {
    background_layer_ = cc::slim::UIResourceLayer::Create();
    background_layer_->SetIsDrawable(true);
    own_tree_->AddChild(background_layer_);
  }
  DCHECK(background_layer_);
  background_layer_->SetUIResourceId(ui_resource_id);
  gfx::Size size =
      resource_manager_
          ->GetResource(ui::ANDROID_RESOURCE_TYPE_DYNAMIC, resource_id)
          ->size();
  background_layer_->SetBounds(size);
  background_layer_->SetOpacity(alpha);
  background_layer_->SetPosition(gfx::PointF(0, top_offset));
}

void TabListSceneLayer::SetDependencies(
    JNIEnv* env,
    const base::android::JavaParamRef<jobject>& jobj,
    const base::android::JavaParamRef<jobject>& jtab_content_manager,
    const base::android::JavaParamRef<jobject>& jresource_manager) {
  if (!tab_content_manager_) {
    tab_content_manager_ =
        TabContentManager::FromJavaObject(jtab_content_manager);
  }
  if (!resource_manager_) {
    resource_manager_ =
        ui::ResourceManagerImpl::FromJavaObject(jresource_manager);
  }
}

void TabListSceneLayer::OnDetach() {
  SceneLayer::OnDetach();
  for (auto tab : tab_map_) {
    tab.second->layer()->RemoveFromParent();
  }
  tab_map_.clear();
}

bool TabListSceneLayer::ShouldShowBackground() {
  return !content_obscures_self_;
}

SkColor TabListSceneLayer::GetBackgroundColor() {
  return background_color_;
}

static jlong JNI_TabListSceneLayer_Init(JNIEnv* env,
                                        const JavaParamRef<jobject>& jobj) {
  // This will automatically bind to the Java object and pass ownership there.
  TabListSceneLayer* scene_layer = new TabListSceneLayer(env, jobj);
  return reinterpret_cast<intptr_t>(scene_layer);
}

}  // namespace android