1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "chrome/browser/plugins/plugin_info_message_filter.h" 6 7 #include "base/at_exit.h" 8 #include "base/bind.h" 9 #include "base/bind_helpers.h" 10 #include "base/message_loop/message_loop.h" 11 #include "base/run_loop.h" 12 #include "base/strings/utf_string_conversions.h" 13 #include "chrome/common/render_messages.h" 14 #include "content/public/browser/plugin_service.h" 15 #include "content/public/browser/plugin_service_filter.h" 16 #include "content/public/browser/render_process_host.h" 17 #include "content/public/test/test_browser_thread.h" 18 #include "testing/gmock/include/gmock/gmock.h" 19 #include "testing/gtest/include/gtest/gtest.h" 20 21 // Linux Aura doesn't support NPAPI. 22 #if !(defined(OS_LINUX) && defined(USE_AURA)) 23 24 using content::PluginService; 25 26 namespace { 27 28 class FakePluginServiceFilter : public content::PluginServiceFilter { 29 public: 30 FakePluginServiceFilter() {} 31 virtual ~FakePluginServiceFilter() {} 32 33 virtual bool IsPluginAvailable(int render_process_id, 34 int render_view_id, 35 const void* context, 36 const GURL& url, 37 const GURL& policy_url, 38 content::WebPluginInfo* plugin) OVERRIDE; 39 40 virtual bool CanLoadPlugin(int render_process_id, 41 const base::FilePath& path) OVERRIDE; 42 43 void set_plugin_enabled(const base::FilePath& plugin_path, bool enabled) { 44 plugin_state_[plugin_path] = enabled; 45 } 46 47 private: 48 std::map<base::FilePath, bool> plugin_state_; 49 }; 50 51 bool FakePluginServiceFilter::IsPluginAvailable(int render_process_id, 52 int render_view_id, 53 const void* context, 54 const GURL& url, 55 const GURL& policy_url, 56 content::WebPluginInfo* plugin) { 57 std::map<base::FilePath, bool>::iterator it = 58 plugin_state_.find(plugin->path); 59 if (it == plugin_state_.end()) { 60 ADD_FAILURE() << "No plug-in state for '" << plugin->path.value() << "'"; 61 return false; 62 } 63 return it->second; 64 } 65 66 bool FakePluginServiceFilter::CanLoadPlugin(int render_process_id, 67 const base::FilePath& path) { 68 return true; 69 } 70 71 } // namespace 72 73 class PluginInfoMessageFilterTest : public ::testing::Test { 74 public: 75 PluginInfoMessageFilterTest() : 76 foo_plugin_path_(FILE_PATH_LITERAL("/path/to/foo")), 77 bar_plugin_path_(FILE_PATH_LITERAL("/path/to/bar")), 78 file_thread_(content::BrowserThread::FILE, &message_loop_) { 79 } 80 81 virtual void SetUp() OVERRIDE { 82 content::WebPluginInfo foo_plugin(ASCIIToUTF16("Foo Plug-in"), 83 foo_plugin_path_, 84 ASCIIToUTF16("1"), 85 ASCIIToUTF16("The Foo plug-in.")); 86 content::WebPluginMimeType mime_type; 87 mime_type.mime_type = "foo/bar"; 88 foo_plugin.mime_types.push_back(mime_type); 89 PluginService::GetInstance()->Init(); 90 PluginService::GetInstance()->RegisterInternalPlugin(foo_plugin, false); 91 92 content::WebPluginInfo bar_plugin(ASCIIToUTF16("Bar Plug-in"), 93 bar_plugin_path_, 94 ASCIIToUTF16("1"), 95 ASCIIToUTF16("The Bar plug-in.")); 96 mime_type.mime_type = "foo/bar"; 97 bar_plugin.mime_types.push_back(mime_type); 98 PluginService::GetInstance()->RegisterInternalPlugin(bar_plugin, false); 99 100 PluginService::GetInstance()->SetFilter(&filter_); 101 102 #if !defined(OS_WIN) 103 // Can't go out of process in unit tests. 104 content::RenderProcessHost::SetRunRendererInProcess(true); 105 #endif 106 PluginService::GetInstance()->GetPlugins( 107 base::Bind(&PluginInfoMessageFilterTest::PluginsLoaded, 108 base::Unretained(this))); 109 base::RunLoop run_loop; 110 run_loop.Run(); 111 #if !defined(OS_WIN) 112 content::RenderProcessHost::SetRunRendererInProcess(false); 113 #endif 114 } 115 116 protected: 117 base::FilePath foo_plugin_path_; 118 base::FilePath bar_plugin_path_; 119 FakePluginServiceFilter filter_; 120 PluginInfoMessageFilter::Context context_; 121 122 private: 123 void PluginsLoaded(const std::vector<content::WebPluginInfo>& plugins) { 124 base::MessageLoop::current()->Quit(); 125 } 126 127 base::MessageLoop message_loop_; 128 // PluginService::GetPlugins on Windows jumps to the FILE thread even with 129 // a MockPluginList. 130 content::TestBrowserThread file_thread_; 131 base::ShadowingAtExitManager at_exit_manager_; // Destroys the PluginService. 132 }; 133 134 TEST_F(PluginInfoMessageFilterTest, FindEnabledPlugin) { 135 filter_.set_plugin_enabled(foo_plugin_path_, true); 136 filter_.set_plugin_enabled(bar_plugin_path_, true); 137 { 138 ChromeViewHostMsg_GetPluginInfo_Status status; 139 content::WebPluginInfo plugin; 140 std::string actual_mime_type; 141 EXPECT_TRUE(context_.FindEnabledPlugin( 142 0, GURL(), GURL(), "foo/bar", &status, &plugin, &actual_mime_type, 143 NULL)); 144 EXPECT_EQ(ChromeViewHostMsg_GetPluginInfo_Status::kAllowed, status.value); 145 EXPECT_EQ(foo_plugin_path_.value(), plugin.path.value()); 146 } 147 148 filter_.set_plugin_enabled(foo_plugin_path_, false); 149 { 150 ChromeViewHostMsg_GetPluginInfo_Status status; 151 content::WebPluginInfo plugin; 152 std::string actual_mime_type; 153 EXPECT_TRUE(context_.FindEnabledPlugin( 154 0, GURL(), GURL(), "foo/bar", &status, &plugin, &actual_mime_type, 155 NULL)); 156 EXPECT_EQ(ChromeViewHostMsg_GetPluginInfo_Status::kAllowed, status.value); 157 EXPECT_EQ(bar_plugin_path_.value(), plugin.path.value()); 158 } 159 160 filter_.set_plugin_enabled(bar_plugin_path_, false); 161 { 162 ChromeViewHostMsg_GetPluginInfo_Status status; 163 content::WebPluginInfo plugin; 164 std::string actual_mime_type; 165 std::string identifier; 166 string16 plugin_name; 167 EXPECT_FALSE(context_.FindEnabledPlugin( 168 0, GURL(), GURL(), "foo/bar", &status, &plugin, &actual_mime_type, 169 NULL)); 170 EXPECT_EQ(ChromeViewHostMsg_GetPluginInfo_Status::kDisabled, status.value); 171 EXPECT_EQ(foo_plugin_path_.value(), plugin.path.value()); 172 } 173 { 174 ChromeViewHostMsg_GetPluginInfo_Status status; 175 content::WebPluginInfo plugin; 176 std::string actual_mime_type; 177 EXPECT_FALSE(context_.FindEnabledPlugin( 178 0, GURL(), GURL(), "baz/blurp", &status, &plugin, &actual_mime_type, 179 NULL)); 180 EXPECT_EQ(ChromeViewHostMsg_GetPluginInfo_Status::kNotFound, status.value); 181 EXPECT_EQ(FILE_PATH_LITERAL(""), plugin.path.value()); 182 } 183 } 184 185 #endif 186