| // Copyright 2020 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "chrome/browser/ui/ash/sharesheet/sharesheet_bubble_view.h" |
| |
| #include <algorithm> |
| |
| #include "ash/shell.h" |
| #include "base/functional/callback_helpers.h" |
| #include "base/memory/raw_ptr.h" |
| #include "base/test/scoped_feature_list.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/apps/app_service/app_service_test.h" |
| #include "chrome/browser/ash/policy/dlp/dlp_files_controller.h" |
| #include "chrome/browser/chromeos/policy/dlp/dlp_rules_manager.h" |
| #include "chrome/browser/chromeos/policy/dlp/dlp_rules_manager_factory.h" |
| #include "chrome/browser/chromeos/policy/dlp/mock_dlp_rules_manager.h" |
| #include "chrome/browser/nearby_sharing/common/nearby_share_features.h" |
| #include "chrome/browser/profiles/profile.h" |
| #include "chrome/browser/sharesheet/sharesheet_metrics.h" |
| #include "chrome/browser/sharesheet/sharesheet_service.h" |
| #include "chrome/browser/sharesheet/sharesheet_service_factory.h" |
| #include "chrome/browser/sharesheet/sharesheet_types.h" |
| #include "chrome/browser/ui/ash/sharesheet/sharesheet_target_button.h" |
| #include "chrome/browser/ui/ash/sharesheet/sharesheet_util.h" |
| #include "chrome/browser/ui/browser.h" |
| #include "chrome/browser/ui/views/frame/browser_view.h" |
| #include "chrome/test/base/in_process_browser_test.h" |
| #include "chromeos/components/sharesheet/constants.h" |
| #include "components/services/app_service/public/cpp/intent_test_util.h" |
| #include "components/services/app_service/public/cpp/intent_util.h" |
| #include "content/public/browser/web_contents.h" |
| #include "content/public/test/browser_test.h" |
| #include "testing/gmock/include/gmock/gmock.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| #include "ui/aura/window.h" |
| #include "ui/views/bubble/bubble_dialog_delegate_view.h" |
| |
| namespace ash { |
| namespace sharesheet { |
| |
| class SharesheetBubbleViewBrowserTest |
| : public ::testing::WithParamInterface<bool>, |
| public InProcessBrowserTest { |
| public: |
| SharesheetBubbleViewBrowserTest() { |
| if (GetParam()) { |
| scoped_feature_list_.InitAndEnableFeature(::features::kNearbySharing); |
| } else { |
| scoped_feature_list_.InitAndDisableFeature(::features::kNearbySharing); |
| } |
| } |
| |
| void ShowUi() { |
| views::Widget::Widgets old_widgets; |
| for (aura::Window* root_window : Shell::GetAllRootWindows()) |
| views::Widget::GetAllChildWidgets(root_window, &old_widgets); |
| |
| ::sharesheet::SharesheetService* const sharesheet_service = |
| ::sharesheet::SharesheetServiceFactory::GetForProfile( |
| browser()->profile()); |
| |
| auto intent = apps_util::MakeShareIntent("text", ""); |
| intent->action = apps_util::kIntentActionSend; |
| sharesheet_service->ShowBubble( |
| browser()->tab_strip_model()->GetActiveWebContents(), std::move(intent), |
| ::sharesheet::LaunchSource::kUnknown, base::DoNothing(), |
| base::DoNothing()); |
| |
| views::Widget::Widgets new_widgets; |
| for (aura::Window* root_window : Shell::GetAllRootWindows()) |
| views::Widget::GetAllChildWidgets(root_window, &new_widgets); |
| |
| views::Widget::Widgets added_widgets; |
| std::set_difference(new_widgets.begin(), new_widgets.end(), |
| old_widgets.begin(), old_widgets.end(), |
| std::inserter(added_widgets, added_widgets.begin())); |
| ASSERT_EQ(added_widgets.size(), 1u); |
| sharesheet_widget_ = *added_widgets.begin(); |
| ASSERT_EQ(sharesheet_widget_->GetName(), "SharesheetBubbleView"); |
| } |
| |
| bool VerifyUi() { |
| if (sharesheet_widget_) { |
| return sharesheet_widget_->IsVisible(); |
| } |
| return false; |
| } |
| |
| void DismissUi() { |
| ASSERT_TRUE(sharesheet_widget_); |
| sharesheet_widget_->Close(); |
| ASSERT_FALSE(sharesheet_widget_->IsVisible()); |
| } |
| |
| protected: |
| raw_ptr<views::Widget, ExperimentalAsh> sharesheet_widget_; |
| |
| private: |
| base::test::ScopedFeatureList scoped_feature_list_; |
| }; |
| |
| INSTANTIATE_TEST_SUITE_P(All, |
| SharesheetBubbleViewBrowserTest, |
| ::testing::Bool()); |
| |
| IN_PROC_BROWSER_TEST_P(SharesheetBubbleViewBrowserTest, InvokeUi_Default) { |
| ShowUi(); |
| ASSERT_TRUE(VerifyUi()); |
| DismissUi(); |
| } |
| |
| class SharesheetBubbleViewPolicyBrowserTest |
| : public SharesheetBubbleViewBrowserTest { |
| public: |
| class MockFilesController : public policy::DlpFilesController { |
| public: |
| explicit MockFilesController(const policy::DlpRulesManager& rules_manager) |
| : DlpFilesController(rules_manager) {} |
| ~MockFilesController() override = default; |
| |
| MOCK_METHOD(bool, |
| IsLaunchBlocked, |
| (const apps::AppUpdate&, const apps::IntentPtr&), |
| (override)); |
| }; |
| |
| void SetupRulesManager(bool is_dlp_blocked) { |
| policy::DlpRulesManagerFactory::GetInstance()->SetTestingFactory( |
| browser()->profile(), |
| base::BindRepeating( |
| &SharesheetBubbleViewPolicyBrowserTest::SetDlpRulesManager, |
| base::Unretained(this))); |
| ASSERT_TRUE(policy::DlpRulesManagerFactory::GetForPrimaryProfile()); |
| |
| ON_CALL(*rules_manager_, IsFilesPolicyEnabled) |
| .WillByDefault(testing::Return(true)); |
| mock_files_controller_ = |
| std::make_unique<MockFilesController>(*rules_manager_); |
| ON_CALL(*rules_manager_, GetDlpFilesController) |
| .WillByDefault(testing::Return(mock_files_controller_.get())); |
| |
| EXPECT_CALL(*mock_files_controller_.get(), IsLaunchBlocked) |
| .WillOnce(testing::Return(is_dlp_blocked)); |
| } |
| |
| void SetupAppService() { |
| app_service_test_.SetUp(browser()->profile()); |
| |
| AddAppServiceAppsForTesting("arcAppId", apps::AppType::kArc, "text/plain", |
| "https://example.com"); |
| } |
| |
| void AddAppServiceAppsForTesting(std::string app_id, |
| apps::AppType app_type, |
| std::string mime_type, |
| absl::optional<std::string> publisher_id) { |
| apps::AppServiceProxy* app_service_proxy = |
| apps::AppServiceProxyFactory::GetForProfile(browser()->profile()); |
| |
| std::vector<apps::AppPtr> fake_apps; |
| apps::AppPtr fake_app = |
| std::make_unique<apps::App>(apps::AppType::kArc, app_id); |
| fake_app->name = "xyz"; |
| fake_app->show_in_management = true; |
| fake_app->readiness = apps::Readiness::kReady; |
| if (publisher_id.has_value()) { |
| fake_app->publisher_id = publisher_id.value(); |
| } |
| std::vector<apps::PermissionPtr> fake_permissions; |
| fake_app->permissions = std::move(fake_permissions); |
| fake_app->handles_intents = true; |
| apps::IntentFilterPtr filter = |
| apps_util::MakeIntentFilterForMimeType(mime_type); |
| fake_app->intent_filters.push_back(std::move(filter)); |
| |
| fake_apps.push_back(std::move(fake_app)); |
| |
| app_service_proxy->AppRegistryCache().OnApps( |
| std::move(fake_apps), app_type, |
| /*should_notify_initialized=*/false); |
| } |
| |
| bool VerifyDlp(bool is_dlp_blocked) { |
| if (!sharesheet_widget_) { |
| return false; |
| } |
| SharesheetBubbleView* sharesheet_bubble_view_ = |
| static_cast<SharesheetBubbleView*>( |
| sharesheet_widget_->GetContentsView()); |
| views::View* targets = sharesheet_bubble_view_->GetViewByID( |
| SharesheetViewID::TARGETS_DEFAULT_VIEW_ID); |
| SharesheetTargetButton* button = static_cast<SharesheetTargetButton*>( |
| targets->children()[targets->children().size() - 1]); |
| return is_dlp_blocked == |
| (button->GetState() == SharesheetTargetButton::STATE_DISABLED); |
| } |
| |
| MockFilesController* mock_files_controller() { |
| return mock_files_controller_.get(); |
| } |
| |
| private: |
| std::unique_ptr<KeyedService> SetDlpRulesManager( |
| content::BrowserContext* context) { |
| auto dlp_rules_manager = |
| std::make_unique<testing::NiceMock<policy::MockDlpRulesManager>>(); |
| rules_manager_ = dlp_rules_manager.get(); |
| return dlp_rules_manager; |
| } |
| |
| apps::AppServiceTest app_service_test_; |
| raw_ptr<policy::MockDlpRulesManager, ExperimentalAsh> rules_manager_ = |
| nullptr; |
| std::unique_ptr<MockFilesController> mock_files_controller_ = nullptr; |
| }; |
| |
| INSTANTIATE_TEST_SUITE_P(All, |
| SharesheetBubbleViewPolicyBrowserTest, |
| ::testing::Bool()); |
| |
| IN_PROC_BROWSER_TEST_P(SharesheetBubbleViewPolicyBrowserTest, |
| InvokeUi_DlpAllowed) { |
| SetupRulesManager(/*is_dlp_blocked*/ false); |
| SetupAppService(); |
| ShowUi(); |
| ASSERT_TRUE(VerifyDlp(/*is_dlp_blocked*/ false)); |
| DismissUi(); |
| } |
| |
| IN_PROC_BROWSER_TEST_P(SharesheetBubbleViewPolicyBrowserTest, |
| InvokeUi_DlpBlocked) { |
| SetupRulesManager(/*is_dlp_blocked*/ true); |
| SetupAppService(); |
| ShowUi(); |
| ASSERT_TRUE(VerifyDlp(/*is_dlp_blocked*/ true)); |
| DismissUi(); |
| } |
| |
| } // namespace sharesheet |
| } // namespace ash |