/*
 * Copyright (C) 2009, 2012 Google Inc. All rights reserved.
 * Copyright (C) 2011 Apple Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above
 * copyright notice, this list of conditions and the following disclaimer
 * in the documentation and/or other materials provided with the
 * distribution.
 *     * Neither the name of Google Inc. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "web/FrameLoaderClientImpl.h"

#include "bindings/core/v8/ScriptController.h"
#include "core/HTMLNames.h"
#include "core/dom/Document.h"
#include "core/dom/Fullscreen.h"
#include "core/events/MessageEvent.h"
#include "core/events/MouseEvent.h"
#include "core/events/UIEventWithKeyState.h"
#include "core/frame/FrameView.h"
#include "core/frame/Settings.h"
#include "core/html/HTMLFrameElementBase.h"
#include "core/html/HTMLMediaElement.h"
#include "core/html/HTMLPlugInElement.h"
#include "core/input/EventHandler.h"
#include "core/layout/HitTestResult.h"
#include "core/loader/DocumentLoader.h"
#include "core/loader/FrameLoadRequest.h"
#include "core/loader/FrameLoader.h"
#include "core/loader/HistoryItem.h"
#include "core/origin_trials/OriginTrials.h"
#include "core/page/Page.h"
#include "core/page/WindowFeatures.h"
#include "modules/audio_output_devices/HTMLMediaElementAudioOutputDevice.h"
#include "modules/device_light/DeviceLightController.h"
#include "modules/device_orientation/DeviceMotionController.h"
#include "modules/device_orientation/DeviceOrientationAbsoluteController.h"
#include "modules/device_orientation/DeviceOrientationController.h"
#include "modules/encryptedmedia/HTMLMediaElementEncryptedMedia.h"
#include "modules/gamepad/NavigatorGamepad.h"
#include "modules/remoteplayback/HTMLMediaElementRemotePlayback.h"
#include "modules/remoteplayback/RemotePlayback.h"
#include "modules/serviceworkers/NavigatorServiceWorker.h"
#include "modules/serviceworkers/ServiceWorkerLinkResource.h"
#include "modules/storage/DOMWindowStorageController.h"
#include "modules/vr/NavigatorVR.h"
#include "platform/Histogram.h"
#include "platform/MIMETypeRegistry.h"
#include "platform/RuntimeEnabledFeatures.h"
#include "platform/UserGestureIndicator.h"
#include "platform/exported/WrappedResourceRequest.h"
#include "platform/exported/WrappedResourceResponse.h"
#include "platform/network/HTTPParsers.h"
#include "platform/plugins/PluginData.h"
#include "public/platform/Platform.h"
#include "public/platform/WebApplicationCacheHost.h"
#include "public/platform/WebMediaPlayerSource.h"
#include "public/platform/WebRTCPeerConnectionHandler.h"
#include "public/platform/WebSecurityOrigin.h"
#include "public/platform/WebURL.h"
#include "public/platform/WebURLError.h"
#include "public/platform/WebVector.h"
#include "public/platform/modules/serviceworker/WebServiceWorkerProvider.h"
#include "public/platform/modules/serviceworker/WebServiceWorkerProviderClient.h"
#include "public/web/WebAutofillClient.h"
#include "public/web/WebContentSettingsClient.h"
#include "public/web/WebDOMEvent.h"
#include "public/web/WebDocument.h"
#include "public/web/WebFormElement.h"
#include "public/web/WebFrameClient.h"
#include "public/web/WebNode.h"
#include "public/web/WebPlugin.h"
#include "public/web/WebPluginParams.h"
#include "public/web/WebViewClient.h"
#include "web/DevToolsEmulator.h"
#include "web/SharedWorkerRepositoryClientImpl.h"
#include "web/WebDataSourceImpl.h"
#include "web/WebDevToolsAgentImpl.h"
#include "web/WebDevToolsFrontendImpl.h"
#include "web/WebLocalFrameImpl.h"
#include "web/WebPluginContainerImpl.h"
#include "web/WebViewImpl.h"
#include "wtf/PtrUtil.h"
#include "wtf/StringExtras.h"
#include "wtf/text/CString.h"
#include "wtf/text/WTFString.h"
#include <memory>
#include <v8.h>

namespace blink {

namespace {

// Convenience helper for frame tree helpers in FrameClient to reduce the amount
// of null-checking boilerplate code. Since the frame tree is maintained in the
// web/ layer, the frame tree helpers often have to deal with null WebFrames:
// for example, a frame with no parent will return null for WebFrame::parent().
// TODO(dcheng): Remove duplication between FrameLoaderClientImpl and
// RemoteFrameClientImpl somehow...
Frame* toCoreFrame(WebFrame* frame) {
  return frame ? frame->toImplBase()->frame() : nullptr;
}

}  // namespace

FrameLoaderClientImpl::FrameLoaderClientImpl(WebLocalFrameImpl* frame)
    : m_webFrame(frame) {}

FrameLoaderClientImpl* FrameLoaderClientImpl::create(WebLocalFrameImpl* frame) {
  return new FrameLoaderClientImpl(frame);
}

FrameLoaderClientImpl::~FrameLoaderClientImpl() {}

DEFINE_TRACE(FrameLoaderClientImpl) {
  visitor->trace(m_webFrame);
  FrameLoaderClient::trace(visitor);
}

void FrameLoaderClientImpl::didCreateNewDocument() {
  if (m_webFrame->client())
    m_webFrame->client()->didCreateNewDocument(m_webFrame);
}

void FrameLoaderClientImpl::dispatchDidClearWindowObjectInMainWorld() {
  if (m_webFrame->client()) {
    m_webFrame->client()->didClearWindowObject(m_webFrame);
    Document* document = m_webFrame->frame()->document();
    if (document) {
      DeviceMotionController::from(*document);
      DeviceOrientationController::from(*document);
      DeviceOrientationAbsoluteController::from(*document);
      if (RuntimeEnabledFeatures::deviceLightEnabled())
        DeviceLightController::from(*document);
      NavigatorGamepad::from(*document);
      NavigatorServiceWorker::from(*document);
      DOMWindowStorageController::from(*document);
      if (RuntimeEnabledFeatures::webVREnabled() ||
          OriginTrials::webVREnabled(document->getExecutionContext()))
        NavigatorVR::from(*document);
    }
  }
  // FIXME: when extensions go out of process, this whole concept stops working.
  WebDevToolsFrontendImpl* devToolsFrontend =
      m_webFrame->top()->isWebLocalFrame()
          ? toWebLocalFrameImpl(m_webFrame->top())->devToolsFrontend()
          : nullptr;
  if (devToolsFrontend)
    devToolsFrontend->didClearWindowObject(m_webFrame);
}

void FrameLoaderClientImpl::documentElementAvailable() {
  if (m_webFrame->client())
    m_webFrame->client()->didCreateDocumentElement(m_webFrame);
}

void FrameLoaderClientImpl::runScriptsAtDocumentElementAvailable() {
  if (m_webFrame->client())
    m_webFrame->client()->runScriptsAtDocumentElementAvailable(m_webFrame);
  // The callback might have deleted the frame, do not use |this|!
}

void FrameLoaderClientImpl::runScriptsAtDocumentReady(bool documentIsEmpty) {
  if (m_webFrame->client())
    m_webFrame->client()->runScriptsAtDocumentReady(m_webFrame,
                                                    documentIsEmpty);
  // The callback might have deleted the frame, do not use |this|!
}

void FrameLoaderClientImpl::didCreateScriptContext(
    v8::Local<v8::Context> context,
    int extensionGroup,
    int worldId) {
  if (m_webFrame->client())
    m_webFrame->client()->didCreateScriptContext(m_webFrame, context,
                                                 extensionGroup, worldId);
}

void FrameLoaderClientImpl::willReleaseScriptContext(
    v8::Local<v8::Context> context,
    int worldId) {
  if (m_webFrame->client())
    m_webFrame->client()->willReleaseScriptContext(m_webFrame, context,
                                                   worldId);
}

bool FrameLoaderClientImpl::allowScriptExtension(const String& extensionName,
                                                 int extensionGroup,
                                                 int worldId) {
  if (m_webFrame->contentSettingsClient())
    return m_webFrame->contentSettingsClient()->allowScriptExtension(
        extensionName, extensionGroup, worldId);

  return true;
}

void FrameLoaderClientImpl::didChangeScrollOffset() {
  if (m_webFrame->client())
    m_webFrame->client()->didChangeScrollOffset(m_webFrame);
}

void FrameLoaderClientImpl::didUpdateCurrentHistoryItem() {
  if (m_webFrame->client())
    m_webFrame->client()->didUpdateCurrentHistoryItem();
}

bool FrameLoaderClientImpl::allowScript(bool enabledPerSettings) {
  if (m_webFrame->contentSettingsClient())
    return m_webFrame->contentSettingsClient()->allowScript(enabledPerSettings);

  return enabledPerSettings;
}

bool FrameLoaderClientImpl::allowScriptFromSource(bool enabledPerSettings,
                                                  const KURL& scriptURL) {
  if (m_webFrame->contentSettingsClient())
    return m_webFrame->contentSettingsClient()->allowScriptFromSource(
        enabledPerSettings, scriptURL);

  return enabledPerSettings;
}

bool FrameLoaderClientImpl::allowPlugins(bool enabledPerSettings) {
  if (m_webFrame->contentSettingsClient())
    return m_webFrame->contentSettingsClient()->allowPlugins(
        enabledPerSettings);

  return enabledPerSettings;
}

bool FrameLoaderClientImpl::allowImage(bool enabledPerSettings,
                                       const KURL& imageURL) {
  if (m_webFrame->contentSettingsClient())
    return m_webFrame->contentSettingsClient()->allowImage(enabledPerSettings,
                                                           imageURL);

  return enabledPerSettings;
}

bool FrameLoaderClientImpl::allowRunningInsecureContent(bool enabledPerSettings,
                                                        SecurityOrigin* context,
                                                        const KURL& url) {
  if (m_webFrame->contentSettingsClient())
    return m_webFrame->contentSettingsClient()->allowRunningInsecureContent(
        enabledPerSettings, WebSecurityOrigin(context), WebURL(url));

  return enabledPerSettings;
}

bool FrameLoaderClientImpl::allowAutoplay(bool defaultValue) {
  if (m_webFrame->contentSettingsClient())
    return m_webFrame->contentSettingsClient()->allowAutoplay(defaultValue);

  return defaultValue;
}

void FrameLoaderClientImpl::passiveInsecureContentFound(const KURL& url) {
  if (m_webFrame->contentSettingsClient())
    return m_webFrame->contentSettingsClient()->passiveInsecureContentFound(
        WebURL(url));
}

void FrameLoaderClientImpl::didNotAllowScript() {
  if (m_webFrame->contentSettingsClient())
    m_webFrame->contentSettingsClient()->didNotAllowScript();
}

void FrameLoaderClientImpl::didNotAllowPlugins() {
  if (m_webFrame->contentSettingsClient())
    m_webFrame->contentSettingsClient()->didNotAllowPlugins();
}

void FrameLoaderClientImpl::didUseKeygen() {
  if (m_webFrame->contentSettingsClient())
    m_webFrame->contentSettingsClient()->didUseKeygen();
}

bool FrameLoaderClientImpl::hasWebView() const {
  return m_webFrame->viewImpl();
}

bool FrameLoaderClientImpl::inShadowTree() const {
  return m_webFrame->inShadowTree();
}

Frame* FrameLoaderClientImpl::opener() const {
  return toCoreFrame(m_webFrame->opener());
}

void FrameLoaderClientImpl::setOpener(Frame* opener) {
  WebFrame* openerFrame = WebFrame::fromFrame(opener);
  if (m_webFrame->client() && m_webFrame->opener() != openerFrame)
    m_webFrame->client()->didChangeOpener(openerFrame);
  m_webFrame->setOpener(openerFrame);
}

Frame* FrameLoaderClientImpl::parent() const {
  return toCoreFrame(m_webFrame->parent());
}

Frame* FrameLoaderClientImpl::top() const {
  return toCoreFrame(m_webFrame->top());
}

Frame* FrameLoaderClientImpl::nextSibling() const {
  return toCoreFrame(m_webFrame->nextSibling());
}

Frame* FrameLoaderClientImpl::firstChild() const {
  return toCoreFrame(m_webFrame->firstChild());
}

void FrameLoaderClientImpl::willBeDetached() {
  m_webFrame->willBeDetached();
}

void FrameLoaderClientImpl::detached(FrameDetachType type) {
  // Alert the client that the frame is being detached. This is the last
  // chance we have to communicate with the client.
  WebFrameClient* client = m_webFrame->client();
  if (!client)
    return;

  m_webFrame->willDetachParent();

  // Signal that no further communication with WebFrameClient should take
  // place at this point since we are no longer associated with the Page.
  m_webFrame->setClient(0);

  client->frameDetached(m_webFrame,
                        static_cast<WebFrameClient::DetachType>(type));
  // Clear our reference to LocalFrame at the very end, in case the client
  // refers to it.
  m_webFrame->setCoreFrame(nullptr);
}

void FrameLoaderClientImpl::dispatchWillSendRequest(ResourceRequest& request) {
  // Give the WebFrameClient a crack at the request.
  if (m_webFrame->client()) {
    WrappedResourceRequest webreq(request);
    m_webFrame->client()->willSendRequest(m_webFrame, webreq);
  }
}

void FrameLoaderClientImpl::dispatchDidReceiveResponse(
    const ResourceResponse& response) {
  if (m_webFrame->client()) {
    WrappedResourceResponse webresp(response);
    m_webFrame->client()->didReceiveResponse(webresp);
  }
}

void FrameLoaderClientImpl::dispatchDidFinishDocumentLoad() {
  // TODO(dglazkov): Sadly, workers are WebFrameClients, and they can totally
  // destroy themselves when didFinishDocumentLoad is invoked, and in turn
  // destroy the fake WebLocalFrame that they create, which means that you
  // should not put any code touching `this` after the two lines below.
  if (m_webFrame->client())
    m_webFrame->client()->didFinishDocumentLoad(m_webFrame);
}

void FrameLoaderClientImpl::dispatchDidLoadResourceFromMemoryCache(
    const ResourceRequest& request,
    const ResourceResponse& response) {
  if (m_webFrame->client())
    m_webFrame->client()->didLoadResourceFromMemoryCache(
        WrappedResourceRequest(request), WrappedResourceResponse(response));
}

void FrameLoaderClientImpl::dispatchDidHandleOnloadEvents() {
  if (m_webFrame->client())
    m_webFrame->client()->didHandleOnloadEvents(m_webFrame);
}

void FrameLoaderClientImpl::
    dispatchDidReceiveServerRedirectForProvisionalLoad() {
  if (m_webFrame->client())
    m_webFrame->client()->didReceiveServerRedirectForProvisionalLoad(
        m_webFrame);
}

void FrameLoaderClientImpl::dispatchDidNavigateWithinPage(
    HistoryItem* item,
    HistoryCommitType commitType,
    bool contentInitiated) {
  bool shouldCreateHistoryEntry = commitType == StandardCommit;
  // TODO(dglazkov): Does this need to be called for subframes?
  m_webFrame->viewImpl()->didCommitLoad(shouldCreateHistoryEntry, true);
  if (m_webFrame->client())
    m_webFrame->client()->didNavigateWithinPage(
        m_webFrame, WebHistoryItem(item),
        static_cast<WebHistoryCommitType>(commitType), contentInitiated);
}

void FrameLoaderClientImpl::dispatchWillCommitProvisionalLoad() {
  if (m_webFrame->client())
    m_webFrame->client()->willCommitProvisionalLoad(m_webFrame);
}

void FrameLoaderClientImpl::dispatchDidStartProvisionalLoad() {
  if (m_webFrame->client())
    m_webFrame->client()->didStartProvisionalLoad(m_webFrame);
  if (WebDevToolsAgentImpl* devTools = devToolsAgent())
    devTools->didStartProvisionalLoad(m_webFrame->frame());
}

void FrameLoaderClientImpl::dispatchDidReceiveTitle(const String& title) {
  if (m_webFrame->client())
    m_webFrame->client()->didReceiveTitle(m_webFrame, title,
                                          WebTextDirectionLeftToRight);
}

void FrameLoaderClientImpl::dispatchDidChangeIcons(IconType type) {
  if (m_webFrame->client())
    m_webFrame->client()->didChangeIcon(m_webFrame,
                                        static_cast<WebIconURL::Type>(type));
}

void FrameLoaderClientImpl::dispatchDidCommitLoad(
    HistoryItem* item,
    HistoryCommitType commitType) {
  if (!m_webFrame->parent()) {
    m_webFrame->viewImpl()->didCommitLoad(commitType == StandardCommit, false);
  }

  if (m_webFrame->client())
    m_webFrame->client()->didCommitProvisionalLoad(
        m_webFrame, WebHistoryItem(item),
        static_cast<WebHistoryCommitType>(commitType));
  if (WebDevToolsAgentImpl* devTools = devToolsAgent())
    devTools->didCommitLoadForLocalFrame(m_webFrame->frame());
}

void FrameLoaderClientImpl::dispatchDidFailProvisionalLoad(
    const ResourceError& error,
    HistoryCommitType commitType) {
  m_webFrame->didFail(error, true, commitType);
}

void FrameLoaderClientImpl::dispatchDidFailLoad(const ResourceError& error,
                                                HistoryCommitType commitType) {
  m_webFrame->didFail(error, false, commitType);
}

void FrameLoaderClientImpl::dispatchDidFinishLoad() {
  m_webFrame->didFinish();
}

void FrameLoaderClientImpl::dispatchDidChangeThemeColor() {
  if (m_webFrame->client())
    m_webFrame->client()->didChangeThemeColor();
}

static bool allowCreatingBackgroundTabs() {
  const WebInputEvent* inputEvent = WebViewImpl::currentInputEvent();
  if (!inputEvent || (inputEvent->type != WebInputEvent::MouseUp &&
                      (inputEvent->type != WebInputEvent::RawKeyDown &&
                       inputEvent->type != WebInputEvent::KeyDown) &&
                      inputEvent->type != WebInputEvent::GestureTap))
    return false;

  unsigned short buttonNumber;
  if (WebInputEvent::isMouseEventType(inputEvent->type)) {
    const WebMouseEvent* mouseEvent =
        static_cast<const WebMouseEvent*>(inputEvent);

    switch (mouseEvent->button) {
      case WebMouseEvent::Button::Left:
        buttonNumber = 0;
        break;
      case WebMouseEvent::Button::Middle:
        buttonNumber = 1;
        break;
      case WebMouseEvent::Button::Right:
        buttonNumber = 2;
        break;
      default:
        return false;
    }
  } else {
    // The click is simulated when triggering the keypress event.
    buttonNumber = 0;
  }
  bool ctrl = inputEvent->modifiers & WebMouseEvent::ControlKey;
  bool shift = inputEvent->modifiers & WebMouseEvent::ShiftKey;
  bool alt = inputEvent->modifiers & WebMouseEvent::AltKey;
  bool meta = inputEvent->modifiers & WebMouseEvent::MetaKey;

  NavigationPolicy userPolicy;
  if (!navigationPolicyFromMouseEvent(buttonNumber, ctrl, shift, alt, meta,
                                      &userPolicy))
    return false;
  return userPolicy == NavigationPolicyNewBackgroundTab;
}

NavigationPolicy FrameLoaderClientImpl::decidePolicyForNavigation(
    const ResourceRequest& request,
    DocumentLoader* loader,
    NavigationType type,
    NavigationPolicy policy,
    bool replacesCurrentHistoryItem,
    bool isClientRedirect,
    HTMLFormElement* form) {
  if (!m_webFrame->client())
    return NavigationPolicyIgnore;

  if (policy == NavigationPolicyNewBackgroundTab &&
      !allowCreatingBackgroundTabs() &&
      !UIEventWithKeyState::newTabModifierSetFromIsolatedWorld())
    policy = NavigationPolicyNewForegroundTab;

  WebDataSourceImpl* ds = WebDataSourceImpl::fromDocumentLoader(loader);

  // Newly created child frames may need to be navigated to a history item
  // during a back/forward navigation. This will only happen when the parent
  // is a LocalFrame doing a back/forward navigation that has not completed.
  // (If the load has completed and the parent later adds a frame with script,
  // we do not want to use a history item for it.)
  bool isHistoryNavigationInNewChildFrame =
      m_webFrame->parent() && m_webFrame->parent()->isWebLocalFrame() &&
      isBackForwardLoadType(toWebLocalFrameImpl(m_webFrame->parent())
                                ->frame()
                                ->loader()
                                .loadType()) &&
      !toWebLocalFrameImpl(m_webFrame->parent())
           ->frame()
           ->document()
           ->loadEventFinished();

  WrappedResourceRequest wrappedResourceRequest(request);
  WebFrameClient::NavigationPolicyInfo navigationInfo(wrappedResourceRequest);
  navigationInfo.navigationType = static_cast<WebNavigationType>(type);
  navigationInfo.defaultPolicy = static_cast<WebNavigationPolicy>(policy);
  navigationInfo.extraData = ds ? ds->getExtraData() : nullptr;
  navigationInfo.replacesCurrentHistoryItem = replacesCurrentHistoryItem;
  navigationInfo.isHistoryNavigationInNewChildFrame =
      isHistoryNavigationInNewChildFrame;
  navigationInfo.isClientRedirect = isClientRedirect;
  if (form)
    navigationInfo.form = WebFormElement(form);

  WebNavigationPolicy webPolicy =
      m_webFrame->client()->decidePolicyForNavigation(navigationInfo);
  return static_cast<NavigationPolicy>(webPolicy);
}

void FrameLoaderClientImpl::dispatchWillSendSubmitEvent(HTMLFormElement* form) {
  if (m_webFrame->client())
    m_webFrame->client()->willSendSubmitEvent(WebFormElement(form));
}

void FrameLoaderClientImpl::dispatchWillSubmitForm(HTMLFormElement* form) {
  if (m_webFrame->client())
    m_webFrame->client()->willSubmitForm(WebFormElement(form));
}

void FrameLoaderClientImpl::didStartLoading(LoadStartType loadStartType) {
  if (m_webFrame->client())
    m_webFrame->client()->didStartLoading(loadStartType ==
                                          NavigationToDifferentDocument);
}

void FrameLoaderClientImpl::progressEstimateChanged(double progressEstimate) {
  if (m_webFrame->client())
    m_webFrame->client()->didChangeLoadProgress(progressEstimate);
}

void FrameLoaderClientImpl::didStopLoading() {
  if (m_webFrame->client())
    m_webFrame->client()->didStopLoading();
}

void FrameLoaderClientImpl::loadURLExternally(const ResourceRequest& request,
                                              NavigationPolicy policy,
                                              const String& suggestedName,
                                              bool shouldReplaceCurrentEntry) {
  if (!m_webFrame->client())
    return;
  DCHECK(m_webFrame->frame()->document());
  Fullscreen::fullyExitFullscreen(*m_webFrame->frame()->document());
  m_webFrame->client()->loadURLExternally(
      WrappedResourceRequest(request), static_cast<WebNavigationPolicy>(policy),
      suggestedName, shouldReplaceCurrentEntry);
}

bool FrameLoaderClientImpl::navigateBackForward(int offset) const {
  WebViewImpl* webview = m_webFrame->viewImpl();
  if (!webview->client())
    return false;

  DCHECK(offset);
  if (offset > webview->client()->historyForwardListCount())
    return false;
  if (offset < -webview->client()->historyBackListCount())
    return false;
  webview->client()->navigateBackForwardSoon(offset);
  return true;
}

void FrameLoaderClientImpl::didAccessInitialDocument() {
  if (m_webFrame->client())
    m_webFrame->client()->didAccessInitialDocument();
}

void FrameLoaderClientImpl::didDisplayInsecureContent() {
  if (m_webFrame->client())
    m_webFrame->client()->didDisplayInsecureContent();
}

void FrameLoaderClientImpl::didRunInsecureContent(SecurityOrigin* origin,
                                                  const KURL& insecureURL) {
  if (m_webFrame->client())
    m_webFrame->client()->didRunInsecureContent(WebSecurityOrigin(origin),
                                                insecureURL);
}

void FrameLoaderClientImpl::didDetectXSS(const KURL& insecureURL,
                                         bool didBlockEntirePage) {
  if (m_webFrame->client())
    m_webFrame->client()->didDetectXSS(insecureURL, didBlockEntirePage);
}

void FrameLoaderClientImpl::didDispatchPingLoader(const KURL& url) {
  if (m_webFrame->client())
    m_webFrame->client()->didDispatchPingLoader(url);
}

void FrameLoaderClientImpl::didDisplayContentWithCertificateErrors(
    const KURL& url) {
  if (m_webFrame->client())
    m_webFrame->client()->didDisplayContentWithCertificateErrors(url);
}

void FrameLoaderClientImpl::didRunContentWithCertificateErrors(
    const KURL& url) {
  if (m_webFrame->client())
    m_webFrame->client()->didRunContentWithCertificateErrors(url);
}

void FrameLoaderClientImpl::didChangePerformanceTiming() {
  if (m_webFrame->client())
    m_webFrame->client()->didChangePerformanceTiming();
}

void FrameLoaderClientImpl::didObserveLoadingBehavior(
    WebLoadingBehaviorFlag behavior) {
  if (m_webFrame->client())
    m_webFrame->client()->didObserveLoadingBehavior(behavior);
}

void FrameLoaderClientImpl::selectorMatchChanged(
    const Vector<String>& addedSelectors,
    const Vector<String>& removedSelectors) {
  if (WebFrameClient* client = m_webFrame->client())
    client->didMatchCSS(m_webFrame, WebVector<WebString>(addedSelectors),
                        WebVector<WebString>(removedSelectors));
}

DocumentLoader* FrameLoaderClientImpl::createDocumentLoader(
    LocalFrame* frame,
    const ResourceRequest& request,
    const SubstituteData& data,
    ClientRedirectPolicy clientRedirectPolicy) {
  WebDataSourceImpl* ds =
      WebDataSourceImpl::create(frame, request, data, clientRedirectPolicy);
  if (m_webFrame->client())
    m_webFrame->client()->didCreateDataSource(m_webFrame, ds);
  return ds;
}

String FrameLoaderClientImpl::userAgent() {
  WebString override =
      m_webFrame->client() ? m_webFrame->client()->userAgentOverride() : "";
  if (!override.isEmpty())
    return override;

  if (m_userAgent.isEmpty())
    m_userAgent = Platform::current()->userAgent();
  return m_userAgent;
}

String FrameLoaderClientImpl::doNotTrackValue() {
  WebString doNotTrack = m_webFrame->client()->doNotTrackValue();
  if (!doNotTrack.isEmpty())
    return doNotTrack;
  return String();
}

// Called when the FrameLoader goes into a state in which a new page load
// will occur.
void FrameLoaderClientImpl::transitionToCommittedForNewPage() {
  m_webFrame->createFrameView();
}

LocalFrame* FrameLoaderClientImpl::createFrame(
    const FrameLoadRequest& request,
    const AtomicString& name,
    HTMLFrameOwnerElement* ownerElement) {
  return m_webFrame->createChildFrame(request, name, ownerElement);
}

bool FrameLoaderClientImpl::canCreatePluginWithoutRenderer(
    const String& mimeType) const {
  if (!m_webFrame->client())
    return false;

  return m_webFrame->client()->canCreatePluginWithoutRenderer(mimeType);
}

Widget* FrameLoaderClientImpl::createPlugin(HTMLPlugInElement* element,
                                            const KURL& url,
                                            const Vector<String>& paramNames,
                                            const Vector<String>& paramValues,
                                            const String& mimeType,
                                            bool loadManually,
                                            DetachedPluginPolicy policy) {
  if (!m_webFrame->client())
    return nullptr;

  WebPluginParams params;
  params.url = url;
  params.mimeType = mimeType;
  params.attributeNames = paramNames;
  params.attributeValues = paramValues;
  params.loadManually = loadManually;

  WebPlugin* webPlugin = m_webFrame->client()->createPlugin(m_webFrame, params);
  if (!webPlugin)
    return nullptr;

  // The container takes ownership of the WebPlugin.
  WebPluginContainerImpl* container =
      WebPluginContainerImpl::create(element, webPlugin);

  if (!webPlugin->initialize(container))
    return nullptr;

  if (policy != AllowDetachedPlugin && !element->layoutObject())
    return nullptr;

  return container;
}

std::unique_ptr<WebMediaPlayer> FrameLoaderClientImpl::createWebMediaPlayer(
    HTMLMediaElement& htmlMediaElement,
    const WebMediaPlayerSource& source,
    WebMediaPlayerClient* client) {
  WebLocalFrameImpl* webFrame =
      WebLocalFrameImpl::fromFrame(htmlMediaElement.document().frame());

  if (!webFrame || !webFrame->client())
    return nullptr;

  HTMLMediaElementEncryptedMedia& encryptedMedia =
      HTMLMediaElementEncryptedMedia::from(htmlMediaElement);
  WebString sinkId(HTMLMediaElementAudioOutputDevice::sinkId(htmlMediaElement));
  return wrapUnique(webFrame->client()->createMediaPlayer(
      source, client, &encryptedMedia, encryptedMedia.contentDecryptionModule(),
      sinkId));
}

WebRemotePlaybackClient* FrameLoaderClientImpl::createWebRemotePlaybackClient(
    HTMLMediaElement& htmlMediaElement) {
  return HTMLMediaElementRemotePlayback::remote(htmlMediaElement);
}

ObjectContentType FrameLoaderClientImpl::getObjectContentType(
    const KURL& url,
    const String& explicitMimeType,
    bool shouldPreferPlugInsForImages) {
  // This code is based on Apple's implementation from
  // WebCoreSupport/WebFrameBridge.mm.

  String mimeType = explicitMimeType;
  if (mimeType.isEmpty()) {
    // Try to guess the MIME type based off the extension.
    String filename = url.lastPathComponent();
    int extensionPos = filename.reverseFind('.');
    if (extensionPos >= 0) {
      String extension = filename.substring(extensionPos + 1);
      mimeType = MIMETypeRegistry::getWellKnownMIMETypeForExtension(extension);
    }

    if (mimeType.isEmpty())
      return ObjectContentFrame;
  }

  // If Chrome is started with the --disable-plugins switch, pluginData is 0.
  PluginData* pluginData = m_webFrame->frame()->pluginData();
  bool plugInSupportsMIMEType =
      pluginData && pluginData->supportsMimeType(mimeType);

  if (MIMETypeRegistry::isSupportedImageMIMEType(mimeType))
    return shouldPreferPlugInsForImages && plugInSupportsMIMEType
               ? ObjectContentNetscapePlugin
               : ObjectContentImage;

  if (plugInSupportsMIMEType)
    return ObjectContentNetscapePlugin;

  if (MIMETypeRegistry::isSupportedNonImageMIMEType(mimeType))
    return ObjectContentFrame;

  return ObjectContentNone;
}

WebCookieJar* FrameLoaderClientImpl::cookieJar() const {
  if (!m_webFrame->client())
    return 0;
  return m_webFrame->client()->cookieJar();
}

void FrameLoaderClientImpl::frameFocused() const {
  if (m_webFrame->client())
    m_webFrame->client()->frameFocused();
}

void FrameLoaderClientImpl::didChangeName(const String& name,
                                          const String& uniqueName) {
  if (!m_webFrame->client())
    return;
  m_webFrame->client()->didChangeName(name, uniqueName);
}

void FrameLoaderClientImpl::didEnforceInsecureRequestPolicy(
    WebInsecureRequestPolicy policy) {
  if (!m_webFrame->client())
    return;
  m_webFrame->client()->didEnforceInsecureRequestPolicy(policy);
}

void FrameLoaderClientImpl::didUpdateToUniqueOrigin() {
  if (!m_webFrame->client())
    return;
  DCHECK(m_webFrame->getSecurityOrigin().isUnique());
  m_webFrame->client()->didUpdateToUniqueOrigin(
      m_webFrame->getSecurityOrigin().isPotentiallyTrustworthy());
}

void FrameLoaderClientImpl::didChangeSandboxFlags(Frame* childFrame,
                                                  SandboxFlags flags) {
  if (!m_webFrame->client())
    return;
  m_webFrame->client()->didChangeSandboxFlags(
      WebFrame::fromFrame(childFrame), static_cast<WebSandboxFlags>(flags));
}

void FrameLoaderClientImpl::didAddContentSecurityPolicy(
    const String& headerValue,
    ContentSecurityPolicyHeaderType type,
    ContentSecurityPolicyHeaderSource source) {
  if (m_webFrame->client()) {
    m_webFrame->client()->didAddContentSecurityPolicy(
        headerValue, static_cast<WebContentSecurityPolicyType>(type),
        static_cast<WebContentSecurityPolicySource>(source));
  }
}

void FrameLoaderClientImpl::didChangeFrameOwnerProperties(
    HTMLFrameElementBase* frameElement) {
  if (!m_webFrame->client())
    return;

  m_webFrame->client()->didChangeFrameOwnerProperties(
      WebFrame::fromFrame(frameElement->contentFrame()),
      WebFrameOwnerProperties(
          frameElement->scrollingMode(), frameElement->marginWidth(),
          frameElement->marginHeight(), frameElement->allowFullscreen(),
          frameElement->csp(), frameElement->delegatedPermissions()));
}

void FrameLoaderClientImpl::dispatchWillStartUsingPeerConnectionHandler(
    WebRTCPeerConnectionHandler* handler) {
  m_webFrame->client()->willStartUsingPeerConnectionHandler(handler);
}

bool FrameLoaderClientImpl::allowWebGL(bool enabledPerSettings) {
  if (m_webFrame->client())
    return m_webFrame->client()->allowWebGL(enabledPerSettings);

  return enabledPerSettings;
}

void FrameLoaderClientImpl::dispatchWillInsertBody() {
  if (m_webFrame->client())
    m_webFrame->client()->willInsertBody(m_webFrame);
}

std::unique_ptr<WebServiceWorkerProvider>
FrameLoaderClientImpl::createServiceWorkerProvider() {
  if (!m_webFrame->client())
    return nullptr;
  return wrapUnique(m_webFrame->client()->createServiceWorkerProvider());
}

bool FrameLoaderClientImpl::isControlledByServiceWorker(
    DocumentLoader& loader) {
  return m_webFrame->client() &&
         m_webFrame->client()->isControlledByServiceWorker(
             *WebDataSourceImpl::fromDocumentLoader(&loader));
}

int64_t FrameLoaderClientImpl::serviceWorkerID(DocumentLoader& loader) {
  if (!m_webFrame->client())
    return -1;
  return m_webFrame->client()->serviceWorkerID(
      *WebDataSourceImpl::fromDocumentLoader(&loader));
}

SharedWorkerRepositoryClient*
FrameLoaderClientImpl::sharedWorkerRepositoryClient() {
  return m_webFrame->sharedWorkerRepositoryClient();
}

std::unique_ptr<WebApplicationCacheHost>
FrameLoaderClientImpl::createApplicationCacheHost(
    WebApplicationCacheHostClient* client) {
  if (!m_webFrame->client())
    return nullptr;
  return wrapUnique(m_webFrame->client()->createApplicationCacheHost(client));
}

void FrameLoaderClientImpl::dispatchDidChangeManifest() {
  if (m_webFrame->client())
    m_webFrame->client()->didChangeManifest();
}

unsigned FrameLoaderClientImpl::backForwardLength() {
  WebViewImpl* webview = m_webFrame->viewImpl();
  if (!webview || !webview->client())
    return 0;
  return webview->client()->historyBackListCount() + 1 +
         webview->client()->historyForwardListCount();
}

void FrameLoaderClientImpl::suddenTerminationDisablerChanged(
    bool present,
    SuddenTerminationDisablerType type) {
  if (m_webFrame->client()) {
    m_webFrame->client()->suddenTerminationDisablerChanged(
        present,
        static_cast<WebFrameClient::SuddenTerminationDisablerType>(type));
  }
}

BlameContext* FrameLoaderClientImpl::frameBlameContext() {
  if (!m_webFrame->client())
    return nullptr;
  return m_webFrame->client()->frameBlameContext();
}

LinkResource* FrameLoaderClientImpl::createServiceWorkerLinkResource(
    HTMLLinkElement* owner) {
  return ServiceWorkerLinkResource::create(owner);
}

WebEffectiveConnectionType FrameLoaderClientImpl::getEffectiveConnectionType() {
  if (m_webFrame->client())
    return m_webFrame->client()->getEffectiveConnectionType();
  return WebEffectiveConnectionType::TypeUnknown;
}

WebDevToolsAgentImpl* FrameLoaderClientImpl::devToolsAgent() {
  return WebLocalFrameImpl::fromFrame(m_webFrame->frame()->localFrameRoot())
      ->devToolsAgentImpl();
}

KURL FrameLoaderClientImpl::overrideFlashEmbedWithHTML(const KURL& url) {
  return m_webFrame->client()->overrideFlashEmbedWithHTML(WebURL(url));
}

}  // namespace blink
