// Copyright 2018 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 <functional>

#include "base/bind.h"
#include "base/strings/stringprintf.h"
#include "base/strings/sys_string_conversions.h"
#import "base/test/ios/wait_util.h"
#include "base/test/scoped_feature_list.h"
#include "ios/testing/embedded_test_server_handlers.h"
#include "ios/web/common/features.h"
#import "ios/web/public/navigation_item.h"
#import "ios/web/public/navigation_manager.h"
#include "ios/web/public/reload_type.h"
#include "ios/web/public/security_style.h"
#include "ios/web/public/ssl_status.h"
#include "ios/web/public/test/element_selector.h"
#include "ios/web/public/test/fakes/test_browser_state.h"
#include "ios/web/public/test/fakes/test_web_state_observer.h"
#import "ios/web/public/test/navigation_test_util.h"
#import "ios/web/public/test/web_test_with_web_state.h"
#import "ios/web/public/test/web_view_content_test_util.h"
#import "ios/web/public/web_client.h"
#import "ios/web/public/web_state/web_state.h"
#include "net/test/embedded_test_server/default_handlers.h"
#include "net/test/embedded_test_server/request_handler_util.h"

#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
#endif

using base::test::ios::kWaitForPageLoadTimeout;
using base::test::ios::WaitUntilConditionOrTimeout;

