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_helper.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 "third_party/WebKit/public/web/WebBindings.h"
21 JavaBridgeDispatcherHostManager::JavaBridgeDispatcherHostManager(
22 WebContents
* web_contents
)
23 : WebContentsObserver(web_contents
) {
26 JavaBridgeDispatcherHostManager::~JavaBridgeDispatcherHostManager() {
27 for (ObjectMap::iterator iter
= objects_
.begin(); iter
!= objects_
.end();
29 blink::WebBindings::releaseObject(iter
->second
);
31 DCHECK_EQ(0U, instances_
.size());
34 void JavaBridgeDispatcherHostManager::AddNamedObject(const base::string16
& name
,
36 // Record this object in a map so that we can add it into RenderViewHosts
37 // created later. The JavaBridgeDispatcherHost instances will take a
38 // reference to the object, but we take one too, because this method can be
39 // called before there are any such instances.
40 blink::WebBindings::retainObject(object
);
41 objects_
[name
] = object
;
43 for (InstanceMap::iterator iter
= instances_
.begin();
44 iter
!= instances_
.end(); ++iter
) {
45 iter
->second
->AddNamedObject(name
, object
);
49 void JavaBridgeDispatcherHostManager::SetRetainedObjectSet(
50 const JavaObjectWeakGlobalRef
& retained_object_set
) {
51 // It's an error to replace the retained_object_set_ after it's been set,
52 // so we check that it hasn't already been here.
53 // TODO(benm): It'd be better to pass the set in the constructor to avoid
54 // the chance of this happening; but that's tricky as this get's constructed
55 // before ContentViewCore (which owns the set). Best solution may be to move
56 // ownership of the JavaBridgerDispatchHostManager from WebContents to
58 JNIEnv
* env
= base::android::AttachCurrentThread();
59 base::android::ScopedJavaLocalRef
<jobject
> new_retained_object_set
=
60 retained_object_set
.get(env
);
61 base::android::ScopedJavaLocalRef
<jobject
> current_retained_object_set
=
62 retained_object_set_
.get(env
);
63 if (!env
->IsSameObject(new_retained_object_set
.obj(),
64 current_retained_object_set
.obj())) {
65 DCHECK(current_retained_object_set
.is_null());
66 retained_object_set_
= retained_object_set
;
70 void JavaBridgeDispatcherHostManager::RemoveNamedObject(
71 const base::string16
& name
) {
72 ObjectMap::iterator iter
= objects_
.find(name
);
73 if (iter
== objects_
.end()) {
77 blink::WebBindings::releaseObject(iter
->second
);
80 for (InstanceMap::iterator iter
= instances_
.begin();
81 iter
!= instances_
.end(); ++iter
) {
82 iter
->second
->RemoveNamedObject(name
);
86 void JavaBridgeDispatcherHostManager::OnGetChannelHandle(
87 RenderViewHost
* render_view_host
, IPC::Message
* reply_msg
) {
88 instances_
[render_view_host
]->OnGetChannelHandle(reply_msg
);
91 void JavaBridgeDispatcherHostManager::RenderViewCreated(
92 RenderViewHost
* render_view_host
) {
93 // Creates a JavaBridgeDispatcherHost for the specified RenderViewHost and
94 // adds all currently registered named objects to the new instance.
95 scoped_refptr
<JavaBridgeDispatcherHost
> instance
=
96 new JavaBridgeDispatcherHost(render_view_host
);
98 for (ObjectMap::const_iterator iter
= objects_
.begin();
99 iter
!= objects_
.end(); ++iter
) {
100 instance
->AddNamedObject(iter
->first
, iter
->second
);
103 instances_
[render_view_host
] = instance
;
106 void JavaBridgeDispatcherHostManager::RenderViewDeleted(
107 RenderViewHost
* render_view_host
) {
108 if (!instances_
.count(render_view_host
)) // Needed for tests.
110 instances_
[render_view_host
]->RenderViewDeleted();
111 instances_
.erase(render_view_host
);
114 void JavaBridgeDispatcherHostManager::DocumentAvailableInMainFrame() {
115 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
116 // Called when the window object has been cleared in the main frame.
117 JNIEnv
* env
= base::android::AttachCurrentThread();
118 base::android::ScopedJavaLocalRef
<jobject
> retained_object_set
=
119 retained_object_set_
.get(env
);
120 if (!retained_object_set
.is_null()) {
121 JNI_Java_HashSet_clear(env
, retained_object_set
);
123 // We also need to add back the named objects we have so far as they
124 // should survive navigations.
125 ObjectMap::iterator it
= objects_
.begin();
126 for (; it
!= objects_
.end(); ++it
) {
127 JNI_Java_HashSet_add(env
, retained_object_set
,
128 JavaBoundObject::GetJavaObject(it
->second
));
133 void JavaBridgeDispatcherHostManager::JavaBoundObjectCreated(
134 const base::android::JavaRef
<jobject
>& object
) {
135 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
137 JNIEnv
* env
= base::android::AttachCurrentThread();
138 base::android::ScopedJavaLocalRef
<jobject
> retained_object_set
=
139 retained_object_set_
.get(env
);
140 if (!retained_object_set
.is_null()) {
141 JNI_Java_HashSet_add(env
, retained_object_set
, object
);
145 void JavaBridgeDispatcherHostManager::JavaBoundObjectDestroyed(
146 const base::android::JavaRef
<jobject
>& object
) {
147 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
149 JNIEnv
* env
= base::android::AttachCurrentThread();
150 base::android::ScopedJavaLocalRef
<jobject
> retained_object_set
=
151 retained_object_set_
.get(env
);
152 if (!retained_object_set
.is_null()) {
153 JNI_Java_HashSet_remove(env
, retained_object_set
, object
);
157 } // namespace content