- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / browser / media_galleries / fileapi / safe_picasa_albums_indexer.cc
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_albums_indexer.h"
6
7 #include "base/file_util.h"
8 #include "chrome/browser/media_galleries/fileapi/media_file_system_backend.h"
9 #include "chrome/common/chrome_utility_messages.h"
10 #include "content/public/browser/browser_thread.h"
11 #include "content/public/browser/child_process_data.h"
12 #include "content/public/browser/utility_process_host.h"
13
14 using content::BrowserThread;
15 using content::UtilityProcessHost;
16
17 namespace picasa {
18
19 namespace {
20
21 // Arbitrarily chosen to be a decent size but not block thread too much.
22 const int kPicasaINIReadBatchSize = 10;
23
24 }  // namespace
25
26 // Picasa INI files are named "picasa.ini" on Picasa for Windows before version
27 // 71.18. Later versions and Picasa for Mac uses ".picasa.ini".
28 // See: https://support.google.com/picasa/answer/11257?hl=en
29 const char kPicasaINIFilenameLegacy[] = "picasa.ini";
30
31 SafePicasaAlbumsIndexer::SafePicasaAlbumsIndexer(const AlbumMap& albums,
32                                                  const AlbumMap& folders)
33     : parser_state_(INITIAL_STATE) {
34   DCHECK(MediaFileSystemBackend::CurrentlyOnMediaTaskRunnerThread());
35
36   folders_inis_.reserve(folders.size());
37
38   for (AlbumMap::const_iterator it = albums.begin(); it != albums.end(); ++it)
39     album_uids_.insert(it->second.uid);
40
41   for (AlbumMap::const_iterator it = folders.begin(); it != folders.end(); ++it)
42     folders_queue_.push(it->second.path);
43 }
44
45 void SafePicasaAlbumsIndexer::Start(const DoneCallback& callback) {
46   DCHECK(MediaFileSystemBackend::CurrentlyOnMediaTaskRunnerThread());
47   DCHECK(!callback.is_null());
48
49   callback_ = callback;
50   ProcessFoldersBatch();
51 }
52
53 SafePicasaAlbumsIndexer::~SafePicasaAlbumsIndexer() {
54 }
55
56 void SafePicasaAlbumsIndexer::ProcessFoldersBatch() {
57   DCHECK(MediaFileSystemBackend::CurrentlyOnMediaTaskRunnerThread());
58
59   for (int i = 0; i < kPicasaINIReadBatchSize && !folders_queue_.empty(); ++i) {
60     base::FilePath folder_path = folders_queue_.front();
61     folders_queue_.pop();
62
63     folders_inis_.push_back(FolderINIContents());
64
65     bool ini_read =
66         base::ReadFileToString(
67             folder_path.AppendASCII(kPicasaINIFilename),
68             &folders_inis_.back().ini_contents) ||
69         base::ReadFileToString(
70             folder_path.AppendASCII(kPicasaINIFilenameLegacy),
71             &folders_inis_.back().ini_contents);
72
73     // See kPicasaINIFilename declaration for details.
74     if (ini_read)
75       folders_inis_.back().folder_path = folder_path;
76     else
77       folders_inis_.pop_back();
78   }
79
80   // If queue of folders to process not empty, post self onto task runner again.
81   if (!folders_queue_.empty()) {
82     MediaFileSystemBackend::MediaTaskRunner()->PostTask(
83         FROM_HERE,
84         base::Bind(&SafePicasaAlbumsIndexer::ProcessFoldersBatch, this));
85   } else {
86     BrowserThread::PostTask(
87         BrowserThread::IO,
88         FROM_HERE,
89         base::Bind(&SafePicasaAlbumsIndexer::StartWorkOnIOThread, this));
90   }
91 }
92
93 void SafePicasaAlbumsIndexer::StartWorkOnIOThread() {
94   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
95   DCHECK_EQ(INITIAL_STATE, parser_state_);
96
97   UtilityProcessHost* host =
98       UtilityProcessHost::Create(this, base::MessageLoopProxy::current());
99   host->EnableZygote();
100   host->Send(new ChromeUtilityMsg_IndexPicasaAlbumsContents(album_uids_,
101                                                             folders_inis_));
102   parser_state_ = STARTED_PARSING_STATE;
103 }
104
105 void SafePicasaAlbumsIndexer::OnIndexPicasaAlbumsContentsFinished(
106     const AlbumImagesMap& albums_images) {
107   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
108   DCHECK(!callback_.is_null());
109   if (parser_state_ != STARTED_PARSING_STATE)
110     return;
111
112   MediaFileSystemBackend::MediaTaskRunner()->PostTask(
113       FROM_HERE,
114       base::Bind(callback_, true, albums_images));
115   parser_state_ = FINISHED_PARSING_STATE;
116 }
117
118 void SafePicasaAlbumsIndexer::OnProcessCrashed(int exit_code) {
119   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
120   DCHECK(!callback_.is_null());
121
122   MediaFileSystemBackend::MediaTaskRunner()->PostTask(
123       FROM_HERE,
124       base::Bind(callback_, false, AlbumImagesMap()));
125 }
126
127 bool SafePicasaAlbumsIndexer::OnMessageReceived(
128     const IPC::Message& message) {
129   bool handled = true;
130   IPC_BEGIN_MESSAGE_MAP(SafePicasaAlbumsIndexer, message)
131     IPC_MESSAGE_HANDLER(
132         ChromeUtilityHostMsg_IndexPicasaAlbumsContents_Finished,
133         OnIndexPicasaAlbumsContentsFinished)
134     IPC_MESSAGE_UNHANDLED(handled = false)
135   IPC_END_MESSAGE_MAP()
136   return handled;
137 }
138
139 }  // namespace picasa