blob: accc12d4e4139be6003eb2323e4c32dfcba3c3ad [file] [log] [blame]
[email protected]14c3571a2013-11-13 00:18:441// Copyright 2013 The Chromium Authors. All rights reserved.
[email protected]703e807a2009-03-28 19:56:512// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
[email protected]14c3571a2013-11-13 00:18:445#include "extensions/browser/extension_function.h"
[email protected]703e807a2009-03-28 19:56:516
[email protected]73404a372009-04-17 23:09:107#include "base/logging.h"
[email protected]86ab86b2011-10-19 03:07:558#include "content/public/browser/notification_source.h"
[email protected]0d6e9bd2011-10-18 04:29:169#include "content/public/browser/notification_types.h"
[email protected]6dd625e2013-12-20 17:03:0710#include "content/public/browser/render_frame_host.h"
[email protected]9c1662b2012-03-06 15:44:3311#include "content/public/browser/render_view_host.h"
[email protected]bc0ee242013-10-22 03:46:1412#include "content/public/browser/web_contents.h"
13#include "content/public/browser/web_contents_observer.h"
[email protected]0b9de032014-03-15 05:47:0114#include "extensions/browser/extension_function_dispatcher.h"
[email protected]1a0436892014-04-01 00:38:2515#include "extensions/browser/extension_message_filter.h"
[email protected]d6ec84a2013-11-01 13:07:3816#include "extensions/common/extension_api.h"
[email protected]fb820c02014-03-13 15:07:0817#include "extensions/common/extension_messages.h"
[email protected]c5dbef02011-05-13 05:06:0918
[email protected]631bb742011-11-02 11:29:3919using content::BrowserThread;
[email protected]eaabba22012-03-07 15:02:1120using content::RenderViewHost;
[email protected]bc0ee242013-10-22 03:46:1421using content::WebContents;
[email protected]b5b26b72013-08-02 00:25:1122using extensions::ExtensionAPI;
23using extensions::Feature;
[email protected]631bb742011-11-02 11:29:3924
[email protected]f4e972d2014-04-24 22:55:5825namespace {
26
27class 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 DCHECK_EQ("", function->GetError());
38 }
39
40 virtual ~MultipleArgumentsResponseValue() {}
41
42 virtual bool Apply() OVERRIDE { return true; }
43};
44
45class ErrorResponseValue : public ExtensionFunction::ResponseValueObject {
46 public:
47 ErrorResponseValue(ExtensionFunction* function, const std::string& error) {
48 DCHECK_NE("", error);
49 function->SetError(error);
50 }
51
52 virtual ~ErrorResponseValue() {}
53
54 virtual bool Apply() OVERRIDE { return false; }
55};
56
57class BadMessageResponseValue : public ExtensionFunction::ResponseValueObject {
58 public:
59 explicit BadMessageResponseValue(ExtensionFunction* function) {
60 function->set_bad_message(true);
61 NOTREACHED() << function->name() << ": bad message";
62 }
63
64 virtual ~BadMessageResponseValue() {}
65
66 virtual bool Apply() OVERRIDE { return false; }
67};
68
69class RespondNowAction : public ExtensionFunction::ResponseActionObject {
70 public:
71 typedef base::Callback<void(bool)> SendResponseCallback;
72 RespondNowAction(ExtensionFunction::ResponseValue result,
73 const SendResponseCallback& send_response)
74 : result_(result.Pass()), send_response_(send_response) {}
75 virtual ~RespondNowAction() {}
76
77 virtual void Execute() OVERRIDE { send_response_.Run(result_->Apply()); }
78
79 private:
80 ExtensionFunction::ResponseValue result_;
81 SendResponseCallback send_response_;
82};
83
84class RespondLaterAction : public ExtensionFunction::ResponseActionObject {
85 public:
86 virtual ~RespondLaterAction() {}
87
88 virtual void Execute() OVERRIDE {}
89};
90
91} // namespace
92
[email protected]a2aef2e2011-05-26 22:48:1293// static
94void ExtensionFunctionDeleteTraits::Destruct(const ExtensionFunction* x) {
95 x->Destruct();
96}
97
[email protected]6dd625e2013-12-20 17:03:0798// Helper class to track the lifetime of ExtensionFunction's RenderViewHost or
99// RenderFrameHost pointer and NULL it out when it dies. It also allows us to
100// filter IPC messages coming from the RenderViewHost/RenderFrameHost.
101class UIThreadExtensionFunction::RenderHostTracker
[email protected]bc0ee242013-10-22 03:46:14102 : public content::WebContentsObserver {
103 public:
[email protected]6dd625e2013-12-20 17:03:07104 explicit RenderHostTracker(UIThreadExtensionFunction* function)
[email protected]bc0ee242013-10-22 03:46:14105 : content::WebContentsObserver(
[email protected]eb7ef5f2014-02-06 09:59:19106 function->render_view_host() ?
[email protected]6dd625e2013-12-20 17:03:07107 WebContents::FromRenderViewHost(function->render_view_host()) :
108 WebContents::FromRenderFrameHost(
109 function->render_frame_host())),
[email protected]bc0ee242013-10-22 03:46:14110 function_(function) {
111 }
[email protected]942690b132010-05-11 06:42:14112
[email protected]bc0ee242013-10-22 03:46:14113 private:
114 // content::WebContentsObserver:
115 virtual void RenderViewDeleted(
116 content::RenderViewHost* render_view_host) OVERRIDE {
117 if (render_view_host != function_->render_view_host())
118 return;
[email protected]ce0e2602013-03-15 20:53:27119
[email protected]bc0ee242013-10-22 03:46:14120 function_->SetRenderViewHost(NULL);
121 }
[email protected]6dd625e2013-12-20 17:03:07122 virtual void RenderFrameDeleted(
123 content::RenderFrameHost* render_frame_host) OVERRIDE {
124 if (render_frame_host != function_->render_frame_host())
125 return;
126
127 function_->SetRenderFrameHost(NULL);
128 }
[email protected]0f7daaa2011-11-22 18:34:56129
[email protected]bc0ee242013-10-22 03:46:14130 virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE {
[email protected]6dd625e2013-12-20 17:03:07131 return function_->OnMessageReceived(message);
[email protected]bc0ee242013-10-22 03:46:14132 }
133
134 UIThreadExtensionFunction* function_;
135
[email protected]6dd625e2013-12-20 17:03:07136 DISALLOW_COPY_AND_ASSIGN(RenderHostTracker);
[email protected]bc0ee242013-10-22 03:46:14137};
[email protected]0f7daaa2011-11-22 18:34:56138
[email protected]3a3d47472010-07-15 21:03:54139ExtensionFunction::ExtensionFunction()
[email protected]9931fbfc2010-07-23 09:15:51140 : request_id_(-1),
[email protected]637bf322011-10-01 20:46:32141 profile_id_(NULL),
[email protected]9931fbfc2010-07-23 09:15:51142 has_callback_(false),
[email protected]6451e332010-10-05 00:14:53143 include_incognito_(false),
[email protected]a2aef2e2011-05-26 22:48:12144 user_gesture_(false),
[email protected]07ad9622013-01-18 23:00:33145 bad_message_(false),
[email protected]eb7ef5f2014-02-06 09:59:19146 histogram_value_(extensions::functions::UNKNOWN),
147 source_tab_id_(-1) {
148}
[email protected]3a3d47472010-07-15 21:03:54149
150ExtensionFunction::~ExtensionFunction() {
151}
152
[email protected]2ad65b32011-05-26 23:39:20153UIThreadExtensionFunction* ExtensionFunction::AsUIThreadExtensionFunction() {
154 return NULL;
155}
156
[email protected]c357acb42011-06-09 20:52:42157IOThreadExtensionFunction* ExtensionFunction::AsIOThreadExtensionFunction() {
158 return NULL;
159}
160
[email protected]3d0e2262012-08-02 15:32:16161bool ExtensionFunction::HasPermission() {
[email protected]b5b26b72013-08-02 00:25:11162 Feature::Availability availability =
163 ExtensionAPI::GetSharedInstance()->IsAvailable(
164 name_, extension_, Feature::BLESSED_EXTENSION_CONTEXT, source_url());
165 return availability.is_available();
[email protected]3d0e2262012-08-02 15:32:16166}
167
[email protected]85231d72012-08-31 09:45:29168void ExtensionFunction::OnQuotaExceeded(const std::string& violation_error) {
169 error_ = violation_error;
[email protected]fd50e7b2011-11-03 09:20:25170 SendResponse(false);
171}
172
[email protected]602542d2012-04-20 02:48:01173void ExtensionFunction::SetArgs(const base::ListValue* args) {
[email protected]30294edf2009-11-10 00:24:38174 DCHECK(!args_.get()); // Should only be called once.
[email protected]16f47e082011-01-18 02:16:59175 args_.reset(args->DeepCopy());
[email protected]b83e4602009-05-15 22:58:33176}
177
[email protected]07ff5fd2012-07-12 22:39:09178void ExtensionFunction::SetResult(base::Value* result) {
179 results_.reset(new base::ListValue());
180 results_->Append(result);
181}
182
[email protected]f4e972d2014-04-24 22:55:58183void ExtensionFunction::SetResultList(scoped_ptr<base::ListValue> results) {
184 results_ = results.Pass();
185}
186
187const base::ListValue* ExtensionFunction::GetResultList() const {
[email protected]07ff5fd2012-07-12 22:39:09188 return results_.get();
[email protected]637bf322011-10-01 20:46:32189}
190
[email protected]f4e972d2014-04-24 22:55:58191std::string ExtensionFunction::GetError() const {
[email protected]3a3d47472010-07-15 21:03:54192 return error_;
193}
194
[email protected]60aad9c2012-01-13 19:55:32195void ExtensionFunction::SetError(const std::string& error) {
196 error_ = error;
197}
198
[email protected]f4e972d2014-04-24 22:55:58199ExtensionFunction::ResponseValue ExtensionFunction::NoArguments() {
200 return MultipleArguments(new base::ListValue());
201}
202
203ExtensionFunction::ResponseValue ExtensionFunction::SingleArgument(
204 base::Value* arg) {
205 base::ListValue* args = new base::ListValue();
206 args->Append(arg);
207 return MultipleArguments(args);
208}
209
210ExtensionFunction::ResponseValue ExtensionFunction::MultipleArguments(
211 base::ListValue* args) {
212 return scoped_ptr<ResponseValueObject>(
213 new MultipleArgumentsResponseValue(this, args));
214}
215
216ExtensionFunction::ResponseValue ExtensionFunction::Error(
217 const std::string& error) {
218 return scoped_ptr<ResponseValueObject>(new ErrorResponseValue(this, error));
219}
220
221ExtensionFunction::ResponseValue ExtensionFunction::BadMessage() {
222 return scoped_ptr<ResponseValueObject>(new BadMessageResponseValue(this));
223}
224
225ExtensionFunction::ResponseAction ExtensionFunction::RespondNow(
226 ResponseValue result) {
227 return scoped_ptr<ResponseActionObject>(new RespondNowAction(
228 result.Pass(), base::Bind(&ExtensionFunction::SendResponse, this)));
229}
230
231ExtensionFunction::ResponseAction ExtensionFunction::RespondLater() {
232 return scoped_ptr<ResponseActionObject>(new RespondLaterAction());
233}
234
[email protected]a2aef2e2011-05-26 22:48:12235void ExtensionFunction::Run() {
[email protected]3a3d47472010-07-15 21:03:54236 if (!RunImpl())
237 SendResponse(false);
238}
239
[email protected]f4e972d2014-04-24 22:55:58240bool ExtensionFunction::RunImpl() {
241 RunImplTypesafe()->Execute();
242 return true;
243}
244
245ExtensionFunction::ResponseAction ExtensionFunction::RunImplTypesafe() {
246 NOTREACHED()
247 << "ExtensionFunctions must override either RunImpl or RunImplTypesafe";
248 return RespondNow(NoArguments());
249}
250
251void ExtensionFunction::SendResponseTypesafe(ResponseValue response) {
252 SendResponse(response->Apply());
253}
254
[email protected]712627bf2012-04-30 03:21:04255bool ExtensionFunction::ShouldSkipQuotaLimiting() const {
256 return false;
257}
258
[email protected]a2aef2e2011-05-26 22:48:12259bool ExtensionFunction::HasOptionalArgument(size_t index) {
[email protected]4b3006f2013-12-23 22:23:08260 base::Value* value;
261 return args_->Get(index, &value) && !value->IsType(base::Value::TYPE_NULL);
[email protected]a2aef2e2011-05-26 22:48:12262}
263
[email protected]35548ab2013-05-15 08:59:47264void ExtensionFunction::SendResponseImpl(bool success) {
265 DCHECK(!response_callback_.is_null());
266
267 ResponseType type = success ? SUCCEEDED : FAILED;
[email protected]c357acb42011-06-09 20:52:42268 if (bad_message_) {
[email protected]35548ab2013-05-15 08:59:47269 type = BAD_MESSAGE;
270 LOG(ERROR) << "Bad extension message " << name_;
[email protected]c357acb42011-06-09 20:52:42271 }
272
[email protected]07ff5fd2012-07-12 22:39:09273 // If results were never set, we send an empty argument list.
[email protected]3eeddd892013-04-17 17:00:11274 if (!results_)
[email protected]aeca23f2013-06-21 22:34:41275 results_.reset(new base::ListValue());
[email protected]602542d2012-04-20 02:48:01276
[email protected]35548ab2013-05-15 08:59:47277 response_callback_.Run(type, *results_, GetError());
[email protected]c357acb42011-06-09 20:52:42278}
279
[email protected]a2aef2e2011-05-26 22:48:12280UIThreadExtensionFunction::UIThreadExtensionFunction()
[email protected]eb7ef5f2014-02-06 09:59:19281 : render_view_host_(NULL),
282 render_frame_host_(NULL),
283 context_(NULL),
284 delegate_(NULL) {
285}
[email protected]a2aef2e2011-05-26 22:48:12286
287UIThreadExtensionFunction::~UIThreadExtensionFunction() {
[email protected]7042b682012-04-19 22:57:51288 if (dispatcher() && render_view_host())
[email protected]720ad1312012-02-27 23:07:36289 dispatcher()->OnExtensionFunctionCompleted(GetExtension());
[email protected]a2aef2e2011-05-26 22:48:12290}
291
[email protected]2ad65b32011-05-26 23:39:20292UIThreadExtensionFunction*
293UIThreadExtensionFunction::AsUIThreadExtensionFunction() {
294 return this;
295}
296
[email protected]6dd625e2013-12-20 17:03:07297bool UIThreadExtensionFunction::OnMessageReceived(const IPC::Message& message) {
[email protected]0f7daaa2011-11-22 18:34:56298 return false;
299}
300
[email protected]a2aef2e2011-05-26 22:48:12301void UIThreadExtensionFunction::Destruct() const {
302 BrowserThread::DeleteOnUIThread::Destruct(this);
303}
304
305void UIThreadExtensionFunction::SetRenderViewHost(
306 RenderViewHost* render_view_host) {
[email protected]6dd625e2013-12-20 17:03:07307 DCHECK(!render_frame_host_);
[email protected]a2aef2e2011-05-26 22:48:12308 render_view_host_ = render_view_host;
[email protected]6dd625e2013-12-20 17:03:07309 tracker_.reset(render_view_host ? new RenderHostTracker(this) : NULL);
310}
311
312void UIThreadExtensionFunction::SetRenderFrameHost(
313 content::RenderFrameHost* render_frame_host) {
314 DCHECK(!render_view_host_);
315 render_frame_host_ = render_frame_host;
316 tracker_.reset(render_frame_host ? new RenderHostTracker(this) : NULL);
[email protected]a2aef2e2011-05-26 22:48:12317}
318
[email protected]91e51d612012-10-21 23:03:05319content::WebContents* UIThreadExtensionFunction::GetAssociatedWebContents() {
[email protected]21a40082013-10-28 21:19:23320 content::WebContents* web_contents = NULL;
321 if (dispatcher())
322 web_contents = dispatcher()->delegate()->GetAssociatedWebContents();
[email protected]91e51d612012-10-21 23:03:05323
[email protected]21a40082013-10-28 21:19:23324 return web_contents;
[email protected]a2aef2e2011-05-26 22:48:12325}
326
327void UIThreadExtensionFunction::SendResponse(bool success) {
[email protected]35548ab2013-05-15 08:59:47328 if (delegate_)
[email protected]ca6df682012-04-10 23:00:20329 delegate_->OnSendResponse(this, success, bad_message_);
[email protected]35548ab2013-05-15 08:59:47330 else
331 SendResponseImpl(success);
[email protected]c5dbef02011-05-13 05:06:09332}
333
[email protected]c6970072013-01-10 02:59:43334void UIThreadExtensionFunction::WriteToConsole(
335 content::ConsoleMessageLevel level,
336 const std::string& message) {
[email protected]6dd625e2013-12-20 17:03:07337 if (render_view_host_) {
338 render_view_host_->Send(new ExtensionMsg_AddMessageToConsole(
339 render_view_host_->GetRoutingID(), level, message));
340 } else {
341 render_frame_host_->Send(new ExtensionMsg_AddMessageToConsole(
342 render_frame_host_->GetRoutingID(), level, message));
343 }
[email protected]c6970072013-01-10 02:59:43344}
345
[email protected]44295a12013-06-05 08:45:46346IOThreadExtensionFunction::IOThreadExtensionFunction()
347 : routing_id_(MSG_ROUTING_NONE) {
[email protected]c357acb42011-06-09 20:52:42348}
349
350IOThreadExtensionFunction::~IOThreadExtensionFunction() {
351}
352
353IOThreadExtensionFunction*
354IOThreadExtensionFunction::AsIOThreadExtensionFunction() {
355 return this;
356}
357
358void IOThreadExtensionFunction::Destruct() const {
359 BrowserThread::DeleteOnIOThread::Destruct(this);
360}
361
362void IOThreadExtensionFunction::SendResponse(bool success) {
[email protected]35548ab2013-05-15 08:59:47363 SendResponseImpl(success);
[email protected]703e807a2009-03-28 19:56:51364}
[email protected]73404a372009-04-17 23:09:10365
[email protected]bdfc03e2011-11-22 00:20:33366AsyncExtensionFunction::AsyncExtensionFunction() {
[email protected]a2aef2e2011-05-26 22:48:12367}
368
369AsyncExtensionFunction::~AsyncExtensionFunction() {
[email protected]35213ce92010-04-08 19:06:15370}
[email protected]3a3d47472010-07-15 21:03:54371
372SyncExtensionFunction::SyncExtensionFunction() {
373}
374
375SyncExtensionFunction::~SyncExtensionFunction() {
376}
377
378void SyncExtensionFunction::Run() {
379 SendResponse(RunImpl());
380}
[email protected]c357acb42011-06-09 20:52:42381
382SyncIOThreadExtensionFunction::SyncIOThreadExtensionFunction() {
383}
384
385SyncIOThreadExtensionFunction::~SyncIOThreadExtensionFunction() {
386}
387
388void SyncIOThreadExtensionFunction::Run() {
389 SendResponse(RunImpl());
390}