Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/renderer/extensions/renderer_extension_bindings.h" | 5 #include "chrome/renderer/extensions/renderer_extension_bindings.h" |
| 6 | 6 |
| 7 #include "app/resource_bundle.h" | 7 #include "app/resource_bundle.h" |
| 8 #include "base/basictypes.h" | 8 #include "base/basictypes.h" |
| 9 #include "base/values.h" | 9 #include "base/values.h" |
| 10 #include "chrome/common/render_messages.h" | 10 #include "chrome/common/render_messages.h" |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 30 namespace { | 30 namespace { |
| 31 | 31 |
| 32 struct ExtensionData { | 32 struct ExtensionData { |
| 33 struct PortData { | 33 struct PortData { |
| 34 int ref_count; // how many contexts have a handle to this port | 34 int ref_count; // how many contexts have a handle to this port |
| 35 bool disconnected; // true if this port was forcefully disconnected | 35 bool disconnected; // true if this port was forcefully disconnected |
| 36 PortData() : ref_count(0), disconnected(false) {} | 36 PortData() : ref_count(0), disconnected(false) {} |
| 37 }; | 37 }; |
| 38 std::map<int, PortData> ports; // port ID -> data | 38 std::map<int, PortData> ports; // port ID -> data |
| 39 }; | 39 }; |
| 40 bool HasPortData(int port_id) { | |
| 41 return Singleton<ExtensionData>::get()->ports.find(port_id) != | |
| 42 Singleton<ExtensionData>::get()->ports.end(); | |
| 43 } | |
| 40 ExtensionData::PortData& GetPortData(int port_id) { | 44 ExtensionData::PortData& GetPortData(int port_id) { |
| 41 return Singleton<ExtensionData>::get()->ports[port_id]; | 45 return Singleton<ExtensionData>::get()->ports[port_id]; |
| 42 } | 46 } |
| 47 void ClearPortData(int port_id) { | |
| 48 Singleton<ExtensionData>::get()->ports.erase(port_id); | |
| 49 } | |
| 43 | 50 |
| 51 const char kPortClosedError[] = "Attempting to use a disconnected port object"; | |
| 44 const char* kExtensionDeps[] = { EventBindings::kName }; | 52 const char* kExtensionDeps[] = { EventBindings::kName }; |
| 45 | 53 |
| 46 class ExtensionImpl : public ExtensionBase { | 54 class ExtensionImpl : public ExtensionBase { |
| 47 public: | 55 public: |
| 48 ExtensionImpl() | 56 ExtensionImpl() |
| 49 : ExtensionBase(RendererExtensionBindings::kName, | 57 : ExtensionBase(RendererExtensionBindings::kName, |
| 50 GetStringResource<IDR_RENDERER_EXTENSION_BINDINGS_JS>(), | 58 GetStringResource<IDR_RENDERER_EXTENSION_BINDINGS_JS>(), |
| 51 arraysize(kExtensionDeps), kExtensionDeps) { | 59 arraysize(kExtensionDeps), kExtensionDeps) { |
| 52 } | 60 } |
| 53 ~ExtensionImpl() {} | 61 ~ExtensionImpl() {} |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 92 } | 100 } |
| 93 | 101 |
| 94 // Sends a message along the given channel. | 102 // Sends a message along the given channel. |
| 95 static v8::Handle<v8::Value> PostMessage(const v8::Arguments& args) { | 103 static v8::Handle<v8::Value> PostMessage(const v8::Arguments& args) { |
| 96 RenderView* renderview = bindings_utils::GetRenderViewForCurrentContext(); | 104 RenderView* renderview = bindings_utils::GetRenderViewForCurrentContext(); |
| 97 if (!renderview) | 105 if (!renderview) |
| 98 return v8::Undefined(); | 106 return v8::Undefined(); |
| 99 | 107 |
| 100 if (args.Length() >= 2 && args[0]->IsInt32() && args[1]->IsString()) { | 108 if (args.Length() >= 2 && args[0]->IsInt32() && args[1]->IsString()) { |
| 101 int port_id = args[0]->Int32Value(); | 109 int port_id = args[0]->Int32Value(); |
| 110 if (!HasPortData(port_id)) { | |
| 111 return v8::ThrowException(v8::Exception::Error( | |
| 112 v8::String::New(kPortClosedError))); | |
| 113 } | |
| 102 std::string message = *v8::String::Utf8Value(args[1]->ToString()); | 114 std::string message = *v8::String::Utf8Value(args[1]->ToString()); |
| 103 renderview->Send(new ViewHostMsg_ExtensionPostMessage( | 115 renderview->Send(new ViewHostMsg_ExtensionPostMessage( |
| 104 renderview->routing_id(), port_id, message)); | 116 renderview->routing_id(), port_id, message)); |
| 105 } | 117 } |
| 106 return v8::Undefined(); | 118 return v8::Undefined(); |
| 107 } | 119 } |
| 108 | 120 |
| 109 // Forcefully disconnects a port. | 121 // Forcefully disconnects a port. |
| 110 static v8::Handle<v8::Value> CloseChannel(const v8::Arguments& args) { | 122 static v8::Handle<v8::Value> CloseChannel(const v8::Arguments& args) { |
| 111 if (args.Length() >= 1 && args[0]->IsInt32()) { | 123 if (args.Length() >= 1 && args[0]->IsInt32()) { |
| 112 int port_id = args[0]->Int32Value(); | 124 int port_id = args[0]->Int32Value(); |
| 125 if (!HasPortData(port_id)) { | |
|
Aaron Boodman
2009/10/31 19:21:22
Maybe we don't want to throw here? It seems nice t
Matt Perry
2009/11/03 00:39:36
Done.
| |
| 126 return v8::ThrowException(v8::Exception::Error( | |
| 127 v8::String::New(kPortClosedError))); | |
| 128 } | |
| 113 // Send via the RenderThread because the RenderView might be closing. | 129 // Send via the RenderThread because the RenderView might be closing. |
| 114 EventBindings::GetRenderThread()->Send( | 130 EventBindings::GetRenderThread()->Send( |
| 115 new ViewHostMsg_ExtensionCloseChannel(port_id)); | 131 new ViewHostMsg_ExtensionCloseChannel(port_id)); |
| 116 GetPortData(port_id).disconnected = true; | 132 ClearPortData(port_id); |
| 117 } | 133 } |
| 118 return v8::Undefined(); | 134 return v8::Undefined(); |
| 119 } | 135 } |
| 120 | 136 |
| 121 // A new port has been created for a context. This occurs both when script | 137 // A new port has been created for a context. This occurs both when script |
| 122 // opens a connection, and when a connection is opened to this script. | 138 // opens a connection, and when a connection is opened to this script. |
| 123 static v8::Handle<v8::Value> PortAddRef(const v8::Arguments& args) { | 139 static v8::Handle<v8::Value> PortAddRef(const v8::Arguments& args) { |
| 124 if (args.Length() >= 1 && args[0]->IsInt32()) { | 140 if (args.Length() >= 1 && args[0]->IsInt32()) { |
| 125 int port_id = args[0]->Int32Value(); | 141 int port_id = args[0]->Int32Value(); |
| 126 ++GetPortData(port_id).ref_count; | 142 ++GetPortData(port_id).ref_count; |
| 127 } | 143 } |
| 128 return v8::Undefined(); | 144 return v8::Undefined(); |
| 129 } | 145 } |
| 130 | 146 |
| 131 // The frame a port lived in has been destroyed. When there are no more | 147 // The frame a port lived in has been destroyed. When there are no more |
| 132 // frames with a reference to a given port, we will disconnect it and notify | 148 // frames with a reference to a given port, we will disconnect it and notify |
| 133 // the other end of the channel. | 149 // the other end of the channel. |
| 134 static v8::Handle<v8::Value> PortRelease(const v8::Arguments& args) { | 150 static v8::Handle<v8::Value> PortRelease(const v8::Arguments& args) { |
| 135 if (args.Length() >= 1 && args[0]->IsInt32()) { | 151 if (args.Length() >= 1 && args[0]->IsInt32()) { |
| 136 int port_id = args[0]->Int32Value(); | 152 int port_id = args[0]->Int32Value(); |
| 137 if (!GetPortData(port_id).disconnected && | 153 if (HasPortData(port_id) && --GetPortData(port_id).ref_count == 0) { |
| 138 --GetPortData(port_id).ref_count == 0) { | |
| 139 // Send via the RenderThread because the RenderView might be closing. | 154 // Send via the RenderThread because the RenderView might be closing. |
| 140 EventBindings::GetRenderThread()->Send( | 155 EventBindings::GetRenderThread()->Send( |
| 141 new ViewHostMsg_ExtensionCloseChannel(port_id)); | 156 new ViewHostMsg_ExtensionCloseChannel(port_id)); |
| 157 ClearPortData(port_id); | |
| 142 } | 158 } |
| 143 } | 159 } |
| 144 return v8::Undefined(); | 160 return v8::Undefined(); |
| 145 } | 161 } |
| 146 }; | 162 }; |
| 147 | 163 |
| 148 // Convert a ListValue to a vector of V8 values. | 164 // Convert a ListValue to a vector of V8 values. |
| 149 static std::vector< v8::Handle<v8::Value> > ListValueToV8( | 165 static std::vector< v8::Handle<v8::Value> > ListValueToV8( |
| 150 const ListValue& value) { | 166 const ListValue& value) { |
| 151 std::vector< v8::Handle<v8::Value> > v8_values; | 167 std::vector< v8::Handle<v8::Value> > v8_values; |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 200 return extension; | 216 return extension; |
| 201 } | 217 } |
| 202 | 218 |
| 203 void RendererExtensionBindings::Invoke(const std::string& function_name, | 219 void RendererExtensionBindings::Invoke(const std::string& function_name, |
| 204 const ListValue& args, | 220 const ListValue& args, |
| 205 RenderView* renderview) { | 221 RenderView* renderview) { |
| 206 v8::HandleScope handle_scope; | 222 v8::HandleScope handle_scope; |
| 207 std::vector< v8::Handle<v8::Value> > argv = ListValueToV8(args); | 223 std::vector< v8::Handle<v8::Value> > argv = ListValueToV8(args); |
| 208 EventBindings::CallFunction(function_name, argv.size(), &argv[0], renderview); | 224 EventBindings::CallFunction(function_name, argv.size(), &argv[0], renderview); |
| 209 } | 225 } |
| OLD | NEW |