• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
4 
5 #include "content/child/quota_dispatcher.h"
6 
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"
17 #include "url/gurl.h"
18 
19 using blink::WebStorageQuotaCallbacks;
20 using blink::WebStorageQuotaError;
21 using blink::WebStorageQuotaType;
22 using storage::QuotaStatusCode;
23 using storage::StorageType;
24 
25 namespace content {
26 
27 static base::LazyInstance<base::ThreadLocalPointer<QuotaDispatcher> >::Leaky
28     g_quota_dispatcher_tls = LAZY_INSTANCE_INITIALIZER;
29 
30 namespace {
31 
32 // QuotaDispatcher::Callback implementation for WebStorageQuotaCallbacks.
33 class WebStorageQuotaDispatcherCallback : public QuotaDispatcher::Callback {
34  public:
WebStorageQuotaDispatcherCallback(blink::WebStorageQuotaCallbacks callback)35   explicit WebStorageQuotaDispatcherCallback(
36       blink::WebStorageQuotaCallbacks callback)
37       : callbacks_(callback) {}
~WebStorageQuotaDispatcherCallback()38   virtual ~WebStorageQuotaDispatcherCallback() {}
39 
DidQueryStorageUsageAndQuota(int64 usage,int64 quota)40   virtual void DidQueryStorageUsageAndQuota(int64 usage, int64 quota) OVERRIDE {
41     callbacks_.didQueryStorageUsageAndQuota(usage, quota);
42   }
DidGrantStorageQuota(int64 usage,int64 granted_quota)43   virtual void DidGrantStorageQuota(int64 usage, int64 granted_quota) OVERRIDE {
44     callbacks_.didGrantStorageQuota(usage, granted_quota);
45   }
DidFail(storage::QuotaStatusCode error)46   virtual void DidFail(storage::QuotaStatusCode error) OVERRIDE {
47     callbacks_.didFail(static_cast<WebStorageQuotaError>(error));
48   }
49 
50  private:
51   blink::WebStorageQuotaCallbacks callbacks_;
52 
53   DISALLOW_COPY_AND_ASSIGN(WebStorageQuotaDispatcherCallback);
54 };
55 
CurrentWorkerId()56 int CurrentWorkerId() {
57   return WorkerTaskRunner::Instance()->CurrentWorkerId();
58 }
59 
60 }  // namespace
61 
QuotaDispatcher(ThreadSafeSender * thread_safe_sender,QuotaMessageFilter * quota_message_filter)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);
67 }
68 
~QuotaDispatcher()69 QuotaDispatcher::~QuotaDispatcher() {
70   IDMap<Callback, IDMapOwnPointer>::iterator iter(&pending_quota_callbacks_);
71   while (!iter.IsAtEnd()) {
72     iter.GetCurrentValue()->DidFail(storage::kQuotaErrorAbort);
73     iter.Advance();
74   }
75 
76   g_quota_dispatcher_tls.Pointer()->Set(NULL);
77 }
78 
ThreadSpecificInstance(ThreadSafeSender * thread_safe_sender,QuotaMessageFilter * quota_message_filter)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();
84 
85   QuotaDispatcher* dispatcher = new QuotaDispatcher(
86       thread_safe_sender, quota_message_filter);
87   if (WorkerTaskRunner::Instance()->CurrentWorkerId())
88     WorkerTaskRunner::Instance()->AddStopObserver(dispatcher);
89   return dispatcher;
90 }
91 
OnWorkerRunLoopStopped()92 void QuotaDispatcher::OnWorkerRunLoopStopped() {
93   delete this;
94 }
95 
OnMessageReceived(const IPC::Message & msg)96 void QuotaDispatcher::OnMessageReceived(const IPC::Message& msg) {
97   bool handled = true;
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();
107 }
108 
QueryStorageUsageAndQuota(const GURL & origin_url,StorageType type,Callback * callback)109 void QuotaDispatcher::QueryStorageUsageAndQuota(
110     const GURL& origin_url,
111     StorageType type,
112     Callback* callback) {
113   DCHECK(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));
118 }
119 
RequestStorageQuota(int render_view_id,const GURL & origin_url,StorageType type,uint64 requested_size,Callback * callback)120 void QuotaDispatcher::RequestStorageQuota(
121     int render_view_id,
122     const GURL& origin_url,
123     StorageType type,
124     uint64 requested_size,
125     Callback* callback) {
126   DCHECK(callback);
127   DCHECK(CurrentWorkerId() == 0);
128   int request_id = quota_message_filter_->GenerateRequestID(CurrentWorkerId());
129   pending_quota_callbacks_.AddWithID(callback, request_id);
130 
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));
140 }
141 
142 // static
143 QuotaDispatcher::Callback*
CreateWebStorageQuotaCallbacksWrapper(blink::WebStorageQuotaCallbacks callbacks)144 QuotaDispatcher::CreateWebStorageQuotaCallbacksWrapper(
145     blink::WebStorageQuotaCallbacks callbacks) {
146   return new WebStorageQuotaDispatcherCallback(callbacks);
147 }
148 
DidGrantStorageQuota(int request_id,int64 current_usage,int64 granted_quota)149 void QuotaDispatcher::DidGrantStorageQuota(
150     int request_id,
151     int64 current_usage,
152     int64 granted_quota) {
153   Callback* callback = pending_quota_callbacks_.Lookup(request_id);
154   DCHECK(callback);
155   callback->DidGrantStorageQuota(current_usage, granted_quota);
156   pending_quota_callbacks_.Remove(request_id);
157 }
158 
DidQueryStorageUsageAndQuota(int request_id,int64 current_usage,int64 current_quota)159 void QuotaDispatcher::DidQueryStorageUsageAndQuota(
160     int request_id,
161     int64 current_usage,
162     int64 current_quota) {
163   Callback* callback = pending_quota_callbacks_.Lookup(request_id);
164   DCHECK(callback);
165   callback->DidQueryStorageUsageAndQuota(current_usage, current_quota);
166   pending_quota_callbacks_.Remove(request_id);
167 }
168 
DidFail(int request_id,QuotaStatusCode error)169 void QuotaDispatcher::DidFail(
170     int request_id,
171     QuotaStatusCode error) {
172   Callback* callback = pending_quota_callbacks_.Lookup(request_id);
173   DCHECK(callback);
174   callback->DidFail(error);
175   pending_quota_callbacks_.Remove(request_id);
176 }
177 
178 COMPILE_ASSERT(int(blink::WebStorageQuotaTypeTemporary) ==
179                    int(storage::kStorageTypeTemporary),
180                mismatching_enums);
181 COMPILE_ASSERT(int(blink::WebStorageQuotaTypePersistent) ==
182                    int(storage::kStorageTypePersistent),
183                mismatching_enums);
184 
185 COMPILE_ASSERT(int(blink::WebStorageQuotaErrorNotSupported) ==
186                    int(storage::kQuotaErrorNotSupported),
187                mismatching_enums);
188 COMPILE_ASSERT(int(blink::WebStorageQuotaErrorAbort) ==
189                    int(storage::kQuotaErrorAbort),
190                mismatching_enums);
191 
192 }  // namespace content
193