--- /dev/null
+// Copyright (c) 2015 The Chromium Embedded Framework 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 "include/base/cef_bind.h"
+#include "include/cef_pack_resources.h"
+#include "include/cef_resource_bundle.h"
+#include "include/wrapper/cef_closure_task.h"
+#include "include/wrapper/cef_stream_resource_handler.h"
+#include "tests/ceftests/routing_test_handler.h"
+#include "tests/gtest/include/gtest/gtest.h"
+#include "tests/shared/browser/client_app_browser.h"
+#include "tests/shared/browser/resource_util.h"
+
+namespace {
+
+std::string GetDataResourceAsString(int resource_id) {
+ void* data;
+ size_t data_size;
+ if (CefResourceBundle::GetGlobal()->GetDataResource(resource_id, data,
+ data_size)) {
+ return std::string(static_cast<char*>(data), data_size);
+ }
+ return std::string();
+}
+
+// Browser-side app delegate.
+class PluginBrowserTest : public client::ClientAppBrowser::Delegate {
+ public:
+ PluginBrowserTest() {}
+
+ void OnBeforeCommandLineProcessing(
+ CefRefPtr<client::ClientAppBrowser> app,
+ CefRefPtr<CefCommandLine> command_line) override {
+ // Allow all plugin loading by default.
+ command_line->AppendSwitchWithValue("plugin-policy", "allow");
+ }
+
+ private:
+ IMPLEMENT_REFCOUNTING(PluginBrowserTest);
+};
+
+const char kPdfTestOrigin[] = "http://tests/";
+const char kPdfHtmlUrl[] = "http://tests/pdf.html";
+const char kPdfDirectUrl[] = "http://tests/pdf.pdf";
+
+// Delay waiting for the plugin placeholder to load.
+const int64 kPlaceholderLoadDelayMs = 1000;
+
+// Delay waiting for iframe tests to load the PDF file.
+#if defined(OS_LINUX)
+const int64 kPdfLoadDelayMs = 7000;
+#else
+const int64 kPdfLoadDelayMs = 5000;
+#endif
+
+// Browser-side test handler.
+class PluginTestHandler : public RoutingTestHandler,
+ public CefContextMenuHandler {
+ public:
+ enum Mode {
+ // No specified context or handler (implicitly uses the global context).
+ GLOBAL_DEFAULT,
+
+ // Global context with no handler.
+ GLOBAL_NO_HANDLER,
+
+ // Global context with handler that allows plugin load.
+ GLOBAL_ALLOW,
+
+ // Global context with handler that blocks plugin load. Then, load the
+ // plugin via the context menu.
+ GLOBAL_BLOCK_LOAD,
+
+ // Global context with handler that blocks plugin load. Then, hide the
+ // plugin via the context menu.
+ GLOBAL_BLOCK_HIDE,
+
+ // Global context with handler that disables plugin load. Then, hide the
+ // plugin via the context menu.
+ GLOBAL_DISABLE_HIDE,
+
+ // Global context with handler that removes the plugin from the
+ // `navigator.plugins` list and consequently disables plugin load.
+ GLOBAL_NO_LIST,
+
+ // Custom context with no handler.
+ CUSTOM_NO_HANDLER,
+
+ // Custom context with handler that allows plugin load.
+ CUSTOM_ALLOW,
+
+ // Custom context with handler that blocks plugin load. Then, load the
+ // plugin via the context menu.
+ CUSTOM_BLOCK_LOAD,
+
+ // Custom context with handler that blocks plugin load. Then, hide the
+ // plugin via the context menu.
+ CUSTOM_BLOCK_HIDE,
+
+ // Custom context with handler that disables plugin load. Then, hide the
+ // plugin via the context menu.
+ CUSTOM_DISABLE_HIDE,
+
+ // Custom context with handler that removes the plugin from the
+ // `navigator.plugins` list and consequently disables plugin load.
+ CUSTOM_NO_LIST,
+ };
+
+ class RequestContextHandler : public CefRequestContextHandler {
+ public:
+ explicit RequestContextHandler(PluginTestHandler* handler)
+ : handler_(handler) {}
+
+ bool OnBeforePluginLoad(const CefString& mime_type,
+ const CefString& plugin_url,
+ bool is_main_frame,
+ const CefString& top_origin_url,
+ CefRefPtr<CefWebPluginInfo> plugin_info,
+ PluginPolicy* plugin_policy) override {
+ const std::string& mime_type_str = mime_type;
+ EXPECT_STREQ("application/pdf", mime_type_str.c_str());
+ EXPECT_STREQ("chrome-extension://mhjfbmdgcfjbbpaeojofohoefgiehjai/",
+ plugin_info->GetPath().ToString().c_str());
+
+ if (top_origin_url.empty()) {
+ if (!handler_->got_on_before_plugin_empty_origin_) {
+ // Checking for PDF support in the plugin frame (navigator.plugins
+ // listing, pdf load, etc).
+ EXPECT_EQ(handler_->HasDirectPluginLoad(), is_main_frame);
+ handler_->got_on_before_plugin_empty_origin_.yes();
+ } else if (handler_->HasNoList()) {
+ // When listing is disabled there should be an additional check in the
+ // main frame for the navigator.plugins listing.
+ if (!handler_->got_on_before_plugin_empty_origin2_) {
+ EXPECT_EQ(true, is_main_frame);
+ handler_->got_on_before_plugin_empty_origin2_.yes();
+ } else {
+ NOTREACHED();
+ }
+ } else {
+ // When listing is enabled there should only be the one check in the
+ // plugin frame.
+ NOTREACHED();
+ }
+
+ if (handler_->HasNoList()) {
+ // Remove the PDF plugin from the `navigator.plugins` list.
+ *plugin_policy = PLUGIN_POLICY_DISABLE;
+ return true;
+ }
+
+ // Ignore requests for building the plugin list.
+ return false;
+ }
+
+ // Should only get requests for the test origin.
+ EXPECT_STREQ(kPdfTestOrigin, top_origin_url.ToString().c_str());
+
+ if (!handler_->got_on_before_plugin_load_pdf_)
+ handler_->got_on_before_plugin_load_pdf_.yes();
+ else
+ NOTREACHED();
+
+ if (handler_->HasAllow()) {
+ *plugin_policy = PLUGIN_POLICY_ALLOW;
+ return true;
+ } else if (handler_->HasBlock()) {
+ *plugin_policy = PLUGIN_POLICY_BLOCK;
+ return true;
+ } else if (handler_->HasDisable()) {
+ *plugin_policy = PLUGIN_POLICY_DISABLE;
+ return true;
+ }
+
+ return false;
+ }
+
+ void Detach() {
+ handler_ = NULL;
+ }
+
+ private:
+ PluginTestHandler* handler_;
+
+ IMPLEMENT_REFCOUNTING(RequestContextHandler);
+ };
+
+ PluginTestHandler(Mode mode,
+ const std::string& url)
+ : mode_(mode),
+ url_(url) {
+ }
+
+ // Loading the PDF directly in the main frame instead of a sub-frame.
+ bool HasDirectPluginLoad() const {
+ return url_ == kPdfDirectUrl;
+ }
+
+ // Has a specified RequestContext but not necessarily a custom handler.
+ bool HasRequestContext() const {
+ return mode_ != GLOBAL_DEFAULT;
+ }
+
+ // Has a specified RequestContext and custom handler.
+ bool HasRequestContextHandler() const {
+ return mode_ != GLOBAL_DEFAULT &&
+ mode_ != GLOBAL_NO_HANDLER &&
+ mode_ != CUSTOM_NO_HANDLER;
+ }
+
+ // Using the global request context, either directly or with a custom handler.
+ bool HasGlobalRequestContext() const {
+ return mode_ >= GLOBAL_DEFAULT && mode_ <= GLOBAL_NO_LIST;
+ }
+
+ // Should allow the plugin load via the custom handler.
+ bool HasAllow() const {
+ return mode_ == GLOBAL_ALLOW || mode_ == CUSTOM_ALLOW;
+ }
+
+ // Should block the plugin load via the custom handler.
+ bool HasBlock() const {
+ return mode_ == GLOBAL_BLOCK_LOAD ||
+ mode_ == GLOBAL_BLOCK_HIDE ||
+ mode_ == CUSTOM_BLOCK_LOAD ||
+ mode_ == CUSTOM_BLOCK_HIDE;
+ }
+
+ // Should disable the plugin load via the custom handler.
+ bool HasDisable() const {
+ return mode_ == GLOBAL_DISABLE_HIDE ||
+ mode_ == CUSTOM_DISABLE_HIDE;
+ }
+
+ // Should exclude the plugin from the `navigator.plugins` list.
+ bool HasNoList() const {
+ return mode_ == GLOBAL_NO_LIST ||
+ mode_ == CUSTOM_NO_LIST;
+ }
+
+ // Should load the plugin via the context menu.
+ bool HasContextLoad() const {
+ return mode_ == GLOBAL_BLOCK_LOAD || mode_ == CUSTOM_BLOCK_LOAD;
+ }
+
+ // Should hide the plugin via the context menu.
+ bool HasContextHide() const {
+ return mode_ == GLOBAL_BLOCK_HIDE ||
+ mode_ == GLOBAL_DISABLE_HIDE ||
+ mode_ == CUSTOM_BLOCK_HIDE ||
+ mode_ == CUSTOM_DISABLE_HIDE;
+ }
+
+ std::string GetPluginNode() const {
+ return "document.getElementsByTagName('embed')[0]";
+ }
+
+ void WaitForNavigatorPlugins(CefRefPtr<CefFrame> frame) const {
+ // Test if the `navigator.plugins` list includes the PDF extension.
+ const std::string& code =
+ " if (navigator.plugins['Chrome PDF Viewer'].filename == "
+ " 'mhjfbmdgcfjbbpaeojofohoefgiehjai') {"
+ " window.testQuery({request:'pdf_plugin_found'});"
+ "} else {"
+ " window.testQuery({request:'pdf_plugin_missing'});"
+ "}";
+ frame->ExecuteJavaScript(code, frame->GetURL(), 0);
+ }
+
+ void WaitForPlaceholderLoad(CefRefPtr<CefFrame> frame) {
+ // Waits for the placeholder to load.
+ CefPostDelayedTask(TID_UI,
+ base::Bind(&PluginTestHandler::TriggerContextMenu, this,
+ frame->GetBrowser()),
+ kPlaceholderLoadDelayMs);
+ }
+
+ void WaitForPlaceholderHide(CefRefPtr<CefFrame> frame) const {
+ // Waits for the placeholder to be hidden (style set to display:none).
+ // See PluginPlaceholderBase::HidePlugin.
+ const std::string& code =
+ "var plugin = " + GetPluginNode() +";"
+ "var observer = new MutationObserver(function(mutations) {"
+ " mutations.forEach(function(mutationRecord) {"
+ " window.testQuery({request:'placeholder_hidden'});"
+ " observer.disconnect();"
+ " });"
+ "});"
+ "observer.observe(plugin, "
+ " { attributes : true, attributeFilter : ['style'] });";
+ frame->ExecuteJavaScript(code, frame->GetURL(), 0);
+ }
+
+ void WaitForPluginLoad(CefRefPtr<CefFrame> frame) {
+ if (url_ == kPdfHtmlUrl) {
+ // PDFScriptingAPI does not work with iframes (the LoadCallback will
+ // never be executed). Use a timeout instead.
+ if (got_context_menu_dismissed_) {
+ // After context menu display. Destroy the test.
+ CefPostDelayedTask(TID_UI,
+ base::Bind(&PluginTestHandler::DestroyTest, this),
+ kPdfLoadDelayMs);
+ } else {
+ // Trigger the context menu.
+ CefPostDelayedTask(TID_UI,
+ base::Bind(&PluginTestHandler::TriggerContextMenu, this,
+ frame->GetBrowser()),
+ kPdfLoadDelayMs);
+ }
+ return;
+ }
+
+ // Wait for the PDF file to load.
+ // See chrome/browser/pdf/pdf_extension_test_util.cc.
+ const std::string& scripting_api_js =
+ GetDataResourceAsString(IDR_PDF_PDF_SCRIPTING_API_JS);
+ EXPECT_TRUE(!scripting_api_js.empty());
+ frame->ExecuteJavaScript(scripting_api_js, frame->GetURL(), 0);
+
+ const std::string& code =
+ "var scriptingAPI = new PDFScriptingAPI(window, "+ GetPluginNode() +");"
+ "scriptingAPI.setLoadCallback(function(success) {"
+ " window.testQuery({request:'plugin_ready'});"
+ "});";
+ frame->ExecuteJavaScript(code, frame->GetURL(), 0);
+ }
+
+ void EndTest() {
+ CefPostTask(TID_UI, base::Bind(&PluginTestHandler::DestroyTest, this));
+ }
+
+ CefRefPtr<CefContextMenuHandler> GetContextMenuHandler() override {
+ return this;
+ }
+
+ void RunTest() override {
+ CefRefPtr<CefRequestContext> request_context;
+
+ if (HasRequestContext()) {
+ if (HasRequestContextHandler())
+ context_handler_ = new RequestContextHandler(this);
+
+ if (HasGlobalRequestContext()) {
+ // Use the global request context.
+ request_context = CefRequestContext::CreateContext(
+ CefRequestContext::GetGlobalContext(), context_handler_.get());
+ } else {
+ // Create the request context that will use an in-memory cache.
+ CefRequestContextSettings settings;
+ request_context = CefRequestContext::CreateContext(
+ settings, context_handler_.get());
+ }
+ }
+
+ // Create the browser.
+ CreateBrowser(url_, request_context);
+
+ // Time out the test after a reasonable period of time.
+ SetTestTimeout(5000 + kPdfLoadDelayMs);
+ }
+
+ CefRefPtr<CefResourceHandler> GetResourceHandler(
+ CefRefPtr<CefBrowser> browser,
+ CefRefPtr<CefFrame> frame,
+ CefRefPtr<CefRequest> request) override {
+ const std::string& url = request->GetURL();
+ if (url == kPdfHtmlUrl) {
+ CefRefPtr<CefStreamReader> stream =
+ client::GetBinaryResourceReader("pdf.html");
+ return new CefStreamResourceHandler("text/html", stream);
+ } else if (url == kPdfDirectUrl) {
+ CefRefPtr<CefStreamReader> stream =
+ client::GetBinaryResourceReader("pdf.pdf");
+ return new CefStreamResourceHandler("application/pdf", stream);
+ }
+
+ NOTREACHED();
+ return NULL;
+ }
+
+ void OnLoadEnd(CefRefPtr<CefBrowser> browser,
+ CefRefPtr<CefFrame> frame,
+ int httpStatusCode) override {
+ bool is_pdf1 = false;
+ const std::string& url = frame->GetURL();
+ if (url == kPdfHtmlUrl) {
+ if (!got_on_load_end_html_)
+ got_on_load_end_html_.yes();
+ else
+ NOTREACHED();
+ } else if (url == kPdfDirectUrl) {
+ if (!got_on_load_end_pdf1_) {
+ got_on_load_end_pdf1_.yes();
+ is_pdf1 = true;
+ } else if (!got_on_load_end_pdf2_) {
+ got_on_load_end_pdf2_.yes();
+ } else {
+ NOTREACHED();
+ }
+ } else {
+ NOTREACHED();
+ }
+
+ if (HasNoList()) {
+ // If the plugin is not listed then the PDF documents will never load.
+ EXPECT_STREQ(kPdfHtmlUrl, url.c_str());
+ WaitForNavigatorPlugins(frame);
+ } else if (is_pdf1) {
+ // The first PDF document has loaded.
+ WaitForNavigatorPlugins(frame);
+ }
+ }
+
+ bool OnQuery(CefRefPtr<CefBrowser> browser,
+ CefRefPtr<CefFrame> frame,
+ int64 query_id,
+ const CefString& request,
+ bool persistent,
+ CefRefPtr<Callback> callback) override {
+ if (request == "pdf_plugin_found" || request == "pdf_plugin_missing") {
+ if (request == "pdf_plugin_found")
+ got_pdf_plugin_found_.yes();
+ else
+ got_pdf_plugin_missing_.yes();
+
+ if (HasNoList()) {
+ // The plugin will not load. End the test.
+ EndTest();
+ } else if (HasBlock() || HasDisable()) {
+ // Wait for the plugin placeholder for the first PDF file to load. The
+ // test will continue from OnQuery.
+ WaitForPlaceholderLoad(frame);
+ } else {
+ // Wait for the first PDF file to load.
+ WaitForPluginLoad(frame);
+ }
+ } else if (request == "placeholder_hidden") {
+ EXPECT_FALSE(got_placeholder_hidden_);
+ got_placeholder_hidden_.yes();
+
+ // The plugin placeholder has been hidden. End the test.
+ EndTest();
+ } else if (request == "plugin_ready") {
+ EXPECT_FALSE(got_plugin_ready_);
+ got_plugin_ready_.yes();
+
+ // The plugin has loaded the PDF file.
+ if (got_context_menu_dismissed_) {
+ // After context menu display. End the test.
+ EndTest();
+ } else {
+ // Trigger the context menu.
+ CefPostTask(TID_UI,
+ base::Bind(&PluginTestHandler::TriggerContextMenu, this, browser));
+ }
+ } else {
+ NOTREACHED();
+ }
+
+ return true;
+ }
+
+ void TriggerContextMenu(CefRefPtr<CefBrowser> browser) {
+ CefMouseEvent mouse_event;
+
+ // Somewhere in the first plugin.
+ mouse_event.x = 100;
+ mouse_event.y = 100;
+
+ // Send right-click mouse down and mouse up to tigger context menu.
+ browser->GetHost()->SendMouseClickEvent(mouse_event, MBT_RIGHT, false, 0);
+ browser->GetHost()->SendMouseClickEvent(mouse_event, MBT_RIGHT, true, 0);
+ }
+
+ bool RunContextMenu(CefRefPtr<CefBrowser> browser,
+ CefRefPtr<CefFrame> frame,
+ CefRefPtr<CefContextMenuParams> params,
+ CefRefPtr<CefMenuModel> model,
+ CefRefPtr<CefRunContextMenuCallback> callback) override {
+ EXPECT_FALSE(got_run_context_menu_);
+ got_run_context_menu_.yes();
+
+ if (HasContextLoad() || HasContextHide()) {
+ // Should have 4 elements -- plugin name, separator, run, hide.
+ EXPECT_EQ(4, model->GetCount());
+
+ int command_id;
+ if (HasContextLoad()) {
+ // Execute the run command.
+ command_id = model->GetCommandIdAt(2);
+ } else {
+ // Wait for the plugin to be hidden.
+ WaitForPlaceholderHide(frame);
+
+ // Execute the hide command.
+ command_id = model->GetCommandIdAt(3);
+ }
+
+ EXPECT_GE(command_id, MENU_ID_CUSTOM_FIRST);
+ EXPECT_LE(command_id, MENU_ID_CUSTOM_LAST);
+
+ callback->Continue(command_id, static_cast<EventFlags>(0));
+ } else {
+ // Do nothing with the context menu.
+ callback->Cancel();
+ }
+ return true;
+ }
+
+ void OnContextMenuDismissed(CefRefPtr<CefBrowser> browser,
+ CefRefPtr<CefFrame> frame) override {
+ EXPECT_FALSE(got_context_menu_dismissed_);
+ got_context_menu_dismissed_.yes();
+
+ if (HasContextHide()) {
+ // Nothing to do here. The test will continue from OnQuery.
+ return;
+ }
+
+ if (HasContextLoad()) {
+ // Wait for the PDF plugin to load.
+ WaitForPluginLoad(frame);
+ return;
+ }
+
+ EndTest();
+ }
+
+ void DestroyTest() override {
+ if (context_handler_.get()) {
+ context_handler_->Detach();
+ context_handler_ = NULL;
+ }
+
+ if (HasContextHide()) {
+ EXPECT_TRUE(got_placeholder_hidden_);
+ EXPECT_FALSE(got_plugin_ready_);
+ } else {
+ EXPECT_FALSE(got_placeholder_hidden_);
+
+ if (url_ == kPdfDirectUrl)
+ EXPECT_TRUE(got_plugin_ready_);
+ else
+ EXPECT_FALSE(got_plugin_ready_);
+ }
+
+ if (HasRequestContextHandler())
+ EXPECT_TRUE(got_on_before_plugin_empty_origin_);
+ else
+ EXPECT_FALSE(got_on_before_plugin_empty_origin_);
+
+ if (HasNoList()) {
+ EXPECT_TRUE(got_on_before_plugin_empty_origin2_);
+ EXPECT_FALSE(got_pdf_plugin_found_);
+ EXPECT_TRUE(got_pdf_plugin_missing_);
+ EXPECT_FALSE(got_run_context_menu_);
+ EXPECT_FALSE(got_context_menu_dismissed_);
+ } else {
+ EXPECT_FALSE(got_on_before_plugin_empty_origin2_);
+ EXPECT_TRUE(got_pdf_plugin_found_);
+ EXPECT_FALSE(got_pdf_plugin_missing_);
+ EXPECT_TRUE(got_run_context_menu_);
+ EXPECT_TRUE(got_context_menu_dismissed_);
+ }
+
+ if (url_ == kPdfHtmlUrl) {
+ // The HTML file will load the PDF twice in iframes.
+ EXPECT_TRUE(got_on_load_end_html_);
+
+ if (!HasNoList()) {
+ EXPECT_TRUE(got_on_load_end_pdf1_);
+ EXPECT_TRUE(got_on_load_end_pdf2_);
+
+ if (HasRequestContextHandler())
+ EXPECT_TRUE(got_on_before_plugin_load_pdf_);
+ }
+ } else if (url_ == kPdfDirectUrl) {
+ // Load the PDF file directly.
+ EXPECT_FALSE(got_on_load_end_html_);
+ EXPECT_TRUE(got_on_load_end_pdf1_);
+ EXPECT_FALSE(got_on_load_end_pdf2_);
+
+ if (HasRequestContextHandler())
+ EXPECT_TRUE(got_on_before_plugin_load_pdf_);
+ } else {
+ NOTREACHED();
+ }
+
+ if (!HasRequestContextHandler() || HasNoList()) {
+ EXPECT_FALSE(got_on_before_plugin_load_pdf_);
+ }
+
+ TestHandler::DestroyTest();
+ }
+
+ const Mode mode_;
+ const std::string url_;
+
+ TrackCallback got_on_before_plugin_empty_origin_;
+ TrackCallback got_on_before_plugin_empty_origin2_;
+ TrackCallback got_on_before_plugin_load_pdf_;
+ TrackCallback got_on_load_end_html_;
+ TrackCallback got_on_load_end_pdf1_;
+ TrackCallback got_on_load_end_pdf2_;
+ TrackCallback got_pdf_plugin_found_;
+ TrackCallback got_pdf_plugin_missing_;
+ TrackCallback got_placeholder_hidden_;
+ TrackCallback got_plugin_ready_;
+ TrackCallback got_run_context_menu_;
+ TrackCallback got_context_menu_dismissed_;
+
+ CefRefPtr<RequestContextHandler> context_handler_;
+
+ IMPLEMENT_REFCOUNTING(PluginTestHandler);
+};
+
+} // namespace
+
+#define RUN_TEST(name, type, url) \
+ TEST(PluginTest, name) { \
+ CefRefPtr<PluginTestHandler> handler = \
+ new PluginTestHandler(PluginTestHandler::type, url); \
+ handler->ExecuteTest(); \
+ ReleaseAndWaitForDestructor(handler); \
+ }
+
+RUN_TEST(GlobalDefaultPdfDirect, GLOBAL_DEFAULT, kPdfDirectUrl);
+RUN_TEST(GlobalDefaultPdfHtml, GLOBAL_DEFAULT, kPdfHtmlUrl);
+
+RUN_TEST(GlobalNoHandlerPdfDirect, GLOBAL_NO_HANDLER, kPdfDirectUrl);
+RUN_TEST(GlobalNoHandlerPdfHtml, GLOBAL_NO_HANDLER, kPdfHtmlUrl);
+RUN_TEST(GlobalAllowPdfDirect, GLOBAL_ALLOW, kPdfDirectUrl);
+RUN_TEST(GlobalAllowPdfHtml, GLOBAL_ALLOW, kPdfHtmlUrl);
+RUN_TEST(GlobalBlockThenLoadPdfDirect, GLOBAL_BLOCK_LOAD, kPdfDirectUrl);
+RUN_TEST(GlobalBlockThenLoadPdfHtml, GLOBAL_BLOCK_LOAD, kPdfHtmlUrl);
+RUN_TEST(GlobalBlockThenHidePdfDirect, GLOBAL_BLOCK_HIDE, kPdfDirectUrl);
+RUN_TEST(GlobalBlockThenHidePdfHtml, GLOBAL_BLOCK_HIDE, kPdfHtmlUrl);
+RUN_TEST(GlobalDisableThenHidePdfDirect, GLOBAL_DISABLE_HIDE, kPdfDirectUrl);
+RUN_TEST(GlobalDisableThenHidePdfHtml, GLOBAL_DISABLE_HIDE, kPdfHtmlUrl);
+RUN_TEST(GlobalNoListHtml, GLOBAL_NO_LIST, kPdfHtmlUrl);
+
+RUN_TEST(CustomNoHandlerPdfDirect, CUSTOM_NO_HANDLER, kPdfDirectUrl);
+RUN_TEST(CustomNoHandlerPdfHtml, CUSTOM_NO_HANDLER, kPdfHtmlUrl);
+RUN_TEST(CustomAllowPdfDirect, CUSTOM_ALLOW, kPdfDirectUrl);
+RUN_TEST(CustomAllowPdfHtml, CUSTOM_ALLOW, kPdfHtmlUrl);
+RUN_TEST(CustomBlockThenLoadPdfDirect, CUSTOM_BLOCK_LOAD, kPdfDirectUrl);
+RUN_TEST(CustomBlockThenLoadPdfHtml, CUSTOM_BLOCK_LOAD, kPdfHtmlUrl);
+RUN_TEST(CustomBlockThenHidePdfDirect, CUSTOM_BLOCK_HIDE, kPdfDirectUrl);
+RUN_TEST(CustomBlockThenHidePdfHtml, CUSTOM_BLOCK_HIDE, kPdfHtmlUrl);
+RUN_TEST(CustomDisableThenHidePdfDirect, CUSTOM_DISABLE_HIDE, kPdfDirectUrl);
+RUN_TEST(CustomDisableThenHidePdfHtml, CUSTOM_DISABLE_HIDE, kPdfHtmlUrl);
+RUN_TEST(CustomNoListHtml, CUSTOM_NO_LIST, kPdfHtmlUrl);
+
+
+// Entry point for creating plugin browser test objects.
+// Called from client_app_delegates.cc.
+void CreatePluginBrowserTests(
+ client::ClientAppBrowser::DelegateSet& delegates) {
+ delegates.insert(new PluginBrowserTest);
+}