Home | History | Annotate | Download | only in webui
      1 // Copyright (c) 2012 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/browser/webui/url_data_manager.h"
      6 
      7 #include <vector>
      8 
      9 #include "base/bind.h"
     10 #include "base/lazy_instance.h"
     11 #include "base/memory/ref_counted_memory.h"
     12 #include "base/message_loop/message_loop.h"
     13 #include "base/strings/string_util.h"
     14 #include "base/synchronization/lock.h"
     15 #include "content/browser/resource_context_impl.h"
     16 #include "content/browser/webui/url_data_manager_backend.h"
     17 #include "content/browser/webui/url_data_source_impl.h"
     18 #include "content/browser/webui/web_ui_data_source_impl.h"
     19 #include "content/public/browser/browser_context.h"
     20 #include "content/public/browser/browser_thread.h"
     21 #include "content/public/browser/url_data_source.h"
     22 
     23 namespace content {
     24 namespace {
     25 
     26 const char kURLDataManagerKeyName[] = "url_data_manager";
     27 
     28 base::LazyInstance<base::Lock>::Leaky g_delete_lock = LAZY_INSTANCE_INITIALIZER;
     29 
     30 URLDataManager* GetFromBrowserContext(BrowserContext* context) {
     31   if (!context->GetUserData(kURLDataManagerKeyName)) {
     32     context->SetUserData(kURLDataManagerKeyName, new URLDataManager(context));
     33   }
     34   return static_cast<URLDataManager*>(
     35       context->GetUserData(kURLDataManagerKeyName));
     36 }
     37 
     38 // Invoked on the IO thread to do the actual adding of the DataSource.
     39 static void AddDataSourceOnIOThread(
     40     ResourceContext* resource_context,
     41     scoped_refptr<URLDataSourceImpl> data_source) {
     42   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
     43   GetURLDataManagerForResourceContext(resource_context)->AddDataSource(
     44       data_source.get());
     45 }
     46 
     47 }  // namespace
     48 
     49 // static
     50 URLDataManager::URLDataSources* URLDataManager::data_sources_ = NULL;
     51 
     52 URLDataManager::URLDataManager(BrowserContext* browser_context)
     53     : browser_context_(browser_context) {
     54 }
     55 
     56 URLDataManager::~URLDataManager() {
     57 }
     58 
     59 void URLDataManager::AddDataSource(URLDataSourceImpl* source) {
     60   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
     61   BrowserThread::PostTask(
     62       BrowserThread::IO, FROM_HERE,
     63       base::Bind(&AddDataSourceOnIOThread,
     64                  browser_context_->GetResourceContext(),
     65                  make_scoped_refptr(source)));
     66 }
     67 
     68 // static
     69 void URLDataManager::DeleteDataSources() {
     70   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
     71   URLDataSources sources;
     72   {
     73     base::AutoLock lock(g_delete_lock.Get());
     74     if (!data_sources_)
     75       return;
     76     data_sources_->swap(sources);
     77   }
     78   for (size_t i = 0; i < sources.size(); ++i)
     79     delete sources[i];
     80 }
     81 
     82 // static
     83 void URLDataManager::DeleteDataSource(const URLDataSourceImpl* data_source) {
     84   // Invoked when a DataSource is no longer referenced and needs to be deleted.
     85   if (BrowserThread::CurrentlyOn(BrowserThread::UI)) {
     86     // We're on the UI thread, delete right away.
     87     delete data_source;
     88     return;
     89   }
     90 
     91   // We're not on the UI thread, add the DataSource to the list of DataSources
     92   // to delete.
     93   bool schedule_delete = false;
     94   {
     95     base::AutoLock lock(g_delete_lock.Get());
     96     if (!data_sources_)
     97       data_sources_ = new URLDataSources();
     98     schedule_delete = data_sources_->empty();
     99     data_sources_->push_back(data_source);
    100   }
    101   if (schedule_delete) {
    102     // Schedule a task to delete the DataSource back on the UI thread.
    103     BrowserThread::PostTask(
    104         BrowserThread::UI, FROM_HERE,
    105         base::Bind(&URLDataManager::DeleteDataSources));
    106   }
    107 }
    108 
    109 // static
    110 void URLDataManager::AddDataSource(BrowserContext* browser_context,
    111                                    URLDataSource* source) {
    112   GetFromBrowserContext(browser_context)->
    113       AddDataSource(new URLDataSourceImpl(source->GetSource(), source));
    114 }
    115 
    116 // static
    117 void URLDataManager::AddWebUIDataSource(BrowserContext* browser_context,
    118                                         WebUIDataSource* source) {
    119   WebUIDataSourceImpl* impl = static_cast<WebUIDataSourceImpl*>(source);
    120   GetFromBrowserContext(browser_context)->AddDataSource(impl);
    121 }
    122 
    123 // static
    124 bool URLDataManager::IsScheduledForDeletion(
    125     const URLDataSourceImpl* data_source) {
    126   base::AutoLock lock(g_delete_lock.Get());
    127   if (!data_sources_)
    128     return false;
    129   return std::find(data_sources_->begin(), data_sources_->end(), data_source) !=
    130       data_sources_->end();
    131 }
    132 
    133 }  // namespace content
    134