Skip to content

Commit

Permalink
Enable shadow DOM-based "missing plugin" placeholder.
Browse files Browse the repository at this point in the history
This is guarded by a command-line switch.

TEST=OverrideCreatePluginTest
BUG=364716

Review URL: https://codereview.chromium.org/649873006

Cr-Commit-Position: refs/heads/master@{#301996}
  • Loading branch information
jeremyroman authored and Commit bot committed Oct 30, 2014
1 parent 526d813 commit 73e9f79
Show file tree
Hide file tree
Showing 12 changed files with 297 additions and 14 deletions.
1 change: 1 addition & 0 deletions chrome/browser/chrome_content_browser_client.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1365,6 +1365,7 @@ void ChromeContentBrowserClient::AppendExtraCommandLineSwitches(
switches::kEnableNaClNonSfiMode,
#endif
switches::kEnableNetBenchmarking,
switches::kEnablePluginPlaceholderShadowDom,
switches::kEnableShowModalDialog,
switches::kEnableStreamlinedHostedApps,
switches::kEnableWebBasedSignin,
Expand Down
1 change: 1 addition & 0 deletions chrome/browser/chromeos/login/chrome_restart_request.cc
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ std::string DeriveCommandLine(const GURL& start_url,
::switches::kEnableLowResTiling,
::switches::kEnableOneCopy,
::switches::kEnablePinch,
::switches::kEnablePluginPlaceholderShadowDom,
::switches::kEnableTouchDragDrop,
::switches::kEnableTouchEditing,
::switches::kEnableViewport,
Expand Down
2 changes: 2 additions & 0 deletions chrome/chrome_renderer.gypi
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@
'renderer/plugins/chrome_plugin_placeholder.h',
'renderer/plugins/plugin_uma.cc',
'renderer/plugins/plugin_uma.h',
'renderer/plugins/shadow_dom_plugin_placeholder.cc',
'renderer/plugins/shadow_dom_plugin_placeholder.h',
'renderer/prefetch_helper.cc',
'renderer/prefetch_helper.h',
'renderer/prerender/prerender_dispatcher.cc',
Expand Down
11 changes: 11 additions & 0 deletions chrome/renderer/chrome_content_renderer_client.cc
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
#include "chrome/renderer/playback_extension.h"
#include "chrome/renderer/plugins/chrome_plugin_placeholder.h"
#include "chrome/renderer/plugins/plugin_uma.h"
#include "chrome/renderer/plugins/shadow_dom_plugin_placeholder.h"
#include "chrome/renderer/prefetch_helper.h"
#include "chrome/renderer/prerender/prerender_dispatcher.h"
#include "chrome/renderer/prerender/prerender_helper.h"
Expand Down Expand Up @@ -92,6 +93,7 @@
#include "third_party/WebKit/public/web/WebLocalFrame.h"
#include "third_party/WebKit/public/web/WebPluginContainer.h"
#include "third_party/WebKit/public/web/WebPluginParams.h"
#include "third_party/WebKit/public/web/WebPluginPlaceholder.h"
#include "third_party/WebKit/public/web/WebSecurityOrigin.h"
#include "third_party/WebKit/public/web/WebSecurityPolicy.h"
#include "ui/base/l10n/l10n_util.h"
Expand Down Expand Up @@ -547,6 +549,15 @@ const Extension* ChromeContentRendererClient::GetExtensionByOrigin(
}
#endif

scoped_ptr<blink::WebPluginPlaceholder>
ChromeContentRendererClient::CreatePluginPlaceholder(
content::RenderFrame* render_frame,
blink::WebLocalFrame* frame,
const blink::WebPluginParams& orig_params) {
return CreateShadowDOMPlaceholderForPluginInfo(
render_frame, frame, orig_params);
}

bool ChromeContentRendererClient::OverrideCreatePlugin(
content::RenderFrame* render_frame,
WebLocalFrame* frame,
Expand Down
4 changes: 4 additions & 0 deletions chrome/renderer/chrome_content_renderer_client.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,10 @@ class ChromeContentRendererClient : public content::ContentRendererClient {
blink::WebLocalFrame* frame,
const blink::WebPluginParams& params,
blink::WebPlugin** plugin) override;
scoped_ptr<blink::WebPluginPlaceholder> CreatePluginPlaceholder(
content::RenderFrame* render_frame,
blink::WebLocalFrame* frame,
const blink::WebPluginParams& params) override;
blink::WebPlugin* CreatePluginReplacement(
content::RenderFrame* render_frame,
const base::FilePath& plugin_path) override;
Expand Down
118 changes: 118 additions & 0 deletions chrome/renderer/chrome_content_renderer_client_browsertest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,33 @@

#include "chrome/renderer/chrome_content_renderer_client.h"

#include <string>
#include <vector>

#include "base/command_line.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/render_messages.h"
#include "chrome/grit/generated_resources.h"
#include "chrome/renderer/chrome_content_renderer_client.h"
#include "chrome/renderer/plugins/shadow_dom_plugin_placeholder.h"
#include "chrome/test/base/chrome_render_view_test.h"
#include "content/public/common/content_constants.h"
#include "content/public/renderer/render_frame.h"
#include "content/public/renderer/render_view.h"
#include "content/public/test/mock_render_thread.h"
#include "ipc/ipc_listener.h"
#include "ipc/ipc_sender.h"
#include "ipc/ipc_test_sink.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "third_party/WebKit/public/web/WebLocalFrame.h"
#include "third_party/WebKit/public/web/WebPluginParams.h"
#include "ui/base/l10n/l10n_util.h"
#include "url/gurl.h"

using testing::_;
using testing::SetArgPointee;

typedef ChromeRenderViewTest InstantProcessNavigationTest;

// Tests that renderer-initiated navigations from an Instant render process get
Expand Down Expand Up @@ -52,3 +69,104 @@ TEST_F(InstantProcessNavigationTest, ForkForNavigationsToSearchURLs) {
GetMainFrame(), GURL("http://example.com/"), "GET", false, false,
&unused));
}

namespace {

// Intercepts plugin info IPCs for a mock render thread within its scope,
// and allows tests to mock the response to each request.
class ScopedMockPluginInfoFilter : public IPC::Listener, public IPC::Sender {
public:
explicit ScopedMockPluginInfoFilter(
content::MockRenderThread* mock_render_thread)
: sink_(mock_render_thread->sink()), sender_(mock_render_thread) {
sink_.AddFilter(this);
}
~ScopedMockPluginInfoFilter() override { sink_.RemoveFilter(this); }

bool OnMessageReceived(const IPC::Message& message) override {
IPC_BEGIN_MESSAGE_MAP(ScopedMockPluginInfoFilter, message)
IPC_MESSAGE_HANDLER(ChromeViewHostMsg_GetPluginInfo, OnGetPluginInfo)
IPC_MESSAGE_UNHANDLED(return false)
IPC_END_MESSAGE_MAP()
return true;
}

bool Send(IPC::Message* message) override { return sender_->Send(message); }

MOCK_METHOD5(OnGetPluginInfo,
void(int render_frame_id,
const GURL& url,
const GURL& top_origin_url,
const std::string& mime_type,
ChromeViewHostMsg_GetPluginInfo_Output* output));

private:
IPC::TestSink& sink_;
IPC::Sender* sender_;
DISALLOW_COPY_AND_ASSIGN(ScopedMockPluginInfoFilter);
};

} // namespace

class CreatePluginPlaceholderTest : public ChromeRenderViewTest {
protected:
void SetUp() override {
ChromeRenderViewTest::SetUp();
base::CommandLine::ForCurrentProcess()->AppendSwitch(
switches::kEnablePluginPlaceholderShadowDom);
}

content::RenderFrame* GetMainRenderFrame() const {
return view_->GetMainRenderFrame();
}

int GetRoutingID() const { return GetMainRenderFrame()->GetRoutingID(); }
};

TEST_F(CreatePluginPlaceholderTest, MissingPlugin) {
GURL url("http://www.example.com/example.swf");
std::string mime_type("application/x-shockwave-flash");

blink::WebPluginParams params;
params.url = url;
params.mimeType = base::ASCIIToUTF16(mime_type);

ChromeViewHostMsg_GetPluginInfo_Output output;
output.status.value = ChromeViewHostMsg_GetPluginInfo_Status::kNotFound;

ScopedMockPluginInfoFilter filter(render_thread_.get());
#if defined(ENABLE_PLUGINS)
EXPECT_CALL(filter, OnGetPluginInfo(GetRoutingID(), url, _, mime_type, _))
.WillOnce(SetArgPointee<4>(output));
#endif

scoped_ptr<blink::WebPluginPlaceholder> placeholder =
content_renderer_client_->CreatePluginPlaceholder(
GetMainRenderFrame(), GetMainFrame(), params);
ASSERT_NE(nullptr, placeholder);
EXPECT_EQ(l10n_util::GetStringUTF16(IDS_PLUGIN_NOT_SUPPORTED),
placeholder->message());
}

TEST_F(CreatePluginPlaceholderTest, PluginFound) {
GURL url("http://www.example.com/example.swf");
std::string mime_type(content::kFlashPluginSwfMimeType);

blink::WebPluginParams params;
params.url = url;
params.mimeType = base::ASCIIToUTF16(mime_type);

ChromeViewHostMsg_GetPluginInfo_Output output;
output.status.value = ChromeViewHostMsg_GetPluginInfo_Status::kAllowed;

ScopedMockPluginInfoFilter filter(render_thread_.get());
#if defined(ENABLE_PLUGINS)
EXPECT_CALL(filter, OnGetPluginInfo(GetRoutingID(), url, _, mime_type, _))
.WillOnce(SetArgPointee<4>(output));
#endif

scoped_ptr<blink::WebPluginPlaceholder> placeholder =
content_renderer_client_->CreatePluginPlaceholder(
GetMainRenderFrame(), GetMainFrame(), params);
EXPECT_EQ(nullptr, placeholder);
}
73 changes: 73 additions & 0 deletions chrome/renderer/plugins/shadow_dom_plugin_placeholder.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
// Copyright 2013 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 "chrome/renderer/plugins/shadow_dom_plugin_placeholder.h"

#include "base/command_line.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/render_messages.h"
#include "chrome/grit/generated_resources.h"
#include "chrome/renderer/plugins/plugin_uma.h"
#include "content/public/renderer/render_frame.h"
#include "third_party/WebKit/public/web/WebDocument.h"
#include "third_party/WebKit/public/web/WebLocalFrame.h"
#include "third_party/WebKit/public/web/WebPluginParams.h"
#include "ui/base/l10n/l10n_util.h"

namespace {

class MissingPluginPlaceholder : public blink::WebPluginPlaceholder {
public:
// blink::WebPluginPlaceholder overrides
blink::WebString message() const override {
// TODO(jbroman): IDS_PLUGIN_SEARCHING if ENABLE_PLUGIN_INSTALLATION
return l10n_util::GetStringUTF16(IDS_PLUGIN_NOT_SUPPORTED);
}
};

} // namespace

bool ShadowDOMPluginPlaceholderEnabled() {
return base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kEnablePluginPlaceholderShadowDom);
}

scoped_ptr<blink::WebPluginPlaceholder> CreateShadowDOMPlaceholderForPluginInfo(
content::RenderFrame* render_frame,
blink::WebLocalFrame* frame,
const blink::WebPluginParams& orig_params) {
using Status = ChromeViewHostMsg_GetPluginInfo_Status;

if (!ShadowDOMPluginPlaceholderEnabled())
return nullptr;

std::string orig_mime_type = orig_params.mimeType.utf8();
// TODO(jbroman): Investigate whether browser plugin needs special handling.
ChromeViewHostMsg_GetPluginInfo_Output output;
#if defined(ENABLE_PLUGINS)
render_frame->Send(
new ChromeViewHostMsg_GetPluginInfo(render_frame->GetRoutingID(),
GURL(orig_params.url),
frame->top()->document().url(),
orig_mime_type,
&output));
#else
output.status.value = Status::kNotFound;
#endif

if (output.status.value == Status::kNotFound) {
// TODO(jbroman): Handle YouTube specially here, as in
// ChromeContentRendererClient::CreatePlugin.
PluginUMAReporter::GetInstance()->ReportPluginMissing(orig_mime_type,
orig_params.url);
return CreateShadowDOMPlaceholderForMissingPlugin();
}

return nullptr;
}

scoped_ptr<blink::WebPluginPlaceholder>
CreateShadowDOMPlaceholderForMissingPlugin() {
return make_scoped_ptr(new MissingPluginPlaceholder);
}
39 changes: 39 additions & 0 deletions chrome/renderer/plugins/shadow_dom_plugin_placeholder.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// Copyright 2014 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.

#ifndef CHROME_RENDERER_PLUGINS_SHADOW_DOM_PLUGIN_PLACEHOLDER_H_
#define CHROME_RENDERER_PLUGINS_SHADOW_DOM_PLUGIN_PLACEHOLDER_H_

#include "base/memory/scoped_ptr.h"
#include "third_party/WebKit/public/web/WebPluginPlaceholder.h"

namespace blink {
class WebLocalFrame;
struct WebPluginParams;
}

namespace content {
class RenderFrame;
}

// This is the Chrome implementation of shadow DOM plugin placeholders,
// intended to ultimately replace those based on WebViewPlugin.
// It is guarded by the --enable-plugin-placeholder-shadow-dom switch.

// Returns |true| if shadow DOM plugin placeholders are enabled.
bool ShadowDOMPluginPlaceholderEnabled();

// Possibly creates a placeholder given plugin info output.
// Returns nullptr if it is not appropriate to create a placeholder
// (for instance, because the plugin should be allowed to load).
scoped_ptr<blink::WebPluginPlaceholder> CreateShadowDOMPlaceholderForPluginInfo(
content::RenderFrame* render_frame,
blink::WebLocalFrame* frame,
const blink::WebPluginParams& orig_params);

// Creates a placeholder suitable for representing a missing plugin.
scoped_ptr<blink::WebPluginPlaceholder>
CreateShadowDOMPlaceholderForMissingPlugin();

#endif // CHROME_RENDERER_PLUGINS_SHADOW_DOM_PLUGIN_PLACEHOLDER_H_
Loading

0 comments on commit 73e9f79

Please sign in to comment.