diff options
Diffstat (limited to 'chrome/browser/media_galleries')
3 files changed, 229 insertions, 3 deletions
diff --git a/chrome/browser/media_galleries/fileapi/picasa/picasa_data_provider.h b/chrome/browser/media_galleries/fileapi/picasa/picasa_data_provider.h index 51eff72..5f34d8a 100644 --- a/chrome/browser/media_galleries/fileapi/picasa/picasa_data_provider.h +++ b/chrome/browser/media_galleries/fileapi/picasa/picasa_data_provider.h @@ -19,11 +19,8 @@ namespace picasa { -struct AlbumInfo; class SafePicasaAlbumTableReader; -typedef std::map<std::string, AlbumInfo> AlbumMap; - // Created and owned by ImportedMediaGalleryRegistryTaskRunnerValues class PicasaDataProvider { public: diff --git a/chrome/browser/media_galleries/fileapi/safe_picasa_albums_indexer.cc b/chrome/browser/media_galleries/fileapi/safe_picasa_albums_indexer.cc new file mode 100644 index 0000000..57ea926 --- /dev/null +++ b/chrome/browser/media_galleries/fileapi/safe_picasa_albums_indexer.cc @@ -0,0 +1,141 @@ +// 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_albums_indexer.h" + +#include "base/file_util.h" +#include "chrome/browser/media_galleries/fileapi/media_file_system_backend.h" +#include "chrome/common/chrome_utility_messages.h" +#include "content/public/browser/browser_thread.h" +#include "content/public/browser/child_process_data.h" +#include "content/public/browser/utility_process_host.h" + +using chrome::MediaFileSystemBackend; +using content::BrowserThread; +using content::UtilityProcessHost; + +namespace picasa { + +namespace { + +// Picasa INI files are named "picasa.ini" on Picasa for Windows before version +// 71.18. Later versions and Picasa for Mac uses ".picasa.ini". +// See: https://support.google.com/picasa/answer/11257?hl=en +const char kPicasaINIFilename[] = ".picasa.ini"; +const char kPicasaINIFilenameLegacy[] = "picasa.ini"; + +// Arbitrarily chosen to be a decent size but not block thread too much. +const int kPicasaINIReadBatchSize = 10; + +} // namespace + +SafePicasaAlbumsIndexer::SafePicasaAlbumsIndexer( + const AlbumMap& albums, + const AlbumMap& folders, + const DoneCallback& callback) + : callback_(callback), + parser_state_(INITIAL_STATE) { + DCHECK(MediaFileSystemBackend::CurrentlyOnMediaTaskRunnerThread()); + DCHECK(!callback_.is_null()); + + folders_inis_.reserve(folders.size()); + + for (AlbumMap::const_iterator it = albums.begin(); it != albums.end(); ++it) + album_uids_.insert(it->second.uid); + + for (AlbumMap::const_iterator it = folders.begin(); it != folders.end(); ++it) + folders_queue_.push(it->second.path); +} + +void SafePicasaAlbumsIndexer::Start() { + DCHECK(MediaFileSystemBackend::CurrentlyOnMediaTaskRunnerThread()); + + ProcessFoldersBatch(); +} + +SafePicasaAlbumsIndexer::~SafePicasaAlbumsIndexer() { +} + +void SafePicasaAlbumsIndexer::ProcessFoldersBatch() { + DCHECK(MediaFileSystemBackend::CurrentlyOnMediaTaskRunnerThread()); + + for (int i = 0; i < kPicasaINIReadBatchSize && !folders_queue_.empty(); ++i) { + base::FilePath folder_path = folders_queue_.front(); + folders_queue_.pop(); + + folders_inis_.push_back(FolderINIContents()); + + bool ini_read = + file_util::ReadFileToString( + folder_path.AppendASCII(kPicasaINIFilename), + &folders_inis_.back().ini_contents) || + file_util::ReadFileToString( + folder_path.AppendASCII(kPicasaINIFilenameLegacy), + &folders_inis_.back().ini_contents); + + // See kPicasaINIFilename declaration for details. + if (ini_read) + folders_inis_.back().folder_path = folder_path; + else + folders_inis_.pop_back(); + } + + // If queue of folders to process not empty, post self onto task runner again. + if (!folders_queue_.empty()) { + MediaFileSystemBackend::MediaTaskRunner()->PostTask( + FROM_HERE, + base::Bind(&SafePicasaAlbumsIndexer::ProcessFoldersBatch, this)); + } else { + BrowserThread::PostTask( + BrowserThread::IO, + FROM_HERE, + base::Bind(&SafePicasaAlbumsIndexer::StartWorkOnIOThread, this)); + } +} + +void SafePicasaAlbumsIndexer::StartWorkOnIOThread() { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + DCHECK_EQ(INITIAL_STATE, parser_state_); + + UtilityProcessHost* host = + UtilityProcessHost::Create(this, base::MessageLoopProxy::current()); + host->EnableZygote(); + host->Send(new ChromeUtilityMsg_IndexPicasaAlbumsContents(album_uids_, + folders_inis_)); + parser_state_ = STARTED_PARSING_STATE; +} + +void SafePicasaAlbumsIndexer::OnIndexPicasaAlbumsContentsFinished( + const AlbumImagesMap& albums_images) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + if (parser_state_ != STARTED_PARSING_STATE) + return; + + MediaFileSystemBackend::MediaTaskRunner()->PostTask( + FROM_HERE, + base::Bind(callback_, true, albums_images)); + parser_state_ = FINISHED_PARSING_STATE; +} + +void SafePicasaAlbumsIndexer::OnProcessCrashed(int exit_code) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + + MediaFileSystemBackend::MediaTaskRunner()->PostTask( + FROM_HERE, + base::Bind(callback_, false, AlbumImagesMap())); +} + +bool SafePicasaAlbumsIndexer::OnMessageReceived( + const IPC::Message& message) { + bool handled = true; + IPC_BEGIN_MESSAGE_MAP(SafePicasaAlbumsIndexer, message) + IPC_MESSAGE_HANDLER( + ChromeUtilityHostMsg_IndexPicasaAlbumsContents_Finished, + OnIndexPicasaAlbumsContentsFinished) + IPC_MESSAGE_UNHANDLED(handled = false) + IPC_END_MESSAGE_MAP() + return handled; +} + +} // namespace picasa diff --git a/chrome/browser/media_galleries/fileapi/safe_picasa_albums_indexer.h b/chrome/browser/media_galleries/fileapi/safe_picasa_albums_indexer.h new file mode 100644 index 0000000..983652c --- /dev/null +++ b/chrome/browser/media_galleries/fileapi/safe_picasa_albums_indexer.h @@ -0,0 +1,88 @@ +// 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. + +#ifndef CHROME_BROWSER_MEDIA_GALLERIES_FILEAPI_SAFE_PICASA_ALBUMS_INDEXER_H_ +#define CHROME_BROWSER_MEDIA_GALLERIES_FILEAPI_SAFE_PICASA_ALBUMS_INDEXER_H_ + +#include <queue> +#include <vector> + +#include "base/callback.h" +#include "base/compiler_specific.h" +#include "base/memory/weak_ptr.h" +#include "chrome/common/media_galleries/picasa_types.h" +#include "content/public/browser/utility_process_host_client.h" + +namespace base { +class FilePath; +} + +namespace IPC { +class Message; +} + +namespace picasa { + +// SafePicasaAlbumsIndexer indexes the contents of Picasa Albums by parsing the +// INI files found in Folders. The SafePicasaAlbumsIndexer object is ref-counted +// and kept alive after Start() is called until the ParserCallback is called. +// The ParserCallback is guaranteed to be called eventually either when the +// utility process replies or when it dies. +class SafePicasaAlbumsIndexer : public content::UtilityProcessHostClient { + public: + typedef base::Callback<void(bool /* success */, + const picasa::AlbumImagesMap&)> DoneCallback; + + SafePicasaAlbumsIndexer(const AlbumMap& albums, + const AlbumMap& folders, + const DoneCallback& callback); + + void Start(); + + private: + enum ParserState { + INITIAL_STATE, + STARTED_PARSING_STATE, + FINISHED_PARSING_STATE, + }; + + // Private because content::UtilityProcessHostClient is ref-counted. + virtual ~SafePicasaAlbumsIndexer(); + + // Processes a batch of folders. Reposts itself until done, then starts IPC. + void ProcessFoldersBatch(); + + // Launches the utility process. Must run on the IO thread. + void StartWorkOnIOThread(); + + // Notification from the utility process when it finshes indexing all the + // album contents. On error will return an empty map. + // Runs on the IO thread. + void OnIndexPicasaAlbumsContentsFinished(const AlbumImagesMap& albums_images); + + // UtilityProcessHostClient implementation. + // Runs on the IO thread. + virtual void OnProcessCrashed(int exit_code) OVERRIDE; + virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE; + + AlbumUIDSet album_uids_; + + // List of folders that still need their INI files read. + std::queue<base::FilePath> folders_queue_; + + std::vector<picasa::FolderINIContents> folders_inis_; + + // Only accessed on the Media Task Runner. + const DoneCallback callback_; + + // Verifies the messages from the utility process came at the right time. + // Initialized on the Media Task Runner, but only accessed on the IO thread. + ParserState parser_state_; + + DISALLOW_COPY_AND_ASSIGN(SafePicasaAlbumsIndexer); +}; + +} // namespace picasa + +#endif // CHROME_BROWSER_MEDIA_GALLERIES_FILEAPI_SAFE_PICASA_ALBUMS_INDEXER_H_ |