chromium/chrome/browser/permissions/permission_prompt_android_unittest.cc

// Copyright 2019 The Chromium Authors
// 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/run_loop.h"
#include "base/test/scoped_feature_list.h"
#include "chrome/common/chrome_features.h"
#include "chrome/test/base/chrome_render_view_host_test_harness.h"
#include "components/content_settings/core/common/pref_names.h"
#include "components/infobars/content/content_infobar_manager.h"
#include "components/permissions/permission_request_manager.h"
#include "components/permissions/request_type.h"
#include "components/permissions/test/mock_permission_request.h"
#include "components/prefs/pref_service.h"
#include "content/public/browser/web_contents.h"

class PermissionPromptAndroidTest : public ChromeRenderViewHostTestHarness {
 public:
  permissions::PermissionRequestManager* permission_request_manager() {
    return permission_request_manager_;
  }

 private:
  void SetUp() override {
    ChromeRenderViewHostTestHarness::SetUp();
    // Ensure that the test uses the mini-infobar variant.
    scoped_feature_list_.InitAndEnableFeature(
        features::kQuietNotificationPrompts);
    profile()->GetPrefs()->SetBoolean(
        prefs::kEnableQuietNotificationPermissionUi, true);

    NavigateAndCommit(GURL("http://example.com"));

    infobars::ContentInfoBarManager::CreateForWebContents(web_contents());

    permissions::PermissionRequestManager::CreateForWebContents(web_contents());
    permission_request_manager_ =
        permissions::PermissionRequestManager::FromWebContents(web_contents());
    permission_request_manager_
        ->set_enabled_app_level_notification_permission_for_testing(true);
  }

  base::test::ScopedFeatureList scoped_feature_list_;
  raw_ptr<permissions::PermissionRequestManager> permission_request_manager_;
};

// Tests the situation in crbug.com/1016233
TEST_F(PermissionPromptAndroidTest, TabCloseMiniInfoBarClosesCleanly) {
  // Create a notification request. This causes an infobar to appear.
  permissions::MockPermissionRequest request(
      permissions::RequestType::kNotifications);
  permission_request_manager()->AddRequest(
      web_contents()->GetPrimaryMainFrame(), &request);

  base::RunLoop().RunUntilIdle();

  // Now remove the infobar from the infobar manager.
  infobars::ContentInfoBarManager::FromWebContents(web_contents())
      ->RemoveAllInfoBars(false);

  // At this point close the permission prompt (after the infobar has been
  // removed already).
  permission_request_manager()->Deny();

  // If no DCHECK has been hit, and the infobar has been closed, the test
  // passes.
  EXPECT_TRUE(request.finished());
}

// Tests the situation in crbug.com/1016233
TEST_F(PermissionPromptAndroidTest, RemoveAllInfoBarsWithOtherObservers) {
  // Create a notification request. This causes an infobar to appear.
  permissions::MockPermissionRequest request(
      permissions::RequestType::kNotifications);
  permission_request_manager()->AddRequest(
      web_contents()->GetPrimaryMainFrame(), &request);

  base::RunLoop().RunUntilIdle();

  // Destroy web contents. This triggered the situation in crbug.com/1016233, as
  // it causes the destruction of the permission prompt after the destruction of
  // the infobar manager.
  DeleteContents();

  // Wait for all the WebContentsObserver's to handle the fact that the
  // WebContents has been destroyed.
  base::RunLoop().RunUntilIdle();

  // If no crash occurs, the test passes.
}