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_albums_indexer.h"
7 #include "base/files/file_util.h"
8 #include "base/single_thread_task_runner.h"
9 #include "base/thread_task_runner_handle.h"
10 #include "chrome/browser/media_galleries/fileapi/media_file_system_backend.h"
11 #include "chrome/common/extensions/chrome_utility_extensions_messages.h"
12 #include "chrome/grit/generated_resources.h"
13 #include "content/public/browser/browser_thread.h"
14 #include "content/public/browser/child_process_data.h"
15 #include "content/public/browser/utility_process_host.h"
16 #include "ui/base/l10n/l10n_util.h"
18 using content::BrowserThread
;
19 using content::UtilityProcessHost
;
25 // Arbitrarily chosen to be a decent size but not block thread too much.
26 const int kPicasaINIReadBatchSize
= 10;
30 // Picasa INI files are named "picasa.ini" on Picasa for Windows before version
31 // 71.18. Later versions and Picasa for Mac uses ".picasa.ini".
32 // See: https://support.google.com/picasa/answer/11257?hl=en
33 const char kPicasaINIFilenameLegacy
[] = "picasa.ini";
35 SafePicasaAlbumsIndexer::SafePicasaAlbumsIndexer(const AlbumMap
& albums
,
36 const AlbumMap
& folders
)
37 : parser_state_(INITIAL_STATE
) {
38 DCHECK(MediaFileSystemBackend::CurrentlyOnMediaTaskRunnerThread());
40 folders_inis_
.reserve(folders
.size());
42 for (AlbumMap::const_iterator it
= albums
.begin(); it
!= albums
.end(); ++it
)
43 album_uids_
.insert(it
->second
.uid
);
45 for (AlbumMap::const_iterator it
= folders
.begin(); it
!= folders
.end(); ++it
)
46 folders_queue_
.push(it
->second
.path
);
49 void SafePicasaAlbumsIndexer::Start(const DoneCallback
& callback
) {
50 DCHECK(MediaFileSystemBackend::CurrentlyOnMediaTaskRunnerThread());
51 DCHECK(!callback
.is_null());
54 ProcessFoldersBatch();
57 SafePicasaAlbumsIndexer::~SafePicasaAlbumsIndexer() {
60 void SafePicasaAlbumsIndexer::ProcessFoldersBatch() {
61 DCHECK(MediaFileSystemBackend::CurrentlyOnMediaTaskRunnerThread());
63 for (int i
= 0; i
< kPicasaINIReadBatchSize
&& !folders_queue_
.empty(); ++i
) {
64 base::FilePath folder_path
= folders_queue_
.front();
67 folders_inis_
.push_back(FolderINIContents());
70 base::ReadFileToString(
71 folder_path
.AppendASCII(kPicasaINIFilename
),
72 &folders_inis_
.back().ini_contents
) ||
73 base::ReadFileToString(
74 folder_path
.AppendASCII(kPicasaINIFilenameLegacy
),
75 &folders_inis_
.back().ini_contents
);
77 // See kPicasaINIFilename declaration for details.
79 folders_inis_
.back().folder_path
= folder_path
;
81 folders_inis_
.pop_back();
84 // If queue of folders to process not empty, post self onto task runner again.
85 if (!folders_queue_
.empty()) {
86 MediaFileSystemBackend::MediaTaskRunner()->PostTask(
88 base::Bind(&SafePicasaAlbumsIndexer::ProcessFoldersBatch
, this));
90 BrowserThread::PostTask(
93 base::Bind(&SafePicasaAlbumsIndexer::StartWorkOnIOThread
, this));
97 void SafePicasaAlbumsIndexer::StartWorkOnIOThread() {
98 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
99 DCHECK_EQ(INITIAL_STATE
, parser_state_
);
101 UtilityProcessHost
* host
=
102 UtilityProcessHost::Create(this, base::ThreadTaskRunnerHandle::Get());
103 host
->SetName(l10n_util::GetStringUTF16(
104 IDS_UTILITY_PROCESS_MEDIA_LIBRARY_FILE_CHECKER_NAME
));
105 host
->Send(new ChromeUtilityMsg_IndexPicasaAlbumsContents(album_uids_
,
107 parser_state_
= STARTED_PARSING_STATE
;
110 void SafePicasaAlbumsIndexer::OnIndexPicasaAlbumsContentsFinished(
111 const AlbumImagesMap
& albums_images
) {
112 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
113 DCHECK(!callback_
.is_null());
114 if (parser_state_
!= STARTED_PARSING_STATE
)
117 MediaFileSystemBackend::MediaTaskRunner()->PostTask(
119 base::Bind(callback_
, true, albums_images
));
120 parser_state_
= FINISHED_PARSING_STATE
;
123 void SafePicasaAlbumsIndexer::OnProcessCrashed(int exit_code
) {
124 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
125 DCHECK(!callback_
.is_null());
127 MediaFileSystemBackend::MediaTaskRunner()->PostTask(
129 base::Bind(callback_
, false, AlbumImagesMap()));
132 bool SafePicasaAlbumsIndexer::OnMessageReceived(
133 const IPC::Message
& message
) {
135 IPC_BEGIN_MESSAGE_MAP(SafePicasaAlbumsIndexer
, message
)
137 ChromeUtilityHostMsg_IndexPicasaAlbumsContents_Finished
,
138 OnIndexPicasaAlbumsContentsFinished
)
139 IPC_MESSAGE_UNHANDLED(handled
= false)
140 IPC_END_MESSAGE_MAP()
144 } // namespace picasa