1 // Copyright (c) 2011 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 "content/child/quota_dispatcher.h"
7 #include "base/basictypes.h"
8 #include "base/lazy_instance.h"
9 #include "base/threading/thread_local.h"
10 #include "content/child/child_thread.h"
11 #include "content/child/quota_message_filter.h"
12 #include "content/child/thread_safe_sender.h"
13 #include "content/common/quota_messages.h"
14 #include "third_party/WebKit/public/platform/WebStorageQuotaCallbacks.h"
15 #include "third_party/WebKit/public/platform/WebStorageQuotaType.h"
18 using quota::QuotaStatusCode
;
19 using quota::StorageType
;
21 using blink::WebStorageQuotaCallbacks
;
22 using blink::WebStorageQuotaError
;
23 using blink::WebStorageQuotaType
;
25 using webkit_glue::WorkerTaskRunner
;
29 static base::LazyInstance
<base::ThreadLocalPointer
<QuotaDispatcher
> >::Leaky
30 g_quota_dispatcher_tls
= LAZY_INSTANCE_INITIALIZER
;
34 // QuotaDispatcher::Callback implementation for WebStorageQuotaCallbacks.
35 class WebStorageQuotaDispatcherCallback
: public QuotaDispatcher::Callback
{
37 WebStorageQuotaDispatcherCallback(blink::WebStorageQuotaCallbacks
* callback
)
38 : callbacks_(callback
) {
41 virtual ~WebStorageQuotaDispatcherCallback() {}
42 virtual void DidQueryStorageUsageAndQuota(int64 usage
, int64 quota
) OVERRIDE
{
43 callbacks_
->didQueryStorageUsageAndQuota(usage
, quota
);
45 virtual void DidGrantStorageQuota(int64 granted_quota
) OVERRIDE
{
46 callbacks_
->didGrantStorageQuota(granted_quota
);
48 virtual void DidFail(quota::QuotaStatusCode error
) OVERRIDE
{
49 callbacks_
->didFail(static_cast<WebStorageQuotaError
>(error
));
53 // Not owned (self-destructed).
54 blink::WebStorageQuotaCallbacks
* callbacks_
;
57 int CurrentWorkerId() {
58 return WorkerTaskRunner::Instance()->CurrentWorkerId();
63 QuotaDispatcher::QuotaDispatcher(ThreadSafeSender
* thread_safe_sender
,
64 QuotaMessageFilter
* quota_message_filter
)
65 : thread_safe_sender_(thread_safe_sender
),
66 quota_message_filter_(quota_message_filter
) {
67 g_quota_dispatcher_tls
.Pointer()->Set(this);
70 QuotaDispatcher::~QuotaDispatcher() {
71 IDMap
<Callback
, IDMapOwnPointer
>::iterator
iter(&pending_quota_callbacks_
);
72 while (!iter
.IsAtEnd()) {
73 iter
.GetCurrentValue()->DidFail(quota::kQuotaErrorAbort
);
77 g_quota_dispatcher_tls
.Pointer()->Set(NULL
);
80 QuotaDispatcher
* QuotaDispatcher::ThreadSpecificInstance(
81 ThreadSafeSender
* thread_safe_sender
,
82 QuotaMessageFilter
* quota_message_filter
) {
83 if (g_quota_dispatcher_tls
.Pointer()->Get())
84 return g_quota_dispatcher_tls
.Pointer()->Get();
86 QuotaDispatcher
* dispatcher
= new QuotaDispatcher(
87 thread_safe_sender
, quota_message_filter
);
88 if (WorkerTaskRunner::Instance()->CurrentWorkerId())
89 WorkerTaskRunner::Instance()->AddStopObserver(dispatcher
);
93 void QuotaDispatcher::OnWorkerRunLoopStopped() {
97 void QuotaDispatcher::OnMessageReceived(const IPC::Message
& msg
) {
99 IPC_BEGIN_MESSAGE_MAP(QuotaDispatcher
, msg
)
100 IPC_MESSAGE_HANDLER(QuotaMsg_DidGrantStorageQuota
,
101 DidGrantStorageQuota
)
102 IPC_MESSAGE_HANDLER(QuotaMsg_DidQueryStorageUsageAndQuota
,
103 DidQueryStorageUsageAndQuota
);
104 IPC_MESSAGE_HANDLER(QuotaMsg_DidFail
, DidFail
);
105 IPC_MESSAGE_UNHANDLED(handled
= false)
106 IPC_END_MESSAGE_MAP()
107 DCHECK(handled
) << "Unhandled message:" << msg
.type();
110 void QuotaDispatcher::QueryStorageUsageAndQuota(
111 const GURL
& origin_url
,
113 Callback
* callback
) {
115 int request_id
= quota_message_filter_
->GenerateRequestID(CurrentWorkerId());
116 pending_quota_callbacks_
.AddWithID(callback
, request_id
);
117 thread_safe_sender_
->Send(new QuotaHostMsg_QueryStorageUsageAndQuota(
118 request_id
, origin_url
, type
));
121 void QuotaDispatcher::RequestStorageQuota(
123 const GURL
& origin_url
,
125 int64 requested_size
,
126 Callback
* callback
) {
128 DCHECK(CurrentWorkerId() == 0);
129 int request_id
= quota_message_filter_
->GenerateRequestID(CurrentWorkerId());
130 pending_quota_callbacks_
.AddWithID(callback
, request_id
);
131 thread_safe_sender_
->Send(new QuotaHostMsg_RequestStorageQuota(
132 render_view_id
, request_id
, origin_url
, type
, requested_size
));
136 QuotaDispatcher::Callback
*
137 QuotaDispatcher::CreateWebStorageQuotaCallbacksWrapper(
138 blink::WebStorageQuotaCallbacks
* callbacks
) {
139 return new WebStorageQuotaDispatcherCallback(callbacks
);
142 void QuotaDispatcher::DidGrantStorageQuota(
144 int64 granted_quota
) {
145 Callback
* callback
= pending_quota_callbacks_
.Lookup(request_id
);
147 callback
->DidGrantStorageQuota(granted_quota
);
148 pending_quota_callbacks_
.Remove(request_id
);
151 void QuotaDispatcher::DidQueryStorageUsageAndQuota(
154 int64 current_quota
) {
155 Callback
* callback
= pending_quota_callbacks_
.Lookup(request_id
);
157 callback
->DidQueryStorageUsageAndQuota(current_usage
, current_quota
);
158 pending_quota_callbacks_
.Remove(request_id
);
161 void QuotaDispatcher::DidFail(
163 QuotaStatusCode error
) {
164 Callback
* callback
= pending_quota_callbacks_
.Lookup(request_id
);
166 callback
->DidFail(error
);
167 pending_quota_callbacks_
.Remove(request_id
);
170 COMPILE_ASSERT(int(blink::WebStorageQuotaTypeTemporary
) == \
171 int(quota::kStorageTypeTemporary
), mismatching_enums
);
172 COMPILE_ASSERT(int(blink::WebStorageQuotaTypePersistent
) == \
173 int(quota::kStorageTypePersistent
), mismatching_enums
);
175 COMPILE_ASSERT(int(blink::WebStorageQuotaErrorNotSupported
) == \
176 int(quota::kQuotaErrorNotSupported
), mismatching_enums
);
177 COMPILE_ASSERT(int(blink::WebStorageQuotaErrorAbort
) == \
178 int(quota::kQuotaErrorAbort
), mismatching_enums
);
180 } // namespace content