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 "chrome/browser/chromeos/drive/file_task_executor.h" 6 7#include <string> 8#include <vector> 9 10#include "chrome/browser/chromeos/drive/drive.pb.h" 11#include "chrome/browser/chromeos/drive/drive_integration_service.h" 12#include "chrome/browser/chromeos/drive/file_system_interface.h" 13#include "chrome/browser/drive/drive_service_interface.h" 14#include "chrome/browser/profiles/profile_manager.h" 15#include "chrome/browser/ui/browser.h" 16#include "chrome/browser/ui/browser_finder.h" 17#include "chrome/browser/ui/browser_tabstrip.h" 18#include "chrome/browser/ui/browser_window.h" 19#include "content/public/browser/browser_thread.h" 20#include "webkit/browser/fileapi/file_system_url.h" 21 22using fileapi::FileSystemURL; 23 24namespace drive { 25 26FileTaskExecutor::FileTaskExecutor(Profile* profile, 27 const std::string& app_id) 28 : profile_(profile), 29 app_id_(app_id), 30 current_index_(0), 31 weak_ptr_factory_(this) { 32} 33 34FileTaskExecutor::~FileTaskExecutor() { 35} 36 37void FileTaskExecutor::Execute( 38 const std::vector<FileSystemURL>& file_urls, 39 const file_manager::file_tasks::FileTaskFinishedCallback& done) { 40 std::vector<base::FilePath> paths; 41 for (size_t i = 0; i < file_urls.size(); ++i) { 42 base::FilePath path = util::ExtractDrivePathFromFileSystemUrl(file_urls[i]); 43 if (path.empty()) { 44 Done(false); 45 return; 46 } 47 paths.push_back(path); 48 } 49 50 DriveIntegrationService* integration_service = 51 DriveIntegrationServiceFactory::GetForProfile(profile_); 52 DCHECK_EQ(current_index_, 0); 53 if (!integration_service || !integration_service->file_system()) { 54 Done(false); 55 return; 56 } 57 FileSystemInterface* file_system = integration_service->file_system(); 58 59 done_ = done; 60 // Reset the index, so we know when we're done. 61 current_index_ = paths.size(); 62 63 for (size_t i = 0; i < paths.size(); ++i) { 64 file_system->GetResourceEntryByPath( 65 paths[i], 66 base::Bind(&FileTaskExecutor::OnFileEntryFetched, 67 weak_ptr_factory_.GetWeakPtr())); 68 } 69} 70 71void FileTaskExecutor::OnFileEntryFetched(FileError error, 72 scoped_ptr<ResourceEntry> entry) { 73 DriveIntegrationService* integration_service = 74 DriveIntegrationServiceFactory::GetForProfile(profile_); 75 76 // Here, we are only interested in files. 77 if (entry.get() && !entry->has_file_specific_info()) 78 error = FILE_ERROR_NOT_FOUND; 79 80 if (!integration_service || error != FILE_ERROR_OK) { 81 Done(false); 82 return; 83 } 84 85 DriveServiceInterface* drive_service = 86 integration_service->drive_service(); 87 88 // Send off a request for the drive service to authorize the apps for the 89 // current document entry for this document so we can get the 90 // open-with-<app_id> urls from the document entry. 91 drive_service->AuthorizeApp(entry->resource_id(), 92 app_id_, 93 base::Bind(&FileTaskExecutor::OnAppAuthorized, 94 weak_ptr_factory_.GetWeakPtr(), 95 entry->resource_id())); 96} 97 98void FileTaskExecutor::OnAppAuthorized(const std::string& resource_id, 99 google_apis::GDataErrorCode error, 100 const GURL& open_link) { 101 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 102 103 DriveIntegrationService* integration_service = 104 DriveIntegrationServiceFactory::GetForProfile(profile_); 105 106 if (!integration_service || error != google_apis::HTTP_SUCCESS) { 107 Done(false); 108 return; 109 } 110 111 if (open_link.is_empty()) { 112 Done(false); 113 return; 114 } 115 116 Browser* browser = chrome::FindOrCreateTabbedBrowser( 117 profile_ ? profile_ : ProfileManager::GetDefaultProfileOrOffTheRecord(), 118 chrome::HOST_DESKTOP_TYPE_ASH); 119 120 chrome::AddSelectedTabWithURL(browser, open_link, 121 content::PAGE_TRANSITION_LINK); 122 // If the current browser is not tabbed then the new tab will be created 123 // in a different browser. Make sure it is visible. 124 browser->window()->Show(); 125 126 // We're done with this file. If this is the last one, then we're done. 127 current_index_--; 128 DCHECK_GE(current_index_, 0); 129 if (current_index_ == 0) 130 Done(true); 131} 132 133void FileTaskExecutor::Done(bool success) { 134 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 135 if (!done_.is_null()) 136 done_.Run(success); 137 delete this; 138} 139 140} // namespace drive 141