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"
16 #include "third_party/WebKit/public/web/WebUserGestureIndicator.h"
19 using blink::WebStorageQuotaCallbacks
;
20 using blink::WebStorageQuotaError
;
21 using blink::WebStorageQuotaType
;
22 using storage::QuotaStatusCode
;
23 using storage::StorageType
;
27 static base::LazyInstance
<base::ThreadLocalPointer
<QuotaDispatcher
> >::Leaky
28 g_quota_dispatcher_tls
= LAZY_INSTANCE_INITIALIZER
;
32 // QuotaDispatcher::Callback implementation for WebStorageQuotaCallbacks.
33 class WebStorageQuotaDispatcherCallback
: public QuotaDispatcher::Callback
{
35 explicit WebStorageQuotaDispatcherCallback(
36 blink::WebStorageQuotaCallbacks callback
)
37 : callbacks_(callback
) {}
38 virtual ~WebStorageQuotaDispatcherCallback() {}
40 virtual void DidQueryStorageUsageAndQuota(int64 usage
, int64 quota
) OVERRIDE
{
41 callbacks_
.didQueryStorageUsageAndQuota(usage
, quota
);
43 virtual void DidGrantStorageQuota(int64 usage
, int64 granted_quota
) OVERRIDE
{
44 callbacks_
.didGrantStorageQuota(usage
, granted_quota
);
46 virtual void DidFail(storage::QuotaStatusCode error
) OVERRIDE
{
47 callbacks_
.didFail(static_cast<WebStorageQuotaError
>(error
));
51 blink::WebStorageQuotaCallbacks callbacks_
;
53 DISALLOW_COPY_AND_ASSIGN(WebStorageQuotaDispatcherCallback
);
56 int CurrentWorkerId() {
57 return WorkerTaskRunner::Instance()->CurrentWorkerId();
62 QuotaDispatcher::QuotaDispatcher(ThreadSafeSender
* thread_safe_sender
,
63 QuotaMessageFilter
* quota_message_filter
)
64 : thread_safe_sender_(thread_safe_sender
),
65 quota_message_filter_(quota_message_filter
) {
66 g_quota_dispatcher_tls
.Pointer()->Set(this);
69 QuotaDispatcher::~QuotaDispatcher() {
70 IDMap
<Callback
, IDMapOwnPointer
>::iterator
iter(&pending_quota_callbacks_
);
71 while (!iter
.IsAtEnd()) {
72 iter
.GetCurrentValue()->DidFail(storage::kQuotaErrorAbort
);
76 g_quota_dispatcher_tls
.Pointer()->Set(NULL
);
79 QuotaDispatcher
* QuotaDispatcher::ThreadSpecificInstance(
80 ThreadSafeSender
* thread_safe_sender
,
81 QuotaMessageFilter
* quota_message_filter
) {
82 if (g_quota_dispatcher_tls
.Pointer()->Get())
83 return g_quota_dispatcher_tls
.Pointer()->Get();
85 QuotaDispatcher
* dispatcher
= new QuotaDispatcher(
86 thread_safe_sender
, quota_message_filter
);
87 if (WorkerTaskRunner::Instance()->CurrentWorkerId())
88 WorkerTaskRunner::Instance()->AddStopObserver(dispatcher
);
92 void QuotaDispatcher::OnWorkerRunLoopStopped() {
96 void QuotaDispatcher::OnMessageReceived(const IPC::Message
& msg
) {
98 IPC_BEGIN_MESSAGE_MAP(QuotaDispatcher
, msg
)
99 IPC_MESSAGE_HANDLER(QuotaMsg_DidGrantStorageQuota
,
100 DidGrantStorageQuota
)
101 IPC_MESSAGE_HANDLER(QuotaMsg_DidQueryStorageUsageAndQuota
,
102 DidQueryStorageUsageAndQuota
);
103 IPC_MESSAGE_HANDLER(QuotaMsg_DidFail
, DidFail
);
104 IPC_MESSAGE_UNHANDLED(handled
= false)
105 IPC_END_MESSAGE_MAP()
106 DCHECK(handled
) << "Unhandled message:" << msg
.type();
109 void QuotaDispatcher::QueryStorageUsageAndQuota(
110 const GURL
& origin_url
,
112 Callback
* callback
) {
114 int request_id
= quota_message_filter_
->GenerateRequestID(CurrentWorkerId());
115 pending_quota_callbacks_
.AddWithID(callback
, request_id
);
116 thread_safe_sender_
->Send(new QuotaHostMsg_QueryStorageUsageAndQuota(
117 request_id
, origin_url
, type
));
120 void QuotaDispatcher::RequestStorageQuota(
122 const GURL
& origin_url
,
124 uint64 requested_size
,
125 Callback
* callback
) {
127 DCHECK(CurrentWorkerId() == 0);
128 int request_id
= quota_message_filter_
->GenerateRequestID(CurrentWorkerId());
129 pending_quota_callbacks_
.AddWithID(callback
, request_id
);
131 StorageQuotaParams params
;
132 params
.render_view_id
= render_view_id
;
133 params
.request_id
= request_id
;
134 params
.origin_url
= origin_url
;
135 params
.storage_type
= type
;
136 params
.requested_size
= requested_size
;
137 params
.user_gesture
=
138 blink::WebUserGestureIndicator::isProcessingUserGesture();
139 thread_safe_sender_
->Send(new QuotaHostMsg_RequestStorageQuota(params
));
143 QuotaDispatcher::Callback
*
144 QuotaDispatcher::CreateWebStorageQuotaCallbacksWrapper(
145 blink::WebStorageQuotaCallbacks callbacks
) {
146 return new WebStorageQuotaDispatcherCallback(callbacks
);
149 void QuotaDispatcher::DidGrantStorageQuota(
152 int64 granted_quota
) {
153 Callback
* callback
= pending_quota_callbacks_
.Lookup(request_id
);
155 callback
->DidGrantStorageQuota(current_usage
, granted_quota
);
156 pending_quota_callbacks_
.Remove(request_id
);
159 void QuotaDispatcher::DidQueryStorageUsageAndQuota(
162 int64 current_quota
) {
163 Callback
* callback
= pending_quota_callbacks_
.Lookup(request_id
);
165 callback
->DidQueryStorageUsageAndQuota(current_usage
, current_quota
);
166 pending_quota_callbacks_
.Remove(request_id
);
169 void QuotaDispatcher::DidFail(
171 QuotaStatusCode error
) {
172 Callback
* callback
= pending_quota_callbacks_
.Lookup(request_id
);
174 callback
->DidFail(error
);
175 pending_quota_callbacks_
.Remove(request_id
);
178 COMPILE_ASSERT(int(blink::WebStorageQuotaTypeTemporary
) ==
179 int(storage::kStorageTypeTemporary
),
181 COMPILE_ASSERT(int(blink::WebStorageQuotaTypePersistent
) ==
182 int(storage::kStorageTypePersistent
),
185 COMPILE_ASSERT(int(blink::WebStorageQuotaErrorNotSupported
) ==
186 int(storage::kQuotaErrorNotSupported
),
188 COMPILE_ASSERT(int(blink::WebStorageQuotaErrorAbort
) ==
189 int(storage::kQuotaErrorAbort
),
192 } // namespace content