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 |