diff options
Diffstat (limited to 'chromium/weblayer/browser/js_communication')
7 files changed, 382 insertions, 0 deletions
diff --git a/chromium/weblayer/browser/js_communication/web_message_browsertest.cc b/chromium/weblayer/browser/js_communication/web_message_browsertest.cc new file mode 100644 index 00000000000..8d147c10be7 --- /dev/null +++ b/chromium/weblayer/browser/js_communication/web_message_browsertest.cc @@ -0,0 +1,112 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "weblayer/public/js_communication/web_message.h" + +#include "base/callback.h" +#include "base/run_loop.h" +#include "base/strings/utf_string_conversions.h" +#include "weblayer/public/js_communication/web_message.h" +#include "weblayer/public/js_communication/web_message_host.h" +#include "weblayer/public/js_communication/web_message_host_factory.h" +#include "weblayer/public/js_communication/web_message_reply_proxy.h" +#include "weblayer/public/navigation.h" +#include "weblayer/public/navigation_controller.h" +#include "weblayer/public/tab.h" +#include "weblayer/shell/browser/shell.h" +#include "weblayer/test/weblayer_browser_test.h" +#include "weblayer/test/weblayer_browser_test_utils.h" + +namespace weblayer { + +namespace { + +class WebMessageHostImpl; +WebMessageHostImpl* current_connection = nullptr; + +// WebMessageHost implementation that records contents of OnPostMessage(). +class WebMessageHostImpl : public WebMessageHost { + public: + WebMessageHostImpl(base::RepeatingClosure quit_closure, + const std::string& origin_string, + bool is_main_frame, + WebMessageReplyProxy* proxy) + : quit_closure_(quit_closure), proxy_(proxy) { + current_connection = this; + } + ~WebMessageHostImpl() override { + if (current_connection == this) + current_connection = nullptr; + } + + std::vector<base::string16>& messages() { return messages_; } + + // WebMessageHost: + void OnPostMessage(std::unique_ptr<WebMessage> message) override { + messages_.push_back(std::move(message->message)); + if (++call_count_ == 1) { + // First time called, send a message to the page. + std::unique_ptr<WebMessage> m2 = std::make_unique<WebMessage>(); + m2->message = base::ASCIIToUTF16("from c++"); + proxy_->PostMessage(std::move(m2)); + } else { + // On subsequent calls quit. + quit_closure_.Run(); + } + } + + private: + int call_count_ = 0; + base::RepeatingClosure quit_closure_; + WebMessageReplyProxy* proxy_; + std::vector<base::string16> messages_; +}; + +// WebMessageHostFactory implementation that creates WebMessageHostImp. +class WebMessageHostFactoryImpl : public WebMessageHostFactory { + public: + explicit WebMessageHostFactoryImpl(base::RepeatingClosure quit_closure) + : quit_closure_(quit_closure) {} + ~WebMessageHostFactoryImpl() override = default; + + // WebMessageHostFactory: + std::unique_ptr<WebMessageHost> CreateHost( + const std::string& origin_string, + bool is_main_frame, + WebMessageReplyProxy* proxy) override { + return std::make_unique<WebMessageHostImpl>(quit_closure_, origin_string, + is_main_frame, proxy); + } + + private: + base::RepeatingClosure quit_closure_; +}; + +} // namespace + +using WebMessageTest = WebLayerBrowserTest; + +IN_PROC_BROWSER_TEST_F(WebMessageTest, SendAndReceive) { + EXPECT_TRUE(embedded_test_server()->Start()); + + base::RunLoop run_loop; + shell()->tab()->AddWebMessageHostFactory( + std::make_unique<WebMessageHostFactoryImpl>(run_loop.QuitClosure()), + base::ASCIIToUTF16("x"), {"*"}); + + // web_message_test.html posts a message immediately. + shell()->tab()->GetNavigationController()->Navigate( + embedded_test_server()->GetURL("/web_message_test.html")); + run_loop.Run(); + + // There should be two messages. The one from the page, and the ack triggered + // when WebMessageHostImpl calls PostMessage(). + ASSERT_TRUE(current_connection); + ASSERT_EQ(2u, current_connection->messages().size()); + EXPECT_EQ(base::ASCIIToUTF16("from page"), current_connection->messages()[0]); + EXPECT_EQ(base::ASCIIToUTF16("bouncing from c++"), + current_connection->messages()[1]); +} + +} // namespace weblayer diff --git a/chromium/weblayer/browser/js_communication/web_message_host_factory_proxy.cc b/chromium/weblayer/browser/js_communication/web_message_host_factory_proxy.cc new file mode 100644 index 00000000000..e634cd95d78 --- /dev/null +++ b/chromium/weblayer/browser/js_communication/web_message_host_factory_proxy.cc @@ -0,0 +1,25 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "weblayer/browser/js_communication/web_message_host_factory_proxy.h" + +#include "weblayer/browser/js_communication/web_message_reply_proxy_impl.h" + +namespace weblayer { + +WebMessageHostFactoryProxy::WebMessageHostFactoryProxy( + const base::android::JavaParamRef<jobject>& client) + : client_(client) {} + +WebMessageHostFactoryProxy::~WebMessageHostFactoryProxy() = default; + +std::unique_ptr<WebMessageHost> WebMessageHostFactoryProxy::CreateHost( + const std::string& origin_string, + bool is_main_frame, + WebMessageReplyProxy* proxy) { + return std::make_unique<WebMessageReplyProxyImpl>( + ++next_id_, client_, origin_string, is_main_frame, proxy); +} + +} // namespace weblayer diff --git a/chromium/weblayer/browser/js_communication/web_message_host_factory_proxy.h b/chromium/weblayer/browser/js_communication/web_message_host_factory_proxy.h new file mode 100644 index 00000000000..93e5d55d71e --- /dev/null +++ b/chromium/weblayer/browser/js_communication/web_message_host_factory_proxy.h @@ -0,0 +1,38 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef WEBLAYER_BROWSER_JS_COMMUNICATION_WEB_MESSAGE_HOST_FACTORY_PROXY_H_ +#define WEBLAYER_BROWSER_JS_COMMUNICATION_WEB_MESSAGE_HOST_FACTORY_PROXY_H_ + +#include "base/android/scoped_java_ref.h" +#include "weblayer/public/js_communication/web_message_host_factory.h" + +namespace weblayer { + +// TabImpl, on android, creates a WebMessageHostFactoryProxy for every call +// to RegisterWebMessageCallback(). This is used to delegate the calls back to +// the Java side. +class WebMessageHostFactoryProxy : public WebMessageHostFactory { + public: + explicit WebMessageHostFactoryProxy( + const base::android::JavaParamRef<jobject>& client); + WebMessageHostFactoryProxy(const WebMessageHostFactoryProxy&) = delete; + WebMessageHostFactoryProxy& operator=(const WebMessageHostFactoryProxy&) = + delete; + ~WebMessageHostFactoryProxy() override; + + // WebMessageHostFactory: + std::unique_ptr<WebMessageHost> CreateHost( + const std::string& origin_string, + bool is_main_frame, + WebMessageReplyProxy* proxy) override; + + private: + base::android::ScopedJavaGlobalRef<jobject> client_; + int next_id_ = 0; +}; + +} // namespace weblayer + +#endif // WEBLAYER_BROWSER_JS_COMMUNICATION_WEB_MESSAGE_HOST_FACTORY_PROXY_H_ diff --git a/chromium/weblayer/browser/js_communication/web_message_host_factory_wrapper.cc b/chromium/weblayer/browser/js_communication/web_message_host_factory_wrapper.cc new file mode 100644 index 00000000000..7a6088f540b --- /dev/null +++ b/chromium/weblayer/browser/js_communication/web_message_host_factory_wrapper.cc @@ -0,0 +1,70 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "weblayer/browser/js_communication/web_message_host_factory_wrapper.h" + +#include "components/js_injection/browser/web_message.h" +#include "components/js_injection/browser/web_message_host.h" +#include "components/js_injection/browser/web_message_reply_proxy.h" +#include "weblayer/public/js_communication/web_message.h" +#include "weblayer/public/js_communication/web_message_host.h" +#include "weblayer/public/js_communication/web_message_host_factory.h" +#include "weblayer/public/js_communication/web_message_reply_proxy.h" + +namespace weblayer { +namespace { + +// An implementation of js_injection::WebMessageHost that delegates to the +// corresponding WebLayer type. This also serves as the WebMessageReplyProxy +// implementation, which forwards to the js_injection implementation. +class WebMessageHostWrapper : public js_injection::WebMessageHost, + public WebMessageReplyProxy { + public: + WebMessageHostWrapper(weblayer::WebMessageHostFactory* factory, + const std::string& origin_string, + bool is_main_frame, + js_injection::WebMessageReplyProxy* proxy) + : proxy_(proxy), + connection_(factory->CreateHost(origin_string, is_main_frame, this)) {} + + // js_injection::WebMessageHost: + void OnPostMessage( + std::unique_ptr<js_injection::WebMessage> message) override { + std::unique_ptr<WebMessage> m = std::make_unique<WebMessage>(); + m->message = message->message; + connection_->OnPostMessage(std::move(m)); + } + + // WebMessageReplyProxy: + void PostMessage(std::unique_ptr<WebMessage> message) override { + std::unique_ptr<js_injection::WebMessage> w = + std::make_unique<js_injection::WebMessage>(); + w->message = std::move(message->message); + proxy_->PostMessage(std::move(w)); + } + + private: + js_injection::WebMessageReplyProxy* proxy_; + std::unique_ptr<weblayer::WebMessageHost> connection_; +}; + +} // namespace + +WebMessageHostFactoryWrapper::WebMessageHostFactoryWrapper( + std::unique_ptr<weblayer::WebMessageHostFactory> factory) + : factory_(std::move(factory)) {} + +WebMessageHostFactoryWrapper::~WebMessageHostFactoryWrapper() = default; + +std::unique_ptr<js_injection::WebMessageHost> +WebMessageHostFactoryWrapper::CreateHost( + const std::string& origin_string, + bool is_main_frame, + js_injection::WebMessageReplyProxy* proxy) { + auto wrapper = std::make_unique<WebMessageHostWrapper>( + factory_.get(), origin_string, is_main_frame, proxy); + return wrapper; +} + +} // namespace weblayer diff --git a/chromium/weblayer/browser/js_communication/web_message_host_factory_wrapper.h b/chromium/weblayer/browser/js_communication/web_message_host_factory_wrapper.h new file mode 100644 index 00000000000..1c32d02bfc2 --- /dev/null +++ b/chromium/weblayer/browser/js_communication/web_message_host_factory_wrapper.h @@ -0,0 +1,38 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef WEBLAYER_BROWSER_JS_COMMUNICATION_WEB_MESSAGE_HOST_FACTORY_WRAPPER_H_ +#define WEBLAYER_BROWSER_JS_COMMUNICATION_WEB_MESSAGE_HOST_FACTORY_WRAPPER_H_ + +#include "components/js_injection/browser/web_message_host_factory.h" + +namespace weblayer { + +class WebMessageHostFactory; + +// Provides an implementation of js_injection::WebMessageHostFactory that +// wraps the corresponding WebLayer type. +class WebMessageHostFactoryWrapper + : public js_injection::WebMessageHostFactory { + public: + explicit WebMessageHostFactoryWrapper( + std::unique_ptr<weblayer::WebMessageHostFactory> factory); + WebMessageHostFactoryWrapper(const WebMessageHostFactoryWrapper&) = delete; + WebMessageHostFactoryWrapper& operator=(const WebMessageHostFactoryWrapper&) = + delete; + ~WebMessageHostFactoryWrapper() override; + + // js_injection::WebMessageHostFactory: + std::unique_ptr<js_injection::WebMessageHost> CreateHost( + const std::string& origin_string, + bool is_main_frame, + js_injection::WebMessageReplyProxy* proxy) override; + + private: + std::unique_ptr<weblayer::WebMessageHostFactory> factory_; +}; + +} // namespace weblayer + +#endif // WEBLAYER_BROWSER_JS_COMMUNICATION_WEB_MESSAGE_HOST_FACTORY_WRAPPER_H_ diff --git a/chromium/weblayer/browser/js_communication/web_message_reply_proxy_impl.cc b/chromium/weblayer/browser/js_communication/web_message_reply_proxy_impl.cc new file mode 100644 index 00000000000..8172852ecec --- /dev/null +++ b/chromium/weblayer/browser/js_communication/web_message_reply_proxy_impl.cc @@ -0,0 +1,52 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "weblayer/browser/js_communication/web_message_reply_proxy_impl.h" + +#include <memory> + +#include "base/android/jni_android.h" +#include "base/android/jni_string.h" +#include "weblayer/browser/java/jni/WebMessageReplyProxyImpl_jni.h" +#include "weblayer/public/js_communication/web_message.h" +#include "weblayer/public/js_communication/web_message_reply_proxy.h" + +namespace weblayer { + +WebMessageReplyProxyImpl::WebMessageReplyProxyImpl( + int id, + base::android::ScopedJavaGlobalRef<jobject> client, + const std::string& origin_string, + bool is_main_frame, + WebMessageReplyProxy* reply_proxy) + : reply_proxy_(reply_proxy) { + auto* env = base::android::AttachCurrentThread(); + java_object_ = Java_WebMessageReplyProxyImpl_create( + env, reinterpret_cast<intptr_t>(this), id, client, is_main_frame, + base::android::ConvertUTF8ToJavaString(env, origin_string)); +} + +WebMessageReplyProxyImpl::~WebMessageReplyProxyImpl() { + Java_WebMessageReplyProxyImpl_onNativeDestroyed( + base::android::AttachCurrentThread(), java_object_); +} + +void WebMessageReplyProxyImpl::PostMessage( + JNIEnv* env, + const base::android::JavaParamRef<jstring>& message_contents) { + auto message = std::make_unique<WebMessage>(); + base::android::ConvertJavaStringToUTF16(env, message_contents, + &(message->message)); + reply_proxy_->PostMessage(std::move(message)); +} + +void WebMessageReplyProxyImpl::OnPostMessage( + std::unique_ptr<WebMessage> message) { + auto* env = base::android::AttachCurrentThread(); + Java_WebMessageReplyProxyImpl_onPostMessage( + env, java_object_, + base::android::ConvertUTF16ToJavaString(env, message->message)); +} + +} // namespace weblayer diff --git a/chromium/weblayer/browser/js_communication/web_message_reply_proxy_impl.h b/chromium/weblayer/browser/js_communication/web_message_reply_proxy_impl.h new file mode 100644 index 00000000000..dbcfe016f06 --- /dev/null +++ b/chromium/weblayer/browser/js_communication/web_message_reply_proxy_impl.h @@ -0,0 +1,47 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef WEBLAYER_BROWSER_JS_COMMUNICATION_WEB_MESSAGE_REPLY_PROXY_IMPL_H_ +#define WEBLAYER_BROWSER_JS_COMMUNICATION_WEB_MESSAGE_REPLY_PROXY_IMPL_H_ + +#include <string> + +#include "base/android/scoped_java_ref.h" +#include "components/js_injection/browser/web_message_host.h" +#include "weblayer/public/js_communication/web_message_host.h" + +namespace weblayer { + +class WebMessageReplyProxy; + +// Created only on the Android side to support post-message. +// WebMessageReplyProxyImpl creates the Java WebMessageReplyProxy that is then +// sent over to the client side for communication with the page. +class WebMessageReplyProxyImpl : public WebMessageHost { + public: + WebMessageReplyProxyImpl(int id, + base::android::ScopedJavaGlobalRef<jobject> client, + const std::string& origin_string, + bool is_main_frame, + WebMessageReplyProxy* reply_proxy); + WebMessageReplyProxyImpl(const WebMessageReplyProxyImpl&) = delete; + WebMessageReplyProxyImpl& operator=(const WebMessageReplyProxyImpl&) = delete; + ~WebMessageReplyProxyImpl() override; + + void PostMessage( + JNIEnv* env, + const base::android::JavaParamRef<jstring>& message_contents); + // WebMessageHost: + void OnPostMessage(std::unique_ptr<WebMessage> message) override; + + private: + WebMessageReplyProxy* reply_proxy_; + + // The Java WebMessageReplyProxy. + base::android::ScopedJavaGlobalRef<jobject> java_object_; +}; + +} // namespace weblayer + +#endif // WEBLAYER_BROWSER_JS_COMMUNICATION_WEB_MESSAGE_REPLY_PROXY_IMPL_H_ |