blob: 3e560b7e29f166955951fda3f583f1e081226fd2 [file] [log] [blame]
// Copyright 2014 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 "chrome/browser/ui/views/extensions/extension_install_dialog_view.h"
#include <string>
#include <utility>
#include "base/bind_helpers.h"
#include "base/files/file_path.h"
#include "base/macros.h"
#include "base/path_service.h"
#include "base/run_loop.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "build/build_config.h"
#include "chrome/browser/extensions/chrome_test_extension_loader.h"
#include "chrome/browser/extensions/extension_browsertest.h"
#include "chrome/browser/extensions/extension_icon_manager.h"
#include "chrome/browser/extensions/extension_install_prompt.h"
#include "chrome/browser/extensions/extension_install_prompt_test_helper.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/platform_util.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_window.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/browser/ui/test/test_browser_dialog.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/extensions/extension_test_util.h"
#include "chrome/grit/generated_resources.h"
#include "components/constrained_window/constrained_window_views.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/test/browser_test.h"
#include "content/public/test/test_utils.h"
#include "extensions/browser/extension_registry.h"
#include "extensions/browser/extension_system.h"
#include "extensions/browser/test_extension_registry_observer.h"
#include "extensions/common/extension.h"
#include "extensions/common/extension_features.h"
#include "extensions/common/permissions/permission_message_provider.h"
#include "extensions/common/permissions/permissions_data.h"
#include "ui/accessibility/ax_enums.mojom.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/views/bubble/bubble_frame_view.h"
#include "ui/views/controls/scroll_view.h"
#include "ui/views/test/widget_test.h"
#include "ui/views/view.h"
#include "ui/views/widget/widget.h"
using extensions::PermissionIDSet;
using extensions::PermissionMessage;
using extensions::PermissionMessages;
using extensions::PermissionSet;
namespace {
void CloseAndWait(views::Widget* widget) {
views::test::WidgetDestroyedWaiter waiter(widget);
widget->Close();
waiter.Wait();
}
} // namespace
class ExtensionInstallDialogViewTestBase
: public extensions::ExtensionBrowserTest {
protected:
ExtensionInstallDialogViewTestBase();
void SetUpOnMainThread() override;
// Creates and returns an install prompt of |prompt_type|.
std::unique_ptr<ExtensionInstallPrompt::Prompt> CreatePrompt(
ExtensionInstallPrompt::PromptType prompt_type);
std::unique_ptr<ExtensionInstallPrompt::Prompt> CreatePrompt(
ExtensionInstallPrompt::PromptType prompt_type,
const extensions::Extension* extension);
content::WebContents* web_contents() { return web_contents_; }
private:
const extensions::Extension* extension_;
content::WebContents* web_contents_;
DISALLOW_COPY_AND_ASSIGN(ExtensionInstallDialogViewTestBase);
};
ExtensionInstallDialogViewTestBase::ExtensionInstallDialogViewTestBase()
: extension_(nullptr), web_contents_(nullptr) {}
void ExtensionInstallDialogViewTestBase::SetUpOnMainThread() {
extensions::ExtensionBrowserTest::SetUpOnMainThread();
extension_ = LoadExtension(test_data_dir_.AppendASCII(
"install_prompt/permissions_scrollbar_regression"));
web_contents_ = browser()->tab_strip_model()->GetWebContentsAt(0);
}
std::unique_ptr<ExtensionInstallPrompt::Prompt>
ExtensionInstallDialogViewTestBase::CreatePrompt(
ExtensionInstallPrompt::PromptType prompt_type) {
return CreatePrompt(prompt_type, extension_);
}
std::unique_ptr<ExtensionInstallPrompt::Prompt>
ExtensionInstallDialogViewTestBase::CreatePrompt(
ExtensionInstallPrompt::PromptType prompt_type,
const extensions::Extension* extension) {
std::unique_ptr<ExtensionInstallPrompt::Prompt> prompt(
new ExtensionInstallPrompt::Prompt(prompt_type));
prompt->set_extension(extension);
std::unique_ptr<ExtensionIconManager> icon_manager(
new ExtensionIconManager());
prompt->set_icon(icon_manager->GetIcon(extension->id()));
return prompt;
}
class ScrollbarTest : public ExtensionInstallDialogViewTestBase {
protected:
ScrollbarTest() {}
bool IsScrollbarVisible(
std::unique_ptr<ExtensionInstallPrompt::Prompt> prompt);
private:
DISALLOW_COPY_AND_ASSIGN(ScrollbarTest);
};
bool ScrollbarTest::IsScrollbarVisible(
std::unique_ptr<ExtensionInstallPrompt::Prompt> prompt) {
ExtensionInstallDialogView* dialog = new ExtensionInstallDialogView(
profile(), web_contents(), ExtensionInstallPrompt::DoneCallback(),
std::move(prompt));
// Create the modal view around the install dialog view.
views::Widget* modal = constrained_window::CreateBrowserModalDialogViews(
dialog, web_contents()->GetTopLevelNativeWindow());
modal->Show();
content::RunAllTasksUntilIdle();
// Check if the vertical scrollbar is visible.
return dialog->scroll_view()->vertical_scroll_bar()->GetVisible();
}
// Tests that a scrollbar _is_ shown for an excessively long extension
// install prompt.
IN_PROC_BROWSER_TEST_F(ScrollbarTest, LongPromptScrollbar) {
base::string16 permission_string(base::ASCIIToUTF16("Test"));
PermissionMessages permissions;
for (int i = 0; i < 20; i++) {
permissions.push_back(PermissionMessage(permission_string,
PermissionIDSet()));
}
std::unique_ptr<ExtensionInstallPrompt::Prompt> prompt =
CreatePrompt(ExtensionInstallPrompt::PERMISSIONS_PROMPT);
prompt->AddPermissionMessages(permissions);
ASSERT_TRUE(IsScrollbarVisible(std::move(prompt)))
<< "Scrollbar is not visible";
}
// Tests that a scrollbar isn't shown for this regression case.
// See crbug.com/385570 for details.
IN_PROC_BROWSER_TEST_F(ScrollbarTest, DISABLED_ScrollbarRegression) {
base::string16 permission_string(base::ASCIIToUTF16(
"Read and modify your data on *.facebook.com"));
PermissionMessages permissions;
permissions.push_back(PermissionMessage(permission_string,
PermissionIDSet()));
std::unique_ptr<ExtensionInstallPrompt::Prompt> prompt =
CreatePrompt(ExtensionInstallPrompt::PERMISSIONS_PROMPT);
prompt->AddPermissionMessages(permissions);
ASSERT_FALSE(IsScrollbarVisible(std::move(prompt))) << "Scrollbar is visible";
}
class ExtensionInstallDialogViewTest
: public ExtensionInstallDialogViewTestBase {
public:
ExtensionInstallDialogViewTest() = default;
ExtensionInstallDialogViewTest(const ExtensionInstallDialogViewTest&) =
delete;
ExtensionInstallDialogViewTest& operator=(
const ExtensionInstallDialogViewTest&) = delete;
protected:
views::DialogDelegateView* CreateAndShowPrompt(
ExtensionInstallPromptTestHelper* helper) {
auto dialog = std::make_unique<ExtensionInstallDialogView>(
profile(), web_contents(), helper->GetCallback(),
CreatePrompt(ExtensionInstallPrompt::INSTALL_PROMPT));
views::DialogDelegateView* delegate_view = dialog.get();
views::Widget* modal_dialog = views::DialogDelegate::CreateDialogWidget(
dialog.release(), nullptr,
platform_util::GetViewForWindow(
browser()->window()->GetNativeWindow()));
modal_dialog->Show();
return delegate_view;
}
};
IN_PROC_BROWSER_TEST_F(ExtensionInstallDialogViewTest, NotifyDelegate) {
{
// User presses install.
ExtensionInstallPromptTestHelper helper;
views::DialogDelegateView* delegate_view = CreateAndShowPrompt(&helper);
delegate_view->AcceptDialog();
EXPECT_EQ(ExtensionInstallPrompt::Result::ACCEPTED, helper.result());
}
{
// User presses cancel.
ExtensionInstallPromptTestHelper helper;
views::DialogDelegateView* delegate_view = CreateAndShowPrompt(&helper);
delegate_view->CancelDialog();
EXPECT_EQ(ExtensionInstallPrompt::Result::USER_CANCELED, helper.result());
}
{
// Dialog is closed without the user explicitly choosing to proceed or
// cancel.
ExtensionInstallPromptTestHelper helper;
views::DialogDelegateView* delegate_view = CreateAndShowPrompt(&helper);
CloseAndWait(delegate_view->GetWidget());
// TODO(devlin): Should this be ABORTED?
EXPECT_EQ(ExtensionInstallPrompt::Result::USER_CANCELED, helper.result());
}
}
// Verifies that the "Add extension" button is disabled initially, but
// re-enabled after a short time delay.
IN_PROC_BROWSER_TEST_F(ExtensionInstallDialogViewTest, InstallButtonDelay) {
ExtensionInstallDialogView::SetInstallButtonDelayForTesting(0);
ExtensionInstallPromptTestHelper helper;
views::DialogDelegateView* delegate_view = CreateAndShowPrompt(&helper);
// Check that dialog is visible.
EXPECT_TRUE(delegate_view->GetVisible());
// Check initial button states.
EXPECT_FALSE(delegate_view->IsDialogButtonEnabled(ui::DIALOG_BUTTON_OK));
EXPECT_TRUE(delegate_view->IsDialogButtonEnabled(ui::DIALOG_BUTTON_CANCEL));
EXPECT_TRUE(delegate_view->GetInitiallyFocusedView()->HasFocus());
// Check OK button state after timeout to verify that it is re-enabled.
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(delegate_view->IsDialogButtonEnabled(ui::DIALOG_BUTTON_OK));
// Ensure default button (cancel) has focus.
EXPECT_TRUE(delegate_view->GetInitiallyFocusedView()->HasFocus());
CloseAndWait(delegate_view->GetWidget());
}
class ExtensionInstallDialogViewInteractiveBrowserTest
: public DialogBrowserTest {
public:
ExtensionInstallDialogViewInteractiveBrowserTest() {
feature_list_.InitAndEnableFeature(
extensions_features::kAllowWithholdingExtensionPermissionsOnInstall);
}
// DialogBrowserTest:
void ShowUi(const std::string& name) override {
extensions::ChromeTestExtensionLoader loader(browser()->profile());
base::FilePath test_data_dir;
base::PathService::Get(chrome::DIR_TEST_DATA, &test_data_dir);
scoped_refptr<const extensions::Extension> extension = loader.LoadExtension(
test_data_dir.AppendASCII("extensions/uitest/long_name"));
SkBitmap icon;
// The dialog will downscale large images.
icon.allocN32Pixels(800, 800);
icon.eraseARGB(255, 128, 255, 128);
auto prompt = std::make_unique<ExtensionInstallPrompt::Prompt>(type_);
// The invoke UI tests can either directly set permission messages to easily
// test different potential edge cases, or use a proper permission set which
// goes through the standard flow to generate the messages.
if (permission_set_)
prompt->AddPermissionSet(*permission_set_);
else
prompt->AddPermissionMessages(permission_messages_);
prompt->set_retained_files(retained_files_);
prompt->set_retained_device_messages(retained_devices_);
if (from_webstore_)
prompt->SetWebstoreData("69,420", true, 2.5, 37);
auto* web_contents = browser()->tab_strip_model()->GetActiveWebContents();
auto install_prompt =
std::make_unique<ExtensionInstallPrompt>(web_contents);
install_prompt->ShowDialog(base::DoNothing(), extension.get(), &icon,
std::move(prompt),
ExtensionInstallPrompt::ShowDialogCallback());
}
void set_from_webstore() { from_webstore_ = true; }
void set_type(ExtensionInstallPrompt::PromptType type) { type_ = type; }
void SetPermissionSet(std::unique_ptr<PermissionSet> permissions) {
permission_set_ = std::move(permissions);
}
void AddPermission(std::string permission) {
permission_messages_.push_back(
PermissionMessage(base::ASCIIToUTF16(permission), PermissionIDSet()));
}
void AddRetainedFile(const base::FilePath& path) {
retained_files_.push_back(path);
}
void AddRetainedDevice(const std::string& device) {
retained_devices_.push_back(base::ASCIIToUTF16(device));
}
void AddPermissionWithDetails(
std::string main_permission,
std::vector<base::string16> detailed_permissions) {
permission_messages_.push_back(
PermissionMessage(base::ASCIIToUTF16(main_permission),
PermissionIDSet(), std::move(detailed_permissions)));
}
private:
ExtensionInstallPrompt::PromptType type_ =
ExtensionInstallPrompt::INSTALL_PROMPT;
bool from_webstore_ = false;
std::unique_ptr<PermissionSet> permission_set_;
PermissionMessages permission_messages_;
std::vector<base::FilePath> retained_files_;
std::vector<base::string16> retained_devices_;
base::test::ScopedFeatureList feature_list_;
DISALLOW_COPY_AND_ASSIGN(ExtensionInstallDialogViewInteractiveBrowserTest);
};
IN_PROC_BROWSER_TEST_F(ExtensionInstallDialogViewInteractiveBrowserTest,
InvokeUi_Simple) {
ShowAndVerifyUi();
}
IN_PROC_BROWSER_TEST_F(ExtensionInstallDialogViewInteractiveBrowserTest,
InvokeUi_External) {
set_type(ExtensionInstallPrompt::EXTERNAL_INSTALL_PROMPT);
ShowAndVerifyUi();
}
IN_PROC_BROWSER_TEST_F(ExtensionInstallDialogViewInteractiveBrowserTest,
InvokeUi_ExternalWithPermission) {
set_type(ExtensionInstallPrompt::EXTERNAL_INSTALL_PROMPT);
AddPermission("Example permission");
ShowAndVerifyUi();
}
IN_PROC_BROWSER_TEST_F(ExtensionInstallDialogViewInteractiveBrowserTest,
InvokeUi_ReEnable) {
set_type(ExtensionInstallPrompt::RE_ENABLE_PROMPT);
AddPermission("Example permission");
ShowAndVerifyUi();
}
IN_PROC_BROWSER_TEST_F(ExtensionInstallDialogViewInteractiveBrowserTest,
InvokeUi_FromWebstore) {
set_type(ExtensionInstallPrompt::WEBSTORE_WIDGET_PROMPT);
set_from_webstore();
ShowAndVerifyUi();
}
IN_PROC_BROWSER_TEST_F(ExtensionInstallDialogViewInteractiveBrowserTest,
InvokeUi_FromWebstoreWithPermission) {
set_type(ExtensionInstallPrompt::WEBSTORE_WIDGET_PROMPT);
set_from_webstore();
AddPermission("Example permission");
ShowAndVerifyUi();
}
IN_PROC_BROWSER_TEST_F(ExtensionInstallDialogViewInteractiveBrowserTest,
InvokeUi_MultilinePermission) {
AddPermission(
"In the shade of the house, in the sunshine of the riverbank "
"near the boats, in the shade of the Sal-wood forest, in the "
"shade of the fig tree is where Siddhartha grew up");
ShowAndVerifyUi();
}
IN_PROC_BROWSER_TEST_F(ExtensionInstallDialogViewInteractiveBrowserTest,
InvokeUi_ManyPermissions) {
for (int i = 0; i < 20; i++)
AddPermission("Example permission");
ShowAndVerifyUi();
}
IN_PROC_BROWSER_TEST_F(ExtensionInstallDialogViewInteractiveBrowserTest,
InvokeUi_DetailedPermission) {
AddPermissionWithDetails(
"Example header permission",
{base::ASCIIToUTF16("Detailed permission 1"),
base::ASCIIToUTF16("Detailed permission 2"),
base::ASCIIToUTF16("Very very very very very very long detailed "
"permission that wraps to a new line")});
ShowAndVerifyUi();
}
IN_PROC_BROWSER_TEST_F(ExtensionInstallDialogViewInteractiveBrowserTest,
InvokeUi_WithRetainedFiles) {
AddRetainedFile(base::FilePath(FILE_PATH_LITERAL("/dev/null")));
AddRetainedFile(base::FilePath(FILE_PATH_LITERAL("/dev/zero")));
AddRetainedFile(base::FilePath(FILE_PATH_LITERAL("/dev/random")));
AddRetainedFile(base::FilePath(FILE_PATH_LITERAL(
"/some/very/very/very/very/very/long/path/longer/than/the/"
"line/length/file_with_long_name_too.txt")));
ShowAndVerifyUi();
}
IN_PROC_BROWSER_TEST_F(ExtensionInstallDialogViewInteractiveBrowserTest,
InvokeUi_WithRetainedDevices) {
AddRetainedDevice("USB Device");
AddRetainedDevice("USB Device With Longer Name");
AddRetainedDevice(
"Another USB Device With A Very Very Very Very Very Very "
"Long Name So That It Hopefully Wraps to A New Line");
ShowAndVerifyUi();
}
IN_PROC_BROWSER_TEST_F(ExtensionInstallDialogViewInteractiveBrowserTest,
InvokeUi_WithWithholdingOption) {
// The permissions withholding UI requires a proper permission set to be used,
// as it checks for host permissions to determine if it should be shown.
auto permissions = std::make_unique<PermissionSet>(
extensions::APIPermissionSet(), extensions::ManifestPermissionSet(),
extensions::URLPatternSet(
{URLPattern(extensions::Extension::kValidHostPermissionSchemes,
"http://example.com/*")}),
extensions::URLPatternSet());
SetPermissionSet(std::move(permissions));
ShowAndVerifyUi();
}
IN_PROC_BROWSER_TEST_F(ExtensionInstallDialogViewInteractiveBrowserTest,
InvokeUi_AllInfoTypes) {
AddPermission("Example permission");
AddPermissionWithDetails("This permission has details",
{base::ASCIIToUTF16("Detailed permission 1"),
base::ASCIIToUTF16("Detailed permission 2")});
AddRetainedDevice("USB Device");
AddRetainedFile(base::FilePath(FILE_PATH_LITERAL("/dev/null")));
ShowAndVerifyUi();
}
class ExtensionInstallDialogViewOnUninstallationTest
: public ExtensionInstallDialogViewTest {
public:
ExtensionInstallDialogViewOnUninstallationTest() = default;
ExtensionInstallDialogViewOnUninstallationTest(
const ExtensionInstallDialogViewOnUninstallationTest&) = delete;
ExtensionInstallDialogViewOnUninstallationTest& operator=(
const ExtensionInstallDialogViewOnUninstallationTest&) = delete;
protected:
void UninstallExtension(const std::string& extension_id);
};
void ExtensionInstallDialogViewOnUninstallationTest::UninstallExtension(
const std::string& extension_id) {
extensions::TestExtensionRegistryObserver observer(
extensions::ExtensionRegistry::Get(browser()->profile()), extension_id);
extensions::ExtensionSystem::Get(browser()->profile())
->extension_service()
->UninstallExtension(
extension_id,
extensions::UninstallReason::UNINSTALL_REASON_FOR_TESTING, nullptr);
observer.WaitForExtensionUninstalled();
}
IN_PROC_BROWSER_TEST_F(ExtensionInstallDialogViewOnUninstallationTest,
UninstallingExtensionClosesDialog) {
const extensions::Extension* extension =
LoadExtension(test_data_dir_.AppendASCII(
"install_prompt/dialog_on_uninstall/same_extension"));
ASSERT_TRUE(extension);
std::unique_ptr<ExtensionInstallPrompt::Prompt> prompt =
CreatePrompt(ExtensionInstallPrompt::REPAIR_PROMPT, extension);
ExtensionInstallDialogView* dialog = new ExtensionInstallDialogView(
profile(), web_contents(), base::DoNothing(), std::move(prompt));
views::Widget* modal_dialog = views::DialogDelegate::CreateDialogWidget(
dialog, nullptr,
platform_util::GetViewForWindow(browser()->window()->GetNativeWindow()));
ASSERT_TRUE(modal_dialog);
views::test::WidgetClosingObserver dialog_observer(modal_dialog);
modal_dialog->Show();
EXPECT_FALSE(modal_dialog->IsClosed());
UninstallExtension(extension->id());
dialog_observer.Wait();
EXPECT_TRUE(dialog_observer.widget_closed());
}
IN_PROC_BROWSER_TEST_F(ExtensionInstallDialogViewOnUninstallationTest,
UninstallingOtherExtensionDoesNotCloseDialog) {
const extensions::Extension* extension =
LoadExtension(test_data_dir_.AppendASCII(
"install_prompt/dialog_on_uninstall/same_extension"));
const extensions::Extension* other_extension =
LoadExtension(test_data_dir_.AppendASCII(
"install_prompt/dialog_on_uninstall/other_extension"));
ASSERT_TRUE(extension);
ASSERT_TRUE(other_extension);
std::unique_ptr<ExtensionInstallPrompt::Prompt> prompt =
CreatePrompt(ExtensionInstallPrompt::REPAIR_PROMPT, extension);
ExtensionInstallDialogView* dialog = new ExtensionInstallDialogView(
profile(), web_contents(), base::DoNothing(), std::move(prompt));
views::Widget* modal_dialog = views::DialogDelegate::CreateDialogWidget(
dialog, nullptr,
platform_util::GetViewForWindow(browser()->window()->GetNativeWindow()));
ASSERT_TRUE(modal_dialog);
views::test::WidgetClosingObserver dialog_observer(modal_dialog);
modal_dialog->Show();
EXPECT_FALSE(modal_dialog->IsClosed());
UninstallExtension(other_extension->id());
ASSERT_TRUE(modal_dialog);
modal_dialog->Close();
dialog_observer.Wait();
}
class ExtensionInstallDialogRatingsSectionTest
: public ExtensionInstallDialogViewTest {
public:
ExtensionInstallDialogRatingsSectionTest() {}
void TestRatingsSectionA11y(int num_ratings,
double average_rating,
const std::string& expected_text);
private:
DISALLOW_COPY_AND_ASSIGN(ExtensionInstallDialogRatingsSectionTest);
};
void ExtensionInstallDialogRatingsSectionTest::TestRatingsSectionA11y(
int num_ratings,
double average_rating,
const std::string& expected_text) {
SCOPED_TRACE(base::StringPrintf(
"Testing with %d ratings, %f average rating. Expected text: '%s'.",
num_ratings, average_rating, expected_text.c_str()));
std::unique_ptr<ExtensionInstallPrompt::Prompt> prompt =
CreatePrompt(ExtensionInstallPrompt::REPAIR_PROMPT);
prompt->SetWebstoreData("1,234", true, average_rating, num_ratings);
ExtensionInstallDialogView* dialog = new ExtensionInstallDialogView(
profile(), web_contents(), base::DoNothing(), std::move(prompt));
views::Widget* modal_dialog = views::DialogDelegate::CreateDialogWidget(
dialog, nullptr,
platform_util::GetViewForWindow(browser()->window()->GetNativeWindow()));
modal_dialog->Show();
views::View* rating_view = modal_dialog->non_client_view()->GetViewByID(
ExtensionInstallDialogView::kRatingsViewId);
ASSERT_TRUE(rating_view);
{
ui::AXNodeData node_data;
rating_view->GetAccessibleNodeData(&node_data);
EXPECT_EQ(ax::mojom::Role::kStaticText, node_data.role);
EXPECT_EQ(expected_text,
node_data.GetStringAttribute(ax::mojom::StringAttribute::kName));
}
for (views::View* child : rating_view->children()) {
ui::AXNodeData node_data;
child->GetAccessibleNodeData(&node_data);
EXPECT_EQ(ax::mojom::Role::kIgnored, node_data.role);
}
CloseAndWait(modal_dialog);
}
IN_PROC_BROWSER_TEST_F(ExtensionInstallDialogRatingsSectionTest,
RatingsSectionA11y) {
TestRatingsSectionA11y(400, 3.297, "Rated 3.3 by 400 users.");
TestRatingsSectionA11y(1, 1.0, "Rated 1.0 by one user.");
TestRatingsSectionA11y(0, 0.0, "Not yet rated by any users.");
}
class ExtensionInstallDialogWithWithholdPermissionsUI
: public ExtensionInstallDialogViewTestBase {
public:
ExtensionInstallDialogWithWithholdPermissionsUI() {
scoped_feature_list_.InitAndEnableFeature(
extensions_features::kAllowWithholdingExtensionPermissionsOnInstall);
}
private:
base::test::ScopedFeatureList scoped_feature_list_;
DISALLOW_COPY_AND_ASSIGN(ExtensionInstallDialogWithWithholdPermissionsUI);
};
// Verifies that some UI is displayed in the extra view for withholding
// permissions on installation.
IN_PROC_BROWSER_TEST_F(ExtensionInstallDialogWithWithholdPermissionsUI,
ShowsWithholdUI) {
ExtensionInstallPromptTestHelper helper;
std::unique_ptr<ExtensionInstallPrompt::Prompt> prompt =
CreatePrompt(ExtensionInstallPrompt::INSTALL_PROMPT);
// Add a permission to the prompt with example.com as an explicit pattern.
PermissionSet permissions(
extensions::APIPermissionSet(), extensions::ManifestPermissionSet(),
extensions::URLPatternSet(
{URLPattern(extensions::Extension::kValidHostPermissionSchemes,
"http://example.com/*")}),
extensions::URLPatternSet());
prompt->AddPermissionSet(permissions);
auto dialog = std::make_unique<ExtensionInstallDialogView>(
profile(), web_contents(), helper.GetCallback(), std::move(prompt));
views::DialogDelegateView* delegate_view = dialog.get();
views::Widget* modal_dialog = views::DialogDelegate::CreateDialogWidget(
dialog.release(), nullptr,
platform_util::GetViewForWindow(browser()->window()->GetNativeWindow()));
modal_dialog->Show();
const views::View* const extra_view = delegate_view->GetExtraView();
EXPECT_TRUE(extra_view);
EXPECT_EQ("Checkbox", std::string(extra_view->GetClassName()));
CloseAndWait(delegate_view->GetWidget());
}