chromium/content/browser/android/navigation_handle_proxy.cc

// Copyright 2019 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "content/browser/android/navigation_handle_proxy.h"

#include "base/android/jni_android.h"
#include "base/android/jni_string.h"
#include "base/android/scoped_java_ref.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/navigation_handle.h"
#include "content/public/common/content_client.h"
#include "net/http/http_response_headers.h"
#include "url/android/gurl_android.h"
#include "url/gurl.h"

// Must come after all headers that specialize FromJniType() / ToJniType().
#include "content/public/android/content_jni_headers/NavigationHandle_jni.h"

using base::android::AttachCurrentThread;
using base::android::JavaParamRef;

namespace content {

NavigationHandleProxy::NavigationHandleProxy(
    NavigationHandle* cpp_navigation_handle)
    : cpp_navigation_handle_(cpp_navigation_handle) {
  JNIEnv* env = AttachCurrentThread();

  java_navigation_handle_ = Java_NavigationHandle_Constructor(
      env, reinterpret_cast<jlong>(cpp_navigation_handle));
}

void NavigationHandleProxy::DidStart() {
  JNIEnv* env = AttachCurrentThread();

  // Set all these methods on the Java side over JNI with a new JNI method.
  Java_NavigationHandle_initialize(
      env, java_navigation_handle_, reinterpret_cast<jlong>(this),
      url::GURLAndroid::FromNativeGURL(env, cpp_navigation_handle_->GetURL()),
      url::GURLAndroid::FromNativeGURL(
          env, cpp_navigation_handle_->GetReferrer().url),
      url::GURLAndroid::FromNativeGURL(
          env, cpp_navigation_handle_->GetBaseURLForDataURL()),
      cpp_navigation_handle_->IsInPrimaryMainFrame(),
      cpp_navigation_handle_->IsSameDocument(),
      cpp_navigation_handle_->IsRendererInitiated(),
      cpp_navigation_handle_->GetInitiatorOrigin()
          ? cpp_navigation_handle_->GetInitiatorOrigin()->ToJavaObject()
          : nullptr,
      cpp_navigation_handle_->GetPageTransition(),
      cpp_navigation_handle_->IsPost(),
      cpp_navigation_handle_->HasUserGesture(),
      cpp_navigation_handle_->WasServerRedirect(),
      cpp_navigation_handle_->IsExternalProtocol(),
      cpp_navigation_handle_->GetNavigationId(),
      cpp_navigation_handle_->IsPageActivation(),
      cpp_navigation_handle_->GetReloadType() != content::ReloadType::NONE,
      cpp_navigation_handle_->IsPdf(),
      base::android::ConvertUTF8ToJavaString(env, GetMimeType()),
      GetContentClient()->browser()->IsSaveableNavigation(
          cpp_navigation_handle_));
}

void NavigationHandleProxy::DidRedirect() {
  JNIEnv* env = AttachCurrentThread();
  Java_NavigationHandle_didRedirect(
      env, java_navigation_handle_,
      url::GURLAndroid::FromNativeGURL(env, cpp_navigation_handle_->GetURL()),
      cpp_navigation_handle_->IsExternalProtocol());
}

void NavigationHandleProxy::DidFinish() {
  JNIEnv* env = AttachCurrentThread();
  // Matches logic in
  // components/navigation_interception/navigation_params_android.cc
  const GURL& gurl = cpp_navigation_handle_->GetBaseURLForDataURL().is_empty()
                         ? cpp_navigation_handle_->GetURL()
                         : cpp_navigation_handle_->GetBaseURLForDataURL();

  bool is_primary_main_frame_fragment_navigation =
      cpp_navigation_handle_->IsInPrimaryMainFrame() &&
      cpp_navigation_handle_->IsSameDocument();

  if (is_primary_main_frame_fragment_navigation &&
      cpp_navigation_handle_->HasCommitted()) {
    // See http://crbug.com/251330 for why it's determined this way.
    bool urls_same_ignoring_fragment =
        cpp_navigation_handle_->GetURL().EqualsIgnoringRef(
            cpp_navigation_handle_->GetPreviousPrimaryMainFrameURL());
    is_primary_main_frame_fragment_navigation = urls_same_ignoring_fragment;
  }

  bool is_valid_search_form_url =
      cpp_navigation_handle_->GetSearchableFormURL() != ""
          ? cpp_navigation_handle_->GetSearchableFormURL().is_valid()
          : false;

  Java_NavigationHandle_didFinish(
      env, java_navigation_handle_, url::GURLAndroid::FromNativeGURL(env, gurl),
      cpp_navigation_handle_->IsErrorPage(),
      cpp_navigation_handle_->HasCommitted(),
      is_primary_main_frame_fragment_navigation,
      cpp_navigation_handle_->IsDownload(), is_valid_search_form_url,
      cpp_navigation_handle_->GetPageTransition(),
      cpp_navigation_handle_->GetNetErrorCode(),
      // TODO(shaktisahu): Change default status to -1 after fixing
      // crbug/690041.
      cpp_navigation_handle_->GetResponseHeaders()
          ? cpp_navigation_handle_->GetResponseHeaders()->response_code()
          : 200,
      cpp_navigation_handle_->IsExternalProtocol(),
      cpp_navigation_handle_->IsPdf(),
      base::android::ConvertUTF8ToJavaString(env, GetMimeType()),
      GetContentClient()->browser()->IsSaveableNavigation(
          cpp_navigation_handle_));
}

NavigationHandleProxy::~NavigationHandleProxy() {
  JNIEnv* env = AttachCurrentThread();
  Java_NavigationHandle_release(env, java_navigation_handle_);
}

std::string NavigationHandleProxy::GetMimeType() const {
  std::string mime_type;
  if (cpp_navigation_handle_->GetResponseHeaders()) {
    cpp_navigation_handle_->GetResponseHeaders()->GetMimeType(&mime_type);
  }
  return mime_type;
}

}  // namespace content