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.
5 #include "extensions/browser/extension_function.h"
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/error_utils.h"
17 #include "extensions/common/extension_api.h"
18 #include "extensions/common/extension_messages.h"
20 using content::BrowserThread
;
21 using content::RenderViewHost
;
22 using content::WebContents
;
23 using extensions::ErrorUtils
;
24 using extensions::ExtensionAPI
;
25 using extensions::Feature
;
29 class ArgumentListResponseValue
30 : public ExtensionFunction::ResponseValueObject
{
32 ArgumentListResponseValue(const std::string
& function_name
,
34 ExtensionFunction
* function
,
35 scoped_ptr
<base::ListValue
> result
)
36 : function_name_(function_name
), title_(title
) {
37 if (function
->GetResultList()) {
38 DCHECK_EQ(function
->GetResultList(), result
.get())
39 << "The result set on this function (" << function_name_
<< ") "
40 << "either by calling SetResult() or directly modifying |result_| is "
41 << "different to the one passed to " << title_
<< "(). "
42 << "The best way to fix this problem is to exclusively use " << title_
43 << "(). SetResult() and |result_| are deprecated.";
45 function
->SetResultList(result
.Pass());
47 // It would be nice to DCHECK(error.empty()) but some legacy extension
48 // function implementations... I'm looking at chrome.input.ime... do this
52 ~ArgumentListResponseValue() override
{}
54 bool Apply() override
{ return true; }
57 std::string function_name_
;
61 class ErrorResponseValue
: public ExtensionFunction::ResponseValueObject
{
63 ErrorResponseValue(ExtensionFunction
* function
, const std::string
& error
) {
64 // It would be nice to DCHECK(!error.empty()) but too many legacy extension
65 // function implementations don't set error but signal failure.
66 function
->SetError(error
);
69 ~ErrorResponseValue() override
{}
71 bool Apply() override
{ return false; }
74 class BadMessageResponseValue
: public ExtensionFunction::ResponseValueObject
{
76 explicit BadMessageResponseValue(ExtensionFunction
* function
) {
77 function
->set_bad_message(true);
78 NOTREACHED() << function
->name() << ": bad message";
81 ~BadMessageResponseValue() override
{}
83 bool Apply() override
{ return false; }
86 class RespondNowAction
: public ExtensionFunction::ResponseActionObject
{
88 typedef base::Callback
<void(bool)> SendResponseCallback
;
89 RespondNowAction(ExtensionFunction::ResponseValue result
,
90 const SendResponseCallback
& send_response
)
91 : result_(result
.Pass()), send_response_(send_response
) {}
92 ~RespondNowAction() override
{}
94 void Execute() override
{ send_response_
.Run(result_
->Apply()); }
97 ExtensionFunction::ResponseValue result_
;
98 SendResponseCallback send_response_
;
101 class RespondLaterAction
: public ExtensionFunction::ResponseActionObject
{
103 ~RespondLaterAction() override
{}
105 void Execute() override
{}
111 void ExtensionFunctionDeleteTraits::Destruct(const ExtensionFunction
* x
) {
115 // Helper class to track the lifetime of ExtensionFunction's RenderViewHost or
116 // RenderFrameHost pointer and NULL it out when it dies. It also allows us to
117 // filter IPC messages coming from the RenderViewHost/RenderFrameHost.
118 class UIThreadExtensionFunction::RenderHostTracker
119 : public content::WebContentsObserver
{
121 explicit RenderHostTracker(UIThreadExtensionFunction
* function
)
122 : content::WebContentsObserver(
123 function
->render_view_host() ?
124 WebContents::FromRenderViewHost(function
->render_view_host()) :
125 WebContents::FromRenderFrameHost(
126 function
->render_frame_host())),
127 function_(function
) {
131 // content::WebContentsObserver:
132 void RenderViewDeleted(content::RenderViewHost
* render_view_host
) override
{
133 if (render_view_host
!= function_
->render_view_host())
136 function_
->SetRenderViewHost(NULL
);
138 void RenderFrameDeleted(
139 content::RenderFrameHost
* render_frame_host
) override
{
140 if (render_frame_host
!= function_
->render_frame_host())
143 function_
->SetRenderFrameHost(NULL
);
146 bool OnMessageReceived(const IPC::Message
& message
,
147 content::RenderFrameHost
* render_frame_host
) override
{
148 DCHECK(render_frame_host
);
149 if (render_frame_host
== function_
->render_frame_host())
150 return function_
->OnMessageReceived(message
);
155 bool OnMessageReceived(const IPC::Message
& message
) override
{
156 return function_
->OnMessageReceived(message
);
159 UIThreadExtensionFunction
* function_
;
161 DISALLOW_COPY_AND_ASSIGN(RenderHostTracker
);
164 ExtensionFunction::ExtensionFunction()
167 has_callback_(false),
168 include_incognito_(false),
169 user_gesture_(false),
171 histogram_value_(extensions::functions::UNKNOWN
),
173 source_context_type_(Feature::UNSPECIFIED_CONTEXT
) {
176 ExtensionFunction::~ExtensionFunction() {
179 UIThreadExtensionFunction
* ExtensionFunction::AsUIThreadExtensionFunction() {
183 IOThreadExtensionFunction
* ExtensionFunction::AsIOThreadExtensionFunction() {
187 bool ExtensionFunction::HasPermission() {
188 Feature::Availability availability
=
189 ExtensionAPI::GetSharedInstance()->IsAvailable(
190 name_
, extension_
.get(), source_context_type_
, source_url());
191 return availability
.is_available();
194 void ExtensionFunction::OnQuotaExceeded(const std::string
& violation_error
) {
195 error_
= violation_error
;
199 void ExtensionFunction::SetArgs(const base::ListValue
* args
) {
200 DCHECK(!args_
.get()); // Should only be called once.
201 args_
.reset(args
->DeepCopy());
204 void ExtensionFunction::SetResult(base::Value
* result
) {
205 results_
.reset(new base::ListValue());
206 results_
->Append(result
);
209 void ExtensionFunction::SetResultList(scoped_ptr
<base::ListValue
> results
) {
210 results_
= results
.Pass();
213 const base::ListValue
* ExtensionFunction::GetResultList() const {
214 return results_
.get();
217 std::string
ExtensionFunction::GetError() const {
221 void ExtensionFunction::SetError(const std::string
& error
) {
225 ExtensionFunction::ResponseValue
ExtensionFunction::NoArguments() {
226 return ResponseValue(new ArgumentListResponseValue(
227 name(), "NoArguments", this, make_scoped_ptr(new base::ListValue())));
230 ExtensionFunction::ResponseValue
ExtensionFunction::OneArgument(
232 scoped_ptr
<base::ListValue
> args(new base::ListValue());
234 return ResponseValue(
235 new ArgumentListResponseValue(name(), "OneArgument", this, args
.Pass()));
238 ExtensionFunction::ResponseValue
ExtensionFunction::TwoArguments(
241 scoped_ptr
<base::ListValue
> args(new base::ListValue());
244 return ResponseValue(
245 new ArgumentListResponseValue(name(), "TwoArguments", this, args
.Pass()));
248 ExtensionFunction::ResponseValue
ExtensionFunction::ArgumentList(
249 scoped_ptr
<base::ListValue
> args
) {
250 return ResponseValue(
251 new ArgumentListResponseValue(name(), "ArgumentList", this, args
.Pass()));
254 ExtensionFunction::ResponseValue
ExtensionFunction::Error(
255 const std::string
& error
) {
256 return ResponseValue(new ErrorResponseValue(this, error
));
259 ExtensionFunction::ResponseValue
ExtensionFunction::Error(
260 const std::string
& format
,
261 const std::string
& s1
) {
262 return ResponseValue(
263 new ErrorResponseValue(this, ErrorUtils::FormatErrorMessage(format
, s1
)));
266 ExtensionFunction::ResponseValue
ExtensionFunction::Error(
267 const std::string
& format
,
268 const std::string
& s1
,
269 const std::string
& s2
) {
270 return ResponseValue(new ErrorResponseValue(
271 this, ErrorUtils::FormatErrorMessage(format
, s1
, s2
)));
274 ExtensionFunction::ResponseValue
ExtensionFunction::Error(
275 const std::string
& format
,
276 const std::string
& s1
,
277 const std::string
& s2
,
278 const std::string
& s3
) {
279 return ResponseValue(new ErrorResponseValue(
280 this, ErrorUtils::FormatErrorMessage(format
, s1
, s2
, s3
)));
283 ExtensionFunction::ResponseValue
ExtensionFunction::BadMessage() {
284 return ResponseValue(new BadMessageResponseValue(this));
287 ExtensionFunction::ResponseAction
ExtensionFunction::RespondNow(
288 ResponseValue result
) {
289 return ResponseAction(new RespondNowAction(
290 result
.Pass(), base::Bind(&ExtensionFunction::SendResponse
, this)));
293 ExtensionFunction::ResponseAction
ExtensionFunction::RespondLater() {
294 return ResponseAction(new RespondLaterAction());
298 ExtensionFunction::ResponseAction
ExtensionFunction::ValidationFailure(
299 ExtensionFunction
* function
) {
300 return function
->RespondNow(function
->BadMessage());
303 void ExtensionFunction::Respond(ResponseValue result
) {
304 SendResponse(result
->Apply());
307 bool ExtensionFunction::ShouldSkipQuotaLimiting() const {
311 bool ExtensionFunction::HasOptionalArgument(size_t index
) {
313 return args_
->Get(index
, &value
) && !value
->IsType(base::Value::TYPE_NULL
);
316 void ExtensionFunction::SendResponseImpl(bool success
) {
317 DCHECK(!response_callback_
.is_null());
319 ResponseType type
= success
? SUCCEEDED
: FAILED
;
322 LOG(ERROR
) << "Bad extension message " << name_
;
325 // If results were never set, we send an empty argument list.
327 results_
.reset(new base::ListValue());
329 response_callback_
.Run(type
, *results_
, GetError());
332 void ExtensionFunction::OnRespondingLater(ResponseValue value
) {
333 SendResponse(value
->Apply());
336 UIThreadExtensionFunction::UIThreadExtensionFunction()
337 : render_view_host_(NULL
),
338 render_frame_host_(NULL
),
343 UIThreadExtensionFunction::~UIThreadExtensionFunction() {
344 if (dispatcher() && render_view_host())
345 dispatcher()->OnExtensionFunctionCompleted(extension());
348 UIThreadExtensionFunction
*
349 UIThreadExtensionFunction::AsUIThreadExtensionFunction() {
353 bool UIThreadExtensionFunction::OnMessageReceived(const IPC::Message
& message
) {
357 void UIThreadExtensionFunction::Destruct() const {
358 BrowserThread::DeleteOnUIThread::Destruct(this);
361 void UIThreadExtensionFunction::SetRenderViewHost(
362 RenderViewHost
* render_view_host
) {
363 DCHECK(!render_frame_host_
);
364 render_view_host_
= render_view_host
;
365 tracker_
.reset(render_view_host
? new RenderHostTracker(this) : NULL
);
368 void UIThreadExtensionFunction::SetRenderFrameHost(
369 content::RenderFrameHost
* render_frame_host
) {
370 DCHECK(!render_view_host_
);
371 render_frame_host_
= render_frame_host
;
372 tracker_
.reset(render_frame_host
? new RenderHostTracker(this) : NULL
);
375 content::WebContents
* UIThreadExtensionFunction::GetAssociatedWebContents() {
376 content::WebContents
* web_contents
= NULL
;
378 web_contents
= dispatcher()->delegate()->GetAssociatedWebContents();
383 void UIThreadExtensionFunction::SendResponse(bool success
) {
385 delegate_
->OnSendResponse(this, success
, bad_message_
);
387 SendResponseImpl(success
);
389 if (!transferred_blob_uuids_
.empty()) {
390 DCHECK(!delegate_
) << "Blob transfer not supported with test delegate.";
391 GetIPCSender()->Send(
392 new ExtensionMsg_TransferBlobs(transferred_blob_uuids_
));
396 void UIThreadExtensionFunction::SetTransferredBlobUUIDs(
397 const std::vector
<std::string
>& blob_uuids
) {
398 DCHECK(transferred_blob_uuids_
.empty()); // Should only be called once.
399 transferred_blob_uuids_
= blob_uuids
;
402 void UIThreadExtensionFunction::WriteToConsole(
403 content::ConsoleMessageLevel level
,
404 const std::string
& message
) {
405 GetIPCSender()->Send(
406 new ExtensionMsg_AddMessageToConsole(GetRoutingID(), level
, message
));
409 IPC::Sender
* UIThreadExtensionFunction::GetIPCSender() {
410 if (render_view_host_
)
411 return render_view_host_
;
413 return render_frame_host_
;
416 int UIThreadExtensionFunction::GetRoutingID() {
417 if (render_view_host_
)
418 return render_view_host_
->GetRoutingID();
420 return render_frame_host_
->GetRoutingID();
423 IOThreadExtensionFunction::IOThreadExtensionFunction()
424 : routing_id_(MSG_ROUTING_NONE
) {
427 IOThreadExtensionFunction::~IOThreadExtensionFunction() {
430 IOThreadExtensionFunction
*
431 IOThreadExtensionFunction::AsIOThreadExtensionFunction() {
435 void IOThreadExtensionFunction::Destruct() const {
436 BrowserThread::DeleteOnIOThread::Destruct(this);
439 void IOThreadExtensionFunction::SendResponse(bool success
) {
440 SendResponseImpl(success
);
443 AsyncExtensionFunction::AsyncExtensionFunction() {
446 AsyncExtensionFunction::~AsyncExtensionFunction() {
449 ExtensionFunction::ResponseAction
AsyncExtensionFunction::Run() {
450 return RunAsync() ? RespondLater() : RespondNow(Error(error_
));
454 bool AsyncExtensionFunction::ValidationFailure(
455 AsyncExtensionFunction
* function
) {
459 SyncExtensionFunction::SyncExtensionFunction() {
462 SyncExtensionFunction::~SyncExtensionFunction() {
465 ExtensionFunction::ResponseAction
SyncExtensionFunction::Run() {
466 return RespondNow(RunSync() ? ArgumentList(results_
.Pass()) : Error(error_
));
470 bool SyncExtensionFunction::ValidationFailure(SyncExtensionFunction
* function
) {
474 SyncIOThreadExtensionFunction::SyncIOThreadExtensionFunction() {
477 SyncIOThreadExtensionFunction::~SyncIOThreadExtensionFunction() {
480 ExtensionFunction::ResponseAction
SyncIOThreadExtensionFunction::Run() {
481 return RespondNow(RunSync() ? ArgumentList(results_
.Pass()) : Error(error_
));
485 bool SyncIOThreadExtensionFunction::ValidationFailure(
486 SyncIOThreadExtensionFunction
* function
) {