Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Set up a Shell class entry for Cobalt #4612

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions cobalt/android/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,7 @@ shared_library("libcobalt_content_shell_content_view") {
"//content/shell:content_shell_app",
"//content/shell:content_shell_lib",
"//content/shell:pak",
"//content/shell/android:content_shell_jni_headers",
"//media",
"//skia",
"//starboard/android/shared:starboard_jni_state",
Expand All @@ -268,8 +269,19 @@ shared_library("libcobalt_content_shell_content_view") {
"//cobalt/cobalt_content_browser_client.h",
"//cobalt/cobalt_main_delegate.cc",
"//cobalt/cobalt_main_delegate.h",
"//cobalt/cobalt_shell.cc",
"//cobalt/cobalt_shell.h",
"cobalt_library_loader.cc",
]

# Content shell Android parts
sources += [
"//cobalt/android/shell_manager.cc",
"//cobalt/android/shell_manager.h",
"//cobalt/android/shell_platform_delegate_android.cc",
"//cobalt/android/shell_web_contents_view_delegate_android.cc",
]

configs -= [ "//build/config/android:hide_all_but_jni_onload" ]
configs += [ "//build/config/android:hide_all_but_jni" ]
}
Expand Down
80 changes: 80 additions & 0 deletions cobalt/android/shell_manager.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "cobalt/android/shell_manager.h"

#include "base/android/jni_android.h"
#include "base/android/jni_string.h"
#include "base/android/scoped_java_ref.h"
#include "base/functional/bind.h"
#include "base/lazy_instance.h"
#include "cobalt/cobalt_shell.h"
#include "content/public/browser/web_contents.h"
#include "content/shell/android/content_shell_jni_headers/ShellManager_jni.h"
#include "content/shell/browser/shell_browser_context.h"
#include "content/shell/browser/shell_content_browser_client.h"
#include "url/gurl.h"

// Note: Origin of this file is content/shell/shell_manager.cc from m114

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

namespace {

struct GlobalState {
GlobalState() {}
base::android::ScopedJavaGlobalRef<jobject> j_shell_manager;
};

base::LazyInstance<GlobalState>::DestructorAtExit g_global_state =
LAZY_INSTANCE_INITIALIZER;

} // namespace

namespace cobalt {

ScopedJavaLocalRef<jobject> CreateShellView(content::Shell* shell) {
JNIEnv* env = base::android::AttachCurrentThread();
return content::Java_ShellManager_createShell(
env, g_global_state.Get().j_shell_manager,
reinterpret_cast<intptr_t>(shell));
}

void RemoveShellView(const JavaRef<jobject>& shell_view) {
JNIEnv* env = base::android::AttachCurrentThread();
content::Java_ShellManager_removeShell(
env, g_global_state.Get().j_shell_manager, shell_view);
}

} // namespace cobalt

// Note: Below tracks generated Java code, which is currently generated
// in content, not cobalt namespace.

namespace content {

static void JNI_ShellManager_Init(JNIEnv* env,
const JavaParamRef<jobject>& obj) {
g_global_state.Get().j_shell_manager.Reset(obj);
}

void JNI_ShellManager_LaunchShell(JNIEnv* env,
const JavaParamRef<jstring>& jurl) {
content::ShellBrowserContext* browserContext =
content::ShellContentBrowserClient::Get()->browser_context();
GURL url(base::android::ConvertJavaStringToUTF8(env, jurl));

// Cobalt specific shell creation
cobalt::CobaltShell::CreateNewWindow(browserContext, url, nullptr,
kaidokert marked this conversation as resolved.
Show resolved Hide resolved
gfx::Size());
}

void DestroyShellManager() {
JNIEnv* env = base::android::AttachCurrentThread();
content::Java_ShellManager_destroy(env, g_global_state.Get().j_shell_manager);
}

} // namespace content
44 changes: 44 additions & 0 deletions cobalt/android/shell_manager.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CONTENT_SHELL_ANDROID_SHELL_MANAGER_H_
#define CONTENT_SHELL_ANDROID_SHELL_MANAGER_H_

#include <jni.h>

#include "base/android/jni_android.h"
#include "base/android/scoped_java_ref.h"

// Note: Origin of this file is content/shell/shell_manager.h from m114

