blob: 22a380f04d0e13023ecdb1b79c68568a2f938f29 [file] [log] [blame]
// Copyright 2019 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 "weblayer/browser/navigation_controller_impl.h"
#include "content/public/browser/navigation_controller.h"
#include "content/public/browser/navigation_entry.h"
#include "content/public/browser/navigation_handle.h"
#include "content/public/browser/web_contents.h"
#include "ui/base/page_transition_types.h"
#include "weblayer/browser/browser_controller_impl.h"
#include "weblayer/public/navigation_observer.h"
#if defined(OS_ANDROID)
#include "base/android/jni_string.h"
#include "weblayer/browser/java/jni/NavigationControllerImpl_jni.h"
#endif
#if defined(OS_ANDROID)
using base::android::AttachCurrentThread;
#endif
namespace weblayer {
NavigationControllerImpl::NavigationControllerImpl(
BrowserControllerImpl* browser_controller)
: WebContentsObserver(browser_controller->web_contents()),
browser_controller_(browser_controller) {}
NavigationControllerImpl::~NavigationControllerImpl() = default;
#if defined(OS_ANDROID)
void NavigationControllerImpl::SetNavigationControllerImpl(
JNIEnv* env,
const base::android::JavaParamRef<jobject>& java_controller) {
java_controller_.Reset(env, java_controller);
}
void NavigationControllerImpl::Navigate(
JNIEnv* env,
const base::android::JavaParamRef<jobject>& obj,
const base::android::JavaParamRef<jstring>& url) {
Navigate(GURL(base::android::ConvertJavaStringToUTF8(env, url)));
}
base::android::ScopedJavaLocalRef<jstring>
NavigationControllerImpl::GetNavigationEntryDisplayUri(
JNIEnv* env,
const base::android::JavaParamRef<jobject>& obj,
int index) {
return base::android::ScopedJavaLocalRef<jstring>(
base::android::ConvertUTF8ToJavaString(
env, GetNavigationEntryDisplayURL(index).spec()));
}
#endif
void NavigationControllerImpl::AddObserver(NavigationObserver* observer) {
observers_.AddObserver(observer);
}
void NavigationControllerImpl::RemoveObserver(NavigationObserver* observer) {
observers_.RemoveObserver(observer);
}
void NavigationControllerImpl::Navigate(const GURL& url) {
content::NavigationController::LoadURLParams params(url);
params.transition_type = ui::PageTransitionFromInt(
ui::PAGE_TRANSITION_TYPED | ui::PAGE_TRANSITION_FROM_ADDRESS_BAR);
browser_controller_->web_contents()->GetController().LoadURLWithParams(
params);
// So that if the user had entered the UI in a bar it stops flashing the
// caret.
browser_controller_->web_contents()->Focus();
}
void NavigationControllerImpl::GoBack() {
browser_controller_->web_contents()->GetController().GoBack();
}
void NavigationControllerImpl::GoForward() {
browser_controller_->web_contents()->GetController().GoForward();
}
void NavigationControllerImpl::Reload() {
browser_controller_->web_contents()->GetController().Reload(
content::ReloadType::NORMAL, false);
}
void NavigationControllerImpl::Stop() {
browser_controller_->web_contents()->Stop();
}
int NavigationControllerImpl::GetNavigationListSize() {
return browser_controller_->web_contents()->GetController().GetEntryCount();
}
int NavigationControllerImpl::GetNavigationListCurrentIndex() {
return browser_controller_->web_contents()
->GetController()
.GetCurrentEntryIndex();
}
GURL NavigationControllerImpl::GetNavigationEntryDisplayURL(int index) {
auto* entry =
browser_controller_->web_contents()->GetController().GetEntryAtIndex(
index);
if (!entry)
return GURL();
return entry->GetVirtualURL();
}
void NavigationControllerImpl::DidStartNavigation(
content::NavigationHandle* navigation_handle) {
if (!navigation_handle->IsInMainFrame())
return;
navigation_map_[navigation_handle] =
std::make_unique<NavigationImpl>(navigation_handle);
auto* navigation = navigation_map_[navigation_handle].get();
#if defined(OS_ANDROID)
if (java_controller_) {
JNIEnv* env = AttachCurrentThread();
Java_NavigationControllerImpl_createNavigation(
env, java_controller_, reinterpret_cast<jlong>(navigation));
Java_NavigationControllerImpl_navigationStarted(
env, java_controller_, navigation->java_navigation());
}
#endif
for (auto& observer : observers_)
observer.NavigationStarted(navigation);
}
void NavigationControllerImpl::DidRedirectNavigation(
content::NavigationHandle* navigation_handle) {
if (!navigation_handle->IsInMainFrame())
return;
DCHECK(navigation_map_.find(navigation_handle) != navigation_map_.end());
auto* navigation = navigation_map_[navigation_handle].get();
#if defined(OS_ANDROID)
if (java_controller_) {
Java_NavigationControllerImpl_navigationRedirected(
AttachCurrentThread(), java_controller_, navigation->java_navigation());
}
#endif
for (auto& observer : observers_)
observer.NavigationRedirected(navigation);
}
void NavigationControllerImpl::ReadyToCommitNavigation(
content::NavigationHandle* navigation_handle) {
if (!navigation_handle->IsInMainFrame())
return;
DCHECK(navigation_map_.find(navigation_handle) != navigation_map_.end());
auto* navigation = navigation_map_[navigation_handle].get();
#if defined(OS_ANDROID)
if (java_controller_) {
Java_NavigationControllerImpl_navigationCommitted(
AttachCurrentThread(), java_controller_, navigation->java_navigation());
}
#endif
for (auto& observer : observers_)
observer.NavigationCommitted(navigation);
}
void NavigationControllerImpl::DidFinishNavigation(
content::NavigationHandle* navigation_handle) {
if (!navigation_handle->IsInMainFrame())
return;
DCHECK(navigation_map_.find(navigation_handle) != navigation_map_.end());
auto* navigation = navigation_map_[navigation_handle].get();
if (navigation_handle->GetNetErrorCode() == net::OK &&
!navigation_handle->IsErrorPage()) {
#if defined(OS_ANDROID)
if (java_controller_) {
Java_NavigationControllerImpl_navigationCompleted(
AttachCurrentThread(), java_controller_,
navigation->java_navigation());
}
#endif
for (auto& observer : observers_)
observer.NavigationCompleted(navigation);
} else {
#if defined(OS_ANDROID)
if (java_controller_) {
Java_NavigationControllerImpl_navigationFailed(
AttachCurrentThread(), java_controller_,
navigation->java_navigation());
}
#endif
for (auto& observer : observers_)
observer.NavigationFailed(navigation);
}
navigation_map_.erase(navigation_map_.find(navigation_handle));
}
#if defined(OS_ANDROID)
static jlong JNI_NavigationControllerImpl_GetNavigationController(
JNIEnv* env,
jlong browserController) {
return reinterpret_cast<jlong>(
reinterpret_cast<BrowserController*>(browserController)
->GetNavigationController());
}
#endif
} // namespace weblayer