OLD | NEW |
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" | |
12 #include "content/public/browser/stream_handle.h" | 11 #include "content/public/browser/stream_handle.h" |
13 #include "content/public/browser/stream_info.h" | 12 #include "content/public/browser/stream_info.h" |
14 #include "extensions/browser/event_router.h" | 13 #include "extensions/browser/event_router.h" |
15 #include "extensions/browser/extension_function_registry.h" | 14 #include "extensions/browser/extension_function_registry.h" |
16 #include "extensions/browser/extension_registry.h" | 15 #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" | 16 #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" | 17 #include "extensions/browser/guest_view/mime_handler_view/mime_handler_view_gues
t.h" |
| 18 #include "extensions/common/manifest_handlers/mime_types_handler.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 MimeHandlerViewGuest* guest = | |
50 MimeHandlerViewGuest::FromWebContents(guest_web_contents); | |
51 if (!guest) | |
52 return false; | |
53 if (guest->view_id() != view_id) | |
54 return false; | |
55 base::WeakPtr<StreamContainer> stream = guest->GetStream(); | |
56 if (stream) | |
57 stream->Abort(); | |
58 return true; | |
59 } | |
60 | |
61 } // namespace | 44 } // namespace |
62 | 45 |
63 namespace streams_private = api::streams_private; | 46 namespace streams_private = api::streams_private; |
64 | 47 |
65 // static | 48 // static |
66 StreamsPrivateAPI* StreamsPrivateAPI::Get(content::BrowserContext* context) { | 49 StreamsPrivateAPI* StreamsPrivateAPI::Get(content::BrowserContext* context) { |
67 return GetFactoryInstance()->Get(context); | 50 return GetFactoryInstance()->Get(context); |
68 } | 51 } |
69 | 52 |
70 StreamsPrivateAPI::StreamsPrivateAPI(content::BrowserContext* context) | 53 StreamsPrivateAPI::StreamsPrivateAPI(content::BrowserContext* context) |
(...skipping 14 matching lines...) Expand all Loading... |
85 int64 expected_content_size, | 68 int64 expected_content_size, |
86 bool embedded, | 69 bool embedded, |
87 int render_process_id, | 70 int render_process_id, |
88 int render_frame_id) { | 71 int render_frame_id) { |
89 const Extension* extension = ExtensionRegistry::Get(browser_context_) | 72 const Extension* extension = ExtensionRegistry::Get(browser_context_) |
90 ->enabled_extensions() | 73 ->enabled_extensions() |
91 .GetByID(extension_id); | 74 .GetByID(extension_id); |
92 if (!extension) | 75 if (!extension) |
93 return; | 76 return; |
94 | 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 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; |
| 92 } |
95 // Create the event's arguments value. | 93 // Create the event's arguments value. |
96 streams_private::StreamInfo info; | 94 streams_private::StreamInfo info; |
97 info.mime_type = stream->mime_type; | 95 info.mime_type = stream->mime_type; |
98 info.original_url = stream->original_url.spec(); | 96 info.original_url = stream->original_url.spec(); |
99 info.stream_url = stream->handle->GetURL().spec(); | 97 info.stream_url = stream->handle->GetURL().spec(); |
100 info.tab_id = ExtensionTabUtil::GetTabId(web_contents); | 98 info.tab_id = ExtensionTabUtil::GetTabId(web_contents); |
101 info.embedded = embedded; | 99 info.embedded = embedded; |
102 | 100 |
103 if (!view_id.empty()) { | 101 if (!view_id.empty()) { |
104 info.view_id.reset(new std::string(view_id)); | 102 info.view_id.reset(new std::string(view_id)); |
105 } | 103 } |
106 | 104 |
107 int size = -1; | 105 int size = -1; |
108 if (expected_content_size <= INT_MAX) | 106 if (expected_content_size <= INT_MAX) |
109 size = expected_content_size; | 107 size = expected_content_size; |
110 info.expected_content_size = size; | 108 info.expected_content_size = size; |
111 | 109 |
112 CreateResponseHeadersDictionary(stream->response_headers.get(), | 110 CreateResponseHeadersDictionary(stream->response_headers.get(), |
113 &info.response_headers.additional_properties); | 111 &info.response_headers.additional_properties); |
114 | 112 |
115 scoped_ptr<Event> event( | 113 scoped_ptr<Event> event( |
116 new Event(streams_private::OnExecuteMimeTypeHandler::kEventName, | 114 new Event(streams_private::OnExecuteMimeTypeHandler::kEventName, |
117 streams_private::OnExecuteMimeTypeHandler::Create(info))); | 115 streams_private::OnExecuteMimeTypeHandler::Create(info))); |
118 | 116 |
119 EventRouter::Get(browser_context_) | 117 EventRouter::Get(browser_context_) |
120 ->DispatchEventToExtension(extension_id, event.Pass()); | 118 ->DispatchEventToExtension(extension_id, event.Pass()); |
121 MimeTypesHandler* handler = MimeTypesHandler::GetHandler(extension); | 119 |
122 GURL url = stream->handle->GetURL(); | 120 GURL url = stream->handle->GetURL(); |
123 // If the mime handler uses MimeHandlerViewGuest, the MimeHandlerViewGuest | 121 streams_[extension_id][url] = make_linked_ptr(stream->handle.release()); |
124 // will take ownership of the stream. Otherwise, store the stream handle in | |
125 // |streams_|. | |
126 if (handler->handler_url().empty()) { | |
127 streams_[extension_id][url] = make_linked_ptr(stream->handle.release()); | |
128 return; | |
129 } | |
130 | |
131 GURL handler_url(Extension::GetBaseURLFromExtensionId(extension_id).spec() + | |
132 handler->handler_url() + "?id=" + view_id); | |
133 MimeHandlerStreamManager::Get(browser_context_) | |
134 ->AddStream(view_id, make_scoped_ptr(new StreamContainer( | |
135 stream.Pass(), handler_url, extension_id)), | |
136 render_process_id, render_frame_id); | |
137 // If the mime handler uses MimeHandlerViewGuest, we need to be able to look | |
138 // up the MimeHandlerViewGuest instance that is handling the streamed | |
139 // resource in order to abort the stream. The embedding WebContents and the | |
140 // view id are necessary to perform that lookup. | |
141 mime_handler_streams_[extension_id][url] = | |
142 std::make_pair(web_contents, view_id); | |
143 } | 122 } |
144 | 123 |
145 void StreamsPrivateAPI::AbortStream(const std::string& extension_id, | 124 void StreamsPrivateAPI::AbortStream(const std::string& extension_id, |
146 const GURL& stream_url, | 125 const GURL& stream_url, |
147 const base::Closure& callback) { | 126 const base::Closure& callback) { |
148 auto streams = mime_handler_streams_.find(extension_id); | |
149 if (streams != mime_handler_streams_.end()) { | |
150 auto stream_info = streams->second.find(stream_url); | |
151 if (stream_info != streams->second.end()) { | |
152 scoped_ptr<StreamContainer> stream = | |
153 MimeHandlerStreamManager::Get(browser_context_) | |
154 ->ReleaseStream(stream_info->second.second); | |
155 // If the mime handler uses MimeHandlerViewGuest, the stream will either | |
156 // be owned by the particular MimeHandlerViewGuest if it has been created, | |
157 // or by the MimeHandleStreamManager, otherwise. | |
158 if (!stream) { | |
159 GuestViewManager::FromBrowserContext(browser_context_) | |
160 ->ForEachGuest(stream_info->second.first, | |
161 base::Bind(&MaybeAbortStreamInGuest, | |
162 stream_info->second.second)); | |
163 } | |
164 streams->second.erase(stream_info); | |
165 callback.Run(); | |
166 } | |
167 return; | |
168 } | |
169 | |
170 StreamMap::iterator extension_it = streams_.find(extension_id); | 127 StreamMap::iterator extension_it = streams_.find(extension_id); |
171 if (extension_it == streams_.end()) { | 128 if (extension_it == streams_.end()) { |
172 callback.Run(); | 129 callback.Run(); |
173 return; | 130 return; |
174 } | 131 } |
175 | 132 |
176 StreamMap::mapped_type* url_map = &extension_it->second; | 133 StreamMap::mapped_type* url_map = &extension_it->second; |
177 StreamMap::mapped_type::iterator url_it = url_map->find(stream_url); | 134 StreamMap::mapped_type::iterator url_it = url_map->find(stream_url); |
178 if (url_it == url_map->end()) { | 135 if (url_it == url_map->end()) { |
179 callback.Run(); | 136 callback.Run(); |
180 return; | 137 return; |
181 } | 138 } |
182 | 139 |
183 url_it->second->AddCloseListener(callback); | 140 url_it->second->AddCloseListener(callback); |
184 url_map->erase(url_it); | 141 url_map->erase(url_it); |
185 } | 142 } |
186 | 143 |
187 void StreamsPrivateAPI::OnExtensionUnloaded( | 144 void StreamsPrivateAPI::OnExtensionUnloaded( |
188 content::BrowserContext* browser_context, | 145 content::BrowserContext* browser_context, |
189 const Extension* extension, | 146 const Extension* extension, |
190 UnloadedExtensionInfo::Reason reason) { | 147 UnloadedExtensionInfo::Reason reason) { |
191 streams_.erase(extension->id()); | 148 streams_.erase(extension->id()); |
192 mime_handler_streams_.erase(extension->id()); | |
193 } | 149 } |
194 | 150 |
195 StreamsPrivateAbortFunction::StreamsPrivateAbortFunction() { | 151 StreamsPrivateAbortFunction::StreamsPrivateAbortFunction() { |
196 } | 152 } |
197 | 153 |
198 ExtensionFunction::ResponseAction StreamsPrivateAbortFunction::Run() { | 154 ExtensionFunction::ResponseAction StreamsPrivateAbortFunction::Run() { |
199 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 155 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
200 EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &stream_url_)); | 156 EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &stream_url_)); |
201 StreamsPrivateAPI::Get(browser_context())->AbortStream( | 157 StreamsPrivateAPI::Get(browser_context())->AbortStream( |
202 extension_id(), GURL(stream_url_), base::Bind( | 158 extension_id(), GURL(stream_url_), base::Bind( |
203 &StreamsPrivateAbortFunction::OnClose, this)); | 159 &StreamsPrivateAbortFunction::OnClose, this)); |
204 return RespondLater(); | 160 return RespondLater(); |
205 } | 161 } |
206 | 162 |
207 void StreamsPrivateAbortFunction::OnClose() { | 163 void StreamsPrivateAbortFunction::OnClose() { |
208 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 164 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
209 Respond(NoArguments()); | 165 Respond(NoArguments()); |
210 } | 166 } |
211 | 167 |
212 static base::LazyInstance<BrowserContextKeyedAPIFactory<StreamsPrivateAPI> > | 168 static base::LazyInstance<BrowserContextKeyedAPIFactory<StreamsPrivateAPI> > |
213 g_factory = LAZY_INSTANCE_INITIALIZER; | 169 g_factory = LAZY_INSTANCE_INITIALIZER; |
214 | 170 |
215 // static | 171 // static |
216 BrowserContextKeyedAPIFactory<StreamsPrivateAPI>* | 172 BrowserContextKeyedAPIFactory<StreamsPrivateAPI>* |
217 StreamsPrivateAPI::GetFactoryInstance() { | 173 StreamsPrivateAPI::GetFactoryInstance() { |
218 return g_factory.Pointer(); | 174 return g_factory.Pointer(); |
219 } | 175 } |
220 | 176 |
221 } // namespace extensions | 177 } // namespace extensions |
OLD | NEW |