1 // Copyright (c) 2012 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.
5 #include "content/browser/renderer_host/java/java_bridge_dispatcher_host_manager.h"
7 #include "base/android/jni_android.h"
8 #include "base/android/jni_weak_ref.h"
9 #include "base/android/scoped_java_ref.h"
10 #include "base/bind.h"
11 #include "base/logging.h"
12 #include "base/strings/utf_string_conversions.h"
13 #include "content/browser/renderer_host/java/java_bound_object.h"
14 #include "content/browser/renderer_host/java/java_bridge_dispatcher_host.h"
15 #include "content/common/android/hash_set.h"
16 #include "content/public/browser/browser_thread.h"
17 #include "content/public/browser/render_frame_host.h"
18 #include "third_party/WebKit/public/web/WebBindings.h"
22 JavaBridgeDispatcherHostManager::JavaBridgeDispatcherHostManager(
23 WebContents
* web_contents
)
24 : WebContentsObserver(web_contents
),
25 allow_object_contents_inspection_(true) {
28 JavaBridgeDispatcherHostManager::~JavaBridgeDispatcherHostManager() {
29 for (ObjectMap::iterator iter
= objects_
.begin(); iter
!= objects_
.end();
31 blink::WebBindings::releaseObject(iter
->second
);
33 DCHECK_EQ(0U, instances_
.size());
36 void JavaBridgeDispatcherHostManager::AddNamedObject(const base::string16
& name
,
38 // Record this object in a map so that we can add it into RenderViewHosts
39 // created later. The JavaBridgeDispatcherHost instances will take a
40 // reference to the object, but we take one too, because this method can be
41 // called before there are any such instances.
42 blink::WebBindings::retainObject(object
);
43 objects_
[name
] = object
;
45 for (InstanceMap::iterator iter
= instances_
.begin();
46 iter
!= instances_
.end(); ++iter
) {
47 iter
->second
->AddNamedObject(name
, object
);
51 void JavaBridgeDispatcherHostManager::SetRetainedObjectSet(
52 const JavaObjectWeakGlobalRef
& retained_object_set
) {
53 // It's an error to replace the retained_object_set_ after it's been set,
54 // so we check that it hasn't already been here.
55 // TODO(benm): It'd be better to pass the set in the constructor to avoid
56 // the chance of this happening; but that's tricky as this get's constructed
57 // before ContentViewCore (which owns the set). Best solution may be to move
58 // ownership of the JavaBridgerDispatchHostManager from WebContents to
60 JNIEnv
* env
= base::android::AttachCurrentThread();
61 base::android::ScopedJavaLocalRef
<jobject
> new_retained_object_set
=
62 retained_object_set
.get(env
);
63 base::android::ScopedJavaLocalRef
<jobject
> current_retained_object_set
=
64 retained_object_set_
.get(env
);
65 if (!env
->IsSameObject(new_retained_object_set
.obj(),
66 current_retained_object_set
.obj())) {
67 DCHECK(current_retained_object_set
.is_null());
68 retained_object_set_
= retained_object_set
;
72 void JavaBridgeDispatcherHostManager::RemoveNamedObject(
73 const base::string16
& name
) {
74 ObjectMap::iterator iter
= objects_
.find(name
);
75 if (iter
== objects_
.end()) {
79 blink::WebBindings::releaseObject(iter
->second
);
82 for (InstanceMap::iterator iter
= instances_
.begin();
83 iter
!= instances_
.end(); ++iter
) {
84 iter
->second
->RemoveNamedObject(name
);
88 void JavaBridgeDispatcherHostManager::OnGetChannelHandle(
89 RenderFrameHost
* render_frame_host
, IPC::Message
* reply_msg
) {
90 instances_
[render_frame_host
]->OnGetChannelHandle(reply_msg
);
93 void JavaBridgeDispatcherHostManager::RenderFrameCreated(
94 RenderFrameHost
* render_frame_host
) {
95 // Creates a JavaBridgeDispatcherHost for the specified RenderViewHost and
96 // adds all currently registered named objects to the new instance.
97 scoped_refptr
<JavaBridgeDispatcherHost
> instance
=
98 new JavaBridgeDispatcherHost(render_frame_host
);
100 for (ObjectMap::const_iterator iter
= objects_
.begin();
101 iter
!= objects_
.end(); ++iter
) {
102 instance
->AddNamedObject(iter
->first
, iter
->second
);
105 instances_
[render_frame_host
] = instance
;
108 void JavaBridgeDispatcherHostManager::RenderFrameDeleted(
109 RenderFrameHost
* render_frame_host
) {
110 if (!instances_
.count(render_frame_host
)) // Needed for tests.
112 instances_
[render_frame_host
]->RenderFrameDeleted();
113 instances_
.erase(render_frame_host
);
116 void JavaBridgeDispatcherHostManager::DocumentAvailableInMainFrame() {
117 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
118 // Called when the window object has been cleared in the main frame.
119 JNIEnv
* env
= base::android::AttachCurrentThread();
120 base::android::ScopedJavaLocalRef
<jobject
> retained_object_set
=
121 retained_object_set_
.get(env
);
122 if (!retained_object_set
.is_null()) {
123 JNI_Java_HashSet_clear(env
, retained_object_set
);
125 // We also need to add back the named objects we have so far as they
126 // should survive navigations.
127 ObjectMap::iterator it
= objects_
.begin();
128 for (; it
!= objects_
.end(); ++it
) {
129 JNI_Java_HashSet_add(env
, retained_object_set
,
130 JavaBoundObject::GetJavaObject(it
->second
));
135 void JavaBridgeDispatcherHostManager::JavaBoundObjectCreated(
136 const base::android::JavaRef
<jobject
>& object
) {
137 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
139 JNIEnv
* env
= base::android::AttachCurrentThread();
140 base::android::ScopedJavaLocalRef
<jobject
> retained_object_set
=
141 retained_object_set_
.get(env
);
142 if (!retained_object_set
.is_null()) {
143 JNI_Java_HashSet_add(env
, retained_object_set
, object
);
147 void JavaBridgeDispatcherHostManager::JavaBoundObjectDestroyed(
148 const base::android::JavaRef
<jobject
>& object
) {
149 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
151 JNIEnv
* env
= base::android::AttachCurrentThread();
152 base::android::ScopedJavaLocalRef
<jobject
> retained_object_set
=
153 retained_object_set_
.get(env
);
154 if (!retained_object_set
.is_null()) {
155 JNI_Java_HashSet_remove(env
, retained_object_set
, object
);
159 void JavaBridgeDispatcherHostManager::SetAllowObjectContentsInspection(
161 allow_object_contents_inspection_
= allow
;
164 } // namespace content