зеркало из https://github.com/mozilla/gecko-dev.git
Bug 909129 - stop leaking imported scripts and don't import duplicates, r=jgriffin
This commit is contained in:
Родитель
809746b013
Коммит
8697a25b19
|
@ -1191,6 +1191,14 @@ class Marionette(object):
|
|||
js = f.read()
|
||||
return self._send_message('importScript', 'ok', script=js)
|
||||
|
||||
def clear_imported_scripts(self):
|
||||
'''
|
||||
Clears all imported scripts in this context, ie: calling clear_imported_scripts in chrome
|
||||
context will clear only scripts you imported in chrome, and will leave the scripts
|
||||
you imported in content context.
|
||||
'''
|
||||
return self._send_message('clearImportedScripts', 'ok')
|
||||
|
||||
def add_cookie(self, cookie):
|
||||
"""
|
||||
Adds a cookie to your current session.
|
||||
|
|
|
@ -1,18 +1,105 @@
|
|||
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
import os
|
||||
from marionette_test import MarionetteTestCase
|
||||
from errors import JavascriptException
|
||||
|
||||
class TestImportScript(MarionetteTestCase):
|
||||
def setUp(self):
|
||||
MarionetteTestCase.setUp(self)
|
||||
|
||||
def clear_other_context(self):
|
||||
self.marionette.set_context("chrome")
|
||||
self.marionette.clear_imported_scripts()
|
||||
self.marionette.set_context("content")
|
||||
|
||||
def check_file_exists(self):
|
||||
return self.marionette.execute_script("""
|
||||
let FileUtils = SpecialPowers.Cu.import("resource://gre/modules/FileUtils.jsm", {}).FileUtils;
|
||||
let importedScripts = FileUtils.getFile('TmpD', ['marionetteContentScripts']);
|
||||
return importedScripts.exists();
|
||||
""", special_powers=True)
|
||||
|
||||
def get_file_size(self):
|
||||
return self.marionette.execute_script("""
|
||||
let FileUtils = SpecialPowers.Cu.import("resource://gre/modules/FileUtils.jsm", {}).FileUtils;
|
||||
let importedScripts = FileUtils.getFile('TmpD', ['marionetteContentScripts']);
|
||||
return importedScripts.fileSize;
|
||||
""", special_powers=True)
|
||||
|
||||
def test_import_script(self):
|
||||
js = os.path.abspath(os.path.join(__file__, os.path.pardir, "importscript.js"))
|
||||
self.marionette.import_script(js)
|
||||
self.assertEqual("i'm a test function!", self.marionette.execute_script("return testFunc();"))
|
||||
self.assertEqual("i'm a test function!", self.marionette.execute_async_script("marionetteScriptFinished(testFunc());"))
|
||||
|
||||
def test_import_script_twice(self):
|
||||
js = os.path.abspath(os.path.join(__file__, os.path.pardir, "importscript.js"))
|
||||
self.marionette.import_script(js)
|
||||
self.assertEqual("i'm a test function!", self.marionette.execute_script("return testFunc();"))
|
||||
self.assertEqual("i'm a test function!", self.marionette.execute_async_script("marionetteScriptFinished(testFunc());"))
|
||||
self.assertTrue(self.check_file_exists())
|
||||
file_size = self.get_file_size()
|
||||
self.assertNotEqual(file_size, None)
|
||||
self.marionette.import_script(js)
|
||||
file_size = self.get_file_size()
|
||||
self.assertEqual(file_size, self.get_file_size())
|
||||
self.assertEqual("i'm a test function!", self.marionette.execute_script("return testFunc();"))
|
||||
self.assertEqual("i'm a test function!", self.marionette.execute_async_script("marionetteScriptFinished(testFunc());"))
|
||||
|
||||
def test_import_two_scripts_twice(self):
|
||||
js = os.path.abspath(os.path.join(__file__, os.path.pardir, "importscript.js"))
|
||||
self.marionette.import_script(js)
|
||||
self.assertEqual("i'm a test function!", self.marionette.execute_script("return testFunc();"))
|
||||
self.assertEqual("i'm a test function!", self.marionette.execute_async_script("marionetteScriptFinished(testFunc());"))
|
||||
self.assertTrue(self.check_file_exists())
|
||||
file_size = self.get_file_size()
|
||||
self.assertNotEqual(file_size, None)
|
||||
self.marionette.import_script(js)
|
||||
# same script should not append to file
|
||||
self.assertEqual(file_size, self.get_file_size())
|
||||
self.assertEqual("i'm a test function!", self.marionette.execute_script("return testFunc();"))
|
||||
self.assertEqual("i'm a test function!", self.marionette.execute_async_script("marionetteScriptFinished(testFunc());"))
|
||||
js = os.path.abspath(os.path.join(__file__, os.path.pardir, "importanotherscript.js"))
|
||||
self.marionette.import_script(js)
|
||||
new_size = self.get_file_size()
|
||||
# new script should append to file
|
||||
self.assertNotEqual(file_size, new_size)
|
||||
file_size = new_size
|
||||
self.assertEqual("i'm yet another test function!",
|
||||
self.marionette.execute_script("return testAnotherFunc();"))
|
||||
self.assertEqual("i'm yet another test function!",
|
||||
self.marionette.execute_async_script("marionetteScriptFinished(testAnotherFunc());"))
|
||||
self.marionette.import_script(js)
|
||||
# same script should not append to file
|
||||
self.assertEqual(file_size, self.get_file_size())
|
||||
|
||||
def test_import_script_and_clear(self):
|
||||
js = os.path.abspath(os.path.join(__file__, os.path.pardir, "importscript.js"))
|
||||
self.marionette.import_script(js)
|
||||
self.assertEqual("i'm a test function!", self.marionette.execute_script("return testFunc();"))
|
||||
self.assertEqual("i'm a test function!", self.marionette.execute_async_script("marionetteScriptFinished(testFunc());"))
|
||||
self.marionette.clear_imported_scripts()
|
||||
self.assertFalse(self.check_file_exists())
|
||||
self.assertRaises(JavascriptException, self.marionette.execute_script, "return testFunc();")
|
||||
self.assertRaises(JavascriptException, self.marionette.execute_async_script, "marionetteScriptFinished(testFunc());")
|
||||
|
||||
def test_import_script_and_clear_in_chrome(self):
|
||||
js = os.path.abspath(os.path.join(__file__, os.path.pardir, "importscript.js"))
|
||||
self.marionette.import_script(js)
|
||||
self.assertTrue(self.check_file_exists())
|
||||
file_size = self.get_file_size()
|
||||
self.assertEqual("i'm a test function!", self.marionette.execute_script("return testFunc();"))
|
||||
self.assertEqual("i'm a test function!", self.marionette.execute_async_script("marionetteScriptFinished(testFunc());"))
|
||||
self.clear_other_context()
|
||||
# clearing other context's script file should not affect ours
|
||||
self.assertTrue(self.check_file_exists())
|
||||
self.assertEqual(file_size, self.get_file_size())
|
||||
self.assertEqual("i'm a test function!", self.marionette.execute_script("return testFunc();"))
|
||||
self.assertEqual("i'm a test function!", self.marionette.execute_async_script("marionetteScriptFinished(testFunc());"))
|
||||
|
||||
def test_importing_another_script_and_check_they_append(self):
|
||||
firstjs = os.path.abspath(
|
||||
os.path.join(__file__, os.path.pardir, "importscript.js"))
|
||||
|
@ -31,4 +118,25 @@ class TestImportScript(MarionetteTestCase):
|
|||
class TestImportScriptChrome(TestImportScript):
|
||||
def setUp(self):
|
||||
MarionetteTestCase.setUp(self)
|
||||
self.marionette.set_script_timeout(30000)
|
||||
self.marionette.set_context("chrome")
|
||||
|
||||
def clear_other_context(self):
|
||||
self.marionette.set_context("content")
|
||||
self.marionette.clear_imported_scripts()
|
||||
self.marionette.set_context("chrome")
|
||||
|
||||
def check_file_exists(self):
|
||||
return self.marionette.execute_async_script("""
|
||||
let FileUtils = Components.utils.import("resource://gre/modules/FileUtils.jsm", {}).FileUtils;
|
||||
let importedScripts = FileUtils.getFile('TmpD', ['marionetteChromeScripts']);
|
||||
marionetteScriptFinished(importedScripts.exists());
|
||||
""")
|
||||
|
||||
def get_file_size(self):
|
||||
return self.marionette.execute_async_script("""
|
||||
let FileUtils = Components.utils.import("resource://gre/modules/FileUtils.jsm", {}).FileUtils;
|
||||
let importedScripts = FileUtils.getFile('TmpD', ['marionetteChromeScripts']);
|
||||
marionetteScriptFinished(importedScripts.fileSize);
|
||||
""")
|
||||
|
||||
|
|
|
@ -98,7 +98,7 @@ function registerSelf() {
|
|||
|
||||
if (register[0]) {
|
||||
listenerId = register[0].id;
|
||||
importedScripts = FileUtils.File(register[0].importedScripts);
|
||||
importedScripts = FileUtils.getFile('TmpD', ['marionetteContentScripts']);
|
||||
startListeners();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -134,7 +134,8 @@ function MarionetteServerConnection(aPrefix, aTransport, aServer)
|
|||
this.command_id = null;
|
||||
this.mainFrame = null; //topmost chrome frame
|
||||
this.curFrame = null; // chrome iframe that currently has focus
|
||||
this.importedScripts = FileUtils.getFile('TmpD', ['marionettescriptchrome']);
|
||||
this.importedScripts = FileUtils.getFile('TmpD', ['marionetteChromeScripts']);
|
||||
this.importedScriptHashes = {"chrome" : [], "content": []};
|
||||
this.currentFrameElement = null;
|
||||
this.testName = null;
|
||||
this.mozBrowserClose = null;
|
||||
|
@ -465,6 +466,16 @@ MarionetteServerConnection.prototype = {
|
|||
return this.uuidGen.generateUUID().toString();
|
||||
},
|
||||
|
||||
/**
|
||||
* Given a file name, this will delete the file from the temp directory if it exists
|
||||
*/
|
||||
deleteFile: function(filename) {
|
||||
let file = FileUtils.getFile('TmpD', [filename.toString()]);
|
||||
if (file.exists()) {
|
||||
file.remove(true);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Marionette API:
|
||||
*
|
||||
|
@ -1947,7 +1958,13 @@ MarionetteServerConnection.prototype = {
|
|||
|
||||
// if there is only 1 window left, delete the session
|
||||
if (numOpenWindows === 1){
|
||||
this.sessionTearDown();
|
||||
try {
|
||||
this.sessionTearDown();
|
||||
}
|
||||
catch (e) {
|
||||
this.sendError("Could not clear session", 500, e.name + ": " + e.message, command_id);
|
||||
return;
|
||||
}
|
||||
this.sendOk(command_id);
|
||||
return;
|
||||
}
|
||||
|
@ -2004,20 +2021,23 @@ MarionetteServerConnection.prototype = {
|
|||
if (this.mainFrame) {
|
||||
this.mainFrame.focus();
|
||||
}
|
||||
try {
|
||||
this.importedScripts.remove(false);
|
||||
}
|
||||
catch (e) {
|
||||
}
|
||||
this.deleteFile('marionetteChromeScripts');
|
||||
this.deleteFile('marionetteContentScripts');
|
||||
},
|
||||
|
||||
/**
|
||||
* Processes the 'deleteSession' request from the client by tearing down
|
||||
* the session and responding 'ok'.
|
||||
*/
|
||||
deleteSession: function MDA_sessionTearDown() {
|
||||
deleteSession: function MDA_deleteSession() {
|
||||
let command_id = this.command_id = this.getCommandId();
|
||||
this.sessionTearDown();
|
||||
try {
|
||||
this.sessionTearDown();
|
||||
}
|
||||
catch (e) {
|
||||
this.sendError("Could not delete session", 500, e.name + ": " + e.message, command_id);
|
||||
return;
|
||||
}
|
||||
this.sendOk(command_id);
|
||||
},
|
||||
|
||||
|
@ -2068,6 +2088,23 @@ MarionetteServerConnection.prototype = {
|
|||
|
||||
importScript: function MDA_importScript(aRequest) {
|
||||
let command_id = this.command_id = this.getCommandId();
|
||||
let converter =
|
||||
Components.classes["@mozilla.org/intl/scriptableunicodeconverter"].
|
||||
createInstance(Components.interfaces.nsIScriptableUnicodeConverter);
|
||||
converter.charset = "UTF-8";
|
||||
let result = {};
|
||||
let data = converter.convertToByteArray(aRequest.parameters.script, result);
|
||||
let ch = Components.classes["@mozilla.org/security/hash;1"]
|
||||
.createInstance(Components.interfaces.nsICryptoHash);
|
||||
ch.init(ch.MD5);
|
||||
ch.update(data, data.length);
|
||||
let hash = ch.finish(true);
|
||||
if (this.importedScriptHashes[this.context].indexOf(hash) > -1) {
|
||||
//we have already imported this script
|
||||
this.sendOk(command_id);
|
||||
return;
|
||||
}
|
||||
this.importedScriptHashes[this.context].push(hash);
|
||||
if (this.context == "chrome") {
|
||||
let file;
|
||||
if (this.importedScripts.exists()) {
|
||||
|
@ -2093,6 +2130,23 @@ MarionetteServerConnection.prototype = {
|
|||
}
|
||||
},
|
||||
|
||||
clearImportedScripts: function MDA_clearImportedScripts(aRequest) {
|
||||
let command_id = this.command_id = this.getCommandId();
|
||||
try {
|
||||
if (this.context == "chrome") {
|
||||
this.deleteFile('marionetteChromeScripts');
|
||||
}
|
||||
else {
|
||||
this.deleteFile('marionetteContentScripts');
|
||||
}
|
||||
}
|
||||
catch (e) {
|
||||
this.sendError("Could not clear imported scripts", 500, e.name + ": " + e.message, command_id);
|
||||
return;
|
||||
}
|
||||
this.sendOk(command_id);
|
||||
},
|
||||
|
||||
/**
|
||||
* Takes a screenshot of a DOM node. If there is no node given a screenshot
|
||||
* of the window will be taken.
|
||||
|
@ -2210,7 +2264,6 @@ MarionetteServerConnection.prototype = {
|
|||
listenerWindow);
|
||||
}
|
||||
this.curBrowser.elementManager.seenItems[reg.id] = Cu.getWeakReference(listenerWindow);
|
||||
reg.importedScripts = this.importedScripts.path;
|
||||
if (nullPrevious && (this.curBrowser.curFrameId != null)) {
|
||||
if (!this.sendAsync("newSession",
|
||||
{ B2G: (appName == "B2G") },
|
||||
|
@ -2276,6 +2329,7 @@ MarionetteServerConnection.prototype.requestTypes = {
|
|||
"deleteSession": MarionetteServerConnection.prototype.deleteSession,
|
||||
"emulatorCmdResult": MarionetteServerConnection.prototype.emulatorCmdResult,
|
||||
"importScript": MarionetteServerConnection.prototype.importScript,
|
||||
"clearImportedScripts": MarionetteServerConnection.prototype.clearImportedScripts,
|
||||
"getAppCacheStatus": MarionetteServerConnection.prototype.getAppCacheStatus,
|
||||
"closeWindow": MarionetteServerConnection.prototype.closeWindow,
|
||||
"setTestName": MarionetteServerConnection.prototype.setTestName,
|
||||
|
|
Загрузка…
Ссылка в новой задаче