Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / extensions / browser / extension_function.cc
1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "extensions/browser/extension_function.h"
6
7 #include "base/logging.h"
8 #include "content/public/browser/notification_source.h"
9 #include "content/public/browser/notification_types.h"
10 #include "content/public/browser/render_frame_host.h"
11 #include "content/public/browser/render_view_host.h"
12 #include "content/public/browser/web_contents.h"
13 #include "content/public/browser/web_contents_observer.h"
14 #include "extensions/browser/extension_function_dispatcher.h"
15 #include "extensions/browser/extension_message_filter.h"
16 #include "extensions/common/extension_api.h"
17 #include "extensions/common/extension_messages.h"
18
19 using content::BrowserThread;
20 using content::RenderViewHost;
21 using content::WebContents;
22 using extensions::ExtensionAPI;
23 using extensions::Feature;
24
25 namespace {
26
27 class MultipleArgumentsResponseValue
28     : public ExtensionFunction::ResponseValueObject {
29  public:
30   MultipleArgumentsResponseValue(ExtensionFunction* function,
31                                  base::ListValue* result) {
32     if (function->GetResultList()) {
33       DCHECK_EQ(function->GetResultList(), result);
34     } else {
35       function->SetResultList(make_scoped_ptr(result));
36     }
37     // It would be nice to DCHECK(error.empty()) but some legacy extension
38     // function implementations... I'm looking at chrome.input.ime... do this
39     // for some reason.
40   }
41
42   virtual ~MultipleArgumentsResponseValue() {}
43
44   virtual bool Apply() OVERRIDE { return true; }
45 };
46
47 class ErrorResponseValue : public ExtensionFunction::ResponseValueObject {
48  public:
49   ErrorResponseValue(ExtensionFunction* function, const std::string& error) {
50     // It would be nice to DCHECK(!error.empty()) but too many legacy extension
51     // function implementations don't set error but signal failure.
52     function->SetError(error);
53   }
54
55   virtual ~ErrorResponseValue() {}
56
57   virtual bool Apply() OVERRIDE { return false; }
58 };
59
60 class BadMessageResponseValue : public ExtensionFunction::ResponseValueObject {
61  public:
62   explicit BadMessageResponseValue(ExtensionFunction* function) {
63     function->set_bad_message(true);
64     NOTREACHED() << function->name() << ": bad message";
65   }
66
67   virtual ~BadMessageResponseValue() {}
68
69   virtual bool Apply() OVERRIDE { return false; }
70 };
71
72 class RespondNowAction : public ExtensionFunction::ResponseActionObject {
73  public:
74   typedef base::Callback<void(bool)> SendResponseCallback;
75   RespondNowAction(ExtensionFunction::ResponseValue result,
76                    const SendResponseCallback& send_response)
77       : result_(result.Pass()), send_response_(send_response) {}
78   virtual ~RespondNowAction() {}
79
80   virtual void Execute() OVERRIDE { send_response_.Run(result_->Apply()); }
81
82  private:
83   ExtensionFunction::ResponseValue result_;
84   SendResponseCallback send_response_;
85 };
86
87 class RespondLaterAction : public ExtensionFunction::ResponseActionObject {
88  public:
89   virtual ~RespondLaterAction() {}
90
91   virtual void Execute() OVERRIDE {}
92 };
93
94 }  // namespace
95
96 // static
97 void ExtensionFunctionDeleteTraits::Destruct(const ExtensionFunction* x) {
98   x->Destruct();
99 }
100
101 // Helper class to track the lifetime of ExtensionFunction's RenderViewHost or
102 // RenderFrameHost  pointer and NULL it out when it dies. It also allows us to
103 // filter IPC messages coming from the RenderViewHost/RenderFrameHost.
104 class UIThreadExtensionFunction::RenderHostTracker
105     : public content::WebContentsObserver {
106  public:
107   explicit RenderHostTracker(UIThreadExtensionFunction* function)
108       : content::WebContentsObserver(
109             function->render_view_host() ?
110                 WebContents::FromRenderViewHost(function->render_view_host()) :
111                 WebContents::FromRenderFrameHost(
112                     function->render_frame_host())),
113         function_(function) {
114   }
115
116  private:
117   // content::WebContentsObserver:
118   virtual void RenderViewDeleted(
119       content::RenderViewHost* render_view_host) OVERRIDE {
120     if (render_view_host != function_->render_view_host())
121       return;
122
123     function_->SetRenderViewHost(NULL);
124   }
125   virtual void RenderFrameDeleted(
126       content::RenderFrameHost* render_frame_host) OVERRIDE {
127     if (render_frame_host != function_->render_frame_host())
128       return;
129
130     function_->SetRenderFrameHost(NULL);
131   }
132
133   virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE {
134     return function_->OnMessageReceived(message);
135   }
136
137   UIThreadExtensionFunction* function_;
138
139   DISALLOW_COPY_AND_ASSIGN(RenderHostTracker);
140 };
141
142 ExtensionFunction::ExtensionFunction()
143     : request_id_(-1),
144       profile_id_(NULL),
145       has_callback_(false),
146       include_incognito_(false),
147       user_gesture_(false),
148       bad_message_(false),
149       histogram_value_(extensions::functions::UNKNOWN),
150       source_tab_id_(-1) {
151 }
152
153 ExtensionFunction::~ExtensionFunction() {
154 }
155
156 UIThreadExtensionFunction* ExtensionFunction::AsUIThreadExtensionFunction() {
157   return NULL;
158 }
159
160 IOThreadExtensionFunction* ExtensionFunction::AsIOThreadExtensionFunction() {
161   return NULL;
162 }
163
164 bool ExtensionFunction::HasPermission() {
165   Feature::Availability availability =
166       ExtensionAPI::GetSharedInstance()->IsAvailable(
167           name_, extension_, Feature::BLESSED_EXTENSION_CONTEXT, source_url());
168   return availability.is_available();
169 }
170
171 void ExtensionFunction::OnQuotaExceeded(const std::string& violation_error) {
172   error_ = violation_error;
173   SendResponse(false);
174 }
175
176 void ExtensionFunction::SetArgs(const base::ListValue* args) {
177   DCHECK(!args_.get());  // Should only be called once.
178   args_.reset(args->DeepCopy());
179 }
180
181 void ExtensionFunction::SetResult(base::Value* result) {
182   results_.reset(new base::ListValue());
183   results_->Append(result);
184 }
185
186 void ExtensionFunction::SetResultList(scoped_ptr<base::ListValue> results) {
187   results_ = results.Pass();
188 }
189
190 const base::ListValue* ExtensionFunction::GetResultList() const {
191   return results_.get();
192 }
193
194 std::string ExtensionFunction::GetError() const {
195   return error_;
196 }
197
198 void ExtensionFunction::SetError(const std::string& error) {
199   error_ = error;
200 }
201
202 ExtensionFunction::ResponseValue ExtensionFunction::NoArguments() {
203   return MultipleArguments(new base::ListValue());
204 }
205
206 ExtensionFunction::ResponseValue ExtensionFunction::SingleArgument(
207     base::Value* arg) {
208   base::ListValue* args = new base::ListValue();
209   args->Append(arg);
210   return MultipleArguments(args);
211 }
212
213 ExtensionFunction::ResponseValue ExtensionFunction::MultipleArguments(
214     base::ListValue* args) {
215   return scoped_ptr<ResponseValueObject>(
216       new MultipleArgumentsResponseValue(this, args));
217 }
218
219 ExtensionFunction::ResponseValue ExtensionFunction::Error(
220     const std::string& error) {
221   return scoped_ptr<ResponseValueObject>(new ErrorResponseValue(this, error));
222 }
223
224 ExtensionFunction::ResponseValue ExtensionFunction::BadMessage() {
225   return scoped_ptr<ResponseValueObject>(new BadMessageResponseValue(this));
226 }
227
228 ExtensionFunction::ResponseAction ExtensionFunction::RespondNow(
229     ResponseValue result) {
230   return ResponseAction(new RespondNowAction(
231       result.Pass(), base::Bind(&ExtensionFunction::SendResponse, this)));
232 }
233
234 ExtensionFunction::ResponseAction ExtensionFunction::RespondLater() {
235   return ResponseAction(new RespondLaterAction());
236 }
237
238 // static
239 ExtensionFunction::ResponseAction ExtensionFunction::ValidationFailure(
240     ExtensionFunction* function) {
241   return function->RespondNow(function->BadMessage());
242 }
243
244 void ExtensionFunction::Respond(ResponseValue result) {
245   SendResponse(result->Apply());
246 }
247
248 bool ExtensionFunction::ShouldSkipQuotaLimiting() const {
249   return false;
250 }
251
252 bool ExtensionFunction::HasOptionalArgument(size_t index) {
253   base::Value* value;
254   return args_->Get(index, &value) && !value->IsType(base::Value::TYPE_NULL);
255 }
256
257 void ExtensionFunction::SendResponseImpl(bool success) {
258   DCHECK(!response_callback_.is_null());
259
260   ResponseType type = success ? SUCCEEDED : FAILED;
261   if (bad_message_) {
262     type = BAD_MESSAGE;
263     LOG(ERROR) << "Bad extension message " << name_;
264   }
265
266   // If results were never set, we send an empty argument list.
267   if (!results_)
268     results_.reset(new base::ListValue());
269
270   response_callback_.Run(type, *results_, GetError());
271 }
272
273 void ExtensionFunction::OnRespondingLater(ResponseValue value) {
274   SendResponse(value->Apply());
275 }
276
277 UIThreadExtensionFunction::UIThreadExtensionFunction()
278     : render_view_host_(NULL),
279       render_frame_host_(NULL),
280       context_(NULL),
281       delegate_(NULL) {
282 }
283
284 UIThreadExtensionFunction::~UIThreadExtensionFunction() {
285   if (dispatcher() && render_view_host())
286     dispatcher()->OnExtensionFunctionCompleted(GetExtension());
287 }
288
289 UIThreadExtensionFunction*
290 UIThreadExtensionFunction::AsUIThreadExtensionFunction() {
291   return this;
292 }
293
294 bool UIThreadExtensionFunction::OnMessageReceived(const IPC::Message& message) {
295   return false;
296 }
297
298 void UIThreadExtensionFunction::Destruct() const {
299   BrowserThread::DeleteOnUIThread::Destruct(this);
300 }
301
302 void UIThreadExtensionFunction::SetRenderViewHost(
303     RenderViewHost* render_view_host) {
304   DCHECK(!render_frame_host_);
305   render_view_host_ = render_view_host;
306   tracker_.reset(render_view_host ? new RenderHostTracker(this) : NULL);
307 }
308
309 void UIThreadExtensionFunction::SetRenderFrameHost(
310     content::RenderFrameHost* render_frame_host) {
311   DCHECK(!render_view_host_);
312   render_frame_host_ = render_frame_host;
313   tracker_.reset(render_frame_host ? new RenderHostTracker(this) : NULL);
314 }
315
316 content::WebContents* UIThreadExtensionFunction::GetAssociatedWebContents() {
317   content::WebContents* web_contents = NULL;
318   if (dispatcher())
319     web_contents = dispatcher()->delegate()->GetAssociatedWebContents();
320
321   return web_contents;
322 }
323
324 void UIThreadExtensionFunction::SendResponse(bool success) {
325   if (delegate_)
326     delegate_->OnSendResponse(this, success, bad_message_);
327   else
328     SendResponseImpl(success);
329 }
330
331 void UIThreadExtensionFunction::WriteToConsole(
332     content::ConsoleMessageLevel level,
333     const std::string& message) {
334   if (render_view_host_) {
335     render_view_host_->Send(new ExtensionMsg_AddMessageToConsole(
336         render_view_host_->GetRoutingID(), level, message));
337   } else {
338     render_frame_host_->Send(new ExtensionMsg_AddMessageToConsole(
339         render_frame_host_->GetRoutingID(), level, message));
340   }
341 }
342
343 IOThreadExtensionFunction::IOThreadExtensionFunction()
344     : routing_id_(MSG_ROUTING_NONE) {
345 }
346
347 IOThreadExtensionFunction::~IOThreadExtensionFunction() {
348 }
349
350 IOThreadExtensionFunction*
351 IOThreadExtensionFunction::AsIOThreadExtensionFunction() {
352   return this;
353 }
354
355 void IOThreadExtensionFunction::Destruct() const {
356   BrowserThread::DeleteOnIOThread::Destruct(this);
357 }
358
359 void IOThreadExtensionFunction::SendResponse(bool success) {
360   SendResponseImpl(success);
361 }
362
363 AsyncExtensionFunction::AsyncExtensionFunction() {
364 }
365
366 AsyncExtensionFunction::~AsyncExtensionFunction() {
367 }
368
369 ExtensionFunction::ResponseAction AsyncExtensionFunction::Run() {
370   return RunAsync() ? RespondLater() : RespondNow(Error(error_));
371 }
372
373 // static
374 bool AsyncExtensionFunction::ValidationFailure(
375     AsyncExtensionFunction* function) {
376   return false;
377 }
378
379 SyncExtensionFunction::SyncExtensionFunction() {
380 }
381
382 SyncExtensionFunction::~SyncExtensionFunction() {
383 }
384
385 ExtensionFunction::ResponseAction SyncExtensionFunction::Run() {
386   return RespondNow(RunSync() ? MultipleArguments(results_.get())
387                               : Error(error_));
388 }
389
390 // static
391 bool SyncExtensionFunction::ValidationFailure(SyncExtensionFunction* function) {
392   return false;
393 }
394
395 SyncIOThreadExtensionFunction::SyncIOThreadExtensionFunction() {
396 }
397
398 SyncIOThreadExtensionFunction::~SyncIOThreadExtensionFunction() {
399 }
400
401 ExtensionFunction::ResponseAction SyncIOThreadExtensionFunction::Run() {
402   return RespondNow(RunSync() ? MultipleArguments(results_.get())
403                               : Error(error_));
404 }
405
406 // static
407 bool SyncIOThreadExtensionFunction::ValidationFailure(
408     SyncIOThreadExtensionFunction* function) {
409   return false;
410 }