1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153
|
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "content/renderer/java/gin_java_bridge_dispatcher.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/utf_string_conversions.h"
#include "content/common/gin_java_bridge_messages.h"
#include "content/public/renderer/render_frame.h"
#include "content/renderer/java/gin_java_bridge_object.h"
#include "third_party/WebKit/public/web/WebLocalFrame.h"
#include "third_party/WebKit/public/web/WebView.h"
namespace content {
GinJavaBridgeDispatcher::GinJavaBridgeDispatcher(RenderFrame* render_frame)
: RenderFrameObserver(render_frame),
inside_did_clear_window_object_(false) {
}
GinJavaBridgeDispatcher::~GinJavaBridgeDispatcher() {
}
bool GinJavaBridgeDispatcher::OnMessageReceived(const IPC::Message& msg) {
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(GinJavaBridgeDispatcher, msg)
IPC_MESSAGE_HANDLER(GinJavaBridgeMsg_AddNamedObject, OnAddNamedObject)
IPC_MESSAGE_HANDLER(GinJavaBridgeMsg_RemoveNamedObject, OnRemoveNamedObject)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
return handled;
}
namespace {
class ScopedFlag {
public:
ScopedFlag(bool* flag) : flag_(flag) {
DCHECK(!*flag_);
*flag_ = true;
}
~ScopedFlag() {
DCHECK(*flag_);
*flag_ = false;
}
private:
bool* flag_;
DISALLOW_COPY_AND_ASSIGN(ScopedFlag);
};
} // namespace
void GinJavaBridgeDispatcher::DidClearWindowObject() {
// Accessing window object when adding properties to it may trigger
// a nested call to DidClearWindowObject.
if (inside_did_clear_window_object_)
return;
ScopedFlag flag(&inside_did_clear_window_object_);
for (NamedObjectMap::const_iterator iter = named_objects_.begin();
iter != named_objects_.end(); ++iter) {
// Always create a new GinJavaBridgeObject, so we don't pull any of the V8
// wrapper's custom properties into the context of the page we have
// navigated to. The old GinJavaBridgeObject will be automatically
// deleted after its wrapper will be collected.
// On the browser side, we ignore wrapper deletion events for named objects,
// as they are only removed upon embedder's request (RemoveNamedObject).
if (objects_.Lookup(iter->second))
objects_.Remove(iter->second);
GinJavaBridgeObject* object = GinJavaBridgeObject::InjectNamed(
render_frame()->GetWebFrame(), AsWeakPtr(), iter->first, iter->second);
if (object) {
objects_.AddWithID(object, iter->second);
} else {
// Inform the host about wrapper creation failure.
render_frame()->Send(new GinJavaBridgeHostMsg_ObjectWrapperDeleted(
routing_id(), iter->second));
}
}
}
void GinJavaBridgeDispatcher::OnAddNamedObject(
const std::string& name,
ObjectID object_id) {
// Added objects only become available after page reload, so here they
// are only added into the internal map.
named_objects_.insert(std::make_pair(name, object_id));
}
void GinJavaBridgeDispatcher::OnRemoveNamedObject(const std::string& name) {
// Removal becomes in effect on next reload. We simply removing the entry
// from the map here.
NamedObjectMap::iterator iter = named_objects_.find(name);
DCHECK(iter != named_objects_.end());
named_objects_.erase(iter);
}
void GinJavaBridgeDispatcher::GetJavaMethods(
ObjectID object_id,
std::set<std::string>* methods) {
render_frame()->Send(new GinJavaBridgeHostMsg_GetMethods(
routing_id(), object_id, methods));
}
bool GinJavaBridgeDispatcher::HasJavaMethod(ObjectID object_id,
const std::string& method_name) {
bool result;
render_frame()->Send(new GinJavaBridgeHostMsg_HasMethod(
routing_id(), object_id, method_name, &result));
return result;
}
scoped_ptr<base::Value> GinJavaBridgeDispatcher::InvokeJavaMethod(
ObjectID object_id,
const std::string& method_name,
const base::ListValue& arguments,
GinJavaBridgeError* error) {
base::ListValue result_wrapper;
render_frame()->Send(
new GinJavaBridgeHostMsg_InvokeMethod(routing_id(),
object_id,
method_name,
arguments,
&result_wrapper,
error));
base::Value* result;
if (result_wrapper.Get(0, &result)) {
return scoped_ptr<base::Value>(result->DeepCopy());
} else {
return scoped_ptr<base::Value>();
}
}
GinJavaBridgeObject* GinJavaBridgeDispatcher::GetObject(ObjectID object_id) {
GinJavaBridgeObject* result = objects_.Lookup(object_id);
if (!result) {
result = GinJavaBridgeObject::InjectAnonymous(AsWeakPtr(), object_id);
if (result)
objects_.AddWithID(result, object_id);
}
return result;
}
void GinJavaBridgeDispatcher::OnGinJavaBridgeObjectDeleted(ObjectID object_id) {
if (!objects_.Lookup(object_id))
return;
objects_.Remove(object_id);
render_frame()->Send(
new GinJavaBridgeHostMsg_ObjectWrapperDeleted(routing_id(), object_id));
}
} // namespace content
|