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/quota_message_filter.h"
11 #include "content/child/thread_safe_sender.h"
12 #include "content/common/quota_messages.h"
13 #include "third_party/WebKit/public/platform/WebStorageQuotaCallbacks.h"
14 #include "third_party/WebKit/public/platform/WebStorageQuotaType.h"
15 #include "third_party/WebKit/public/web/WebUserGestureIndicator.h"
18 using blink::WebStorageQuotaCallbacks
;
19 using blink::WebStorageQuotaError
;
20 using blink::WebStorageQuotaType
;
21 using storage::QuotaStatusCode
;
22 using storage::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 ~WebStorageQuotaDispatcherCallback() override
{}
39 void DidQueryStorageUsageAndQuota(int64 usage
, int64 quota
) override
{
40 callbacks_
.didQueryStorageUsageAndQuota(usage
, quota
);
42 void DidGrantStorageQuota(int64 usage
, int64 granted_quota
) override
{
43 callbacks_
.didGrantStorageQuota(usage
, granted_quota
);
45 void DidFail(storage::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 WorkerThread::GetCurrentId();
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(storage::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 (WorkerThread::GetCurrentId())
87 WorkerThread::AddObserver(dispatcher
);
91 void QuotaDispatcher::WillStopCurrentWorkerThread() {
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
);
130 StorageQuotaParams params
;
131 params
.render_view_id
= render_view_id
;
132 params
.request_id
= request_id
;
133 params
.origin_url
= origin_url
;
134 params
.storage_type
= type
;
135 params
.requested_size
= requested_size
;
136 params
.user_gesture
=
137 blink::WebUserGestureIndicator::isProcessingUserGesture();
138 thread_safe_sender_
->Send(new QuotaHostMsg_RequestStorageQuota(params
));
142 QuotaDispatcher::Callback
*
143 QuotaDispatcher::CreateWebStorageQuotaCallbacksWrapper(
144 blink::WebStorageQuotaCallbacks callbacks
) {
145 return new WebStorageQuotaDispatcherCallback(callbacks
);
148 void QuotaDispatcher::DidGrantStorageQuota(
151 int64 granted_quota
) {
152 Callback
* callback
= pending_quota_callbacks_
.Lookup(request_id
);
154 callback
->DidGrantStorageQuota(current_usage
, granted_quota
);
155 pending_quota_callbacks_
.Remove(request_id
);
158 void QuotaDispatcher::DidQueryStorageUsageAndQuota(
161 int64 current_quota
) {
162 Callback
* callback
= pending_quota_callbacks_
.Lookup(request_id
);
164 callback
->DidQueryStorageUsageAndQuota(current_usage
, current_quota
);
165 pending_quota_callbacks_
.Remove(request_id
);
168 void QuotaDispatcher::DidFail(
170 QuotaStatusCode error
) {
171 Callback
* callback
= pending_quota_callbacks_
.Lookup(request_id
);
173 callback
->DidFail(error
);
174 pending_quota_callbacks_
.Remove(request_id
);
177 static_assert(int(blink::WebStorageQuotaTypeTemporary
) ==
178 int(storage::kStorageTypeTemporary
),
179 "mismatching enums: kStorageTypeTemporary");
180 static_assert(int(blink::WebStorageQuotaTypePersistent
) ==
181 int(storage::kStorageTypePersistent
),
182 "mismatching enums: kStorageTypePersistent");
184 static_assert(int(blink::WebStorageQuotaErrorNotSupported
) ==
185 int(storage::kQuotaErrorNotSupported
),
186 "mismatching enums: kQuotaErrorNotSupported");
187 static_assert(int(blink::WebStorageQuotaErrorAbort
) ==
188 int(storage::kQuotaErrorAbort
),
189 "mismatching enums: kQuotaErrorAbort");
191 } // namespace content