chromium/chrome/browser/extensions/app_background_page_apitest.cc

// Copyright 2012 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/files/file_util.h"
#include "base/functional/bind.h"
#include "base/location.h"
#include "base/memory/raw_ptr.h"
#include "base/path_service.h"
#include "base/run_loop.h"
#include "base/scoped_observation.h"
#include "base/strings/stringprintf.h"
#include "base/task/single_thread_task_runner.h"
#include "base/test/scoped_feature_list.h"
#include "base/threading/thread_restrictions.h"
#include "build/build_config.h"
#include "build/buildflag.h"
#include "build/chromeos_buildflags.h"
#include "chrome/browser/background/background_contents_service.h"
#include "chrome/browser/background/background_contents_service_factory.h"
#include "chrome/browser/background/background_contents_service_observer.h"
#include "chrome/browser/background/background_mode_manager.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chrome_browser_main_extra_parts_nacl_deprecation.h"
#include "chrome/browser/extensions/extension_apitest.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_dialogs.h"
#include "chrome/browser/ui/browser_window.h"
#include "chrome/browser/ui/extensions/application_launch.h"
#include "chrome/common/chrome_paths.h"
#include "components/embedder_support/switches.h"
#include "components/nacl/common/buildflags.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/test/browser_test.h"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/test_utils.h"
#include "extensions/browser/process_manager.h"
#include "extensions/common/extension.h"
#include "extensions/common/switches.h"
#include "extensions/test/extension_test_message_listener.h"
#include "net/dns/mock_host_resolver.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "url/gurl.h"

#if BUILDFLAG(ENABLE_NACL)
#include "components/nacl/browser/nacl_process_host.h"
#endif

#if BUILDFLAG(IS_MAC)
#include "base/apple/scoped_nsautorelease_pool.h"
#endif

Extension;

namespace {

class BackgroundContentsCreationObserver
    : public BackgroundContentsServiceObserver {};

class BackgroundContentsClosedObserver
    : protected BackgroundContentsServiceObserver {};

}  // namespace

class AppBackgroundPageApiTest : public extensions::ExtensionApiTest {};

namespace {

// Fixture to assist in testing v2 app background pages containing
// Native Client embeds.
class AppBackgroundPageNaClTest : public AppBackgroundPageApiTest {};

}  // namespace

// This test is meaningless if background mode is not enabled.
#if BUILDFLAG(ENABLE_BACKGROUND_MODE)
IN_PROC_BROWSER_TEST_F(AppBackgroundPageApiTest, Basic) {}
#endif  // BUILDFLAG(ENABLE_BACKGROUND_MODE)

IN_PROC_BROWSER_TEST_F(AppBackgroundPageApiTest, LacksPermission) {}

IN_PROC_BROWSER_TEST_F(AppBackgroundPageApiTest, ManifestBackgroundPage) {}

IN_PROC_BROWSER_TEST_F(AppBackgroundPageApiTest, NoJsBackgroundPage) {}

IN_PROC_BROWSER_TEST_F(AppBackgroundPageApiTest, NoJsManifestBackgroundPage) {}

IN_PROC_BROWSER_TEST_F(AppBackgroundPageApiTest, OpenTwoBackgroundPages) {}

IN_PROC_BROWSER_TEST_F(AppBackgroundPageApiTest, OpenTwoPagesWithManifest) {}

IN_PROC_BROWSER_TEST_F(AppBackgroundPageApiTest, OpenPopupFromBGPage) {}

// Partly a regression test for crbug.com/756465. Namely, that window.open
// correctly matches an app URL with a path component.
// Flaky on Chrome OS https://crbug.com/1462141.
#if BUILDFLAG(IS_CHROMEOS)
#define MAYBE_OpenThenClose
#else
#define MAYBE_OpenThenClose
#endif
IN_PROC_BROWSER_TEST_F(AppBackgroundPageApiTest, MAYBE_OpenThenClose) {}

IN_PROC_BROWSER_TEST_F(AppBackgroundPageApiTest, UnloadExtensionWhileHidden) {}

#if BUILDFLAG(ENABLE_NACL)

// Verify that active NaCl embeds raise the keepalive count.
IN_PROC_BROWSER_TEST_F(AppBackgroundPageNaClTest, BackgroundKeepaliveActive) {
  extensions::ProcessManager* manager =
      extensions::ProcessManager::Get(browser()->profile());
  ExtensionTestMessageListener ready_listener("ready",
                                              ReplyBehavior::kWillReply);
  LaunchTestingApp();
  EXPECT_TRUE(ready_listener.WaitUntilSatisfied());

  const auto api_activity = std::make_pair(extensions::Activity::API_FUNCTION,
                                           std::string("test.sendMessage"));
  const auto pepper_api_activity =
      std::make_pair(extensions::Activity::PEPPER_API, std::string());
  // When the app calls chrome.test.sendMessage() the keepalive count stays
  // incremented until the call completes (i.e. until we call Reply() below).
  // So between WaitUntilSatisfied() and Reply(), we know that the count must
  // be in the incremented state, and in this case that is the only
  // contributor to the keepalive count.
  EXPECT_EQ(1, manager->GetLazyKeepaliveCount(extension()));
  extensions::ProcessManager::ActivitiesMultiset activities =
      manager->GetLazyKeepaliveActivities(extension());
  EXPECT_THAT(activities, testing::UnorderedElementsAre(api_activity));

  ExtensionTestMessageListener created1_listener("created_module:1",
                                                 ReplyBehavior::kWillReply);
  ready_listener.Reply("create_module");
  EXPECT_TRUE(created1_listener.WaitUntilSatisfied());

  // Now chrome.test.sendMessage() is incrementing the keepalive count, but
  // there is also a Native Client module active, incrementing it again.
  EXPECT_EQ(2, manager->GetLazyKeepaliveCount(extension()));
  activities = manager->GetLazyKeepaliveActivities(extension());
  EXPECT_THAT(activities,
              testing::UnorderedElementsAre(api_activity, pepper_api_activity));

  ExtensionTestMessageListener created2_listener("created_module:2",
                                                 ReplyBehavior::kWillReply);
  created1_listener.Reply("create_module");
  EXPECT_TRUE(created2_listener.WaitUntilSatisfied());

  // Keepalive comes from chrome.test.sendMessage, plus two modules.
  EXPECT_EQ(3, manager->GetLazyKeepaliveCount(extension()));
  activities = manager->GetLazyKeepaliveActivities(extension());
  EXPECT_EQ(3u, activities.size());
  EXPECT_THAT(activities,
              testing::UnorderedElementsAre(api_activity, pepper_api_activity,
                                            pepper_api_activity));

  // Tear-down both modules.
  ExtensionTestMessageListener destroyed1_listener("destroyed_module",
                                                   ReplyBehavior::kWillReply);
  created2_listener.Reply("destroy_module");
  EXPECT_TRUE(destroyed1_listener.WaitUntilSatisfied());
  ExtensionTestMessageListener destroyed2_listener("destroyed_module");
  destroyed1_listener.Reply("destroy_module");
  EXPECT_TRUE(destroyed2_listener.WaitUntilSatisfied());

  // Both modules are gone, and no sendMessage API reply is pending (since the
  // last listener has the |will_reply| flag set to |false|).
  EXPECT_EQ(0, manager->GetLazyKeepaliveCount(extension()));
  activities = manager->GetLazyKeepaliveActivities(extension());
  EXPECT_TRUE(activities.empty());
}

#endif  //  BUILDFLAG(ENABLE_NACL)