| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 var util = {}; | 5 var util = {}; |
| 6 | 6 |
| 7 // Creates a <webview> tag in document.body and returns the reference to it. | 7 // Creates a <webview> tag in document.body and returns the reference to it. |
| 8 // It also sets a dummy src. The dummy src is significant because this makes | 8 // It also sets a dummy src. The dummy src is significant because this makes |
| 9 // sure that the <object> shim is created (asynchronously at this point) for the | 9 // sure that the <object> shim is created (asynchronously at this point) for the |
| 10 // <webview> tag. This makes the <webview> tag ready for add/removeEventListener | 10 // <webview> tag. This makes the <webview> tag ready for add/removeEventListener |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 53 chrome.test.assertEq(230, dynamicWebViewTag.offsetHeight); | 53 chrome.test.assertEq(230, dynamicWebViewTag.offsetHeight); |
| 54 | 54 |
| 55 chrome.test.succeed(); | 55 chrome.test.succeed(); |
| 56 }, 0); | 56 }, 0); |
| 57 }, | 57 }, |
| 58 | 58 |
| 59 function webViewApiMethodExistence() { | 59 function webViewApiMethodExistence() { |
| 60 var webview = document.createElement('webview'); | 60 var webview = document.createElement('webview'); |
| 61 webview.setAttribute('src', 'data:text/html,webview check api'); | 61 webview.setAttribute('src', 'data:text/html,webview check api'); |
| 62 var apiMethodsToCheck = [ | 62 var apiMethodsToCheck = [ |
| 63 'addEventListener', | |
| 64 'back', | 63 'back', |
| 65 'canGoBack', | 64 'canGoBack', |
| 66 'canGoForward', | 65 'canGoForward', |
| 67 'forward', | 66 'forward', |
| 68 'getProcessId', | 67 'getProcessId', |
| 69 'go', | 68 'go', |
| 70 'reload', | 69 'reload', |
| 71 'removeEventListener', | |
| 72 'stop', | 70 'stop', |
| 73 'terminate' | 71 'terminate' |
| 74 ]; | 72 ]; |
| 75 document.body.appendChild(webview); | 73 document.body.appendChild(webview); |
| 76 | 74 |
| 77 // Timeout is necessary to give the mutation observers of the webview tag | 75 // Timeout is necessary to give the mutation observers of the webview tag |
| 78 // shim a chance to fire. | 76 // shim a chance to fire. |
| 79 setTimeout(function() { | 77 setTimeout(function() { |
| 80 for (var i = 0; i < apiMethodsToCheck.length; ++i) { | 78 for (var i = 0; i < apiMethodsToCheck.length; ++i) { |
| 81 chrome.test.assertEq('function', | 79 chrome.test.assertEq('function', |
| 82 typeof webview[apiMethodsToCheck[i]]); | 80 typeof webview[apiMethodsToCheck[i]]); |
| 83 } | 81 } |
| 84 | 82 |
| 85 // Check contentWindow. | 83 // Check contentWindow. |
| 86 chrome.test.assertEq('object', typeof webview.contentWindow); | 84 chrome.test.assertEq('object', typeof webview.contentWindow); |
| 87 chrome.test.assertEq('function', | 85 chrome.test.assertEq('function', |
| 88 typeof webview.contentWindow.postMessage); | 86 typeof webview.contentWindow.postMessage); |
| 89 | 87 |
| 90 chrome.test.succeed(); | 88 chrome.test.succeed(); |
| 91 }, 0); | 89 }, 0); |
| 92 }, | 90 }, |
| 93 | 91 |
| 94 function webViewEventListeners() { | |
| 95 var webview = document.createElement('webview'); | |
| 96 webview.setAttribute('src', 'data:text/html,webview check api'); | |
| 97 document.body.appendChild(webview); | |
| 98 | |
| 99 var validEvents = [ | |
| 100 'exit', | |
| 101 'loadabort', | |
| 102 'loadredirect', | |
| 103 'loadstart', | |
| 104 'loadstop' | |
| 105 ]; | |
| 106 var invalidEvents = [ | |
| 107 'makemesandwich', | |
| 108 'sudomakemesandwich' | |
| 109 ]; | |
| 110 | |
| 111 // Timeout is necessary to give the mutation observers of the webview tag | |
| 112 // shim a chance to fire. | |
| 113 setTimeout(function() { | |
| 114 for (var i = 0; i < validEvents.length; ++i) { | |
| 115 chrome.test.assertTrue( | |
| 116 webview.addEventListener(validEvents[i], function() {})); | |
| 117 } | |
| 118 | |
| 119 for (var i = 0; i < invalidEvents.length; ++i) { | |
| 120 chrome.test.assertFalse( | |
| 121 webview.addEventListener(invalidEvents[i], function() {})); | |
| 122 } | |
| 123 | |
| 124 chrome.test.succeed(); | |
| 125 }, 0); | |
| 126 }, | |
| 127 | |
| 128 function webViewEventName() { | 92 function webViewEventName() { |
| 129 var webview = document.createElement('webview'); | 93 var webview = document.createElement('webview'); |
| 130 webview.setAttribute('src', 'data:text/html,webview check api'); | 94 webview.setAttribute('src', 'data:text/html,webview check api'); |
| 131 document.body.appendChild(webview); | 95 document.body.appendChild(webview); |
| 132 | 96 |
| 133 setTimeout(function() { | 97 webview.addEventListener('loadstart', function(evt) { |
| 134 webview.addEventListener('loadstart', function(evt) { | 98 chrome.test.assertEq('loadstart', evt.type); |
| 135 chrome.test.assertEq('loadstart', evt.name); | 99 }); |
| 136 }); | |
| 137 | 100 |
| 138 webview.addEventListener('loadstop', function(evt) { | 101 webview.addEventListener('loadstop', function(evt) { |
| 139 chrome.test.assertEq('loadstop', evt.name); | 102 chrome.test.assertEq('loadstop', evt.type); |
| 140 webview.terminate(); | 103 webview.terminate(); |
| 141 }); | 104 }); |
| 142 | 105 |
| 143 webview.addEventListener('exit', function(evt) { | 106 webview.addEventListener('exit', function(evt) { |
| 144 chrome.test.assertEq('exit', evt.name); | 107 chrome.test.assertEq('exit', evt.type); |
| 145 chrome.test.succeed(); | 108 chrome.test.succeed(); |
| 146 }); | 109 }); |
| 147 | 110 |
| 148 webview.setAttribute('src', 'data:text/html,trigger navigation'); | 111 webview.setAttribute('src', 'data:text/html,trigger navigation'); |
| 149 }, 0); | |
| 150 }, | 112 }, |
| 151 | 113 |
| 152 // This test registers two listeners on an event (loadcommit) and removes | 114 // This test registers two listeners on an event (loadcommit) and removes |
| 153 // the <webview> tag when the first listener fires. | 115 // the <webview> tag when the first listener fires. |
| 154 // Current expected behavior is that the second event listener will still | 116 // Current expected behavior is that the second event listener will still |
| 155 // fire (and we don't crash). | 117 // fire without crashing. |
| 156 function webviewDestroyOnEventListener() { | 118 function webviewDestroyOnEventListener() { |
| 157 var webview = util.createWebViewTagInDOM(); | 119 var webview = util.createWebViewTagInDOM(); |
| 158 var url = 'data:text/html,<body>Destroy test</body>'; | 120 var url = 'data:text/html,<body>Destroy test</body>'; |
| 159 | 121 |
| 160 var continuedAfterDelete = false; | |
| 161 var loadCommitCount = 0; | 122 var loadCommitCount = 0; |
| 162 var updateLoadCommitCount = function() { | 123 function loadCommitCommon(e) { |
| 124 chrome.test.assertEq('loadcommit', e.type); |
| 125 if (url != e.url) |
| 126 return; |
| 163 ++loadCommitCount; | 127 ++loadCommitCount; |
| 164 if (loadCommitCount == 1) { | 128 if (loadCommitCount == 1) { |
| 165 // We remove the <webview> tag when the first listener fires. | |
| 166 webview.parentNode.removeChild(webview); | 129 webview.parentNode.removeChild(webview); |
| 167 webview = null; | 130 webview = null; |
| 168 // Make sure the js executes after nulling |webview|. | 131 setTimeout(function() { |
| 169 continuedAfterDelete = true; | 132 chrome.test.succeed(); |
| 170 } else if (loadCommitCount == 2) { | 133 }, 0); |
| 171 chrome.test.assertTrue(continuedAfterDelete); | 134 } else if (loadCommitCount > 2) { |
| 172 chrome.test.succeed(); | |
| 173 } | |
| 174 }; | |
| 175 | |
| 176 var onLoadCommitA = function(e) { | |
| 177 chrome.test.assertEq('loadcommit', e.name); | |
| 178 if (e.url == url) { | |
| 179 updateLoadCommitCount(); | |
| 180 } | |
| 181 }; | |
| 182 var onLoadCommitB = function(e) { | |
| 183 chrome.test.assertEq('loadcommit', e.name); | |
| 184 if (e.url == url) { | |
| 185 updateLoadCommitCount(); | |
| 186 } | |
| 187 }; | |
| 188 | |
| 189 setTimeout(function() { | |
| 190 // The test starts from here, by setting the src to |url|. Event | |
| 191 // listener registration works because we already have a (dummy) src set | |
| 192 // on the <webview> tag. | |
| 193 webview.addEventListener('loadcommit', onLoadCommitA); | |
| 194 webview.addEventListener('loadcommit', onLoadCommitB); | |
| 195 webview.setAttribute('src', url); | |
| 196 }, 0); | |
| 197 }, | |
| 198 | |
| 199 // This test checks the current behavior of dynamic event listener | |
| 200 // registration 'during' an event listener fire. | |
| 201 // Once an event starts firing its listeners, any mutation to the list of | |
| 202 // event listeners for this event are deferred until all of the listeners | |
| 203 // have fired. | |
| 204 // | |
| 205 // Step1: Loads a guest with |urlStep1| with two listeners to 'loadcommit': | |
| 206 // onLoadCommitA and onLoadCommitB. When first of them fires, we try to | |
| 207 // remove the other and add a third listener (onLoadCommitC). | |
| 208 // Current expected behavior is these add/remove will be ignored and the | |
| 209 // original two listeners will fire. | |
| 210 // Step2: We change the guest to |urlStep2|. This will cause 'loadcommit' to | |
| 211 // fire with mutated event listeners list (that is one of | |
| 212 // onLoadCommitA/onLoadCommitB and onLoadCommitC). | |
| 213 function dynamicEventListenerRegistrationOnListenerFire() { | |
| 214 var urlStep1 = 'data:text/html,<body>Two</body>'; | |
| 215 var urlStep2 = 'data:text/html,<body>Three</body>'; | |
| 216 var webview = util.createWebViewTagInDOM(); | |
| 217 | |
| 218 var listenerFireCount1 = 0; // Step 1 listeners. | |
| 219 var listenerFireCount2 = 0; // Step 2 listeners. | |
| 220 | |
| 221 var loadCommitACalledStep1 = false; | |
| 222 var loadCommitBCalledStep1 = false; | |
| 223 | |
| 224 var loadCommitACalledStep2 = false; | |
| 225 var loadCommitBCalledStep2 = false; | |
| 226 var loadCommitCCalledStep2 = false; | |
| 227 | |
| 228 var expectAToFireInStep2; | |
| 229 var expectBToFireInStep2; | |
| 230 | |
| 231 var updateTestStateOnListenerStep1 = function() { | |
| 232 ++listenerFireCount1; | |
| 233 if (listenerFireCount1 == 1) { // First listener fire on Step 1. | |
| 234 chrome.test.assertTrue(loadCommitACalledStep1 || | |
| 235 loadCommitBCalledStep1); | |
| 236 // Add an event listener and remove one existing one when the first | |
| 237 // listener fires. Current implmementation does not expect any of | |
| 238 // these to be reflected before all event listeners are fired for the | |
| 239 // current event. | |
| 240 | |
| 241 // Remove. | |
| 242 if (loadCommitACalledStep1) { | |
| 243 webview.removeEventListener('loadcommit', onLoadCommitB); | |
| 244 expectAToFireInStep2 = true; | |
| 245 expectBToFireInStep2 = false; | |
| 246 } else { | |
| 247 webview.removeEventListener('loadcommit', onLoadCommitA); | |
| 248 expectAToFireInStep2 = false; | |
| 249 expectBToFireInStep2 = true; | |
| 250 } | |
| 251 // Add the other one. | |
| 252 webview.addEventListener('loadcommit', onLoadCommitC); | |
| 253 } else if (listenerFireCount1 == 2) { // Last listener fire on Step 1. | |
| 254 chrome.test.assertTrue(loadCommitACalledStep1 && | |
| 255 loadCommitBCalledStep1); | |
| 256 // Move to Step 2. | |
| 257 webview.setAttribute('src', urlStep2); | |
| 258 } else { | |
| 259 // More than expected listeners fired. | |
| 260 chrome.test.fail(); | 135 chrome.test.fail(); |
| 261 } | 136 } |
| 262 }; | 137 }; |
| 263 | 138 |
| 264 var updateTestStateOnListenerStep2 = function() { | 139 // The test starts from here, by setting the src to |url|. |
| 265 ++listenerFireCount2; | 140 webview.addEventListener('loadcommit', function(e) { |
| 266 if (listenerFireCount2 == 2) { | 141 loadCommitCommon(e); |
| 267 // Exactly one of onLoadCommitA and onLoadCommitB must be called. | 142 }); |
| 268 chrome.test.assertTrue(loadCommitACalledStep2 || | 143 webview.addEventListener('loadcommit', function(e) { |
| 269 loadCommitBCalledStep2); | 144 loadCommitCommon(e); |
| 270 // onLoadCommitC must be called. | 145 }); |
| 271 chrome.test.assertTrue(loadCommitCCalledStep2); | 146 webview.setAttribute('src', url); |
| 272 | |
| 273 chrome.test.succeed(); | |
| 274 } else if (listenerFireCount2 > 2) { | |
| 275 // More than expected listeners fired. | |
| 276 chrome.test.fail(); | |
| 277 } | |
| 278 }; | |
| 279 | |
| 280 var onLoadCommitA = function(e) { | |
| 281 chrome.test.assertEq('loadcommit', e.name); | |
| 282 switch (e.url) { | |
| 283 case urlStep1: // Step 1. | |
| 284 chrome.test.log('Step 1. onLoadCommitA'); | |
| 285 chrome.test.assertFalse(loadCommitACalledStep1); | |
| 286 loadCommitACalledStep1 = true; | |
| 287 | |
| 288 updateTestStateOnListenerStep1(); | |
| 289 break; | |
| 290 case urlStep2: // Step 2. | |
| 291 chrome.test.log('Step 2. onLoadCommitA'); | |
| 292 chrome.test.assertTrue(expectAToFireInStep2); | |
| 293 // Can be called at most once. | |
| 294 chrome.test.assertFalse(loadCommitACalledStep2); | |
| 295 loadCommitACalledStep2 = true; | |
| 296 | |
| 297 updateTestStateOnListenerStep2(); | |
| 298 break; | |
| 299 } | |
| 300 }; | |
| 301 | |
| 302 var onLoadCommitB = function(e) { | |
| 303 chrome.test.assertEq('loadcommit', e.name); | |
| 304 switch (e.url) { | |
| 305 case urlStep1: // Step 1. | |
| 306 chrome.test.log('Step 1. onLoadCommitB'); | |
| 307 chrome.test.assertFalse(loadCommitBCalledStep1); | |
| 308 loadCommitBCalledStep1 = true; | |
| 309 | |
| 310 updateTestStateOnListenerStep1(); | |
| 311 break; | |
| 312 case urlStep2: // Step 2. | |
| 313 chrome.test.log('Step 2. onLoadCommitB'); | |
| 314 chrome.test.assertTrue(expecBToFireInStep2); | |
| 315 // Can be called at most once. | |
| 316 chrome.test.assertFalse(loadCommitBCalledStep2); | |
| 317 loadCommitBCalledStep2 = true; | |
| 318 | |
| 319 updateTestStateOnListenerStep2(); | |
| 320 break; | |
| 321 } | |
| 322 }; | |
| 323 | |
| 324 var onLoadCommitC = function(e) { | |
| 325 chrome.test.assertEq('loadcommit', e.name); | |
| 326 switch (e.url) { | |
| 327 case urlStep1: // Step 1. | |
| 328 chrome.test.fail(); | |
| 329 break; | |
| 330 case urlStep2: // Step 2. | |
| 331 chrome.test.log('Step 2. onLoadCommitC'); | |
| 332 chrome.test.assertFalse(loadCommitCCalledStep2); | |
| 333 loadCommitCCalledStep2 = true; | |
| 334 | |
| 335 updateTestStateOnListenerStep2(); | |
| 336 break; | |
| 337 } | |
| 338 }; | |
| 339 | |
| 340 setTimeout(function() { | |
| 341 // The test starts from here, by setting the src to |urlStep1|. Event | |
| 342 // listener registration works because we already have a (dummy) src set | |
| 343 // on the <webview> tag. | |
| 344 webview.addEventListener('loadcommit', onLoadCommitA); | |
| 345 webview.addEventListener('loadcommit', onLoadCommitB); | |
| 346 webview.setAttribute('src', urlStep1); | |
| 347 }, 0); | |
| 348 }, | 147 }, |
| 349 | 148 |
| 350 // This test registers two event listeners on a same event (loadcommit). | 149 // This test registers two event listeners on a same event (loadcommit). |
| 351 // Each of the listener tries to change some properties on the event param, | 150 // Each of the listener tries to change some properties on the event param, |
| 352 // which should not be possible. | 151 // which should not be possible. |
| 353 function cannotMutateEventName() { | 152 function cannotMutateEventName() { |
| 354 var webview = util.createWebViewTagInDOM(); | 153 var webview = util.createWebViewTagInDOM(); |
| 355 var url = 'data:text/html,<body>Two</body>'; | 154 var url = 'data:text/html,<body>Two</body>'; |
| 356 | 155 |
| 357 var loadCommitACalled = false; | 156 var loadCommitACalled = false; |
| 358 var loadCommitBCalled = false; | 157 var loadCommitBCalled = false; |
| 359 | 158 |
| 360 var maybeFinishTest = function(e) { | 159 var maybeFinishTest = function(e) { |
| 361 if (loadCommitACalled && loadCommitBCalled) { | 160 if (loadCommitACalled && loadCommitBCalled) { |
| 362 chrome.test.assertEq('loadcommit', e.name); | 161 chrome.test.assertEq('loadcommit', e.type); |
| 363 chrome.test.assertTrue(e.isTopLevel); | |
| 364 chrome.test.succeed(); | 162 chrome.test.succeed(); |
| 365 } | 163 } |
| 366 }; | 164 }; |
| 367 | 165 |
| 368 var onLoadCommitA = function(e) { | 166 var onLoadCommitA = function(e) { |
| 369 if (e.url == url) { | 167 if (e.url == url) { |
| 370 chrome.test.assertEq('loadcommit', e.name); | 168 chrome.test.assertEq('loadcommit', e.type); |
| 371 chrome.test.assertTrue(e.isTopLevel); | 169 chrome.test.assertTrue(e.isTopLevel); |
| 372 chrome.test.assertFalse(loadCommitACalled); | 170 chrome.test.assertFalse(loadCommitACalled); |
| 373 loadCommitACalled = true; | 171 loadCommitACalled = true; |
| 374 // Try mucking with properities inside |e|. | 172 // Try mucking with properities inside |e|. |
| 375 e.name = 'modified'; | 173 e.type = 'modified'; |
| 376 e.isTopLevel = 'string-value'; | |
| 377 maybeFinishTest(e); | 174 maybeFinishTest(e); |
| 378 } | 175 } |
| 379 }; | 176 }; |
| 380 var onLoadCommitB = function(e) { | 177 var onLoadCommitB = function(e) { |
| 381 if (e.url == url) { | 178 if (e.url == url) { |
| 382 chrome.test.assertEq('loadcommit', e.name); | 179 chrome.test.assertEq('loadcommit', e.type); |
| 383 chrome.test.assertTrue(e.isTopLevel); | 180 chrome.test.assertTrue(e.isTopLevel); |
| 384 chrome.test.assertFalse(loadCommitBCalled); | 181 chrome.test.assertFalse(loadCommitBCalled); |
| 385 loadCommitBCalled = true; | 182 loadCommitBCalled = true; |
| 386 // Try mucking with properities inside |e|. | 183 // Try mucking with properities inside |e|. |
| 387 e.name = 'modified'; | 184 e.type = 'modified'; |
| 388 e.isTopLevel = 'string-value'; | |
| 389 maybeFinishTest(e); | 185 maybeFinishTest(e); |
| 390 } | 186 } |
| 391 }; | 187 }; |
| 392 | 188 |
| 393 setTimeout(function() { | 189 setTimeout(function() { |
| 394 // The test starts from here, by setting the src to |url|. Event | 190 // The test starts from here, by setting the src to |url|. Event |
| 395 // listener registration works because we already have a (dummy) src set | 191 // listener registration works because we already have a (dummy) src set |
| 396 // on the <webview> tag. | 192 // on the <webview> tag. |
| 397 webview.addEventListener('loadcommit', onLoadCommitA); | 193 webview.addEventListener('loadcommit', onLoadCommitA); |
| 398 webview.addEventListener('loadcommit', onLoadCommitB); | 194 webview.addEventListener('loadcommit', onLoadCommitB); |
| 399 webview.setAttribute('src', url); | 195 webview.setAttribute('src', url); |
| 400 }, 0); | 196 }, 0); |
| 401 } | 197 } |
| 402 ]); | 198 ]); |
| 403 }; | 199 }; |
| OLD | NEW |