blob: b315fbcfa39b720017324618b205e00395deac32 [file] [log] [blame]
// Copyright 2013 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/media_galleries/fileapi/safe_picasa_album_table_reader.h"
#include "base/bind.h"
#include "base/logging.h"
#include "chrome/browser/media_galleries/fileapi/media_file_system_backend.h"
#include "chrome/common/chrome_utility_messages.h"
#include "chrome/common/extensions/chrome_utility_extensions_messages.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/child_process_data.h"
using content::BrowserThread;
namespace picasa {
SafePicasaAlbumTableReader::SafePicasaAlbumTableReader(
AlbumTableFiles album_table_files)
: album_table_files_(album_table_files.Pass()),
parser_state_(INITIAL_STATE) {
// TODO(tommycli): Add DCHECK to make sure |album_table_files| are all
// opened read-only once security adds ability to check PlatformFiles.
DCHECK(MediaFileSystemBackend::CurrentlyOnMediaTaskRunnerThread());
}
void SafePicasaAlbumTableReader::Start(const ParserCallback& callback) {
DCHECK(MediaFileSystemBackend::CurrentlyOnMediaTaskRunnerThread());
DCHECK(!callback.is_null());
callback_ = callback;
// Don't bother spawning process if any of the files are invalid.
if (!album_table_files_.indicator_file.IsValid() ||
!album_table_files_.category_file.IsValid() ||
!album_table_files_.date_file.IsValid() ||
!album_table_files_.filename_file.IsValid() ||
!album_table_files_.name_file.IsValid() ||
!album_table_files_.token_file.IsValid() ||
!album_table_files_.uid_file.IsValid()) {
MediaFileSystemBackend::MediaTaskRunner()->PostTask(
FROM_HERE,
base::Bind(callback_,
false /* parse_success */,
std::vector<AlbumInfo>(),
std::vector<AlbumInfo>()));
return;
}
BrowserThread::PostTask(
BrowserThread::IO,
FROM_HERE,
base::Bind(&SafePicasaAlbumTableReader::StartWorkOnIOThread, this));
}
SafePicasaAlbumTableReader::~SafePicasaAlbumTableReader() {
}
void SafePicasaAlbumTableReader::StartWorkOnIOThread() {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
DCHECK_EQ(INITIAL_STATE, parser_state_);
utility_process_host_ = content::UtilityProcessHost::Create(
this,
BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO).get())
->AsWeakPtr();
// Wait for the startup notification before sending the main IPC to the
// utility process, so that we can dup the file handle.
utility_process_host_->Send(new ChromeUtilityMsg_StartupPing);
parser_state_ = PINGED_UTILITY_PROCESS_STATE;
}
void SafePicasaAlbumTableReader::OnProcessStarted() {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
if (parser_state_ != PINGED_UTILITY_PROCESS_STATE)
return;
if (utility_process_host_->GetData().handle == base::kNullProcessHandle) {
DLOG(ERROR) << "Child process handle is null";
}
AlbumTableFilesForTransit files_for_transit;
files_for_transit.indicator_file = IPC::TakeFileHandleForProcess(
album_table_files_.indicator_file.Pass(),
utility_process_host_->GetData().handle);
files_for_transit.category_file = IPC::TakeFileHandleForProcess(
album_table_files_.category_file.Pass(),
utility_process_host_->GetData().handle);
files_for_transit.date_file = IPC::TakeFileHandleForProcess(
album_table_files_.date_file.Pass(),
utility_process_host_->GetData().handle);
files_for_transit.filename_file = IPC::TakeFileHandleForProcess(
album_table_files_.filename_file.Pass(),
utility_process_host_->GetData().handle);
files_for_transit.name_file = IPC::TakeFileHandleForProcess(
album_table_files_.name_file.Pass(),
utility_process_host_->GetData().handle);
files_for_transit.token_file = IPC::TakeFileHandleForProcess(
album_table_files_.token_file.Pass(),
utility_process_host_->GetData().handle);
files_for_transit.uid_file = IPC::TakeFileHandleForProcess(
album_table_files_.uid_file.Pass(),
utility_process_host_->GetData().handle);
utility_process_host_->Send(new ChromeUtilityMsg_ParsePicasaPMPDatabase(
files_for_transit));
parser_state_ = STARTED_PARSING_STATE;
}
void SafePicasaAlbumTableReader::OnParsePicasaPMPDatabaseFinished(
bool parse_success,
const std::vector<AlbumInfo>& albums,
const std::vector<AlbumInfo>& folders) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
DCHECK(!callback_.is_null());
if (parser_state_ != STARTED_PARSING_STATE)
return;
MediaFileSystemBackend::MediaTaskRunner()->PostTask(
FROM_HERE, base::Bind(callback_, parse_success, albums, folders));
parser_state_ = FINISHED_PARSING_STATE;
}
void SafePicasaAlbumTableReader::OnProcessCrashed(int exit_code) {
DLOG(ERROR) << "SafePicasaAlbumTableReader::OnProcessCrashed()";
OnParsePicasaPMPDatabaseFinished(
false, std::vector<AlbumInfo>(), std::vector<AlbumInfo>());
}
bool SafePicasaAlbumTableReader::OnMessageReceived(
const IPC::Message& message) {
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(SafePicasaAlbumTableReader, message)
IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_ProcessStarted,
OnProcessStarted)
IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_ParsePicasaPMPDatabase_Finished,
OnParsePicasaPMPDatabaseFinished)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
return handled;
}
} // namespace picasa