Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / chrome / browser / media_galleries / fileapi / safe_picasa_albums_indexer.cc
blob06a2bf5ab29dd375276aff8e21de2f740506655f
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;
21 namespace picasa {
23 namespace {
25 // Arbitrarily chosen to be a decent size but not block thread too much.
26 const int kPicasaINIReadBatchSize = 10;
28 } // namespace
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());
53 callback_ = callback;
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();
65 folders_queue_.pop();
67 folders_inis_.push_back(FolderINIContents());
69 bool ini_read =
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.
78 if (ini_read)
79 folders_inis_.back().folder_path = folder_path;
80 else
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(
87 FROM_HERE,
88 base::Bind(&SafePicasaAlbumsIndexer::ProcessFoldersBatch, this));
89 } else {
90 BrowserThread::PostTask(
91 BrowserThread::IO,
92 FROM_HERE,
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_,
106 folders_inis_));
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)
115 return;
117 MediaFileSystemBackend::MediaTaskRunner()->PostTask(
118 FROM_HERE,
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(
128 FROM_HERE,
129 base::Bind(callback_, false, AlbumImagesMap()));
132 bool SafePicasaAlbumsIndexer::OnMessageReceived(
133 const IPC::Message& message) {
134 bool handled = true;
135 IPC_BEGIN_MESSAGE_MAP(SafePicasaAlbumsIndexer, message)
136 IPC_MESSAGE_HANDLER(
137 ChromeUtilityHostMsg_IndexPicasaAlbumsContents_Finished,
138 OnIndexPicasaAlbumsContentsFinished)
139 IPC_MESSAGE_UNHANDLED(handled = false)
140 IPC_END_MESSAGE_MAP()
141 return handled;
144 } // namespace picasa