1
    2
    3
    4
    5
    6
    7
    8
    9
   10
   11
   12
   13
   14
   15
   16
   17
   18
   19
   20
   21
   22
   23
   24
   25
   26
   27
   28
   29
   30
   31
   32
   33
   34
   35
   36
   37
   38
   39
   40
   41
   42
   43
   44
   45
   46
   47
   48
   49
   50
   51
   52
   53
   54
   55
   56
   57
   58
   59
   60
   61
   62
   63
   64
   65
   66
   67
   68
   69
   70
   71
   72
   73
   74
   75
   76
   77
   78
   79
   80
   81
   82
   83
   84
   85
   86
   87
   88
   89
   90
   91
   92
   93
   94
   95
   96
   97
   98
   99
  100
  101
  102
  103
  104
  105
  106
  107
  108
  109
  110
  111
  112
  113
  114
  115
  116
  117
  118
  119
  120
  121
  122
  123
  124
  125
  126
  127
  128
  129
  130
  131
  132
  133
  134
  135
  136
  137
  138
  139
  140
  141
  142
  143
  144
  145
  146
  147
  148
  149

content / browser / browser_plugin / browser_plugin_guest.cc [blame]

// Copyright 2012 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/browser_plugin/browser_plugin_guest.h"

#include <stddef.h>

#include <utility>

#include "base/memory/ptr_util.h"
#include "base/metrics/user_metrics.h"
#include "build/build_config.h"
#include "content/browser/renderer_host/navigation_request.h"
#include "content/browser/renderer_host/render_widget_host_impl.h"
#include "content/browser/renderer_host/render_widget_host_view_base.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/public/browser/navigation_handle.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/render_widget_host_view.h"
#include "content/public/browser/web_contents_observer.h"
#include "third_party/blink/public/common/renderer_preferences/renderer_preferences.h"

namespace content {

BrowserPluginGuest::BrowserPluginGuest(WebContentsImpl* web_contents,
                                       BrowserPluginGuestDelegate* delegate)
    : WebContentsObserver(web_contents),
      delegate_(delegate->GetGuestDelegateWeakPtr()) {
  CHECK(web_contents);
  CHECK(delegate_);
  RecordAction(base::UserMetricsAction("BrowserPlugin.Guest.Create"));
}

void BrowserPluginGuest::Init() {
  WebContentsImpl* owner_web_contents = static_cast<WebContentsImpl*>(
      delegate_->GetOwnerWebContents());
  owner_web_contents->CreateBrowserPluginEmbedderIfNecessary();
  InitInternal(owner_web_contents);
}

std::unique_ptr<WebContentsImpl> BrowserPluginGuest::CreateNewGuestWindow(
    const WebContents::CreateParams& params) {
  std::unique_ptr<WebContents> new_contents =
      delegate_->CreateNewGuestWindow(params);
  DCHECK(new_contents);
  return base::WrapUnique(
      static_cast<WebContentsImpl*>(new_contents.release()));
}

void BrowserPluginGuest::InitInternal(WebContentsImpl* owner_web_contents) {
  RenderWidgetHostImpl* rwhi =
      GetWebContents()->GetPrimaryMainFrame()->GetRenderWidgetHost();
  DCHECK(rwhi);
  // The initial state will not be focused but the plugin may be active so
  // set that appropriately.
  rwhi->GetWidgetInputHandler()->SetFocus(
      rwhi->is_active() ? blink::mojom::FocusState::kNotFocusedAndActive
                        : blink::mojom::FocusState::kNotFocusedAndNotActive);

  blink::RendererPreferences* renderer_prefs =
      GetWebContents()->GetMutableRendererPrefs();
  blink::UserAgentOverride guest_user_agent_override =
      renderer_prefs->user_agent_override;
  // Copy renderer preferences (and nothing else) from the embedder's
  // WebContents to the guest.
  //
  // For GTK and Aura this is necessary to get proper renderer configuration
  // values for caret blinking interval, colors related to selection and
  // focus.
  *renderer_prefs = *owner_web_contents->GetMutableRendererPrefs();
  renderer_prefs->user_agent_override = std::move(guest_user_agent_override);

  // Navigation is disabled in Chrome Apps. We want to make sure guest-initiated
  // navigations still continue to function inside the app.
  renderer_prefs->browser_handles_all_top_level_requests = false;

  // Also disable drag/drop navigations.
  renderer_prefs->can_accept_load_drops = false;
}

BrowserPluginGuest::~BrowserPluginGuest() = default;

// static
void BrowserPluginGuest::CreateInWebContents(
    WebContentsImpl* web_contents,
    BrowserPluginGuestDelegate* delegate) {
  auto guest = base::WrapUnique(new BrowserPluginGuest(web_contents, delegate));
  web_contents->SetBrowserPluginGuest(std::move(guest));
}

WebContentsImpl* BrowserPluginGuest::GetWebContents() const {
  return static_cast<WebContentsImpl*>(web_contents());
}

RenderFrameHostImpl* BrowserPluginGuest::GetProspectiveOuterDocument() {
  if (!delegate_) {
    // The guest delegate may only be null during some destruction scenarios.
    CHECK(!web_contents() || web_contents()->IsBeingDestroyed());
    return nullptr;
  }
  return static_cast<RenderFrameHostImpl*>(
      delegate_->GetProspectiveOuterDocument());
}

void BrowserPluginGuest::DidStartNavigation(
    NavigationHandle* navigation_handle) {
  // Originally added to suppress the error page when a navigation is blocked
  // using the webrequest API in a <webview> guest: https://crbug.com/284741.
  //
  // TODO(crbug.com/40148437): net::ERR_BLOCKED_BY_CLIENT is used for
  // many other errors. Figure out what suppression policy is desirable here.
  //
  // TODO(mcnee): Investigate moving this out to WebViewGuest.
  NavigationRequest::From(navigation_handle)
      ->SetSilentlyIgnoreBlockedByClient();
}

void BrowserPluginGuest::DidFinishNavigation(
    NavigationHandle* navigation_handle) {
  if (navigation_handle->HasCommitted())
    RecordAction(base::UserMetricsAction("BrowserPlugin.Guest.DidNavigate"));
}

void BrowserPluginGuest::PrimaryMainFrameRenderProcessGone(
    base::TerminationStatus status) {
  switch (status) {
#if BUILDFLAG(IS_CHROMEOS)
    case base::TERMINATION_STATUS_PROCESS_WAS_KILLED_BY_OOM:
#endif
    case base::TERMINATION_STATUS_PROCESS_WAS_KILLED:
      RecordAction(base::UserMetricsAction("BrowserPlugin.Guest.Killed"));
      break;
    case base::TERMINATION_STATUS_PROCESS_CRASHED:
      RecordAction(base::UserMetricsAction("BrowserPlugin.Guest.Crashed"));
      break;
    case base::TERMINATION_STATUS_ABNORMAL_TERMINATION:
      RecordAction(
          base::UserMetricsAction("BrowserPlugin.Guest.AbnormalDeath"));
      break;
    case base::TERMINATION_STATUS_LAUNCH_FAILED:
      RecordAction(base::UserMetricsAction("BrowserPlugin.Guest.LaunchFailed"));
      break;
    default:
      break;
  }
}

}  // namespace content