chromium/components/thin_webview/internal/thin_webview.cc

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

#include "components/thin_webview/internal/thin_webview.h"

#include "base/android/jni_android.h"
#include "cc/input/browser_controls_offset_tags_info.h"
#include "cc/input/browser_controls_state.h"
#include "cc/slim/layer.h"
#include "components/embedder_support/android/delegate/web_contents_delegate_android.h"
#include "components/thin_webview/thin_webview_initializer.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/web_contents.h"

// Must come after all headers that specialize FromJniType() / ToJniType().
#include "components/thin_webview/internal/jni_headers/ThinWebViewImpl_jni.h"

using base::android::JavaParamRef;
using web_contents_delegate_android::WebContentsDelegateAndroid;

namespace thin_webview {
namespace android {

jlong JNI_ThinWebViewImpl_Init(JNIEnv* env,
                               const JavaParamRef<jobject>& obj,
                               const JavaParamRef<jobject>& jcompositor_view,
                               const JavaParamRef<jobject>& jwindow_android) {
  CompositorView* compositor_view =
      CompositorViewImpl::FromJavaObject(jcompositor_view);
  ui::WindowAndroid* window_android =
      ui::WindowAndroid::FromJavaWindowAndroid(jwindow_android);
  ThinWebView* view =
      new ThinWebView(env, obj, compositor_view, window_android);
  return reinterpret_cast<intptr_t>(view);
}

ThinWebView::ThinWebView(JNIEnv* env,
                         jobject obj,
                         CompositorView* compositor_view,
                         ui::WindowAndroid* window_android)
    : obj_(env, obj),
      compositor_view_(compositor_view),
      window_android_(window_android),
      web_contents_(nullptr) {}

ThinWebView::~ThinWebView() = default;

void ThinWebView::Destroy(JNIEnv* env, const JavaParamRef<jobject>& object) {
  delete this;
}

void ThinWebView::PrimaryPageChanged(content::Page& page) {
  // Disable browser controls when used for thin webview.
  web_contents_->UpdateBrowserControlsState(cc::BrowserControlsState::kHidden,
                                            cc::BrowserControlsState::kHidden,
                                            false, std::nullopt);
}

void ThinWebView::SetWebContents(
    JNIEnv* env,
    const JavaParamRef<jobject>& obj,
    const JavaParamRef<jobject>& jweb_contents,
    const JavaParamRef<jobject>& jweb_contents_delegate) {
  content::WebContents* web_contents =
      content::WebContents::FromJavaWebContents(jweb_contents);
  WebContentsDelegateAndroid* delegate =
      jweb_contents_delegate.is_null()
          ? nullptr
          : new WebContentsDelegateAndroid(env, jweb_contents_delegate);
  SetWebContents(web_contents, delegate);
}

void ThinWebView::SetWebContents(content::WebContents* web_contents,
                                 WebContentsDelegateAndroid* delegate) {
  DCHECK(web_contents);
  web_contents_ = web_contents;
  Observe(web_contents_);
  ui::ViewAndroid* view_android = web_contents_->GetNativeView();
  if (view_android->parent() != window_android_) {
    window_android_->AddChild(view_android);
  }

  compositor_view_->SetRootLayer(web_contents_->GetNativeView()->GetLayer());
  ResizeWebContents(view_size_);
  web_contents_delegate_.reset(delegate);
  if (delegate)
    web_contents->SetDelegate(delegate);

  ThinWebViewInitializer::GetInstance()->AttachTabHelpers(web_contents);
}

void ThinWebView::SizeChanged(JNIEnv* env,
                              const JavaParamRef<jobject>& object,
                              jint width,
                              jint height) {
  view_size_ = gfx::Size(width, height);

  // TODO(shaktisahu): If we want to use a different size for WebContents, e.g.
  // showing full screen contents instead inside this view, don't do the resize.
  if (web_contents_)
    ResizeWebContents(view_size_);
}

void ThinWebView::ResizeWebContents(const gfx::Size& size) {
  if (!web_contents_)
    return;

  web_contents_->GetNativeView()->OnPhysicalBackingSizeChanged(size);
  web_contents_->GetNativeView()->OnSizeChanged(size.width(), size.height());
}

}  // namespace android
}  // namespace thin_webview