text: // Copyright 2020 The Chromium Authors. All rights reserved.
  // Use of this source code is governed by a BSD-style license that can be
  // found in the LICENSE file.
  
  #include "base/memory/raw_ptr.h"
  #include "base/values.h"
  #include "build/build_config.h"
  #include "chrome/browser/apps/app_service/app_service_proxy.h"
  #include "chrome/browser/apps/app_service/app_service_proxy_factory.h"
  #include "chrome/browser/policy/extension_policy_test_base.h"
  #include "chrome/browser/profiles/profile.h"
  #include "chrome/browser/ui/browser.h"
  #include "chrome/browser/ui/browser_commands.h"
  #include "chrome/browser/ui/browser_window.h"
  #include "components/policy/core/common/policy_map.h"
  #include "components/policy/core/common/policy_types.h"
  #include "components/policy/policy_constants.h"
  #include "content/public/test/browser_test.h"
  #include "content/public/test/browser_test_utils.h"
  #include "extensions/browser/app_window/app_window.h"
  #include "extensions/browser/app_window/app_window_registry.h"
  #include "extensions/browser/app_window/native_app_window.h"
  #include "extensions/common/extension.h"
  #include "ui/base/window_open_disposition.h"
  
  namespace policy {
  
  namespace {
  
  const base::FilePath::CharType kUnpackedFullscreenAppName[] =
      FILE_PATH_LITERAL("fullscreen_app");
  
  // Observer used to wait for the creation of a new app window.
  class TestAddAppWindowObserver
      : public extensions::AppWindowRegistry::Observer {
   public:
    explicit TestAddAppWindowObserver(extensions::AppWindowRegistry* registry);
    ~TestAddAppWindowObserver() override;
  
    // extensions::AppWindowRegistry::Observer:
    void OnAppWindowAdded(extensions::AppWindow* app_window) override;
  
    extensions::AppWindow* WaitForAppWindow();
  
   private:
    raw_ptr<extensions::AppWindowRegistry> registry_;  // Not owned.
    raw_ptr<extensions::AppWindow> window_;            // Not owned.
    base::RunLoop run_loop_;
  };
  
  TestAddAppWindowObserver::TestAddAppWindowObserver(
      extensions::AppWindowRegistry* registry)
      : registry_(registry), window_(nullptr) {
    registry_->AddObserver(this);
  }
  
  TestAddAppWindowObserver::~TestAddAppWindowObserver() {
    registry_->RemoveObserver(this);
  }
  
  void TestAddAppWindowObserver::OnAppWindowAdded(
      extensions::AppWindow* app_window) {
    window_ = app_window;
    run_loop_.Quit();
  }
  
  extensions::AppWindow* TestAddAppWindowObserver::WaitForAppWindow() {
    run_loop_.Run();
    return window_;
  }
  
  }  // namespace
  
  typedef ExtensionPolicyTestBase FullscreenPolicyTest;
  
  IN_PROC_BROWSER_TEST_F(FullscreenPolicyTest, FullscreenAllowedBrowser) {
    PolicyMap policies;
    policies.Set(key::kFullscreenAllowed, POLICY_LEVEL_MANDATORY,
                 POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD, base::Value(false),
                 nullptr);
    UpdateProviderPolicy(policies);
  
    BrowserWindow* browser_window = browser()->window();
    ASSERT_TRUE(browser_window);
  
    EXPECT_FALSE(browser_window->IsFullscreen());
    chrome::ToggleFullscreenMode(browser());
    EXPECT_FALSE(browser_window->IsFullscreen());
  }
  
  IN_PROC_BROWSER_TEST_F(FullscreenPolicyTest, FullscreenAllowedApp) {
    PolicyMap policies;
    policies.Set(key::kFullscreenAllowed, POLICY_LEVEL_MANDATORY,
                 POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD, base::Value(false),
                 nullptr);
    UpdateProviderPolicy(policies);
  
    scoped_refptr<const extensions::Extension> extension =
        LoadUnpackedExtension(kUnpackedFullscreenAppName);
    ASSERT_TRUE(extension);
  
    // Launch an app that tries to open a fullscreen window.
    TestAddAppWindowObserver add_window_observer(
        extensions::AppWindowRegistry::Get(browser()->profile()));
    apps::AppServiceProxyFactory::GetForProfile(browser()->profile())
        ->BrowserAppLauncher()
        ->LaunchAppWithParams(apps::AppLaunchParams(
            extension->id(), apps::mojom::LaunchContainer::kLaunchContainerNone,
            WindowOpenDisposition::NEW_WINDOW,
            apps::mojom::LaunchSource::kFromTest));
    extensions::AppWindow* window = add_window_observer.WaitForAppWindow();
    ASSERT_TRUE(window);
  
    // Verify that the window is not in fullscreen mode.
    EXPECT_FALSE(window->GetBaseWindow()->IsFullscreen());
  
    // We have to wait for the navigation to commit since the JS object
    // registration is delayed (see AppWindowCreateFunction::RunAsync).
    EXPECT_TRUE(content::WaitForLoadStop(window->web_contents()));
  
    // Verify that the window cannot be toggled into fullscreen mode via apps
    // APIs.
    EXPECT_TRUE(content::ExecuteScript(
        window->web_contents(), "chrome.app.window.current().fullscreen();"));
    EXPECT_FALSE(window->GetBaseWindow()->IsFullscreen());
  
    // Verify that the window cannot be toggled into fullscreen mode from within
    // Chrome (e.g., using keyboard accelerators).
    window->Fullscreen();
    EXPECT_FALSE(window->GetBaseWindow()->IsFullscreen());
  }
  
  }  // namespace policy
  