OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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/app_bindings.h" | 5 #include "chrome/renderer/extensions/app_bindings.h" |
6 | 6 |
7 #include "base/command_line.h" | 7 #include "base/command_line.h" |
8 #include "base/string16.h" | 8 #include "base/string16.h" |
9 #include "base/string_util.h" | 9 #include "base/string_util.h" |
10 #include "base/utf_string_conversions.h" | 10 #include "base/utf_string_conversions.h" |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
46 return false; | 46 return false; |
47 } | 47 } |
48 | 48 |
49 return true; | 49 return true; |
50 } | 50 } |
51 | 51 |
52 const char* kMissingClientIdError = "Missing clientId parameter"; | 52 const char* kMissingClientIdError = "Missing clientId parameter"; |
53 const char* kInvalidClientIdError = "Invalid clientId"; | 53 const char* kInvalidClientIdError = "Invalid clientId"; |
54 const char* kInvalidCallbackIdError = "Invalid callbackId"; | 54 const char* kInvalidCallbackIdError = "Invalid callbackId"; |
55 | 55 |
56 | |
57 class AppBindingsHandler : public ChromeV8ExtensionHandler { | |
58 public: | |
59 AppBindingsHandler(ExtensionDispatcher* dispatcher, ChromeV8Context* context); | |
60 | |
61 // ChromeV8ExtensionHandler | |
62 virtual v8::Handle<v8::Value> HandleNativeFunction( | |
63 const std::string& name, | |
64 const v8::Arguments& arguments) OVERRIDE; | |
65 | |
66 // IPC::Channel::Listener | |
67 virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE; | |
68 | |
69 private: | |
70 v8::Handle<v8::Value> GetIsInstalled(const v8::Arguments& args); | |
71 v8::Handle<v8::Value> Install(const v8::Arguments& args); | |
72 v8::Handle<v8::Value> GetDetails(const v8::Arguments& args); | |
73 v8::Handle<v8::Value> GetDetailsForFrame(const v8::Arguments& args); | |
74 v8::Handle<v8::Value> GetAppNotifyChannel(const v8::Arguments& args); | |
75 | |
76 v8::Handle<v8::Value> GetDetailsForFrameImpl(WebKit::WebFrame* frame); | |
77 | |
78 void OnGetAppNotifyChannelResponse(const std::string& channel_id, | |
79 const std::string& error, | |
80 int callback_id); | |
81 | |
82 ExtensionDispatcher* dispatcher_; | |
83 DISALLOW_COPY_AND_ASSIGN(AppBindingsHandler); | |
84 }; | |
85 | |
86 } // namespace | 56 } // namespace |
87 | 57 |
88 | 58 |
89 AppBindings::AppBindings(ExtensionDispatcher* dispatcher) | 59 AppBindings::AppBindings(ExtensionDispatcher* dispatcher, |
90 : ChromeV8Extension("extensions/app.js", IDR_APP_BINDINGS_JS, | 60 ChromeV8Context* context) |
91 dispatcher) { | 61 : ChromeV8Extension(dispatcher), |
92 } | 62 ChromeV8ExtensionHandler(context) { |
93 | 63 RouteFunction("GetIsInstalled", |
94 ChromeV8ExtensionHandler* AppBindings::CreateHandler( | 64 base::Bind(&AppBindings::GetIsInstalled, base::Unretained(this))); |
95 ChromeV8Context* context) { | 65 RouteFunction("Install", |
96 return new AppBindingsHandler(extension_dispatcher(), context); | 66 base::Bind(&AppBindings::Install, base::Unretained(this))); |
| 67 RouteFunction("GetDetails", |
| 68 base::Bind(&AppBindings::GetDetails, base::Unretained(this))); |
| 69 RouteFunction("GetDetailsForFrame", |
| 70 base::Bind(&AppBindings::GetDetailsForFrame, base::Unretained(this))); |
| 71 RouteFunction("GetAppNotifyChannel", |
| 72 base::Bind(&AppBindings::GetAppNotifyChannel, base::Unretained(this))); |
97 } | 73 } |
98 | 74 |
99 | 75 |
100 | 76 v8::Handle<v8::Value> AppBindings::GetIsInstalled( |
101 AppBindingsHandler::AppBindingsHandler(ExtensionDispatcher* dispatcher, | |
102 ChromeV8Context* context) | |
103 : ChromeV8ExtensionHandler(context), | |
104 dispatcher_(dispatcher) { | |
105 } | |
106 | |
107 v8::Handle<v8::Value> AppBindingsHandler::HandleNativeFunction( | |
108 const std::string& name, const v8::Arguments& args) { | |
109 // TODO(aa): Create a helper map of callback that can be used in either | |
110 // extensions or handlers. | |
111 if (name == "GetIsInstalled") { | |
112 return GetIsInstalled(args); | |
113 } else if (name == "Install") { | |
114 return Install(args); | |
115 } else if (name == "GetDetails") { | |
116 return GetDetails(args); | |
117 } else if (name == "GetDetailsForFrame") { | |
118 return GetDetailsForFrame(args); | |
119 } else if (name == "GetAppNotifyChannel") { | |
120 return GetAppNotifyChannel(args); | |
121 } else { | |
122 CHECK(false) << "Unknown native function: " << name; | |
123 } | |
124 | |
125 return v8::Undefined(); | |
126 } | |
127 | |
128 v8::Handle<v8::Value> AppBindingsHandler::GetIsInstalled( | |
129 const v8::Arguments& args) { | 77 const v8::Arguments& args) { |
130 // TODO(aa): Hm, maybe ExtensionBindingsContext should have GetExtension() | 78 // TODO(aa): Hm, maybe ExtensionBindingsContext should have GetExtension() |
131 // afterall? | 79 // afterall? |
132 const ::Extension* extension = | 80 const ::Extension* extension = |
133 dispatcher_->extensions()->GetByID(context_->extension_id()); | 81 extension_dispatcher_->extensions()->GetByID(context_->extension_id()); |
134 | 82 |
135 // TODO(aa): Why only hosted app? | 83 // TODO(aa): Why only hosted app? |
136 // TODO(aa): GARRR - why is there IsExtensionActive and IsApplicationActive!? | 84 // TODO(aa): GARRR - why is there IsExtensionActive and IsApplicationActive!? |
137 bool result = extension && extension->is_hosted_app() && | 85 bool result = extension && extension->is_hosted_app() && |
138 dispatcher_->IsApplicationActive(extension->id()); | 86 extension_dispatcher_->IsApplicationActive(extension->id()); |
139 return v8::Boolean::New(result); | 87 return v8::Boolean::New(result); |
140 } | 88 } |
141 | 89 |
142 v8::Handle<v8::Value> AppBindingsHandler::Install(const v8::Arguments& args) { | 90 v8::Handle<v8::Value> AppBindings::Install(const v8::Arguments& args) { |
143 content::RenderView* render_view = context_->GetRenderView(); | 91 content::RenderView* render_view = context_->GetRenderView(); |
144 CHECK(render_view); | 92 CHECK(render_view); |
145 | 93 |
146 string16 error; | 94 string16 error; |
147 ExtensionHelper* helper = ExtensionHelper::Get(render_view); | 95 ExtensionHelper* helper = ExtensionHelper::Get(render_view); |
148 if (!helper->InstallWebApplicationUsingDefinitionFile( | 96 if (!helper->InstallWebApplicationUsingDefinitionFile( |
149 context_->web_frame(), &error)) { | 97 context_->web_frame(), &error)) { |
150 v8::ThrowException(v8::String::New(UTF16ToUTF8(error).c_str())); | 98 v8::ThrowException(v8::String::New(UTF16ToUTF8(error).c_str())); |
151 } | 99 } |
152 | 100 |
153 return v8::Undefined(); | 101 return v8::Undefined(); |
154 } | 102 } |
155 | 103 |
156 v8::Handle<v8::Value> AppBindingsHandler::GetDetails( | 104 v8::Handle<v8::Value> AppBindings::GetDetails( |
157 const v8::Arguments& args) { | 105 const v8::Arguments& args) { |
158 CHECK(context_->web_frame()); | 106 CHECK(context_->web_frame()); |
159 return GetDetailsForFrameImpl(context_->web_frame()); | 107 return GetDetailsForFrameImpl(context_->web_frame()); |
160 } | 108 } |
161 | 109 |
162 v8::Handle<v8::Value> AppBindingsHandler::GetDetailsForFrame( | 110 v8::Handle<v8::Value> AppBindings::GetDetailsForFrame( |
163 const v8::Arguments& args) { | 111 const v8::Arguments& args) { |
164 CHECK(context_->web_frame()); | 112 CHECK(context_->web_frame()); |
165 if (!CheckAccessToAppDetails(context_->web_frame())) | 113 if (!CheckAccessToAppDetails(context_->web_frame())) |
166 return v8::Undefined(); | 114 return v8::Undefined(); |
167 | 115 |
168 if (args.Length() < 0) | 116 if (args.Length() < 0) |
169 return v8::ThrowException(v8::String::New("Not enough arguments.")); | 117 return v8::ThrowException(v8::String::New("Not enough arguments.")); |
170 | 118 |
171 if (!args[0]->IsObject()) { | 119 if (!args[0]->IsObject()) { |
172 return v8::ThrowException( | 120 return v8::ThrowException( |
173 v8::String::New("Argument 0 must be an object.")); | 121 v8::String::New("Argument 0 must be an object.")); |
174 } | 122 } |
175 | 123 |
176 v8::Local<v8::Context> context = | 124 v8::Local<v8::Context> context = |
177 v8::Local<v8::Object>::Cast(args[0])->CreationContext(); | 125 v8::Local<v8::Object>::Cast(args[0])->CreationContext(); |
178 CHECK(!context.IsEmpty()); | 126 CHECK(!context.IsEmpty()); |
179 | 127 |
180 WebFrame* target_frame = WebFrame::frameForContext(context); | 128 WebFrame* target_frame = WebFrame::frameForContext(context); |
181 if (!target_frame) { | 129 if (!target_frame) { |
182 return v8::ThrowException( | 130 return v8::ThrowException( |
183 v8::String::New("Could not find frame for specified object.")); | 131 v8::String::New("Could not find frame for specified object.")); |
184 } | 132 } |
185 | 133 |
186 return GetDetailsForFrameImpl(target_frame); | 134 return GetDetailsForFrameImpl(target_frame); |
187 } | 135 } |
188 | 136 |
189 v8::Handle<v8::Value> AppBindingsHandler::GetDetailsForFrameImpl( | 137 v8::Handle<v8::Value> AppBindings::GetDetailsForFrameImpl( |
190 WebFrame* frame) { | 138 WebFrame* frame) { |
191 const ::Extension* extension = | 139 const ::Extension* extension = |
192 dispatcher_->extensions()->GetExtensionOrAppByURL(ExtensionURLInfo( | 140 extension_dispatcher_->extensions()->GetExtensionOrAppByURL( |
193 frame->document().securityOrigin(), | 141 ExtensionURLInfo(frame->document().securityOrigin(), |
194 frame->document().url())); | 142 frame->document().url())); |
195 if (!extension) | 143 if (!extension) |
196 return v8::Null(); | 144 return v8::Null(); |
197 | 145 |
198 scoped_ptr<DictionaryValue> manifest_copy( | 146 scoped_ptr<DictionaryValue> manifest_copy( |
199 extension->manifest()->value()->DeepCopy()); | 147 extension->manifest()->value()->DeepCopy()); |
200 manifest_copy->SetString("id", extension->id()); | 148 manifest_copy->SetString("id", extension->id()); |
201 scoped_ptr<V8ValueConverter> converter(V8ValueConverter::create()); | 149 scoped_ptr<V8ValueConverter> converter(V8ValueConverter::create()); |
202 return converter->ToV8Value(manifest_copy.get(), | 150 return converter->ToV8Value(manifest_copy.get(), |
203 frame->mainWorldScriptContext()); | 151 frame->mainWorldScriptContext()); |
204 } | 152 } |
205 | 153 |
206 v8::Handle<v8::Value> AppBindingsHandler::GetAppNotifyChannel( | 154 v8::Handle<v8::Value> AppBindings::GetAppNotifyChannel( |
207 const v8::Arguments& args) { | 155 const v8::Arguments& args) { |
208 // Read the required 'clientId' value out of the object at args[0]. | 156 // Read the required 'clientId' value out of the object at args[0]. |
209 std::string client_id; | 157 std::string client_id; |
210 if (args.Length() < 1 || !args[0]->IsObject()) { | 158 if (args.Length() < 1 || !args[0]->IsObject()) { |
211 v8::ThrowException(v8::String::New(kMissingClientIdError)); | 159 v8::ThrowException(v8::String::New(kMissingClientIdError)); |
212 return v8::Undefined(); | 160 return v8::Undefined(); |
213 } | 161 } |
214 v8::Local<v8::Object> obj = v8::Local<v8::Object>::Cast(args[0]); | 162 v8::Local<v8::Object> obj = v8::Local<v8::Object>::Cast(args[0]); |
215 v8::Local<v8::String> client_id_key = v8::String::New("clientId"); | 163 v8::Local<v8::String> client_id_key = v8::String::New("clientId"); |
216 if (obj->Has(client_id_key)) { | 164 if (obj->Has(client_id_key)) { |
(...skipping 18 matching lines...) Expand all Loading... |
235 | 183 |
236 content::RenderView* render_view = context_->GetRenderView(); | 184 content::RenderView* render_view = context_->GetRenderView(); |
237 CHECK(render_view); | 185 CHECK(render_view); |
238 | 186 |
239 Send(new ExtensionHostMsg_GetAppNotifyChannel( | 187 Send(new ExtensionHostMsg_GetAppNotifyChannel( |
240 render_view->GetRoutingID(), context_->web_frame()->document().url(), | 188 render_view->GetRoutingID(), context_->web_frame()->document().url(), |
241 client_id, GetRoutingID(), callback_id)); | 189 client_id, GetRoutingID(), callback_id)); |
242 return v8::Undefined(); | 190 return v8::Undefined(); |
243 } | 191 } |
244 | 192 |
245 bool AppBindingsHandler::OnMessageReceived(const IPC::Message& message) { | 193 bool AppBindings::OnMessageReceived(const IPC::Message& message) { |
246 IPC_BEGIN_MESSAGE_MAP(AppBindingsHandler, message) | 194 IPC_BEGIN_MESSAGE_MAP(AppBindings, message) |
247 IPC_MESSAGE_HANDLER(ExtensionMsg_GetAppNotifyChannelResponse, | 195 IPC_MESSAGE_HANDLER(ExtensionMsg_GetAppNotifyChannelResponse, |
248 OnGetAppNotifyChannelResponse) | 196 OnGetAppNotifyChannelResponse) |
249 IPC_MESSAGE_UNHANDLED(CHECK(false) << "Unhandled IPC message") | 197 IPC_MESSAGE_UNHANDLED(CHECK(false) << "Unhandled IPC message") |
250 IPC_END_MESSAGE_MAP() | 198 IPC_END_MESSAGE_MAP() |
251 return true; | 199 return true; |
252 } | 200 } |
253 | 201 |
254 void AppBindingsHandler::OnGetAppNotifyChannelResponse( | 202 void AppBindings::OnGetAppNotifyChannelResponse( |
255 const std::string& channel_id, const std::string& error, int callback_id) { | 203 const std::string& channel_id, const std::string& error, int callback_id) { |
256 v8::HandleScope handle_scope; | 204 v8::HandleScope handle_scope; |
257 v8::Context::Scope context_scope(context_->v8_context()); | 205 v8::Context::Scope context_scope(context_->v8_context()); |
258 v8::Handle<v8::Value> argv[3]; | 206 v8::Handle<v8::Value> argv[3]; |
259 argv[0] = v8::String::New(channel_id.c_str()); | 207 argv[0] = v8::String::New(channel_id.c_str()); |
260 argv[1] = v8::String::New(error.c_str()); | 208 argv[1] = v8::String::New(error.c_str()); |
261 argv[2] = v8::Integer::New(callback_id); | 209 argv[2] = v8::Integer::New(callback_id); |
262 CHECK(context_->CallChromeHiddenMethod("app.onGetAppNotifyChannelResponse", | 210 CHECK(context_->CallChromeHiddenMethod("app.onGetAppNotifyChannelResponse", |
263 arraysize(argv), argv, NULL)); | 211 arraysize(argv), argv, NULL)); |
264 } | 212 } |
OLD | NEW |