diff options
author | slightlyoff@chromium.org <slightlyoff@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-09-24 05:11:58 +0000 |
---|---|---|
committer | slightlyoff@chromium.org <slightlyoff@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-09-24 05:11:58 +0000 |
commit | f781782dd67077478e117c61dca4ea5eefce3544 (patch) | |
tree | 4801f724123cfdcbb69c4e7fe40a565b331723ae /chrome_frame/chrome_frame_npapi_unittest.cc | |
parent | 63cf4759efa2373e33436fb5df6849f930081226 (diff) | |
download | chromium_src-f781782dd67077478e117c61dca4ea5eefce3544.zip chromium_src-f781782dd67077478e117c61dca4ea5eefce3544.tar.gz chromium_src-f781782dd67077478e117c61dca4ea5eefce3544.tar.bz2 |
Initial import of the Chrome Frame codebase. Integration in chrome.gyp coming in a separate CL.
BUG=None
TEST=None
Review URL: http://codereview.chromium.org/218019
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@27042 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome_frame/chrome_frame_npapi_unittest.cc')
-rw-r--r-- | chrome_frame/chrome_frame_npapi_unittest.cc | 551 |
1 files changed, 551 insertions, 0 deletions
diff --git a/chrome_frame/chrome_frame_npapi_unittest.cc b/chrome_frame/chrome_frame_npapi_unittest.cc new file mode 100644 index 0000000..d2c9b4e --- /dev/null +++ b/chrome_frame/chrome_frame_npapi_unittest.cc @@ -0,0 +1,551 @@ +// Copyright (c) 2009 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 "gtest/gtest.h" +#include "gmock/gmock.h" +#include "chrome_frame/chrome_frame_automation.h" +#include "chrome_frame/chrome_frame_npapi.h" +#include "chrome_frame/ff_privilege_check.h" + + +TEST(ChromeFrameNPAPI, DoesNotCrashOnConstruction) { + ChromeFrameNPAPI* api = new ChromeFrameNPAPI(); + delete api; +} + + +// All mocks in the anonymous namespace. +namespace { + +using ::testing::_; +using ::testing::Eq; +using ::testing::Invoke; +using ::testing::Return; +using ::testing::StrEq; + +// Make mocking privilege test easy. +class MockPrivilegeTest { + public: + MockPrivilegeTest() { + CHECK(current_ == NULL); + current_ = this; + } + ~MockPrivilegeTest() { + CHECK(current_ == this); + current_ = NULL; + } + + MOCK_METHOD1(IsFireFoxPrivilegedInvocation, bool(NPP)); + + static MockPrivilegeTest* current() { return current_; } + + private: + static MockPrivilegeTest* current_; +}; + +MockPrivilegeTest* MockPrivilegeTest::current_ = NULL; + +const char* kMimeType = "application/chromeframe"; +// The default profile name is by default derived from the currently +// running executable's name. +const wchar_t* kDefaultProfileName = L"chrome_frame_unittests"; + + +class MockNPAPI: public ChromeFrameNPAPI { + public: + MockNPAPI() : mock_automation_client_(NULL) {} + + MOCK_METHOD0(CreatePrefService, NpProxyService*()); + + MOCK_METHOD0(GetLocation, std::string()); + MOCK_METHOD0(GetBrowserIncognitoMode, bool()); + + MOCK_METHOD1(JavascriptToNPObject, virtual NPObject*(const std::string&)); + + // Make public for test purposes + void OnAutomationServerReady() { + ChromeFrameNPAPI::OnAutomationServerReady(); + } + + // Neuter this (or it dchecks during testing). + void SetReadyState(READYSTATE new_state) {} + + ChromeFrameAutomationClient* CreateAutomationClient() { + return mock_automation_client_; + } + + ChromeFrameAutomationClient* mock_automation_client_; +}; + +class MockAutomationClient: public ChromeFrameAutomationClient { + public: + MOCK_METHOD6(Initialize, bool(ChromeFrameDelegate*, int, bool, + const std::wstring&, const std::wstring&, + bool)); + MOCK_METHOD1(SetEnableExtensionAutomation, void(bool)); // NOLINT +}; + +class MockProxyService: public NpProxyService { + public: + MOCK_METHOD2(Initialize, bool(NPP instance, ChromeFrameAutomationClient*)); +}; + + +// Test fixture to allow testing the privileged NPAPI APIs +class TestNPAPIPrivilegedApi: public ::testing::Test { + public: + virtual void SetUp() { + memset(&instance, 0, sizeof(instance)); + + // Gets owned & destroyed by mock_api (in the + // ChromeFramePlugin<T>::Uninitialize() function). + mock_automation = new MockAutomationClient; + + mock_api.mock_automation_client_ = mock_automation; + mock_proxy = new MockProxyService; + mock_proxy->AddRef(); + mock_proxy_holder.Attach(mock_proxy); + } + + virtual void TearDown() { + } + + void SetupPrivilegeTest(bool is_incognito, + bool expect_privilege_check, + bool is_privileged, + const std::wstring& profile_name, + const std::wstring& extra_args) { + EXPECT_CALL(mock_api, GetLocation()) + .WillOnce(Return(std::string("http://www.google.com"))); + EXPECT_CALL(mock_api, CreatePrefService()) + .WillOnce(Return(mock_proxy)); + EXPECT_CALL(mock_api, GetBrowserIncognitoMode()) + .WillOnce(Return(is_incognito)); + + EXPECT_CALL(*mock_proxy, Initialize(_, _)).WillRepeatedly(Return(false)); + + EXPECT_CALL(*mock_automation, + Initialize(_, _, true, StrEq(profile_name), StrEq(extra_args), false)) + .WillOnce(Return(true)); + + if (expect_privilege_check) { + EXPECT_CALL(mock_priv, IsFireFoxPrivilegedInvocation(_)) + .WillOnce(Return(is_privileged)); + } else { + EXPECT_CALL(mock_priv, IsFireFoxPrivilegedInvocation(_)) + .Times(0); // Fail if privilege check invoked. + } + } + + public: + MockNPAPI mock_api; + MockAutomationClient* mock_automation; + MockProxyService* mock_proxy; + ScopedNsPtr<nsISupports> mock_proxy_holder; + MockPrivilegeTest mock_priv; + NPP_t instance; +}; + +} // namespace + +// Stub for unittesting. +bool IsFireFoxPrivilegedInvocation(NPP npp) { + MockPrivilegeTest* mock = MockPrivilegeTest::current(); + if (!mock) + return false; + + return mock->IsFireFoxPrivilegedInvocation(npp); +} + +TEST_F(TestNPAPIPrivilegedApi, NoPrivilegeCheckWhenNoArguments) { + SetupPrivilegeTest(false, // Not incognito + false, // Fail if privilege check is invoked. + false, + kDefaultProfileName, + L""); // No extra args to initialize. + + // No arguments, no privilege requested. + EXPECT_TRUE(mock_api.Initialize(const_cast<NPMIMEType>(kMimeType), + &instance, + NP_EMBED, + 0, 0, 0)); +} + +TEST_F(TestNPAPIPrivilegedApi, NoPrivilegeCheckWhenZeroArgument) { + SetupPrivilegeTest(false, // Not incognito + false, // Fail if privilege check is invoked. + false, + kDefaultProfileName, + L""); // No extra args to initialize. + + // Privileged mode explicitly zero. + char* argn = "is_privileged"; + char* argv = "0"; + EXPECT_TRUE(mock_api.Initialize(const_cast<NPMIMEType>(kMimeType), + &instance, + NP_EMBED, + 1, &argn, &argv)); +} + +TEST_F(TestNPAPIPrivilegedApi, NotPrivilegedDoesNotAllowArgsOrProfile) { + SetupPrivilegeTest(false, // Not incognito. + true, // Fail unless privilege check is invoked. + false, // Not privileged. + kDefaultProfileName, + L""); // No extra arguments allowed. + + char* argn[] = { + "privileged_mode", + "chrome_extra_arguments", + "chrome_profile_name", + }; + char *argv[] = { + "1", + "foo", + "bar", + }; + EXPECT_TRUE(mock_api.Initialize(const_cast<NPMIMEType>(kMimeType), + &instance, + NP_EMBED, + arraysize(argn), argn, argv)); +} + +TEST_F(TestNPAPIPrivilegedApi, PrivilegedAllowsArgsAndProfile) { + SetupPrivilegeTest(false, // Not incognito. + true, // Fail unless privilege check is invoked. + true, // Privileged mode. + L"custom_profile_name", // Custom profile expected. + L"-bar=far"); // Extra arguments expected + + // With privileged mode we expect automation to be enabled. + EXPECT_CALL(*mock_automation, SetEnableExtensionAutomation(true)) + .Times(1); + + char* argn[] = { + "privileged_mode", + "chrome_extra_arguments", + "chrome_profile_name", + }; + char *argv[] = { + "1", + "-bar=far", + "custom_profile_name", + }; + EXPECT_TRUE(mock_api.Initialize(const_cast<NPMIMEType>(kMimeType), + &instance, + NP_EMBED, + arraysize(argn), argn, argv)); + + // Since we're mocking out ChromeFrameAutomationClient::Initialize, we need + // to tickle this explicitly. + mock_api.OnAutomationServerReady(); +} + + +namespace { + +static const NPIdentifier kOnPrivateMessageId = + reinterpret_cast<NPIdentifier>(0x100); +static const NPIdentifier kPostPrivateMessageId = + reinterpret_cast<NPIdentifier>(0x100); + + +class MockNetscapeFuncs { + public: + MockNetscapeFuncs() { + CHECK(NULL == current_); + current_ = this; + } + + ~MockNetscapeFuncs() { + CHECK(this == current_); + current_ = NULL; + } + + MOCK_METHOD3(GetValue, NPError(NPP, NPNVariable, void *)); + MOCK_METHOD3(GetStringIdentifiers, void(const NPUTF8 **, + int32_t, + NPIdentifier *)); // NOLINT + MOCK_METHOD1(RetainObject, NPObject*(NPObject*)); // NOLINT + MOCK_METHOD1(ReleaseObject, void(NPObject*)); // NOLINT + + + void GetPrivilegedStringIdentifiers(const NPUTF8 **names, + int32_t name_count, + NPIdentifier *identifiers) { + for (int32_t i = 0; i < name_count; ++i) { + if (0 == strcmp(names[i], "onprivatemessage")) { + identifiers[i] = kOnPrivateMessageId; + } else if (0 == strcmp(names[i], "postPrivateMessage")) { + identifiers[i] = kPostPrivateMessageId; + } else { + identifiers[i] = 0; + } + } + } + + static const NPNetscapeFuncs* netscape_funcs() { + return &netscape_funcs_; + } + + private: + static NPError MockGetValue(NPP instance, + NPNVariable variable, + void *ret_value) { + DCHECK(current_); + return current_->GetValue(instance, variable, ret_value); + } + + static void MockGetStringIdentifiers(const NPUTF8 **names, + int32_t name_count, + NPIdentifier *identifiers) { + DCHECK(current_); + return current_->GetStringIdentifiers(names, name_count, identifiers); + } + + static NPObject* MockRetainObject(NPObject* obj) { + DCHECK(current_); + return current_->RetainObject(obj); + } + + static void MockReleaseObject(NPObject* obj) { + DCHECK(current_); + current_->ReleaseObject(obj); + } + + static MockNetscapeFuncs* current_; + static NPNetscapeFuncs netscape_funcs_; +}; + +MockNetscapeFuncs* MockNetscapeFuncs::current_ = NULL; +NPNetscapeFuncs MockNetscapeFuncs::netscape_funcs_ = { + 0, // size + 0, // version + NULL, // geturl + NULL, // posturl + NULL, // requestread + NULL, // newstream + NULL, // write + NULL, // destroystream + NULL, // status + NULL, // uagent + NULL, // memalloc + NULL, // memfree + NULL, // memflush + NULL, // reloadplugins + NULL, // getJavaEnv + NULL, // getJavaPeer + NULL, // geturlnotify + NULL, // posturlnotify + MockGetValue, // getvalue + NULL, // setvalue + NULL, // invalidaterect + NULL, // invalidateregion + NULL, // forceredraw + NULL, // getstringidentifier + MockGetStringIdentifiers, // getstringidentifiers + NULL, // getintidentifier + NULL, // identifierisstring + NULL, // utf8fromidentifier + NULL, // intfromidentifier + NULL, // createobject + MockRetainObject, // retainobject + MockReleaseObject, // releaseobject + NULL, // invoke + NULL, // invokeDefault + NULL, // evaluate + NULL, // getproperty + NULL, // setproperty + NULL, // removeproperty + NULL, // hasproperty + NULL, // hasmethod + NULL, // releasevariantvalue + NULL, // setexception + NULL, // pushpopupsenabledstate + NULL, // poppopupsenabledstate + NULL, // enumerate + NULL, // pluginthreadasynccall + NULL, // construct +}; + +NPObject* const kMockNPObject = reinterpret_cast<NPObject*>(0xCafeBabe); + +class TestNPAPIPrivilegedProperty: public TestNPAPIPrivilegedApi { + public: + virtual void SetUp() { + TestNPAPIPrivilegedApi::SetUp(); + npapi::InitializeBrowserFunctions( + const_cast<NPNetscapeFuncs*>(mock_funcs.netscape_funcs())); + + // Expect calls to release and retain objects. + EXPECT_CALL(mock_funcs, RetainObject(kMockNPObject)) + .WillRepeatedly(Return(kMockNPObject)); + EXPECT_CALL(mock_funcs, ReleaseObject(kMockNPObject)) + .WillRepeatedly(Return()); + + // And we should expect SetEnableExtensionAutomation to be called + // for privileged tests. + EXPECT_CALL(*mock_automation, SetEnableExtensionAutomation(true)) + .WillRepeatedly(Return()); + + // Initializes identifiers. + EXPECT_CALL(mock_funcs, GetStringIdentifiers(_, _, _)) + .WillRepeatedly( + Invoke(&mock_funcs, + &MockNetscapeFuncs::GetPrivilegedStringIdentifiers)); + MockNPAPI::InitializeIdentifiers(); + } + + virtual void TearDown() { + npapi::UninitializeBrowserFunctions(); + TestNPAPIPrivilegedApi::TearDown(); + } + + public: + MockNetscapeFuncs mock_funcs; +}; + + +} // namespace + +TEST_F(TestNPAPIPrivilegedProperty, + NonPrivilegedOnPrivateMessageInitializationFails) { + // Attempt setting onprivatemessage when not privileged. + SetupPrivilegeTest(false, // not incognito. + true, // expect privilege check. + false, // not privileged. + kDefaultProfileName, + L""); + + char* on_private_message_str = "onprivatemessage()"; + EXPECT_CALL(mock_api, JavascriptToNPObject(StrEq(on_private_message_str))) + .Times(0); // this should not be called. + + char* argn[] = { + "privileged_mode", + "onprivatemessage", + }; + char* argv[] = { + "1", + on_private_message_str, + }; + EXPECT_TRUE(mock_api.Initialize(const_cast<NPMIMEType>(kMimeType), + &instance, + NP_EMBED, + arraysize(argn), argn, argv)); + // Shouldn't be able to retrieve it. + NPVariant var; + VOID_TO_NPVARIANT(var); + EXPECT_FALSE(mock_api.GetProperty(kOnPrivateMessageId, &var)); + EXPECT_TRUE(NPVARIANT_IS_VOID(var)); + + mock_api.Uninitialize(); +} + +TEST_F(TestNPAPIPrivilegedProperty, + PrivilegedOnPrivateMessageInitializationSucceeds) { + // Set onprivatemessage argument when privileged. + SetupPrivilegeTest(false, // not incognito. + true, // expect privilege check. + true, // privileged. + kDefaultProfileName, + L""); + + char* on_private_message_str = "onprivatemessage()"; + NPObject* on_private_object = kMockNPObject; + EXPECT_CALL(mock_api, JavascriptToNPObject(StrEq(on_private_message_str))) + .WillOnce(Return(on_private_object)); + + char* argn[] = { + "privileged_mode", + "onprivatemessage", + }; + char* argv[] = { + "1", + on_private_message_str, + }; + EXPECT_TRUE(mock_api.Initialize(const_cast<NPMIMEType>(kMimeType), + &instance, + NP_EMBED, + arraysize(argn), argn, argv)); + // The property should have been set, verify that + // we can retrieve it and test it for correct value. + NPVariant var; + VOID_TO_NPVARIANT(var); + EXPECT_TRUE(mock_api.GetProperty(kOnPrivateMessageId, &var)); + EXPECT_TRUE(NPVARIANT_IS_OBJECT(var)); + EXPECT_EQ(kMockNPObject, NPVARIANT_TO_OBJECT(var)); + + mock_api.Uninitialize(); +} + +TEST_F(TestNPAPIPrivilegedProperty, + NonPrivilegedOnPrivateMessageAssignmentFails) { + // Assigning to onprivatemessage when not privileged should fail. + SetupPrivilegeTest(false, // not incognito. + true, // expect privilege check. + false, // not privileged. + kDefaultProfileName, + L""); + + char* argn = "privileged_mode"; + char* argv = "1"; + EXPECT_TRUE(mock_api.Initialize(const_cast<NPMIMEType>(kMimeType), + &instance, + NP_EMBED, + 1, &argn, &argv)); + + NPVariant var = {}; + OBJECT_TO_NPVARIANT(kMockNPObject, var); + // Setting should fail. + EXPECT_FALSE(mock_api.SetProperty(kOnPrivateMessageId, &var)); + + // And so should getting. + NULL_TO_NPVARIANT(var); + EXPECT_FALSE(mock_api.GetProperty(kOnPrivateMessageId, &var)); + + mock_api.Uninitialize(); +} + +TEST_F(TestNPAPIPrivilegedProperty, + PrivilegedOnPrivateMessageAssignmentSucceeds) { + // Assigning to onprivatemessage when privileged should succeed. + SetupPrivilegeTest(false, // not incognito. + true, // expect privilege check. + true, // privileged. + kDefaultProfileName, + L""); + + char* argn = "privileged_mode"; + char* argv = "1"; + EXPECT_TRUE(mock_api.Initialize(const_cast<NPMIMEType>(kMimeType), + &instance, + NP_EMBED, + 1, &argn, &argv)); + + NPVariant var = {}; + VOID_TO_NPVARIANT(var); + // Getting the property when NULL fails under current implementation. + // I shouldn't have thought this is correct behavior, e.g. I should + // have thought retrieving the NULL should succeed, but this is consistent + // with how other properties behave. + // TODO(robertshield): investigate and/or fix. + EXPECT_FALSE(mock_api.GetProperty(kOnPrivateMessageId, &var)); + // EXPECT_TRUE(NPVARIANT_IS_OBJECT(var)); + // EXPECT_EQ(NULL, NPVARIANT_TO_OBJECT(var)); + + // Setting the property should succeed. + OBJECT_TO_NPVARIANT(kMockNPObject, var); + EXPECT_TRUE(mock_api.SetProperty(kOnPrivateMessageId, &var)); + + // And fething it should return the value we just set. + VOID_TO_NPVARIANT(var); + EXPECT_TRUE(mock_api.GetProperty(kOnPrivateMessageId, &var)); + EXPECT_TRUE(NPVARIANT_IS_OBJECT(var)); + EXPECT_EQ(kMockNPObject, NPVARIANT_TO_OBJECT(var)); + + mock_api.Uninitialize(); +} + +// TODO(siggi): test invoking postPrivateMessage. |