Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / extensions / browser / extension_function.cc
index 8c7c752..773f027 100644 (file)
 #include "extensions/browser/extension_function.h"
 
 #include "base/logging.h"
-#include "base/metrics/sparse_histogram.h"
-#include "chrome/browser/extensions/extension_function_dispatcher.h"
-#include "chrome/browser/extensions/extension_service.h"
-#include "chrome/browser/renderer_host/chrome_render_message_filter.h"
-#include "chrome/common/extensions/extension_messages.h"
 #include "content/public/browser/notification_source.h"
 #include "content/public/browser/notification_types.h"
 #include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/render_view_host.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/browser/web_contents_observer.h"
+#include "extensions/browser/extension_function_dispatcher.h"
+#include "extensions/browser/extension_message_filter.h"
+#include "extensions/common/error_utils.h"
 #include "extensions/common/extension_api.h"
+#include "extensions/common/extension_messages.h"
 
 using content::BrowserThread;
 using content::RenderViewHost;
 using content::WebContents;
+using extensions::ErrorUtils;
 using extensions::ExtensionAPI;
 using extensions::Feature;
 
+namespace {
+
+class ArgumentListResponseValue
+    : public ExtensionFunction::ResponseValueObject {
+ public:
+  ArgumentListResponseValue(const std::string& function_name,
+                            const char* title,
+                            ExtensionFunction* function,
+                            scoped_ptr<base::ListValue> result)
+      : function_name_(function_name), title_(title) {
+    if (function->GetResultList()) {
+      DCHECK_EQ(function->GetResultList(), result.get())
+          << "The result set on this function (" << function_name_ << ") "
+          << "either by calling SetResult() or directly modifying |result_| is "
+          << "different to the one passed to " << title_ << "(). "
+          << "The best way to fix this problem is to exclusively use " << title_
+          << "(). SetResult() and |result_| are deprecated.";
+    } else {
+      function->SetResultList(result.Pass());
+    }
+    // It would be nice to DCHECK(error.empty()) but some legacy extension
+    // function implementations... I'm looking at chrome.input.ime... do this
+    // for some reason.
+  }
+
+  virtual ~ArgumentListResponseValue() {}
+
+  virtual bool Apply() OVERRIDE { return true; }
+
+ private:
+  std::string function_name_;
+  const char* title_;
+};
+
+class ErrorResponseValue : public ExtensionFunction::ResponseValueObject {
+ public:
+  ErrorResponseValue(ExtensionFunction* function, const std::string& error) {
+    // It would be nice to DCHECK(!error.empty()) but too many legacy extension
+    // function implementations don't set error but signal failure.
+    function->SetError(error);
+  }
+
+  virtual ~ErrorResponseValue() {}
+
+  virtual bool Apply() OVERRIDE { return false; }
+};
+
+class BadMessageResponseValue : public ExtensionFunction::ResponseValueObject {
+ public:
+  explicit BadMessageResponseValue(ExtensionFunction* function) {
+    function->set_bad_message(true);
+    NOTREACHED() << function->name() << ": bad message";
+  }
+
+  virtual ~BadMessageResponseValue() {}
+
+  virtual bool Apply() OVERRIDE { return false; }
+};
+
+class RespondNowAction : public ExtensionFunction::ResponseActionObject {
+ public:
+  typedef base::Callback<void(bool)> SendResponseCallback;
+  RespondNowAction(ExtensionFunction::ResponseValue result,
+                   const SendResponseCallback& send_response)
+      : result_(result.Pass()), send_response_(send_response) {}
+  virtual ~RespondNowAction() {}
+
+  virtual void Execute() OVERRIDE { send_response_.Run(result_->Apply()); }
+
+ private:
+  ExtensionFunction::ResponseValue result_;
+  SendResponseCallback send_response_;
+};
+
+class RespondLaterAction : public ExtensionFunction::ResponseActionObject {
+ public:
+  virtual ~RespondLaterAction() {}
+
+  virtual void Execute() OVERRIDE {}
+};
+
+}  // namespace
+
 // static
 void ExtensionFunctionDeleteTraits::Destruct(const ExtensionFunction* x) {
   x->Destruct();
@@ -61,6 +144,16 @@ class UIThreadExtensionFunction::RenderHostTracker
     function_->SetRenderFrameHost(NULL);
   }
 
+  virtual bool OnMessageReceived(
+      const IPC::Message& message,
+      content::RenderFrameHost* render_frame_host) OVERRIDE {
+    DCHECK(render_frame_host);
+    if (render_frame_host == function_->render_frame_host())
+      return function_->OnMessageReceived(message);
+    else
+      return false;
+  }
+
   virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE {
     return function_->OnMessageReceived(message);
   }
