blob: f2cc79dfe8d1101b9c32f0c48cf8d907d6f9482f [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 }
[email protected]a0c91a9f2014-05-03 03:41:4337 // 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.
[email protected]f4e972d2014-04-24 22:55:5840 }
41
42 virtual ~MultipleArgumentsResponseValue() {}
43
44 virtual bool Apply() OVERRIDE { return true; }
45};
46
47class ErrorResponseValue : public ExtensionFunction::ResponseValueObject {
48 public:
49 ErrorResponseValue(ExtensionFunction* function, const std::string& error) {
[email protected]a0c91a9f2014-05-03 03:41:4350 // It would be nice to DCHECK(!error.empty()) but too many legacy extension
51 // function implementations don't set error but signal failure.
[email protected]f4e972d2014-04-24 22:55:5852 function->SetError(error);
53 }
54
55 virtual ~ErrorResponseValue() {}
56
57 virtual bool Apply() OVERRIDE { return false; }
58};
59
60class 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
72class 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
87class RespondLaterAction : public ExtensionFunction::ResponseActionObject {
88 public:
89 virtual ~RespondLaterAction() {}
90
91 virtual void Execute() OVERRIDE {}
92};
93
94} // namespace
95
[email protected]a2aef2e2011-05-26 22:48:1296// static
97void ExtensionFunctionDeleteTraits::Destruct(const ExtensionFunction* x) {
98 x->Destruct();
99}
100
[email protected]6dd625e2013-12-20 17:03:07101// 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.
104class UIThreadExtensionFunction::RenderHostTracker
[email protected]bc0ee242013-10-22 03:46:14105 : public content::WebContentsObserver {
106 public:
[email protected]6dd625e2013-12-20 17:03:07107 explicit RenderHostTracker(UIThreadExtensionFunction* function)
[email protected]bc0ee242013-10-22 03:46:14108 : content::WebContentsObserver(
[email protected]eb7ef5f2014-02-06 09:59:19109 function->render_view_host() ?
[email protected]6dd625e2013-12-20 17:03:07110 WebContents::FromRenderViewHost(function->render_view_host()) :
111 WebContents::FromRenderFrameHost(
112 function->render_frame_host())),
[email protected]bc0ee242013-10-22 03:46:14113 function_(function) {
114 }
[email protected]942690b132010-05-11 06:42:14115
[email protected]bc0ee242013-10-22 03:46:14116 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;
[email protected]ce0e2602013-03-15 20:53:27122
[email protected]bc0ee242013-10-22 03:46:14123 function_->SetRenderViewHost(NULL);
124 }
[email protected]6dd625e2013-12-20 17:03:07125 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 }
[email protected]0f7daaa2011-11-22 18:34:56132
[email protected]64ffefa2014-05-10 12:06:33133 virtual bool OnMessageReceived(
134 const IPC::Message& message,
135 content::RenderFrameHost* render_frame_host) OVERRIDE {
136 DCHECK(render_frame_host);
137 if (render_frame_host == function_->render_frame_host())
138 return function_->OnMessageReceived(message);
139 else
140 return false;
141 }
142
[email protected]bc0ee242013-10-22 03:46:14143 virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE {
[email protected]6dd625e2013-12-20 17:03:07144 return function_->OnMessageReceived(message);
[email protected]bc0ee242013-10-22 03:46:14145 }
146
147 UIThreadExtensionFunction* function_;
148
[email protected]6dd625e2013-12-20 17:03:07149 DISALLOW_COPY_AND_ASSIGN(RenderHostTracker);
[email protected]bc0ee242013-10-22 03:46:14150};
[email protected]0f7daaa2011-11-22 18:34:56151
[email protected]3a3d47472010-07-15 21:03:54152ExtensionFunction::ExtensionFunction()
[email protected]9931fbfc2010-07-23 09:15:51153 : request_id_(-1),
[email protected]637bf322011-10-01 20:46:32154 profile_id_(NULL),
[email protected]9931fbfc2010-07-23 09:15:51155 has_callback_(false),
[email protected]6451e332010-10-05 00:14:53156 include_incognito_(false),
[email protected]a2aef2e2011-05-26 22:48:12157 user_gesture_(false),
[email protected]07ad9622013-01-18 23:00:33158 bad_message_(false),
[email protected]eb7ef5f2014-02-06 09:59:19159 histogram_value_(extensions::functions::UNKNOWN),
160 source_tab_id_(-1) {
161}
[email protected]3a3d47472010-07-15 21:03:54162
163ExtensionFunction::~ExtensionFunction() {
164}
165
[email protected]2ad65b32011-05-26 23:39:20166UIThreadExtensionFunction* ExtensionFunction::AsUIThreadExtensionFunction() {
167 return NULL;
168}
169
[email protected]c357acb42011-06-09 20:52:42170IOThreadExtensionFunction* ExtensionFunction::AsIOThreadExtensionFunction() {
171 return NULL;
172}
173
[email protected]3d0e2262012-08-02 15:32:16174bool ExtensionFunction::HasPermission() {
[email protected]b5b26b72013-08-02 00:25:11175 Feature::Availability availability =
176 ExtensionAPI::GetSharedInstance()->IsAvailable(
177 name_, extension_, Feature::BLESSED_EXTENSION_CONTEXT, source_url());
178 return availability.is_available();
[email protected]3d0e2262012-08-02 15:32:16179}
180
[email protected]85231d72012-08-31 09:45:29181void ExtensionFunction::OnQuotaExceeded(const std::string& violation_error) {
182 error_ = violation_error;
[email protected]fd50e7b2011-11-03 09:20:25183 SendResponse(false);
184}
185
[email protected]602542d2012-04-20 02:48:01186void ExtensionFunction::SetArgs(const base::ListValue* args) {
[email protected]30294edf2009-11-10 00:24:38187 DCHECK(!args_.get()); // Should only be called once.
[email protected]16f47e082011-01-18 02:16:59188 args_.reset(args->DeepCopy());
[email protected]b83e4602009-05-15 22:58:33189}
190
[email protected]07ff5fd2012-07-12 22:39:09191void ExtensionFunction::SetResult(base::Value* result) {
192 results_.reset(new base::ListValue());
193 results_->Append(result);
194}
195
[email protected]f4e972d2014-04-24 22:55:58196void ExtensionFunction::SetResultList(scoped_ptr<base::ListValue> results) {
197 results_ = results.Pass();
198}
199
200const base::ListValue* ExtensionFunction::GetResultList() const {
[email protected]07ff5fd2012-07-12 22:39:09201 return results_.get();
[email protected]637bf322011-10-01 20:46:32202}
203
[email protected]f4e972d2014-04-24 22:55:58204std::string ExtensionFunction::GetError() const {
[email protected]3a3d47472010-07-15 21:03:54205 return error_;
206}
207
[email protected]60aad9c2012-01-13 19:55:32208void ExtensionFunction::SetError(const std::string& error) {
209 error_ = error;
210}
211
[email protected]f4e972d2014-04-24 22:55:58212ExtensionFunction::ResponseValue ExtensionFunction::NoArguments() {
213 return MultipleArguments(new base::ListValue());
214}
215
216ExtensionFunction::ResponseValue ExtensionFunction::SingleArgument(
217 base::Value* arg) {
218 base::ListValue* args = new base::ListValue();
219 args->Append(arg);
220 return MultipleArguments(args);
221}
222
223ExtensionFunction::ResponseValue ExtensionFunction::MultipleArguments(
224 base::ListValue* args) {
225 return scoped_ptr<ResponseValueObject>(
226 new MultipleArgumentsResponseValue(this, args));
227}
228
229ExtensionFunction::ResponseValue ExtensionFunction::Error(
230 const std::string& error) {
231 return scoped_ptr<ResponseValueObject>(new ErrorResponseValue(this, error));
232}
233
234ExtensionFunction::ResponseValue ExtensionFunction::BadMessage() {
235 return scoped_ptr<ResponseValueObject>(new BadMessageResponseValue(this));
236}
237
238ExtensionFunction::ResponseAction ExtensionFunction::RespondNow(
239 ResponseValue result) {
[email protected]5b50d882014-05-09 11:37:30240 return ResponseAction(new RespondNowAction(
[email protected]f4e972d2014-04-24 22:55:58241 result.Pass(), base::Bind(&ExtensionFunction::SendResponse, this)));
242}
243
244ExtensionFunction::ResponseAction ExtensionFunction::RespondLater() {
[email protected]5b50d882014-05-09 11:37:30245 return ResponseAction(new RespondLaterAction());
246}
247
248// static
249ExtensionFunction::ResponseAction ExtensionFunction::ValidationFailure(
250 ExtensionFunction* function) {
251 return function->RespondNow(function->BadMessage());
[email protected]f4e972d2014-04-24 22:55:58252}
253
[email protected]a0c91a9f2014-05-03 03:41:43254void ExtensionFunction::Respond(ResponseValue result) {
255 SendResponse(result->Apply());
[email protected]f4e972d2014-04-24 22:55:58256}
257
[email protected]712627bf2012-04-30 03:21:04258bool ExtensionFunction::ShouldSkipQuotaLimiting() const {
259 return false;
260}
261
[email protected]a2aef2e2011-05-26 22:48:12262bool ExtensionFunction::HasOptionalArgument(size_t index) {
[email protected]4b3006f2013-12-23 22:23:08263 base::Value* value;
264 return args_->Get(index, &value) && !value->IsType(base::Value::TYPE_NULL);
[email protected]a2aef2e2011-05-26 22:48:12265}
266
[email protected]35548ab2013-05-15 08:59:47267void ExtensionFunction::SendResponseImpl(bool success) {
268 DCHECK(!response_callback_.is_null());
269
270 ResponseType type = success ? SUCCEEDED : FAILED;
[email protected]c357acb42011-06-09 20:52:42271 if (bad_message_) {
[email protected]35548ab2013-05-15 08:59:47272 type = BAD_MESSAGE;
273 LOG(ERROR) << "Bad extension message " << name_;
[email protected]c357acb42011-06-09 20:52:42274 }
275
[email protected]07ff5fd2012-07-12 22:39:09276 // If results were never set, we send an empty argument list.
[email protected]3eeddd892013-04-17 17:00:11277 if (!results_)
[email protected]aeca23f2013-06-21 22:34:41278 results_.reset(new base::ListValue());
[email protected]602542d2012-04-20 02:48:01279
[email protected]35548ab2013-05-15 08:59:47280 response_callback_.Run(type, *results_, GetError());
[email protected]c357acb42011-06-09 20:52:42281}
282
[email protected]a0c91a9f2014-05-03 03:41:43283void ExtensionFunction::OnRespondingLater(ResponseValue value) {
284 SendResponse(value->Apply());
285}
286
[email protected]a2aef2e2011-05-26 22:48:12287UIThreadExtensionFunction::UIThreadExtensionFunction()
[email protected]eb7ef5f2014-02-06 09:59:19288 : render_view_host_(NULL),
289 render_frame_host_(NULL),
290 context_(NULL),
291 delegate_(NULL) {
292}
[email protected]a2aef2e2011-05-26 22:48:12293
294UIThreadExtensionFunction::~UIThreadExtensionFunction() {
[email protected]7042b682012-04-19 22:57:51295 if (dispatcher() && render_view_host())
[email protected]720ad1312012-02-27 23:07:36296 dispatcher()->OnExtensionFunctionCompleted(GetExtension());
[email protected]a2aef2e2011-05-26 22:48:12297}
298
[email protected]2ad65b32011-05-26 23:39:20299UIThreadExtensionFunction*
300UIThreadExtensionFunction::AsUIThreadExtensionFunction() {
301 return this;
302}
303
[email protected]6dd625e2013-12-20 17:03:07304bool UIThreadExtensionFunction::OnMessageReceived(const IPC::Message& message) {
[email protected]0f7daaa2011-11-22 18:34:56305 return false;
306}
307
[email protected]a2aef2e2011-05-26 22:48:12308void UIThreadExtensionFunction::Destruct() const {
309 BrowserThread::DeleteOnUIThread::Destruct(this);
310}
311
312void UIThreadExtensionFunction::SetRenderViewHost(
313 RenderViewHost* render_view_host) {
[email protected]6dd625e2013-12-20 17:03:07314 DCHECK(!render_frame_host_);
[email protected]a2aef2e2011-05-26 22:48:12315 render_view_host_ = render_view_host;
[email protected]6dd625e2013-12-20 17:03:07316 tracker_.reset(render_view_host ? new RenderHostTracker(this) : NULL);
317}
318
319void UIThreadExtensionFunction::SetRenderFrameHost(
320 content::RenderFrameHost* render_frame_host) {
321 DCHECK(!render_view_host_);
322 render_frame_host_ = render_frame_host;
323 tracker_.reset(render_frame_host ? new RenderHostTracker(this) : NULL);
[email protected]a2aef2e2011-05-26 22:48:12324}
325
[email protected]91e51d612012-10-21 23:03:05326content::WebContents* UIThreadExtensionFunction::GetAssociatedWebContents() {
[email protected]21a40082013-10-28 21:19:23327 content::WebContents* web_contents = NULL;
328 if (dispatcher())
329 web_contents = dispatcher()->delegate()->GetAssociatedWebContents();
[email protected]91e51d612012-10-21 23:03:05330
[email protected]21a40082013-10-28 21:19:23331 return web_contents;
[email protected]a2aef2e2011-05-26 22:48:12332}
333
334void UIThreadExtensionFunction::SendResponse(bool success) {
[email protected]35548ab2013-05-15 08:59:47335 if (delegate_)
[email protected]ca6df682012-04-10 23:00:20336 delegate_->OnSendResponse(this, success, bad_message_);
[email protected]35548ab2013-05-15 08:59:47337 else
338 SendResponseImpl(success);
[email protected]c5dbef02011-05-13 05:06:09339}
340
[email protected]c6970072013-01-10 02:59:43341void UIThreadExtensionFunction::WriteToConsole(
342 content::ConsoleMessageLevel level,
343 const std::string& message) {
[email protected]6dd625e2013-12-20 17:03:07344 if (render_view_host_) {
345 render_view_host_->Send(new ExtensionMsg_AddMessageToConsole(
346 render_view_host_->GetRoutingID(), level, message));
347 } else {
348 render_frame_host_->Send(new ExtensionMsg_AddMessageToConsole(
349 render_frame_host_->GetRoutingID(), level, message));
350 }
[email protected]c6970072013-01-10 02:59:43351}
352
[email protected]44295a12013-06-05 08:45:46353IOThreadExtensionFunction::IOThreadExtensionFunction()
354 : routing_id_(MSG_ROUTING_NONE) {
[email protected]c357acb42011-06-09 20:52:42355}
356
357IOThreadExtensionFunction::~IOThreadExtensionFunction() {
358}
359
360IOThreadExtensionFunction*
361IOThreadExtensionFunction::AsIOThreadExtensionFunction() {
362 return this;
363}
364
365void IOThreadExtensionFunction::Destruct() const {
366 BrowserThread::DeleteOnIOThread::Destruct(this);
367}
368
369void IOThreadExtensionFunction::SendResponse(bool success) {
[email protected]35548ab2013-05-15 08:59:47370 SendResponseImpl(success);
[email protected]703e807a2009-03-28 19:56:51371}
[email protected]73404a372009-04-17 23:09:10372
[email protected]bdfc03e2011-11-22 00:20:33373AsyncExtensionFunction::AsyncExtensionFunction() {
[email protected]a2aef2e2011-05-26 22:48:12374}
375
376AsyncExtensionFunction::~AsyncExtensionFunction() {
[email protected]35213ce92010-04-08 19:06:15377}
[email protected]3a3d47472010-07-15 21:03:54378
[email protected]a0c91a9f2014-05-03 03:41:43379ExtensionFunction::ResponseAction AsyncExtensionFunction::Run() {
380 return RunAsync() ? RespondLater() : RespondNow(Error(error_));
381}
382
[email protected]5b50d882014-05-09 11:37:30383// static
384bool AsyncExtensionFunction::ValidationFailure(
385 AsyncExtensionFunction* function) {
386 return false;
387}
388
[email protected]3a3d47472010-07-15 21:03:54389SyncExtensionFunction::SyncExtensionFunction() {
390}
391
392SyncExtensionFunction::~SyncExtensionFunction() {
393}
394
[email protected]a0c91a9f2014-05-03 03:41:43395ExtensionFunction::ResponseAction SyncExtensionFunction::Run() {
396 return RespondNow(RunSync() ? MultipleArguments(results_.get())
397 : Error(error_));
[email protected]3a3d47472010-07-15 21:03:54398}
[email protected]c357acb42011-06-09 20:52:42399
[email protected]5b50d882014-05-09 11:37:30400// static
401bool SyncExtensionFunction::ValidationFailure(SyncExtensionFunction* function) {
402 return false;
403}
404
[email protected]c357acb42011-06-09 20:52:42405SyncIOThreadExtensionFunction::SyncIOThreadExtensionFunction() {
406}
407
408SyncIOThreadExtensionFunction::~SyncIOThreadExtensionFunction() {
409}
410
[email protected]a0c91a9f2014-05-03 03:41:43411ExtensionFunction::ResponseAction SyncIOThreadExtensionFunction::Run() {
412 return RespondNow(RunSync() ? MultipleArguments(results_.get())
413 : Error(error_));
[email protected]c357acb42011-06-09 20:52:42414}
[email protected]5b50d882014-05-09 11:37:30415
416// static
417bool SyncIOThreadExtensionFunction::ValidationFailure(
418 SyncIOThreadExtensionFunction* function) {
419 return false;
420}