| Index: chrome/browser/browsing_data_filesystem_helper.cc | 
| diff --git a/chrome/browser/browsing_data_filesystem_helper.cc b/chrome/browser/browsing_data_filesystem_helper.cc | 
| new file mode 100644 | 
| index 0000000000000000000000000000000000000000..619147aa13ee3409cb3b14bd2e8d53f2b286f2d2 | 
| --- /dev/null | 
| +++ b/chrome/browser/browsing_data_filesystem_helper.cc | 
| @@ -0,0 +1,297 @@ | 
| +// Copyright (c) 2011 The Chromium Authors. All rights reserved. | 
| +// Use of this source code is governed by a BSD-style license that can be | 
| +// found in the LICENSE file. | 
| + | 
| +#include "chrome/browser/browsing_data_filesystem_helper.h" | 
| + | 
| +#include "base/file_util.h" | 
| +#include "base/memory/scoped_ptr.h" | 
| +#include "base/message_loop.h" | 
| +#include "base/string_util.h" | 
| +#include "base/utf_string_conversions.h" | 
| +#include "chrome/browser/profiles/profile.h" | 
| +#include "third_party/WebKit/Source/WebKit/chromium/public/WebCString.h" | 
| +#include "third_party/WebKit/Source/WebKit/chromium/public/WebSecurityOrigin.h" | 
| +#include "third_party/WebKit/Source/WebKit/chromium/public/WebString.h" | 
| +#include "content/browser/browser_thread.h" | 
| +#include "content/browser/in_process_webkit/webkit_context.h" | 
| +#include "webkit/glue/webkit_glue.h" | 
| + | 
| +#include "webkit/fileapi/file_system_context.h" | 
| +#include "webkit/fileapi/file_system_types.h" | 
| +#include "webkit/fileapi/sandbox_mount_point_provider.h" | 
| + | 
| +using WebKit::WebSecurityOrigin; | 
| + | 
| +namespace { | 
| + | 
| +class BrowsingDataFilesystemHelperImpl : public BrowsingDataFilesystemHelper { | 
| + public: | 
| +  explicit BrowsingDataFilesystemHelperImpl(Profile* profile); | 
| + | 
| +  virtual void StartFetching( | 
| +      Callback1<const std::vector<FilesystemInfo>& >::Type* callback); | 
| +  virtual void CancelNotification(); | 
| +  virtual void DeleteFilesystemOrigin(const GURL& origin); | 
| + | 
| + private: | 
| +  virtual ~BrowsingDataFilesystemHelperImpl(); | 
| + | 
| +  // Enumerates all filesystem files in the FILE thread. | 
| +  void FetchFilesystemInfoInFileThread(); | 
| +  // Notifies the completion callback in the UI thread. | 
| +  void NotifyInUIThread(); | 
| +  // Delete data for an origin on the FILE thread. | 
| +  void DeleteFilesystemOriginInFileThread(const GURL& origin); | 
| + | 
| +  Profile* profile_; | 
| + | 
| +  // This only mutates in the FILE thread. | 
| +  std::vector<FilesystemInfo> filesystem_info_; | 
| + | 
| +  // This only mutates on the UI thread. | 
| +  scoped_ptr<Callback1<const std::vector<FilesystemInfo>& >::Type > | 
| +      completion_callback_; | 
| + | 
| +  // Indicates whether or not we're currently fetching information: | 
| +  // it's true when StartFetching() is called in the UI thread, and it's reset | 
| +  // after we notified the callback in the UI thread. | 
| +  // This only mutates on the UI thread. | 
| +  bool is_fetching_; | 
| + | 
| +  DISALLOW_COPY_AND_ASSIGN(BrowsingDataFilesystemHelperImpl); | 
| +}; | 
| + | 
| +BrowsingDataFilesystemHelperImpl::BrowsingDataFilesystemHelperImpl( | 
| +    Profile* profile) | 
| +    : profile_(profile), | 
| +      completion_callback_(NULL), | 
| +      is_fetching_(false) { | 
| +  DCHECK(profile_); | 
| +} | 
| + | 
| +BrowsingDataFilesystemHelperImpl::~BrowsingDataFilesystemHelperImpl() { | 
| +} | 
| + | 
| +void BrowsingDataFilesystemHelperImpl::StartFetching( | 
| +    Callback1<const std::vector<FilesystemInfo>& >::Type* callback) { | 
| +  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 
| +  DCHECK(!is_fetching_); | 
| +  DCHECK(callback); | 
| +  is_fetching_ = true; | 
| +  completion_callback_.reset(callback); | 
| +  BrowserThread::PostTask( | 
| +      BrowserThread::FILE, FROM_HERE, | 
| +      NewRunnableMethod( | 
| +          this, | 
| +          &BrowsingDataFilesystemHelperImpl:: | 
| +              FetchFilesystemInfoInFileThread)); | 
| +} | 
| + | 
| +void BrowsingDataFilesystemHelperImpl::CancelNotification() { | 
| +  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 
| +  completion_callback_.reset(NULL); | 
| +} | 
| + | 
| +void BrowsingDataFilesystemHelperImpl::DeleteFilesystemOrigin( | 
| +    const GURL& origin) { | 
| +  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 
| +  BrowserThread::PostTask( | 
| +      BrowserThread::FILE, FROM_HERE, | 
| +       NewRunnableMethod( | 
| +           this, | 
| +           &BrowsingDataFilesystemHelperImpl:: | 
| +               DeleteFilesystemOriginInFileThread, | 
| +           origin)); | 
| +} | 
| + | 
| +void BrowsingDataFilesystemHelperImpl::FetchFilesystemInfoInFileThread() { | 
| +  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 
| +  fileapi::SandboxMountPointProvider::OriginEnumerator* origin_enumerator = | 
| +      profile_->GetFileSystemContext()->path_manager()->sandbox_provider()-> | 
| +          CreateOriginEnumerator(); | 
| + | 
| +  GURL current; | 
| +  while (!(current = origin_enumerator->Next()).is_empty()) { | 
| +    if (current.SchemeIs(chrome::kExtensionScheme)) { | 
| +      // Extension state is not considered browsing data. | 
| +      continue; | 
| +    } | 
| +    filesystem_info_.push_back( | 
| +        FilesystemInfo( | 
| +            current.scheme(), | 
| +            current.host(), | 
| +            current.port(), | 
| +            current, | 
| +            origin_enumerator->HasFileSystemType( | 
| +                fileapi::kFileSystemTypePersistent), | 
| +            origin_enumerator->HasFileSystemType( | 
| +                fileapi::kFileSystemTypeTemporary))); | 
| +  } | 
| + | 
| +  BrowserThread::PostTask( | 
| +      BrowserThread::UI, FROM_HERE, | 
| +      NewRunnableMethod( | 
| +          this, &BrowsingDataFilesystemHelperImpl::NotifyInUIThread)); | 
| +} | 
| + | 
| +void BrowsingDataFilesystemHelperImpl::NotifyInUIThread() { | 
| +  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 
| +  DCHECK(is_fetching_); | 
| +  // Note: completion_callback_ mutates only in the UI thread, so it's safe to | 
| +  // test it here. | 
| +  if (completion_callback_ != NULL) { | 
| +    completion_callback_->Run(filesystem_info_); | 
| +    completion_callback_.reset(); | 
| +  } | 
| +  is_fetching_ = false; | 
| +} | 
| + | 
| +void BrowsingDataFilesystemHelperImpl::DeleteFilesystemOriginInFileThread( | 
| +    const GURL& origin) { | 
| +  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 
| +  fileapi::FileSystemContext* context = profile_->GetFileSystemContext(); | 
| +  context->DeleteDataForOriginOnFileThread(origin); | 
| +} | 
| + | 
| +}  // namespace | 
| + | 
| +BrowsingDataFilesystemHelper::FilesystemInfo::FilesystemInfo( | 
| +    const std::string& protocol, | 
| +    const std::string& host, | 
| +    const std::string& port, | 
| +    const GURL& origin, | 
| +    bool has_persistent, | 
| +    bool has_temporary) | 
| +    : protocol(protocol), | 
| +      host(host), | 
| +      port(port), | 
| +      origin(origin), | 
| +      has_persistent(has_persistent), | 
| +      has_temporary(has_temporary) { | 
| +} | 
| + | 
| +BrowsingDataFilesystemHelper::FilesystemInfo::~FilesystemInfo() {} | 
| + | 
| +// static | 
| +BrowsingDataFilesystemHelper* BrowsingDataFilesystemHelper::Create( | 
| +    Profile* profile) { | 
| +  return new BrowsingDataFilesystemHelperImpl(profile); | 
| +} | 
| + | 
| +CannedBrowsingDataFilesystemHelper:: | 
| +PendingFilesystemInfo::PendingFilesystemInfo() { | 
| +} | 
| + | 
| +CannedBrowsingDataFilesystemHelper:: | 
| +PendingFilesystemInfo::PendingFilesystemInfo(const GURL& origin, | 
| +                                             const fileapi::FileSystemType type) | 
| +    : origin(origin), | 
| +      type(type) { | 
| +} | 
| + | 
| +CannedBrowsingDataFilesystemHelper:: | 
| +PendingFilesystemInfo::~PendingFilesystemInfo() { | 
| +} | 
| + | 
| +CannedBrowsingDataFilesystemHelper::CannedBrowsingDataFilesystemHelper( | 
| +    Profile* profile) | 
| +    : profile_(profile), | 
| +      completion_callback_(NULL), | 
| +      is_fetching_(false) { | 
| +  DCHECK(profile); | 
| +} | 
| + | 
| +CannedBrowsingDataFilesystemHelper* | 
| +    CannedBrowsingDataFilesystemHelper::Clone() { | 
| +  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 
| +  CannedBrowsingDataFilesystemHelper* clone = | 
| +      new CannedBrowsingDataFilesystemHelper(profile_); | 
| + | 
| +  base::AutoLock auto_lock(lock_); | 
| +  clone->pending_filesystem_info_ = pending_filesystem_info_; | 
| +  clone->filesystem_info_ = filesystem_info_; | 
| +  return clone; | 
| +} | 
| + | 
| +void CannedBrowsingDataFilesystemHelper::AddFilesystem( | 
| +    const GURL& origin, const fileapi::FileSystemType type) { | 
| +  base::AutoLock auto_lock(lock_); | 
| +  pending_filesystem_info_.push_back(PendingFilesystemInfo(origin, type)); | 
| +} | 
| + | 
| +void CannedBrowsingDataFilesystemHelper::Reset() { | 
| +  base::AutoLock auto_lock(lock_); | 
| +  filesystem_info_.clear(); | 
| +  pending_filesystem_info_.clear(); | 
| +} | 
| + | 
| +bool CannedBrowsingDataFilesystemHelper::empty() const { | 
| +  base::AutoLock auto_lock(lock_); | 
| +  return filesystem_info_.empty() && pending_filesystem_info_.empty(); | 
| +} | 
| + | 
| +void CannedBrowsingDataFilesystemHelper::StartFetching( | 
| +    Callback1<const std::vector<FilesystemInfo>& >::Type* callback) { | 
| +  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 
| +  DCHECK(!is_fetching_); | 
| +  DCHECK(callback); | 
| +  is_fetching_ = true; | 
| +  completion_callback_.reset(callback); | 
| +  BrowserThread::PostTask(BrowserThread::WEBKIT, FROM_HERE, NewRunnableMethod( | 
| +      this, | 
| +      &CannedBrowsingDataFilesystemHelper::ConvertPendingInfoInWebKitThread)); | 
| +} | 
| + | 
| +CannedBrowsingDataFilesystemHelper::~CannedBrowsingDataFilesystemHelper() {} | 
| + | 
| +void CannedBrowsingDataFilesystemHelper::ConvertPendingInfoInWebKitThread() { | 
| +  base::AutoLock auto_lock(lock_); | 
| +  for (std::vector<PendingFilesystemInfo>::const_iterator | 
| +       info = pending_filesystem_info_.begin(); | 
| +       info != pending_filesystem_info_.end(); ++info) { | 
| +    bool duplicate = false; | 
| +    for (std::vector<FilesystemInfo>::iterator | 
| +             filesystem = filesystem_info_.begin(); | 
| +         filesystem != filesystem_info_.end(); | 
| +         ++filesystem) { | 
| +      if (filesystem->origin == info->origin) { | 
| +        if (info->type == fileapi::kFileSystemTypePersistent) { | 
| +          filesystem->has_persistent = true; | 
| +        } else { | 
| +          filesystem->has_temporary = true; | 
| +        } | 
| +        duplicate = true; | 
| +        break; | 
| +      } | 
| +    } | 
| +    if (duplicate) | 
| +      continue; | 
| + | 
| +    filesystem_info_.push_back(FilesystemInfo( | 
| +        info->origin.scheme(), | 
| +        info->origin.host(), | 
| +        info->origin.port(), | 
| +        info->origin, | 
| +        (info->type == fileapi::kFileSystemTypePersistent), | 
| +        (info->type == fileapi::kFileSystemTypeTemporary))); | 
| +  } | 
| +  pending_filesystem_info_.clear(); | 
| + | 
| +  BrowserThread::PostTask( | 
| +      BrowserThread::UI, FROM_HERE, | 
| +      NewRunnableMethod( | 
| +          this, &CannedBrowsingDataFilesystemHelper::NotifyInUIThread)); | 
| +} | 
| + | 
| +void CannedBrowsingDataFilesystemHelper::NotifyInUIThread() { | 
| +  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 
| +  DCHECK(is_fetching_); | 
| +  // Note: completion_callback_ mutates only in the UI thread, so it's safe to | 
| +  // test it here. | 
| +  if (completion_callback_ != NULL) { | 
| +    completion_callback_->Run(filesystem_info_); | 
| +    completion_callback_.reset(); | 
| +  } | 
| +  is_fetching_ = false; | 
| +} | 
|  |