1 // Copyright (c) 2012 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 // Helper function to log message to both the local console and to the
6 // background page, so that the latter can output the message via the
7 // chrome.test.log() function.
8 function logToConsoleAndStdout(msg
) {
10 chrome
.extension
.sendRequest("log: " + msg
);
13 // We ask the background page to get the extension API to test against. When it
14 // responds we start the test.
15 console
.log("asking for api ...");
16 chrome
.extension
.sendRequest("getApi", function(apis
) {
17 var apiFeatures
= chrome
.test
.getApiFeatures();
18 function isAvailableToContentScripts(namespace, path
) {
19 function checkContexts(contextList
) {
20 return contextList
== 'all' ||
21 contextList
.indexOf('content_script') != -1;
23 function checkFeature(feature
) {
24 if (feature
.contexts
) {
26 return checkContexts(feature
.contexts
);
29 for (var i
= 0; i
< feature
.length
; i
++) {
30 if (checkContexts(feature
[i
].contexts
))
37 if (apiFeatures
.hasOwnProperty(path
))
38 return checkFeature(apiFeatures
[path
]);
39 return apiFeatures
.hasOwnProperty(namespace) &&
40 checkFeature(apiFeatures
[namespace]);
43 console
.log("got api response");
44 var privilegedPaths
= [];
45 var unprivilegedPaths
= [];
46 apis
.forEach(function(module
) {
47 var namespace = module
.namespace;
49 ["functions", "events"].forEach(function(section
) {
50 if (typeof(module
[section
]) == "undefined")
52 module
[section
].forEach(function(entry
) {
53 // Ignore entries that are not applicable to the manifest that we're
55 if (entry
.maximumManifestVersion
&& entry
.maximumManifestVersion
< 2) {
59 var path
= namespace + "." + entry
.name
;
60 if (module
.unprivileged
|| entry
.unprivileged
||
61 isAvailableToContentScripts(namespace, path
)) {
62 unprivilegedPaths
.push(path
);
64 privilegedPaths
.push(path
);
69 if (module
.properties
) {
70 for (var propName
in module
.properties
) {
71 var path
= namespace + "." + propName
;
72 if (module
.unprivileged
|| module
.properties
[propName
].unprivileged
||
73 isAvailableToContentScripts(namespace, path
)) {
74 unprivilegedPaths
.push(path
);
76 privilegedPaths
.push(path
);
81 doTest(privilegedPaths
, unprivilegedPaths
);
85 // Tests whether missing properties of the chrome object correctly throw an
86 // error on access. The path is a namespace or function/property/event etc.
87 // within a namespace, and is dot-separated.
88 function testPath(path
, expectError
) {
89 var parts
= path
.split('.');
92 for (var i
= 0; i
< parts
.length
; i
++) {
93 if (i
< parts
.length
- 1) {
94 // Not the last component. Allowed to be undefined because some paths are
95 // only defined on some platforms.
96 module
= module
[parts
[i
]];
97 if (typeof(module
) == "undefined")
100 // This is the last component - we expect it to either be undefined or
101 // to throw an error on access.
102 if (typeof(module
[parts
[i
]]) == "undefined" &&
103 // lastError being defined depends on there being an error obviously.
104 path
!= "extension.lastError" &&
105 path
!= "runtime.lastError") {
109 logToConsoleAndStdout(" fail (should not be undefined): " + path
);
112 } else if (!expectError
) {
117 logToConsoleAndStdout(" fail (no error when we were expecting one): " + path
);
121 function displayResult(status
) {
122 var div
= document
.createElement("div");
123 div
.innerHTML
= "<h1>" + status
+ "</h2>";
124 document
.body
.appendChild(div
);
127 function reportSuccess() {
128 displayResult("pass");
129 chrome
.extension
.sendRequest("pass");
132 function reportFailure() {
133 displayResult("fail");
134 // Let the "fail" show for a little while so you can see it when running
135 // browser_tests in the debugger.
136 setTimeout(function() {
137 chrome
.extension
.sendRequest("fail");
141 // Runs over each string path in privilegedPaths and unprivilegedPaths, testing
142 // to ensure a proper error is thrown on access or the path is defined.
143 function doTest(privilegedPaths
, unprivilegedPaths
) {
144 console
.log("starting");
146 if (!privilegedPaths
|| privilegedPaths
.length
< 1 || !unprivilegedPaths
||
147 unprivilegedPaths
.length
< 1) {
155 // Returns a function that will test a path and record any failures.
156 function makeTestFunction(expectError
) {
157 return function(path
) {
158 // runtime.connect and runtime.sendMessage are available in all contexts,
159 // unlike the runtime API in general.
160 var expectErrorForPath
= expectError
&&
161 path
!= 'runtime.connect' &&
162 path
!= 'runtime.sendMessage';
163 if (!testPath(path
, expectErrorForPath
)) {
169 privilegedPaths
.forEach(makeTestFunction(true));
170 unprivilegedPaths
.forEach(makeTestFunction(false));
172 console
.log(success
? "pass" : "fail");
176 logToConsoleAndStdout("failures on:\n" + failures
.join("\n") +
177 "\n\n\n>>> See comment in stubs_apitest.cc for a " +
178 "hint about fixing this failure.\n\n");