summaryrefslogtreecommitdiffstats
path: root/ppapi
diff options
context:
space:
mode:
Diffstat (limited to 'ppapi')
-rw-r--r--ppapi/thunk/enter.cc78
-rw-r--r--ppapi/thunk/enter.h83
-rw-r--r--ppapi/thunk/ppb_graphics_2d_thunk.cc21
-rw-r--r--ppapi/thunk/ppb_url_loader_thunk.cc48
4 files changed, 184 insertions, 46 deletions
diff --git a/ppapi/thunk/enter.cc b/ppapi/thunk/enter.cc
index 7e9f70a..42f4a0e 100644
--- a/ppapi/thunk/enter.cc
+++ b/ppapi/thunk/enter.cc
@@ -4,13 +4,89 @@
#include "ppapi/thunk/enter.h"
-#include "base/lazy_instance.h"
+#include "base/bind.h"
+#include "base/logging.h"
+#include "base/message_loop.h"
+#include "ppapi/c/pp_errors.h"
#include "ppapi/thunk/ppb_instance_api.h"
#include "ppapi/thunk/resource_creation_api.h"
namespace ppapi {
namespace thunk {
+namespace subtle {
+
+bool CallbackIsRequired(const PP_CompletionCallback& callback) {
+ return callback.func != NULL &&
+ (callback.flags & PP_COMPLETIONCALLBACK_FLAG_OPTIONAL) == 0;
+}
+
+EnterBase::EnterBase()
+ : callback_(PP_BlockUntilComplete()),
+ retval_(PP_OK) {
+ // TODO(brettw) validate threads.
+}
+
+EnterBase::EnterBase(const PP_CompletionCallback& callback)
+ : callback_(CallbackIsRequired(callback) ? callback
+ : PP_BlockUntilComplete()),
+ retval_(PP_OK) {
+ // TODO(brettw) validate threads.
+}
+
+EnterBase::~EnterBase() {
+ if (callback_.func) {
+ // All async completions should have cleared the callback in SetResult().
+ DCHECK(retval_ != PP_OK_COMPLETIONPENDING && retval_ != PP_OK);
+ MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
+ callback_.func, callback_.user_data, retval_));
+ }
+}
+
+int32_t EnterBase::SetResult(int32_t result) {
+ if (!callback_.func || result == PP_OK_COMPLETIONPENDING) {
+ // Easy case, we don't need to issue the callback (either none is
+ // required, or the implementation will asynchronously issue it
+ // for us), just store the result.
+ callback_ = PP_BlockUntilComplete();
+ retval_ = result;
+ return retval_;
+ }
+
+ // This is a required callback, asynchronously issue it.
+ // TODO(brettw) make this work on different threads, etc.
+ MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
+ callback_.func, callback_.user_data, result));
+
+ // Now that the callback will be issued in the future, we should return
+ // "pending" to the caller, and not issue the callback again.
+ callback_ = PP_BlockUntilComplete();
+ retval_ = PP_OK_COMPLETIONPENDING;
+ return retval_;
+}
+
+FunctionGroupBase* EnterBase::GetFunctions(PP_Instance instance,
+ ApiID id) const {
+ return PpapiGlobals::Get()->GetFunctionAPI(instance, id);
+}
+
+Resource* EnterBase::GetResource(PP_Resource resource) const {
+ return PpapiGlobals::Get()->GetResourceTracker()->GetResource(resource);
+}
+
+void EnterBase::SetStateForResourceError(PP_Resource /* pp_resource */,
+ Resource* /* resource_base */,
+ void* object,
+ bool /* report_error */) {
+ if (object)
+ return; // Everything worked.
+
+ retval_ = PP_ERROR_BADRESOURCE;
+ // TODO(brettw) log the error.
+}
+
+} // namespace subtle
+
EnterResourceCreation::EnterResourceCreation(PP_Instance instance)
: EnterFunctionNoLock<ResourceCreationAPI>(instance, true) {
}
diff --git a/ppapi/thunk/enter.h b/ppapi/thunk/enter.h
index e2c6938..86d6022 100644
--- a/ppapi/thunk/enter.h
+++ b/ppapi/thunk/enter.h
@@ -66,16 +66,67 @@ struct LockOnEntry<true> {
}
};
+// Keep non-templatized since we need non-inline functions here.
+class PPAPI_THUNK_EXPORT EnterBase {
+ public:
+ EnterBase();
+ explicit EnterBase(const PP_CompletionCallback& callback);
+ virtual ~EnterBase();
+
+ // Sets the result.
+ //
+ // Returns the "retval()". This is to support the typical usage of
+ // return enter.SetResult(...);
+ // without having to write a separate "return enter.retval();" line.
+ int32_t SetResult(int32_t result);
+
+ // Use this value as the return value for the function.
+ int32_t retval() const { return retval_; }
+
+ protected:
+ // Helper function to return a function group from a PP_Instance. Having this
+ // code be in the non-templatized base keeps us from having to instantiate
+ // it in every template.
+ FunctionGroupBase* GetFunctions(PP_Instance instance, ApiID id) const;
+
+ // Helper function to return a Resource from a PP_Resource. Having this
+ // code be in the non-templatized base keeps us from having to instantiate
+ // it in every template.
+ Resource* GetResource(PP_Resource resource) const;
+
+ // Does error handling associated with entering a resource. The resource_base
+ // is the result of looking up the given pp_resource. The object is the
+ // result of converting the base to the desired object (converted back to a
+ // Resource* so this function doesn't have to be templatized). The reason for
+ // passing both resource_base and object is that we can differentiate "bad
+ // resource ID" from "valid resource ID not of the currect type."
+ //
+ // This will set retval_ = PP_ERROR_BADRESOURCE if the object is invalid, and
+ // if report_error is set, log a message to the programmer.
+ void SetStateForResourceError(PP_Resource pp_resource,
+ Resource* resource_base,
+ void* object,
+ bool report_error);
+
+ private:
+ // Holds the callback. The function will only be non-NULL when the
+ // callback is requried. Optional callbacks don't require any special
+ // handling from us at this layer.
+ PP_CompletionCallback callback_;
+
+ int32_t retval_;
+};
+
} // namespace subtle
template<typename FunctionsT, bool lock_on_entry = true>
-class EnterFunction : subtle::LockOnEntry<lock_on_entry> {
+class EnterFunction : public subtle::EnterBase,
+ public subtle::LockOnEntry<lock_on_entry> {
public:
EnterFunction(PP_Instance instance, bool report_error)
: functions_(NULL) {
- FunctionGroupBase* base = PpapiGlobals::Get()->GetFunctionAPI(
- instance, FunctionsT::kApiID);
+ FunctionGroupBase* base = GetFunctions(instance, FunctionsT::kApiID);
if (base)
functions_ = base->GetAs<FunctionsT>();
// TODO(brettw) check error and if report_error is set, do something.
@@ -124,15 +175,18 @@ class EnterFunctionGivenResource : public EnterFunction<FunctionsT> {
// EnterResource ---------------------------------------------------------------
template<typename ResourceT, bool lock_on_entry = true>
-class EnterResource : subtle::LockOnEntry<lock_on_entry> {
+class EnterResource : public subtle::EnterBase,
+ public subtle::LockOnEntry<lock_on_entry> {
public:
EnterResource(PP_Resource resource, bool report_error)
- : object_(NULL) {
- resource_ =
- PpapiGlobals::Get()->GetResourceTracker()->GetResource(resource);
- if (resource_)
- object_ = resource_->GetAs<ResourceT>();
- // TODO(brettw) check error and if report_error is set, do something.
+ : EnterBase() {
+ Init(resource, report_error);
+ }
+ EnterResource(PP_Resource resource,
+ const PP_CompletionCallback& callback,
+ bool report_error)
+ : EnterBase(callback) {
+ Init(resource, report_error);
}
~EnterResource() {}
@@ -143,6 +197,15 @@ class EnterResource : subtle::LockOnEntry<lock_on_entry> {
Resource* resource() { return resource_; }
private:
+ void Init(PP_Resource resource, bool report_error) {
+ resource_ = GetResource(resource);
+ if (resource_)
+ object_ = resource_->GetAs<ResourceT>();
+ else
+ object_ = NULL;
+ SetStateForResourceError(resource, resource_, object_, report_error);
+ }
+
Resource* resource_;
ResourceT* object_;
diff --git a/ppapi/thunk/ppb_graphics_2d_thunk.cc b/ppapi/thunk/ppb_graphics_2d_thunk.cc
index e42d002..edb7ea9 100644
--- a/ppapi/thunk/ppb_graphics_2d_thunk.cc
+++ b/ppapi/thunk/ppb_graphics_2d_thunk.cc
@@ -16,24 +16,26 @@ namespace thunk {
namespace {
+typedef EnterResource<PPB_Graphics2D_API> EnterGraphics2D;
+
PP_Resource Create(PP_Instance instance,
const PP_Size* size,
PP_Bool is_always_opaque) {
- EnterFunction<ResourceCreationAPI> enter(instance, true);
+ EnterResourceCreation enter(instance);
if (enter.failed())
return 0;
return enter.functions()->CreateGraphics2D(instance, *size, is_always_opaque);
}
PP_Bool IsGraphics2D(PP_Resource resource) {
- EnterResource<PPB_Graphics2D_API> enter(resource, false);
+ EnterGraphics2D enter(resource, false);
return enter.succeeded() ? PP_TRUE : PP_FALSE;
}
PP_Bool Describe(PP_Resource graphics_2d,
PP_Size* size,
PP_Bool* is_always_opaque) {
- EnterResource<PPB_Graphics2D_API> enter(graphics_2d, true);
+ EnterGraphics2D enter(graphics_2d, true);
if (enter.failed()) {
size->width = 0;
size->height = 0;
@@ -47,7 +49,7 @@ void PaintImageData(PP_Resource graphics_2d,
PP_Resource image_data,
const PP_Point* top_left,
const PP_Rect* src_rect) {
- EnterResource<PPB_Graphics2D_API> enter(graphics_2d, true);
+ EnterGraphics2D enter(graphics_2d, true);
if (enter.failed())
return;
enter.object()->PaintImageData(image_data, top_left, src_rect);
@@ -56,14 +58,14 @@ void PaintImageData(PP_Resource graphics_2d,
void Scroll(PP_Resource graphics_2d,
const PP_Rect* clip_rect,
const PP_Point* amount) {
- EnterResource<PPB_Graphics2D_API> enter(graphics_2d, true);
+ EnterGraphics2D enter(graphics_2d, true);
if (enter.failed())
return;
enter.object()->Scroll(clip_rect, amount);
}
void ReplaceContents(PP_Resource graphics_2d, PP_Resource image_data) {
- EnterResource<PPB_Graphics2D_API> enter(graphics_2d, true);
+ EnterGraphics2D enter(graphics_2d, true);
if (enter.failed())
return;
enter.object()->ReplaceContents(image_data);
@@ -71,11 +73,10 @@ void ReplaceContents(PP_Resource graphics_2d, PP_Resource image_data) {
int32_t Flush(PP_Resource graphics_2d,
PP_CompletionCallback callback) {
- EnterResource<PPB_Graphics2D_API> enter(graphics_2d, true);
+ EnterGraphics2D enter(graphics_2d, callback, true);
if (enter.failed())
- return MayForceCallback(callback, PP_ERROR_BADRESOURCE);
- int32_t result = enter.object()->Flush(callback);
- return MayForceCallback(callback, result);
+ return enter.retval();
+ return enter.SetResult(enter.object()->Flush(callback));
}
const PPB_Graphics2D g_ppb_graphics_2d_thunk = {
diff --git a/ppapi/thunk/ppb_url_loader_thunk.cc b/ppapi/thunk/ppb_url_loader_thunk.cc
index 719d443..a4a2b3d 100644
--- a/ppapi/thunk/ppb_url_loader_thunk.cc
+++ b/ppapi/thunk/ppb_url_loader_thunk.cc
@@ -15,41 +15,41 @@ namespace thunk {
namespace {
+typedef EnterResource<PPB_URLLoader_API> EnterURLLoader;
+
PP_Resource Create(PP_Instance instance) {
- EnterFunction<ResourceCreationAPI> enter(instance, true);
+ EnterResourceCreation enter(instance);
if (enter.failed())
return 0;
return enter.functions()->CreateURLLoader(instance);
}
PP_Bool IsURLLoader(PP_Resource resource) {
- EnterResource<PPB_URLLoader_API> enter(resource, false);
+ EnterURLLoader enter(resource, false);
return PP_FromBool(enter.succeeded());
}
int32_t Open(PP_Resource loader,
PP_Resource request_id,
PP_CompletionCallback callback) {
- EnterResource<PPB_URLLoader_API> enter(loader, true);
+ EnterURLLoader enter(loader, callback, true);
if (enter.failed())
- return MayForceCallback(callback, PP_ERROR_BADRESOURCE);
- int32_t result = enter.object()->Open(request_id, callback);
- return MayForceCallback(callback, result);
+ return enter.retval();
+ return enter.SetResult(enter.object()->Open(request_id, callback));
}
int32_t FollowRedirect(PP_Resource loader,
PP_CompletionCallback callback) {
- EnterResource<PPB_URLLoader_API> enter(loader, true);
+ EnterURLLoader enter(loader, callback, true);
if (enter.failed())
- return MayForceCallback(callback, PP_ERROR_BADRESOURCE);
- int32_t result = enter.object()->FollowRedirect(callback);
- return MayForceCallback(callback, result);
+ return enter.retval();
+ return enter.SetResult(enter.object()->FollowRedirect(callback));
}
PP_Bool GetUploadProgress(PP_Resource loader,
int64_t* bytes_sent,
int64_t* total_bytes_to_be_sent) {
- EnterResource<PPB_URLLoader_API> enter(loader, true);
+ EnterURLLoader enter(loader, true);
if (enter.failed()) {
*bytes_sent = 0;
*total_bytes_to_be_sent = 0;
@@ -62,7 +62,7 @@ PP_Bool GetUploadProgress(PP_Resource loader,
PP_Bool GetDownloadProgress(PP_Resource loader,
int64_t* bytes_received,
int64_t* total_bytes_to_be_received) {
- EnterResource<PPB_URLLoader_API> enter(loader, true);
+ EnterURLLoader enter(loader, true);
if (enter.failed()) {
*bytes_received = 0;
*total_bytes_to_be_received = 0;
@@ -73,7 +73,7 @@ PP_Bool GetDownloadProgress(PP_Resource loader,
}
PP_Resource GetResponseInfo(PP_Resource loader) {
- EnterResource<PPB_URLLoader_API> enter(loader, true);
+ EnterURLLoader enter(loader, true);
if (enter.failed())
return 0;
return enter.object()->GetResponseInfo();
@@ -83,38 +83,36 @@ int32_t ReadResponseBody(PP_Resource loader,
void* buffer,
int32_t bytes_to_read,
PP_CompletionCallback callback) {
- EnterResource<PPB_URLLoader_API> enter(loader, true);
+ EnterURLLoader enter(loader, callback, true);
if (enter.failed())
- return MayForceCallback(callback, PP_ERROR_BADRESOURCE);
- int32_t result = enter.object()->ReadResponseBody(buffer, bytes_to_read,
- callback);
- return MayForceCallback(callback, result);
+ return enter.retval();
+ return enter.SetResult(enter.object()->ReadResponseBody(buffer, bytes_to_read,
+ callback));
}
int32_t FinishStreamingToFile(PP_Resource loader,
PP_CompletionCallback callback) {
- EnterResource<PPB_URLLoader_API> enter(loader, true);
+ EnterURLLoader enter(loader, callback, true);
if (enter.failed())
- return MayForceCallback(callback, PP_ERROR_BADRESOURCE);
- int32_t result = enter.object()->FinishStreamingToFile(callback);
- return MayForceCallback(callback, result);
+ return enter.retval();
+ return enter.SetResult(enter.object()->FinishStreamingToFile(callback));
}
void Close(PP_Resource loader) {
- EnterResource<PPB_URLLoader_API> enter(loader, true);
+ EnterURLLoader enter(loader, true);
if (enter.succeeded())
enter.object()->Close();
}
void GrantUniversalAccess(PP_Resource loader) {
- EnterResource<PPB_URLLoader_API> enter(loader, true);
+ EnterURLLoader enter(loader, true);
if (enter.succeeded())
enter.object()->GrantUniversalAccess();
}
void SetStatusCallback(PP_Resource loader,
PP_URLLoaderTrusted_StatusCallback cb) {
- EnterResource<PPB_URLLoader_API> enter(loader, true);
+ EnterURLLoader enter(loader, true);
if (enter.succeeded())
enter.object()->SetStatusCallback(cb);
}