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