| // Copyright (c) 2011 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 "base/auto_reset.h" |
| #include "base/command_line.h" |
| #include "base/utf_string_conversions.h" |
| #include "chrome/browser/mock_plugin_exceptions_table_model.h" |
| #include "chrome/common/chrome_switches.h" |
| #include "chrome/test/testing_pref_service.h" |
| #include "chrome/test/testing_profile.h" |
| #include "testing/gmock/include/gmock/gmock.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| #include "ui/base/models/table_model_observer.h" |
| #include "webkit/plugins/npapi/plugin_group.h" |
| #include "webkit/plugins/npapi/webplugininfo.h" |
| |
| // Can't be an internal namespace because PluginExceptionsTableModel declares |
| // as a friend. |
| namespace plugin_test_internal { |
| |
| using ::testing::_; |
| using ::testing::Invoke; |
| |
| class MockTableModelObserver : public ui::TableModelObserver { |
| public: |
| explicit MockTableModelObserver(ui::TableModel* model) |
| : model_(model) { |
| ON_CALL(*this, OnItemsRemoved(_, _)) |
| .WillByDefault( |
| Invoke(this, &MockTableModelObserver::CheckOnItemsRemoved)); |
| } |
| |
| MOCK_METHOD0(OnModelChanged, void()); |
| MOCK_METHOD2(OnItemsChanged, void(int start, int length)); |
| MOCK_METHOD2(OnItemsAdded, void(int start, int length)); |
| MOCK_METHOD2(OnItemsRemoved, void(int start, int length)); |
| |
| private: |
| void CheckOnItemsRemoved(int start, int length) { |
| if (!model_) |
| return; |
| // This method is called *after* the items have been removed, so we check if |
| // the first removed item was still inside the correct range. |
| EXPECT_LT(start, model_->RowCount() + 1); |
| } |
| |
| ui::TableModel* model_; |
| }; |
| |
| } // namespace plugin_test_internal |
| |
| using ::testing::InSequence; |
| |
| class PluginExceptionsTableModelTest : public testing::Test { |
| public: |
| PluginExceptionsTableModelTest() |
| : ui_thread_(BrowserThread::UI, &message_loop_), |
| command_line_(CommandLine::ForCurrentProcess(), |
| *CommandLine::ForCurrentProcess()) {} |
| |
| virtual void SetUp() { |
| CommandLine::ForCurrentProcess()->AppendSwitch( |
| switches::kEnableResourceContentSettings); |
| |
| profile_.reset(new TestingProfile()); |
| |
| HostContentSettingsMap* map = profile_->GetHostContentSettingsMap(); |
| |
| ContentSettingsPattern example_com("[*.]example.com"); |
| ContentSettingsPattern moose_org("[*.]moose.org"); |
| map->SetContentSetting(example_com, |
| CONTENT_SETTINGS_TYPE_PLUGINS, |
| "a-foo", |
| CONTENT_SETTING_ALLOW); |
| map->SetContentSetting(moose_org, |
| CONTENT_SETTINGS_TYPE_PLUGINS, |
| "b-bar", |
| CONTENT_SETTING_BLOCK); |
| map->SetContentSetting(example_com, |
| CONTENT_SETTINGS_TYPE_PLUGINS, |
| "b-bar", |
| CONTENT_SETTING_ALLOW); |
| |
| table_model_.reset(new MockPluginExceptionsTableModel(map, NULL)); |
| |
| std::vector<webkit::npapi::PluginGroup> plugins; |
| webkit::npapi::WebPluginInfo foo_plugin; |
| foo_plugin.path = FilePath(FILE_PATH_LITERAL("a-foo")); |
| foo_plugin.name = ASCIIToUTF16("FooPlugin"); |
| foo_plugin.enabled = |
| webkit::npapi::WebPluginInfo::USER_ENABLED_POLICY_UNMANAGED; |
| scoped_ptr<webkit::npapi::PluginGroup> foo_group( |
| webkit::npapi::PluginGroup::FromWebPluginInfo(foo_plugin)); |
| plugins.push_back(*foo_group); |
| |
| webkit::npapi::WebPluginInfo bar_plugin; |
| bar_plugin.path = FilePath(FILE_PATH_LITERAL("b-bar")); |
| bar_plugin.name = ASCIIToUTF16("BarPlugin"); |
| bar_plugin.enabled = |
| webkit::npapi::WebPluginInfo::USER_ENABLED_POLICY_UNMANAGED; |
| scoped_ptr<webkit::npapi::PluginGroup> bar_group( |
| webkit::npapi::PluginGroup::FromWebPluginInfo(bar_plugin)); |
| plugins.push_back(*bar_group); |
| |
| table_model_->set_plugins(plugins); |
| table_model_->ReloadSettings(); |
| } |
| |
| protected: |
| void CheckInvariants() const { |
| typedef std::vector<PluginExceptionsTableModel::SettingsEntry> Entries; |
| const Entries& settings = table_model_->settings_; |
| const std::vector<int>& row_counts = table_model_->row_counts_; |
| const std::vector<std::string>& resources = table_model_->resources_; |
| const ui::TableModel::Groups& groups = table_model_->groups_; |
| |
| EXPECT_EQ(groups.size(), row_counts.size()); |
| EXPECT_EQ(groups.size(), resources.size()); |
| |
| int last_plugin = 0; |
| int count = 0; |
| for (Entries::const_iterator it = settings.begin(); |
| it != settings.end(); ++it) { |
| // Plugin IDs are indices into |groups|. |
| EXPECT_GE(it->plugin_id, 0); |
| EXPECT_LT(it->plugin_id, static_cast<int>(groups.size())); |
| if (it->plugin_id == last_plugin) { |
| count++; |
| } else { |
| // Plugin IDs are ascending one by one. |
| EXPECT_EQ(last_plugin+1, it->plugin_id); |
| |
| // Consecutive runs of plugins with id |x| are |row_counts[x]| long. |
| EXPECT_EQ(count, row_counts[last_plugin]); |
| count = 1; |
| last_plugin = it->plugin_id; |
| } |
| } |
| if (!row_counts.empty()) |
| EXPECT_EQ(count, row_counts[last_plugin]); |
| } |
| |
| protected: |
| MessageLoop message_loop_; |
| BrowserThread ui_thread_; |
| |
| scoped_ptr<TestingProfile> profile_; |
| scoped_ptr<MockPluginExceptionsTableModel> table_model_; |
| |
| private: |
| AutoReset<CommandLine> command_line_; |
| }; |
| |
| TEST_F(PluginExceptionsTableModelTest, Basic) { |
| EXPECT_EQ(3, table_model_->RowCount()); |
| CheckInvariants(); |
| } |
| |
| TEST_F(PluginExceptionsTableModelTest, RemoveOneRow) { |
| plugin_test_internal::MockTableModelObserver observer(table_model_.get()); |
| table_model_->SetObserver(&observer); |
| |
| EXPECT_CALL(observer, OnItemsRemoved(1, 1)); |
| RemoveRowsTableModel::Rows rows; |
| rows.insert(1); |
| table_model_->RemoveRows(rows); |
| EXPECT_EQ(2, table_model_->RowCount()); |
| EXPECT_EQ(2, static_cast<int>(table_model_->GetGroups().size())); |
| CheckInvariants(); |
| table_model_->SetObserver(NULL); |
| } |
| |
| TEST_F(PluginExceptionsTableModelTest, RemoveLastRowInGroup) { |
| plugin_test_internal::MockTableModelObserver observer(table_model_.get()); |
| table_model_->SetObserver(&observer); |
| |
| EXPECT_CALL(observer, OnModelChanged()); |
| RemoveRowsTableModel::Rows rows; |
| rows.insert(0); |
| table_model_->RemoveRows(rows); |
| EXPECT_EQ(2, table_model_->RowCount()); |
| EXPECT_EQ(1, static_cast<int>(table_model_->GetGroups().size())); |
| CheckInvariants(); |
| |
| HostContentSettingsMap* map = profile_->GetHostContentSettingsMap(); |
| EXPECT_CALL(observer, OnModelChanged()); |
| map->SetContentSetting(ContentSettingsPattern("[*.]blurp.net"), |
| CONTENT_SETTINGS_TYPE_PLUGINS, |
| "b-bar", |
| CONTENT_SETTING_BLOCK); |
| EXPECT_EQ(3, table_model_->RowCount()); |
| |
| InSequence s; |
| EXPECT_CALL(observer, OnItemsRemoved(2, 1)); |
| EXPECT_CALL(observer, OnItemsRemoved(0, 1)); |
| rows.clear(); |
| rows.insert(0); |
| rows.insert(2); |
| table_model_->RemoveRows(rows); |
| EXPECT_EQ(1, table_model_->RowCount()); |
| EXPECT_EQ(1, static_cast<int>(table_model_->GetGroups().size())); |
| CheckInvariants(); |
| |
| table_model_->SetObserver(NULL); |
| } |
| |
| TEST_F(PluginExceptionsTableModelTest, RemoveAllRows) { |
| plugin_test_internal::MockTableModelObserver observer(table_model_.get()); |
| table_model_->SetObserver(&observer); |
| |
| EXPECT_CALL(observer, OnModelChanged()); |
| table_model_->RemoveAll(); |
| EXPECT_EQ(0, table_model_->RowCount()); |
| EXPECT_EQ(0, static_cast<int>(table_model_->GetGroups().size())); |
| CheckInvariants(); |
| table_model_->SetObserver(NULL); |
| } |