1// Copyright 2014 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef CONTENT_BROWSER_ANDROID_JAVA_GIN_JAVA_BRIDGE_DISPATCHER_HOST_H_
6#define CONTENT_BROWSER_ANDROID_JAVA_GIN_JAVA_BRIDGE_DISPATCHER_HOST_H_
7
8#include <map>
9#include <set>
10
11#include "base/android/jni_weak_ref.h"
12#include "base/android/scoped_java_ref.h"
13#include "base/memory/ref_counted.h"
14#include "base/memory/weak_ptr.h"
15#include "base/synchronization/lock.h"
16#include "content/browser/android/java/gin_java_bound_object.h"
17#include "content/browser/android/java/gin_java_method_invocation_helper.h"
18#include "content/public/browser/browser_message_filter.h"
19#include "content/public/browser/web_contents_observer.h"
20
21namespace base {
22class ListValue;
23}
24
25namespace IPC {
26class Message;
27}
28
29namespace content {
30
31// This class handles injecting Java objects into a single RenderView. The Java
32// object itself lives in the browser process on a background thread, while a
33// proxy object is created in the renderer. An instance of this class exists
34// for each RenderFrameHost.
35class GinJavaBridgeDispatcherHost
36    : public WebContentsObserver,
37      public BrowserMessageFilter,
38      public GinJavaMethodInvocationHelper::DispatcherDelegate {
39 public:
40
41  GinJavaBridgeDispatcherHost(WebContents* web_contents,
42                              jobject retained_object_set);
43
44  void AddNamedObject(
45      const std::string& name,
46      const base::android::JavaRef<jobject>& object,
47      const base::android::JavaRef<jclass>& safe_annotation_clazz);
48  void RemoveNamedObject(const std::string& name);
49  void SetAllowObjectContentsInspection(bool allow);
50
51  // WebContentsObserver
52  virtual void RenderFrameCreated(RenderFrameHost* render_frame_host) OVERRIDE;
53  virtual void RenderFrameDeleted(RenderFrameHost* render_frame_host) OVERRIDE;
54  virtual void DocumentAvailableInMainFrame() OVERRIDE;
55
56  // BrowserMessageFilter
57  using BrowserMessageFilter::Send;
58  virtual void OnDestruct() const OVERRIDE;
59  virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
60  virtual base::TaskRunner* OverrideTaskRunnerForMessage(
61      const IPC::Message& message) OVERRIDE;
62
63  // GinJavaMethodInvocationHelper::DispatcherDelegate
64  virtual JavaObjectWeakGlobalRef GetObjectWeakRef(
65      GinJavaBoundObject::ObjectID object_id) OVERRIDE;
66
67 private:
68  friend class BrowserThread;
69  friend class base::DeleteHelper<GinJavaBridgeDispatcherHost>;
70
71  typedef std::map<GinJavaBoundObject::ObjectID,
72                   scoped_refptr<GinJavaBoundObject>> ObjectMap;
73
74  virtual ~GinJavaBridgeDispatcherHost() OVERRIDE;
75
76  void AddBrowserFilterIfNeeded();
77
78  // Run on any thread.
79  GinJavaBoundObject::ObjectID AddObject(
80      const base::android::JavaRef<jobject>& object,
81      const base::android::JavaRef<jclass>& safe_annotation_clazz,
82      bool is_named,
83      int32 holder);
84  scoped_refptr<GinJavaBoundObject> FindObject(
85      GinJavaBoundObject::ObjectID object_id);
86  bool FindObjectId(const base::android::JavaRef<jobject>& object,
87                    GinJavaBoundObject::ObjectID* object_id);
88  void RemoveFromRetainedObjectSetLocked(const JavaObjectWeakGlobalRef& ref);
89  JavaObjectWeakGlobalRef RemoveHolderAndAdvanceLocked(
90      int32 holder,
91      ObjectMap::iterator* iter_ptr);
92
93  // Run on the background thread.
94  void OnGetMethods(GinJavaBoundObject::ObjectID object_id,
95                    std::set<std::string>* returned_method_names);
96  void OnHasMethod(GinJavaBoundObject::ObjectID object_id,
97                   const std::string& method_name,
98                   bool* result);
99  void OnInvokeMethod(GinJavaBoundObject::ObjectID object_id,
100                      const std::string& method_name,
101                      const base::ListValue& arguments,
102                      base::ListValue* result,
103                      content::GinJavaBridgeError* error_code);
104  void OnObjectWrapperDeleted(GinJavaBoundObject::ObjectID object_id);
105  int GetCurrentRoutingID() const;
106  void SetCurrentRoutingID(int routing_id);
107
108  bool browser_filter_added_;
109
110  typedef std::map<std::string, GinJavaBoundObject::ObjectID> NamedObjectMap;
111  NamedObjectMap named_objects_;
112
113  // The following objects are used on both threads, so locking must be used.
114
115  // Every time a GinJavaBoundObject backed by a real Java object is
116  // created/destroyed, we insert/remove a strong ref to that Java object into
117  // this set so that it doesn't get garbage collected while it's still
118  // potentially in use. Although the set is managed native side, it's owned
119  // and defined in Java so that pushing refs into it does not create new GC
120  // roots that would prevent ContentViewCore from being garbage collected.
121  JavaObjectWeakGlobalRef retained_object_set_;
122  // Note that retained_object_set_ does not need to be consistent
123  // with objects_.
124  ObjectMap objects_;
125  base::Lock objects_lock_;
126
127  // The following objects are only used on the background thread.
128  bool allow_object_contents_inspection_;
129  // The routing id of the RenderFrameHost whose request we are processing.
130  int32 current_routing_id_;
131
132  DISALLOW_COPY_AND_ASSIGN(GinJavaBridgeDispatcherHost);
133};
134
135}  // namespace content
136
137#endif  // CONTENT_BROWSER_ANDROID_JAVA_GIN_JAVA_BRIDGE_DISPATCHER_HOST_H_
138