// Copyright 2015 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 "ios/chrome/browser/signin/gaia_auth_fetcher_ios.h" #import "base/mac/scoped_nsobject.h" #include "base/memory/scoped_ptr.h" #include "base/run_loop.h" #include "google_apis/gaia/gaia_urls.h" #include "ios/chrome/browser/signin/gaia_auth_fetcher_ios_private.h" #include "ios/web/public/test/test_browser_state.h" #include "ios/web/public/test/test_web_thread_bundle.h" #include "net/url_request/test_url_fetcher_factory.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" #import "testing/gtest_mac.h" #include "testing/platform_test.h" #import "third_party/ocmock/OCMock/OCMock.h" #import "third_party/ocmock/gtest_support.h" namespace { class FakeGaiaAuthFetcherIOSBridge : public GaiaAuthFetcherIOSBridge { public: FakeGaiaAuthFetcherIOSBridge(GaiaAuthFetcherIOS* fetcher, web::BrowserState* browser_state) : GaiaAuthFetcherIOSBridge(fetcher, browser_state), mock_web_view_(nil) {} private: WKWebView* CreateWKWebView() override { if (!mock_web_view_) { mock_web_view_ = [OCMockObject niceMockForClass:[WKWebView class]]; } return [mock_web_view_ retain]; } id mock_web_view_; }; class MockGaiaConsumer : public GaiaAuthConsumer { public: MockGaiaConsumer() {} ~MockGaiaConsumer() {} MOCK_METHOD1(OnMergeSessionSuccess, void(const std::string& data)); MOCK_METHOD1(OnClientLoginFailure, void(const GoogleServiceAuthError& error)); MOCK_METHOD1(OnLogOutFailure, void(const GoogleServiceAuthError& error)); MOCK_METHOD1(OnGetCheckConnectionInfoSuccess, void(const std::string& data)); }; } // Tests fixture for GaiaAuthFetcherIOS class GaiaAuthFetcherIOSTest : public PlatformTest { protected: void SetUp() override { PlatformTest::SetUp(); web::BrowserState::GetActiveStateManager(&browser_state_)->SetActive(true); gaia_auth_fetcher_.reset(new GaiaAuthFetcherIOS(&consumer_, std::string(), nullptr, &browser_state_)); gaia_auth_fetcher_->bridge_.reset(new FakeGaiaAuthFetcherIOSBridge( gaia_auth_fetcher_.get(), &browser_state_)); } void TearDown() override { gaia_auth_fetcher_.reset(); web::BrowserState::GetActiveStateManager(&browser_state_)->SetActive(false); PlatformTest::TearDown(); } GaiaAuthFetcherIOSBridge* GetBridge() { return gaia_auth_fetcher_->bridge_.get(); } id GetMockWKWebView() { return gaia_auth_fetcher_->bridge_->GetWKWebView(); } web::TestWebThreadBundle thread_bundle_; // BrowserState, required for WKWebView creation. web::TestBrowserState browser_state_; MockGaiaConsumer consumer_; scoped_ptr<GaiaAuthFetcherIOS> gaia_auth_fetcher_; }; // Tests that the cancel mechanism works properly by cancelling an OAuthLogin // request and controlling that the consumer is properly called. TEST_F(GaiaAuthFetcherIOSTest, StartOAuthLoginCancelled) { GoogleServiceAuthError expected_error = GoogleServiceAuthError(GoogleServiceAuthError::REQUEST_CANCELED); EXPECT_CALL(consumer_, OnClientLoginFailure(expected_error)).Times(1); [static_cast<WKWebView*>([GetMockWKWebView() expect]) loadHTMLString:[OCMArg any] baseURL:[OCMArg any]]; [[GetMockWKWebView() expect] stopLoading]; gaia_auth_fetcher_->StartOAuthLogin("fake_token", "gaia"); gaia_auth_fetcher_->CancelRequest(); EXPECT_OCMOCK_VERIFY(GetMockWKWebView()); } // Tests that the successful case works properly by starting a MergeSession // request, making it succeed and controlling that the consumer is properly // called. TEST_F(GaiaAuthFetcherIOSTest, StartMergeSession) { EXPECT_CALL(consumer_, OnMergeSessionSuccess("data")).Times(1); [static_cast<WKWebView*>([[GetMockWKWebView() expect] andDo:^(NSInvocation*) { GetBridge()->URLFetchSuccess("data"); }]) loadRequest:[OCMArg any]]; gaia_auth_fetcher_->StartMergeSession("uber_token", ""); EXPECT_OCMOCK_VERIFY(GetMockWKWebView()); } // Tests that the failure case works properly by starting a LogOut request, // making it fail, and controlling that the consumer is properly called. TEST_F(GaiaAuthFetcherIOSTest, StartLogOutError) { GoogleServiceAuthError expected_error = GoogleServiceAuthError(GoogleServiceAuthError::CONNECTION_FAILED); EXPECT_CALL(consumer_, OnLogOutFailure(expected_error)).Times(1); [static_cast<WKWebView*>([[GetMockWKWebView() expect] andDo:^(NSInvocation*) { GetBridge()->URLFetchFailure(false); }]) loadRequest:[OCMArg any]]; gaia_auth_fetcher_->StartLogOut(); EXPECT_OCMOCK_VERIFY(GetMockWKWebView()); } // Tests that requests that do not require cookies are using the original // GaiaAuthFetcher and not the GaiaAuthFetcherIOS specialization. TEST_F(GaiaAuthFetcherIOSTest, StartGetCheckConnectionInfo) { std::string data( "[{\"carryBackToken\": \"token1\", \"url\": \"http://www.google.com\"}]"); EXPECT_CALL(consumer_, OnGetCheckConnectionInfoSuccess(data)).Times(1); // Set up the fake URL Fetcher. scoped_ptr<net::FakeURLFetcherFactory> fake_url_fetcher_factory( new net::FakeURLFetcherFactory(new net::URLFetcherImplFactory())); fake_url_fetcher_factory->SetFakeResponse( GaiaUrls::GetInstance()->GetCheckConnectionInfoURLWithSource( std::string()), data, net::HTTP_OK, net::URLRequestStatus::SUCCESS); gaia_auth_fetcher_->StartGetCheckConnectionInfo(); base::RunLoop().RunUntilIdle(); } // Tests whether the WKWebView is actually stopped when the browser state is // inactive. TEST_F(GaiaAuthFetcherIOSTest, OnInactive) { [[GetMockWKWebView() expect] stopLoading]; web::BrowserState::GetActiveStateManager(&browser_state_)->SetActive(false); EXPECT_OCMOCK_VERIFY(GetMockWKWebView()); } // Tests that the pending request is processed when the browser state becomes // active. TEST_F(GaiaAuthFetcherIOSTest, FetchOnActive) { EXPECT_CALL(consumer_, OnMergeSessionSuccess("data")).Times(1); // No action is made until the browser state is active, then a WKWebView and // its navigation delegate are created, and the request is processed. [[GetMockWKWebView() expect] setNavigationDelegate:[OCMArg isNotNil]]; [static_cast<WKWebView*>([[GetMockWKWebView() expect] andDo:^(NSInvocation*) { GetBridge()->URLFetchSuccess("data"); }]) loadRequest:[OCMArg any]]; web::BrowserState::GetActiveStateManager(&browser_state_)->SetActive(false); gaia_auth_fetcher_->StartMergeSession("uber_token", ""); web::BrowserState::GetActiveStateManager(&browser_state_)->SetActive(true); EXPECT_OCMOCK_VERIFY(GetMockWKWebView()); } // Tests that the pending request is stopped when the browser state becomes // inactive and restarted when it becomes active again. TEST_F(GaiaAuthFetcherIOSTest, StopOnInactiveReFetchOnActive) { EXPECT_CALL(consumer_, OnMergeSessionSuccess("data")).Times(1); [static_cast<WKWebView*>([GetMockWKWebView() expect]) loadRequest:[OCMArg any]]; [[GetMockWKWebView() expect] setNavigationDelegate:[OCMArg isNil]]; [[GetMockWKWebView() expect] setNavigationDelegate:[OCMArg isNotNil]]; [static_cast<WKWebView*>([[GetMockWKWebView() expect] andDo:^(NSInvocation*) { GetBridge()->URLFetchSuccess("data"); }]) loadRequest:[OCMArg any]]; gaia_auth_fetcher_->StartMergeSession("uber_token", ""); web::BrowserState::GetActiveStateManager(&browser_state_)->SetActive(false); web::BrowserState::GetActiveStateManager(&browser_state_)->SetActive(true); EXPECT_OCMOCK_VERIFY(GetMockWKWebView()); }