1 // Copyright 2014 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_media_metadata_parser.h" 6 7 #include "chrome/browser/extensions/blob_reader.h" 8 #include "chrome/common/chrome_utility_messages.h" 9 #include "content/public/browser/browser_thread.h" 10 #include "content/public/browser/child_process_data.h" 11 #include "content/public/browser/utility_process_host.h" 12 13 using content::BrowserThread; 14 15 namespace metadata { 16 17 SafeMediaMetadataParser::SafeMediaMetadataParser( 18 Profile* profile, const std::string& blob_uuid, int64 blob_size, 19 const std::string& mime_type, bool get_attached_images) 20 : profile_(profile), 21 blob_uuid_(blob_uuid), 22 blob_size_(blob_size), 23 mime_type_(mime_type), 24 get_attached_images_(get_attached_images), 25 parser_state_(INITIAL_STATE) { 26 DCHECK_CURRENTLY_ON(BrowserThread::UI); 27 } 28 29 void SafeMediaMetadataParser::Start(const DoneCallback& callback) { 30 DCHECK_CURRENTLY_ON(BrowserThread::UI); 31 32 BrowserThread::PostTask( 33 BrowserThread::IO, 34 FROM_HERE, 35 base::Bind(&SafeMediaMetadataParser::StartWorkOnIOThread, this, 36 callback)); 37 } 38 39 SafeMediaMetadataParser::~SafeMediaMetadataParser() { 40 } 41 42 void SafeMediaMetadataParser::StartWorkOnIOThread( 43 const DoneCallback& callback) { 44 DCHECK_CURRENTLY_ON(BrowserThread::IO); 45 DCHECK_EQ(INITIAL_STATE, parser_state_); 46 DCHECK(!callback.is_null()); 47 48 callback_ = callback; 49 50 utility_process_host_ = content::UtilityProcessHost::Create( 51 this, base::MessageLoopProxy::current())->AsWeakPtr(); 52 53 utility_process_host_->Send( 54 new ChromeUtilityMsg_ParseMediaMetadata(mime_type_, blob_size_, 55 get_attached_images_)); 56 57 parser_state_ = STARTED_PARSING_STATE; 58 } 59 60 void SafeMediaMetadataParser::OnParseMediaMetadataFinished( 61 bool parse_success, const base::DictionaryValue& metadata_dictionary, 62 const std::vector<AttachedImage>& attached_images) { 63 DCHECK_CURRENTLY_ON(BrowserThread::IO); 64 DCHECK(!callback_.is_null()); 65 66 if (parser_state_ != STARTED_PARSING_STATE) 67 return; 68 69 // We need to make a scoped copy of this vector since it will be destroyed 70 // at the end of the IPC message handler. 71 scoped_ptr<std::vector<metadata::AttachedImage> > attached_images_copy = 72 make_scoped_ptr(new std::vector<metadata::AttachedImage>( 73 attached_images)); 74 75 BrowserThread::PostTask( 76 BrowserThread::UI, 77 FROM_HERE, 78 base::Bind(callback_, parse_success, 79 base::Passed(make_scoped_ptr(metadata_dictionary.DeepCopy())), 80 base::Passed(&attached_images_copy))); 81 parser_state_ = FINISHED_PARSING_STATE; 82 } 83 84 void SafeMediaMetadataParser::OnUtilityProcessRequestBlobBytes( 85 int64 request_id, int64 byte_start, int64 length) { 86 DCHECK_CURRENTLY_ON(BrowserThread::IO); 87 BrowserThread::PostTask( 88 BrowserThread::UI, 89 FROM_HERE, 90 base::Bind(&SafeMediaMetadataParser::StartBlobReaderOnUIThread, this, 91 request_id, byte_start, length)); 92 } 93 94 void SafeMediaMetadataParser::StartBlobReaderOnUIThread( 95 int64 request_id, int64 byte_start, int64 length) { 96 DCHECK_CURRENTLY_ON(BrowserThread::UI); 97 98 // BlobReader is self-deleting. 99 BlobReader* reader = new BlobReader(profile_, blob_uuid_, base::Bind( 100 &SafeMediaMetadataParser::OnBlobReaderDoneOnUIThread, this, request_id)); 101 reader->SetByteRange(byte_start, length); 102 reader->Start(); 103 } 104 105 void SafeMediaMetadataParser::OnBlobReaderDoneOnUIThread( 106 int64 request_id, scoped_ptr<std::string> data, 107 int64 /* blob_total_size */) { 108 DCHECK_CURRENTLY_ON(BrowserThread::UI); 109 BrowserThread::PostTask( 110 BrowserThread::IO, 111 FROM_HERE, 112 base::Bind(&SafeMediaMetadataParser::FinishRequestBlobBytes, this, 113 request_id, base::Passed(data.Pass()))); 114 } 115 116 void SafeMediaMetadataParser::FinishRequestBlobBytes( 117 int64 request_id, scoped_ptr<std::string> data) { 118 DCHECK_CURRENTLY_ON(BrowserThread::IO); 119 if (!utility_process_host_.get()) 120 return; 121 utility_process_host_->Send(new ChromeUtilityMsg_RequestBlobBytes_Finished( 122 request_id, *data)); 123 } 124 125 void SafeMediaMetadataParser::OnProcessCrashed(int exit_code) { 126 DCHECK_CURRENTLY_ON(BrowserThread::IO); 127 DCHECK(!callback_.is_null()); 128 129 BrowserThread::PostTask( 130 BrowserThread::UI, 131 FROM_HERE, 132 base::Bind(callback_, false, 133 base::Passed(scoped_ptr<base::DictionaryValue>()), 134 base::Passed(scoped_ptr<std::vector<AttachedImage> >()))); 135 parser_state_ = FINISHED_PARSING_STATE; 136 } 137 138 bool SafeMediaMetadataParser::OnMessageReceived(const IPC::Message& message) { 139 bool handled = true; 140 IPC_BEGIN_MESSAGE_MAP(SafeMediaMetadataParser, message) 141 IPC_MESSAGE_HANDLER( 142 ChromeUtilityHostMsg_ParseMediaMetadata_Finished, 143 OnParseMediaMetadataFinished) 144 IPC_MESSAGE_HANDLER( 145 ChromeUtilityHostMsg_RequestBlobBytes, 146 OnUtilityProcessRequestBlobBytes) 147 IPC_MESSAGE_UNHANDLED(handled = false) 148 IPC_END_MESSAGE_MAP() 149 return handled; 150 } 151 152 } // namespace metadata 153