namespace content {
class Shell;
}

namespace cc {
class Layer;
}
kaidokert marked this conversation as resolved.
Show resolved Hide resolved

namespace cobalt {

// Creates an Android specific shell view, which is our version of a shell
// window. This view holds the controls and content views necessary to
// render a shell window. Returns the java object representing the shell view.
// object.
base::android::ScopedJavaLocalRef<jobject> CreateShellView(
content::Shell* shell);

// Removes a previously created shell view.
void RemoveShellView(const base::android::JavaRef<jobject>& shell_view);

} // namespace cobalt
namespace content {

// Destroys the ShellManager on app exit. Must not use the above functions
// after this is called.
void DestroyShellManager();

} // namespace content

#endif // CONTENT_SHELL_ANDROID_SHELL_MANAGER_H_
172 changes: 172 additions & 0 deletions cobalt/android/shell_platform_delegate_android.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "content/shell/browser/shell_platform_delegate.h"

#include <jni.h>

#include "base/android/jni_string.h"
#include "base/android/scoped_java_ref.h"
#include "base/command_line.h"
#include "base/containers/contains.h"
#include "base/notreached.h"
#include "base/strings/string_piece.h"
#include "cobalt/android/shell_manager.h"
#include "content/public/browser/render_widget_host_view.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/content_switches.h"
#include "content/shell/android/content_shell_jni_headers/Shell_jni.h"
#include "content/shell/browser/shell.h"

using base::android::AttachCurrentThread;
using base::android::ConvertUTF8ToJavaString;
using base::android::JavaParamRef;
using base::android::ScopedJavaLocalRef;

// Note: Origin of this file is
// content/shell/browser/shell_platform_delegate_android.cc from m114

