Skip to content

Commit

Permalink
Notify clients when the web engine wants to create a new Window
Browse files Browse the repository at this point in the history
Certain navigations (like target=_blank links) require the web
engine to create a new Window. In those cases Chromium creates a
new WebContents object and notifies the client (Wolvic in this case)
about that. However the current architecture of Wolvic does
not allow us to properly use that new WebContents object to
create a new tab.

To circumvent that, we can use the fact that Chromium cancels
the creation of a new window if the ownership of the WebContents
object is not taken when AddNewContents() is called on the delegate.
We precisely do that (we let the new WebContents die) but we
use the target_url (the URL of the new window) to notify the
client (Wolvic) via a new method called onCreateNewWindow() that
was added to a new object called WolvicWebContentsDelegate which
directly inherits from WebContentsDelegateAndroid (the one we
were using previously).

The client just needs to override that onCreateWindow() method
and trigger the creation of a new window there using the passed
in URL.
  • Loading branch information
svillar committed Nov 23, 2023
1 parent ec1a77d commit ebcd9cb
Show file tree
Hide file tree
Showing 8 changed files with 119 additions and 13 deletions.
8 changes: 6 additions & 2 deletions wolvic/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,6 @@ shared_library("libcontent_native") {
"browser/session_settings.cc",
"browser/session_settings.h",
"browser/session_settings_jni.cc",
"browser/wolvic_contents.cc",
"browser/wolvic_contents.h",
"browser/tab_jni.cc",
"browser/vr/moz_external_vr.h",
"browser/vr/wolvic_xr_integration_client.cc",
Expand All @@ -54,6 +52,10 @@ shared_library("libcontent_native") {
"browser/vr/wvr_manager.h",
"browser/vr/wvr_thread.cc",
"browser/vr/wvr_thread.h",
"browser/wolvic_contents.cc",
"browser/wolvic_contents.h",
"browser/wolvic_web_contents_delegate.cc",
"browser/wolvic_web_contents_delegate.h",
"renderer/browser_exposed_renderer_interfaces.cc",
"renderer/browser_exposed_renderer_interfaces.h",
"renderer/wolvic_content_renderer_client.cc",
Expand Down Expand Up @@ -214,6 +216,7 @@ generate_jni("jni_headers") {
"java/org/chromium/wolvic/Tab.java",
"java/org/chromium/wolvic/VRManager.java",
"java/org/chromium/wolvic/WVRSurfaceTexture.java",
"java/org/chromium/wolvic/WolvicWebContentsDelegate.java",
]
}

Expand All @@ -225,6 +228,7 @@ android_library("wolvic_java") {
"java/org/chromium/wolvic/TabCompositorView.java",
"java/org/chromium/wolvic/VRManager.java",
"java/org/chromium/wolvic/WVRSurfaceTexture.java",
"java/org/chromium/wolvic/WolvicWebContentsDelegate.java",
]
annotation_processor_deps = [ "//base/android/jni_generator:jni_processor" ]
deps = [
Expand Down
6 changes: 2 additions & 4 deletions wolvic/browser/tab_jni.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@

#include "wolvic/jni_headers/Tab_jni.h"

#include "components/embedder_support/android/delegate/web_contents_delegate_android.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/navigation_controller.h"
#include "content/public/browser/web_contents.h"
#include "url/gurl.h"
#include "wolvic/browser/wolvic_contents.h"
#include "wolvic/browser/wolvic_web_contents_delegate.h"
#include "wolvic/wolvic_browser_context.h"
#include "wolvic/wolvic_content_browser_client.h"

Expand Down Expand Up @@ -47,10 +47,8 @@ void JNI_Tab_SetWebContentsDelegate(
DCHECK(web_contents);

auto* wolvic_contents = WolvicContents::FromWebContents(web_contents);
DCHECK(wolvic_contents);

auto web_contents_delegate =
std::make_unique<web_contents_delegate_android::WebContentsDelegateAndroid>(env, jweb_contents_delegate);
std::make_unique<WolvicWebContentsDelegate>(env, jweb_contents_delegate);
wolvic_contents->SetDelegate(std::move(web_contents_delegate));
}

Expand Down
3 changes: 2 additions & 1 deletion wolvic/browser/wolvic_contents.cc
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

#include "wolvic/wolvic_browser_context.h"
#include "wolvic/wolvic_content_browser_client.h"
#include "wolvic/browser/wolvic_web_contents_delegate.h"

using content::WebContents;

Expand Down Expand Up @@ -75,7 +76,7 @@ WolvicContents::DidFinishNavigation(content::NavigationHandle* navigation_handle
}

void
WolvicContents::SetDelegate(std::unique_ptr<web_contents_delegate_android::WebContentsDelegateAndroid> delegate) {
WolvicContents::SetDelegate(std::unique_ptr<WolvicWebContentsDelegate> delegate) {
web_contents_delegate_ = std::move(delegate);
web_contents_->SetDelegate(web_contents_delegate_.get());
}
Expand Down
7 changes: 4 additions & 3 deletions wolvic/browser/wolvic_contents.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,12 @@
#ifndef WOLVIC_BROWSER_WOLVIC_CONTENTS_H_
#define WOLVIC_BROWSER_WOLVIC_CONTENTS_H_

#include "components/embedder_support/android/delegate/web_contents_delegate_android.h"
#include "content/public/browser/web_contents_observer.h"

namespace wolvic {

class WolvicWebContentsDelegate;

class WolvicContents : public content::WebContentsObserver {
public:
static WolvicContents* FromWebContents(content::WebContents* web_contents);
Expand All @@ -24,11 +25,11 @@ class WolvicContents : public content::WebContentsObserver {

void DidFinishNavigation(content::NavigationHandle*) override;

void SetDelegate(std::unique_ptr<web_contents_delegate_android::WebContentsDelegateAndroid> delegate);
void SetDelegate(std::unique_ptr<WolvicWebContentsDelegate>);

private:
std::unique_ptr<content::WebContents> web_contents_;
std::unique_ptr<web_contents_delegate_android::WebContentsDelegateAndroid> web_contents_delegate_;
std::unique_ptr<WolvicWebContentsDelegate> web_contents_delegate_;
};

} // namespace content
Expand Down
50 changes: 50 additions & 0 deletions wolvic/browser/wolvic_web_contents_delegate.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "wolvic/browser/wolvic_web_contents_delegate.h"

#include "base/android/jni_android.h"
#include "base/android/scoped_java_ref.h"
#include "content/public/browser/web_contents.h"
#include "wolvic/browser/wolvic_contents.h"
#include "wolvic/jni_headers/WolvicWebContentsDelegate_jni.h"
#include "url/android/gurl_android.h"

namespace wolvic {

WolvicWebContentsDelegate::WolvicWebContentsDelegate(JNIEnv* env, jobject obj)
: WebContentsDelegateAndroid(env, obj) {}

WolvicWebContentsDelegate::~WolvicWebContentsDelegate() = default;

using base::android::ScopedJavaLocalRef;

// Called by web_contents_impl.cc whenever a navigation
// requires the creation of a new window (for example
// a link with target=_blank
void WolvicWebContentsDelegate::AddNewContents(
content::WebContents* source,
std::unique_ptr<content::WebContents> new_contents,
const GURL& target_url,
WindowOpenDisposition disposition,
const blink::mojom::WindowFeatures& window_features,
bool user_gesture,
bool* was_blocked) {

JNIEnv* env = base::android::AttachCurrentThread();
ScopedJavaLocalRef<jobject> java_delegate = GetJavaDelegate(env);
DCHECK(java_delegate.obj());

// We let new_contents die on purpouse (by not assigning the
// unique_ptr to any local variable/attribute because that way
// we are telling the web engine that we do not want a new
// window to be created. We'll in any case use the target_urlformatter
// to notify the client (Wolvic) so that it can create the window
// for the new URL on its own.
ScopedJavaLocalRef<jobject> java_gurl =
url::GURLAndroid::FromNativeGURL(env, target_url);
Java_WolvicWebContentsDelegate_onCreateNewWindow(env, java_delegate, java_gurl);
}

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

#ifndef WOLVIC_BROWSER_WOLVIC_WEB_CONTENTS_DELEGATE_H_
#define WOLVIC_BROWSER_WOLVIC_WEB_CONTENTS_DELEGATE_H_

#include "components/embedder_support/android/delegate/web_contents_delegate_android.h"

namespace wolvic {

class WolvicWebContentsDelegate
: public web_contents_delegate_android::WebContentsDelegateAndroid {
public:
WolvicWebContentsDelegate(JNIEnv* env, jobject obj);
~WolvicWebContentsDelegate() override;

// See //android_webview/docs/how-does-on-create-window-work.md for more
// details.
void AddNewContents(content::WebContents* source,
std::unique_ptr<content::WebContents> new_contents,
const GURL& target_url,
WindowOpenDisposition disposition,
const blink::mojom::WindowFeatures& window_features,
bool user_gesture,
bool* was_blocked) final;

private:
std::unique_ptr<content::WebContents> new_contents_;
};

}// namespace wolvic

#endif // WOLVIC_BROWSER_WOLVIC_WEB_CONTENTS_DELEGATE_H_
6 changes: 3 additions & 3 deletions wolvic/java/org/chromium/wolvic/Tab.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
import org.chromium.base.ContextUtils;
import org.chromium.base.annotations.JNINamespace;
import org.chromium.base.annotations.NativeMethods;
import org.chromium.components.embedder_support.delegate.WebContentsDelegateAndroid;
import org.chromium.components.embedder_support.view.ContentView;
import org.chromium.components.url_formatter.UrlFormatter;
import org.chromium.content_public.browser.ImeAdapter;
Expand All @@ -21,6 +20,7 @@
import org.chromium.ui.base.ActivityWindowAndroid;
import org.chromium.ui.base.IntentRequestTracker;
import org.chromium.ui.base.ViewAndroidDelegate;
import org.chromium.wolvic.WolvicWebContentsDelegate;

@JNINamespace("wolvic")
public class Tab {
Expand All @@ -35,7 +35,7 @@ public WebContents createWebContents(boolean is_off_the_record) {
}

public void setWebContentsDelegate(
WebContents webContents, WebContentsDelegateAndroid delegate) {
WebContents webContents, WolvicWebContentsDelegate delegate) {
TabJni.get().setWebContentsDelegate(webContents, delegate);
}

Expand Down Expand Up @@ -96,6 +96,6 @@ public ImeAdapter getImeAdapter() {
@NativeMethods
public interface Natives {
WebContents createWebContents(boolean is_off_the_record);
void setWebContentsDelegate(WebContents webContents, WebContentsDelegateAndroid delegate);
void setWebContentsDelegate(WebContents webContents, WolvicWebContentsDelegate delegate);
}
}
18 changes: 18 additions & 0 deletions wolvic/java/org/chromium/wolvic/WolvicWebContentsDelegate.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

package org.chromium.wolvic;

import androidx.annotation.VisibleForTesting;

import org.chromium.url.GURL;
import org.chromium.base.annotations.CalledByNative;
import org.chromium.base.annotations.JNINamespace;
import org.chromium.components.embedder_support.delegate.WebContentsDelegateAndroid;

@JNINamespace("wolvic")
public abstract class WolvicWebContentsDelegate extends WebContentsDelegateAndroid {
@CalledByNative
public abstract void onCreateNewWindow(GURL url);
}

0 comments on commit ebcd9cb

Please sign in to comment.