1 // Copyright 2014 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.
5 #include "extensions/renderer/api_test_base.h"
9 #include "base/run_loop.h"
10 #include "extensions/common/extension_urls.h"
11 #include "extensions/renderer/dispatcher.h"
12 #include "extensions/renderer/process_info_native_handler.h"
13 #include "gin/converter.h"
14 #include "gin/dictionary.h"
15 #include "third_party/mojo/src/mojo/edk/js/core.h"
16 #include "third_party/mojo/src/mojo/edk/js/handle.h"
17 #include "third_party/mojo/src/mojo/edk/js/support.h"
18 #include "third_party/mojo/src/mojo/public/cpp/bindings/interface_request.h"
19 #include "third_party/mojo/src/mojo/public/cpp/system/core.h"
21 namespace extensions
{
24 // Natives for the implementation of the unit test version of chrome.test. Calls
25 // the provided |quit_closure| when either notifyPass or notifyFail is called.
26 class TestNatives
: public gin::Wrappable
<TestNatives
> {
28 static gin::Handle
<TestNatives
> Create(v8::Isolate
* isolate
,
29 const base::Closure
& quit_closure
) {
30 return gin::CreateHandle(isolate
, new TestNatives(quit_closure
));
33 gin::ObjectTemplateBuilder
GetObjectTemplateBuilder(
34 v8::Isolate
* isolate
) override
{
35 return Wrappable
<TestNatives
>::GetObjectTemplateBuilder(isolate
)
36 .SetMethod("Log", &TestNatives::Log
)
37 .SetMethod("NotifyPass", &TestNatives::NotifyPass
)
38 .SetMethod("NotifyFail", &TestNatives::NotifyFail
);
41 void Log(const std::string
& value
) { logs_
+= value
+ "\n"; }
42 void NotifyPass() { FinishTesting(); }
44 void NotifyFail(const std::string
& message
) {
46 FAIL() << logs_
<< message
;
49 void FinishTesting() {
50 base::MessageLoop::current()->PostTask(FROM_HERE
, quit_closure_
);
53 static gin::WrapperInfo kWrapperInfo
;
56 explicit TestNatives(const base::Closure
& quit_closure
)
57 : quit_closure_(quit_closure
) {}
59 const base::Closure quit_closure_
;
63 gin::WrapperInfo
TestNatives::kWrapperInfo
= {gin::kEmbedderNativeGin
};
67 gin::WrapperInfo
TestServiceProvider::kWrapperInfo
= {gin::kEmbedderNativeGin
};
69 gin::Handle
<TestServiceProvider
> TestServiceProvider::Create(
70 v8::Isolate
* isolate
) {
71 return gin::CreateHandle(isolate
, new TestServiceProvider());
74 TestServiceProvider::~TestServiceProvider() {
77 gin::ObjectTemplateBuilder
TestServiceProvider::GetObjectTemplateBuilder(
78 v8::Isolate
* isolate
) {
79 return Wrappable
<TestServiceProvider
>::GetObjectTemplateBuilder(isolate
)
80 .SetMethod("connectToService", &TestServiceProvider::ConnectToService
);
83 mojo::Handle
TestServiceProvider::ConnectToService(
84 const std::string
& service_name
) {
85 EXPECT_EQ(1u, service_factories_
.count(service_name
))
86 << "Unregistered service " << service_name
<< " requested.";
87 mojo::MessagePipe pipe
;
89 base::Callback
<void(mojo::ScopedMessagePipeHandle
)> >::iterator it
=
90 service_factories_
.find(service_name
);
91 if (it
!= service_factories_
.end())
92 it
->second
.Run(pipe
.handle0
.Pass());
93 return pipe
.handle1
.release();
96 TestServiceProvider::TestServiceProvider() {
100 void TestServiceProvider::IgnoreHandle(mojo::ScopedMessagePipeHandle handle
) {
103 ApiTestEnvironment::ApiTestEnvironment(
104 ModuleSystemTestEnvironment
* environment
) {
106 InitializeEnvironment();
110 ApiTestEnvironment::~ApiTestEnvironment() {
113 void ApiTestEnvironment::RegisterModules() {
114 v8_schema_registry_
.reset(new V8SchemaRegistry
);
115 const std::vector
<std::pair
<std::string
, int> > resources
=
116 Dispatcher::GetJsResources();
117 for (std::vector
<std::pair
<std::string
, int> >::const_iterator resource
=
119 resource
!= resources
.end();
121 if (resource
->first
!= "test_environment_specific_bindings")
122 env()->RegisterModule(resource
->first
, resource
->second
);
124 Dispatcher::RegisterNativeHandlers(env()->module_system(),
128 v8_schema_registry_
.get());
129 env()->module_system()->RegisterNativeHandler(
131 scoped_ptr
<NativeHandler
>(new ProcessInfoNativeHandler(
133 env()->context()->GetExtensionID(),
134 env()->context()->GetContextTypeDescription(),
139 env()->RegisterTestFile("test_environment_specific_bindings",
140 "unit_test_environment_specific_bindings.js");
142 env()->OverrideNativeHandler("activityLogger",
143 "exports.LogAPICall = function() {};");
144 env()->OverrideNativeHandler(
146 "exports.GetExtensionAPIDefinitionsForTest = function() { return [] };");
147 env()->OverrideNativeHandler(
149 "exports.AttachEvent = function() {};"
150 "exports.DetachEvent = function() {};"
151 "exports.AttachFilteredEvent = function() {};"
152 "exports.AttachFilteredEvent = function() {};"
153 "exports.MatchAgainstEventFilter = function() { return [] };");
155 gin::ModuleRegistry::From(env()->context()->v8_context())
156 ->AddBuiltinModule(env()->isolate(),
157 mojo::js::Core::kModuleName
,
158 mojo::js::Core::GetModule(env()->isolate()));
159 gin::ModuleRegistry::From(env()->context()->v8_context())
160 ->AddBuiltinModule(env()->isolate(),
161 mojo::js::Support::kModuleName
,
162 mojo::js::Support::GetModule(env()->isolate()));
163 gin::Handle
<TestServiceProvider
> service_provider
=
164 TestServiceProvider::Create(env()->isolate());
165 service_provider_
= service_provider
.get();
166 gin::ModuleRegistry::From(env()->context()->v8_context())
167 ->AddBuiltinModule(env()->isolate(),
168 "content/public/renderer/service_provider",
169 service_provider
.ToV8());
172 void ApiTestEnvironment::InitializeEnvironment() {
173 gin::Dictionary
global(env()->isolate(),
174 env()->context()->v8_context()->Global());
175 gin::Dictionary
navigator(gin::Dictionary::CreateEmpty(env()->isolate()));
176 navigator
.Set("appVersion", base::StringPiece(""));
177 global
.Set("navigator", navigator
);
178 gin::Dictionary
chrome(gin::Dictionary::CreateEmpty(env()->isolate()));
179 global
.Set("chrome", chrome
);
180 gin::Dictionary
extension(gin::Dictionary::CreateEmpty(env()->isolate()));
181 chrome
.Set("extension", extension
);
182 gin::Dictionary
runtime(gin::Dictionary::CreateEmpty(env()->isolate()));
183 chrome
.Set("runtime", runtime
);
186 void ApiTestEnvironment::RunTest(const std::string
& file_name
,
187 const std::string
& test_name
) {
188 env()->RegisterTestFile("testBody", file_name
);
189 base::RunLoop run_loop
;
190 gin::ModuleRegistry::From(env()->context()->v8_context())->AddBuiltinModule(
193 TestNatives::Create(env()->isolate(), run_loop
.QuitClosure()).ToV8());
194 base::MessageLoop::current()->PostTask(
196 base::Bind(&ApiTestEnvironment::RunTestInner
, base::Unretained(this),
197 test_name
, run_loop
.QuitClosure()));
198 base::MessageLoop::current()->PostTask(
199 FROM_HERE
, base::Bind(&ApiTestEnvironment::RunPromisesAgain
,
200 base::Unretained(this)));
204 void ApiTestEnvironment::RunTestInner(const std::string
& test_name
,
205 const base::Closure
& quit_closure
) {
206 v8::HandleScope
scope(env()->isolate());
207 ModuleSystem::NativesEnabledScope
natives_enabled(env()->module_system());
208 v8::Local
<v8::Value
> result
=
209 env()->module_system()->CallModuleMethod("testBody", test_name
);
210 if (!result
->IsTrue()) {
211 base::MessageLoop::current()->PostTask(FROM_HERE
, quit_closure
);
212 FAIL() << "Failed to run test \"" << test_name
<< "\"";
216 void ApiTestEnvironment::RunPromisesAgain() {
217 env()->isolate()->RunMicrotasks();
218 base::MessageLoop::current()->PostTask(
219 FROM_HERE
, base::Bind(&ApiTestEnvironment::RunPromisesAgain
,
220 base::Unretained(this)));
223 ApiTestBase::ApiTestBase() {
226 ApiTestBase::~ApiTestBase() {
229 void ApiTestBase::SetUp() {
230 ModuleSystemTest::SetUp();
231 test_env_
.reset(new ApiTestEnvironment(env()));
234 void ApiTestBase::RunTest(const std::string
& file_name
,
235 const std::string
& test_name
) {
236 ExpectNoAssertionsMade();
237 test_env_
->RunTest(file_name
, test_name
);
240 } // namespace extensions