@@ -78,7 +171,8 @@ ExtensionFunction::ExtensionFunction()
       user_gesture_(false),
       bad_message_(false),
       histogram_value_(extensions::functions::UNKNOWN),
-      source_tab_id_(-1) {
+      source_tab_id_(-1),
+      source_context_type_(Feature::UNSPECIFIED_CONTEXT) {
 }
 
 ExtensionFunction::~ExtensionFunction() {
@@ -95,7 +189,7 @@ IOThreadExtensionFunction* ExtensionFunction::AsIOThreadExtensionFunction() {
 bool ExtensionFunction::HasPermission() {
   Feature::Availability availability =
       ExtensionAPI::GetSharedInstance()->IsAvailable(
-          name_, extension_, Feature::BLESSED_EXTENSION_CONTEXT, source_url());
+          name_, extension_, source_context_type_, source_url());
   return availability.is_available();
 }
 
@@ -114,11 +208,15 @@ void ExtensionFunction::SetResult(base::Value* result) {
   results_->Append(result);
 }
 
-const base::ListValue* ExtensionFunction::GetResultList() {
+void ExtensionFunction::SetResultList(scoped_ptr<base::ListValue> results) {
+  results_ = results.Pass();
+}
+
+const base::ListValue* ExtensionFunction::GetResultList() const {
   return results_.get();
 }
 
-const std::string ExtensionFunction::GetError() {
+std::string ExtensionFunction::GetError() const {
   return error_;
 }
 
@@ -126,11 +224,86 @@ void ExtensionFunction::SetError(const std::string& error) {
   error_ = error;
 }
 
-void ExtensionFunction::Run() {
-  UMA_HISTOGRAM_SPARSE_SLOWLY("Extensions.FunctionCalls", histogram_value());
+ExtensionFunction::ResponseValue ExtensionFunction::NoArguments() {
+  return ResponseValue(new ArgumentListResponseValue(
+      name(), "NoArguments", this, make_scoped_ptr(new base::ListValue())));
+}
+
+ExtensionFunction::ResponseValue ExtensionFunction::OneArgument(
+    base::Value* arg) {
+  scoped_ptr<base::ListValue> args(new base::ListValue());
+  args->Append(arg);
+  return ResponseValue(
+      new ArgumentListResponseValue(name(), "OneArgument", this, args.Pass()));
+}
+
+ExtensionFunction::ResponseValue ExtensionFunction::TwoArguments(
+    base::Value* arg1,
+    base::Value* arg2) {
+  scoped_ptr<base::ListValue> args(new base::ListValue());
+  args->Append(arg1);
+  args->Append(arg2);
+  return ResponseValue(
+      new ArgumentListResponseValue(name(), "TwoArguments", this, args.Pass()));
+}
+
+ExtensionFunction::ResponseValue ExtensionFunction::ArgumentList(
+    scoped_ptr<base::ListValue> args) {
+  return ResponseValue(
+      new ArgumentListResponseValue(name(), "ArgumentList", this, args.Pass()));
+}
+
+ExtensionFunction::ResponseValue ExtensionFunction::Error(
+    const std::string& error) {
+  return ResponseValue(new ErrorResponseValue(this, error));
+}
+
+ExtensionFunction::ResponseValue ExtensionFunction::Error(
+    const std::string& format,
+    const std::string& s1) {
+  return ResponseValue(
+      new ErrorResponseValue(this, ErrorUtils::FormatErrorMessage(format, s1)));
+}
+
+ExtensionFunction::ResponseValue ExtensionFunction::Error(
+    const std::string& format,
+    const std::string& s1,
+    const std::string& s2) {
+  return ResponseValue(new ErrorResponseValue(
+      this, ErrorUtils::FormatErrorMessage(format, s1, s2)));
+}
+
+ExtensionFunction::ResponseValue ExtensionFunction::Error(
+    const std::string& format,
+    const std::string& s1,
+    const std::string& s2,
+    const std::string& s3) {
+  return ResponseValue(new ErrorResponseValue(
+      this, ErrorUtils::FormatErrorMessage(format, s1, s2, s3)));
+}
+
+ExtensionFunction::ResponseValue ExtensionFunction::BadMessage() {
+  return ResponseValue(new BadMessageResponseValue(this));
+}
+
+ExtensionFunction::ResponseAction ExtensionFunction::RespondNow(
+    ResponseValue result) {
+  return ResponseAction(new RespondNowAction(
+      result.Pass(), base::Bind(&ExtensionFunction::SendResponse, this)));
+}
+
+ExtensionFunction::ResponseAction ExtensionFunction::RespondLater() {
+  return ResponseAction(new RespondLaterAction());
+}
+
+// static
+ExtensionFunction::ResponseAction ExtensionFunction::ValidationFailure(
+    ExtensionFunction* function) {
+  return function->RespondNow(function->BadMessage());
+}
 
-  if (!RunImpl())
-    SendResponse(false);
+void ExtensionFunction::Respond(ResponseValue result) {
+  SendResponse(result->Apply());
 }
 
 bool ExtensionFunction::ShouldSkipQuotaLimiting() const {
@@ -158,6 +331,10 @@ void ExtensionFunction::SendResponseImpl(bool success) {
   response_callback_.Run(type, *results_, GetError());
 }
 
+void ExtensionFunction::OnRespondingLater(ResponseValue value) {
+  SendResponse(value->Apply());
+}
+
 UIThreadExtensionFunction::UIThreadExtensionFunction()
     : render_view_host_(NULL),
       render_frame_host_(NULL),
@@ -167,7 +344,7 @@ UIThreadExtensionFunction::UIThreadExtensionFunction()
 
 UIThreadExtensionFunction::~UIThreadExtensionFunction() {
   if (dispatcher() && render_view_host())
-    dispatcher()->OnExtensionFunctionCompleted(GetExtension());
+    dispatcher()->OnExtensionFunctionCompleted(extension());
 }
 
 UIThreadExtensionFunction*
@@ -210,18 +387,39 @@ void UIThreadExtensionFunction::SendResponse(bool success) {
     delegate_->OnSendResponse(this, success, bad_message_);
   else
     SendResponseImpl(success);
+
+  if (!transferred_blob_uuids_.empty()) {
+    DCHECK(!delegate_) << "Blob transfer not supported with test delegate.";
+    GetIPCSender()->Send(
+        new ExtensionMsg_TransferBlobs(transferred_blob_uuids_));
+  }
+}
+
+void UIThreadExtensionFunction::SetTransferredBlobUUIDs(
+    const std::vector<std::string>& blob_uuids) {
+  DCHECK(transferred_blob_uuids_.empty());  // Should only be called once.
+  transferred_blob_uuids_ = blob_uuids;
 }
 
 void UIThreadExtensionFunction::WriteToConsole(
     content::ConsoleMessageLevel level,
     const std::string& message) {
-  if (render_view_host_) {
-    render_view_host_->Send(new ExtensionMsg_AddMessageToConsole(
-        render_view_host_->GetRoutingID(), level, message));
-  } else {
-    render_frame_host_->Send(new ExtensionMsg_AddMessageToConsole(
-        render_frame_host_->GetRoutingID(), level, message));
-  }
+  GetIPCSender()->Send(
+      new ExtensionMsg_AddMessageToConsole(GetRoutingID(), level, message));
+}
+
+IPC::Sender* UIThreadExtensionFunction::GetIPCSender() {
+  if (render_view_host_)
+    return render_view_host_;
+  else
+    return render_frame_host_;
+}
+
+int UIThreadExtensionFunction::GetRoutingID() {
+  if (render_view_host_)
+    return render_view_host_->GetRoutingID();
+  else
+    return render_frame_host_->GetRoutingID();
 }
 
 IOThreadExtensionFunction::IOThreadExtensionFunction()
@@ -250,14 +448,29 @@ AsyncExtensionFunction::AsyncExtensionFunction() {
 AsyncExtensionFunction::~AsyncExtensionFunction() {
 }
 
+ExtensionFunction::ResponseAction AsyncExtensionFunction::Run() {
+  return RunAsync() ? RespondLater() : RespondNow(Error(error_));
+}
+
+// static
+bool AsyncExtensionFunction::ValidationFailure(
+    AsyncExtensionFunction* function) {
+  return false;
+}
+
 SyncExtensionFunction::SyncExtensionFunction() {
 }
 
 SyncExtensionFunction::~SyncExtensionFunction() {
 }
 
-void SyncExtensionFunction::Run() {
-  SendResponse(RunImpl());
+ExtensionFunction::ResponseAction SyncExtensionFunction::Run() {
+  return RespondNow(RunSync() ? ArgumentList(results_.Pass()) : Error(error_));
+}
+
+// static
+bool SyncExtensionFunction::ValidationFailure(SyncExtensionFunction* function) {
+  return false;
 }
 
 SyncIOThreadExtensionFunction::SyncIOThreadExtensionFunction() {
@@ -266,6 +479,12 @@ SyncIOThreadExtensionFunction::SyncIOThreadExtensionFunction() {
 SyncIOThreadExtensionFunction::~SyncIOThreadExtensionFunction() {
 }
 
-void SyncIOThreadExtensionFunction::Run() {
-  SendResponse(RunImpl());
+ExtensionFunction::ResponseAction SyncIOThreadExtensionFunction::Run() {
+  return RespondNow(RunSync() ? ArgumentList(results_.Pass()) : Error(error_));
+}
+
+// static
+bool SyncIOThreadExtensionFunction::ValidationFailure(
+    SyncIOThreadExtensionFunction* function) {
+  return false;
 }