Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / chrome / browser / extensions / api / streams_private / streams_private_api.cc
blob9b23daa259060714041caa8692157bcfe6aa9437
1 // Copyright (c) 2012 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.
5 #include "chrome/browser/extensions/api/streams_private/streams_private_api.h"
7 #include "base/lazy_instance.h"
8 #include "base/values.h"
9 #include "chrome/browser/extensions/extension_tab_util.h"
10 #include "chrome/common/extensions/api/streams_private.h"
11 #include "content/public/browser/stream_handle.h"
12 #include "content/public/browser/stream_info.h"
13 #include "extensions/browser/event_router.h"
14 #include "extensions/browser/extension_function_registry.h"
15 #include "extensions/browser/extension_registry.h"
16 #include "extensions/browser/guest_view/mime_handler_view/mime_handler_stream_manager.h"
17 #include "extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest.h"
18 #include "extensions/common/manifest_handlers/mime_types_handler.h"
19 #include "net/http/http_response_headers.h"
21 namespace extensions {
22 namespace {
24 void CreateResponseHeadersDictionary(const net::HttpResponseHeaders* headers,
25 base::DictionaryValue* result) {
26 if (!headers)
27 return;
29 void* iter = NULL;
30 std::string header_name;
31 std::string header_value;
32 while (headers->EnumerateHeaderLines(&iter, &header_name, &header_value)) {
33 base::Value* existing_value = NULL;
34 if (result->Get(header_name, &existing_value)) {
35 base::StringValue* existing_string_value =
36 static_cast<base::StringValue*>(existing_value);
37 existing_string_value->GetString()->append(", ").append(header_value);
38 } else {
39 result->SetString(header_name, header_value);
44 } // namespace
46 namespace streams_private = api::streams_private;
48 // static
49 StreamsPrivateAPI* StreamsPrivateAPI::Get(content::BrowserContext* context) {
50 return GetFactoryInstance()->Get(context);
53 StreamsPrivateAPI::StreamsPrivateAPI(content::BrowserContext* context)
54 : browser_context_(context),
55 extension_registry_observer_(this),
56 weak_ptr_factory_(this) {
57 extension_registry_observer_.Add(ExtensionRegistry::Get(browser_context_));
60 StreamsPrivateAPI::~StreamsPrivateAPI() {
63 void StreamsPrivateAPI::ExecuteMimeTypeHandler(
64 const std::string& extension_id,
65 content::WebContents* web_contents,
66 scoped_ptr<content::StreamInfo> stream,
67 const std::string& view_id,
68 int64 expected_content_size,
69 bool embedded,
70 int render_process_id,
71 int render_frame_id) {
72 const Extension* extension = ExtensionRegistry::Get(browser_context_)
73 ->enabled_extensions()
74 .GetByID(extension_id);
75 if (!extension)
76 return;
78 MimeTypesHandler* handler = MimeTypesHandler::GetHandler(extension);
79 // If the mime handler uses MimeHandlerViewGuest, the MimeHandlerViewGuest
80 // will take ownership of the stream. Otherwise, store the stream handle in
81 // |streams_| and fire an event notifying the extension.
82 if (handler->HasPlugin()) {
83 GURL handler_url(Extension::GetBaseURLFromExtensionId(extension_id).spec() +
84 handler->handler_url());
85 auto tab_id = ExtensionTabUtil::GetTabId(web_contents);
86 scoped_ptr<StreamContainer> stream_container(new StreamContainer(
87 stream.Pass(), tab_id, embedded, handler_url, extension_id));
88 MimeHandlerStreamManager::Get(browser_context_)
89 ->AddStream(view_id, stream_container.Pass(), render_process_id,
90 render_frame_id);
91 return;
93 // Create the event's arguments value.
94 streams_private::StreamInfo info;
95 info.mime_type = stream->mime_type;
96 info.original_url = stream->original_url.spec();
97 info.stream_url = stream->handle->GetURL().spec();
98 info.tab_id = ExtensionTabUtil::GetTabId(web_contents);
99 info.embedded = embedded;
101 if (!view_id.empty()) {
102 info.view_id.reset(new std::string(view_id));
105 int size = -1;
106 if (expected_content_size <= INT_MAX)
107 size = expected_content_size;
108 info.expected_content_size = size;
110 CreateResponseHeadersDictionary(stream->response_headers.get(),
111 &info.response_headers.additional_properties);
113 scoped_ptr<Event> event(
114 new Event(events::STREAMS_PRIVATE_ON_EXECUTE_MIME_TYPE_HANDLER,
115 streams_private::OnExecuteMimeTypeHandler::kEventName,
116 streams_private::OnExecuteMimeTypeHandler::Create(info)));
118 EventRouter::Get(browser_context_)
119 ->DispatchEventToExtension(extension_id, event.Pass());
121 GURL url = stream->handle->GetURL();
122 streams_[extension_id][url] = make_linked_ptr(stream->handle.release());
125 void StreamsPrivateAPI::AbortStream(const std::string& extension_id,
126 const GURL& stream_url,
127 const base::Closure& callback) {
128 StreamMap::iterator extension_it = streams_.find(extension_id);
129 if (extension_it == streams_.end()) {
130 callback.Run();
131 return;
134 StreamMap::mapped_type* url_map = &extension_it->second;
135 StreamMap::mapped_type::iterator url_it = url_map->find(stream_url);
136 if (url_it == url_map->end()) {
137 callback.Run();
138 return;
141 url_it->second->AddCloseListener(callback);
142 url_map->erase(url_it);
145 void StreamsPrivateAPI::OnExtensionUnloaded(
146 content::BrowserContext* browser_context,
147 const Extension* extension,
148 UnloadedExtensionInfo::Reason reason) {
149 streams_.erase(extension->id());
152 StreamsPrivateAbortFunction::StreamsPrivateAbortFunction() {
155 ExtensionFunction::ResponseAction StreamsPrivateAbortFunction::Run() {
156 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
157 EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &stream_url_));
158 StreamsPrivateAPI::Get(browser_context())->AbortStream(
159 extension_id(), GURL(stream_url_), base::Bind(
160 &StreamsPrivateAbortFunction::OnClose, this));
161 return RespondLater();
164 void StreamsPrivateAbortFunction::OnClose() {
165 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
166 Respond(NoArguments());
169 static base::LazyInstance<BrowserContextKeyedAPIFactory<StreamsPrivateAPI> >
170 g_factory = LAZY_INSTANCE_INITIALIZER;
172 // static
173 BrowserContextKeyedAPIFactory<StreamsPrivateAPI>*
174 StreamsPrivateAPI::GetFactoryInstance() {
175 return g_factory.Pointer();
178 } // namespace extensions