1a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
2a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// found in the LICENSE file.
4a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
5a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "chrome/utility/media_galleries/media_metadata_parser.h"
6a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
75d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include <string>
85d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
9a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "base/bind.h"
100529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#include "base/memory/linked_ptr.h"
11a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "base/message_loop/message_loop.h"
125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/strings/string_util.h"
13a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/task_runner_util.h"
14a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/threading/thread.h"
15a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch#include "chrome/utility/media_galleries/image_metadata_extractor.h"
165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "media/base/audio_video_metadata_extractor.h"
175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "media/base/data_source.h"
18cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "net/base/mime_sniffer.h"
19a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
200529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochnamespace MediaGalleries = extensions::api::media_galleries;
210529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
22a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)namespace metadata {
23a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace {
255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void SetStringScopedPtr(const std::string& value,
275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                        scoped_ptr<std::string>* destination) {
28a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  DCHECK(destination);
295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!value.empty())
305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    destination->reset(new std::string(value));
315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void SetIntScopedPtr(int value, scoped_ptr<int>* destination) {
34a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  DCHECK(destination);
355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (value >= 0)
365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    destination->reset(new int(value));
375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
39a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochvoid SetDoubleScopedPtr(double value, scoped_ptr<double>* destination) {
40a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  DCHECK(destination);
41a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  if (value >= 0)
42a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    destination->reset(new double(value));
43a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch}
44a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
45a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochvoid SetBoolScopedPtr(bool value, scoped_ptr<bool>* destination) {
46a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  DCHECK(destination);
47a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  destination->reset(new bool(value));
48a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch}
49a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
50a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// This runs on |media_thread_|, as the underlying FFmpeg operation is
51a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// blocking, and the utility thread must not be blocked, so the media file
52a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// bytes can be sent from the browser process to the utility process.
53cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void ParseAudioVideoMetadata(
54cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    media::DataSource* source, bool get_attached_images,
55cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    MediaMetadataParser::MediaMetadata* metadata,
56cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    std::vector<AttachedImage>* attached_images) {
57a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  DCHECK(source);
58cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK(metadata);
59a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  media::AudioVideoMetadataExtractor extractor;
60a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
61cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (!extractor.Extract(source, get_attached_images))
62cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return;
63a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
64a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (extractor.duration() >= 0)
65a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    metadata->duration.reset(new double(extractor.duration()));
66a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
67a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (extractor.height() >= 0 && extractor.width() >= 0) {
68a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    metadata->height.reset(new int(extractor.height()));
69a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    metadata->width.reset(new int(extractor.width()));
70a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
71a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
72a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  SetStringScopedPtr(extractor.artist(), &metadata->artist);
73a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  SetStringScopedPtr(extractor.album(), &metadata->album);
74a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  SetStringScopedPtr(extractor.artist(), &metadata->artist);
75a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  SetStringScopedPtr(extractor.comment(), &metadata->comment);
76a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  SetStringScopedPtr(extractor.copyright(), &metadata->copyright);
77a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  SetIntScopedPtr(extractor.disc(), &metadata->disc);
78a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  SetStringScopedPtr(extractor.genre(), &metadata->genre);
79a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  SetStringScopedPtr(extractor.language(), &metadata->language);
80a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  SetIntScopedPtr(extractor.rotation(), &metadata->rotation);
81a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  SetStringScopedPtr(extractor.title(), &metadata->title);
82a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  SetIntScopedPtr(extractor.track(), &metadata->track);
83a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
840529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  for (media::AudioVideoMetadataExtractor::StreamInfoVector::const_iterator it =
850529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch           extractor.stream_infos().begin();
860529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch       it != extractor.stream_infos().end(); ++it) {
870529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    linked_ptr<MediaGalleries::StreamInfo> stream_info(
880529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch        new MediaGalleries::StreamInfo);
890529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    stream_info->type = it->type;
900529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
910529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    for (std::map<std::string, std::string>::const_iterator tag_it =
920529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch             it->tags.begin();
930529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch         tag_it != it->tags.end(); ++tag_it) {
940529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      stream_info->tags.additional_properties.SetString(tag_it->first,
950529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch                                                        tag_it->second);
960529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    }
970529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
980529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    metadata->raw_tags.push_back(stream_info);
99c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
100c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
101cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (get_attached_images) {
102cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    for (std::vector<std::string>::const_iterator it =
103cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)             extractor.attached_images_bytes().begin();
104cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)         it != extractor.attached_images_bytes().end(); ++it) {
105cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      attached_images->push_back(AttachedImage());
106cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      attached_images->back().data = *it;
107cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      net::SniffMimeTypeFromLocalData(it->c_str(), it->length(),
108cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                      &attached_images->back().type);
109cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    }
110cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
111a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
112a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
113cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void FinishParseAudioVideoMetadata(
114a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    MediaMetadataParser::MetadataCallback callback,
115cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    MediaMetadataParser::MediaMetadata* metadata,
116cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    std::vector<AttachedImage>* attached_images) {
117cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK(!callback.is_null());
118cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK(metadata);
119cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK(attached_images);
120cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
121cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  callback.Run(*metadata, *attached_images);
122cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
123cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
124cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void FinishParseImageMetadata(
125cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    ImageMetadataExtractor* extractor, const std::string& mime_type,
126cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    MediaMetadataParser::MetadataCallback callback, bool extract_success) {
127a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  DCHECK(extractor);
128cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  MediaMetadataParser::MediaMetadata metadata;
129cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  metadata.mime_type = mime_type;
130a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
131a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  if (!extract_success) {
132cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    callback.Run(metadata, std::vector<AttachedImage>());
133a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    return;
134a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  }
135a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
136cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  SetIntScopedPtr(extractor->height(), &metadata.height);
137cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  SetIntScopedPtr(extractor->width(), &metadata.width);
138a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
139cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  SetIntScopedPtr(extractor->rotation(), &metadata.rotation);
140a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
141cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  SetDoubleScopedPtr(extractor->x_resolution(), &metadata.x_resolution);
142cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  SetDoubleScopedPtr(extractor->y_resolution(), &metadata.y_resolution);
143cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  SetBoolScopedPtr(extractor->flash_fired(), &metadata.flash_fired);
144cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  SetStringScopedPtr(extractor->camera_make(), &metadata.camera_make);
145cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  SetStringScopedPtr(extractor->camera_model(), &metadata.camera_model);
146a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  SetDoubleScopedPtr(extractor->exposure_time_sec(),
147cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                     &metadata.exposure_time_seconds);
148a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
149cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  SetDoubleScopedPtr(extractor->f_number(), &metadata.f_number);
150cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  SetDoubleScopedPtr(extractor->focal_length_mm(), &metadata.focal_length_mm);
151cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  SetDoubleScopedPtr(extractor->iso_equivalent(), &metadata.iso_equivalent);
152a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
153cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  callback.Run(metadata, std::vector<AttachedImage>());
154a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch}
155a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
1565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}  // namespace
1575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)MediaMetadataParser::MediaMetadataParser(media::DataSource* source,
159cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                         const std::string& mime_type,
160cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                         bool get_attached_images)
1615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    : source_(source),
162cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      mime_type_(mime_type),
163cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      get_attached_images_(get_attached_images) {
164a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
165a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
166a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)MediaMetadataParser::~MediaMetadataParser() {}
167a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
168a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void MediaMetadataParser::Start(const MetadataCallback& callback) {
169a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (StartsWithASCII(mime_type_, "audio/", true) ||
170a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      StartsWithASCII(mime_type_, "video/", true)) {
171cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    MediaMetadata* metadata = new MediaMetadata;
172cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    metadata->mime_type = mime_type_;
173cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    std::vector<AttachedImage>* attached_images =
174cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        new std::vector<AttachedImage>;
175cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
176a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    media_thread_.reset(new base::Thread("media_thread"));
177a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    CHECK(media_thread_->Start());
178cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    media_thread_->message_loop_proxy()->PostTaskAndReply(
179a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        FROM_HERE,
180cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        base::Bind(&ParseAudioVideoMetadata, source_, get_attached_images_,
181cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                   metadata, attached_images),
182cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        base::Bind(&FinishParseAudioVideoMetadata, callback,
183cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                   base::Owned(metadata), base::Owned(attached_images)));
1845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
1855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
187a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  if (StartsWithASCII(mime_type_, "image/", true)) {
188a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    ImageMetadataExtractor* extractor = new ImageMetadataExtractor;
189a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    extractor->Extract(
190a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch        source_,
191a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch        base::Bind(&FinishParseImageMetadata, base::Owned(extractor),
192cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                   mime_type_, callback));
193a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    return;
194a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  }
195a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
196cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  callback.Run(MediaMetadata(), std::vector<AttachedImage>());
1975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
199a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}  // namespace metadata
200