root/chrome/browser/local_discovery/storage/privet_filesystem_operations.cc

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. weak_factory_
  2. GetFileInfo
  3. ReadDirectory
  4. RemoveOperation
  5. RemoveAllOperations
  6. weak_factory_
  7. Start
  8. OnGotDeviceDescription
  9. OnGotPrivetHTTP
  10. callback_
  11. Start
  12. PrivetFileSystemResolved
  13. OnStorageListResult
  14. SignalError
  15. TriggerCallbackAndDestroy
  16. callback_
  17. Start
  18. PrivetFileSystemResolved
  19. OnStorageListResult
  20. SignalError
  21. TriggerCallbackAndDestroy

// Copyright 2014 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/local_discovery/storage/privet_filesystem_operations.h"

#include "chrome/browser/local_discovery/storage/privet_filesystem_constants.h"

namespace local_discovery {

PrivetFileSystemOperationFactory::PrivetFileSystemOperationFactory(
    content::BrowserContext* browser_context)
    : browser_context_(browser_context), weak_factory_(this) {}

PrivetFileSystemOperationFactory::~PrivetFileSystemOperationFactory() {
  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
  RemoveAllOperations();
}

void PrivetFileSystemOperationFactory::GetFileInfo(
    const fileapi::FileSystemURL& url,
    const fileapi::AsyncFileUtil::GetFileInfoCallback& callback) {
  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
  PrivetFileSystemAsyncOperation* operation =
      new PrivetFileSystemDetailsOperation(
          url.path(), browser_context_, this, &attribute_cache_, callback);
  async_operations_.insert(operation);
  operation->Start();
}

void PrivetFileSystemOperationFactory::ReadDirectory(
    const fileapi::FileSystemURL& url,
    const fileapi::AsyncFileUtil::ReadDirectoryCallback& callback) {
  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
  PrivetFileSystemAsyncOperation* operation = new PrivetFileSystemListOperation(
      url.path(), browser_context_, this, &attribute_cache_, callback);
  async_operations_.insert(operation);
  operation->Start();
}

void PrivetFileSystemOperationFactory::RemoveOperation(
    PrivetFileSystemAsyncOperation* operation) {
  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
  async_operations_.erase(operation);
  delete operation;
}

void PrivetFileSystemOperationFactory::RemoveAllOperations() {
  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
  STLDeleteElements(&async_operations_);
}

PrivetFileSystemAsyncOperationUtil::PrivetFileSystemAsyncOperationUtil(
    const base::FilePath& full_path,
    content::BrowserContext* browser_context,
    Delegate* delegate)
    : parsed_path_(full_path),
      browser_context_(browser_context),
      delegate_(delegate),
      weak_factory_(this) {
  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
}

PrivetFileSystemAsyncOperationUtil::~PrivetFileSystemAsyncOperationUtil() {
  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
}

void PrivetFileSystemAsyncOperationUtil::Start() {
  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
  request_context_ = browser_context_->GetRequestContext();
  service_discovery_client_ = ServiceDiscoverySharedClient::GetInstance();
  privet_device_resolver_.reset(new PrivetDeviceResolver(
      service_discovery_client_.get(),
      parsed_path_.service_name,
      base::Bind(
          &PrivetFileSystemAsyncOperationUtil::OnGotDeviceDescription,
          base::Unretained(this))));
  privet_device_resolver_->Start();
}

void PrivetFileSystemAsyncOperationUtil::OnGotDeviceDescription(
    bool success, const DeviceDescription& device_description) {
  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
  if (!success) {
    delegate_->PrivetFileSystemResolved(NULL, parsed_path_.path);
    return;
  }

  privet_async_factory_ = PrivetHTTPAsynchronousFactory::CreateInstance(
      service_discovery_client_.get(),
      request_context_.get());
  privet_http_resolution_ = privet_async_factory_->CreatePrivetHTTP(
      parsed_path_.service_name,
      device_description.address,
      base::Bind(&PrivetFileSystemAsyncOperationUtil::OnGotPrivetHTTP,
                 base::Unretained(this)));
  privet_http_resolution_->Start();
}

void PrivetFileSystemAsyncOperationUtil::OnGotPrivetHTTP(
    scoped_ptr<PrivetHTTPClient> privet_http_client) {
  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
  privet_client_ = privet_http_client.Pass();
  delegate_->PrivetFileSystemResolved(privet_client_.get(),
                                      parsed_path_.path);
}

PrivetFileSystemListOperation::PrivetFileSystemListOperation(
    const base::FilePath& full_path,
    content::BrowserContext* browser_context,
    PrivetFileSystemAsyncOperationContainer* container,
    PrivetFileSystemAttributeCache* attribute_cache,
    const fileapi::AsyncFileUtil::ReadDirectoryCallback& callback)
    : core_(full_path, browser_context, this),
      full_path_(full_path),
      container_(container),
      attribute_cache_(attribute_cache),
      callback_(callback) {
  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
}

PrivetFileSystemListOperation::~PrivetFileSystemListOperation() {
  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
}

void PrivetFileSystemListOperation::Start() {
  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
  core_.Start();
}

void PrivetFileSystemListOperation::PrivetFileSystemResolved(
    PrivetHTTPClient* http_client,
    const std::string& path) {
  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
  if (!http_client) {
    SignalError();
    return;
  }

  list_operation_ = http_client->CreateStorageListOperation(
      path,
      base::Bind(&PrivetFileSystemListOperation::OnStorageListResult,
                 base::Unretained(this)));
    list_operation_->Start();
}

void PrivetFileSystemListOperation::OnStorageListResult(
    const base::DictionaryValue* value) {
  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
  list_operation_.reset();

  if (!value) {
    SignalError();
    return;
  }

  attribute_cache_->AddFileInfoFromJSON(full_path_, value);

  fileapi::AsyncFileUtil::EntryList entry_list;

  const base::ListValue* entries;
  if (!value->GetList(kPrivetListEntries, &entries)) {
    SignalError();
    return;
  }

  for (size_t i = 0; i < entries->GetSize(); i++) {
    const base::DictionaryValue* entry_value;
    if (!entries->GetDictionary(i, &entry_value)) {
      SignalError();
      return;
    }

    std::string name;
    std::string type;
    int size = 0;

    entry_value->GetString(kPrivetListKeyName, &name);
    entry_value->GetString(kPrivetListKeyType, &type);
    entry_value->GetInteger(kPrivetListKeySize, &size);

    fileapi::DirectoryEntry entry(
        name,
        (type == kPrivetListTypeDir) ?
        fileapi::DirectoryEntry::DIRECTORY : fileapi::DirectoryEntry::FILE,
        size,
        base::Time() /* TODO(noamsml) */);

    entry_list.push_back(entry);
  }

  TriggerCallbackAndDestroy(base::File::FILE_OK, entry_list, false);
}

void PrivetFileSystemListOperation::SignalError() {
  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
  TriggerCallbackAndDestroy(base::File::FILE_ERROR_FAILED,
                            fileapi::AsyncFileUtil::EntryList(),
                            false);
}

void PrivetFileSystemListOperation::TriggerCallbackAndDestroy(
    base::File::Error result,
    const fileapi::AsyncFileUtil::EntryList& file_list,
    bool has_more) {
  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
  content::BrowserThread::PostTask(
      content::BrowserThread::IO,
      FROM_HERE,
      base::Bind(callback_, result, file_list, has_more));
  container_->RemoveOperation(this);
}

PrivetFileSystemDetailsOperation::PrivetFileSystemDetailsOperation(
    const base::FilePath& full_path,
    content::BrowserContext* browser_context,
    PrivetFileSystemAsyncOperationContainer* container,
    PrivetFileSystemAttributeCache* attribute_cache,
    const fileapi::AsyncFileUtil::GetFileInfoCallback& callback)
    : core_(full_path, browser_context, this),
      full_path_(full_path),
      container_(container),
      attribute_cache_(attribute_cache),
      callback_(callback) {
  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
}

PrivetFileSystemDetailsOperation::~PrivetFileSystemDetailsOperation() {
  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
}

void PrivetFileSystemDetailsOperation::Start() {
  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
  const base::File::Info* info = attribute_cache_->GetFileInfo(full_path_);
  if (info) {
    TriggerCallbackAndDestroy(base::File::FILE_OK, *info);
    return;
  }

  core_.Start();
}

void PrivetFileSystemDetailsOperation::PrivetFileSystemResolved(
    PrivetHTTPClient* http_client,
    const std::string& path) {
  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
  if (!http_client) {
    SignalError();
    return;
  }

  list_operation_ = http_client->CreateStorageListOperation(
      path,
      base::Bind(&PrivetFileSystemDetailsOperation::OnStorageListResult,
                 base::Unretained(this)));
  list_operation_->Start();
}

void PrivetFileSystemDetailsOperation::OnStorageListResult(
    const base::DictionaryValue* value) {
  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
  list_operation_.reset();

  attribute_cache_->AddFileInfoFromJSON(full_path_, value);
  const base::File::Info* info = attribute_cache_->GetFileInfo(full_path_);

  if (info) {
    TriggerCallbackAndDestroy(base::File::FILE_OK, *info);
  } else {
    SignalError();
  }
}

void PrivetFileSystemDetailsOperation::SignalError() {
  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
  TriggerCallbackAndDestroy(base::File::FILE_ERROR_FAILED, base::File::Info());
}

void PrivetFileSystemDetailsOperation::TriggerCallbackAndDestroy(
    base::File::Error result,
    const base::File::Info& info) {
  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
  content::BrowserThread::PostTask(content::BrowserThread::IO,
                                   FROM_HERE,
                                   base::Bind(callback_, result, info));
  container_->RemoveOperation(this);
}

}  // namespace local_discovery

/* [<][>][^][v][top][bottom][index][help] */