| // Copyright 2014 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "chrome/browser/extensions/extension_install_prompt_show_params.h" |
| |
| #include <memory> |
| |
| #include "base/memory/raw_ptr.h" |
| #include "base/memory/weak_ptr.h" |
| #include "chrome/browser/profiles/profile.h" |
| #include "content/public/browser/web_contents.h" |
| |
| #if !BUILDFLAG(IS_ANDROID) |
| #include "ui/native_window_tracker/native_window_tracker.h" |
| #endif |
| |
| #if defined(USE_AURA) |
| #include "ui/aura/window.h" |
| #endif |
| |
| namespace { |
| |
| #if defined(USE_AURA) |
| bool g_root_checking_enabled = true; |
| #endif |
| |
| bool RootCheck(gfx::NativeWindow window) { |
| #if defined(USE_AURA) |
| // If the window is not contained in a root window, then it's not connected |
| // to a display and can't be used as the context. To do otherwise results in |
| // checks later on assuming context has a root. |
| return !g_root_checking_enabled || (window->GetRootWindow() != nullptr); |
| #else |
| return true; |
| #endif |
| } |
| } // namespace |
| |
| ExtensionInstallPromptShowParams::ExtensionInstallPromptShowParams( |
| content::WebContents* contents) |
| : profile_(Profile::FromBrowserContext(contents->GetBrowserContext())), |
| parent_web_contents_(contents->GetWeakPtr()) { |
| DCHECK(profile_); |
| DCHECK(parent_web_contents_); |
| |
| if (!parent_web_contents_->GetTopLevelNativeWindow()) { |
| // WebContents were created without a top-level window. This can happen when |
| // the callers pass a dummy WebContents, or in some tests. There is no |
| // window to track in this case. Reset the WebContents pointer and just keep |
| // the profile. If we keep web contents in this case, WasParentDestroyed() |
| // will always return true, even though there is no real window to check. |
| parent_web_contents_.reset(); |
| } |
| } |
| |
| ExtensionInstallPromptShowParams::ExtensionInstallPromptShowParams( |
| Profile* profile, |
| gfx::NativeWindow parent_window) |
| : profile_(profile), |
| parent_web_contents_(nullptr), |
| parent_window_(parent_window) { |
| DCHECK(profile); |
| #if BUILDFLAG(IS_ANDROID) |
| DCHECK(!parent_window) << "Android does not support a parent window."; |
| #else |
| if (parent_window_) { |
| native_window_tracker_ = ui::NativeWindowTracker::Create(parent_window_); |
| } |
| #endif |
| } |
| |
| ExtensionInstallPromptShowParams::~ExtensionInstallPromptShowParams() = default; |
| |
| content::WebContents* ExtensionInstallPromptShowParams::GetParentWebContents() { |
| return parent_web_contents_.get(); |
| } |
| |
| gfx::NativeWindow ExtensionInstallPromptShowParams::GetParentWindow() { |
| if (WasParentDestroyed()) { |
| return gfx::NativeWindow(); |
| } |
| |
| if (WasConfiguredForWebContents()) { |
| return parent_web_contents_->GetTopLevelNativeWindow(); |
| } |
| |
| return parent_window_; |
| } |
| |
| bool ExtensionInstallPromptShowParams::WasParentDestroyed() { |
| if (profile_->ShutdownStarted()) { |
| return true; |
| } |
| |
| if (WasConfiguredForWebContents()) { |
| return !parent_web_contents_ || parent_web_contents_->IsBeingDestroyed() || |
| !parent_web_contents_->GetTopLevelNativeWindow() || |
| !RootCheck(parent_web_contents_->GetTopLevelNativeWindow()); |
| } |
| |
| #if !BUILDFLAG(IS_ANDROID) |
| if (native_window_tracker_) { |
| return native_window_tracker_->WasNativeWindowDestroyed() || |
| !RootCheck(parent_window_); |
| } |
| #endif |
| |
| return false; |
| } |
| |
| bool ExtensionInstallPromptShowParams::WasConfiguredForWebContents() { |
| // If we ever had a valid web contents, it means we were configured for it. |
| return parent_web_contents_ || parent_web_contents_.WasInvalidated(); |
| } |
| |
| namespace test { |
| |
| ScopedDisableRootChecking::ScopedDisableRootChecking() { |
| #if defined(USE_AURA) |
| // There should be no need to support multiple ScopedDisableRootCheckings |
| // at a time. |
| DCHECK(g_root_checking_enabled); |
| g_root_checking_enabled = false; |
| #endif |
| } |
| |
| ScopedDisableRootChecking::~ScopedDisableRootChecking() { |
| #if defined(USE_AURA) |
| DCHECK(!g_root_checking_enabled); |
| g_root_checking_enabled = true; |
| #endif |
| } |
| |
| } // namespace test |