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
|
// 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/auto_reset.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;
}
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;
base::AutoReset<bool> flag_entry(&inside_did_clear_window_object_, true);
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(
GinJavaBridgeObject* object) {
int object_id = object->object_id();
// Ignore cleaning up of old object wrappers.
if (objects_.Lookup(object_id) != object) return;
objects_.Remove(object_id);
render_frame()->Send(
new GinJavaBridgeHostMsg_ObjectWrapperDeleted(routing_id(), object_id));
}
} // namespace content
|