Home | History | Annotate | Download | only in child
      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 "url/gurl.h"
     17 
     18 using quota::QuotaStatusCode;
     19 using quota::StorageType;
     20 
     21 using blink::WebStorageQuotaCallbacks;
     22 using blink::WebStorageQuotaError;
     23 using blink::WebStorageQuotaType;
     24 
     25 using webkit_glue::WorkerTaskRunner;
     26 
     27 namespace content {
     28 
     29 static base::LazyInstance<base::ThreadLocalPointer<QuotaDispatcher> >::Leaky
     30     g_quota_dispatcher_tls = LAZY_INSTANCE_INITIALIZER;
     31 
     32 namespace {
     33 
     34 // QuotaDispatcher::Callback implementation for WebStorageQuotaCallbacks.
     35 class WebStorageQuotaDispatcherCallback : public QuotaDispatcher::Callback {
     36  public:
     37   WebStorageQuotaDispatcherCallback(blink::WebStorageQuotaCallbacks* callback)
     38       : callbacks_(callback) {
     39     DCHECK(callbacks_);
     40   }
     41   virtual ~WebStorageQuotaDispatcherCallback() {}
     42   virtual void DidQueryStorageUsageAndQuota(int64 usage, int64 quota) OVERRIDE {
     43     callbacks_->didQueryStorageUsageAndQuota(usage, quota);
     44   }
     45   virtual void DidGrantStorageQuota(int64 granted_quota) OVERRIDE {
     46     callbacks_->didGrantStorageQuota(granted_quota);
     47   }
     48   virtual void DidFail(quota::QuotaStatusCode error) OVERRIDE {
     49     callbacks_->didFail(static_cast<WebStorageQuotaError>(error));
     50   }
     51 
     52  private:
     53   // Not owned (self-destructed).
     54   blink::WebStorageQuotaCallbacks* callbacks_;
     55 };
     56 
     57 int CurrentWorkerId() {
     58   return WorkerTaskRunner::Instance()->CurrentWorkerId();
     59 }
     60 
     61 }  // namespace
     62 
     63 QuotaDispatcher::QuotaDispatcher(ThreadSafeSender* thread_safe_sender,
     64                                  QuotaMessageFilter* quota_message_filter)
     65     : thread_safe_sender_(thread_safe_sender),
     66       quota_message_filter_(quota_message_filter) {
     67   g_quota_dispatcher_tls.Pointer()->Set(this);
     68 }
     69 
     70 QuotaDispatcher::~QuotaDispatcher() {
     71   IDMap<Callback, IDMapOwnPointer>::iterator iter(&pending_quota_callbacks_);
     72   while (!iter.IsAtEnd()) {
     73     iter.GetCurrentValue()->DidFail(quota::kQuotaErrorAbort);
     74     iter.Advance();
     75   }
     76 
     77   g_quota_dispatcher_tls.Pointer()->Set(NULL);
     78 }
     79 
     80 QuotaDispatcher* QuotaDispatcher::ThreadSpecificInstance(
     81     ThreadSafeSender* thread_safe_sender,
     82     QuotaMessageFilter* quota_message_filter) {
     83   if (g_quota_dispatcher_tls.Pointer()->Get())
     84     return g_quota_dispatcher_tls.Pointer()->Get();
     85 
     86   QuotaDispatcher* dispatcher = new QuotaDispatcher(
     87       thread_safe_sender, quota_message_filter);
     88   if (WorkerTaskRunner::Instance()->CurrentWorkerId())
     89     WorkerTaskRunner::Instance()->AddStopObserver(dispatcher);
     90   return dispatcher;
     91 }
     92 
     93 void QuotaDispatcher::OnWorkerRunLoopStopped() {
     94   delete this;
     95 }
     96 
     97 void QuotaDispatcher::OnMessageReceived(const IPC::Message& msg) {
     98   bool handled = true;
     99   IPC_BEGIN_MESSAGE_MAP(QuotaDispatcher, msg)
    100     IPC_MESSAGE_HANDLER(QuotaMsg_DidGrantStorageQuota,
    101                         DidGrantStorageQuota)
    102     IPC_MESSAGE_HANDLER(QuotaMsg_DidQueryStorageUsageAndQuota,
    103                         DidQueryStorageUsageAndQuota);
    104     IPC_MESSAGE_HANDLER(QuotaMsg_DidFail, DidFail);
    105     IPC_MESSAGE_UNHANDLED(handled = false)
    106   IPC_END_MESSAGE_MAP()
    107   DCHECK(handled) << "Unhandled message:" << msg.type();
    108 }
    109 
    110 void QuotaDispatcher::QueryStorageUsageAndQuota(
    111     const GURL& origin_url,
    112     StorageType type,
    113     Callback* callback) {
    114   DCHECK(callback);
    115   int request_id = quota_message_filter_->GenerateRequestID(CurrentWorkerId());
    116   pending_quota_callbacks_.AddWithID(callback, request_id);
    117   thread_safe_sender_->Send(new QuotaHostMsg_QueryStorageUsageAndQuota(
    118       request_id, origin_url, type));
    119 }
    120 
    121 void QuotaDispatcher::RequestStorageQuota(
    122     int render_view_id,
    123     const GURL& origin_url,
    124     StorageType type,
    125     int64 requested_size,
    126     Callback* callback) {
    127   DCHECK(callback);
    128   DCHECK(CurrentWorkerId() == 0);
    129   int request_id = quota_message_filter_->GenerateRequestID(CurrentWorkerId());
    130   pending_quota_callbacks_.AddWithID(callback, request_id);
    131   thread_safe_sender_->Send(new QuotaHostMsg_RequestStorageQuota(
    132       render_view_id, request_id, origin_url, type, requested_size));
    133 }
    134 
    135 // static
    136 QuotaDispatcher::Callback*
    137 QuotaDispatcher::CreateWebStorageQuotaCallbacksWrapper(
    138     blink::WebStorageQuotaCallbacks* callbacks) {
    139   return new WebStorageQuotaDispatcherCallback(callbacks);
    140 }
    141 
    142 void QuotaDispatcher::DidGrantStorageQuota(
    143     int request_id,
    144     int64 granted_quota) {
    145   Callback* callback = pending_quota_callbacks_.Lookup(request_id);
    146   DCHECK(callback);
    147   callback->DidGrantStorageQuota(granted_quota);
    148   pending_quota_callbacks_.Remove(request_id);
    149 }
    150 
    151 void QuotaDispatcher::DidQueryStorageUsageAndQuota(
    152     int request_id,
    153     int64 current_usage,
    154     int64 current_quota) {
    155   Callback* callback = pending_quota_callbacks_.Lookup(request_id);
    156   DCHECK(callback);
    157   callback->DidQueryStorageUsageAndQuota(current_usage, current_quota);
    158   pending_quota_callbacks_.Remove(request_id);
    159 }
    160 
    161 void QuotaDispatcher::DidFail(
    162     int request_id,
    163     QuotaStatusCode error) {
    164   Callback* callback = pending_quota_callbacks_.Lookup(request_id);
    165   DCHECK(callback);
    166   callback->DidFail(error);
    167   pending_quota_callbacks_.Remove(request_id);
    168 }
    169 
    170 COMPILE_ASSERT(int(blink::WebStorageQuotaTypeTemporary) == \
    171                int(quota::kStorageTypeTemporary), mismatching_enums);
    172 COMPILE_ASSERT(int(blink::WebStorageQuotaTypePersistent) == \
    173                int(quota::kStorageTypePersistent), mismatching_enums);
    174 
    175 COMPILE_ASSERT(int(blink::WebStorageQuotaErrorNotSupported) == \
    176                int(quota::kQuotaErrorNotSupported), mismatching_enums);
    177 COMPILE_ASSERT(int(blink::WebStorageQuotaErrorAbort) == \
    178                int(quota::kQuotaErrorAbort), mismatching_enums);
    179 
    180 }  // namespace content
    181