| Index: extensions/browser/guest_view/mime_handler_view/mime_handler_stream_manager.cc
|
| diff --git a/extensions/browser/guest_view/mime_handler_view/mime_handler_stream_manager.cc b/extensions/browser/guest_view/mime_handler_view/mime_handler_stream_manager.cc
|
| index 78b76340f07594e71f6b6e7d9303300e5cf9cdd8..9a24d70fc9ed4129f7b673d06e140f20a7716b66 100644
|
| --- a/extensions/browser/guest_view/mime_handler_view/mime_handler_stream_manager.cc
|
| +++ b/extensions/browser/guest_view/mime_handler_view/mime_handler_stream_manager.cc
|
| @@ -4,12 +4,15 @@
|
|
|
| #include "extensions/browser/guest_view/mime_handler_view/mime_handler_stream_manager.h"
|
|
|
| +#include <map>
|
| #include "base/memory/ptr_util.h"
|
| #include "base/memory/singleton.h"
|
| #include "components/keyed_service/content/browser_context_dependency_manager.h"
|
| #include "components/keyed_service/content/browser_context_keyed_service_factory.h"
|
| +#include "content/public/browser/navigation_handle.h"
|
| #include "content/public/browser/render_frame_host.h"
|
| #include "content/public/browser/render_process_host.h"
|
| +#include "content/public/common/browser_side_navigation_policy.h"
|
| #include "extensions/browser/extension_registry.h"
|
| #include "extensions/browser/extensions_browser_client.h"
|
| #include "extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest.h"
|
| @@ -72,9 +75,11 @@ class MimeHandlerStreamManager::EmbedderObserver
|
| : public content::WebContentsObserver {
|
| public:
|
| EmbedderObserver(MimeHandlerStreamManager* stream_manager,
|
| + const std::string& view_id,
|
| + content::WebContents* web_contents,
|
| + int frame_tree_node_id,
|
| int render_process_id,
|
| - int render_frame_id,
|
| - const std::string& view_id);
|
| + int render_frame_id);
|
|
|
| private:
|
| // WebContentsObserver overrides.
|
| @@ -86,15 +91,32 @@ class MimeHandlerStreamManager::EmbedderObserver
|
| bool is_error_page,
|
| bool is_iframe_srcdoc) override;
|
| void WebContentsDestroyed() override;
|
| + void DidStartNavigation(
|
| + content::NavigationHandle* navigation_handle) override;
|
| + void RenderFrameHostChanged(content::RenderFrameHost* old_host,
|
| + content::RenderFrameHost* new_host) override;
|
|
|
| void AbortStream();
|
|
|
| bool IsTrackedRenderFrameHost(content::RenderFrameHost* render_frame_host);
|
|
|
| MimeHandlerStreamManager* const stream_manager_;
|
| + const std::string view_id_;
|
| + const int frame_tree_node_id_;
|
| const int render_process_id_;
|
| const int render_frame_id_;
|
| - const std::string view_id_;
|
| + // With PlzNavigate we get an initial provisional load notification for the
|
| + // URL the mime handler is serving. We don't want to clean up the stream
|
| + // here. This field helps us track the first load notification. Defaults
|
| + // to true.
|
| + bool initial_load_for_frame_;
|
| + // Used to track whether a RenderFrameHost is swapped with another
|
| + // RenderFrameHost. We use it to determine when it is safe to clean up the
|
| + // stream. For e.g if a RFH is swapped with another RFH, and the first one
|
| + // goes away, we want to clean up the stream when the second RFH dies.
|
| + typedef std::map<content::RenderFrameHost*, content::RenderFrameHost*>
|
| + RenderFrameHostMap;
|
| + RenderFrameHostMap changed_hosts_map_;
|
| };
|
|
|
| MimeHandlerStreamManager::MimeHandlerStreamManager()
|
| @@ -113,13 +135,16 @@ MimeHandlerStreamManager* MimeHandlerStreamManager::Get(
|
| void MimeHandlerStreamManager::AddStream(
|
| const std::string& view_id,
|
| std::unique_ptr<StreamContainer> stream,
|
| + content::WebContents* web_contents,
|
| + int frame_tree_node_id,
|
| int render_process_id,
|
| int render_frame_id) {
|
| streams_by_extension_id_[stream->extension_id()].insert(view_id);
|
| auto result = streams_.insert(std::make_pair(view_id, std::move(stream)));
|
| DCHECK(result.second);
|
| embedder_observers_[view_id] = base::MakeUnique<EmbedderObserver>(
|
| - this, render_process_id, render_frame_id, view_id);
|
| + this, view_id, web_contents, frame_tree_node_id, render_process_id,
|
| + render_frame_id);
|
| }
|
|
|
| std::unique_ptr<StreamContainer> MimeHandlerStreamManager::ReleaseStream(
|
| @@ -153,23 +178,32 @@ void MimeHandlerStreamManager::OnExtensionUnloaded(
|
|
|
| MimeHandlerStreamManager::EmbedderObserver::EmbedderObserver(
|
| MimeHandlerStreamManager* stream_manager,
|
| + const std::string& view_id,
|
| + content::WebContents* web_contents,
|
| + int frame_tree_node_id,
|
| int render_process_id,
|
| - int render_frame_id,
|
| - const std::string& view_id)
|
| - : WebContentsObserver(content::WebContents::FromRenderFrameHost(
|
| - content::RenderFrameHost::FromID(render_process_id,
|
| - render_frame_id))),
|
| + int render_frame_id)
|
| + : WebContentsObserver(web_contents),
|
| stream_manager_(stream_manager),
|
| + view_id_(view_id),
|
| + frame_tree_node_id_(frame_tree_node_id),
|
| render_process_id_(render_process_id),
|
| render_frame_id_(render_frame_id),
|
| - view_id_(view_id) {
|
| -}
|
| + initial_load_for_frame_(true) {}
|
|
|
| void MimeHandlerStreamManager::EmbedderObserver::RenderFrameDeleted(
|
| content::RenderFrameHost* render_frame_host) {
|
| - if (!IsTrackedRenderFrameHost(render_frame_host))
|
| + if (!IsTrackedRenderFrameHost(render_frame_host)) {
|
| return;
|
| -
|
| + }
|
| + // If the |render_frame_host| is swapped with another RFH, then we should
|
| + // cleanup the stream when the other RFH dies,
|
| + RenderFrameHostMap::iterator index =
|
| + changed_hosts_map_.find(render_frame_host);
|
| + if (index != changed_hosts_map_.end()) {
|
| + changed_hosts_map_.erase(index);
|
| + return;
|
| + }
|
| AbortStream();
|
| }
|
|
|
| @@ -177,6 +211,7 @@ void MimeHandlerStreamManager::EmbedderObserver::RenderProcessGone(
|
| base::TerminationStatus status) {
|
| AbortStream();
|
| }
|
| +
|
| void MimeHandlerStreamManager::EmbedderObserver::
|
| DidStartProvisionalLoadForFrame(content::RenderFrameHost* render_frame_host,
|
| const GURL& validated_url,
|
| @@ -184,10 +219,28 @@ void MimeHandlerStreamManager::EmbedderObserver::
|
| bool is_iframe_srcdoc) {
|
| if (!IsTrackedRenderFrameHost(render_frame_host))
|
| return;
|
| -
|
| + // With PlzNavigate we get a provisional load notification for the URL we are
|
| + // serving. We don't want to clean up the stream here.
|
| + if (initial_load_for_frame_ && content::IsBrowserSideNavigationEnabled()) {
|
| + initial_load_for_frame_ = false;
|
| + return;
|
| + }
|
| AbortStream();
|
| }
|
|
|
| +void MimeHandlerStreamManager::EmbedderObserver::DidStartNavigation(
|
| + content::NavigationHandle* navigation_handle) {
|
| + // If the top level frame is navigating away, clean up the stream.
|
| + if (navigation_handle->IsInMainFrame())
|
| + AbortStream();
|
| +}
|
| +
|
| +void MimeHandlerStreamManager::EmbedderObserver::RenderFrameHostChanged(
|
| + content::RenderFrameHost* old_host,
|
| + content::RenderFrameHost* new_host) {
|
| + changed_hosts_map_[old_host] = new_host;
|
| +}
|
| +
|
| void MimeHandlerStreamManager::EmbedderObserver::WebContentsDestroyed() {
|
| AbortStream();
|
| }
|
| @@ -200,8 +253,13 @@ void MimeHandlerStreamManager::EmbedderObserver::AbortStream() {
|
|
|
| bool MimeHandlerStreamManager::EmbedderObserver::IsTrackedRenderFrameHost(
|
| content::RenderFrameHost* render_frame_host) {
|
| - return render_frame_host->GetRoutingID() == render_frame_id_ &&
|
| - render_frame_host->GetProcess()->GetID() == render_process_id_;
|
| + if (frame_tree_node_id_ != -1) {
|
| + return (render_frame_host->GetFrameTreeNodeId() == frame_tree_node_id_);
|
| + } else {
|
| + DCHECK((render_frame_id_ != -1) && (render_process_id_ != -1));
|
| + return render_frame_host->GetRoutingID() == render_frame_id_ &&
|
| + render_frame_host->GetProcess()->GetID() == render_process_id_;
|
| + }
|
| }
|
|
|
| } // namespace extensions
|
|
|