blob: 67e54bb4b92f636046e02328540b79800d4e6db1 [file] [log] [blame] [edit]
// Copyright (c) 2012 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/chromeos/gdata/drive_task_executor.h"
#include <string>
#include <vector>
#include "base/json/json_writer.h"
#include "base/string_util.h"
#include "chrome/browser/chromeos/extensions/file_browser_private_api.h"
#include "chrome/browser/chromeos/gdata/drive.pb.h"
#include "chrome/browser/chromeos/gdata/drive_service_interface.h"
#include "chrome/browser/chromeos/gdata/drive_system_service.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_finder.h"
#include "chrome/browser/ui/browser_tabstrip.h"
#include "chrome/browser/ui/browser_window.h"
#include "content/public/browser/browser_thread.h"
#include "webkit/fileapi/file_system_types.h"
#include "webkit/fileapi/file_system_url.h"
#include "webkit/fileapi/file_system_util.h"
namespace gdata {
using file_handler_util::FileTaskExecutor;
DriveTaskExecutor::DriveTaskExecutor(Profile* profile,
const std::string& app_id,
const std::string& action_id)
: file_handler_util::FileTaskExecutor(profile, app_id),
action_id_(action_id),
current_index_(0) {
DCHECK("open-with" == action_id_);
}
DriveTaskExecutor::~DriveTaskExecutor() {
}
bool DriveTaskExecutor::ExecuteAndNotify(
const std::vector<GURL>& file_urls,
const file_handler_util::FileTaskFinishedCallback& done) {
std::vector<FilePath> raw_paths;
for (std::vector<GURL>::const_iterator iter = file_urls.begin();
iter != file_urls.end(); ++iter) {
fileapi::FileSystemURL url(*iter);
if (!url.is_valid() || url.type() != fileapi::kFileSystemTypeDrive)
return false;
raw_paths.push_back(url.virtual_path());
}
DriveSystemService* system_service =
DriveSystemServiceFactory::GetForProfile(profile());
DCHECK(current_index_ == 0);
if (!system_service || !system_service->file_system())
return false;
DriveFileSystemInterface* file_system = system_service->file_system();
// Reset the index, so we know when we're done.
current_index_ = raw_paths.size();
for (std::vector<FilePath>::const_iterator iter = raw_paths.begin();
iter != raw_paths.end(); ++iter) {
file_system->GetEntryInfoByPath(
*iter,
base::Bind(&DriveTaskExecutor::OnFileEntryFetched, this));
}
return true;
}
void DriveTaskExecutor::OnFileEntryFetched(
DriveFileError error,
scoped_ptr<DriveEntryProto> entry_proto) {
// If we aborted, then this will be zero.
if (!current_index_)
return;
DriveSystemService* system_service =
DriveSystemServiceFactory::GetForProfile(profile());
// Here, we are only interested in files.
if (entry_proto.get() && !entry_proto->has_file_specific_info())
error = DRIVE_FILE_ERROR_NOT_FOUND;
if (!system_service || error != DRIVE_FILE_OK) {
Done(false);
return;
}
DriveServiceInterface* drive_service =
system_service->drive_service();
// Send off a request for the drive service to authorize the apps for the
// current document entry for this document so we can get the
// open-with-<app_id> urls from the document entry.
drive_service->AuthorizeApp(
GURL(entry_proto->edit_url()),
extension_id(), // really app_id
base::Bind(&DriveTaskExecutor::OnAppAuthorized,
this,
entry_proto->resource_id()));
}
void DriveTaskExecutor::OnAppAuthorized(
const std::string& resource_id,
GDataErrorCode error,
scoped_ptr<base::Value> feed_data) {
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
// If we aborted, then this will be zero.
if (!current_index_)
return;
DriveSystemService* system_service =
DriveSystemServiceFactory::GetForProfile(profile());
if (!system_service || error != HTTP_SUCCESS) {
Done(false);
return;
}
// Yay! We've got the feed data finally, and we can get the open-with URL.
GURL open_with_url;
base::ListValue* link_list = NULL;
feed_data->GetAsList(&link_list);
for (size_t i = 0; i < link_list->GetSize(); ++i) {
DictionaryValue* entry = NULL;
link_list->GetDictionary(i, &entry);
std::string app_id;
entry->GetString("app_id", &app_id);
if (app_id == extension_id()) {
std::string href;
entry->GetString("href", &href);
open_with_url = GURL(href);
break;
}
}
if (open_with_url.is_empty()) {
Done(false);
return;
}
Browser* browser = GetBrowser();
chrome::AddSelectedTabWithURL(browser, open_with_url,
content::PAGE_TRANSITION_LINK);
// If the current browser is not tabbed then the new tab will be created
// in a different browser. Make sure it is visible.
browser->window()->Show();
// We're done with this file. If this is the last one, then we're done.
current_index_--;
DCHECK(current_index_ >= 0);
if (current_index_ == 0)
Done(true);
}
void DriveTaskExecutor::Done(bool success) {
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
current_index_ = 0;
if (!done_.is_null())
done_.Run(success);
done_.Reset();
}
} // namespace gdata