namespace web {

namespace {

// Builds the text for the error page in TestWebClient.
std::string GetErrorText(WebState* web_state,
                         const GURL& url,
                         const std::string& error_domain,
                         long error_code,
                         bool is_post,
                         bool is_off_the_record) {
  return base::StringPrintf(
      "web_state: %p url: %s domain: %s code: %ld post: %d otr: %d", web_state,
      url.spec().c_str(), error_domain.c_str(), error_code, is_post,
      is_off_the_record);
}

// Waits for text for and error in NSURLErrorDomain and
// kCFURLErrorNetworkConnectionLost error code.
bool WaitForErrorText(WebState* web_state, const GURL& url) WARN_UNUSED_RESULT;
bool WaitForErrorText(WebState* web_state, const GURL& url) {
  return test::WaitForWebViewContainingText(
      web_state,
      GetErrorText(web_state, url, "NSURLErrorDomain", /*error_code*/ -1005,
                   /*is_post*/ false, /*is_otr*/ false));
}

// Overrides PrepareErrorPage to render all important arguments.
class TestWebClient : public WebClient {
  void PrepareErrorPage(WebState* web_state,
                        const GURL& url,
                        NSError* error,
                        bool is_post,
                        bool is_off_the_record,
                        NSString** error_html) override {
    *error_html = base::SysUTF8ToNSString(
        GetErrorText(web_state, url, base::SysNSStringToUTF8(error.domain),
                     error.code, is_post, is_off_the_record));
  }
};
}  // namespace

// ErrorPageTest is parameterized on this enum to test both
// LegacyNavigationManagerImpl and WKBasedNavigationManagerImpl.
enum class NavigationManagerChoice {
  LEGACY,
  WK_BASED,
};

// Test fixture for error page testing. Error page simply renders the arguments
// passed to WebClient::PrepareErrorPage, so the test also acts as integration
// test for PrepareErrorPage WebClient method.
class ErrorPageTest
    : public WebTestWithWebState,
      public ::testing::WithParamInterface<NavigationManagerChoice> {
 protected:
  ErrorPageTest() : WebTestWithWebState(std::make_unique<TestWebClient>()) {
    RegisterDefaultHandlers(&server_);
    server_.RegisterRequestHandler(base::BindRepeating(
        &net::test_server::HandlePrefixedRequest, "/echo-query",
        base::BindRepeating(&testing::HandleEchoQueryOrCloseSocket,
                            std::cref(server_responds_with_content_))));
    server_.RegisterRequestHandler(
        base::BindRepeating(&net::test_server::HandlePrefixedRequest, "/iframe",
                            base::BindRepeating(&testing::HandleIFrame)));
    server_.RegisterRequestHandler(
        base::BindRepeating(&net::test_server::HandlePrefixedRequest, "/form",
                            base::BindRepeating(&testing::HandleForm)));

    if (GetParam() == NavigationManagerChoice::LEGACY) {
      scoped_feature_list_.InitAndDisableFeature(
          web::features::kSlimNavigationManager);
    } else {
      scoped_feature_list_.InitAndEnableFeature(
          web::features::kSlimNavigationManager);
    }
  }

  void SetUp() override {
    WebTestWithWebState::SetUp();

    web_state_observer_ = std::make_unique<TestWebStateObserver>(web_state());
    ASSERT_TRUE(server_.Start());
  }

  TestDidChangeVisibleSecurityStateInfo* security_state_info() {
    return web_state_observer_->did_change_visible_security_state_info();
  }

  net::EmbeddedTestServer server_;
  bool server_responds_with_content_ = false;

 private:
  std::unique_ptr<TestWebStateObserver> web_state_observer_;
  base::test::ScopedFeatureList scoped_feature_list_;
  DISALLOW_COPY_AND_ASSIGN(ErrorPageTest);
};

// Tests that the error page is correctly displayed after navigating back to it
// multiple times. See http://crbug.com/944037 .
// TODO(crbug.com/954231): this test is flaky on device.
#if TARGET_IPHONE_SIMULATOR
#define MAYBE_BackForwardErrorPage BackForwardErrorPage
#else
#define MAYBE_BackForwardErrorPage FLAKY_BackForwardErrorPage
#endif
TEST_P(ErrorPageTest, MAYBE_BackForwardErrorPage) {
  test::LoadUrl(web_state(), server_.GetURL("/close-socket"));
  ASSERT_TRUE(WaitForErrorText(web_state(), server_.GetURL("/close-socket")));

  test::LoadUrl(web_state(), server_.GetURL("/echo"));
  ASSERT_TRUE(test::WaitForWebViewContainingText(web_state(), "Echo"));

  web_state()->GetNavigationManager()->GoBack();
  ASSERT_TRUE(WaitForErrorText(web_state(), server_.GetURL("/close-socket")));

  web_state()->GetNavigationManager()->GoForward();
  ASSERT_TRUE(test::WaitForWebViewContainingText(web_state(), "Echo"));

  web_state()->GetNavigationManager()->GoBack();
  ASSERT_TRUE(WaitForErrorText(web_state(), server_.GetURL("/close-socket")));

  // Make sure that the forward history isn't destroyed.
  web_state()->GetNavigationManager()->GoForward();
  ASSERT_TRUE(test::WaitForWebViewContainingText(web_state(), "Echo"));
}

// Loads the URL which fails to load, then sucessfully reloads the page.
TEST_P(ErrorPageTest, ReloadErrorPage) {
  // No response leads to -1005 error code.
  server_responds_with_content_ = false;
  test::LoadUrl(web_state(), server_.GetURL("/echo-query?foo"));
  ASSERT_TRUE(WaitForErrorText(web_state(), server_.GetURL("/echo-query?foo")));
  ASSERT_FALSE(security_state_info());

  // Reload the page, which should load without errors.
  server_responds_with_content_ = true;
  web_state()->GetNavigationManager()->Reload(ReloadType::NORMAL,
                                              /*check_for_repost=*/false);
  ASSERT_TRUE(test::WaitForWebViewContainingText(web_state(), "foo"));
}

// Sucessfully loads the page, stops the server and reloads the page.
TEST_P(ErrorPageTest, ReloadPageAfterServerIsDown) {
  // Sucessfully load the page.
  server_responds_with_content_ = true;
  test::LoadUrl(web_state(), server_.GetURL("/echo-query?foo"));
  ASSERT_TRUE(test::WaitForWebViewContainingText(web_state(), "foo"));

  // Reload the page, no response leads to -1005 error code.
  server_responds_with_content_ = false;
  web_state()->GetNavigationManager()->Reload(ReloadType::NORMAL,
                                              /*check_for_repost=*/false);
  ASSERT_TRUE(WaitForErrorText(web_state(), server_.GetURL("/echo-query?foo")));
  ASSERT_TRUE(security_state_info());
  ASSERT_TRUE(security_state_info()->visible_ssl_status);
  EXPECT_EQ(SECURITY_STYLE_UNKNOWN,
            security_state_info()->visible_ssl_status->security_style);
}

// Sucessfully loads the page, goes back, stops the server, goes forward and
// reloads.
TEST_P(ErrorPageTest, GoForwardAfterServerIsDownAndReload) {
  // First page loads sucessfully.
  test::LoadUrl(web_state(), server_.GetURL("/echo"));
  ASSERT_TRUE(test::WaitForWebViewContainingText(web_state(), "Echo"));

  // Second page loads sucessfully.
  server_responds_with_content_ = true;
  test::LoadUrl(web_state(), server_.GetURL("/echo-query?foo"));
  ASSERT_TRUE(test::WaitForWebViewContainingText(web_state(), "foo"));

  // Go back to the first page.
  web_state()->GetNavigationManager()->GoBack();
  ASSERT_TRUE(test::WaitForWebViewContainingText(web_state(), "Echo"));

#if TARGET_IPHONE_SIMULATOR
  // Go forward. The response will be retrieved from the page cache and will not
  // present the error page. Page cache may not always exist on device (which is
  // more memory constrained), so this part of the test is simulator-only.
  server_responds_with_content_ = false;
  web_state()->GetNavigationManager()->GoForward();
  ASSERT_TRUE(test::WaitForWebViewContainingText(web_state(), "foo"));

  // Reload bypasses the cache.
  web_state()->GetNavigationManager()->Reload(ReloadType::NORMAL,
                                              /*check_for_repost=*/false);
  ASSERT_TRUE(WaitForErrorText(web_state(), server_.GetURL("/echo-query?foo")));
  ASSERT_TRUE(security_state_info());
  ASSERT_TRUE(security_state_info()->visible_ssl_status);
  EXPECT_EQ(SECURITY_STYLE_UNKNOWN,
            security_state_info()->visible_ssl_status->security_style);
#endif  // TARGET_IPHONE_SIMULATOR
}

// Sucessfully loads the page, then loads the URL which fails to load, then
// sucessfully goes back to the first page and goes forward to error page.
// Back-forward navigations are browser-initiated.
TEST_P(ErrorPageTest, GoBackFromErrorPageAndForwardToErrorPage) {
  // First page loads sucessfully.
  test::LoadUrl(web_state(), server_.GetURL("/echo"));
  ASSERT_TRUE(test::WaitForWebViewContainingText(web_state(), "Echo"));

  // Second page fails to load.
  test::LoadUrl(web_state(), server_.GetURL("/close-socket"));
  ASSERT_TRUE(WaitForErrorText(web_state(), server_.GetURL("/close-socket")));

  // Going back should sucessfully load the first page.
  web_state()->GetNavigationManager()->GoBack();
  ASSERT_TRUE(test::WaitForWebViewContainingText(web_state(), "Echo"));

  // Going forward fails the load.
  web_state()->GetNavigationManager()->GoForward();
  ASSERT_TRUE(WaitForErrorText(web_state(), server_.GetURL("/close-socket")));
  ASSERT_TRUE(security_state_info());
  ASSERT_TRUE(security_state_info()->visible_ssl_status);
  EXPECT_EQ(SECURITY_STYLE_UNKNOWN,
            security_state_info()->visible_ssl_status->security_style);
}

// Sucessfully loads the page, then loads the URL which fails to load, then
// sucessfully goes back to the first page and goes forward to error page.
// Back-forward navigations are renderer-initiated.
TEST_P(ErrorPageTest,
       RendererInitiatedGoBackFromErrorPageAndForwardToErrorPage) {
  if (GetParam() == NavigationManagerChoice::WK_BASED) {
    // TODO(crbug.com/867927): Re-enable this test.
    return;
  }

  // First page loads sucessfully.
  test::LoadUrl(web_state(), server_.GetURL("/echo"));
  ASSERT_TRUE(test::WaitForWebViewContainingText(web_state(), "Echo"));

  // Second page fails to load.
  test::LoadUrl(web_state(), server_.GetURL("/close-socket"));
  ASSERT_TRUE(WaitForErrorText(web_state(), server_.GetURL("/close-socket")));

  // Going back should sucessfully load the first page.
  ExecuteJavaScript(@"window.history.back();");
  ASSERT_TRUE(test::WaitForWebViewContainingText(web_state(), "Echo"));

  // Going forward fails the load.
  ExecuteJavaScript(@"window.history.forward();");
  ASSERT_TRUE(WaitForErrorText(web_state(), server_.GetURL("/close-socket")));
  ASSERT_TRUE(security_state_info());
  ASSERT_TRUE(security_state_info()->visible_ssl_status);
  EXPECT_EQ(SECURITY_STYLE_UNKNOWN,
            security_state_info()->visible_ssl_status->security_style);
}

// Loads the URL which redirects to unresponsive server.
TEST_P(ErrorPageTest, RedirectToFailingURL) {
  // No response leads to -1005 error code.
  server_responds_with_content_ = false;
  test::LoadUrl(web_state(), server_.GetURL("/server-redirect?echo-query"));
  // Error is displayed after the resdirection to /echo-query.
  ASSERT_TRUE(WaitForErrorText(web_state(), server_.GetURL("/echo-query")));
}

// Loads the page with iframe, and that iframe fails to load. There should be no
// error page if the main frame has sucessfully loaded.
TEST_P(ErrorPageTest, ErrorPageInIFrame) {
  test::LoadUrl(web_state(), server_.GetURL("/iframe?echo-query"));
  EXPECT_TRUE(WaitUntilConditionOrTimeout(kWaitForPageLoadTimeout, ^{
    return test::IsWebViewContainingElement(
        web_state(),
        [ElementSelector selectorWithCSSSelector:"iframe[src*='echo-query']"]);
  }));
}

// Loads the URL with off the record browser state.
TEST_P(ErrorPageTest, OtrError) {
  TestBrowserState browser_state;
  browser_state.SetOffTheRecord(true);
  WebState::CreateParams params(&browser_state);
  auto web_state = WebState::Create(params);

  // No response leads to -1005 error code.
  server_responds_with_content_ = false;
  test::LoadUrl(web_state.get(), server_.GetURL("/echo-query?foo"));
  // LoadIfNecessary is needed because the view is not created (but needed) when
  // loading the page. TODO(crbug.com/705819): Remove this call.
  web_state->GetNavigationManager()->LoadIfNecessary();
  ASSERT_TRUE(test::WaitForWebViewContainingText(
      web_state.get(),
      GetErrorText(web_state.get(), server_.GetURL("/echo-query?foo"),
                   "NSURLErrorDomain", /*error_code*/ -1005,
                   /*is_post*/ false, /*is_otr*/ true)));
}

// Loads the URL with form which fails to submit.
TEST_P(ErrorPageTest, FormSubmissionError) {
  test::LoadUrl(web_state(), server_.GetURL("/form?close-socket"));
  ASSERT_TRUE(
      test::WaitForWebViewContainingText(web_state(), testing::kTestFormPage));

  // Submit the form using JavaScript.
  ExecuteJavaScript(@"document.getElementById('form').submit();");

  // Error is displayed after the form submission navigation.
  ASSERT_TRUE(test::WaitForWebViewContainingText(
      web_state(), GetErrorText(web_state(), server_.GetURL("/close-socket"),
                                "NSURLErrorDomain", /*error_code*/ -1005,
                                /*is_post*/ true, /*is_otr*/ false)));
}

// Loads an item and checks that virtualURL and URL after displaying the error
// are correct.
TEST_P(ErrorPageTest, URLAndVirtualURLAfterError) {
  GURL url(server_.GetURL("/close-socket"));
  GURL virtual_url("http://virual_url.test");
  web::NavigationManager::WebLoadParams params(url);
  params.virtual_url = virtual_url;
  web::NavigationManager* manager = web_state()->GetNavigationManager();
  manager->LoadURLWithParams(params);
  manager->LoadIfNecessary();
  ASSERT_TRUE(WaitForErrorText(web_state(), url));

  EXPECT_EQ(url, manager->GetLastCommittedItem()->GetURL());
  EXPECT_EQ(virtual_url, manager->GetLastCommittedItem()->GetVirtualURL());
}

INSTANTIATE_TEST_SUITE_P(ProgrammaticErrorPageTest,
                         ErrorPageTest,
                         ::testing::Values(NavigationManagerChoice::LEGACY,
                                           NavigationManagerChoice::WK_BASED));
}  // namespace web