namespace content {

struct ShellPlatformDelegate::ShellData {
kaidokert marked this conversation as resolved.
Show resolved Hide resolved
base::android::ScopedJavaGlobalRef<jobject> java_object;
};

struct ShellPlatformDelegate::PlatformData {};

ShellPlatformDelegate::ShellPlatformDelegate() = default;

void ShellPlatformDelegate::Initialize(const gfx::Size& default_window_size) {
// |platform_| is not used on this platform.
}

ShellPlatformDelegate::~ShellPlatformDelegate() {
content::DestroyShellManager();
}

void ShellPlatformDelegate::CreatePlatformWindow(
Shell* shell,
const gfx::Size& initial_size) {
DCHECK(!base::Contains(shell_data_map_, shell));
ShellData& shell_data = shell_data_map_[shell];

// Cobalt specific ShellView creation
shell_data.java_object.Reset(cobalt::CreateShellView(shell));
}

void ShellPlatformDelegate::CleanUp(Shell* shell) {
JNIEnv* env = AttachCurrentThread();
DCHECK(base::Contains(shell_data_map_, shell));
ShellData& shell_data = shell_data_map_[shell];

// Cobalt specific ShellView removal
cobalt::RemoveShellView(shell_data.java_object);

if (!shell_data.java_object.is_null()) {
Java_Shell_onNativeDestroyed(env, shell_data.java_object);
}

shell_data_map_.erase(shell);
}

void ShellPlatformDelegate::SetContents(Shell* shell) {
JNIEnv* env = AttachCurrentThread();
DCHECK(base::Contains(shell_data_map_, shell));
ShellData& shell_data = shell_data_map_[shell];

Java_Shell_initFromNativeTabContents(
env, shell_data.java_object, shell->web_contents()->GetJavaWebContents());
}

void ShellPlatformDelegate::ResizeWebContent(Shell* shell,
const gfx::Size& content_size) {
shell->web_contents()->GetRenderWidgetHostView()->SetSize(content_size);
}

void ShellPlatformDelegate::EnableUIControl(Shell* shell,
UIControl control,
bool is_enabled) {
JNIEnv* env = AttachCurrentThread();
DCHECK(base::Contains(shell_data_map_, shell));
ShellData& shell_data = shell_data_map_[shell];

if (shell_data.java_object.is_null()) {
return;
}
Java_Shell_enableUiControl(env, shell_data.java_object, control, is_enabled);
}

void ShellPlatformDelegate::SetAddressBarURL(Shell* shell, const GURL& url) {
JNIEnv* env = AttachCurrentThread();
DCHECK(base::Contains(shell_data_map_, shell));
ShellData& shell_data = shell_data_map_[shell];

ScopedJavaLocalRef<jstring> j_url = ConvertUTF8ToJavaString(env, url.spec());
Java_Shell_onUpdateUrl(env, shell_data.java_object, j_url);
}

void ShellPlatformDelegate::SetIsLoading(Shell* shell, bool loading) {
JNIEnv* env = AttachCurrentThread();
DCHECK(base::Contains(shell_data_map_, shell));
ShellData& shell_data = shell_data_map_[shell];

Java_Shell_setIsLoading(env, shell_data.java_object, loading);
}

void ShellPlatformDelegate::SetTitle(Shell* shell,
const std::u16string& title) {}

void ShellPlatformDelegate::MainFrameCreated(Shell* shell) {}

bool ShellPlatformDelegate::DestroyShell(Shell* shell) {
return false; // Shell destroys itself.
}

void ShellPlatformDelegate::ToggleFullscreenModeForTab(
Shell* shell,
WebContents* web_contents,
bool enter_fullscreen) {
JNIEnv* env = AttachCurrentThread();
DCHECK(base::Contains(shell_data_map_, shell));
ShellData& shell_data = shell_data_map_[shell];

Java_Shell_toggleFullscreenModeForTab(env, shell_data.java_object,
enter_fullscreen);
}

bool ShellPlatformDelegate::IsFullscreenForTabOrPending(
Shell* shell,
const WebContents* web_contents) const {
JNIEnv* env = AttachCurrentThread();
DCHECK(base::Contains(shell_data_map_, shell));
const ShellData& shell_data = shell_data_map_.find(shell)->second;

return Java_Shell_isFullscreenForTabOrPending(env, shell_data.java_object);
}

void ShellPlatformDelegate::SetOverlayMode(Shell* shell,
bool use_overlay_mode) {
JNIEnv* env = base::android::AttachCurrentThread();
DCHECK(base::Contains(shell_data_map_, shell));
ShellData& shell_data = shell_data_map_[shell];

return Java_Shell_setOverlayMode(env, shell_data.java_object,
use_overlay_mode);
}

void ShellPlatformDelegate::LoadProgressChanged(Shell* shell, double progress) {
JNIEnv* env = AttachCurrentThread();
DCHECK(base::Contains(shell_data_map_, shell));
ShellData& shell_data = shell_data_map_[shell];

Java_Shell_onLoadProgressChanged(env, shell_data.java_object, progress);
}

// static
void JNI_Shell_CloseShell(JNIEnv* env, jlong shellPtr) {
Shell* shell = reinterpret_cast<Shell*>(shellPtr);
shell->Close();
}

} // namespace content
33 changes: 33 additions & 0 deletions cobalt/android/shell_web_contents_view_delegate_android.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// Copyright 2013 The Chromium Authors
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this file needed? which part is changes after it is copied from content/shell/browser?

Copy link
Member Author

@kaidokert kaidokert Jan 14, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Technically it is not currently needed. I only copied it over because all of those 4 are grouped together in gn in a single block.

I'm expecting we may need to override our own Delegate soon however, too.

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

#include "content/shell/browser/shell_web_contents_view_delegate.h"

#include <memory>

#include "base/command_line.h"
#include "content/public/browser/context_menu_params.h"
#include "content/public/browser/web_contents.h"
#include "content/shell/browser/shell_web_contents_view_delegate_creator.h"

namespace content {

std::unique_ptr<WebContentsViewDelegate> CreateShellWebContentsViewDelegate(
WebContents* web_contents) {
return std::make_unique<ShellWebContentsViewDelegate>(web_contents);
}

ShellWebContentsViewDelegate::ShellWebContentsViewDelegate(
WebContents* web_contents)
: web_contents_(web_contents) {
DCHECK(web_contents_); // Avoids 'unused private field' build error.
}

ShellWebContentsViewDelegate::~ShellWebContentsViewDelegate() {}

void ShellWebContentsViewDelegate::ShowContextMenu(
RenderFrameHost& render_frame_host,
const ContextMenuParams& params) {}

} // namespace content
Loading
Loading