Commit 74ce234c authored by tommycli@chromium.org's avatar tommycli@chromium.org

Media Galleries API Metadata: SafeMediaMetadataParser and IPCTunnelDataReader.

BUG=318450

Review URL: https://codereview.chromium.org/103283003

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@244310 0039d316-1c4b-4281-b951-d872f2087c98
parent 611aae68
// Copyright 2014 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_media_metadata_parser.h"
#include "chrome/browser/extensions/blob_reader.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 content::BrowserThread;
namespace metadata {
namespace {
// Completes the Blob byte request by forwarding it to the utility process.
void OnBlobReaderDone(
const base::WeakPtr<content::UtilityProcessHost>& utility_process_host,
int64 request_id,
scoped_ptr<std::string> data) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
if (!utility_process_host.get())
return;
utility_process_host->Send(new ChromeUtilityMsg_RequestBlobBytes_Finished(
request_id, *data));
}
} // namespace
SafeMediaMetadataParser::SafeMediaMetadataParser(Profile* profile,
const std::string& blob_uuid,
int64 blob_size,
const std::string& mime_type)
: profile_(profile),
blob_uuid_(blob_uuid),
blob_size_(blob_size),
mime_type_(mime_type),
parser_state_(INITIAL_STATE) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
}
void SafeMediaMetadataParser::Start(const DoneCallback& callback) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
BrowserThread::PostTask(
BrowserThread::IO,
FROM_HERE,
base::Bind(&SafeMediaMetadataParser::StartWorkOnIOThread, this,
callback));
}
SafeMediaMetadataParser::~SafeMediaMetadataParser() {
}
void SafeMediaMetadataParser::StartWorkOnIOThread(
const DoneCallback& callback) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
DCHECK_EQ(INITIAL_STATE, parser_state_);
DCHECK(!callback.is_null());
callback_ = callback;
utility_process_host_ = content::UtilityProcessHost::Create(
this, base::MessageLoopProxy::current())->AsWeakPtr();
utility_process_host_->Send(
new ChromeUtilityMsg_ParseMediaMetadata(mime_type_, blob_size_));
parser_state_ = STARTED_PARSING_STATE;
}
void SafeMediaMetadataParser::OnParseMediaMetadataFinished(
bool parse_success, const base::DictionaryValue& metadata_dictionary) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
DCHECK(!callback_.is_null());
if (parser_state_ != STARTED_PARSING_STATE)
return;
BrowserThread::PostTask(
BrowserThread::UI,
FROM_HERE,
base::Bind(callback_, parse_success,
base::Owned(metadata_dictionary.DeepCopy())));
parser_state_ = FINISHED_PARSING_STATE;
}
void SafeMediaMetadataParser::OnUtilityProcessRequestBlobBytes(
int64 request_id, int64 byte_start, int64 length) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
// BlobReader is self-deleting.
BlobReader* reader = new BlobReader(
profile_,
blob_uuid_,
base::Bind(&OnBlobReaderDone, utility_process_host_, request_id));
reader->SetByteRange(byte_start, length);
reader->Start();
}
void SafeMediaMetadataParser::OnProcessCrashed(int exit_code) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
DCHECK(!callback_.is_null());
BrowserThread::PostTask(
BrowserThread::UI,
FROM_HERE,
base::Bind(callback_, false, base::Owned(new base::DictionaryValue)));
parser_state_ = FINISHED_PARSING_STATE;
}
bool SafeMediaMetadataParser::OnMessageReceived(const IPC::Message& message) {
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(SafeMediaMetadataParser, message)
IPC_MESSAGE_HANDLER(
ChromeUtilityHostMsg_ParseMediaMetadata_Finished,
OnParseMediaMetadataFinished)
IPC_MESSAGE_HANDLER(
ChromeUtilityHostMsg_RequestBlobBytes,
OnUtilityProcessRequestBlobBytes)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
return handled;
}
} // namespace metadata
// Copyright 2014 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_MEDIA_METADATA_PARSER_H_
#define CHROME_BROWSER_MEDIA_GALLERIES_FILEAPI_SAFE_MEDIA_METADATA_PARSER_H_
#include "base/callback.h"
#include "base/compiler_specific.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
#include "chrome/common/extensions/api/media_galleries.h"
#include "content/public/browser/utility_process_host.h"
#include "content/public/browser/utility_process_host_client.h"
namespace IPC {
class Message;
}
class Profile;
namespace metadata {
// Parses the media metadata of a Blob safely in a utility process. This class
// expects the MIME type of the Blob to be already determined. It spawns a
// utility process to do further MIME-type specific metadata extraction.
// All public methods and callbacks of this class run on the UI thread.
class SafeMediaMetadataParser : public content::UtilityProcessHostClient {
public:
// |metadata_dictionary| is owned by the callback.
typedef base::Callback<
void(bool parse_success, base::DictionaryValue* metadata_dictionary)>
DoneCallback;
SafeMediaMetadataParser(Profile* profile, const std::string& blob_uuid,
int64 blob_size, const std::string& mime_type);
// Should be called on the UI thread. |callback| also runs on the UI thread.
void Start(const DoneCallback& callback);
private:
enum ParserState {
INITIAL_STATE,
STARTED_PARSING_STATE,
FINISHED_PARSING_STATE,
};
// Private because content::UtilityProcessHostClient is ref-counted.
virtual ~SafeMediaMetadataParser();
// Launches the utility process. Must run on the IO thread.
void StartWorkOnIOThread(const DoneCallback& callback);
// Notification from the utility process when it finishes parsing metadata.
// Runs on the IO thread.
void OnParseMediaMetadataFinished(
bool parse_success,
const base::DictionaryValue& metadata_dictionary);
// Notification when the utility process requests a byte range from the blob.
// Runs on the IO thread.
void OnUtilityProcessRequestBlobBytes(int64 request_id, int64 byte_start,
int64 length);
// UtilityProcessHostClient implementation.
// Runs on the IO thread.
virtual void OnProcessCrashed(int exit_code) OVERRIDE;
virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
// All member variables are only accessed on the IO thread.
Profile* const profile_;
const std::string blob_uuid_;
const int64 blob_size_;
const std::string mime_type_;
DoneCallback callback_;
base::WeakPtr<content::UtilityProcessHost> utility_process_host_;
// Verifies the messages from the utility process came at the right time.
// Initialized on the UI thread, but only accessed on the IO thread.
ParserState parser_state_;
DISALLOW_COPY_AND_ASSIGN(SafeMediaMetadataParser);
};
} // namespace metadata
#endif // CHROME_BROWSER_MEDIA_GALLERIES_FILEAPI_SAFE_MEDIA_METADATA_PARSER_H_
......@@ -288,6 +288,8 @@
'utility/importer/nss_decryptor_win.h',
'utility/importer/safari_importer.h',
'utility/importer/safari_importer.mm',
'utility/media_galleries/ipc_data_source.cc',
'utility/media_galleries/ipc_data_source.h',
'utility/media_galleries/itunes_pref_parser_win.cc',
'utility/media_galleries/itunes_pref_parser_win.h',
'utility/media_galleries/media_metadata_parser.cc',
......
......@@ -1113,6 +1113,8 @@
'browser/media_galleries/fileapi/picasa_finder_mac.mm',
'browser/media_galleries/fileapi/safe_audio_video_checker.cc',
'browser/media_galleries/fileapi/safe_audio_video_checker.h',
'browser/media_galleries/fileapi/safe_media_metadata_parser.cc',
'browser/media_galleries/fileapi/safe_media_metadata_parser.h',
'browser/media_galleries/fileapi/supported_audio_video_checker.cc',
'browser/media_galleries/fileapi/supported_audio_video_checker.h',
'browser/media_galleries/fileapi/supported_image_type_validator.cc',
......
......@@ -227,6 +227,14 @@ IPC_MESSAGE_CONTROL2(ChromeUtilityMsg_IndexPicasaAlbumsContents,
IPC_MESSAGE_CONTROL2(ChromeUtilityMsg_CheckMediaFile,
int64 /* milliseconds_of_decoding */,
IPC::PlatformFileForTransit /* Media file to parse */)
IPC_MESSAGE_CONTROL2(ChromeUtilityMsg_ParseMediaMetadata,
std::string /* mime_type */,
int64 /* total_size */)
IPC_MESSAGE_CONTROL2(ChromeUtilityMsg_RequestBlobBytes_Finished,
int64 /* request_id */,
std::string /* bytes */)
#endif // !defined(OS_ANDROID) && !defined(OS_IOS)
//------------------------------------------------------------------------------
......@@ -372,4 +380,13 @@ IPC_MESSAGE_CONTROL1(ChromeUtilityHostMsg_IndexPicasaAlbumsContents_Finished,
// the file appears to be a well formed media file.
IPC_MESSAGE_CONTROL1(ChromeUtilityHostMsg_CheckMediaFile_Finished,
bool /* passed_checks */)
IPC_MESSAGE_CONTROL2(ChromeUtilityHostMsg_ParseMediaMetadata_Finished,
bool /* parse_success */,
base::DictionaryValue /* metadata */)
IPC_MESSAGE_CONTROL3(ChromeUtilityHostMsg_RequestBlobBytes,
int64 /* request_id */,
int64 /* start_byte */,
int64 /* length */)
#endif // !defined(OS_ANDROID) && !defined(OS_IOS)
......@@ -11,7 +11,6 @@
#include "base/files/file_path.h"
#include "base/json/json_reader.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "base/path_service.h"
#include "base/scoped_native_library.h"
#include "base/time/time.h"
......@@ -61,6 +60,11 @@
#include "chrome/utility/media_galleries/picasa_albums_indexer.h"
#endif // defined(OS_WIN) || defined(OS_MACOSX)
#if !defined(OS_ANDROID) && !defined(OS_IOS)
#include "chrome/utility/media_galleries/ipc_data_source.h"
#include "chrome/utility/media_galleries/media_metadata_parser.h"
#endif // !defined(OS_ANDROID) && !defined(OS_IOS)
#if defined(ENABLE_FULL_PRINTING)
#include "chrome/common/crash_keys.h"
#include "printing/backend/print_backend.h"
......@@ -289,6 +293,14 @@ typedef PdfFunctionsWin PdfFunctions;
typedef PdfFunctionsBase PdfFunctions;
#endif // OS_WIN
#if !defined(OS_ANDROID) && !defined(OS_IOS)
void SendMediaMetadataToHost(
scoped_ptr<extensions::api::media_galleries::MediaMetadata> metadata) {
Send(new ChromeUtilityHostMsg_ParseMediaMetadata_Finished(
true, *(metadata->ToValue().get())));
}
#endif // !defined(OS_ANDROID) && !defined(OS_IOS)
static base::LazyInstance<PdfFunctions> g_pdf_lib = LAZY_INSTANCE_INITIALIZER;
} // namespace
......@@ -342,6 +354,8 @@ bool ChromeContentUtilityClient::OnMessageReceived(
#if !defined(OS_ANDROID) && !defined(OS_IOS)
IPC_MESSAGE_HANDLER(ChromeUtilityMsg_CheckMediaFile, OnCheckMediaFile)
IPC_MESSAGE_HANDLER(ChromeUtilityMsg_ParseMediaMetadata,
OnParseMediaMetadata)
#endif // !defined(OS_ANDROID) && !defined(OS_IOS)
#if defined(OS_CHROMEOS)
......@@ -759,6 +773,19 @@ void ChromeContentUtilityClient::OnCheckMediaFile(
Send(new ChromeUtilityHostMsg_CheckMediaFile_Finished(check_success));
ReleaseProcessIfNeeded();
}
void ChromeContentUtilityClient::OnParseMediaMetadata(
const std::string& mime_type,
int64 total_size) {
// Only one IPCDataSource may be created and added to the list of handlers.
CHECK(!media_metadata_parser_);
metadata::IPCDataSource* source = new metadata::IPCDataSource(total_size);
handlers_.push_back(source);
media_metadata_parser_.reset(new metadata::MediaMetadataParser(source,
mime_type));
media_metadata_parser_->Start(base::Bind(&SendMediaMetadataToHost));
}
#endif // !defined(OS_ANDROID) && !defined(OS_IOS)
#if defined(OS_WIN)
......
......@@ -6,6 +6,7 @@
#define CHROME_UTILITY_CHROME_CONTENT_UTILITY_CLIENT_H_
#include "base/compiler_specific.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/scoped_vector.h"
#include "base/platform_file.h"
#include "chrome/common/media_galleries/picasa_types.h"
......@@ -21,6 +22,10 @@ namespace gfx {
class Rect;
}
namespace metadata {
class MediaMetadataParser;
}
namespace printing {
class PdfRenderSettings;
struct PageRange;
......@@ -92,6 +97,7 @@ class ChromeContentUtilityClient : public content::ContentUtilityClient {
#if !defined(OS_ANDROID) && !defined(OS_IOS)
void OnCheckMediaFile(int64 milliseconds_of_decoding,
const IPC::PlatformFileForTransit& media_file);
void OnParseMediaMetadata(const std::string& mime_type, int64 total_size);
#endif // !defined(OS_ANDROID) && !defined(OS_IOS)
#if defined(OS_WIN)
......@@ -118,6 +124,10 @@ class ChromeContentUtilityClient : public content::ContentUtilityClient {
typedef ScopedVector<UtilityMessageHandler> Handlers;
Handlers handlers_;
#if !defined(OS_ANDROID) && !defined(OS_IOS)
scoped_ptr<metadata::MediaMetadataParser> media_metadata_parser_;
#endif // !defined(OS_ANDROID) && !defined(OS_IOS)
DISALLOW_COPY_AND_ASSIGN(ChromeContentUtilityClient);
};
......
// Copyright 2014 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/utility/media_galleries/ipc_data_source.h"
#include "chrome/common/chrome_utility_messages.h"
#include "content/public/utility/utility_thread.h"
namespace metadata {
IPCDataSource::IPCDataSource(int64 total_size)
: total_size_(total_size),
next_request_id_(0) {
}
IPCDataSource::~IPCDataSource() {}
void IPCDataSource::set_host(media::DataSourceHost* host) {
DataSource::set_host(host);
if (media::DataSource::host()) {
media::DataSource::host()->SetTotalBytes(total_size_);
}
}
void IPCDataSource::Stop(const base::Closure& callback) {
callback.Run();
}
void IPCDataSource::Read(int64 position, int size, uint8* data,
const DataSource::ReadCB& read_cb) {
CHECK_GE(total_size_, 0);
CHECK_GE(position, 0);
CHECK_GE(size, 0);
// Cap position and size within bounds.
position = std::min(position, total_size_);
int64 clamped_size =
std::min(static_cast<int64>(size), total_size_ - position);
int64 request_id = ++next_request_id_;
Request request;
request.destination = data;
request.callback = read_cb;
pending_requests_[request_id] = request;
content::UtilityThread::Get()->Send(new ChromeUtilityHostMsg_RequestBlobBytes(
request_id, position, clamped_size));
}
bool IPCDataSource::GetSize(int64* size_out) {
*size_out = total_size_;
return true;
}
bool IPCDataSource::IsStreaming() {
return false;
}
void IPCDataSource::SetBitrate(int bitrate) {
}
bool IPCDataSource::OnMessageReceived(const IPC::Message& message) {
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(IPCDataSource, message)
IPC_MESSAGE_HANDLER(ChromeUtilityMsg_RequestBlobBytes_Finished,
OnRequestBlobBytesFinished)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
return handled;
}
IPCDataSource::Request::Request()
: destination(NULL) {
}
IPCDataSource::Request::~Request() {
}
void IPCDataSource::OnRequestBlobBytesFinished(int64 request_id,
const std::string& bytes) {
std::map<int64, Request>::iterator it = pending_requests_.find(request_id);
if (it == pending_requests_.end())
return;
std::copy(bytes.begin(), bytes.end(), it->second.destination);
it->second.callback.Run(bytes.size());
pending_requests_.erase(it);
}
} // namespace metadata
// Copyright 2014 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_UTILITY_MEDIA_GALLERIES_IPC_DATA_SOURCE_H_
#define CHROME_UTILITY_MEDIA_GALLERIES_IPC_DATA_SOURCE_H_
#include <map>
#include <string>
#include "chrome/utility/utility_message_handler.h"
#include "media/base/data_source.h"
namespace metadata {
// Provides the metadata parser with bytes from the browser process via IPC.
class IPCDataSource: public media::DataSource,
public chrome::UtilityMessageHandler {
public:
explicit IPCDataSource(int64 total_size);
virtual ~IPCDataSource();
// Implementation of DataSource.
virtual void set_host(media::DataSourceHost* host) OVERRIDE;
virtual void Stop(const base::Closure& callback) OVERRIDE;
virtual void Read(int64 position, int size, uint8* data,
const ReadCB& read_cb) OVERRIDE;
virtual bool GetSize(int64* size_out) OVERRIDE;
virtual bool IsStreaming() OVERRIDE;
virtual void SetBitrate(int bitrate) OVERRIDE;
// Implementation of UtilityMessageHandler.
virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
private:
struct Request {
Request();
~Request();
uint8* destination;
ReadCB callback;
};
void OnRequestBlobBytesFinished(int64 request_id,
const std::string& bytes);
const int64 total_size_;
std::map<int64, Request> pending_requests_;
int64 next_request_id_;
};
} // namespace metadata
#endif // CHROME_UTILITY_MEDIA_GALLERIES_IPC_DATA_SOURCE_H_
......@@ -25,9 +25,8 @@ class MediaMetadataParser {
typedef extensions::api::media_galleries::MediaMetadata MediaMetadata;
typedef base::Callback<void(scoped_ptr<MediaMetadata>)> MetadataCallback;
// Does not take ownership of |source|. The MIME type is sniffed in the
// browser process, as it's faster (and safe enough). When the user wants
// more metadata than just the MIME type, this class provides it.
// Does not take ownership of |source|. Caller is responsible for ensuring
// that |source| outlives this object.
MediaMetadataParser(media::DataSource* source, const std::string& mime_type);
~MediaMetadataParser();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment