summaryrefslogtreecommitdiffstats
path: root/chrome/browser/media_galleries
diff options
context:
space:
mode:
authortommycli@chromium.org <tommycli@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-07-26 17:45:36 +0000
committertommycli@chromium.org <tommycli@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-07-26 17:45:36 +0000
commit7bbf03c589baa5f2bc26b3748c84ccd979e056de (patch)
tree9e7e0b6c0d06a4883c47607e80223e187ad673fa /chrome/browser/media_galleries
parent30026af7347b33f5cdc72804bbc5c2833256f65d (diff)
downloadchromium_src-7bbf03c589baa5f2bc26b3748c84ccd979e056de.zip
chromium_src-7bbf03c589baa5f2bc26b3748c84ccd979e056de.tar.gz
chromium_src-7bbf03c589baa5f2bc26b3748c84ccd979e056de.tar.bz2
Media Galleries API Picasa: Put INI indexing step into sandboxed utility process.
Picasa parses all the INI files in the Folders to build up an index of the album contents. This sandboxes that operation into the utility process. BUG=151701 Review URL: https://chromiumcodereview.appspot.com/18562007 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@213948 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/media_galleries')
-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
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_