Chromium Code Reviews| 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" | 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 Loading... | |
| 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 |
| OLD | NEW |