blob: 8692a0c3649b7ac5702340ea62cda1b2e3700984 [file] [log] [blame]
// 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.
#import "ios/chrome/browser/ntp/new_tab_page_tab_helper.h"
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/feature_list.h"
#include "base/memory/ptr_util.h"
#include "base/strings/string_util.h"
#include "base/strings/sys_string_conversions.h"
#include "components/strings/grit/components_strings.h"
#include "ios/chrome/browser/chrome_url_constants.h"
#include "ios/chrome/browser/ntp/new_tab_page_tab_helper_delegate.h"
#include "ios/chrome/browser/ui/ui_feature_flags.h"
#import "ios/web/public/navigation_item.h"
#import "ios/web/public/navigation_manager.h"
#import "ios/web/public/web_state/navigation_context.h"
#import "ios/web/public/web_state/web_state.h"
#include "ui/base/l10n/l10n_util.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
#endif
namespace {
// Internally the NTP URL is about://newtab/. However, with
// |url::kAboutScheme|, there's no host value, only a path. Use this value for
// matching the NTP.
const char kAboutNewTabPath[] = "//newtab/";
} // namespace
// static
void NewTabPageTabHelper::CreateForWebState(
web::WebState* web_state,
id<NewTabPageTabHelperDelegate> delegate) {
DCHECK(web_state);
if (!FromWebState(web_state)) {
web_state->SetUserData(
UserDataKey(),
base::WrapUnique(new NewTabPageTabHelper(web_state, delegate)));
}
}
NewTabPageTabHelper::~NewTabPageTabHelper() = default;
NewTabPageTabHelper::NewTabPageTabHelper(
web::WebState* web_state,
id<NewTabPageTabHelperDelegate> delegate)
: delegate_(delegate), web_state_(web_state) {
DCHECK(delegate);
DCHECK(base::FeatureList::IsEnabled(kBrowserContainerContainsNTP));
web_state->AddObserver(this);
active_ = IsNTPURL(web_state->GetVisibleURL());
if (active_) {
UpdatePendingItem();
[delegate_ newTabPageHelperDidChangeVisibility:this forWebState:web_state_];
}
}
bool NewTabPageTabHelper::IsActive() const {
return active_;
}
void NewTabPageTabHelper::Deactivate() {
SetActive(false);
}
#pragma mark - WebStateObserver
void NewTabPageTabHelper::WebStateDestroyed(web::WebState* web_state) {
web_state->RemoveObserver(this);
SetActive(false);
}
void NewTabPageTabHelper::DidStartNavigation(
web::WebState* web_state,
web::NavigationContext* navigation_context) {
if (IsNTPURL(navigation_context->GetUrl())) {
UpdatePendingItem();
} else {
SetActive(false);
}
}
void NewTabPageTabHelper::DidFinishNavigation(
web::WebState* web_state,
web::NavigationContext* navigation_context) {
if (navigation_context->IsSameDocument()) {
return;
}
SetActive(IsNTPURL(navigation_context->GetUrl()));
}
#pragma mark - Private
void NewTabPageTabHelper::SetActive(bool active) {
bool was_active = active_;
active_ = active;
// Tell |delegate_| to show or hide the NTP, if necessary.
if (active_ != was_active) {
[delegate_ newTabPageHelperDidChangeVisibility:this forWebState:web_state_];
}
}
void NewTabPageTabHelper::UpdatePendingItem() {
web::NavigationManager* manager = web_state_->GetNavigationManager();
web::NavigationItem* item = manager->GetPendingItem();
if (item) {
item->SetVirtualURL(GURL(kChromeUINewTabURL));
item->SetTitle(l10n_util::GetStringUTF16(IDS_NEW_TAB_TITLE));
}
}
bool NewTabPageTabHelper::IsNTPURL(const GURL& url) {
// |url| can be chrome://newtab/ or about://newtab/ depending on where |url|
// comes from (the VisibleURL chrome:// from a navigation item or the actual
// webView url about://). If the url is about://newtab/, there is no origin
// to match, so instead check the scheme and the path.
return url.GetOrigin() == kChromeUINewTabURL ||
(url.SchemeIs(url::kAboutScheme) && url.path() == kAboutNewTabPath);
}