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 "base/metrics/sparse_histogram.h"
9 #include "chrome/browser/extensions/extension_function_dispatcher.h"
10 #include "chrome/browser/extensions/extension_service.h"
11 #include "chrome/browser/renderer_host/chrome_render_message_filter.h"
12 #include "chrome/common/extensions/extension_messages.h"
13 #include "content/public/browser/notification_source.h"
14 #include "content/public/browser/notification_types.h"
15 #include "content/public/browser/render_frame_host.h"
16 #include "content/public/browser/render_view_host.h"
17 #include "content/public/browser/web_contents.h"
18 #include "content/public/browser/web_contents_observer.h"
19 #include "extensions/common/extension_api.h"
21 using content::BrowserThread;
22 using content::RenderViewHost;
23 using content::WebContents;
24 using extensions::ExtensionAPI;
25 using extensions::Feature;
28 void ExtensionFunctionDeleteTraits::Destruct(const ExtensionFunction* x) {
32 // Helper class to track the lifetime of ExtensionFunction's RenderViewHost or
33 // RenderFrameHost pointer and NULL it out when it dies. It also allows us to
34 // filter IPC messages coming from the RenderViewHost/RenderFrameHost.
35 class UIThreadExtensionFunction::RenderHostTracker
36 : public content::WebContentsObserver {
38 explicit RenderHostTracker(UIThreadExtensionFunction* function)
39 : content::WebContentsObserver(
40 function->render_view_host() ?
41 WebContents::FromRenderViewHost(function->render_view_host()) :
42 WebContents::FromRenderFrameHost(
43 function->render_frame_host())),
48 // content::WebContentsObserver:
49 virtual void RenderViewDeleted(
50 content::RenderViewHost* render_view_host) OVERRIDE {
51 if (render_view_host != function_->render_view_host())
54 function_->SetRenderViewHost(NULL);
56 virtual void RenderFrameDeleted(
57 content::RenderFrameHost* render_frame_host) OVERRIDE {
58 if (render_frame_host != function_->render_frame_host())
61 function_->SetRenderFrameHost(NULL);
64 virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE {
65 return function_->OnMessageReceived(message);
68 UIThreadExtensionFunction* function_;
70 DISALLOW_COPY_AND_ASSIGN(RenderHostTracker);
73 ExtensionFunction::ExtensionFunction()
77 include_incognito_(false),
80 histogram_value_(extensions::functions::UNKNOWN),
84 ExtensionFunction::~ExtensionFunction() {
87 UIThreadExtensionFunction* ExtensionFunction::AsUIThreadExtensionFunction() {
91 IOThreadExtensionFunction* ExtensionFunction::AsIOThreadExtensionFunction() {
95 bool ExtensionFunction::HasPermission() {
96 Feature::Availability availability =
97 ExtensionAPI::GetSharedInstance()->IsAvailable(
98 name_, extension_, Feature::BLESSED_EXTENSION_CONTEXT, source_url());
99 return availability.is_available();
102 void ExtensionFunction::OnQuotaExceeded(const std::string& violation_error) {
103 error_ = violation_error;
107 void ExtensionFunction::SetArgs(const base::ListValue* args) {
108 DCHECK(!args_.get()); // Should only be called once.
109 args_.reset(args->DeepCopy());
112 void ExtensionFunction::SetResult(base::Value* result) {
113 results_.reset(new base::ListValue());
114 results_->Append(result);
117 const base::ListValue* ExtensionFunction::GetResultList() {
118 return results_.get();
121 const std::string ExtensionFunction::GetError() {
125 void ExtensionFunction::SetError(const std::string& error) {
129 void ExtensionFunction::Run() {
130 UMA_HISTOGRAM_SPARSE_SLOWLY("Extensions.FunctionCalls", histogram_value());
136 bool ExtensionFunction::ShouldSkipQuotaLimiting() const {
140 bool ExtensionFunction::HasOptionalArgument(size_t index) {
142 return args_->Get(index, &value) && !value->IsType(base::Value::TYPE_NULL);
145 void ExtensionFunction::SendResponseImpl(bool success) {
146 DCHECK(!response_callback_.is_null());
148 ResponseType type = success ? SUCCEEDED : FAILED;
151 LOG(ERROR) << "Bad extension message " << name_;
154 // If results were never set, we send an empty argument list.
156 results_.reset(new base::ListValue());
158 response_callback_.Run(type, *results_, GetError());
161 UIThreadExtensionFunction::UIThreadExtensionFunction()
162 : render_view_host_(NULL),
163 render_frame_host_(NULL),
168 UIThreadExtensionFunction::~UIThreadExtensionFunction() {
169 if (dispatcher() && render_view_host())
170 dispatcher()->OnExtensionFunctionCompleted(GetExtension());
173 UIThreadExtensionFunction*
174 UIThreadExtensionFunction::AsUIThreadExtensionFunction() {
178 bool UIThreadExtensionFunction::OnMessageReceived(const IPC::Message& message) {
182 void UIThreadExtensionFunction::Destruct() const {
183 BrowserThread::DeleteOnUIThread::Destruct(this);
186 void UIThreadExtensionFunction::SetRenderViewHost(
187 RenderViewHost* render_view_host) {
188 DCHECK(!render_frame_host_);
189 render_view_host_ = render_view_host;
190 tracker_.reset(render_view_host ? new RenderHostTracker(this) : NULL);
193 void UIThreadExtensionFunction::SetRenderFrameHost(
194 content::RenderFrameHost* render_frame_host) {
195 DCHECK(!render_view_host_);
196 render_frame_host_ = render_frame_host;
197 tracker_.reset(render_frame_host ? new RenderHostTracker(this) : NULL);
200 content::WebContents* UIThreadExtensionFunction::GetAssociatedWebContents() {
201 content::WebContents* web_contents = NULL;
203 web_contents = dispatcher()->delegate()->GetAssociatedWebContents();
208 void UIThreadExtensionFunction::SendResponse(bool success) {
210 delegate_->OnSendResponse(this, success, bad_message_);
212 SendResponseImpl(success);
215 void UIThreadExtensionFunction::WriteToConsole(
216 content::ConsoleMessageLevel level,
217 const std::string& message) {
218 if (render_view_host_) {
219 render_view_host_->Send(new ExtensionMsg_AddMessageToConsole(
220 render_view_host_->GetRoutingID(), level, message));
222 render_frame_host_->Send(new ExtensionMsg_AddMessageToConsole(
223 render_frame_host_->GetRoutingID(), level, message));
227 IOThreadExtensionFunction::IOThreadExtensionFunction()
228 : routing_id_(MSG_ROUTING_NONE) {
231 IOThreadExtensionFunction::~IOThreadExtensionFunction() {
234 IOThreadExtensionFunction*
235 IOThreadExtensionFunction::AsIOThreadExtensionFunction() {
239 void IOThreadExtensionFunction::Destruct() const {
240 BrowserThread::DeleteOnIOThread::Destruct(this);
243 void IOThreadExtensionFunction::SendResponse(bool success) {
244 SendResponseImpl(success);
247 AsyncExtensionFunction::AsyncExtensionFunction() {
250 AsyncExtensionFunction::~AsyncExtensionFunction() {
253 SyncExtensionFunction::SyncExtensionFunction() {
256 SyncExtensionFunction::~SyncExtensionFunction() {
259 void SyncExtensionFunction::Run() {
260 SendResponse(RunImpl());
263 SyncIOThreadExtensionFunction::SyncIOThreadExtensionFunction() {
266 SyncIOThreadExtensionFunction::~SyncIOThreadExtensionFunction() {
269 void SyncIOThreadExtensionFunction::Run() {
270 SendResponse(RunImpl());