summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/browser/media_galleries/fileapi/picasa/picasa_data_provider.h3
-rw-r--r--chrome/browser/media_galleries/fileapi/safe_picasa_albums_indexer.cc141
-rw-r--r--chrome/browser/media_galleries/fileapi/safe_picasa_albums_indexer.h88
-rw-r--r--chrome/chrome_browser.gypi2
-rw-r--r--chrome/common/chrome_utility_messages.h16
-rw-r--r--chrome/common/media_galleries/picasa_types.h14
-rw-r--r--chrome/utility/chrome_content_utility_client.cc17
-rw-r--r--chrome/utility/chrome_content_utility_client.h13
-rw-r--r--chrome/utility/media_galleries/picasa_albums_indexer.cc11
-rw-r--r--chrome/utility/media_galleries/picasa_albums_indexer.h12
10 files changed, 293 insertions, 24 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_
diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi
index b901144..a55106d 100644
--- a/chrome/chrome_browser.gypi
+++ b/chrome/chrome_browser.gypi
@@ -2456,6 +2456,8 @@
'browser/media_galleries/fileapi/safe_itunes_pref_parser_win.h',
'browser/media_galleries/fileapi/safe_picasa_album_table_reader.cc',
'browser/media_galleries/fileapi/safe_picasa_album_table_reader.h',
+ 'browser/media_galleries/fileapi/safe_picasa_albums_indexer.cc',
+ 'browser/media_galleries/fileapi/safe_picasa_albums_indexer.h',
],
}],
['enable_extensions==1', {
diff --git a/chrome/common/chrome_utility_messages.h b/chrome/common/chrome_utility_messages.h
index 19eed81..f48b136 100644
--- a/chrome/common/chrome_utility_messages.h
+++ b/chrome/common/chrome_utility_messages.h
@@ -88,6 +88,11 @@ IPC_STRUCT_TRAITS_BEGIN(picasa::AlbumTableFilesForTransit)
IPC_STRUCT_TRAITS_MEMBER(uid_file)
IPC_STRUCT_TRAITS_END()
+IPC_STRUCT_TRAITS_BEGIN(picasa::FolderINIContents)
+ IPC_STRUCT_TRAITS_MEMBER(folder_path)
+ IPC_STRUCT_TRAITS_MEMBER(ini_contents)
+IPC_STRUCT_TRAITS_END()
+
//------------------------------------------------------------------------------
// Utility process messages:
// These are messages from the browser to the utility process.
@@ -176,6 +181,12 @@ IPC_MESSAGE_CONTROL1(ChromeUtilityMsg_ParseITunesLibraryXmlFile,
// listing of the user's Picasa albums and folders, along with metadata.
IPC_MESSAGE_CONTROL1(ChromeUtilityMsg_ParsePicasaPMPDatabase,
picasa::AlbumTableFilesForTransit /* album_table_files */)
+
+// Tells the utility process to index the Picasa user-created Album contents
+// by parsing all the INI files in Picasa Folders.
+IPC_MESSAGE_CONTROL2(ChromeUtilityMsg_IndexPicasaAlbumsContents,
+ picasa::AlbumUIDSet /* album_uids */,
+ std::vector<picasa::FolderINIContents> /* folders_inis */)
#endif // defined(OS_WIN) || defined(OS_MACOSX)
//------------------------------------------------------------------------------
@@ -295,4 +306,9 @@ IPC_MESSAGE_CONTROL3(ChromeUtilityHostMsg_ParsePicasaPMPDatabase_Finished,
bool /* parse_success */,
std::vector<picasa::AlbumInfo> /* albums */,
std::vector<picasa::AlbumInfo> /* folders */)
+
+// Reply after indexing the Picasa user-created Album contents by parsing all
+// the INI files in Picasa Folders.
+IPC_MESSAGE_CONTROL1(ChromeUtilityHostMsg_IndexPicasaAlbumsContents_Finished,
+ picasa::AlbumImagesMap /* albums_images */)
#endif // defined(OS_WIN) || defined(OS_MACOSX)
diff --git a/chrome/common/media_galleries/picasa_types.h b/chrome/common/media_galleries/picasa_types.h
index 58dcf32..e807bc1 100644
--- a/chrome/common/media_galleries/picasa_types.h
+++ b/chrome/common/media_galleries/picasa_types.h
@@ -5,6 +5,8 @@
#ifndef CHROME_COMMON_MEDIA_GALLERIES_PICASA_TYPES_H_
#define CHROME_COMMON_MEDIA_GALLERIES_PICASA_TYPES_H_
+#include <map>
+#include <set>
#include <string>
#include "base/files/file_path.h"
@@ -13,6 +15,13 @@
namespace picasa {
+struct AlbumInfo;
+
+typedef std::set<base::FilePath> AlbumImages;
+typedef std::set<std::string> AlbumUIDSet;
+typedef std::map<std::string, AlbumImages> AlbumImagesMap;
+typedef std::map<std::string, AlbumInfo> AlbumMap;
+
const char kPicasaAlbumTableName[] = "albumdata";
struct AlbumInfo {
@@ -56,6 +65,11 @@ struct AlbumTableFilesForTransit {
IPC::PlatformFileForTransit uid_file;
};
+struct FolderINIContents {
+ base::FilePath folder_path;
+ std::string ini_contents;
+};
+
void CloseAlbumTableFiles(AlbumTableFiles* table_files);
} // namespace picasa
diff --git a/chrome/utility/chrome_content_utility_client.cc b/chrome/utility/chrome_content_utility_client.cc
index b5db0fd..66303fa 100644
--- a/chrome/utility/chrome_content_utility_client.cc
+++ b/chrome/utility/chrome_content_utility_client.cc
@@ -43,9 +43,9 @@
#endif // defined(OS_WIN)
#if defined(OS_WIN) || defined(OS_MACOSX)
-#include "chrome/common/media_galleries/picasa_types.h"
#include "chrome/utility/itunes_library_parser.h"
#include "chrome/utility/media_galleries/picasa_album_table_reader.h"
+#include "chrome/utility/media_galleries/picasa_albums_indexer.h"
#endif // defined(OS_WIN) || defined(OS_MACOSX)
#if defined(ENABLE_PRINTING)
@@ -562,6 +562,21 @@ void ChromeContentUtilityClient::OnParsePicasaPMPDatabase(
reader.folders()));
ReleaseProcessIfNeeded();
}
+
+void OnIndexPicasaAlbumsContents(
+ const picasa::AlbumUIDSet& album_uids,
+ const std::vector<picasa::FolderINIContents>& folders_inis) {
+ picasa::PicasaAlbumsIndexer indexer(album_uids);
+ for (std::vector<picasa::FolderINIContents>::const_iterator it =
+ folders_inis.begin();
+ it != folders_inis.end(); ++it) {
+ indexer.ParseFolderINI(it->folder_path, it->ini_contents);
+ }
+
+ Send(new ChromeUtilityHostMsg_IndexPicasaAlbumsContents_Finished(
+ indexer.albums_images()));
+ ReleaseProcessIfNeeded();
+}
#endif // defined(OS_WIN) || defined(OS_MACOSX)
} // namespace chrome
diff --git a/chrome/utility/chrome_content_utility_client.h b/chrome/utility/chrome_content_utility_client.h
index c155cf5..419c155 100644
--- a/chrome/utility/chrome_content_utility_client.h
+++ b/chrome/utility/chrome_content_utility_client.h
@@ -8,6 +8,7 @@
#include "base/compiler_specific.h"
#include "base/memory/scoped_vector.h"
#include "base/platform_file.h"
+#include "chrome/common/media_galleries/picasa_types.h"
#include "content/public/utility/content_utility_client.h"
#include "ipc/ipc_platform_file.h"
#include "printing/pdf_render_settings.h"
@@ -21,10 +22,6 @@ namespace gfx {
class Rect;
}
-namespace picasa {
-struct AlbumTableFilesForTransit;
-}
-
namespace printing {
struct PageRange;
}
@@ -91,11 +88,15 @@ class ChromeContentUtilityClient : public content::ContentUtilityClient {
#endif // defined(OS_WIN)
#if defined(OS_WIN) || defined(OS_MACOSX)
+ void OnParseITunesLibraryXmlFile(
+ IPC::PlatformFileForTransit itunes_library_file);
+
void OnParsePicasaPMPDatabase(
const picasa::AlbumTableFilesForTransit& album_table_files);
- void OnParseITunesLibraryXmlFile(
- IPC::PlatformFileForTransit itunes_library_file);
+ void OnIndexPicasaAlbumsContents(
+ const picasa::AlbumUIDSet& album_uids,
+ const std::vector<picasa::FolderINIContents>& folders_inis);
#endif // defined(OS_WIN) || defined(OS_MACOSX)
typedef ScopedVector<UtilityMessageHandler> Handlers;
diff --git a/chrome/utility/media_galleries/picasa_albums_indexer.cc b/chrome/utility/media_galleries/picasa_albums_indexer.cc
index a512e4e..87c7a47 100644
--- a/chrome/utility/media_galleries/picasa_albums_indexer.cc
+++ b/chrome/utility/media_galleries/picasa_albums_indexer.cc
@@ -43,7 +43,7 @@ class PicasaINIParser : public base::INIParser {
it != containing_albums.end(); ++it) {
AlbumImagesMap::iterator album_map_it = albums_images_->find(*it);
- // Ignore entry if the album UUID is not listed among in |album_uuids|
+ // Ignore entry if the album uid is not listed among in |album_uids|
// in the constructor. Happens if the PMP and INI files are inconsistent.
if (album_map_it == albums_images_->end())
continue;
@@ -59,11 +59,10 @@ class PicasaINIParser : public base::INIParser {
} // namespace
-PicasaAlbumsIndexer::PicasaAlbumsIndexer(
- const AlbumUUIDSet& album_uuids) {
- // Create an entry in the map for the valid album uuids.
- for (AlbumUUIDSet::const_iterator it = album_uuids.begin();
- it != album_uuids.end(); ++it) {
+PicasaAlbumsIndexer::PicasaAlbumsIndexer(const AlbumUIDSet& album_uids) {
+ // Create an entry in the map for the valid album uids.
+ for (AlbumUIDSet::const_iterator it = album_uids.begin();
+ it != album_uids.end(); ++it) {
albums_images_[*it] = AlbumImages();
}
}
diff --git a/chrome/utility/media_galleries/picasa_albums_indexer.h b/chrome/utility/media_galleries/picasa_albums_indexer.h
index 6bf9993..9cb180f 100644
--- a/chrome/utility/media_galleries/picasa_albums_indexer.h
+++ b/chrome/utility/media_galleries/picasa_albums_indexer.h
@@ -10,16 +10,12 @@
#include <string>
#include "base/files/file_path.h"
+#include "chrome/common/media_galleries/picasa_types.h"
namespace picasa {
-// Defined outside of class because used by IPC messages.
-typedef std::set<base::FilePath> AlbumImages;
-typedef std::set<std::string> AlbumUUIDSet;
-typedef std::map<std::string, AlbumImages> AlbumImagesMap;
-
// Parses a series of INI files and builds up the set of files contained within
-// the albums passed in through |album_uuids|.
+// the albums passed in through |album_uids|.
//
// Each INI file only describes the images contained within a single directory.
// To build the contents of all the albums, we read in all the INI files
@@ -28,7 +24,7 @@ typedef std::map<std::string, AlbumImages> AlbumImagesMap;
// The INI albums also contain ".album*" sections describing the albums that
// have pictures in the same directory as the INI. However, we use the PMP
// database as the authoritative source on Album metadata, so we ignore those
-// sections. The PMP derived |album_uuids| are passed in by the constructor.
+// sections. The PMP derived |album_uids| are passed in by the constructor.
//
// Example INI File:
//
@@ -48,7 +44,7 @@ typedef std::map<std::string, AlbumImages> AlbumImagesMap;
// albums=18cb2df48aaa98e1c276b45cfcd81c95
class PicasaAlbumsIndexer {
public:
- explicit PicasaAlbumsIndexer(const AlbumUUIDSet& album_uuids);
+ explicit PicasaAlbumsIndexer(const AlbumUIDSet& album_uids);
~PicasaAlbumsIndexer();
// This method should be called once for each Folder in the PMP database.