Generate ax enums from idl.
[chromium-blink-merge.git] / content / browser / quota_dispatcher_host.cc
blob2351269cbaad21efc4dab9ba16d5b744a969e454
1 // Copyright 2013 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/browser/quota_dispatcher_host.h"
7 #include "base/bind.h"
8 #include "base/memory/weak_ptr.h"
9 #include "base/numerics/safe_conversions.h"
10 #include "content/common/quota_messages.h"
11 #include "content/public/browser/quota_permission_context.h"
12 #include "net/base/net_util.h"
13 #include "url/gurl.h"
14 #include "webkit/browser/quota/quota_manager.h"
16 using quota::QuotaClient;
17 using quota::QuotaManager;
18 using quota::QuotaStatusCode;
19 using quota::StorageType;
21 namespace content {
23 // Created one per request to carry the request's request_id around.
24 // Dispatches requests from renderer/worker to the QuotaManager and
25 // sends back the response to the renderer/worker.
26 class QuotaDispatcherHost::RequestDispatcher {
27 public:
28 RequestDispatcher(base::WeakPtr<QuotaDispatcherHost> dispatcher_host,
29 int request_id)
30 : dispatcher_host_(dispatcher_host),
31 render_process_id_(dispatcher_host->process_id_),
32 request_id_(request_id) {
33 dispatcher_host_->outstanding_requests_.AddWithID(this, request_id_);
35 virtual ~RequestDispatcher() {}
37 protected:
38 // Subclass must call this when it's done with the request.
39 void Completed() {
40 if (dispatcher_host_)
41 dispatcher_host_->outstanding_requests_.Remove(request_id_);
44 QuotaDispatcherHost* dispatcher_host() const {
45 return dispatcher_host_.get();
47 quota::QuotaManager* quota_manager() const {
48 return dispatcher_host_ ? dispatcher_host_->quota_manager_ : NULL;
50 QuotaPermissionContext* permission_context() const {
51 return dispatcher_host_ ?
52 dispatcher_host_->permission_context_.get() : NULL;
54 int render_process_id() const { return render_process_id_; }
55 int request_id() const { return request_id_; }
57 private:
58 base::WeakPtr<QuotaDispatcherHost> dispatcher_host_;
59 int render_process_id_;
60 int request_id_;
63 class QuotaDispatcherHost::QueryUsageAndQuotaDispatcher
64 : public RequestDispatcher {
65 public:
66 QueryUsageAndQuotaDispatcher(
67 base::WeakPtr<QuotaDispatcherHost> dispatcher_host,
68 int request_id)
69 : RequestDispatcher(dispatcher_host, request_id),
70 weak_factory_(this) {}
71 virtual ~QueryUsageAndQuotaDispatcher() {}
73 void QueryStorageUsageAndQuota(const GURL& origin, StorageType type) {
74 quota_manager()->GetUsageAndQuotaForWebApps(
75 origin, type,
76 base::Bind(&QueryUsageAndQuotaDispatcher::DidQueryStorageUsageAndQuota,
77 weak_factory_.GetWeakPtr()));
80 private:
81 void DidQueryStorageUsageAndQuota(
82 QuotaStatusCode status, int64 usage, int64 quota) {
83 if (!dispatcher_host())
84 return;
85 if (status != quota::kQuotaStatusOk) {
86 dispatcher_host()->Send(new QuotaMsg_DidFail(request_id(), status));
87 } else {
88 dispatcher_host()->Send(new QuotaMsg_DidQueryStorageUsageAndQuota(
89 request_id(), usage, quota));
91 Completed();
94 base::WeakPtrFactory<QueryUsageAndQuotaDispatcher> weak_factory_;
97 class QuotaDispatcherHost::RequestQuotaDispatcher
98 : public RequestDispatcher {
99 public:
100 typedef RequestQuotaDispatcher self_type;
102 RequestQuotaDispatcher(base::WeakPtr<QuotaDispatcherHost> dispatcher_host,
103 int request_id,
104 const GURL& origin,
105 StorageType type,
106 uint64 requested_quota,
107 int render_view_id)
108 : RequestDispatcher(dispatcher_host, request_id),
109 origin_(origin),
110 type_(type),
111 current_usage_(0),
112 current_quota_(0),
113 requested_quota_(0),
114 render_view_id_(render_view_id),
115 weak_factory_(this) {
116 // Convert the requested size from uint64 to int64 since the quota backend
117 // requires int64 values.
118 // TODO(nhiroki): The backend should accept uint64 values.
119 requested_quota_ = base::saturated_cast<int64>(requested_quota);
121 virtual ~RequestQuotaDispatcher() {}
123 void Start() {
124 DCHECK(dispatcher_host());
126 DCHECK(type_ == quota::kStorageTypeTemporary ||
127 type_ == quota::kStorageTypePersistent ||
128 type_ == quota::kStorageTypeSyncable);
129 if (type_ == quota::kStorageTypePersistent) {
130 quota_manager()->GetUsageAndQuotaForWebApps(
131 origin_, type_,
132 base::Bind(&self_type::DidGetPersistentUsageAndQuota,
133 weak_factory_.GetWeakPtr()));
134 } else {
135 quota_manager()->GetUsageAndQuotaForWebApps(
136 origin_, type_,
137 base::Bind(&self_type::DidGetTemporaryUsageAndQuota,
138 weak_factory_.GetWeakPtr()));
142 private:
143 void DidGetPersistentUsageAndQuota(QuotaStatusCode status,
144 int64 usage,
145 int64 quota) {
146 if (!dispatcher_host())
147 return;
148 if (status != quota::kQuotaStatusOk) {
149 DidFinish(status, 0, 0);
150 return;
153 if (quota_manager()->IsStorageUnlimited(origin_, type_) ||
154 requested_quota_ <= quota) {
155 // Seems like we can just let it go.
156 DidFinish(quota::kQuotaStatusOk, usage, requested_quota_);
157 return;
159 current_usage_ = usage;
160 current_quota_ = quota;
162 // Otherwise we need to consult with the permission context and
163 // possibly show an infobar.
164 DCHECK(permission_context());
165 permission_context()->RequestQuotaPermission(
166 origin_, type_, requested_quota_, render_process_id(), render_view_id_,
167 base::Bind(&self_type::DidGetPermissionResponse,
168 weak_factory_.GetWeakPtr()));
171 void DidGetTemporaryUsageAndQuota(QuotaStatusCode status,
172 int64 usage,
173 int64 quota) {
174 DidFinish(status, usage, std::min(requested_quota_, quota));
177 void DidGetPermissionResponse(
178 QuotaPermissionContext::QuotaPermissionResponse response) {
179 if (!dispatcher_host())
180 return;
181 if (response != QuotaPermissionContext::QUOTA_PERMISSION_RESPONSE_ALLOW) {
182 // User didn't allow the new quota. Just returning the current quota.
183 DidFinish(quota::kQuotaStatusOk, current_usage_, current_quota_);
184 return;
186 // Now we're allowed to set the new quota.
187 quota_manager()->SetPersistentHostQuota(
188 net::GetHostOrSpecFromURL(origin_), requested_quota_,
189 base::Bind(&self_type::DidSetHostQuota, weak_factory_.GetWeakPtr()));
192 void DidSetHostQuota(QuotaStatusCode status, int64 new_quota) {
193 DidFinish(status, current_usage_, new_quota);
196 void DidFinish(QuotaStatusCode status,
197 int64 usage,
198 int64 granted_quota) {
199 if (!dispatcher_host())
200 return;
201 DCHECK(dispatcher_host());
202 if (status != quota::kQuotaStatusOk) {
203 dispatcher_host()->Send(new QuotaMsg_DidFail(request_id(), status));
204 } else {
205 dispatcher_host()->Send(new QuotaMsg_DidGrantStorageQuota(
206 request_id(), usage, granted_quota));
208 Completed();
211 const GURL origin_;
212 const StorageType type_;
213 int64 current_usage_;
214 int64 current_quota_;
215 int64 requested_quota_;
216 const int render_view_id_;
217 base::WeakPtrFactory<self_type> weak_factory_;
220 QuotaDispatcherHost::QuotaDispatcherHost(
221 int process_id,
222 QuotaManager* quota_manager,
223 QuotaPermissionContext* permission_context)
224 : process_id_(process_id),
225 quota_manager_(quota_manager),
226 permission_context_(permission_context),
227 weak_factory_(this) {
230 bool QuotaDispatcherHost::OnMessageReceived(
231 const IPC::Message& message, bool* message_was_ok) {
232 *message_was_ok = true;
233 bool handled = true;
234 IPC_BEGIN_MESSAGE_MAP_EX(QuotaDispatcherHost, message, *message_was_ok)
235 IPC_MESSAGE_HANDLER(QuotaHostMsg_QueryStorageUsageAndQuota,
236 OnQueryStorageUsageAndQuota)
237 IPC_MESSAGE_HANDLER(QuotaHostMsg_RequestStorageQuota,
238 OnRequestStorageQuota)
239 IPC_MESSAGE_UNHANDLED(handled = false)
240 IPC_END_MESSAGE_MAP_EX()
241 return handled;
244 QuotaDispatcherHost::~QuotaDispatcherHost() {}
246 void QuotaDispatcherHost::OnQueryStorageUsageAndQuota(
247 int request_id,
248 const GURL& origin,
249 StorageType type) {
250 QueryUsageAndQuotaDispatcher* dispatcher = new QueryUsageAndQuotaDispatcher(
251 weak_factory_.GetWeakPtr(), request_id);
252 dispatcher->QueryStorageUsageAndQuota(origin, type);
255 void QuotaDispatcherHost::OnRequestStorageQuota(
256 int render_view_id,
257 int request_id,
258 const GURL& origin,
259 StorageType type,
260 uint64 requested_size) {
261 if (type != quota::kStorageTypeTemporary &&
262 type != quota::kStorageTypePersistent) {
263 // Unsupported storage types.
264 Send(new QuotaMsg_DidFail(request_id, quota::kQuotaErrorNotSupported));
265 return;
268 RequestQuotaDispatcher* dispatcher = new RequestQuotaDispatcher(
269 weak_factory_.GetWeakPtr(), request_id, origin, type,
270 requested_size, render_view_id);
271 dispatcher->Start();
274 } // namespace content