blob: d4074101fccda30dadc493ba4d5583706c1457f1 [file] [log] [blame]
// Copyright 2021 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/extensions/api/identity/web_auth_flow.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/test/base/in_process_browser_test.h"
#include "content/public/test/browser_test.h"
#include "content/public/test/fenced_frame_test_util.h"
#include "content/public/test/test_navigation_observer.h"
#include "testing/gmock/include/gmock/gmock.h"
class MockWebAuthFlowDelegate : public extensions::WebAuthFlow::Delegate {
public:
MOCK_METHOD(void, OnAuthFlowURLChange, (const GURL&), (override));
MOCK_METHOD(void, OnAuthFlowTitleChange, (const std::string&), (override));
MOCK_METHOD(void,
OnAuthFlowFailure,
(extensions::WebAuthFlow::Failure),
(override));
};
class WebAuthFlowBrowserTest : public InProcessBrowserTest {
public:
void SetUpOnMainThread() override {
InProcessBrowserTest::SetUpOnMainThread();
ASSERT_TRUE(embedded_test_server()->Start());
}
void TearDownOnMainThread() override {
// Delete the web auth flow (uses DeleteSoon).
web_auth_flow_.release()->DetachDelegateAndDelete();
base::RunLoop().RunUntilIdle();
InProcessBrowserTest::TearDownOnMainThread();
}
void StartWebAuthFlow(const GURL& url) {
web_auth_flow_ = std::make_unique<extensions::WebAuthFlow>(
&mock_web_auth_flow_delegate_, browser()->profile(), url,
extensions::WebAuthFlow::INTERACTIVE,
extensions::WebAuthFlow::LAUNCH_WEB_AUTH_FLOW);
web_auth_flow_->Start();
}
content::WebContents* web_contents() {
DCHECK(web_auth_flow_);
return web_auth_flow_->web_contents();
}
MockWebAuthFlowDelegate& mock() { return mock_web_auth_flow_delegate_; }
private:
std::unique_ptr<extensions::WebAuthFlow> web_auth_flow_;
MockWebAuthFlowDelegate mock_web_auth_flow_delegate_;
};
IN_PROC_BROWSER_TEST_F(WebAuthFlowBrowserTest, OnAuthFlowURLChangeCalled) {
const GURL auth_url = embedded_test_server()->GetURL("/title1.html");
// Observer for waiting until a navigation to a url has finished.
content::TestNavigationObserver navigation_observer(auth_url);
navigation_observer.StartWatchingNewWebContents();
StartWebAuthFlow(auth_url);
// The delegate method OnAuthFlowURLChange should be called
// by DidStartNavigation.
EXPECT_CALL(mock(), OnAuthFlowURLChange(auth_url));
navigation_observer.WaitForNavigationFinished();
}
IN_PROC_BROWSER_TEST_F(WebAuthFlowBrowserTest, OnAuthFlowFailureChangeCalled) {
// Navigate to a url that doesn't exist.
const GURL error_url = embedded_test_server()->GetURL("/error");
content::TestNavigationObserver navigation_observer(error_url);
navigation_observer.StartWatchingNewWebContents();
StartWebAuthFlow(error_url);
// The delegate method OnAuthFlowFailure should be called
// by DidFinishNavigation.
EXPECT_CALL(mock(), OnAuthFlowFailure(extensions::WebAuthFlow::LOAD_FAILED));
navigation_observer.WaitForNavigationFinished();
}
class WebAuthFlowFencedFrameTest : public WebAuthFlowBrowserTest {
public:
content::test::FencedFrameTestHelper& fenced_frame_test_helper() {
return fenced_frame_helper_;
}
private:
content::test::FencedFrameTestHelper fenced_frame_helper_;
};
IN_PROC_BROWSER_TEST_F(WebAuthFlowFencedFrameTest,
FencedFrameNavigationSuccess) {
const GURL auth_url = embedded_test_server()->GetURL("/title1.html");
// Observer for waiting until loading stops. A fenced frame will be created
// after load has finished.
content::TestNavigationObserver navigation_observer(auth_url);
navigation_observer.set_wait_event(
content::TestNavigationObserver::WaitEvent::kLoadStopped);
navigation_observer.StartWatchingNewWebContents();
StartWebAuthFlow(auth_url);
EXPECT_CALL(mock(), OnAuthFlowURLChange(auth_url));
navigation_observer.Wait();
testing::Mock::VerifyAndClearExpectations(&mock());
// Navigation for fenced frames should not affect to call the delegate methods
// in the WebAuthFlow.
EXPECT_CALL(mock(), OnAuthFlowURLChange(auth_url)).Times(0);
// Create a fenced frame into the inner WebContents of the WebAuthFlow.
ASSERT_TRUE(fenced_frame_test_helper().CreateFencedFrame(
web_contents()->GetPrimaryMainFrame(),
embedded_test_server()->GetURL("/fenced_frames/title1.html")));
}
IN_PROC_BROWSER_TEST_F(WebAuthFlowFencedFrameTest,
FencedFrameNavigationFailure) {
const GURL auth_url = embedded_test_server()->GetURL("/title1.html");
// Observer for waiting until loading stops. A fenced frame will be created
// after load has finished.
content::TestNavigationObserver navigation_observer(auth_url);
navigation_observer.set_wait_event(
content::TestNavigationObserver::WaitEvent::kLoadStopped);
navigation_observer.StartWatchingNewWebContents();
StartWebAuthFlow(auth_url);
EXPECT_CALL(mock(), OnAuthFlowURLChange(auth_url));
navigation_observer.Wait();
testing::Mock::VerifyAndClearExpectations(&mock());
// Navigation for fenced frames should not affect to call the delegate methods
// in the WebAuthFlow.
EXPECT_CALL(mock(), OnAuthFlowURLChange(auth_url)).Times(0);
EXPECT_CALL(mock(), OnAuthFlowFailure).Times(0);
// Create a fenced frame into the inner WebContents of the WebAuthFlow.
ASSERT_TRUE(fenced_frame_test_helper().CreateFencedFrame(
web_contents()->GetPrimaryMainFrame(),
embedded_test_server()->GetURL("/error"), net::Error::ERR_FAILED));
}