Commit f34caa12 authored by kkhorimoto's avatar kkhorimoto Committed by Commit bot

Created TestRedirectObserver.

This class observes redirects using WebStateObserver rather than the
net stack, and can be used by both KIF and EG tests.

BUG=589968

Review-Url: https://codereview.chromium.org/2048123002
Cr-Commit-Position: refs/heads/master@{#400749}
parent e07de81b
...@@ -350,6 +350,8 @@ source_set("test_support") { ...@@ -350,6 +350,8 @@ source_set("test_support") {
"public/test/scoped_testing_web_client.mm", "public/test/scoped_testing_web_client.mm",
"public/test/test_browser_state.cc", "public/test/test_browser_state.cc",
"public/test/test_browser_state.h", "public/test/test_browser_state.h",
"public/test/test_redirect_observer.h",
"public/test/test_redirect_observer.mm",
"public/test/test_web_client.h", "public/test/test_web_client.h",
"public/test/test_web_client.mm", "public/test/test_web_client.mm",
"public/test/test_web_state.h", "public/test/test_web_state.h",
......
...@@ -495,6 +495,8 @@ ...@@ -495,6 +495,8 @@
'public/test/scoped_testing_web_client.mm', 'public/test/scoped_testing_web_client.mm',
'public/test/test_browser_state.cc', 'public/test/test_browser_state.cc',
'public/test/test_browser_state.h', 'public/test/test_browser_state.h',
'public/test/test_redirect_observer.h',
'public/test/test_redirect_observer.mm',
'public/test/test_web_client.h', 'public/test/test_web_client.h',
'public/test/test_web_client.mm', 'public/test/test_web_client.mm',
'public/test/test_web_state.h', 'public/test/test_web_state.h',
......
// Copyright 2016 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.
#ifndef IOS_WEB_PUBLIC_TEST_TEST_REDIRECT_OBSERVER_H_
#define IOS_WEB_PUBLIC_TEST_TEST_REDIRECT_OBSERVER_H_
#include <map>
#include <set>
#include "ios/web/public/web_state/web_state_observer.h"
#include "url/gurl.h"
namespace web {
class NavigationItem;
// A utility class that is used to track redirects during tests to enable URL
// verification for redirected page loads.
class TestRedirectObserver : public web::WebStateObserver {
public:
// Getter that lazily instantiates a TestRedirectObserver that is stored in
// |web_state|'s user data.
static TestRedirectObserver* FromWebState(WebState* web_state);
// Notifies the observer that |url| is about to be loaded by the associated
// WebState, triggering the TestRedirectObserver to start observing redirects.
void BeginObservingRedirectsForUrl(const GURL& url);
// Returns the final url in the redirect chain that began with |url|.
GURL GetFinalUrlForUrl(const GURL& url);
private:
// TestRedirectObservers must be instantiated using |FromWebState()|.
friend class TestRedirectObserverUserDataWrapper;
TestRedirectObserver();
TestRedirectObserver(WebState* web_state);
~TestRedirectObserver() final;
// WebStateObserver:
void ProvisionalNavigationStarted(const GURL& url) override;
// RedirectChains store the original and final redirect URLs for a given page
// load.
typedef struct RedirectChain {
GURL original_url;
GURL final_url;
} RedirectChain;
// Stores redirect chains with their corresponding NavigationItems.
std::map<NavigationItem*, RedirectChain> redirect_chains_;
// Stores URLs passed into |BeginObservingRedirectsForUrl()|. Once a
// provisional load has begin for a URL contained in this set, the URL will
// be removed and the redirect chain originating from that URL will be stored
// in |redirect_chains_|.
std::set<GURL> expected_urls_;
};
} // namespace web
#endif // IOS_WEB_PUBLIC_TEST_TEST_REDIRECT_OBSERVER_H_
// Copyright 2016 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/web/public/test/test_redirect_observer.h"
#include "base/supports_user_data.h"
#import "ios/web/public/navigation_item.h"
#import "ios/web/public/navigation_manager.h"
#import "ios/web/public/web_state/web_state.h"
namespace {
// The key under which TestRedirectObservers are stored in a WebState's user
// data.
const void* const kTestRedirectObserverKey = &kTestRedirectObserverKey;
} // namespace
namespace web {
#pragma mark - TestRedirectObserverUserDataWrapper
// Wrapper class used to associated TestRedirectObservers with their WebStates.
class TestRedirectObserverUserDataWrapper
: public base::SupportsUserData::Data {
public:
static TestRedirectObserverUserDataWrapper* FromWebState(
web::WebState* web_state) {
DCHECK(web_state);
TestRedirectObserverUserDataWrapper* wrapper =
static_cast<TestRedirectObserverUserDataWrapper*>(
web_state->GetUserData(kTestRedirectObserverKey));
if (!wrapper)
wrapper = new TestRedirectObserverUserDataWrapper(web_state);
return wrapper;
}
explicit TestRedirectObserverUserDataWrapper(web::WebState* web_state)
: redirect_observer_(web_state) {
DCHECK(web_state);
web_state->SetUserData(kTestRedirectObserverKey, this);
}
web::TestRedirectObserver* redirect_observer() { return &redirect_observer_; }
private:
web::TestRedirectObserver redirect_observer_;
};
#pragma mark - TestRedirectObserver
TestRedirectObserver::TestRedirectObserver(WebState* web_state)
: WebStateObserver(web_state) {}
TestRedirectObserver::~TestRedirectObserver() {}
// static
TestRedirectObserver* TestRedirectObserver::FromWebState(
web::WebState* web_state) {
return TestRedirectObserverUserDataWrapper::FromWebState(web_state)
->redirect_observer();
}
void TestRedirectObserver::BeginObservingRedirectsForUrl(const GURL& url) {
expected_urls_.insert(url);
}
GURL TestRedirectObserver::GetFinalUrlForUrl(const GURL& url) {
for (auto redirect_chain_for_item : redirect_chains_) {
RedirectChain redirect_chain = redirect_chain_for_item.second;
if (redirect_chain.original_url == url)
return redirect_chain.final_url;
}
// If load for |url| did not occur after BeginObservingRedirectsForUrl() is
// called, there will be no final redirected URL.
return GURL();
}
void TestRedirectObserver::ProvisionalNavigationStarted(const GURL& url) {
NavigationItem* item = web_state()->GetNavigationManager()->GetVisibleItem();
DCHECK(item);
if (redirect_chains_.find(item) != redirect_chains_.end()) {
// If the redirect chain for the pending NavigationItem is already being
// tracked, add the new URL to the end of the chain.
redirect_chains_[item].final_url = url;
} else if (expected_urls_.find(url) != expected_urls_.end()) {
// If a load has begun for an expected URL, begin observing the redirect
// chain for that NavigationItem.
expected_urls_.erase(url);
RedirectChain redirect_chain;
redirect_chain.original_url = url;
redirect_chain.final_url = url;
redirect_chains_[item] = redirect_chain;
}
}
} // namespace web
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment