Home | History | Annotate | Download | only in common
      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 "content/common/plugin_list.h"
      6 
      7 #include "base/strings/string16.h"
      8 #include "base/strings/utf_string_conversions.h"
      9 #include "testing/gtest/include/gtest/gtest.h"
     10 #include "url/gurl.h"
     11 
     12 namespace content {
     13 
     14 namespace {
     15 
     16 base::FilePath::CharType kFooPath[] = FILE_PATH_LITERAL("/plugins/foo.plugin");
     17 base::FilePath::CharType kBarPath[] = FILE_PATH_LITERAL("/plugins/bar.plugin");
     18 const char* kFooName = "Foo Plugin";
     19 const char* kFooMimeType = "application/x-foo-mime-type";
     20 const char* kFooFileType = "foo";
     21 
     22 bool Equals(const WebPluginInfo& a, const WebPluginInfo& b) {
     23   return (a.name == b.name &&
     24           a.path == b.path &&
     25           a.version == b.version &&
     26           a.desc == b.desc);
     27 }
     28 
     29 bool Contains(const std::vector<WebPluginInfo>& list,
     30               const WebPluginInfo& plugin) {
     31   for (std::vector<WebPluginInfo>::const_iterator it = list.begin();
     32        it != list.end(); ++it) {
     33     if (Equals(*it, plugin))
     34       return true;
     35   }
     36   return false;
     37 }
     38 
     39 }  // namespace
     40 
     41 class PluginListTest : public testing::Test {
     42  public:
     43   PluginListTest()
     44       : foo_plugin_(ASCIIToUTF16(kFooName),
     45                     base::FilePath(kFooPath),
     46                     ASCIIToUTF16("1.2.3"),
     47                     ASCIIToUTF16("foo")),
     48         bar_plugin_(ASCIIToUTF16("Bar Plugin"),
     49                     base::FilePath(kBarPath),
     50                     ASCIIToUTF16("2.3.4"),
     51                     ASCIIToUTF16("bar")) {
     52   }
     53 
     54   virtual void SetUp() {
     55     plugin_list_.DisablePluginsDiscovery();
     56     plugin_list_.RegisterInternalPlugin(bar_plugin_, false);
     57     foo_plugin_.mime_types.push_back(
     58         WebPluginMimeType(kFooMimeType, kFooFileType, std::string()));
     59     plugin_list_.RegisterInternalPlugin(foo_plugin_, false);
     60   }
     61 
     62  protected:
     63   PluginList plugin_list_;
     64   WebPluginInfo foo_plugin_;
     65   WebPluginInfo bar_plugin_;
     66 };
     67 
     68 TEST_F(PluginListTest, GetPlugins) {
     69   std::vector<WebPluginInfo> plugins;
     70   plugin_list_.GetPlugins(&plugins, true);
     71   EXPECT_EQ(2u, plugins.size());
     72   EXPECT_TRUE(Contains(plugins, foo_plugin_));
     73   EXPECT_TRUE(Contains(plugins, bar_plugin_));
     74 }
     75 
     76 TEST_F(PluginListTest, BadPluginDescription) {
     77   WebPluginInfo plugin_3043(
     78       base::string16(), base::FilePath(FILE_PATH_LITERAL("/myplugin.3.0.43")),
     79       base::string16(), base::string16());
     80   // Simulate loading of the plugins.
     81   plugin_list_.RegisterInternalPlugin(plugin_3043, false);
     82   // Now we should have them in the state we specified above.
     83   plugin_list_.RefreshPlugins();
     84   std::vector<WebPluginInfo> plugins;
     85   plugin_list_.GetPlugins(&plugins, true);
     86   ASSERT_TRUE(Contains(plugins, plugin_3043));
     87 }
     88 
     89 TEST_F(PluginListTest, GetPluginInfoArray) {
     90   const char kTargetUrl[] = "http://example.com/test.foo";
     91   GURL target_url(kTargetUrl);
     92   std::vector<WebPluginInfo> plugins;
     93   std::vector<std::string> actual_mime_types;
     94 
     95   // The file type of the URL is supported by foo_plugin_. However,
     96   // GetPluginInfoArray should not match foo_plugin_ because the MIME type is
     97   // application/octet-stream.
     98   plugin_list_.GetPluginInfoArray(target_url,
     99                                   "application/octet-stream",
    100                                   false, // allow_wildcard
    101                                   NULL,  // use_stale
    102                                   false, // include_npapi
    103                                   &plugins,
    104                                   &actual_mime_types);
    105   EXPECT_EQ(0u, plugins.size());
    106   EXPECT_EQ(0u, actual_mime_types.size());
    107 
    108   // foo_plugin_ matches due to the MIME type.
    109   plugins.clear();
    110   actual_mime_types.clear();
    111   plugin_list_.GetPluginInfoArray(target_url,
    112                                   kFooMimeType,
    113                                   false, // allow_wildcard
    114                                   NULL,  // use_stale
    115                                   false, // include_npapi
    116                                   &plugins,
    117                                   &actual_mime_types);
    118   EXPECT_EQ(1u, plugins.size());
    119   EXPECT_TRUE(Contains(plugins, foo_plugin_));
    120   ASSERT_EQ(1u, actual_mime_types.size());
    121   EXPECT_EQ(kFooMimeType, actual_mime_types.front());
    122 
    123   // foo_plugin_ matches due to the file type and empty MIME type.
    124   plugins.clear();
    125   actual_mime_types.clear();
    126   plugin_list_.GetPluginInfoArray(target_url,
    127                                   "",
    128                                   false, // allow_wildcard
    129                                   NULL,  // use_stale
    130                                   false, // include_npapi
    131                                   &plugins,
    132                                   &actual_mime_types);
    133   EXPECT_EQ(1u, plugins.size());
    134   EXPECT_TRUE(Contains(plugins, foo_plugin_));
    135   ASSERT_EQ(1u, actual_mime_types.size());
    136   EXPECT_EQ(kFooMimeType, actual_mime_types.front());
    137 }
    138 
    139 #if defined(OS_POSIX) && !defined(OS_MACOSX)
    140 
    141 // Test parsing a simple description: Real Audio.
    142 TEST(MIMEDescriptionParse, Simple) {
    143   std::vector<WebPluginMimeType> types;
    144   PluginList::ParseMIMEDescription(
    145       "audio/x-pn-realaudio-plugin:rpm:RealAudio document;",
    146       &types);
    147   ASSERT_EQ(1U, types.size());
    148   const WebPluginMimeType& type = types[0];
    149   EXPECT_EQ("audio/x-pn-realaudio-plugin", type.mime_type);
    150   ASSERT_EQ(1U, type.file_extensions.size());
    151   EXPECT_EQ("rpm", type.file_extensions[0]);
    152   EXPECT_EQ(ASCIIToUTF16("RealAudio document"), type.description);
    153 }
    154 
    155 // Test parsing a multi-entry description: QuickTime as provided by Totem.
    156 TEST(MIMEDescriptionParse, Multi) {
    157   std::vector<WebPluginMimeType> types;
    158   PluginList::ParseMIMEDescription(
    159       "video/quicktime:mov:QuickTime video;video/mp4:mp4:MPEG-4 "
    160       "video;image/x-macpaint:pntg:MacPaint Bitmap image;image/x"
    161       "-quicktime:pict, pict1, pict2:QuickTime image;video/x-m4v"
    162       ":m4v:MPEG-4 video;",
    163       &types);
    164 
    165   ASSERT_EQ(5U, types.size());
    166 
    167   // Check the x-quicktime one, since it looks tricky with spaces in the
    168   // extension list.
    169   const WebPluginMimeType& type = types[3];
    170   EXPECT_EQ("image/x-quicktime", type.mime_type);
    171   ASSERT_EQ(3U, type.file_extensions.size());
    172   EXPECT_EQ("pict2", type.file_extensions[2]);
    173   EXPECT_EQ(ASCIIToUTF16("QuickTime image"), type.description);
    174 }
    175 
    176 // Test parsing a Japanese description, since we got this wrong in the past.
    177 // This comes from loading Totem with LANG=ja_JP.UTF-8.
    178 TEST(MIMEDescriptionParse, JapaneseUTF8) {
    179   std::vector<WebPluginMimeType> types;
    180   PluginList::ParseMIMEDescription(
    181       "audio/x-ogg:ogg:Ogg \xe3\x82\xaa\xe3\x83\xbc\xe3\x83\x87"
    182       "\xe3\x82\xa3\xe3\x83\xaa",
    183       &types);
    184 
    185   ASSERT_EQ(1U, types.size());
    186   // Check we got the right number of Unicode characters out of the parse.
    187   EXPECT_EQ(9U, types[0].description.size());
    188 }
    189 
    190 // Test that we handle corner cases gracefully.
    191 TEST(MIMEDescriptionParse, CornerCases) {
    192   std::vector<WebPluginMimeType> types;
    193   PluginList::ParseMIMEDescription("mime/type:", &types);
    194   EXPECT_TRUE(types.empty());
    195 
    196   types.clear();
    197   PluginList::ParseMIMEDescription("mime/type:ext1:", &types);
    198   ASSERT_EQ(1U, types.size());
    199   EXPECT_EQ("mime/type", types[0].mime_type);
    200   EXPECT_EQ(1U, types[0].file_extensions.size());
    201   EXPECT_EQ("ext1", types[0].file_extensions[0]);
    202   EXPECT_EQ(base::string16(), types[0].description);
    203 }
    204 
    205 // This Java plugin has embedded semicolons in the mime type.
    206 TEST(MIMEDescriptionParse, ComplicatedJava) {
    207   std::vector<WebPluginMimeType> types;
    208   PluginList::ParseMIMEDescription(
    209       "application/x-java-vm:class,jar:IcedTea;application/x-java"
    210       "-applet:class,jar:IcedTea;application/x-java-applet;versio"
    211       "n=1.1:class,jar:IcedTea;application/x-java-applet;version="
    212       "1.1.1:class,jar:IcedTea;application/x-java-applet;version="
    213       "1.1.2:class,jar:IcedTea;application/x-java-applet;version="
    214       "1.1.3:class,jar:IcedTea;application/x-java-applet;version="
    215       "1.2:class,jar:IcedTea;application/x-java-applet;version=1."
    216       "2.1:class,jar:IcedTea;application/x-java-applet;version=1."
    217       "2.2:class,jar:IcedTea;application/x-java-applet;version=1."
    218       "3:class,jar:IcedTea;application/x-java-applet;version=1.3."
    219       "1:class,jar:IcedTea;application/x-java-applet;version=1.4:"
    220       "class,jar:IcedTea",
    221       &types);
    222 
    223   ASSERT_EQ(12U, types.size());
    224   for (size_t i = 0; i < types.size(); ++i)
    225     EXPECT_EQ(ASCIIToUTF16("IcedTea"), types[i].description);
    226 
    227   // Verify that the mime types with semis are coming through ok.
    228   EXPECT_TRUE(types[4].mime_type.find(';') != std::string::npos);
    229 }
    230 
    231 // Make sure we understand how to get the version numbers for common Linux
    232 // plug-ins.
    233 TEST(PluginDescriptionParse, ExtractVersion) {
    234   WebPluginInfo info;
    235   PluginList::ExtractVersionString("Shockwave Flash 10.1 r102", &info);
    236   EXPECT_EQ(ASCIIToUTF16("10.1 r102"), info.version);
    237   PluginList::ExtractVersionString("Java(TM) Plug-in 1.6.0_22", &info);
    238   EXPECT_EQ(ASCIIToUTF16("1.6.0_22"), info.version);
    239   // It's actually much more likely for a modern Linux distribution to have
    240   // IcedTea.
    241   PluginList::ExtractVersionString(
    242       "IcedTea-Web Plugin "
    243       "(using IcedTea-Web 1.2 (1.2-2ubuntu0.10.04.2))",
    244       &info);
    245   EXPECT_EQ(ASCIIToUTF16("1.2"), info.version);
    246 }
    247 
    248 #endif  // defined(OS_POSIX) && !defined(OS_MACOSX)
    249 
    250 
    251 }  // namespace content
    252