// Copyright 2016 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#import "ios/web/public/web_state_delegate_bridge.h"
#import <Foundation/Foundation.h>
#import <memory>
#import "base/functional/bind.h"
#import "base/functional/callback_helpers.h"
#import "base/strings/utf_string_conversions.h"
#import "ios/web/public/test/crw_fake_web_state_delegate.h"
#import "ios/web/public/test/fakes/fake_web_state.h"
#import "ios/web/public/ui/context_menu_params.h"
#import "testing/gtest_mac.h"
#import "testing/platform_test.h"
#import "third_party/ocmock/OCMock/OCMock.h"
#import "third_party/ocmock/gtest_support.h"
#import "ui/base/page_transition_types.h"
// Class which conforms to CRWWebStateDelegate protocol, but does not implement
// any optional methods.
@interface TestEmptyWebStateDelegate : NSObject<CRWWebStateDelegate>
@end
@implementation TestEmptyWebStateDelegate
@end
namespace web {
// Test fixture to test WebStateDelegateBridge class.
class WebStateDelegateBridgeTest : public PlatformTest {
protected:
void SetUp() override {
PlatformTest::SetUp();
delegate_ = [[CRWFakeWebStateDelegate alloc] init];
empty_delegate_ = [[TestEmptyWebStateDelegate alloc] init];
bridge_.reset(new WebStateDelegateBridge(delegate_));
empty_delegate_bridge_.reset(new WebStateDelegateBridge(empty_delegate_));
}
void TearDown() override {
PlatformTest::TearDown();
}
CRWFakeWebStateDelegate* delegate_;
id empty_delegate_;
std::unique_ptr<WebStateDelegateBridge> bridge_;
std::unique_ptr<WebStateDelegateBridge> empty_delegate_bridge_;
web::FakeWebState fake_web_state_;
};
// Tests `webState:createNewWebStateForURL:openerURL:initiatedByUser:`
// forwarding.
TEST_F(WebStateDelegateBridgeTest, CreateNewWebState) {
ASSERT_FALSE([delegate_ webState]);
ASSERT_FALSE([delegate_ webStateCreationRequested]);
EXPECT_FALSE(
bridge_->CreateNewWebState(&fake_web_state_, GURL(), GURL(), true));
EXPECT_EQ(&fake_web_state_, [delegate_ webState]);
ASSERT_TRUE([delegate_ webStateCreationRequested]);
}
// Tests `closeWebState:` forwarding.
TEST_F(WebStateDelegateBridgeTest, CloseWebState) {
ASSERT_FALSE([delegate_ webState]);
ASSERT_FALSE([delegate_ webStateClosingRequested]);
bridge_->CloseWebState(&fake_web_state_);
EXPECT_EQ(&fake_web_state_, [delegate_ webState]);
ASSERT_TRUE([delegate_ webStateClosingRequested]);
}
// Tests `webState:openURLWithParams:` forwarding.
TEST_F(WebStateDelegateBridgeTest, OpenURLFromWebState) {
ASSERT_FALSE([delegate_ webState]);
ASSERT_FALSE([delegate_ openURLParams]);
web::WebState::OpenURLParams params(
GURL("https://chromium.test/"), GURL("https://virtual.chromium.test/"),
web::Referrer(GURL("https://chromium2.test/"), ReferrerPolicyNever),
WindowOpenDisposition::NEW_WINDOW, ui::PAGE_TRANSITION_FORM_SUBMIT, true);
EXPECT_EQ(&fake_web_state_,
bridge_->OpenURLFromWebState(&fake_web_state_, params));
EXPECT_EQ(&fake_web_state_, [delegate_ webState]);
const web::WebState::OpenURLParams* result_params = [delegate_ openURLParams];
ASSERT_TRUE(result_params);
EXPECT_EQ(params.url, result_params->url);
EXPECT_EQ(params.virtual_url, result_params->virtual_url);
EXPECT_EQ(params.referrer.url, result_params->referrer.url);
EXPECT_EQ(params.referrer.policy, result_params->referrer.policy);
EXPECT_EQ(params.disposition, result_params->disposition);
EXPECT_EQ(static_cast<int>(params.transition),
static_cast<int>(result_params->transition));
EXPECT_EQ(params.is_renderer_initiated, result_params->is_renderer_initiated);
}
// Tests `ShowRepostFormWarningDialog` forwarding.
TEST_F(WebStateDelegateBridgeTest, ShowRepostFormWarningDialog) {
EXPECT_FALSE([delegate_ repostFormWarningRequested]);
EXPECT_FALSE([delegate_ webState]);
base::OnceCallback<void(bool)> callback;
bridge_->ShowRepostFormWarningDialog(
&fake_web_state_, web::FormWarningType::kRepost, std::move(callback));
EXPECT_TRUE([delegate_ repostFormWarningRequested]);
EXPECT_EQ(&fake_web_state_, [delegate_ webState]);
}
// Tests `ShowRepostFormWarningDialog` forwarding to delegate which does not
// implement `webState:runRepostFormDialogWithCompletionHandler:` method.
TEST_F(WebStateDelegateBridgeTest, ShowRepostFormWarningWithNoDelegateMethod) {
__block bool callback_called = false;
empty_delegate_bridge_->ShowRepostFormWarningDialog(
nullptr, web::FormWarningType::kRepost,
base::BindOnce(^(bool should_repost) {
EXPECT_TRUE(should_repost);
callback_called = true;
}));
EXPECT_TRUE(callback_called);
}
// Tests `GetJavaScriptDialogPresenter` forwarding.
TEST_F(WebStateDelegateBridgeTest, GetJavaScriptDialogPresenter) {
EXPECT_FALSE([delegate_ javaScriptDialogPresenterRequested]);
bridge_->GetJavaScriptDialogPresenter(nullptr);
EXPECT_TRUE([delegate_ javaScriptDialogPresenterRequested]);
}
// Tests `HandlePermissionsDecisionRequest` forwarding.
TEST_F(WebStateDelegateBridgeTest, HandlePermissionsDecisionRequest) {
__block bool callback_called = false;
EXPECT_FALSE([delegate_ permissionsRequestHandled]);
EXPECT_FALSE([delegate_ webState]);
bridge_->HandlePermissionsDecisionRequest(
&fake_web_state_, @[], ^(PermissionDecision decision) {
EXPECT_EQ(decision, PermissionDecisionGrant);
callback_called = true;
});
EXPECT_TRUE([delegate_ permissionsRequestHandled]);
EXPECT_EQ(&fake_web_state_, [delegate_ webState]);
EXPECT_TRUE(callback_called);
}
// Tests `HandlePermissionsDecisionRequest` forwarding to delegate which does
// not implement `webState:handlePermissions:decisionHandler:` method.
TEST_F(WebStateDelegateBridgeTest,
HandlePermissionsDecisionRequestWithNoDelegateMethod) {
__block bool callback_called = false;
empty_delegate_bridge_->HandlePermissionsDecisionRequest(
nullptr, @[], ^(PermissionDecision decision) {
// Default decision `PermissionDecisionShowDefaultPrompt` will be used
// when delegate doesn't implement
// `webState:handlePermissions:decisionHandler:` method to handle the
// permissions.
EXPECT_EQ(decision, PermissionDecisionShowDefaultPrompt);
callback_called = true;
});
EXPECT_TRUE(callback_called);
}
// Tests `OnAuthRequired` forwarding.
TEST_F(WebStateDelegateBridgeTest, OnAuthRequired) {
EXPECT_FALSE([delegate_ authenticationRequested]);
EXPECT_FALSE([delegate_ webState]);
NSURLProtectionSpace* protection_space = [[NSURLProtectionSpace alloc] init];
NSURLCredential* credential = [[NSURLCredential alloc] init];
WebStateDelegate::AuthCallback callback = base::DoNothing();
bridge_->OnAuthRequired(&fake_web_state_, protection_space, credential,
std::move(callback));
EXPECT_TRUE([delegate_ authenticationRequested]);
EXPECT_EQ(&fake_web_state_, [delegate_ webState]);
}
} // namespace web