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 22 using fileapi::FileSystemURL; 23 24 namespace drive { 25 26 FileTaskExecutor::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 34 FileTaskExecutor::~FileTaskExecutor() { 35 } 36 37 void 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 71 void 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 98 void 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 133 void 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