Index: Source/platform/exported/WebCryptoResult.cpp |
diff --git a/Source/platform/exported/WebCryptoResult.cpp b/Source/platform/exported/WebCryptoResult.cpp |
index d5515064a86e9aa829d129b2828f678f1820fadf..177968387e7ed4b157c859bf8951f7e618d267fa 100644 |
--- a/Source/platform/exported/WebCryptoResult.cpp |
+++ b/Source/platform/exported/WebCryptoResult.cpp |
@@ -33,68 +33,122 @@ |
#include "platform/CryptoResult.h" |
#include "platform/heap/Heap.h" |
-#include <string.h> |
+#include "wtf/Atomics.h" |
namespace blink { |
void WebCryptoResult::completeWithError(WebCryptoErrorType errorType, const WebString& errorDetails) |
{ |
+ if (cancelled()) |
+ return; |
+ ASSERT(m_impl->isOwnerResult(this)); |
m_impl->completeWithError(errorType, errorDetails); |
- reset(); |
+ clear(); |
} |
void WebCryptoResult::completeWithBuffer(const void* bytes, unsigned bytesSize) |
{ |
+ if (cancelled()) |
+ return; |
+ ASSERT(m_impl->isOwnerResult(this)); |
m_impl->completeWithBuffer(bytes, bytesSize); |
- reset(); |
+ clear(); |
} |
void WebCryptoResult::completeWithJson(const char* utf8Data, unsigned length) |
{ |
+ if (cancelled()) |
+ return; |
+ ASSERT(m_impl->isOwnerResult(this)); |
m_impl->completeWithJson(utf8Data, length); |
- reset(); |
+ clear(); |
} |
void WebCryptoResult::completeWithBoolean(bool b) |
{ |
+ if (cancelled()) |
+ return; |
+ ASSERT(m_impl->isOwnerResult(this)); |
m_impl->completeWithBoolean(b); |
- reset(); |
+ clear(); |
} |
void WebCryptoResult::completeWithKey(const WebCryptoKey& key) |
{ |
+ if (cancelled()) |
+ return; |
ASSERT(!key.isNull()); |
+ ASSERT(m_impl->isOwnerResult(this)); |
m_impl->completeWithKey(key); |
- reset(); |
+ clear(); |
} |
void WebCryptoResult::completeWithKeyPair(const WebCryptoKey& publicKey, const WebCryptoKey& privateKey) |
{ |
+ if (cancelled()) |
+ return; |
ASSERT(!publicKey.isNull()); |
ASSERT(!privateKey.isNull()); |
+ ASSERT(m_impl->isOwnerResult(this)); |
m_impl->completeWithKeyPair(publicKey, privateKey); |
- reset(); |
+ clear(); |
} |
bool WebCryptoResult::cancelled() const |
{ |
- return m_impl->cancelled(); |
+ return acquireLoad(&m_cancelled); |
} |
WebCryptoResult::WebCryptoResult(const PassRefPtrWillBeRawPtr<CryptoResult>& impl) |
- : m_impl(impl) |
+ : m_cancelled(0) |
+ , m_impl(impl) |
{ |
ASSERT(m_impl.get()); |
+ bool cancel = m_impl->registerResult(this); |
+ // The Blink origin thread invokes this constructor; cancellation |
+ // cannot happen while doing so. |
+ ASSERT_UNUSED(cancel, !cancel && !cancelled()); |
} |
void WebCryptoResult::reset() |
{ |
- m_impl.reset(); |
+ CryptoResult* result = m_impl.get(); |
+ if (cancelled()) |
+ return; |
+ |
+ if (result) { |
+ result->unregisterResult(this); |
+ m_impl.reset(); |
+ } |
+} |
+ |
+void WebCryptoResult::clear() |
+{ |
+ reset(); |
+ releaseStore(&m_cancelled, 1); |
} |
void WebCryptoResult::assign(const WebCryptoResult& o) |
{ |
m_impl = o.m_impl; |
+ m_cancelled = o.cancelled(); |
+ if (m_cancelled) { |
+ m_impl.reset(); |
+ return; |
+ } |
+ |
+ // Notice that m_impl will not be updated by the Blink thread calling cancel() |
+ // until registerResult(this) has been called for it. |
+ // |
+ // Should the o.m_impl CryptoResultImpl be concurrently cancelled, clear out the |
+ // WebCryptoResult that was attempted registered, effectively forwarding the |
+ // cancellation to the assigned result. |
+ if (!m_impl.isNull()) { |
+ bool cancel = m_impl->registerResult(this); |
+ releaseStore(&m_cancelled, cancel); |
+ if (cancel) |
+ m_impl.reset(); |
+ } |
} |
} // namespace blink |