Allow only one bookmark to be added for multiple fast starring
[chromium-blink-merge.git] / extensions / browser / guest_view / mime_handler_view / mime_handler_stream_manager.cc
blob075341bcd6082981433e619b53939e92ef577123
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 {
17 namespace {
19 class MimeHandlerStreamManagerFactory
20 : public BrowserContextKeyedServiceFactory {
21 public:
22 MimeHandlerStreamManagerFactory();
23 static MimeHandlerStreamManagerFactory* GetInstance();
24 MimeHandlerStreamManager* Get(content::BrowserContext* context);
26 private:
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()) {
40 // static
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(
61 context);
64 } // namespace
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 {
72 public:
73 EmbedderObserver(MimeHandlerStreamManager* stream_manager,
74 int render_process_id,
75 int render_frame_id,
76 const std::string& view_id);
78 private:
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,
85 bool is_error_page,
86 bool is_iframe_srcdoc) override;
87 void WebContentsDestroyed() override;
89 void AbortStream();
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() {
106 // static
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())
128 return nullptr;
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())
144 return;
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,
156 int render_frame_id,
157 const std::string& view_id)
158 : WebContentsObserver(content::WebContents::FromRenderFrameHost(
159 content::RenderFrameHost::FromID(render_process_id,
160 render_frame_id))),
161 stream_manager_(stream_manager),
162 render_process_id_(render_process_id),
163 render_frame_id_(render_frame_id),
164 view_id_(view_id) {
167 void MimeHandlerStreamManager::EmbedderObserver::RenderFrameDeleted(
168 content::RenderFrameHost* render_frame_host) {
169 if (!IsTrackedRenderFrameHost(render_frame_host))
170 return;
172 AbortStream();
175 void MimeHandlerStreamManager::EmbedderObserver::RenderProcessGone(
176 base::TerminationStatus status) {
177 AbortStream();
179 void MimeHandlerStreamManager::EmbedderObserver::
180 DidStartProvisionalLoadForFrame(content::RenderFrameHost* render_frame_host,
181 const GURL& validated_url,
182 bool is_error_page,
183 bool is_iframe_srcdoc) {
184 if (!IsTrackedRenderFrameHost(render_frame_host))
185 return;
187 AbortStream();
190 void MimeHandlerStreamManager::EmbedderObserver::WebContentsDestroyed() {
191 AbortStream();
194 void MimeHandlerStreamManager::EmbedderObserver::AbortStream() {
195 Observe(nullptr);
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