| Index: chrome/browser/background/background_contents.cc
|
| diff --git a/chrome/browser/background/background_contents.cc b/chrome/browser/background/background_contents.cc
|
| index a419a5471ad2ea05fa84e208c68419d68a793feb..5eb57800c75ed5c78653b7c40d9399688f848343 100644
|
| --- a/chrome/browser/background/background_contents.cc
|
| +++ b/chrome/browser/background/background_contents.cc
|
| @@ -6,6 +6,9 @@
|
|
|
| #include <utility>
|
|
|
| +#include "base/bind.h"
|
| +#include "base/callback.h"
|
| +#include "base/metrics/histogram_macros.h"
|
| #include "base/profiler/scoped_tracker.h"
|
| #include "chrome/browser/background/background_contents_service.h"
|
| #include "chrome/browser/chrome_notification_types.h"
|
| @@ -26,6 +29,7 @@
|
| #include "extensions/browser/deferred_start_render_host_observer.h"
|
| #include "extensions/browser/extension_host_delegate.h"
|
| #include "extensions/browser/extension_host_queue.h"
|
| +#include "extensions/browser/extension_registry.h"
|
| #include "extensions/browser/extensions_browser_client.h"
|
| #include "extensions/browser/view_type_utils.h"
|
| #include "ui/gfx/geometry/rect.h"
|
| @@ -44,7 +48,8 @@ BackgroundContents::BackgroundContents(
|
| content::SessionStorageNamespace* session_storage_namespace)
|
| : delegate_(delegate),
|
| extension_host_delegate_(extensions::ExtensionsBrowserClient::Get()
|
| - ->CreateExtensionHostDelegate()) {
|
| + ->CreateExtensionHostDelegate()),
|
| + weak_factory_(this) {
|
| profile_ = Profile::FromBrowserContext(
|
| site_instance->GetBrowserContext());
|
|
|
| @@ -66,6 +71,7 @@ BackgroundContents::BackgroundContents(
|
| } else {
|
| web_contents_.reset(WebContents::Create(create_params));
|
| }
|
| + TrackPreviousOpener();
|
| extensions::SetViewType(
|
| web_contents_.get(), extensions::VIEW_TYPE_BACKGROUND_CONTENTS);
|
| web_contents_->SetDelegate(this);
|
| @@ -92,9 +98,7 @@ BackgroundContents::BackgroundContents(
|
|
|
| // Exposed to allow creating mocks.
|
| BackgroundContents::BackgroundContents()
|
| - : delegate_(NULL),
|
| - profile_(NULL) {
|
| -}
|
| + : delegate_(NULL), profile_(NULL), weak_factory_(this) {}
|
|
|
| BackgroundContents::~BackgroundContents() {
|
| if (!web_contents_.get()) // Will be null for unit tests.
|
| @@ -230,3 +234,73 @@ void BackgroundContents::RemoveDeferredStartRenderHostObserver(
|
| extensions::DeferredStartRenderHostObserver* observer) {
|
| deferred_start_render_host_observer_list_.RemoveObserver(observer);
|
| }
|
| +
|
| +namespace {
|
| +
|
| +class OpenerDestroyedObserver : public content::WebContentsObserver {
|
| + public:
|
| + OpenerDestroyedObserver(content::RenderFrameHost* opener,
|
| + base::OnceClosure callback)
|
| + : WebContentsObserver(WebContents::FromRenderFrameHost(opener)),
|
| + opener_(opener),
|
| + callback_(std::move(callback)) {
|
| + DCHECK(!callback_.is_null());
|
| + }
|
| +
|
| + // WebContentsObserver override:
|
| + void RenderFrameDeleted(content::RenderFrameHost* deleted_frame) override {
|
| + if (deleted_frame == opener_) {
|
| + std::move(callback_).Run();
|
| + delete this;
|
| + }
|
| + }
|
| +
|
| + private:
|
| + content::RenderFrameHost* opener_;
|
| + base::OnceClosure callback_;
|
| + DISALLOW_COPY_AND_ASSIGN(OpenerDestroyedObserver);
|
| +};
|
| +
|
| +} // namespace
|
| +
|
| +void BackgroundContents::TrackPreviousOpener() {
|
| + // Do we already have a still-alive previous opener that is a hosted app?
|
| + if (previous_opener_)
|
| + return;
|
| +
|
| + if (!IsCurrentOpenerHostedApp())
|
| + return;
|
| +
|
| + previous_opener_ = web_contents()->GetOpener();
|
| + DCHECK(previous_opener_);
|
| + new OpenerDestroyedObserver(
|
| + previous_opener_,
|
| + base::Bind(&BackgroundContents::OnPreviousOpenerDestroyed,
|
| + weak_factory_.GetWeakPtr()));
|
| +}
|
| +
|
| +void BackgroundContents::OnPreviousOpenerDestroyed() {
|
| + previous_opener_ = nullptr;
|
| +}
|
| +
|
| +bool BackgroundContents::IsCurrentOpenerHostedApp() {
|
| + content::RenderFrameHost* current_opener = web_contents()->GetOpener();
|
| + if (!current_opener)
|
| + return false;
|
| +
|
| + const extensions::Extension* opener_extension =
|
| + extensions::ExtensionRegistry::Get(web_contents()->GetBrowserContext())
|
| + ->enabled_extensions()
|
| + .GetExtensionOrAppByURL(current_opener->GetLastCommittedURL());
|
| + return opener_extension && opener_extension->is_hosted_app();
|
| +}
|
| +
|
| +void BackgroundContents::DidChangeOpener() {
|
| + if (previous_opener_ && IsCurrentOpenerHostedApp() &&
|
| + (web_contents()->GetOpener() != previous_opener_)) {
|
| + UMA_HISTOGRAM_BOOLEAN(
|
| + "Extensions.HostedAppOpenedBackgroundContentsFromTwoOpeners", true);
|
| + }
|
| +
|
| + TrackPreviousOpener();
|
| +}
|
|
|