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/media_galleries/fileapi/safe_picasa_album_table_reader.h" 6 7#include "base/bind.h" 8#include "base/logging.h" 9#include "chrome/browser/media_galleries/fileapi/media_file_system_backend.h" 10#include "chrome/common/chrome_utility_messages.h" 11#include "chrome/common/extensions/chrome_utility_extensions_messages.h" 12#include "content/public/browser/browser_thread.h" 13#include "content/public/browser/child_process_data.h" 14 15using content::BrowserThread; 16 17namespace picasa { 18 19SafePicasaAlbumTableReader::SafePicasaAlbumTableReader( 20 AlbumTableFiles album_table_files) 21 : album_table_files_(album_table_files.Pass()), 22 parser_state_(INITIAL_STATE) { 23 // TODO(tommycli): Add DCHECK to make sure |album_table_files| are all 24 // opened read-only once security adds ability to check PlatformFiles. 25 DCHECK(MediaFileSystemBackend::CurrentlyOnMediaTaskRunnerThread()); 26} 27 28void SafePicasaAlbumTableReader::Start(const ParserCallback& callback) { 29 DCHECK(MediaFileSystemBackend::CurrentlyOnMediaTaskRunnerThread()); 30 DCHECK(!callback.is_null()); 31 32 callback_ = callback; 33 34 // Don't bother spawning process if any of the files are invalid. 35 if (!album_table_files_.indicator_file.IsValid() || 36 !album_table_files_.category_file.IsValid() || 37 !album_table_files_.date_file.IsValid() || 38 !album_table_files_.filename_file.IsValid() || 39 !album_table_files_.name_file.IsValid() || 40 !album_table_files_.token_file.IsValid() || 41 !album_table_files_.uid_file.IsValid()) { 42 MediaFileSystemBackend::MediaTaskRunner()->PostTask( 43 FROM_HERE, 44 base::Bind(callback_, 45 false /* parse_success */, 46 std::vector<AlbumInfo>(), 47 std::vector<AlbumInfo>())); 48 return; 49 } 50 51 BrowserThread::PostTask( 52 BrowserThread::IO, 53 FROM_HERE, 54 base::Bind(&SafePicasaAlbumTableReader::StartWorkOnIOThread, this)); 55} 56 57SafePicasaAlbumTableReader::~SafePicasaAlbumTableReader() { 58} 59 60void SafePicasaAlbumTableReader::StartWorkOnIOThread() { 61 DCHECK_CURRENTLY_ON(BrowserThread::IO); 62 DCHECK_EQ(INITIAL_STATE, parser_state_); 63 64 utility_process_host_ = content::UtilityProcessHost::Create( 65 this, 66 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO).get()) 67 ->AsWeakPtr(); 68 // Wait for the startup notification before sending the main IPC to the 69 // utility process, so that we can dup the file handle. 70 utility_process_host_->Send(new ChromeUtilityMsg_StartupPing); 71 parser_state_ = PINGED_UTILITY_PROCESS_STATE; 72} 73 74void SafePicasaAlbumTableReader::OnProcessStarted() { 75 DCHECK_CURRENTLY_ON(BrowserThread::IO); 76 if (parser_state_ != PINGED_UTILITY_PROCESS_STATE) 77 return; 78 79 if (utility_process_host_->GetData().handle == base::kNullProcessHandle) { 80 DLOG(ERROR) << "Child process handle is null"; 81 } 82 AlbumTableFilesForTransit files_for_transit; 83 files_for_transit.indicator_file = IPC::TakeFileHandleForProcess( 84 album_table_files_.indicator_file.Pass(), 85 utility_process_host_->GetData().handle); 86 files_for_transit.category_file = IPC::TakeFileHandleForProcess( 87 album_table_files_.category_file.Pass(), 88 utility_process_host_->GetData().handle); 89 files_for_transit.date_file = IPC::TakeFileHandleForProcess( 90 album_table_files_.date_file.Pass(), 91 utility_process_host_->GetData().handle); 92 files_for_transit.filename_file = IPC::TakeFileHandleForProcess( 93 album_table_files_.filename_file.Pass(), 94 utility_process_host_->GetData().handle); 95 files_for_transit.name_file = IPC::TakeFileHandleForProcess( 96 album_table_files_.name_file.Pass(), 97 utility_process_host_->GetData().handle); 98 files_for_transit.token_file = IPC::TakeFileHandleForProcess( 99 album_table_files_.token_file.Pass(), 100 utility_process_host_->GetData().handle); 101 files_for_transit.uid_file = IPC::TakeFileHandleForProcess( 102 album_table_files_.uid_file.Pass(), 103 utility_process_host_->GetData().handle); 104 utility_process_host_->Send(new ChromeUtilityMsg_ParsePicasaPMPDatabase( 105 files_for_transit)); 106 parser_state_ = STARTED_PARSING_STATE; 107} 108 109void SafePicasaAlbumTableReader::OnParsePicasaPMPDatabaseFinished( 110 bool parse_success, 111 const std::vector<AlbumInfo>& albums, 112 const std::vector<AlbumInfo>& folders) { 113 DCHECK_CURRENTLY_ON(BrowserThread::IO); 114 DCHECK(!callback_.is_null()); 115 if (parser_state_ != STARTED_PARSING_STATE) 116 return; 117 118 MediaFileSystemBackend::MediaTaskRunner()->PostTask( 119 FROM_HERE, base::Bind(callback_, parse_success, albums, folders)); 120 parser_state_ = FINISHED_PARSING_STATE; 121} 122 123void SafePicasaAlbumTableReader::OnProcessCrashed(int exit_code) { 124 DLOG(ERROR) << "SafePicasaAlbumTableReader::OnProcessCrashed()"; 125 OnParsePicasaPMPDatabaseFinished( 126 false, std::vector<AlbumInfo>(), std::vector<AlbumInfo>()); 127} 128 129bool SafePicasaAlbumTableReader::OnMessageReceived( 130 const IPC::Message& message) { 131 bool handled = true; 132 IPC_BEGIN_MESSAGE_MAP(SafePicasaAlbumTableReader, message) 133 IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_ProcessStarted, 134 OnProcessStarted) 135 IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_ParsePicasaPMPDatabase_Finished, 136 OnParsePicasaPMPDatabaseFinished) 137 IPC_MESSAGE_UNHANDLED(handled = false) 138 IPC_END_MESSAGE_MAP() 139 return handled; 140} 141 142} // namespace picasa 143