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 blink::WebStorageQuotaCallbacks
;
19 using blink::WebStorageQuotaError
;
20 using blink::WebStorageQuotaType
;
21 using quota::QuotaStatusCode
;
22 using quota::StorageType
;
26 static base::LazyInstance
<base::ThreadLocalPointer
<QuotaDispatcher
> >::Leaky
27 g_quota_dispatcher_tls
= LAZY_INSTANCE_INITIALIZER
;
31 // QuotaDispatcher::Callback implementation for WebStorageQuotaCallbacks.
32 class WebStorageQuotaDispatcherCallback
: public QuotaDispatcher::Callback
{
34 explicit WebStorageQuotaDispatcherCallback(
35 blink::WebStorageQuotaCallbacks callback
)
36 : callbacks_(callback
) {}
37 virtual ~WebStorageQuotaDispatcherCallback() {}
39 virtual void DidQueryStorageUsageAndQuota(int64 usage
, int64 quota
) OVERRIDE
{
40 callbacks_
.didQueryStorageUsageAndQuota(usage
, quota
);
42 virtual void DidGrantStorageQuota(int64 usage
, int64 granted_quota
) OVERRIDE
{
43 callbacks_
.didGrantStorageQuota(usage
, granted_quota
);
45 virtual void DidFail(quota::QuotaStatusCode error
) OVERRIDE
{
46 callbacks_
.didFail(static_cast<WebStorageQuotaError
>(error
));
50 blink::WebStorageQuotaCallbacks callbacks_
;
52 DISALLOW_COPY_AND_ASSIGN(WebStorageQuotaDispatcherCallback
);
55 int CurrentWorkerId() {
56 return WorkerTaskRunner::Instance()->CurrentWorkerId();
61 QuotaDispatcher::QuotaDispatcher(ThreadSafeSender
* thread_safe_sender
,
62 QuotaMessageFilter
* quota_message_filter
)
63 : thread_safe_sender_(thread_safe_sender
),
64 quota_message_filter_(quota_message_filter
) {
65 g_quota_dispatcher_tls
.Pointer()->Set(this);
68 QuotaDispatcher::~QuotaDispatcher() {
69 IDMap
<Callback
, IDMapOwnPointer
>::iterator
iter(&pending_quota_callbacks_
);
70 while (!iter
.IsAtEnd()) {
71 iter
.GetCurrentValue()->DidFail(quota::kQuotaErrorAbort
);
75 g_quota_dispatcher_tls
.Pointer()->Set(NULL
);
78 QuotaDispatcher
* QuotaDispatcher::ThreadSpecificInstance(
79 ThreadSafeSender
* thread_safe_sender
,
80 QuotaMessageFilter
* quota_message_filter
) {
81 if (g_quota_dispatcher_tls
.Pointer()->Get())
82 return g_quota_dispatcher_tls
.Pointer()->Get();
84 QuotaDispatcher
* dispatcher
= new QuotaDispatcher(
85 thread_safe_sender
, quota_message_filter
);
86 if (WorkerTaskRunner::Instance()->CurrentWorkerId())
87 WorkerTaskRunner::Instance()->AddStopObserver(dispatcher
);
91 void QuotaDispatcher::OnWorkerRunLoopStopped() {
95 void QuotaDispatcher::OnMessageReceived(const IPC::Message
& msg
) {
97 IPC_BEGIN_MESSAGE_MAP(QuotaDispatcher
, msg
)
98 IPC_MESSAGE_HANDLER(QuotaMsg_DidGrantStorageQuota
,
100 IPC_MESSAGE_HANDLER(QuotaMsg_DidQueryStorageUsageAndQuota
,
101 DidQueryStorageUsageAndQuota
);
102 IPC_MESSAGE_HANDLER(QuotaMsg_DidFail
, DidFail
);
103 IPC_MESSAGE_UNHANDLED(handled
= false)
104 IPC_END_MESSAGE_MAP()
105 DCHECK(handled
) << "Unhandled message:" << msg
.type();
108 void QuotaDispatcher::QueryStorageUsageAndQuota(
109 const GURL
& origin_url
,
111 Callback
* callback
) {
113 int request_id
= quota_message_filter_
->GenerateRequestID(CurrentWorkerId());
114 pending_quota_callbacks_
.AddWithID(callback
, request_id
);
115 thread_safe_sender_
->Send(new QuotaHostMsg_QueryStorageUsageAndQuota(
116 request_id
, origin_url
, type
));
119 void QuotaDispatcher::RequestStorageQuota(
121 const GURL
& origin_url
,
123 uint64 requested_size
,
124 Callback
* callback
) {
126 DCHECK(CurrentWorkerId() == 0);
127 int request_id
= quota_message_filter_
->GenerateRequestID(CurrentWorkerId());
128 pending_quota_callbacks_
.AddWithID(callback
, request_id
);
129 thread_safe_sender_
->Send(new QuotaHostMsg_RequestStorageQuota(
130 render_view_id
, request_id
, origin_url
, type
, requested_size
));
134 QuotaDispatcher::Callback
*
135 QuotaDispatcher::CreateWebStorageQuotaCallbacksWrapper(
136 blink::WebStorageQuotaCallbacks callbacks
) {
137 return new WebStorageQuotaDispatcherCallback(callbacks
);
140 void QuotaDispatcher::DidGrantStorageQuota(
143 int64 granted_quota
) {
144 Callback
* callback
= pending_quota_callbacks_
.Lookup(request_id
);
146 callback
->DidGrantStorageQuota(current_usage
, granted_quota
);
147 pending_quota_callbacks_
.Remove(request_id
);
150 void QuotaDispatcher::DidQueryStorageUsageAndQuota(
153 int64 current_quota
) {
154 Callback
* callback
= pending_quota_callbacks_
.Lookup(request_id
);
156 callback
->DidQueryStorageUsageAndQuota(current_usage
, current_quota
);
157 pending_quota_callbacks_
.Remove(request_id
);
160 void QuotaDispatcher::DidFail(
162 QuotaStatusCode error
) {
163 Callback
* callback
= pending_quota_callbacks_
.Lookup(request_id
);
165 callback
->DidFail(error
);
166 pending_quota_callbacks_
.Remove(request_id
);
169 COMPILE_ASSERT(int(blink::WebStorageQuotaTypeTemporary
) == \
170 int(quota::kStorageTypeTemporary
), mismatching_enums
);
171 COMPILE_ASSERT(int(blink::WebStorageQuotaTypePersistent
) == \
172 int(quota::kStorageTypePersistent
), mismatching_enums
);
174 COMPILE_ASSERT(int(blink::WebStorageQuotaErrorNotSupported
) == \
175 int(quota::kQuotaErrorNotSupported
), mismatching_enums
);
176 COMPILE_ASSERT(int(blink::WebStorageQuotaErrorAbort
) == \
177 int(quota::kQuotaErrorAbort
), mismatching_enums
);
179 } // namespace content