Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(526)

Side by Side Diff: chrome/browser/extensions/api/streams_private/streams_private_api.cc

Issue 797183005: Add a mimeHandler extension API. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@streams-lifetime
Patch Set: Created 5 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/extensions/api/streams_private/streams_private_api.h" 5 #include "chrome/browser/extensions/api/streams_private/streams_private_api.h"
6 6
7 #include "base/lazy_instance.h" 7 #include "base/lazy_instance.h"
8 #include "base/values.h" 8 #include "base/values.h"
9 #include "chrome/browser/extensions/extension_tab_util.h" 9 #include "chrome/browser/extensions/extension_tab_util.h"
10 #include "chrome/common/extensions/api/streams_private.h" 10 #include "chrome/common/extensions/api/streams_private.h"
11 #include "chrome/common/extensions/manifest_handlers/mime_types_handler.h" 11 #include "chrome/common/extensions/manifest_handlers/mime_types_handler.h"
12 #include "content/public/browser/stream_handle.h" 12 #include "content/public/browser/stream_handle.h"
13 #include "content/public/browser/stream_info.h" 13 #include "content/public/browser/stream_info.h"
14 #include "extensions/browser/event_router.h" 14 #include "extensions/browser/event_router.h"
15 #include "extensions/browser/extension_function_registry.h" 15 #include "extensions/browser/extension_function_registry.h"
16 #include "extensions/browser/extension_registry.h" 16 #include "extensions/browser/extension_registry.h"
17 #include "extensions/browser/guest_view/guest_view_manager.h"
18 #include "extensions/browser/guest_view/mime_handler_view/mime_handler_stream_ma nager.h" 17 #include "extensions/browser/guest_view/mime_handler_view/mime_handler_stream_ma nager.h"
19 #include "extensions/browser/guest_view/mime_handler_view/mime_handler_view_gues t.h" 18 #include "extensions/browser/guest_view/mime_handler_view/mime_handler_view_gues t.h"
20 #include "net/http/http_response_headers.h" 19 #include "net/http/http_response_headers.h"
21 20
22 namespace extensions { 21 namespace extensions {
23 namespace { 22 namespace {
24 23
25 void CreateResponseHeadersDictionary(const net::HttpResponseHeaders* headers, 24 void CreateResponseHeadersDictionary(const net::HttpResponseHeaders* headers,
26 base::DictionaryValue* result) { 25 base::DictionaryValue* result) {
27 if (!headers) 26 if (!headers)
28 return; 27 return;
29 28
30 void* iter = NULL; 29 void* iter = NULL;
31 std::string header_name; 30 std::string header_name;
32 std::string header_value; 31 std::string header_value;
33 while (headers->EnumerateHeaderLines(&iter, &header_name, &header_value)) { 32 while (headers->EnumerateHeaderLines(&iter, &header_name, &header_value)) {
34 base::Value* existing_value = NULL; 33 base::Value* existing_value = NULL;
35 if (result->Get(header_name, &existing_value)) { 34 if (result->Get(header_name, &existing_value)) {
36 base::StringValue* existing_string_value = 35 base::StringValue* existing_string_value =
37 static_cast<base::StringValue*>(existing_value); 36 static_cast<base::StringValue*>(existing_value);
38 existing_string_value->GetString()->append(", ").append(header_value); 37 existing_string_value->GetString()->append(", ").append(header_value);
39 } else { 38 } else {
40 result->SetString(header_name, header_value); 39 result->SetString(header_name, header_value);
41 } 40 }
42 } 41 }
43 } 42 }
44 43
45 // If |guest_web_contents| has a MimeHandlerViewGuest with view id of |view_id|,
46 // abort it. Returns true if the MimeHandlerViewGuest has a matching view id.
47 bool MaybeAbortStreamInGuest(const std::string& view_id,
48 content::WebContents* guest_web_contents) {
49 auto guest = MimeHandlerViewGuest::FromWebContents(guest_web_contents);
50 if (!guest)
51 return false;
52 if (guest->view_id() != view_id)
53 return false;
54 auto stream = guest->GetStream();
55 if (stream)
56 stream->Abort();
57 return true;
58 }
59
60 } // namespace 44 } // namespace
61 45
62 namespace streams_private = api::streams_private; 46 namespace streams_private = api::streams_private;
63 47
64 // static 48 // static
65 StreamsPrivateAPI* StreamsPrivateAPI::Get(content::BrowserContext* context) { 49 StreamsPrivateAPI* StreamsPrivateAPI::Get(content::BrowserContext* context) {
66 return GetFactoryInstance()->Get(context); 50 return GetFactoryInstance()->Get(context);
67 } 51 }
68 52
69 StreamsPrivateAPI::StreamsPrivateAPI(content::BrowserContext* context) 53 StreamsPrivateAPI::StreamsPrivateAPI(content::BrowserContext* context)
(...skipping 14 matching lines...) Expand all
84 int64 expected_content_size, 68 int64 expected_content_size,
85 bool embedded, 69 bool embedded,
86 int render_process_id, 70 int render_process_id,
87 int render_frame_id) { 71 int render_frame_id) {
88 const Extension* extension = ExtensionRegistry::Get(browser_context_) 72 const Extension* extension = ExtensionRegistry::Get(browser_context_)
89 ->enabled_extensions() 73 ->enabled_extensions()
90 .GetByID(extension_id); 74 .GetByID(extension_id);
91 if (!extension) 75 if (!extension)
92 return; 76 return;
93 77
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->handler_url().empty()) {
83 GURL handler_url(Extension::GetBaseURLFromExtensionId(extension_id).spec() +
84 handler->handler_url());
85 MimeHandlerStreamManager::Get(browser_context_)
86 ->AddStream(
87 view_id,
88 make_scoped_ptr(new StreamContainer(
89 stream.Pass(), ExtensionTabUtil::GetTabId(web_contents),
90 expected_content_size, embedded, handler_url, extension_id)),
91 render_process_id, render_frame_id);
raymes 2015/01/12 05:26:04 Can we split this up into a few statements?? :)
Sam McNally 2015/01/12 07:13:35 Done.
92 return;
93 }
94 // Create the event's arguments value. 94 // Create the event's arguments value.
95 streams_private::StreamInfo info; 95 streams_private::StreamInfo info;
96 info.mime_type = stream->mime_type; 96 info.mime_type = stream->mime_type;
97 info.original_url = stream->original_url.spec(); 97 info.original_url = stream->original_url.spec();
98 info.stream_url = stream->handle->GetURL().spec(); 98 info.stream_url = stream->handle->GetURL().spec();
99 info.tab_id = ExtensionTabUtil::GetTabId(web_contents); 99 info.tab_id = ExtensionTabUtil::GetTabId(web_contents);
100 info.embedded = embedded; 100 info.embedded = embedded;
101 101
102 if (!view_id.empty()) { 102 if (!view_id.empty()) {
103 info.view_id.reset(new std::string(view_id)); 103 info.view_id.reset(new std::string(view_id));
104 } 104 }
105 105
106 int size = -1; 106 int size = -1;
107 if (expected_content_size <= INT_MAX) 107 if (expected_content_size <= INT_MAX)
108 size = expected_content_size; 108 size = expected_content_size;
109 info.expected_content_size = size; 109 info.expected_content_size = size;
110 110
111 CreateResponseHeadersDictionary(stream->response_headers.get(), 111 CreateResponseHeadersDictionary(stream->response_headers.get(),
112 &info.response_headers.additional_properties); 112 &info.response_headers.additional_properties);
113 113
114 scoped_ptr<Event> event( 114 scoped_ptr<Event> event(
115 new Event(streams_private::OnExecuteMimeTypeHandler::kEventName, 115 new Event(streams_private::OnExecuteMimeTypeHandler::kEventName,
116 streams_private::OnExecuteMimeTypeHandler::Create(info))); 116 streams_private::OnExecuteMimeTypeHandler::Create(info)));
117 117
118 EventRouter::Get(browser_context_) 118 EventRouter::Get(browser_context_)
119 ->DispatchEventToExtension(extension_id, event.Pass()); 119 ->DispatchEventToExtension(extension_id, event.Pass());
120 MimeTypesHandler* handler = MimeTypesHandler::GetHandler(extension);
121 GURL url = stream->handle->GetURL();
122 // If the mime handler uses MimeHandlerViewGuest, the MimeHandlerViewGuest
123 // will take ownership of the stream. Otherwise, store the stream handle in
124 // |streams_|.
125 if (handler->handler_url().empty()) {
126 streams_[extension_id][url] = make_linked_ptr(stream->handle.release());
raymes 2015/01/12 05:26:04 I think we might need this.
Sam McNally 2015/01/12 07:13:35 Done.
127 return;
128 }
129 120
130 GURL handler_url(Extension::GetBaseURLFromExtensionId(extension_id).spec() +
131 handler->handler_url() + "?id=" + view_id);
132 MimeHandlerStreamManager::Get(browser_context_)
133 ->AddStream(view_id, make_scoped_ptr(new StreamContainer(
134 stream.Pass(), handler_url, extension_id)),
135 render_process_id, render_frame_id);
136 // If the mime handler uses MimeHandlerViewGuest, we need to be able to look
137 // up the MimeHandlerViewGuest instance that is handling the streamed
138 // resource in order to abort the stream. The embedding WebContents and the
139 // view id are necessary to perform that lookup.
140 mime_handler_streams_[extension_id][url] =
141 std::make_pair(web_contents, view_id);
142 } 121 }
143 122
144 void StreamsPrivateAPI::AbortStream(const std::string& extension_id, 123 void StreamsPrivateAPI::AbortStream(const std::string& extension_id,
145 const GURL& stream_url, 124 const GURL& stream_url,
146 const base::Closure& callback) { 125 const base::Closure& callback) {
147 auto streams = mime_handler_streams_.find(extension_id);
148 if (streams != mime_handler_streams_.end()) {
149 auto stream_info = streams->second.find(stream_url);
150 if (stream_info != streams->second.end()) {
151 auto stream = MimeHandlerStreamManager::Get(browser_context_)
152 ->GetStream(stream_info->second.second);
153 // If the mime handler uses MimeHandlerViewGuest, the stream will either
154 // be owned by the particular MimeHandlerViewGuest if it has been created,
155 // or by the MimeHandleStreamManager, otherwise.
156 if (!stream) {
157 GuestViewManager::FromBrowserContext(browser_context_)
158 ->ForEachGuest(stream_info->second.first,
159 base::Bind(&MaybeAbortStreamInGuest,
160 stream_info->second.second));
161 }
162 streams->second.erase(stream_info);
163 callback.Run();
164 }
165 return;
166 }
167
168 StreamMap::iterator extension_it = streams_.find(extension_id); 126 StreamMap::iterator extension_it = streams_.find(extension_id);
169 if (extension_it == streams_.end()) { 127 if (extension_it == streams_.end()) {
170 callback.Run(); 128 callback.Run();
171 return; 129 return;
172 } 130 }
173 131
174 StreamMap::mapped_type* url_map = &extension_it->second; 132 StreamMap::mapped_type* url_map = &extension_it->second;
175 StreamMap::mapped_type::iterator url_it = url_map->find(stream_url); 133 StreamMap::mapped_type::iterator url_it = url_map->find(stream_url);
176 if (url_it == url_map->end()) { 134 if (url_it == url_map->end()) {
177 callback.Run(); 135 callback.Run();
178 return; 136 return;
179 } 137 }
180 138
181 url_it->second->AddCloseListener(callback); 139 url_it->second->AddCloseListener(callback);
182 url_map->erase(url_it); 140 url_map->erase(url_it);
183 } 141 }
184 142
185 void StreamsPrivateAPI::OnExtensionUnloaded( 143 void StreamsPrivateAPI::OnExtensionUnloaded(
186 content::BrowserContext* browser_context, 144 content::BrowserContext* browser_context,
187 const Extension* extension, 145 const Extension* extension,
188 UnloadedExtensionInfo::Reason reason) { 146 UnloadedExtensionInfo::Reason reason) {
189 streams_.erase(extension->id()); 147 streams_.erase(extension->id());
190 mime_handler_streams_.erase(extension->id());
191 } 148 }
192 149
193 StreamsPrivateAbortFunction::StreamsPrivateAbortFunction() { 150 StreamsPrivateAbortFunction::StreamsPrivateAbortFunction() {
194 } 151 }
195 152
196 ExtensionFunction::ResponseAction StreamsPrivateAbortFunction::Run() { 153 ExtensionFunction::ResponseAction StreamsPrivateAbortFunction::Run() {
197 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 154 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
198 EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &stream_url_)); 155 EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &stream_url_));
199 StreamsPrivateAPI::Get(browser_context())->AbortStream( 156 StreamsPrivateAPI::Get(browser_context())->AbortStream(
200 extension_id(), GURL(stream_url_), base::Bind( 157 extension_id(), GURL(stream_url_), base::Bind(
201 &StreamsPrivateAbortFunction::OnClose, this)); 158 &StreamsPrivateAbortFunction::OnClose, this));
202 return RespondLater(); 159 return RespondLater();
203 } 160 }
204 161
205 void StreamsPrivateAbortFunction::OnClose() { 162 void StreamsPrivateAbortFunction::OnClose() {
206 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 163 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
207 Respond(NoArguments()); 164 Respond(NoArguments());
208 } 165 }
209 166
210 static base::LazyInstance<BrowserContextKeyedAPIFactory<StreamsPrivateAPI> > 167 static base::LazyInstance<BrowserContextKeyedAPIFactory<StreamsPrivateAPI> >
211 g_factory = LAZY_INSTANCE_INITIALIZER; 168 g_factory = LAZY_INSTANCE_INITIALIZER;
212 169
213 // static 170 // static
214 BrowserContextKeyedAPIFactory<StreamsPrivateAPI>* 171 BrowserContextKeyedAPIFactory<StreamsPrivateAPI>*
215 StreamsPrivateAPI::GetFactoryInstance() { 172 StreamsPrivateAPI::GetFactoryInstance() {
216 return g_factory.Pointer(); 173 return g_factory.Pointer();
217 } 174 }
218 175
219 } // namespace extensions 176 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698