blob: bd39fd97d33685608d185f6dc92498bd413c61df [file] [log] [blame]
// Copyright 2016 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 <memory>
#include "base/auto_reset.h"
#include "base/optional.h"
#include "base/test/scoped_feature_list.h"
#include "build/build_config.h"
#include "chrome/browser/extensions/extension_browsertest.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/signin/identity_manager_factory.h"
#include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
#include "chrome/browser/signin/signin_manager_factory.h"
#include "chrome/browser/ui/extensions/extension_installed_bubble.h"
#include "chrome/browser/ui/test/test_browser_dialog.h"
#include "chrome/browser/ui/toolbar/toolbar_actions_bar.h"
#include "chrome/common/chrome_features.h"
#include "components/bubble/bubble_controller.h"
#include "components/bubble/bubble_ui.h"
#include "components/signin/core/browser/signin_manager.h"
#include "extensions/common/extension_builder.h"
#include "extensions/common/manifest_constants.h"
#include "services/identity/public/cpp/identity_test_utils.h"
#include "ui/base/ui_base_features.h"
using extensions::Manifest;
using ActionType = extensions::ExtensionBuilder::ActionType;
class ExtensionInstalledBubbleBrowserTest
: public SupportsTestDialog<extensions::ExtensionBrowserTest> {
public:
ExtensionInstalledBubbleBrowserTest()
: disable_animations_(&ToolbarActionsBar::disable_animations_for_testing_,
true) {}
std::unique_ptr<ExtensionInstalledBubble> MakeBubble(
const std::string& name,
base::Optional<ActionType> type,
Manifest::Location location = Manifest::INTERNAL,
std::unique_ptr<base::DictionaryValue> extra_keys = nullptr);
// DialogBrowserTest:
void ShowUi(const std::string& name) override;
BubbleController* GetExtensionBubbleControllerFromManager(
BubbleManager* manager) const {
for (auto& controller : manager->controllers_) {
if (controller->GetName() == "ExtensionInstalled")
return controller.get();
}
return nullptr;
}
BubbleUi* GetBubbleUiFromManager(BubbleManager* manager) const {
BubbleController* controller =
GetExtensionBubbleControllerFromManager(manager);
return controller ? controller->bubble_ui_.get() : nullptr;
}
private:
base::AutoReset<bool> disable_animations_;
DISALLOW_COPY_AND_ASSIGN(ExtensionInstalledBubbleBrowserTest);
};
std::unique_ptr<ExtensionInstalledBubble>
ExtensionInstalledBubbleBrowserTest::MakeBubble(
const std::string& name,
base::Optional<ActionType> type,
Manifest::Location location,
std::unique_ptr<base::DictionaryValue> extra_keys) {
const SkBitmap kEmptyBitmap;
extensions::ExtensionBuilder builder(name);
if (type)
builder.SetAction(*type);
builder.SetLocation(location);
if (extra_keys)
builder.MergeManifest(std::move(extra_keys));
scoped_refptr<const extensions::Extension> extension = builder.Build();
extension_service()->AddExtension(extension.get());
auto bubble = std::make_unique<ExtensionInstalledBubble>(
extension.get(), browser(), SkBitmap());
bubble->Initialize();
return bubble;
}
void ExtensionInstalledBubbleBrowserTest::ShowUi(const std::string& name) {
// Default to Manifest::COMPONENT to test all anchoring locations. Without
// this, a page action is added automatically, which will always be the
// preferred anchor.
Manifest::Location location = Manifest::COMPONENT;
base::Optional<ActionType> type;
if (name == "BrowserAction")
type = ActionType::BROWSER_ACTION;
else if (name == "PageAction")
type = ActionType::PAGE_ACTION;
// Use INTERNAL for these so that the instruction text and signin promo are
// not suppressed.
if (name == "SignInPromo" || name == "NoAction")
location = Manifest::INTERNAL;
auto extra_keys = std::make_unique<base::DictionaryValue>();
if (name == "Omnibox")
extra_keys->SetString(extensions::manifest_keys::kOmniboxKeyword, "foo");
auto bubble = MakeBubble(name, type, location, std::move(extra_keys));
BubbleManager* manager = browser()->GetBubbleManager();
manager->ShowBubble(std::move(bubble));
}
IN_PROC_BROWSER_TEST_F(ExtensionInstalledBubbleBrowserTest,
InvokeUi_BrowserAction) {
ShowAndVerifyUi();
}
IN_PROC_BROWSER_TEST_F(ExtensionInstalledBubbleBrowserTest,
InvokeUi_PageAction) {
ShowAndVerifyUi();
}
// Test anchoring to the app menu.
IN_PROC_BROWSER_TEST_F(ExtensionInstalledBubbleBrowserTest,
InvokeUi_InstalledByDefault) {
ShowAndVerifyUi();
}
// Test anchoring to the omnibox.
IN_PROC_BROWSER_TEST_F(ExtensionInstalledBubbleBrowserTest, InvokeUi_Omnibox) {
ShowAndVerifyUi();
}
IN_PROC_BROWSER_TEST_F(ExtensionInstalledBubbleBrowserTest,
InvokeUi_SignInPromo) {
ShowAndVerifyUi();
}
IN_PROC_BROWSER_TEST_F(ExtensionInstalledBubbleBrowserTest, InvokeUi_NoAction) {
// Sign in to supppress the signin promo.
identity::MakePrimaryAccountAvailable(
SigninManagerFactory::GetForProfile(profile()),
ProfileOAuth2TokenServiceFactory::GetForProfile(profile()),
IdentityManagerFactory::GetForProfile(profile()), "test@example.com");
ShowAndVerifyUi();
}
IN_PROC_BROWSER_TEST_F(ExtensionInstalledBubbleBrowserTest,
DoNotShowHowToUseForSynthesizedActions) {
{
auto bubble = MakeBubble("No action", base::nullopt);
EXPECT_EQ(0, bubble->options() & ExtensionInstalledBubble::HOW_TO_USE);
}
{
auto bubble = MakeBubble("Browser action", ActionType::BROWSER_ACTION);
EXPECT_NE(0, bubble->options() & ExtensionInstalledBubble::HOW_TO_USE);
}
{
auto bubble = MakeBubble("Page action", ActionType::PAGE_ACTION);
EXPECT_NE(0, bubble->options() & ExtensionInstalledBubble::HOW_TO_USE);
}
}
// http://crbug.com/822022
#if defined(OS_CHROMEOS)
#define MAYBE_CloseBubbleUI DISABLED_CloseBubbleUI
#else
#define MAYBE_CloseBubbleUI CloseBubbleUI
#endif
// Tests if the BubbleController gets removed from the BubbleManager when
// the BubbleUi is closed.
IN_PROC_BROWSER_TEST_F(ExtensionInstalledBubbleBrowserTest,
MAYBE_CloseBubbleUI) {
base::test::ScopedFeatureList scoped_feature_list;
#if defined(OS_MACOSX)
scoped_feature_list.InitWithFeatures(
{features::kSecondaryUiMd, features::kShowAllDialogsWithViewsToolkit},
{});
#else
scoped_feature_list.InitWithFeatures({features::kSecondaryUiMd}, {});
#endif
auto bubble = MakeBubble("No action", base::nullopt);
BubbleManager* manager = browser()->GetBubbleManager();
manager->ShowBubble(std::move(bubble));
BubbleUi* bubble_ui = GetBubbleUiFromManager(manager);
DCHECK(bubble_ui);
bubble_ui->Close();
// BubbleManager should no longer hold the controller.
EXPECT_FALSE(GetExtensionBubbleControllerFromManager(manager));
}