#ifndef CONTENT_BROWSER_ANDROID_JAVA_GIN_JAVA_BRIDGE_DISPATCHER_HOST_H_
#define CONTENT_BROWSER_ANDROID_JAVA_GIN_JAVA_BRIDGE_DISPATCHER_HOST_H_
#include <stdint.h>
#include <map>
#include <set>
#include "base/android/jni_weak_ref.h"
#include "base/android/scoped_java_ref.h"
#include "base/memory/ref_counted.h"
#include "base/memory/ref_counted_delete_on_sequence.h"
#include "base/synchronization/lock.h"
#include "base/thread_annotations.h"
#include "base/values.h"
#include "components/origin_matcher/origin_matcher.h"
#include "content/browser/android/java/gin_java_bound_object.h"
#include "content/browser/android/java/gin_java_method_invocation_helper.h"
#include "content/common/buildflags.h"
#include "content/common/gin_java_bridge.mojom.h"
#include "content/public/browser/global_routing_id.h"
#include "content/public/browser/web_contents_observer.h"
#include "mojo/public/cpp/bindings/associated_remote.h"
#include "mojo/public/cpp/bindings/receiver_set.h"
namespace content {
class WebContentsImpl;
struct NamedObject {
GinJavaBoundObject::ObjectID object_id;
origin_matcher::OriginMatcher matcher;
};
class GinJavaBridgeDispatcherHost
: public base::RefCountedDeleteOnSequence<GinJavaBridgeDispatcherHost>,
public WebContentsObserver,
public mojom::GinJavaBridgeHost,
public mojom::GinJavaBridgeRemoteObject,
public GinJavaMethodInvocationHelper::DispatcherDelegate {
public:
GinJavaBridgeDispatcherHost(
WebContents* web_contents,
const base::android::JavaRef<jobject>& retained_object_set);
GinJavaBridgeDispatcherHost(const GinJavaBridgeDispatcherHost&) = delete;
GinJavaBridgeDispatcherHost& operator=(const GinJavaBridgeDispatcherHost&) =
delete;
void AddNamedObject(
const std::string& name,
const base::android::JavaRef<jobject>& object,
const base::android::JavaRef<jclass>& safe_annotation_clazz,
origin_matcher::OriginMatcher matcher);
void RemoveNamedObject(const std::string& name);
void SetAllowObjectContentsInspection(bool allow);
void RenderFrameCreated(RenderFrameHost* render_frame_host) override;
void RenderFrameDeleted(RenderFrameHost* render_frame_host) override;
void WebContentsDestroyed() override;
void PrimaryMainDocumentElementAvailable() override;
JavaObjectWeakGlobalRef GetObjectWeakRef(
GinJavaBoundObject::ObjectID object_id) override;
void OnInvokeMethod(const GlobalRenderFrameHostId& routing_id,
GinJavaBoundObject::ObjectID object_id,
const std::string& method_name,
const base::Value::List& arguments,
base::Value::List* result,
mojom::GinJavaBridgeError* error_code);
void OnObjectWrapperDeleted(const GlobalRenderFrameHostId& routing_id,
GinJavaBoundObject::ObjectID object_id);
void GetObject(int32_t object_id,
mojo::PendingReceiver<mojom::GinJavaBridgeRemoteObject>
receiver) override;
void ObjectWrapperDeleted(int32_t object_id) override;
void GetMethods(GetMethodsCallback callback) override;
void HasMethod(const std::string& method_name,
HasMethodCallback callback) override;
void InvokeMethod(const std::string& method_name,
base::Value::List arguments,
InvokeMethodCallback callback) override;
private:
friend class base::RefCountedDeleteOnSequence<GinJavaBridgeDispatcherHost>;
friend class base::DeleteHelper<GinJavaBridgeDispatcherHost>;
typedef std::map<GinJavaBoundObject::ObjectID,
scoped_refptr<GinJavaBoundObject>> ObjectMap;
~GinJavaBridgeDispatcherHost() override;
void BindNewHostOnBackgroundThread(
GlobalRenderFrameHostId routing_id,
mojo::PendingReceiver<mojom::GinJavaBridgeHost> host);
void ClearAllReceivers();
void ObjectDisconnected();
mojom::GinJavaBridge* GetJavaBridge(RenderFrameHost* frame_host,
bool should_create);
WebContentsImpl* web_contents() const;
void RemoteDisconnected(const content::GlobalRenderFrameHostId& routing_id);
GinJavaBoundObject::ObjectID AddObject(
const base::android::JavaRef<jobject>& object,
const base::android::JavaRef<jclass>& safe_annotation_clazz,
std::optional<GlobalRenderFrameHostId> holder);
scoped_refptr<GinJavaBoundObject> FindObject(
GinJavaBoundObject::ObjectID object_id);
bool FindObjectId(const base::android::JavaRef<jobject>& object,
GinJavaBoundObject::ObjectID* object_id);
void RemoveFromRetainedObjectSetLocked(const JavaObjectWeakGlobalRef& ref);
JavaObjectWeakGlobalRef RemoveHolderLocked(
const GlobalRenderFrameHostId& holder,
ObjectMap::iterator* iter_ptr) EXCLUSIVE_LOCKS_REQUIRED(objects_lock_);
void DeleteObjectForRouteLocked(const GlobalRenderFrameHostId& routing_id,
GinJavaBoundObject::ObjectID object_id);
typedef std::map<std::string, NamedObject> NamedObjectMap;
NamedObjectMap named_objects_;
GinJavaBoundObject::ObjectID next_object_id_ = 1;
JavaObjectWeakGlobalRef retained_object_set_;
ObjectMap objects_ GUARDED_BY(objects_lock_);
base::Lock objects_lock_;
bool allow_object_contents_inspection_ = true;
mojo::ReceiverSet<mojom::GinJavaBridgeHost, GlobalRenderFrameHostId>
receivers_;
mojo::ReceiverSet<
mojom::GinJavaBridgeRemoteObject,
std::pair<GlobalRenderFrameHostId, GinJavaBoundObject::ObjectID>>
object_receivers_;
std::map<GlobalRenderFrameHostId,
mojo::AssociatedRemote<mojom::GinJavaBridge>>
remotes_;
const bool mojo_skip_clear_on_main_document_;
};
}
#endif