| Index: chrome_frame/chrome_frame_npapi_unittest.cc
|
| ===================================================================
|
| --- chrome_frame/chrome_frame_npapi_unittest.cc (revision 0)
|
| +++ chrome_frame/chrome_frame_npapi_unittest.cc (revision 0)
|
| @@ -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.
|
|
|