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.
5 #include "chrome/browser/media_galleries/fileapi/safe_picasa_album_table_reader.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 "content/public/browser/browser_thread.h"
12 #include "content/public/browser/child_process_data.h"
14 using content::BrowserThread
;
18 SafePicasaAlbumTableReader::SafePicasaAlbumTableReader(
19 const AlbumTableFiles
& album_table_files
)
20 : album_table_files_(album_table_files
), parser_state_(INITIAL_STATE
) {
21 // TODO(tommycli): Add DCHECK to make sure |album_table_files| are all
22 // opened read-only once security adds ability to check PlatformFiles.
23 DCHECK(MediaFileSystemBackend::CurrentlyOnMediaTaskRunnerThread());
26 void SafePicasaAlbumTableReader::Start(const ParserCallback
& callback
) {
27 DCHECK(MediaFileSystemBackend::CurrentlyOnMediaTaskRunnerThread());
28 DCHECK(!callback
.is_null());
32 // Don't bother spawning process if any of the files are invalid.
33 if (album_table_files_
.indicator_file
== base::kInvalidPlatformFileValue
||
34 album_table_files_
.category_file
== base::kInvalidPlatformFileValue
||
35 album_table_files_
.date_file
== base::kInvalidPlatformFileValue
||
36 album_table_files_
.filename_file
== base::kInvalidPlatformFileValue
||
37 album_table_files_
.name_file
== base::kInvalidPlatformFileValue
||
38 album_table_files_
.token_file
== base::kInvalidPlatformFileValue
||
39 album_table_files_
.uid_file
== base::kInvalidPlatformFileValue
) {
40 MediaFileSystemBackend::MediaTaskRunner()->PostTask(
43 false /* parse_success */,
44 std::vector
<AlbumInfo
>(),
45 std::vector
<AlbumInfo
>()));
49 BrowserThread::PostTask(
52 base::Bind(&SafePicasaAlbumTableReader::StartWorkOnIOThread
, this));
55 SafePicasaAlbumTableReader::~SafePicasaAlbumTableReader() {
58 void SafePicasaAlbumTableReader::StartWorkOnIOThread() {
59 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
60 DCHECK_EQ(INITIAL_STATE
, parser_state_
);
62 utility_process_host_
= content::UtilityProcessHost::Create(
64 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO
).get())
66 // Wait for the startup notification before sending the main IPC to the
67 // utility process, so that we can dup the file handle.
68 utility_process_host_
->Send(new ChromeUtilityMsg_StartupPing
);
69 parser_state_
= PINGED_UTILITY_PROCESS_STATE
;
72 void SafePicasaAlbumTableReader::OnProcessStarted() {
73 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
74 if (parser_state_
!= PINGED_UTILITY_PROCESS_STATE
)
77 if (utility_process_host_
->GetData().handle
== base::kNullProcessHandle
) {
78 DLOG(ERROR
) << "Child process handle is null";
80 AlbumTableFilesForTransit files_for_transit
;
81 files_for_transit
.indicator_file
= IPC::GetFileHandleForProcess(
82 album_table_files_
.indicator_file
,
83 utility_process_host_
->GetData().handle
,
84 true /* close_source_handle */);
85 files_for_transit
.category_file
= IPC::GetFileHandleForProcess(
86 album_table_files_
.category_file
,
87 utility_process_host_
->GetData().handle
,
88 true /* close_source_handle */);
89 files_for_transit
.date_file
= IPC::GetFileHandleForProcess(
90 album_table_files_
.date_file
,
91 utility_process_host_
->GetData().handle
,
92 true /* close_source_handle */);
93 files_for_transit
.filename_file
= IPC::GetFileHandleForProcess(
94 album_table_files_
.filename_file
,
95 utility_process_host_
->GetData().handle
,
96 true /* close_source_handle */);
97 files_for_transit
.name_file
= IPC::GetFileHandleForProcess(
98 album_table_files_
.name_file
,
99 utility_process_host_
->GetData().handle
,
100 true /* close_source_handle */);
101 files_for_transit
.token_file
= IPC::GetFileHandleForProcess(
102 album_table_files_
.token_file
,
103 utility_process_host_
->GetData().handle
,
104 true /* close_source_handle */);
105 files_for_transit
.uid_file
= IPC::GetFileHandleForProcess(
106 album_table_files_
.uid_file
,
107 utility_process_host_
->GetData().handle
,
108 true /* close_source_handle */);
109 utility_process_host_
->Send(new ChromeUtilityMsg_ParsePicasaPMPDatabase(
111 parser_state_
= STARTED_PARSING_STATE
;
114 void SafePicasaAlbumTableReader::OnParsePicasaPMPDatabaseFinished(
116 const std::vector
<AlbumInfo
>& albums
,
117 const std::vector
<AlbumInfo
>& folders
) {
118 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
119 DCHECK(!callback_
.is_null());
120 if (parser_state_
!= STARTED_PARSING_STATE
)
123 MediaFileSystemBackend::MediaTaskRunner()->PostTask(
124 FROM_HERE
, base::Bind(callback_
, parse_success
, albums
, folders
));
125 parser_state_
= FINISHED_PARSING_STATE
;
128 void SafePicasaAlbumTableReader::OnProcessCrashed(int exit_code
) {
129 DLOG(ERROR
) << "SafePicasaAlbumTableReader::OnProcessCrashed()";
130 OnParsePicasaPMPDatabaseFinished(
131 false, std::vector
<AlbumInfo
>(), std::vector
<AlbumInfo
>());
134 bool SafePicasaAlbumTableReader::OnMessageReceived(
135 const IPC::Message
& message
) {
137 IPC_BEGIN_MESSAGE_MAP(SafePicasaAlbumTableReader
, message
)
138 IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_ProcessStarted
,
140 IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_ParsePicasaPMPDatabase_Finished
,
141 OnParsePicasaPMPDatabaseFinished
)
142 IPC_MESSAGE_UNHANDLED(handled
= false)
143 IPC_END_MESSAGE_MAP()
147 } // namespace picasa