Home | History | Annotate | Download | only in renderer
      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/common/content_settings.h"
      6 #include "chrome/common/render_messages.h"
      7 #include "chrome/renderer/content_settings_observer.h"
      8 #include "chrome/test/base/chrome_render_view_test.h"
      9 #include "content/public/renderer/render_view.h"
     10 #include "ipc/ipc_message_macros.h"
     11 #include "testing/gmock/include/gmock/gmock.h"
     12 #include "testing/gtest/include/gtest/gtest.h"
     13 #include "third_party/WebKit/public/web/WebView.h"
     14 
     15 using testing::_;
     16 using testing::DeleteArg;
     17 
     18 namespace {
     19 
     20 class MockContentSettingsObserver : public ContentSettingsObserver {
     21  public:
     22   explicit MockContentSettingsObserver(content::RenderFrame* render_frame);
     23 
     24   virtual bool Send(IPC::Message* message);
     25 
     26   MOCK_METHOD1(OnContentBlocked,
     27                void(ContentSettingsType));
     28 
     29   MOCK_METHOD5(OnAllowDOMStorage,
     30                void(int, const GURL&, const GURL&, bool, IPC::Message*));
     31   GURL image_url_;
     32   std::string image_origin_;
     33 };
     34 
     35 MockContentSettingsObserver::MockContentSettingsObserver(
     36     content::RenderFrame* render_frame)
     37     : ContentSettingsObserver(render_frame, NULL),
     38       image_url_("http://www.foo.com/image.jpg"),
     39       image_origin_("http://www.foo.com") {
     40 }
     41 
     42 bool MockContentSettingsObserver::Send(IPC::Message* message) {
     43   IPC_BEGIN_MESSAGE_MAP(MockContentSettingsObserver, *message)
     44     IPC_MESSAGE_HANDLER(ChromeViewHostMsg_ContentBlocked, OnContentBlocked)
     45     IPC_MESSAGE_HANDLER_DELAY_REPLY(ChromeViewHostMsg_AllowDOMStorage,
     46                                     OnAllowDOMStorage)
     47     IPC_MESSAGE_UNHANDLED(ADD_FAILURE())
     48   IPC_END_MESSAGE_MAP()
     49 
     50   // Our super class deletes the message.
     51   return RenderFrameObserver::Send(message);
     52 }
     53 
     54 }  // namespace
     55 
     56 TEST_F(ChromeRenderViewTest, DidBlockContentType) {
     57   MockContentSettingsObserver observer(view_->GetMainRenderFrame());
     58   EXPECT_CALL(observer,
     59               OnContentBlocked(CONTENT_SETTINGS_TYPE_COOKIES));
     60   observer.DidBlockContentType(CONTENT_SETTINGS_TYPE_COOKIES);
     61 
     62   // Blocking the same content type a second time shouldn't send a notification.
     63   observer.DidBlockContentType(CONTENT_SETTINGS_TYPE_COOKIES);
     64   ::testing::Mock::VerifyAndClearExpectations(&observer);
     65 }
     66 
     67 // Tests that multiple invokations of AllowDOMStorage result in a single IPC.
     68 // Fails due to http://crbug.com/104300
     69 TEST_F(ChromeRenderViewTest, DISABLED_AllowDOMStorage) {
     70   // Load some HTML, so we have a valid security origin.
     71   LoadHTML("<html></html>");
     72   MockContentSettingsObserver observer(view_->GetMainRenderFrame());
     73   ON_CALL(observer,
     74           OnAllowDOMStorage(_, _, _, _, _)).WillByDefault(DeleteArg<4>());
     75   EXPECT_CALL(observer,
     76               OnAllowDOMStorage(_, _, _, _, _));
     77   observer.allowStorage(true);
     78 
     79   // Accessing localStorage from the same origin again shouldn't result in a
     80   // new IPC.
     81   observer.allowStorage(true);
     82   ::testing::Mock::VerifyAndClearExpectations(&observer);
     83 }
     84 
     85 // Regression test for http://crbug.com/35011
     86 TEST_F(ChromeRenderViewTest, JSBlockSentAfterPageLoad) {
     87   // 1. Load page with JS.
     88   std::string html = "<html>"
     89                      "<head>"
     90                      "<script>document.createElement('div');</script>"
     91                      "</head>"
     92                      "<body>"
     93                      "</body>"
     94                      "</html>";
     95   render_thread_->sink().ClearMessages();
     96   LoadHTML(html.c_str());
     97 
     98   // 2. Block JavaScript.
     99   RendererContentSettingRules content_setting_rules;
    100   ContentSettingsForOneType& script_setting_rules =
    101       content_setting_rules.script_rules;
    102   script_setting_rules.push_back(
    103       ContentSettingPatternSource(ContentSettingsPattern::Wildcard(),
    104                                   ContentSettingsPattern::Wildcard(),
    105                                   CONTENT_SETTING_BLOCK,
    106                                   std::string(),
    107                                   false));
    108   ContentSettingsObserver* observer = ContentSettingsObserver::Get(
    109       view_->GetMainRenderFrame());
    110   observer->SetContentSettingRules(&content_setting_rules);
    111 
    112   // Make sure no pending messages are in the queue.
    113   ProcessPendingMessages();
    114   render_thread_->sink().ClearMessages();
    115 
    116   // 3. Reload page.
    117   std::string url_str = "data:text/html;charset=utf-8,";
    118   url_str.append(html);
    119   GURL url(url_str);
    120   Reload(url);
    121   ProcessPendingMessages();
    122 
    123   // 4. Verify that the notification that javascript was blocked is sent after
    124   //    the navigation notification is sent.
    125   int navigation_index = -1;
    126   int block_index = -1;
    127   for (size_t i = 0; i < render_thread_->sink().message_count(); ++i) {
    128     const IPC::Message* msg = render_thread_->sink().GetMessageAt(i);
    129     if (msg->type() == GetNavigationIPCType())
    130       navigation_index = i;
    131     if (msg->type() == ChromeViewHostMsg_ContentBlocked::ID)
    132       block_index = i;
    133   }
    134   EXPECT_NE(-1, navigation_index);
    135   EXPECT_NE(-1, block_index);
    136   EXPECT_LT(navigation_index, block_index);
    137 }
    138 
    139 TEST_F(ChromeRenderViewTest, PluginsTemporarilyAllowed) {
    140   // Load some HTML.
    141   LoadHTML("<html>Foo</html>");
    142 
    143   std::string foo_plugin = "foo";
    144   std::string bar_plugin = "bar";
    145 
    146   ContentSettingsObserver* observer =
    147       ContentSettingsObserver::Get(view_->GetMainRenderFrame());
    148   EXPECT_FALSE(observer->IsPluginTemporarilyAllowed(foo_plugin));
    149 
    150   // Temporarily allow the "foo" plugin.
    151   observer->OnLoadBlockedPlugins(foo_plugin);
    152   EXPECT_TRUE(observer->IsPluginTemporarilyAllowed(foo_plugin));
    153   EXPECT_FALSE(observer->IsPluginTemporarilyAllowed(bar_plugin));
    154 
    155   // Simulate a navigation within the page.
    156   DidNavigateWithinPage(GetMainFrame(), true);
    157   EXPECT_TRUE(observer->IsPluginTemporarilyAllowed(foo_plugin));
    158   EXPECT_FALSE(observer->IsPluginTemporarilyAllowed(bar_plugin));
    159 
    160   // Navigate to a different page.
    161   LoadHTML("<html>Bar</html>");
    162   EXPECT_FALSE(observer->IsPluginTemporarilyAllowed(foo_plugin));
    163   EXPECT_FALSE(observer->IsPluginTemporarilyAllowed(bar_plugin));
    164 
    165   // Temporarily allow all plugins.
    166   observer->OnLoadBlockedPlugins(std::string());
    167   EXPECT_TRUE(observer->IsPluginTemporarilyAllowed(foo_plugin));
    168   EXPECT_TRUE(observer->IsPluginTemporarilyAllowed(bar_plugin));
    169 }
    170 
    171 TEST_F(ChromeRenderViewTest, ImagesBlockedByDefault) {
    172   MockContentSettingsObserver mock_observer(view_->GetMainRenderFrame());
    173 
    174   // Load some HTML.
    175   LoadHTML("<html>Foo</html>");
    176 
    177   // Set the default image blocking setting.
    178   RendererContentSettingRules content_setting_rules;
    179   ContentSettingsForOneType& image_setting_rules =
    180       content_setting_rules.image_rules;
    181   image_setting_rules.push_back(
    182       ContentSettingPatternSource(ContentSettingsPattern::Wildcard(),
    183                                   ContentSettingsPattern::Wildcard(),
    184                                   CONTENT_SETTING_BLOCK,
    185                                   std::string(),
    186                                   false));
    187 
    188   ContentSettingsObserver* observer = ContentSettingsObserver::Get(
    189       view_->GetMainRenderFrame());
    190   observer->SetContentSettingRules(&content_setting_rules);
    191   EXPECT_CALL(mock_observer,
    192               OnContentBlocked(CONTENT_SETTINGS_TYPE_IMAGES));
    193   EXPECT_FALSE(observer->allowImage(true, mock_observer.image_url_));
    194   ::testing::Mock::VerifyAndClearExpectations(&observer);
    195 
    196   // Create an exception which allows the image.
    197   image_setting_rules.insert(
    198       image_setting_rules.begin(),
    199       ContentSettingPatternSource(
    200           ContentSettingsPattern::Wildcard(),
    201           ContentSettingsPattern::FromString(mock_observer.image_origin_),
    202           CONTENT_SETTING_ALLOW,
    203           std::string(),
    204           false));
    205 
    206   EXPECT_CALL(
    207       mock_observer,
    208       OnContentBlocked(CONTENT_SETTINGS_TYPE_IMAGES)).Times(0);
    209   EXPECT_TRUE(observer->allowImage(true, mock_observer.image_url_));
    210   ::testing::Mock::VerifyAndClearExpectations(&observer);
    211 }
    212 
    213 TEST_F(ChromeRenderViewTest, ImagesAllowedByDefault) {
    214   MockContentSettingsObserver mock_observer(view_->GetMainRenderFrame());
    215 
    216   // Load some HTML.
    217   LoadHTML("<html>Foo</html>");
    218 
    219   // Set the default image blocking setting.
    220   RendererContentSettingRules content_setting_rules;
    221   ContentSettingsForOneType& image_setting_rules =
    222       content_setting_rules.image_rules;
    223   image_setting_rules.push_back(
    224       ContentSettingPatternSource(ContentSettingsPattern::Wildcard(),
    225                                   ContentSettingsPattern::Wildcard(),
    226                                   CONTENT_SETTING_ALLOW,
    227                                   std::string(),
    228                                   false));
    229 
    230   ContentSettingsObserver* observer =
    231       ContentSettingsObserver::Get(view_->GetMainRenderFrame());
    232   observer->SetContentSettingRules(&content_setting_rules);
    233   EXPECT_CALL(
    234       mock_observer,
    235       OnContentBlocked(CONTENT_SETTINGS_TYPE_IMAGES)).Times(0);
    236   EXPECT_TRUE(observer->allowImage(true, mock_observer.image_url_));
    237   ::testing::Mock::VerifyAndClearExpectations(&observer);
    238 
    239   // Create an exception which blocks the image.
    240   image_setting_rules.insert(
    241       image_setting_rules.begin(),
    242       ContentSettingPatternSource(
    243           ContentSettingsPattern::Wildcard(),
    244           ContentSettingsPattern::FromString(mock_observer.image_origin_),
    245           CONTENT_SETTING_BLOCK,
    246           std::string(),
    247           false));
    248   EXPECT_CALL(mock_observer,
    249               OnContentBlocked(CONTENT_SETTINGS_TYPE_IMAGES));
    250   EXPECT_FALSE(observer->allowImage(true, mock_observer.image_url_));
    251   ::testing::Mock::VerifyAndClearExpectations(&observer);
    252 }
    253 
    254 TEST_F(ChromeRenderViewTest, ContentSettingsBlockScripts) {
    255   // Set the content settings for scripts.
    256   RendererContentSettingRules content_setting_rules;
    257   ContentSettingsForOneType& script_setting_rules =
    258       content_setting_rules.script_rules;
    259   script_setting_rules.push_back(
    260       ContentSettingPatternSource(ContentSettingsPattern::Wildcard(),
    261                                   ContentSettingsPattern::Wildcard(),
    262                                   CONTENT_SETTING_BLOCK,
    263                                   std::string(),
    264                                   false));
    265 
    266   ContentSettingsObserver* observer =
    267       ContentSettingsObserver::Get(view_->GetMainRenderFrame());
    268   observer->SetContentSettingRules(&content_setting_rules);
    269 
    270   // Load a page which contains a script.
    271   std::string html = "<html>"
    272                      "<head>"
    273                      "<script src='data:foo'></script>"
    274                      "</head>"
    275                      "<body>"
    276                      "</body>"
    277                      "</html>";
    278   LoadHTML(html.c_str());
    279 
    280   // Verify that the script was blocked.
    281   bool was_blocked = false;
    282   for (size_t i = 0; i < render_thread_->sink().message_count(); ++i) {
    283     const IPC::Message* msg = render_thread_->sink().GetMessageAt(i);
    284     if (msg->type() == ChromeViewHostMsg_ContentBlocked::ID)
    285       was_blocked = true;
    286   }
    287   EXPECT_TRUE(was_blocked);
    288 }
    289 
    290 TEST_F(ChromeRenderViewTest, ContentSettingsAllowScripts) {
    291   // Set the content settings for scripts.
    292   RendererContentSettingRules content_setting_rules;
    293   ContentSettingsForOneType& script_setting_rules =
    294       content_setting_rules.script_rules;
    295   script_setting_rules.push_back(
    296       ContentSettingPatternSource(ContentSettingsPattern::Wildcard(),
    297                                   ContentSettingsPattern::Wildcard(),
    298                                   CONTENT_SETTING_ALLOW,
    299                                   std::string(),
    300                                   false));
    301 
    302   ContentSettingsObserver* observer =
    303       ContentSettingsObserver::Get(view_->GetMainRenderFrame());
    304   observer->SetContentSettingRules(&content_setting_rules);
    305 
    306   // Load a page which contains a script.
    307   std::string html = "<html>"
    308                      "<head>"
    309                      "<script src='data:foo'></script>"
    310                      "</head>"
    311                      "<body>"
    312                      "</body>"
    313                      "</html>";
    314   LoadHTML(html.c_str());
    315 
    316   // Verify that the script was not blocked.
    317   bool was_blocked = false;
    318   for (size_t i = 0; i < render_thread_->sink().message_count(); ++i) {
    319     const IPC::Message* msg = render_thread_->sink().GetMessageAt(i);
    320     if (msg->type() == ChromeViewHostMsg_ContentBlocked::ID)
    321       was_blocked = true;
    322   }
    323   EXPECT_FALSE(was_blocked);
    324 }
    325 
    326 TEST_F(ChromeRenderViewTest, ContentSettingsInterstitialPages) {
    327   MockContentSettingsObserver mock_observer(view_->GetMainRenderFrame());
    328   // Block scripts.
    329   RendererContentSettingRules content_setting_rules;
    330   ContentSettingsForOneType& script_setting_rules =
    331       content_setting_rules.script_rules;
    332   script_setting_rules.push_back(
    333       ContentSettingPatternSource(ContentSettingsPattern::Wildcard(),
    334                                   ContentSettingsPattern::Wildcard(),
    335                                   CONTENT_SETTING_BLOCK,
    336                                   std::string(),
    337                                   false));
    338   // Block images.
    339   ContentSettingsForOneType& image_setting_rules =
    340       content_setting_rules.image_rules;
    341   image_setting_rules.push_back(
    342       ContentSettingPatternSource(ContentSettingsPattern::Wildcard(),
    343                                   ContentSettingsPattern::Wildcard(),
    344                                   CONTENT_SETTING_BLOCK,
    345                                   std::string(),
    346                                   false));
    347 
    348   ContentSettingsObserver* observer =
    349       ContentSettingsObserver::Get(view_->GetMainRenderFrame());
    350   observer->SetContentSettingRules(&content_setting_rules);
    351   observer->OnSetAsInterstitial();
    352 
    353   // Load a page which contains a script.
    354   std::string html = "<html>"
    355                      "<head>"
    356                      "<script src='data:foo'></script>"
    357                      "</head>"
    358                      "<body>"
    359                      "</body>"
    360                      "</html>";
    361   LoadHTML(html.c_str());
    362 
    363   // Verify that the script was allowed.
    364   bool was_blocked = false;
    365   for (size_t i = 0; i < render_thread_->sink().message_count(); ++i) {
    366     const IPC::Message* msg = render_thread_->sink().GetMessageAt(i);
    367     if (msg->type() == ChromeViewHostMsg_ContentBlocked::ID)
    368       was_blocked = true;
    369   }
    370   EXPECT_FALSE(was_blocked);
    371 
    372   // Verify that images are allowed.
    373   EXPECT_CALL(
    374       mock_observer,
    375       OnContentBlocked(CONTENT_SETTINGS_TYPE_IMAGES)).Times(0);
    376   EXPECT_TRUE(observer->allowImage(true, mock_observer.image_url_));
    377   ::testing::Mock::VerifyAndClearExpectations(&observer);
    378 }
    379