blob: b30d5e8a152793294deb028bc659fd2e54bf1056 [file] [log] [blame]
[email protected]f7817822009-09-24 05:11:581// Copyright (c) 2009 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 "gtest/gtest.h"
6#include "gmock/gmock.h"
7#include "chrome_frame/chrome_frame_automation.h"
8#include "chrome_frame/chrome_frame_npapi.h"
9#include "chrome_frame/ff_privilege_check.h"
10
11
12TEST(ChromeFrameNPAPI, DoesNotCrashOnConstruction) {
13 ChromeFrameNPAPI* api = new ChromeFrameNPAPI();
14 delete api;
15}
16
17
18// All mocks in the anonymous namespace.
19namespace {
20
21using ::testing::_;
22using ::testing::Eq;
23using ::testing::Invoke;
24using ::testing::Return;
25using ::testing::StrEq;
26
27// Make mocking privilege test easy.
28class MockPrivilegeTest {
29 public:
30 MockPrivilegeTest() {
31 CHECK(current_ == NULL);
32 current_ = this;
33 }
34 ~MockPrivilegeTest() {
35 CHECK(current_ == this);
36 current_ = NULL;
37 }
38
39 MOCK_METHOD1(IsFireFoxPrivilegedInvocation, bool(NPP));
40
41 static MockPrivilegeTest* current() { return current_; }
42
43 private:
44 static MockPrivilegeTest* current_;
45};
46
47MockPrivilegeTest* MockPrivilegeTest::current_ = NULL;
48
49const char* kMimeType = "application/chromeframe";
50// The default profile name is by default derived from the currently
51// running executable's name.
52const wchar_t* kDefaultProfileName = L"chrome_frame_unittests";
53
54
55class MockNPAPI: public ChromeFrameNPAPI {
56 public:
57 MockNPAPI() : mock_automation_client_(NULL) {}
58
59 MOCK_METHOD0(CreatePrefService, NpProxyService*());
60
61 MOCK_METHOD0(GetLocation, std::string());
62 MOCK_METHOD0(GetBrowserIncognitoMode, bool());
63
64 MOCK_METHOD1(JavascriptToNPObject, virtual NPObject*(const std::string&));
65
66 // Make public for test purposes
67 void OnAutomationServerReady() {
68 ChromeFrameNPAPI::OnAutomationServerReady();
69 }
70
71 // Neuter this (or it dchecks during testing).
72 void SetReadyState(READYSTATE new_state) {}
73
74 ChromeFrameAutomationClient* CreateAutomationClient() {
75 return mock_automation_client_;
76 }
77
78 ChromeFrameAutomationClient* mock_automation_client_;
79};
80
81class MockAutomationClient: public ChromeFrameAutomationClient {
82 public:
83 MOCK_METHOD6(Initialize, bool(ChromeFrameDelegate*, int, bool,
84 const std::wstring&, const std::wstring&,
85 bool));
[email protected]50f53162009-10-23 19:16:2086 MOCK_METHOD1(SetEnableExtensionAutomation,
87 void(const std::vector<std::string>&)); // NOLINT
[email protected]f7817822009-09-24 05:11:5888};
89
90class MockProxyService: public NpProxyService {
91 public:
92 MOCK_METHOD2(Initialize, bool(NPP instance, ChromeFrameAutomationClient*));
93};
94
95
96// Test fixture to allow testing the privileged NPAPI APIs
97class TestNPAPIPrivilegedApi: public ::testing::Test {
98 public:
99 virtual void SetUp() {
100 memset(&instance, 0, sizeof(instance));
101
102 // Gets owned & destroyed by mock_api (in the
103 // ChromeFramePlugin<T>::Uninitialize() function).
104 mock_automation = new MockAutomationClient;
105
106 mock_api.mock_automation_client_ = mock_automation;
107 mock_proxy = new MockProxyService;
108 mock_proxy->AddRef();
109 mock_proxy_holder.Attach(mock_proxy);
110 }
111
112 virtual void TearDown() {
113 }
114
115 void SetupPrivilegeTest(bool is_incognito,
116 bool expect_privilege_check,
117 bool is_privileged,
118 const std::wstring& profile_name,
119 const std::wstring& extra_args) {
120 EXPECT_CALL(mock_api, GetLocation())
121 .WillOnce(Return(std::string("http://www.google.com")));
122 EXPECT_CALL(mock_api, CreatePrefService())
123 .WillOnce(Return(mock_proxy));
124 EXPECT_CALL(mock_api, GetBrowserIncognitoMode())
125 .WillOnce(Return(is_incognito));
126
127 EXPECT_CALL(*mock_proxy, Initialize(_, _)).WillRepeatedly(Return(false));
128
129 EXPECT_CALL(*mock_automation,
130 Initialize(_, _, true, StrEq(profile_name), StrEq(extra_args), false))
131 .WillOnce(Return(true));
132
133 if (expect_privilege_check) {
134 EXPECT_CALL(mock_priv, IsFireFoxPrivilegedInvocation(_))
135 .WillOnce(Return(is_privileged));
136 } else {
137 EXPECT_CALL(mock_priv, IsFireFoxPrivilegedInvocation(_))
138 .Times(0); // Fail if privilege check invoked.
139 }
140 }
141
142 public:
143 MockNPAPI mock_api;
144 MockAutomationClient* mock_automation;
145 MockProxyService* mock_proxy;
146 ScopedNsPtr<nsISupports> mock_proxy_holder;
147 MockPrivilegeTest mock_priv;
148 NPP_t instance;
149};
150
151} // namespace
152
153// Stub for unittesting.
154bool IsFireFoxPrivilegedInvocation(NPP npp) {
155 MockPrivilegeTest* mock = MockPrivilegeTest::current();
156 if (!mock)
157 return false;
158
159 return mock->IsFireFoxPrivilegedInvocation(npp);
160}
161
162TEST_F(TestNPAPIPrivilegedApi, NoPrivilegeCheckWhenNoArguments) {
163 SetupPrivilegeTest(false, // Not incognito
164 false, // Fail if privilege check is invoked.
165 false,
166 kDefaultProfileName,
167 L""); // No extra args to initialize.
168
169 // No arguments, no privilege requested.
170 EXPECT_TRUE(mock_api.Initialize(const_cast<NPMIMEType>(kMimeType),
171 &instance,
172 NP_EMBED,
173 0, 0, 0));
174}
175
176TEST_F(TestNPAPIPrivilegedApi, NoPrivilegeCheckWhenZeroArgument) {
177 SetupPrivilegeTest(false, // Not incognito
178 false, // Fail if privilege check is invoked.
179 false,
180 kDefaultProfileName,
181 L""); // No extra args to initialize.
182
183 // Privileged mode explicitly zero.
184 char* argn = "is_privileged";
185 char* argv = "0";
186 EXPECT_TRUE(mock_api.Initialize(const_cast<NPMIMEType>(kMimeType),
187 &instance,
188 NP_EMBED,
189 1, &argn, &argv));
190}
191
192TEST_F(TestNPAPIPrivilegedApi, NotPrivilegedDoesNotAllowArgsOrProfile) {
193 SetupPrivilegeTest(false, // Not incognito.
194 true, // Fail unless privilege check is invoked.
195 false, // Not privileged.
196 kDefaultProfileName,
197 L""); // No extra arguments allowed.
198
199 char* argn[] = {
200 "privileged_mode",
201 "chrome_extra_arguments",
202 "chrome_profile_name",
203 };
204 char *argv[] = {
205 "1",
206 "foo",
207 "bar",
208 };
209 EXPECT_TRUE(mock_api.Initialize(const_cast<NPMIMEType>(kMimeType),
210 &instance,
211 NP_EMBED,
212 arraysize(argn), argn, argv));
213}
214
215TEST_F(TestNPAPIPrivilegedApi, PrivilegedAllowsArgsAndProfile) {
216 SetupPrivilegeTest(false, // Not incognito.
217 true, // Fail unless privilege check is invoked.
218 true, // Privileged mode.
219 L"custom_profile_name", // Custom profile expected.
220 L"-bar=far"); // Extra arguments expected
221
222 // With privileged mode we expect automation to be enabled.
[email protected]50f53162009-10-23 19:16:20223 EXPECT_CALL(*mock_automation, SetEnableExtensionAutomation(_))
[email protected]f7817822009-09-24 05:11:58224 .Times(1);
225
226 char* argn[] = {
227 "privileged_mode",
228 "chrome_extra_arguments",
229 "chrome_profile_name",
230 };
231 char *argv[] = {
232 "1",
233 "-bar=far",
234 "custom_profile_name",
235 };
236 EXPECT_TRUE(mock_api.Initialize(const_cast<NPMIMEType>(kMimeType),
237 &instance,
238 NP_EMBED,
239 arraysize(argn), argn, argv));
240
241 // Since we're mocking out ChromeFrameAutomationClient::Initialize, we need
242 // to tickle this explicitly.
243 mock_api.OnAutomationServerReady();
244}
245
246
247namespace {
248
249static const NPIdentifier kOnPrivateMessageId =
250 reinterpret_cast<NPIdentifier>(0x100);
251static const NPIdentifier kPostPrivateMessageId =
252 reinterpret_cast<NPIdentifier>(0x100);
253
254
255class MockNetscapeFuncs {
256 public:
257 MockNetscapeFuncs() {
258 CHECK(NULL == current_);
259 current_ = this;
260 }
261
262 ~MockNetscapeFuncs() {
263 CHECK(this == current_);
264 current_ = NULL;
265 }
266
267 MOCK_METHOD3(GetValue, NPError(NPP, NPNVariable, void *));
268 MOCK_METHOD3(GetStringIdentifiers, void(const NPUTF8 **,
269 int32_t,
270 NPIdentifier *)); // NOLINT
271 MOCK_METHOD1(RetainObject, NPObject*(NPObject*)); // NOLINT
272 MOCK_METHOD1(ReleaseObject, void(NPObject*)); // NOLINT
273
274
275 void GetPrivilegedStringIdentifiers(const NPUTF8 **names,
276 int32_t name_count,
277 NPIdentifier *identifiers) {
278 for (int32_t i = 0; i < name_count; ++i) {
279 if (0 == strcmp(names[i], "onprivatemessage")) {
280 identifiers[i] = kOnPrivateMessageId;
281 } else if (0 == strcmp(names[i], "postPrivateMessage")) {
282 identifiers[i] = kPostPrivateMessageId;
283 } else {
284 identifiers[i] = 0;
285 }
286 }
287 }
288
289 static const NPNetscapeFuncs* netscape_funcs() {
290 return &netscape_funcs_;
291 }
292
293 private:
294 static NPError MockGetValue(NPP instance,
295 NPNVariable variable,
296 void *ret_value) {
297 DCHECK(current_);
298 return current_->GetValue(instance, variable, ret_value);
299 }
300
301 static void MockGetStringIdentifiers(const NPUTF8 **names,
302 int32_t name_count,
303 NPIdentifier *identifiers) {
304 DCHECK(current_);
305 return current_->GetStringIdentifiers(names, name_count, identifiers);
306 }
307
308 static NPObject* MockRetainObject(NPObject* obj) {
309 DCHECK(current_);
310 return current_->RetainObject(obj);
311 }
312
313 static void MockReleaseObject(NPObject* obj) {
314 DCHECK(current_);
315 current_->ReleaseObject(obj);
316 }
317
318 static MockNetscapeFuncs* current_;
319 static NPNetscapeFuncs netscape_funcs_;
320};
321
322MockNetscapeFuncs* MockNetscapeFuncs::current_ = NULL;
323NPNetscapeFuncs MockNetscapeFuncs::netscape_funcs_ = {
324 0, // size
325 0, // version
326 NULL, // geturl
327 NULL, // posturl
328 NULL, // requestread
329 NULL, // newstream
330 NULL, // write
331 NULL, // destroystream
332 NULL, // status
333 NULL, // uagent
334 NULL, // memalloc
335 NULL, // memfree
336 NULL, // memflush
337 NULL, // reloadplugins
338 NULL, // getJavaEnv
339 NULL, // getJavaPeer
340 NULL, // geturlnotify
341 NULL, // posturlnotify
342 MockGetValue, // getvalue
343 NULL, // setvalue
344 NULL, // invalidaterect
345 NULL, // invalidateregion
346 NULL, // forceredraw
347 NULL, // getstringidentifier
348 MockGetStringIdentifiers, // getstringidentifiers
349 NULL, // getintidentifier
350 NULL, // identifierisstring
351 NULL, // utf8fromidentifier
352 NULL, // intfromidentifier
353 NULL, // createobject
354 MockRetainObject, // retainobject
355 MockReleaseObject, // releaseobject
356 NULL, // invoke
357 NULL, // invokeDefault
358 NULL, // evaluate
359 NULL, // getproperty
360 NULL, // setproperty
361 NULL, // removeproperty
362 NULL, // hasproperty
363 NULL, // hasmethod
364 NULL, // releasevariantvalue
365 NULL, // setexception
366 NULL, // pushpopupsenabledstate
367 NULL, // poppopupsenabledstate
368 NULL, // enumerate
369 NULL, // pluginthreadasynccall
370 NULL, // construct
371};
372
373NPObject* const kMockNPObject = reinterpret_cast<NPObject*>(0xCafeBabe);
374
375class TestNPAPIPrivilegedProperty: public TestNPAPIPrivilegedApi {
376 public:
377 virtual void SetUp() {
378 TestNPAPIPrivilegedApi::SetUp();
379 npapi::InitializeBrowserFunctions(
380 const_cast<NPNetscapeFuncs*>(mock_funcs.netscape_funcs()));
381
382 // Expect calls to release and retain objects.
383 EXPECT_CALL(mock_funcs, RetainObject(kMockNPObject))
384 .WillRepeatedly(Return(kMockNPObject));
385 EXPECT_CALL(mock_funcs, ReleaseObject(kMockNPObject))
386 .WillRepeatedly(Return());
387
388 // And we should expect SetEnableExtensionAutomation to be called
389 // for privileged tests.
[email protected]50f53162009-10-23 19:16:20390 EXPECT_CALL(*mock_automation, SetEnableExtensionAutomation(_))
[email protected]f7817822009-09-24 05:11:58391 .WillRepeatedly(Return());
392
393 // Initializes identifiers.
394 EXPECT_CALL(mock_funcs, GetStringIdentifiers(_, _, _))
395 .WillRepeatedly(
396 Invoke(&mock_funcs,
397 &MockNetscapeFuncs::GetPrivilegedStringIdentifiers));
398 MockNPAPI::InitializeIdentifiers();
399 }
400
401 virtual void TearDown() {
402 npapi::UninitializeBrowserFunctions();
403 TestNPAPIPrivilegedApi::TearDown();
404 }
405
406 public:
407 MockNetscapeFuncs mock_funcs;
408};
409
410
411} // namespace
412
413TEST_F(TestNPAPIPrivilegedProperty,
414 NonPrivilegedOnPrivateMessageInitializationFails) {
415 // Attempt setting onprivatemessage when not privileged.
416 SetupPrivilegeTest(false, // not incognito.
417 true, // expect privilege check.
418 false, // not privileged.
419 kDefaultProfileName,
420 L"");
421
422 char* on_private_message_str = "onprivatemessage()";
423 EXPECT_CALL(mock_api, JavascriptToNPObject(StrEq(on_private_message_str)))
424 .Times(0); // this should not be called.
425
426 char* argn[] = {
427 "privileged_mode",
428 "onprivatemessage",
429 };
430 char* argv[] = {
431 "1",
432 on_private_message_str,
433 };
434 EXPECT_TRUE(mock_api.Initialize(const_cast<NPMIMEType>(kMimeType),
435 &instance,
436 NP_EMBED,
437 arraysize(argn), argn, argv));
438 // Shouldn't be able to retrieve it.
439 NPVariant var;
440 VOID_TO_NPVARIANT(var);
441 EXPECT_FALSE(mock_api.GetProperty(kOnPrivateMessageId, &var));
442 EXPECT_TRUE(NPVARIANT_IS_VOID(var));
443
444 mock_api.Uninitialize();
445}
446
447TEST_F(TestNPAPIPrivilegedProperty,
448 PrivilegedOnPrivateMessageInitializationSucceeds) {
449 // Set onprivatemessage argument when privileged.
450 SetupPrivilegeTest(false, // not incognito.
451 true, // expect privilege check.
452 true, // privileged.
453 kDefaultProfileName,
454 L"");
455
456 char* on_private_message_str = "onprivatemessage()";
457 NPObject* on_private_object = kMockNPObject;
458 EXPECT_CALL(mock_api, JavascriptToNPObject(StrEq(on_private_message_str)))
459 .WillOnce(Return(on_private_object));
460
461 char* argn[] = {
462 "privileged_mode",
463 "onprivatemessage",
464 };
465 char* argv[] = {
466 "1",
467 on_private_message_str,
468 };
469 EXPECT_TRUE(mock_api.Initialize(const_cast<NPMIMEType>(kMimeType),
470 &instance,
471 NP_EMBED,
472 arraysize(argn), argn, argv));
473 // The property should have been set, verify that
474 // we can retrieve it and test it for correct value.
475 NPVariant var;
476 VOID_TO_NPVARIANT(var);
477 EXPECT_TRUE(mock_api.GetProperty(kOnPrivateMessageId, &var));
478 EXPECT_TRUE(NPVARIANT_IS_OBJECT(var));
479 EXPECT_EQ(kMockNPObject, NPVARIANT_TO_OBJECT(var));
480
481 mock_api.Uninitialize();
482}
483
484TEST_F(TestNPAPIPrivilegedProperty,
485 NonPrivilegedOnPrivateMessageAssignmentFails) {
486 // Assigning to onprivatemessage when not privileged should fail.
487 SetupPrivilegeTest(false, // not incognito.
488 true, // expect privilege check.
489 false, // not privileged.
490 kDefaultProfileName,
491 L"");
492
493 char* argn = "privileged_mode";
494 char* argv = "1";
495 EXPECT_TRUE(mock_api.Initialize(const_cast<NPMIMEType>(kMimeType),
496 &instance,
497 NP_EMBED,
498 1, &argn, &argv));
499
500 NPVariant var = {};
501 OBJECT_TO_NPVARIANT(kMockNPObject, var);
502 // Setting should fail.
503 EXPECT_FALSE(mock_api.SetProperty(kOnPrivateMessageId, &var));
504
505 // And so should getting.
506 NULL_TO_NPVARIANT(var);
507 EXPECT_FALSE(mock_api.GetProperty(kOnPrivateMessageId, &var));
508
509 mock_api.Uninitialize();
510}
511
512TEST_F(TestNPAPIPrivilegedProperty,
513 PrivilegedOnPrivateMessageAssignmentSucceeds) {
514 // Assigning to onprivatemessage when privileged should succeed.
515 SetupPrivilegeTest(false, // not incognito.
516 true, // expect privilege check.
517 true, // privileged.
518 kDefaultProfileName,
519 L"");
520
521 char* argn = "privileged_mode";
522 char* argv = "1";
523 EXPECT_TRUE(mock_api.Initialize(const_cast<NPMIMEType>(kMimeType),
524 &instance,
525 NP_EMBED,
526 1, &argn, &argv));
527
528 NPVariant var = {};
529 VOID_TO_NPVARIANT(var);
530 // Getting the property when NULL fails under current implementation.
531 // I shouldn't have thought this is correct behavior, e.g. I should
532 // have thought retrieving the NULL should succeed, but this is consistent
533 // with how other properties behave.
534 // TODO(robertshield): investigate and/or fix.
535 EXPECT_FALSE(mock_api.GetProperty(kOnPrivateMessageId, &var));
536 // EXPECT_TRUE(NPVARIANT_IS_OBJECT(var));
537 // EXPECT_EQ(NULL, NPVARIANT_TO_OBJECT(var));
538
539 // Setting the property should succeed.
540 OBJECT_TO_NPVARIANT(kMockNPObject, var);
541 EXPECT_TRUE(mock_api.SetProperty(kOnPrivateMessageId, &var));
542
543 // And fething it should return the value we just set.
544 VOID_TO_NPVARIANT(var);
545 EXPECT_TRUE(mock_api.GetProperty(kOnPrivateMessageId, &var));
546 EXPECT_TRUE(NPVARIANT_IS_OBJECT(var));
547 EXPECT_EQ(kMockNPObject, NPVARIANT_TO_OBJECT(var));
548
549 mock_api.Uninitialize();
550}
551
552// TODO(siggi): test invoking postPrivateMessage.