136b6013cf78c818e362ab8bb5a58f4f30b60ad7eMikhail Naganov// Copyright 2014 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 536b6013cf78c818e362ab8bb5a58f4f30b60ad7eMikhail Naganov#include "content/browser/android/java/java_bridge_dispatcher_host_manager.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/android/jni_android.h" 80529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#include "base/android/jni_weak_ref.h" 92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/android/scoped_java_ref.h" 102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/bind.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 12868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h" 1336b6013cf78c818e362ab8bb5a58f4f30b60ad7eMikhail Naganov#include "content/browser/android/java/java_bound_object.h" 1436b6013cf78c818e362ab8bb5a58f4f30b60ad7eMikhail Naganov#include "content/browser/android/java/java_bridge_dispatcher_host.h" 152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/common/android/hash_set.h" 16cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "content/common/java_bridge_messages.h" 172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/browser/browser_thread.h" 18a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "content/public/browser/render_frame_host.h" 197d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "third_party/WebKit/public/web/WebBindings.h" 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace content { 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)JavaBridgeDispatcherHostManager::JavaBridgeDispatcherHostManager( 24cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) WebContents* web_contents, 25cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) jobject retained_object_set) 26a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) : WebContentsObserver(web_contents), 27cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) retained_object_set_(base::android::AttachCurrentThread(), 28cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) retained_object_set), 29a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) allow_object_contents_inspection_(true) { 30cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DCHECK(retained_object_set); 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)JavaBridgeDispatcherHostManager::~JavaBridgeDispatcherHostManager() { 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (ObjectMap::iterator iter = objects_.begin(); iter != objects_.end(); 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++iter) { 36f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) blink::WebBindings::releaseObject(iter->second); 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(0U, instances_.size()); 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 41a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void JavaBridgeDispatcherHostManager::AddNamedObject(const base::string16& name, 422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) NPObject* object) { 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Record this object in a map so that we can add it into RenderViewHosts 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // created later. The JavaBridgeDispatcherHost instances will take a 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // reference to the object, but we take one too, because this method can be 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // called before there are any such instances. 47f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) blink::WebBindings::retainObject(object); 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) objects_[name] = object; 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (InstanceMap::iterator iter = instances_.begin(); 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) iter != instances_.end(); ++iter) { 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) iter->second->AddNamedObject(name, object); 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 56a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void JavaBridgeDispatcherHostManager::RemoveNamedObject( 57a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const base::string16& name) { 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ObjectMap::iterator iter = objects_.find(name); 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (iter == objects_.end()) { 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 63f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) blink::WebBindings::releaseObject(iter->second); 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) objects_.erase(iter); 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (InstanceMap::iterator iter = instances_.begin(); 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) iter != instances_.end(); ++iter) { 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) iter->second->RemoveNamedObject(name); 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 72a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void JavaBridgeDispatcherHostManager::RenderFrameCreated( 73a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) RenderFrameHost* render_frame_host) { 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Creates a JavaBridgeDispatcherHost for the specified RenderViewHost and 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // adds all currently registered named objects to the new instance. 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<JavaBridgeDispatcherHost> instance = 77a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) new JavaBridgeDispatcherHost(render_frame_host); 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (ObjectMap::const_iterator iter = objects_.begin(); 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) iter != objects_.end(); ++iter) { 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) instance->AddNamedObject(iter->first, iter->second); 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 84a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) instances_[render_frame_host] = instance; 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 87a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void JavaBridgeDispatcherHostManager::RenderFrameDeleted( 88a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) RenderFrameHost* render_frame_host) { 89a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (!instances_.count(render_frame_host)) // Needed for tests. 901e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) return; 91a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) instances_[render_frame_host]->RenderFrameDeleted(); 92a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) instances_.erase(render_frame_host); 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void JavaBridgeDispatcherHostManager::DocumentAvailableInMainFrame() { 96effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DCHECK_CURRENTLY_ON(BrowserThread::UI); 972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Called when the window object has been cleared in the main frame. 982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) JNIEnv* env = base::android::AttachCurrentThread(); 992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::android::ScopedJavaLocalRef<jobject> retained_object_set = 1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) retained_object_set_.get(env); 1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!retained_object_set.is_null()) { 1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) JNI_Java_HashSet_clear(env, retained_object_set); 1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // We also need to add back the named objects we have so far as they 1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // should survive navigations. 1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ObjectMap::iterator it = objects_.begin(); 1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (; it != objects_.end(); ++it) { 1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) JNI_Java_HashSet_add(env, retained_object_set, 1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) JavaBoundObject::GetJavaObject(it->second)); 1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 114cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)bool JavaBridgeDispatcherHostManager::OnMessageReceived( 115cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const IPC::Message& message, 116cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) RenderFrameHost* render_frame_host) { 117cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DCHECK(render_frame_host); 118cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (!instances_.count(render_frame_host)) 119cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return false; 120cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) scoped_refptr<JavaBridgeDispatcherHost> instance = 121cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) instances_[render_frame_host]; 122cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) bool handled = true; 123cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) IPC_BEGIN_MESSAGE_MAP(JavaBridgeDispatcherHostManager, message) 124cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) IPC_MESSAGE_FORWARD_DELAY_REPLY( 125cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) JavaBridgeHostMsg_GetChannelHandle, 126cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) instance.get(), 127cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) JavaBridgeDispatcherHost::OnGetChannelHandle) 128cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) IPC_MESSAGE_UNHANDLED(handled = false) 129cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) IPC_END_MESSAGE_MAP() 130cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return handled; 131cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 132cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void JavaBridgeDispatcherHostManager::JavaBoundObjectCreated( 1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const base::android::JavaRef<jobject>& object) { 135effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DCHECK_CURRENTLY_ON(BrowserThread::UI); 1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) JNIEnv* env = base::android::AttachCurrentThread(); 1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::android::ScopedJavaLocalRef<jobject> retained_object_set = 1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) retained_object_set_.get(env); 1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!retained_object_set.is_null()) { 1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) JNI_Java_HashSet_add(env, retained_object_set, object); 1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void JavaBridgeDispatcherHostManager::JavaBoundObjectDestroyed( 1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const base::android::JavaRef<jobject>& object) { 147effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DCHECK_CURRENTLY_ON(BrowserThread::UI); 1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) JNIEnv* env = base::android::AttachCurrentThread(); 1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::android::ScopedJavaLocalRef<jobject> retained_object_set = 1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) retained_object_set_.get(env); 1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!retained_object_set.is_null()) { 1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) JNI_Java_HashSet_remove(env, retained_object_set, object); 1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 157a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void JavaBridgeDispatcherHostManager::SetAllowObjectContentsInspection( 158a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) bool allow) { 159a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) allow_object_contents_inspection_ = allow; 160a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 161a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace content 163