1 // Copyright 2015 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 "extensions/browser/guest_view/mime_handler_view/mime_handler_stream_manager.h"
7 #include "base/memory/singleton.h"
8 #include "components/keyed_service/content/browser_context_dependency_manager.h"
9 #include "components/keyed_service/content/browser_context_keyed_service_factory.h"
10 #include "content/public/browser/render_frame_host.h"
11 #include "content/public/browser/render_process_host.h"
12 #include "extensions/browser/extension_registry.h"
13 #include "extensions/browser/extensions_browser_client.h"
14 #include "extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest.h"
16 namespace extensions
{
19 class MimeHandlerStreamManagerFactory
20 : public BrowserContextKeyedServiceFactory
{
22 MimeHandlerStreamManagerFactory();
23 static MimeHandlerStreamManagerFactory
* GetInstance();
24 MimeHandlerStreamManager
* Get(content::BrowserContext
* context
);
27 // BrowserContextKeyedServiceFactory overrides.
28 KeyedService
* BuildServiceInstanceFor(
29 content::BrowserContext
* profile
) const override
;
30 content::BrowserContext
* GetBrowserContextToUse(
31 content::BrowserContext
* context
) const override
;
34 MimeHandlerStreamManagerFactory::MimeHandlerStreamManagerFactory()
35 : BrowserContextKeyedServiceFactory(
36 "MimeHandlerStreamManager",
37 BrowserContextDependencyManager::GetInstance()) {
41 MimeHandlerStreamManagerFactory
*
42 MimeHandlerStreamManagerFactory::GetInstance() {
43 return Singleton
<MimeHandlerStreamManagerFactory
>::get();
46 MimeHandlerStreamManager
* MimeHandlerStreamManagerFactory::Get(
47 content::BrowserContext
* context
) {
48 return static_cast<MimeHandlerStreamManager
*>(
49 GetServiceForBrowserContext(context
, true));
52 KeyedService
* MimeHandlerStreamManagerFactory::BuildServiceInstanceFor(
53 content::BrowserContext
* context
) const {
54 return new MimeHandlerStreamManager();
57 content::BrowserContext
*
58 MimeHandlerStreamManagerFactory::GetBrowserContextToUse(
59 content::BrowserContext
* context
) const {
60 return extensions::ExtensionsBrowserClient::Get()->GetOriginalContext(
66 // A WebContentsObserver that observes for a particular RenderFrameHost either
67 // navigating or closing (including by crashing). This is necessary to ensure
68 // that streams that aren't claimed by a MimeHandlerViewGuest are not leaked, by
69 // aborting the stream if any of those events occurs.
70 class MimeHandlerStreamManager::EmbedderObserver
71 : public content::WebContentsObserver
{
73 EmbedderObserver(MimeHandlerStreamManager
* stream_manager
,
74 int render_process_id
,
76 const std::string
& view_id
);
79 // WebContentsObserver overrides.
80 void RenderFrameDeleted(content::RenderFrameHost
* render_frame_host
) override
;
81 void RenderProcessGone(base::TerminationStatus status
) override
;
82 void DidStartProvisionalLoadForFrame(
83 content::RenderFrameHost
* render_frame_host
,
84 const GURL
& validated_url
,
86 bool is_iframe_srcdoc
) override
;
87 void WebContentsDestroyed() override
;
91 bool IsTrackedRenderFrameHost(content::RenderFrameHost
* render_frame_host
);
93 MimeHandlerStreamManager
* const stream_manager_
;
94 const int render_process_id_
;
95 const int render_frame_id_
;
96 const std::string view_id_
;
99 MimeHandlerStreamManager::MimeHandlerStreamManager()
100 : extension_registry_observer_(this) {
103 MimeHandlerStreamManager::~MimeHandlerStreamManager() {
107 MimeHandlerStreamManager
* MimeHandlerStreamManager::Get(
108 content::BrowserContext
* context
) {
109 return MimeHandlerStreamManagerFactory::GetInstance()->Get(context
);
112 void MimeHandlerStreamManager::AddStream(const std::string
& view_id
,
113 scoped_ptr
<StreamContainer
> stream
,
114 int render_process_id
,
115 int render_frame_id
) {
116 streams_by_extension_id_
[stream
->extension_id()].insert(view_id
);
117 auto result
= streams_
.insert(
118 std::make_pair(view_id
, make_linked_ptr(stream
.release())));
119 DCHECK(result
.second
);
120 embedder_observers_
[view_id
] = make_linked_ptr(
121 new EmbedderObserver(this, render_process_id
, render_frame_id
, view_id
));
124 scoped_ptr
<StreamContainer
> MimeHandlerStreamManager::ReleaseStream(
125 const std::string
& view_id
) {
126 auto stream
= streams_
.find(view_id
);
127 if (stream
== streams_
.end())
130 scoped_ptr
<StreamContainer
> result
=
131 make_scoped_ptr(stream
->second
.release());
132 streams_by_extension_id_
[result
->extension_id()].erase(view_id
);
133 streams_
.erase(stream
);
134 embedder_observers_
.erase(view_id
);
135 return result
.Pass();
138 void MimeHandlerStreamManager::OnExtensionUnloaded(
139 content::BrowserContext
* browser_context
,
140 const Extension
* extension
,
141 UnloadedExtensionInfo::Reason reason
) {
142 auto streams
= streams_by_extension_id_
.find(extension
->id());
143 if (streams
== streams_by_extension_id_
.end())
146 for (const auto& view_id
: streams
->second
) {
147 streams_
.erase(view_id
);
148 embedder_observers_
.erase(view_id
);
150 streams_by_extension_id_
.erase(streams
);
153 MimeHandlerStreamManager::EmbedderObserver::EmbedderObserver(
154 MimeHandlerStreamManager
* stream_manager
,
155 int render_process_id
,
157 const std::string
& view_id
)
158 : WebContentsObserver(content::WebContents::FromRenderFrameHost(
159 content::RenderFrameHost::FromID(render_process_id
,
161 stream_manager_(stream_manager
),
162 render_process_id_(render_process_id
),
163 render_frame_id_(render_frame_id
),
167 void MimeHandlerStreamManager::EmbedderObserver::RenderFrameDeleted(
168 content::RenderFrameHost
* render_frame_host
) {
169 if (!IsTrackedRenderFrameHost(render_frame_host
))
175 void MimeHandlerStreamManager::EmbedderObserver::RenderProcessGone(
176 base::TerminationStatus status
) {
179 void MimeHandlerStreamManager::EmbedderObserver::
180 DidStartProvisionalLoadForFrame(content::RenderFrameHost
* render_frame_host
,
181 const GURL
& validated_url
,
183 bool is_iframe_srcdoc
) {
184 if (!IsTrackedRenderFrameHost(render_frame_host
))
190 void MimeHandlerStreamManager::EmbedderObserver::WebContentsDestroyed() {
194 void MimeHandlerStreamManager::EmbedderObserver::AbortStream() {
196 // This will cause the stream to be destroyed.
197 stream_manager_
->ReleaseStream(view_id_
);
200 bool MimeHandlerStreamManager::EmbedderObserver::IsTrackedRenderFrameHost(
201 content::RenderFrameHost
* render_frame_host
) {
202 return render_frame_host
->GetRoutingID() == render_frame_id_
&&
203 render_frame_host
->GetProcess()->GetID() == render_process_id_
;
206 } // namespace extensions