private_api_drive.cc revision 010d83a9304c5a91596085d917d248abff47903a
1// Copyright 2013 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/extensions/file_manager/private_api_drive.h" 6 7#include "chrome/browser/browser_process.h" 8#include "chrome/browser/chromeos/drive/drive_integration_service.h" 9#include "chrome/browser/chromeos/extensions/file_manager/private_api_util.h" 10#include "chrome/browser/chromeos/file_manager/file_tasks.h" 11#include "chrome/browser/chromeos/file_manager/fileapi_util.h" 12#include "chrome/browser/chromeos/file_manager/url_util.h" 13#include "chrome/browser/chromeos/fileapi/file_system_backend.h" 14#include "chrome/browser/chromeos/login/user_manager.h" 15#include "chrome/browser/drive/drive_app_registry.h" 16#include "chrome/browser/drive/event_logger.h" 17#include "chrome/browser/profiles/profile.h" 18#include "chrome/browser/profiles/profile_manager.h" 19#include "chrome/common/extensions/api/file_browser_private.h" 20#include "content/public/browser/browser_thread.h" 21#include "webkit/common/fileapi/file_system_info.h" 22#include "webkit/common/fileapi/file_system_util.h" 23 24using content::BrowserThread; 25 26using file_manager::util::EntryDefinition; 27using file_manager::util::EntryDefinitionCallback; 28using file_manager::util::EntryDefinitionList; 29using file_manager::util::EntryDefinitionListCallback; 30using file_manager::util::FileDefinition; 31using file_manager::util::FileDefinitionList; 32using extensions::api::file_browser_private::DriveEntryProperties; 33 34namespace extensions { 35namespace { 36 37// List of connection types of drive. 38// Keep this in sync with the DriveConnectionType in common/js/util.js. 39const char kDriveConnectionTypeOffline[] = "offline"; 40const char kDriveConnectionTypeMetered[] = "metered"; 41const char kDriveConnectionTypeOnline[] = "online"; 42 43// List of reasons of kDriveConnectionType*. 44// Keep this in sync with the DriveConnectionReason in common/js/util.js. 45const char kDriveConnectionReasonNotReady[] = "not_ready"; 46const char kDriveConnectionReasonNoNetwork[] = "no_network"; 47const char kDriveConnectionReasonNoService[] = "no_service"; 48 49// Copies properties from |entry_proto| to |properties|. |shared_with_me| is 50// given from the running profile. 51void FillDriveEntryPropertiesValue(const drive::ResourceEntry& entry_proto, 52 bool shared_with_me, 53 DriveEntryProperties* properties) { 54 properties->shared_with_me.reset(new bool(shared_with_me)); 55 properties->shared.reset(new bool(entry_proto.shared())); 56 57 const drive::PlatformFileInfoProto& file_info = entry_proto.file_info(); 58 properties->file_size.reset(new double(file_info.size())); 59 properties->last_modified_time.reset(new double( 60 base::Time::FromInternalValue(file_info.last_modified()).ToJsTime())); 61 62 if (!entry_proto.has_file_specific_info()) 63 return; 64 65 const drive::FileSpecificInfo& file_specific_info = 66 entry_proto.file_specific_info(); 67 68 if (!entry_proto.resource_id().empty()) { 69 properties->thumbnail_url.reset( 70 new std::string("https://www.googledrive.com/thumb/" + 71 entry_proto.resource_id() + "?width=500&height=500")); 72 } 73 if (file_specific_info.has_image_width()) { 74 properties->image_width.reset( 75 new int(file_specific_info.image_width())); 76 } 77 if (file_specific_info.has_image_height()) { 78 properties->image_height.reset( 79 new int(file_specific_info.image_height())); 80 } 81 if (file_specific_info.has_image_rotation()) { 82 properties->image_rotation.reset( 83 new int(file_specific_info.image_rotation())); 84 } 85 properties->is_hosted.reset( 86 new bool(file_specific_info.is_hosted_document())); 87 properties->content_mime_type.reset( 88 new std::string(file_specific_info.content_mime_type())); 89} 90 91// Creates entry definition list for (metadata) search result info list. 92template <class T> 93void ConvertSearchResultInfoListToEntryDefinitionList( 94 Profile* profile, 95 const std::string& extension_id, 96 const std::vector<T>& search_result_info_list, 97 const EntryDefinitionListCallback& callback) { 98 FileDefinitionList file_definition_list; 99 100 for (size_t i = 0; i < search_result_info_list.size(); ++i) { 101 FileDefinition file_definition; 102 file_definition.virtual_path = 103 file_manager::util::ConvertDrivePathToRelativeFileSystemPath( 104 profile, extension_id, search_result_info_list.at(i).path); 105 file_definition.is_directory = search_result_info_list.at(i).is_directory; 106 file_definition_list.push_back(file_definition); 107 } 108 109 file_manager::util::ConvertFileDefinitionListToEntryDefinitionList( 110 profile, 111 extension_id, 112 file_definition_list, // Safe, since copied internally. 113 callback); 114} 115 116class SingleDriveEntryPropertiesGetter { 117 public: 118 typedef base::Callback<void(drive::FileError error)> ResultCallback; 119 120 // Creates an instance and starts the process. 121 static void Start(const base::FilePath local_path, 122 linked_ptr<DriveEntryProperties> properties, 123 Profile* const profile, 124 const ResultCallback& callback) { 125 126 SingleDriveEntryPropertiesGetter* instance = 127 new SingleDriveEntryPropertiesGetter( 128 local_path, properties, profile, callback); 129 instance->StartProcess(); 130 131 // The instance will be destroyed by itself. 132 } 133 134 virtual ~SingleDriveEntryPropertiesGetter() {} 135 136 private: 137 // Given parameters. 138 const ResultCallback callback_; 139 const base::FilePath local_path_; 140 const linked_ptr<DriveEntryProperties> properties_; 141 Profile* const running_profile_; 142 143 // Values used in the process. 144 Profile* file_owner_profile_; 145 base::FilePath file_path_; 146 scoped_ptr<drive::ResourceEntry> owner_resource_entry_; 147 148 base::WeakPtrFactory<SingleDriveEntryPropertiesGetter> weak_ptr_factory_; 149 150 SingleDriveEntryPropertiesGetter(const base::FilePath local_path, 151 linked_ptr<DriveEntryProperties> properties, 152 Profile* const profile, 153 const ResultCallback& callback) 154 : callback_(callback), 155 local_path_(local_path), 156 properties_(properties), 157 running_profile_(profile), 158 file_owner_profile_(NULL), 159 weak_ptr_factory_(this) { 160 DCHECK(!callback_.is_null()); 161 DCHECK(profile); 162 } 163 164 base::WeakPtr<SingleDriveEntryPropertiesGetter> GetWeakPtr() { 165 return weak_ptr_factory_.GetWeakPtr(); 166 } 167 168 void StartProcess() { 169 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 170 171 file_path_ = drive::util::ExtractDrivePath(local_path_); 172 file_owner_profile_ = drive::util::ExtractProfileFromPath(local_path_); 173 174 if (!file_owner_profile_ || 175 !g_browser_process->profile_manager()->IsValidProfile( 176 file_owner_profile_)) { 177 CompleteGetFileProperties(drive::FILE_ERROR_FAILED); 178 return; 179 } 180 181 // Start getting the file info. 182 drive::FileSystemInterface* const file_system = 183 drive::util::GetFileSystemByProfile(file_owner_profile_); 184 if (!file_system) { 185 // |file_system| is NULL if Drive is disabled or not mounted. 186 CompleteGetFileProperties(drive::FILE_ERROR_FAILED); 187 return; 188 } 189 190 file_system->GetResourceEntry( 191 file_path_, 192 base::Bind(&SingleDriveEntryPropertiesGetter::OnGetFileInfo, 193 GetWeakPtr())); 194 } 195 196 void OnGetFileInfo(drive::FileError error, 197 scoped_ptr<drive::ResourceEntry> entry) { 198 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 199 200 if (error != drive::FILE_ERROR_OK) { 201 CompleteGetFileProperties(error); 202 return; 203 } 204 205 DCHECK(entry); 206 owner_resource_entry_.swap(entry); 207 208 if (running_profile_->IsSameProfile(file_owner_profile_)) { 209 StartParseFileInfo(owner_resource_entry_->shared_with_me()); 210 return; 211 } 212 213 // If the running profile does not own the file, obtain the shared_with_me 214 // flag from the running profile's value. 215 drive::FileSystemInterface* const file_system = 216 drive::util::GetFileSystemByProfile(running_profile_); 217 if (!file_system) { 218 CompleteGetFileProperties(drive::FILE_ERROR_FAILED); 219 return; 220 } 221 file_system->GetPathFromResourceId( 222 owner_resource_entry_->resource_id(), 223 base::Bind(&SingleDriveEntryPropertiesGetter::OnGetRunningPath, 224 GetWeakPtr())); 225 } 226 227 void OnGetRunningPath(drive::FileError error, 228 const base::FilePath& file_path) { 229 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 230 231 if (error != drive::FILE_ERROR_OK) { 232 // The running profile does not know the file. 233 StartParseFileInfo(false); 234 return; 235 } 236 237 drive::FileSystemInterface* const file_system = 238 drive::util::GetFileSystemByProfile(running_profile_); 239 if (!file_system) { 240 // The drive is disable for the running profile. 241 StartParseFileInfo(false); 242 return; 243 } 244 245 file_system->GetResourceEntry( 246 file_path, 247 base::Bind(&SingleDriveEntryPropertiesGetter::OnGetShareInfo, 248 GetWeakPtr())); 249 } 250 251 void OnGetShareInfo(drive::FileError error, 252 scoped_ptr<drive::ResourceEntry> entry) { 253 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 254 255 if (error != drive::FILE_ERROR_OK) { 256 CompleteGetFileProperties(error); 257 return; 258 } 259 260 DCHECK(entry); 261 StartParseFileInfo(entry->shared_with_me()); 262 } 263 264 void StartParseFileInfo(bool shared_with_me) { 265 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 266 267 FillDriveEntryPropertiesValue( 268 *owner_resource_entry_, shared_with_me, properties_.get()); 269 270 drive::FileSystemInterface* const file_system = 271 drive::util::GetFileSystemByProfile(file_owner_profile_); 272 drive::DriveAppRegistry* const app_registry = 273 drive::util::GetDriveAppRegistryByProfile(file_owner_profile_); 274 if (!file_system || !app_registry) { 275 // |file_system| or |app_registry| is NULL if Drive is disabled. 276 CompleteGetFileProperties(drive::FILE_ERROR_FAILED); 277 return; 278 } 279 280 // The properties meaningful for directories are already filled in 281 // FillDriveEntryPropertiesValue(). 282 if (!owner_resource_entry_->has_file_specific_info()) { 283 CompleteGetFileProperties(drive::FILE_ERROR_OK); 284 return; 285 } 286 287 const drive::FileSpecificInfo& file_specific_info = 288 owner_resource_entry_->file_specific_info(); 289 290 // Get drive WebApps that can accept this file. We just need to extract the 291 // doc icon for the drive app, which is set as default. 292 std::vector<drive::DriveAppInfo> drive_apps; 293 app_registry->GetAppsForFile(file_path_.Extension(), 294 file_specific_info.content_mime_type(), 295 &drive_apps); 296 if (!drive_apps.empty()) { 297 std::string default_task_id = 298 file_manager::file_tasks::GetDefaultTaskIdFromPrefs( 299 *file_owner_profile_->GetPrefs(), 300 file_specific_info.content_mime_type(), 301 file_path_.Extension()); 302 file_manager::file_tasks::TaskDescriptor default_task; 303 file_manager::file_tasks::ParseTaskID(default_task_id, &default_task); 304 DCHECK(default_task_id.empty() || !default_task.app_id.empty()); 305 for (size_t i = 0; i < drive_apps.size(); ++i) { 306 const drive::DriveAppInfo& app_info = drive_apps[i]; 307 if (default_task.app_id == app_info.app_id) { 308 // The drive app is set as default. Files.app should use the doc icon. 309 const GURL doc_icon = drive::util::FindPreferredIcon( 310 app_info.document_icons, drive::util::kPreferredIconSize); 311 properties_->custom_icon_url.reset(new std::string(doc_icon.spec())); 312 } 313 } 314 } 315 316 file_system->GetCacheEntry( 317 file_path_, 318 base::Bind(&SingleDriveEntryPropertiesGetter::CacheStateReceived, 319 GetWeakPtr())); 320 } 321 322 void CacheStateReceived(bool /* success */, 323 const drive::FileCacheEntry& cache_entry) { 324 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 325 326 // In case of an error (i.e. success is false), cache_entry.is_*() all 327 // returns false. 328 properties_->is_pinned.reset(new bool(cache_entry.is_pinned())); 329 properties_->is_present.reset(new bool(cache_entry.is_present())); 330 331 CompleteGetFileProperties(drive::FILE_ERROR_OK); 332 } 333 334 void CompleteGetFileProperties(drive::FileError error) { 335 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 336 DCHECK(!callback_.is_null()); 337 callback_.Run(error); 338 339 delete this; 340 } 341}; // class SingleDriveEntryPropertiesGetter 342 343} // namespace 344 345FileBrowserPrivateGetDriveEntryPropertiesFunction:: 346 FileBrowserPrivateGetDriveEntryPropertiesFunction() 347 : processed_count_(0) {} 348 349FileBrowserPrivateGetDriveEntryPropertiesFunction:: 350 ~FileBrowserPrivateGetDriveEntryPropertiesFunction() {} 351 352bool FileBrowserPrivateGetDriveEntryPropertiesFunction::RunAsync() { 353 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 354 355 using api::file_browser_private::GetDriveEntryProperties::Params; 356 const scoped_ptr<Params> params(Params::Create(*args_)); 357 EXTENSION_FUNCTION_VALIDATE(params); 358 359 properties_list_.resize(params->file_urls.size()); 360 361 for (size_t i = 0; i < params->file_urls.size(); i++) { 362 const GURL url = GURL(params->file_urls[i]); 363 const base::FilePath local_path = file_manager::util::GetLocalPathFromURL( 364 render_view_host(), GetProfile(), url); 365 properties_list_[i] = make_linked_ptr(new DriveEntryProperties); 366 367 SingleDriveEntryPropertiesGetter::Start( 368 local_path, 369 properties_list_[i], 370 GetProfile(), 371 base::Bind(&FileBrowserPrivateGetDriveEntryPropertiesFunction:: 372 CompleteGetFileProperties, 373 this)); 374 } 375 376 return true; 377} 378 379void FileBrowserPrivateGetDriveEntryPropertiesFunction:: 380 CompleteGetFileProperties(drive::FileError error) { 381 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 382 DCHECK(0 <= processed_count_ && processed_count_ < properties_list_.size()); 383 384 processed_count_++; 385 if (processed_count_ < properties_list_.size()) 386 return; 387 388 results_ = extensions::api::file_browser_private::GetDriveEntryProperties:: 389 Results::Create(properties_list_); 390 SendResponse(true); 391} 392 393bool FileBrowserPrivatePinDriveFileFunction::RunAsync() { 394 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 395 396 using extensions::api::file_browser_private::PinDriveFile::Params; 397 const scoped_ptr<Params> params(Params::Create(*args_)); 398 EXTENSION_FUNCTION_VALIDATE(params); 399 400 drive::FileSystemInterface* const file_system = 401 drive::util::GetFileSystemByProfile(GetProfile()); 402 if (!file_system) // |file_system| is NULL if Drive is disabled. 403 return false; 404 405 const base::FilePath drive_path = 406 drive::util::ExtractDrivePath(file_manager::util::GetLocalPathFromURL( 407 render_view_host(), GetProfile(), GURL(params->file_url))); 408 if (params->pin) { 409 file_system->Pin(drive_path, 410 base::Bind(&FileBrowserPrivatePinDriveFileFunction:: 411 OnPinStateSet, this)); 412 } else { 413 file_system->Unpin(drive_path, 414 base::Bind(&FileBrowserPrivatePinDriveFileFunction:: 415 OnPinStateSet, this)); 416 } 417 return true; 418} 419 420void FileBrowserPrivatePinDriveFileFunction:: 421 OnPinStateSet(drive::FileError error) { 422 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 423 424 if (error == drive::FILE_ERROR_OK) { 425 SendResponse(true); 426 } else { 427 SetError(drive::FileErrorToString(error)); 428 SendResponse(false); 429 } 430} 431 432FileBrowserPrivateGetDriveFilesFunction:: 433 FileBrowserPrivateGetDriveFilesFunction() { 434} 435 436FileBrowserPrivateGetDriveFilesFunction:: 437 ~FileBrowserPrivateGetDriveFilesFunction() { 438} 439 440bool FileBrowserPrivateGetDriveFilesFunction::RunAsync() { 441 using extensions::api::file_browser_private::GetDriveFiles::Params; 442 const scoped_ptr<Params> params(Params::Create(*args_)); 443 EXTENSION_FUNCTION_VALIDATE(params); 444 445 // Convert the list of strings to a list of GURLs. 446 for (size_t i = 0; i < params->file_urls.size(); ++i) { 447 const base::FilePath path = file_manager::util::GetLocalPathFromURL( 448 render_view_host(), GetProfile(), GURL(params->file_urls[i])); 449 DCHECK(drive::util::IsUnderDriveMountPoint(path)); 450 base::FilePath drive_path = drive::util::ExtractDrivePath(path); 451 remaining_drive_paths_.push(drive_path); 452 } 453 454 GetFileOrSendResponse(); 455 return true; 456} 457 458void FileBrowserPrivateGetDriveFilesFunction::GetFileOrSendResponse() { 459 // Send the response if all files are obtained. 460 if (remaining_drive_paths_.empty()) { 461 results_ = extensions::api::file_browser_private:: 462 GetDriveFiles::Results::Create(local_paths_); 463 SendResponse(true); 464 return; 465 } 466 467 // Get the file on the top of the queue. 468 base::FilePath drive_path = remaining_drive_paths_.front(); 469 470 drive::FileSystemInterface* file_system = 471 drive::util::GetFileSystemByProfile(GetProfile()); 472 if (!file_system) { 473 // |file_system| is NULL if Drive is disabled or not mounted. 474 OnFileReady(drive::FILE_ERROR_FAILED, drive_path, 475 scoped_ptr<drive::ResourceEntry>()); 476 return; 477 } 478 479 file_system->GetFile( 480 drive_path, 481 base::Bind(&FileBrowserPrivateGetDriveFilesFunction::OnFileReady, this)); 482} 483 484 485void FileBrowserPrivateGetDriveFilesFunction::OnFileReady( 486 drive::FileError error, 487 const base::FilePath& local_path, 488 scoped_ptr<drive::ResourceEntry> entry) { 489 base::FilePath drive_path = remaining_drive_paths_.front(); 490 491 if (error == drive::FILE_ERROR_OK) { 492 local_paths_.push_back(local_path.AsUTF8Unsafe()); 493 DVLOG(1) << "Got " << drive_path.value() << " as " << local_path.value(); 494 } else { 495 local_paths_.push_back(""); 496 DVLOG(1) << "Failed to get " << drive_path.value() 497 << " with error code: " << error; 498 } 499 500 remaining_drive_paths_.pop(); 501 502 // Start getting the next file. 503 GetFileOrSendResponse(); 504} 505 506bool FileBrowserPrivateCancelFileTransfersFunction::RunAsync() { 507 using extensions::api::file_browser_private::CancelFileTransfers::Params; 508 const scoped_ptr<Params> params(Params::Create(*args_)); 509 EXTENSION_FUNCTION_VALIDATE(params); 510 511 drive::DriveIntegrationService* integration_service = 512 drive::DriveIntegrationServiceFactory::FindForProfile(GetProfile()); 513 if (!integration_service || !integration_service->IsMounted()) 514 return false; 515 516 // Create the mapping from file path to job ID. 517 drive::JobListInterface* job_list = integration_service->job_list(); 518 DCHECK(job_list); 519 std::vector<drive::JobInfo> jobs = job_list->GetJobInfoList(); 520 521 typedef std::map<base::FilePath, std::vector<drive::JobID> > PathToIdMap; 522 PathToIdMap path_to_id_map; 523 for (size_t i = 0; i < jobs.size(); ++i) { 524 if (drive::IsActiveFileTransferJobInfo(jobs[i])) 525 path_to_id_map[jobs[i].file_path].push_back(jobs[i].job_id); 526 } 527 528 // Cancel by Job ID. 529 std::vector<linked_ptr<api::file_browser_private:: 530 FileTransferCancelStatus> > responses; 531 for (size_t i = 0; i < params->file_urls.size(); ++i) { 532 base::FilePath file_path = file_manager::util::GetLocalPathFromURL( 533 render_view_host(), GetProfile(), GURL(params->file_urls[i])); 534 if (file_path.empty()) 535 continue; 536 537 DCHECK(drive::util::IsUnderDriveMountPoint(file_path)); 538 file_path = drive::util::ExtractDrivePath(file_path); 539 540 // Cancel all the jobs for the file. 541 PathToIdMap::iterator it = path_to_id_map.find(file_path); 542 if (it != path_to_id_map.end()) { 543 for (size_t i = 0; i < it->second.size(); ++i) 544 job_list->CancelJob(it->second[i]); 545 } 546 linked_ptr<api::file_browser_private::FileTransferCancelStatus> result( 547 new api::file_browser_private::FileTransferCancelStatus); 548 result->canceled = it != path_to_id_map.end(); 549 // TODO(kinaba): simplify cancelFileTransfer() to take single URL each time, 550 // and eliminate this field; it is just returning a copy of the argument. 551 result->file_url = params->file_urls[i]; 552 responses.push_back(result); 553 } 554 results_ = api::file_browser_private::CancelFileTransfers::Results::Create( 555 responses); 556 SendResponse(true); 557 return true; 558} 559 560bool FileBrowserPrivateSearchDriveFunction::RunAsync() { 561 using extensions::api::file_browser_private::SearchDrive::Params; 562 const scoped_ptr<Params> params(Params::Create(*args_)); 563 EXTENSION_FUNCTION_VALIDATE(params); 564 565 drive::FileSystemInterface* const file_system = 566 drive::util::GetFileSystemByProfile(GetProfile()); 567 if (!file_system) { 568 // |file_system| is NULL if Drive is disabled. 569 return false; 570 } 571 572 file_system->Search( 573 params->search_params.query, GURL(params->search_params.next_feed), 574 base::Bind(&FileBrowserPrivateSearchDriveFunction::OnSearch, this)); 575 return true; 576} 577 578void FileBrowserPrivateSearchDriveFunction::OnSearch( 579 drive::FileError error, 580 const GURL& next_link, 581 scoped_ptr<SearchResultInfoList> results) { 582 if (error != drive::FILE_ERROR_OK) { 583 SendResponse(false); 584 return; 585 } 586 587 // Outlives the following conversion, since the pointer is bound to the 588 // callback. 589 DCHECK(results.get()); 590 const SearchResultInfoList& results_ref = *results.get(); 591 592 ConvertSearchResultInfoListToEntryDefinitionList( 593 GetProfile(), 594 extension_->id(), 595 results_ref, 596 base::Bind(&FileBrowserPrivateSearchDriveFunction::OnEntryDefinitionList, 597 this, 598 next_link, 599 base::Passed(&results))); 600} 601 602void FileBrowserPrivateSearchDriveFunction::OnEntryDefinitionList( 603 const GURL& next_link, 604 scoped_ptr<SearchResultInfoList> search_result_info_list, 605 scoped_ptr<EntryDefinitionList> entry_definition_list) { 606 DCHECK_EQ(search_result_info_list->size(), entry_definition_list->size()); 607 base::ListValue* entries = new base::ListValue(); 608 609 // Convert Drive files to something File API stack can understand. 610 for (EntryDefinitionList::const_iterator it = entry_definition_list->begin(); 611 it != entry_definition_list->end(); 612 ++it) { 613 base::DictionaryValue* entry = new base::DictionaryValue(); 614 entry->SetString("fileSystemName", it->file_system_name); 615 entry->SetString("fileSystemRoot", it->file_system_root_url); 616 entry->SetString("fileFullPath", "/" + it->full_path.AsUTF8Unsafe()); 617 entry->SetBoolean("fileIsDirectory", it->is_directory); 618 entries->Append(entry); 619 } 620 621 base::DictionaryValue* result = new base::DictionaryValue(); 622 result->Set("entries", entries); 623 result->SetString("nextFeed", next_link.spec()); 624 625 SetResult(result); 626 SendResponse(true); 627} 628 629bool FileBrowserPrivateSearchDriveMetadataFunction::RunAsync() { 630 using api::file_browser_private::SearchDriveMetadata::Params; 631 const scoped_ptr<Params> params(Params::Create(*args_)); 632 EXTENSION_FUNCTION_VALIDATE(params); 633 634 drive::EventLogger* logger = file_manager::util::GetLogger(GetProfile()); 635 if (logger) { 636 logger->Log(logging::LOG_INFO, 637 "%s[%d] called. (types: '%s', maxResults: '%d')", 638 name().c_str(), 639 request_id(), 640 api::file_browser_private::ToString( 641 params->search_params.types).c_str(), 642 params->search_params.max_results); 643 } 644 set_log_on_completion(true); 645 646 drive::FileSystemInterface* const file_system = 647 drive::util::GetFileSystemByProfile(GetProfile()); 648 if (!file_system) { 649 // |file_system| is NULL if Drive is disabled. 650 return false; 651 } 652 653 int options = -1; 654 switch (params->search_params.types) { 655 case api::file_browser_private::SEARCH_TYPE_EXCLUDE_DIRECTORIES: 656 options = drive::SEARCH_METADATA_EXCLUDE_DIRECTORIES; 657 break; 658 case api::file_browser_private::SEARCH_TYPE_SHARED_WITH_ME: 659 options = drive::SEARCH_METADATA_SHARED_WITH_ME; 660 break; 661 case api::file_browser_private::SEARCH_TYPE_OFFLINE: 662 options = drive::SEARCH_METADATA_OFFLINE; 663 break; 664 case api::file_browser_private::SEARCH_TYPE_ALL: 665 options = drive::SEARCH_METADATA_ALL; 666 break; 667 case api::file_browser_private::SEARCH_TYPE_NONE: 668 break; 669 } 670 DCHECK_NE(options, -1); 671 672 file_system->SearchMetadata( 673 params->search_params.query, 674 options, 675 params->search_params.max_results, 676 base::Bind(&FileBrowserPrivateSearchDriveMetadataFunction:: 677 OnSearchMetadata, this)); 678 return true; 679} 680 681void FileBrowserPrivateSearchDriveMetadataFunction::OnSearchMetadata( 682 drive::FileError error, 683 scoped_ptr<drive::MetadataSearchResultVector> results) { 684 if (error != drive::FILE_ERROR_OK) { 685 SendResponse(false); 686 return; 687 } 688 689 // Outlives the following conversion, since the pointer is bound to the 690 // callback. 691 DCHECK(results.get()); 692 const drive::MetadataSearchResultVector& results_ref = *results.get(); 693 694 ConvertSearchResultInfoListToEntryDefinitionList( 695 GetProfile(), 696 extension_->id(), 697 results_ref, 698 base::Bind( 699 &FileBrowserPrivateSearchDriveMetadataFunction::OnEntryDefinitionList, 700 this, 701 base::Passed(&results))); 702} 703 704void FileBrowserPrivateSearchDriveMetadataFunction::OnEntryDefinitionList( 705 scoped_ptr<drive::MetadataSearchResultVector> search_result_info_list, 706 scoped_ptr<EntryDefinitionList> entry_definition_list) { 707 DCHECK_EQ(search_result_info_list->size(), entry_definition_list->size()); 708 base::ListValue* results_list = new base::ListValue(); 709 710 // Convert Drive files to something File API stack can understand. See 711 // file_browser_handler_custom_bindings.cc and 712 // file_browser_private_custom_bindings.js for how this is magically 713 // converted to a FileEntry. 714 for (size_t i = 0; i < entry_definition_list->size(); ++i) { 715 base::DictionaryValue* result_dict = new base::DictionaryValue(); 716 717 // FileEntry fields. 718 base::DictionaryValue* entry = new base::DictionaryValue(); 719 entry->SetString( 720 "fileSystemName", entry_definition_list->at(i).file_system_name); 721 entry->SetString( 722 "fileSystemRoot", entry_definition_list->at(i).file_system_root_url); 723 entry->SetString( 724 "fileFullPath", 725 "/" + entry_definition_list->at(i).full_path.AsUTF8Unsafe()); 726 entry->SetBoolean("fileIsDirectory", 727 entry_definition_list->at(i).is_directory); 728 729 result_dict->Set("entry", entry); 730 result_dict->SetString( 731 "highlightedBaseName", 732 search_result_info_list->at(i).highlighted_base_name); 733 results_list->Append(result_dict); 734 } 735 736 SetResult(results_list); 737 SendResponse(true); 738} 739 740bool FileBrowserPrivateGetDriveConnectionStateFunction::RunSync() { 741 api::file_browser_private::DriveConnectionState result; 742 743 switch (drive::util::GetDriveConnectionStatus(GetProfile())) { 744 case drive::util::DRIVE_DISCONNECTED_NOSERVICE: 745 result.type = kDriveConnectionTypeOffline; 746 result.reason.reset(new std::string(kDriveConnectionReasonNoService)); 747 break; 748 case drive::util::DRIVE_DISCONNECTED_NONETWORK: 749 result.type = kDriveConnectionTypeOffline; 750 result.reason.reset(new std::string(kDriveConnectionReasonNoNetwork)); 751 break; 752 case drive::util::DRIVE_DISCONNECTED_NOTREADY: 753 result.type = kDriveConnectionTypeOffline; 754 result.reason.reset(new std::string(kDriveConnectionReasonNotReady)); 755 break; 756 case drive::util::DRIVE_CONNECTED_METERED: 757 result.type = kDriveConnectionTypeMetered; 758 break; 759 case drive::util::DRIVE_CONNECTED: 760 result.type = kDriveConnectionTypeOnline; 761 break; 762 } 763 764 results_ = api::file_browser_private::GetDriveConnectionState::Results:: 765 Create(result); 766 767 drive::EventLogger* logger = file_manager::util::GetLogger(GetProfile()); 768 if (logger) 769 logger->Log(logging::LOG_INFO, "%s succeeded.", name().c_str()); 770 return true; 771} 772 773bool FileBrowserPrivateRequestAccessTokenFunction::RunAsync() { 774 using extensions::api::file_browser_private::RequestAccessToken::Params; 775 const scoped_ptr<Params> params(Params::Create(*args_)); 776 EXTENSION_FUNCTION_VALIDATE(params); 777 778 drive::DriveServiceInterface* const drive_service = 779 drive::util::GetDriveServiceByProfile(GetProfile()); 780 781 if (!drive_service) { 782 // DriveService is not available. 783 SetResult(new base::StringValue("")); 784 SendResponse(true); 785 return true; 786 } 787 788 // If refreshing is requested, then clear the token to refetch it. 789 if (params->refresh) 790 drive_service->ClearAccessToken(); 791 792 // Retrieve the cached auth token (if available), otherwise the AuthService 793 // instance will try to refetch it. 794 drive_service->RequestAccessToken( 795 base::Bind(&FileBrowserPrivateRequestAccessTokenFunction:: 796 OnAccessTokenFetched, this)); 797 return true; 798} 799 800void FileBrowserPrivateRequestAccessTokenFunction::OnAccessTokenFetched( 801 google_apis::GDataErrorCode code, 802 const std::string& access_token) { 803 SetResult(new base::StringValue(access_token)); 804 SendResponse(true); 805} 806 807bool FileBrowserPrivateGetShareUrlFunction::RunAsync() { 808 using extensions::api::file_browser_private::GetShareUrl::Params; 809 const scoped_ptr<Params> params(Params::Create(*args_)); 810 EXTENSION_FUNCTION_VALIDATE(params); 811 812 const base::FilePath path = file_manager::util::GetLocalPathFromURL( 813 render_view_host(), GetProfile(), GURL(params->url)); 814 DCHECK(drive::util::IsUnderDriveMountPoint(path)); 815 816 const base::FilePath drive_path = drive::util::ExtractDrivePath(path); 817 818 drive::FileSystemInterface* const file_system = 819 drive::util::GetFileSystemByProfile(GetProfile()); 820 if (!file_system) { 821 // |file_system| is NULL if Drive is disabled. 822 return false; 823 } 824 825 file_system->GetShareUrl( 826 drive_path, 827 file_manager::util::GetFileManagerBaseUrl(), // embed origin 828 base::Bind(&FileBrowserPrivateGetShareUrlFunction::OnGetShareUrl, this)); 829 return true; 830} 831 832void FileBrowserPrivateGetShareUrlFunction::OnGetShareUrl( 833 drive::FileError error, 834 const GURL& share_url) { 835 if (error != drive::FILE_ERROR_OK) { 836 SetError("Share Url for this item is not available."); 837 SendResponse(false); 838 return; 839 } 840 841 SetResult(new base::StringValue(share_url.spec())); 842 SendResponse(true); 843} 844 845bool FileBrowserPrivateRequestDriveShareFunction::RunAsync() { 846 using extensions::api::file_browser_private::RequestDriveShare::Params; 847 const scoped_ptr<Params> params(Params::Create(*args_)); 848 EXTENSION_FUNCTION_VALIDATE(params); 849 850 const base::FilePath path = file_manager::util::GetLocalPathFromURL( 851 render_view_host(), GetProfile(), GURL(params->url)); 852 const base::FilePath drive_path = drive::util::ExtractDrivePath(path); 853 Profile* const owner_profile = drive::util::ExtractProfileFromPath(path); 854 855 if (!owner_profile) 856 return false; 857 858 drive::FileSystemInterface* const owner_file_system = 859 drive::util::GetFileSystemByProfile(owner_profile); 860 if (!owner_file_system) 861 return false; 862 863 const chromeos::User* const user = 864 chromeos::UserManager::Get()->GetUserByProfile(GetProfile()); 865 if (!user || !user->is_logged_in()) 866 return false; 867 868 google_apis::drive::PermissionRole role = 869 google_apis::drive::PERMISSION_ROLE_READER; 870 switch (params->share_type) { 871 case api::file_browser_private::DRIVE_SHARE_TYPE_NONE: 872 NOTREACHED(); 873 return false; 874 case api::file_browser_private::DRIVE_SHARE_TYPE_CAN_EDIT: 875 role = google_apis::drive::PERMISSION_ROLE_WRITER; 876 break; 877 case api::file_browser_private::DRIVE_SHARE_TYPE_CAN_COMMENT: 878 role = google_apis::drive::PERMISSION_ROLE_COMMENTER; 879 break; 880 case api::file_browser_private::DRIVE_SHARE_TYPE_CAN_VIEW: 881 role = google_apis::drive::PERMISSION_ROLE_READER; 882 break; 883 } 884 885 // Share |drive_path| in |owner_file_system| to |user->email()|. 886 owner_file_system->AddPermission( 887 drive_path, 888 user->email(), 889 role, 890 base::Bind(&FileBrowserPrivateRequestDriveShareFunction::OnAddPermission, 891 this)); 892 return true; 893} 894 895void FileBrowserPrivateRequestDriveShareFunction::OnAddPermission( 896 drive::FileError error) { 897 SendResponse(error == drive::FILE_ERROR_OK); 898} 899 900} // namespace extensions 901