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/extension_api.h"
17 #include "extensions/common/extension_messages.h"
19 using content::BrowserThread;
20 using content::RenderViewHost;
21 using content::WebContents;
22 using extensions::ExtensionAPI;
23 using extensions::Feature;
27 class MultipleArgumentsResponseValue
28 : public ExtensionFunction::ResponseValueObject {
30 MultipleArgumentsResponseValue(ExtensionFunction* function,
31 base::ListValue* result) {
32 if (function->GetResultList()) {
33 DCHECK_EQ(function->GetResultList(), result);
35 function->SetResultList(make_scoped_ptr(result));
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
42 virtual ~MultipleArgumentsResponseValue() {}
44 virtual bool Apply() OVERRIDE { return true; }
47 class ErrorResponseValue : public ExtensionFunction::ResponseValueObject {
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);
55 virtual ~ErrorResponseValue() {}
57 virtual bool Apply() OVERRIDE { return false; }
60 class BadMessageResponseValue : public ExtensionFunction::ResponseValueObject {
62 explicit BadMessageResponseValue(ExtensionFunction* function) {
63 function->set_bad_message(true);
64 NOTREACHED() << function->name() << ": bad message";
67 virtual ~BadMessageResponseValue() {}
69 virtual bool Apply() OVERRIDE { return false; }
72 class RespondNowAction : public ExtensionFunction::ResponseActionObject {
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() {}
80 virtual void Execute() OVERRIDE { send_response_.Run(result_->Apply()); }
83 ExtensionFunction::ResponseValue result_;
84 SendResponseCallback send_response_;
87 class RespondLaterAction : public ExtensionFunction::ResponseActionObject {
89 virtual ~RespondLaterAction() {}
91 virtual void Execute() OVERRIDE {}
97 void ExtensionFunctionDeleteTraits::Destruct(const ExtensionFunction* x) {
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 {
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) {
117 // content::WebContentsObserver:
118 virtual void RenderViewDeleted(
119 content::RenderViewHost* render_view_host) OVERRIDE {
120 if (render_view_host != function_->render_view_host())
123 function_->SetRenderViewHost(NULL);
125 virtual void RenderFrameDeleted(
126 content::RenderFrameHost* render_frame_host) OVERRIDE {
127 if (render_frame_host != function_->render_frame_host())
130 function_->SetRenderFrameHost(NULL);
133 virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE {
134 return function_->OnMessageReceived(message);
137 UIThreadExtensionFunction* function_;
139 DISALLOW_COPY_AND_ASSIGN(RenderHostTracker);
142 ExtensionFunction::ExtensionFunction()
145 has_callback_(false),
146 include_incognito_(false),
147 user_gesture_(false),
149 histogram_value_(extensions::functions::UNKNOWN),
153 ExtensionFunction::~ExtensionFunction() {
156 UIThreadExtensionFunction* ExtensionFunction::AsUIThreadExtensionFunction() {
160 IOThreadExtensionFunction* ExtensionFunction::AsIOThreadExtensionFunction() {
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();
171 void ExtensionFunction::OnQuotaExceeded(const std::string& violation_error) {
172 error_ = violation_error;
176 void ExtensionFunction::SetArgs(const base::ListValue* args) {
177 DCHECK(!args_.get()); // Should only be called once.
178 args_.reset(args->DeepCopy());
181 void ExtensionFunction::SetResult(base::Value* result) {
182 results_.reset(new base::ListValue());
183 results_->Append(result);
186 void ExtensionFunction::SetResultList(scoped_ptr<base::ListValue> results) {
187 results_ = results.Pass();
190 const base::ListValue* ExtensionFunction::GetResultList() const {
191 return results_.get();
194 std::string ExtensionFunction::GetError() const {
198 void ExtensionFunction::SetError(const std::string& error) {
202 ExtensionFunction::ResponseValue ExtensionFunction::NoArguments() {
203 return MultipleArguments(new base::ListValue());
206 ExtensionFunction::ResponseValue ExtensionFunction::SingleArgument(
208 base::ListValue* args = new base::ListValue();
210 return MultipleArguments(args);
213 ExtensionFunction::ResponseValue ExtensionFunction::MultipleArguments(
214 base::ListValue* args) {
215 return scoped_ptr<ResponseValueObject>(
216 new MultipleArgumentsResponseValue(this, args));
219 ExtensionFunction::ResponseValue ExtensionFunction::Error(
220 const std::string& error) {
221 return scoped_ptr<ResponseValueObject>(new ErrorResponseValue(this, error));
224 ExtensionFunction::ResponseValue ExtensionFunction::BadMessage() {
225 return scoped_ptr<ResponseValueObject>(new BadMessageResponseValue(this));
228 ExtensionFunction::ResponseAction ExtensionFunction::RespondNow(
229 ResponseValue result) {
230 return ResponseAction(new RespondNowAction(
231 result.Pass(), base::Bind(&ExtensionFunction::SendResponse, this)));
234 ExtensionFunction::ResponseAction ExtensionFunction::RespondLater() {
235 return ResponseAction(new RespondLaterAction());
239 ExtensionFunction::ResponseAction ExtensionFunction::ValidationFailure(
240 ExtensionFunction* function) {
241 return function->RespondNow(function->BadMessage());
244 void ExtensionFunction::Respond(ResponseValue result) {
245 SendResponse(result->Apply());
248 bool ExtensionFunction::ShouldSkipQuotaLimiting() const {
252 bool ExtensionFunction::HasOptionalArgument(size_t index) {
254 return args_->Get(index, &value) && !value->IsType(base::Value::TYPE_NULL);
257 void ExtensionFunction::SendResponseImpl(bool success) {
258 DCHECK(!response_callback_.is_null());
260 ResponseType type = success ? SUCCEEDED : FAILED;
263 LOG(ERROR) << "Bad extension message " << name_;
266 // If results were never set, we send an empty argument list.
268 results_.reset(new base::ListValue());
270 response_callback_.Run(type, *results_, GetError());
273 void ExtensionFunction::OnRespondingLater(ResponseValue value) {
274 SendResponse(value->Apply());
277 UIThreadExtensionFunction::UIThreadExtensionFunction()
278 : render_view_host_(NULL),
279 render_frame_host_(NULL),
284 UIThreadExtensionFunction::~UIThreadExtensionFunction() {
285 if (dispatcher() && render_view_host())
286 dispatcher()->OnExtensionFunctionCompleted(GetExtension());
289 UIThreadExtensionFunction*
290 UIThreadExtensionFunction::AsUIThreadExtensionFunction() {
294 bool UIThreadExtensionFunction::OnMessageReceived(const IPC::Message& message) {
298 void UIThreadExtensionFunction::Destruct() const {
299 BrowserThread::DeleteOnUIThread::Destruct(this);
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);
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);
316 content::WebContents* UIThreadExtensionFunction::GetAssociatedWebContents() {
317 content::WebContents* web_contents = NULL;
319 web_contents = dispatcher()->delegate()->GetAssociatedWebContents();
324 void UIThreadExtensionFunction::SendResponse(bool success) {
326 delegate_->OnSendResponse(this, success, bad_message_);
328 SendResponseImpl(success);
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));
338 render_frame_host_->Send(new ExtensionMsg_AddMessageToConsole(
339 render_frame_host_->GetRoutingID(), level, message));
343 IOThreadExtensionFunction::IOThreadExtensionFunction()
344 : routing_id_(MSG_ROUTING_NONE) {
347 IOThreadExtensionFunction::~IOThreadExtensionFunction() {
350 IOThreadExtensionFunction*
351 IOThreadExtensionFunction::AsIOThreadExtensionFunction() {
355 void IOThreadExtensionFunction::Destruct() const {
356 BrowserThread::DeleteOnIOThread::Destruct(this);
359 void IOThreadExtensionFunction::SendResponse(bool success) {
360 SendResponseImpl(success);
363 AsyncExtensionFunction::AsyncExtensionFunction() {
366 AsyncExtensionFunction::~AsyncExtensionFunction() {
369 ExtensionFunction::ResponseAction AsyncExtensionFunction::Run() {
370 return RunAsync() ? RespondLater() : RespondNow(Error(error_));
374 bool AsyncExtensionFunction::ValidationFailure(
375 AsyncExtensionFunction* function) {
379 SyncExtensionFunction::SyncExtensionFunction() {
382 SyncExtensionFunction::~SyncExtensionFunction() {
385 ExtensionFunction::ResponseAction SyncExtensionFunction::Run() {
386 return RespondNow(RunSync() ? MultipleArguments(results_.get())
391 bool SyncExtensionFunction::ValidationFailure(SyncExtensionFunction* function) {
395 SyncIOThreadExtensionFunction::SyncIOThreadExtensionFunction() {
398 SyncIOThreadExtensionFunction::~SyncIOThreadExtensionFunction() {
401 ExtensionFunction::ResponseAction SyncIOThreadExtensionFunction::Run() {
402 return RespondNow(RunSync() ? MultipleArguments(results_.get())
407 bool SyncIOThreadExtensionFunction::ValidationFailure(
408 SyncIOThreadExtensionFunction* function) {