Merge from mozilla-central.
@ -75,7 +75,7 @@ protected:
|
||||
/**
|
||||
* The document accessible reference owning this queue.
|
||||
*/
|
||||
nsRefPtr<DocAccessible> mDocument;
|
||||
DocAccessible* mDocument;
|
||||
|
||||
/**
|
||||
* Pending events array. Don't make this an nsAutoTArray; we use
|
||||
|
@ -54,7 +54,6 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(NotificationController)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(NotificationController)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDocument)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mHangingChildDocuments)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mContentInsertions)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mEvents)
|
||||
|
@ -1757,6 +1757,7 @@ DocAccessible::UpdateTree(Accessible* aContainer, nsIContent* aChildNode,
|
||||
// XXX: since select change insertion point of option contained by optgroup
|
||||
// then we need to have special processing for them (bug 690417).
|
||||
if (!aIsInsert && aChildNode->IsHTML(nsGkAtoms::optgroup) &&
|
||||
aContainer->GetContent() &&
|
||||
aContainer->GetContent()->IsHTML(nsGkAtoms::select)) {
|
||||
for (nsIContent* optContent = aChildNode->GetFirstChild(); optContent;
|
||||
optContent = optContent->GetNextSibling()) {
|
||||
|
@ -1,30 +1,30 @@
|
||||
The files which make up the SDK are developed by Mozilla and licensed
|
||||
under the MPL 2.0 (http://mozilla.org/MPL/2.0/), with the exception of the
|
||||
components listed below, which are made available by their authors under
|
||||
the licenses listed alongside.
|
||||
|
||||
syntaxhighlighter
|
||||
------------------
|
||||
doc/static-files/syntaxhighlighter
|
||||
Made available under the MIT license.
|
||||
|
||||
jQuery
|
||||
------
|
||||
examples/reddit-panel/data/jquery-1.4.4.min.js
|
||||
examples/annotator/data/jquery-1.4.2.min.js
|
||||
Made available under the MIT license.
|
||||
|
||||
simplejson
|
||||
----------
|
||||
python-lib/simplejson
|
||||
Made available under the MIT license.
|
||||
|
||||
Python Markdown
|
||||
---------------
|
||||
python-lib/markdown
|
||||
Made available under the BSD license.
|
||||
|
||||
LibraryDetector
|
||||
---------------
|
||||
examples/library-detector/data/library-detector.js
|
||||
Made available under the MIT license.
|
||||
The files which make up the SDK are developed by Mozilla and licensed
|
||||
under the MPL 2.0 (http://mozilla.org/MPL/2.0/), with the exception of the
|
||||
components listed below, which are made available by their authors under
|
||||
the licenses listed alongside.
|
||||
|
||||
syntaxhighlighter
|
||||
------------------
|
||||
doc/static-files/syntaxhighlighter
|
||||
Made available under the MIT license.
|
||||
|
||||
jQuery
|
||||
------
|
||||
examples/reddit-panel/data/jquery-1.4.4.min.js
|
||||
examples/annotator/data/jquery-1.4.2.min.js
|
||||
Made available under the MIT license.
|
||||
|
||||
simplejson
|
||||
----------
|
||||
python-lib/simplejson
|
||||
Made available under the MIT license.
|
||||
|
||||
Python Markdown
|
||||
---------------
|
||||
python-lib/markdown
|
||||
Made available under the BSD license.
|
||||
|
||||
LibraryDetector
|
||||
---------------
|
||||
examples/library-detector/data/library-detector.js
|
||||
Made available under the MIT license.
|
||||
|
@ -1,45 +1,45 @@
|
||||
Add-on SDK README
|
||||
==================
|
||||
|
||||
Before proceeding, please make sure you've installed Python 2.5,
|
||||
2.6, or 2.7 (if it's not already on your system):
|
||||
|
||||
http://python.org/download/
|
||||
|
||||
Note that Python 3.0 and 3.1 are not supported in this release.
|
||||
|
||||
For Windows users, MozillaBuild (https://wiki.mozilla.org/MozillaBuild)
|
||||
will install the correct version of Python and the MSYS package, which
|
||||
will make it easier to work with the SDK.
|
||||
|
||||
To get started, first enter the same directory that this README file
|
||||
is in (the SDK's root directory) using a shell program. On Unix systems
|
||||
or on Windows with MSYS, you can execute the following command:
|
||||
|
||||
source bin/activate
|
||||
|
||||
Windows users using cmd.exe should instead run:
|
||||
|
||||
bin\activate.bat
|
||||
|
||||
Then run:
|
||||
|
||||
cfx docs
|
||||
|
||||
This should start a documentation server and open a web browser
|
||||
with further instructions.
|
||||
|
||||
If you get an error when running cfx or have any other problems getting
|
||||
started, see the "Troubleshooting" guide at:
|
||||
https://addons.mozilla.org/en-US/developers/docs/sdk/latest/dev-guide/tutorials/troubleshooting.html
|
||||
|
||||
Bugs
|
||||
-------
|
||||
|
||||
* file a bug: https://bugzilla.mozilla.org/enter_bug.cgi?product=Add-on%20SDK
|
||||
|
||||
|
||||
Style Guidelines
|
||||
--------------------
|
||||
|
||||
Add-on SDK README
|
||||
==================
|
||||
|
||||
Before proceeding, please make sure you've installed Python 2.5,
|
||||
2.6, or 2.7 (if it's not already on your system):
|
||||
|
||||
http://python.org/download/
|
||||
|
||||
Note that Python 3.0 and 3.1 are not supported in this release.
|
||||
|
||||
For Windows users, MozillaBuild (https://wiki.mozilla.org/MozillaBuild)
|
||||
will install the correct version of Python and the MSYS package, which
|
||||
will make it easier to work with the SDK.
|
||||
|
||||
To get started, first enter the same directory that this README file
|
||||
is in (the SDK's root directory) using a shell program. On Unix systems
|
||||
or on Windows with MSYS, you can execute the following command:
|
||||
|
||||
source bin/activate
|
||||
|
||||
Windows users using cmd.exe should instead run:
|
||||
|
||||
bin\activate.bat
|
||||
|
||||
Then run:
|
||||
|
||||
cfx docs
|
||||
|
||||
This should start a documentation server and open a web browser
|
||||
with further instructions.
|
||||
|
||||
If you get an error when running cfx or have any other problems getting
|
||||
started, see the "Troubleshooting" guide at:
|
||||
https://addons.mozilla.org/en-US/developers/docs/sdk/latest/dev-guide/tutorials/troubleshooting.html
|
||||
|
||||
Bugs
|
||||
-------
|
||||
|
||||
* file a bug: https://bugzilla.mozilla.org/enter_bug.cgi?product=Add-on%20SDK
|
||||
|
||||
|
||||
Style Guidelines
|
||||
--------------------
|
||||
|
||||
* https://github.com/mozilla/addon-sdk/wiki/Coding-style-guide
|
||||
|
58
addon-sdk/source/app-extension/bootstrap.js
vendored
@ -19,6 +19,13 @@ const resourceHandler = ioService.getProtocolHandler('resource').
|
||||
const systemPrincipal = CC('@mozilla.org/systemprincipal;1', 'nsIPrincipal')();
|
||||
const scriptLoader = Cc['@mozilla.org/moz/jssubscript-loader;1'].
|
||||
getService(Ci.mozIJSSubScriptLoader);
|
||||
const prefService = Cc['@mozilla.org/preferences-service;1'].
|
||||
getService(Ci.nsIPrefService);
|
||||
const appInfo = Cc["@mozilla.org/xre/app-info;1"].
|
||||
getService(Ci.nsIXULAppInfo);
|
||||
const vc = Cc["@mozilla.org/xpcom/version-comparator;1"].
|
||||
getService(Ci.nsIVersionComparator);
|
||||
|
||||
|
||||
const REASON = [ 'unknown', 'startup', 'shutdown', 'enable', 'disable',
|
||||
'install', 'uninstall', 'upgrade', 'downgrade' ];
|
||||
@ -120,19 +127,54 @@ function startup(data, reasonCode) {
|
||||
if (name == 'addon-sdk')
|
||||
paths['tests/'] = prefixURI + name + '/tests/';
|
||||
|
||||
// Maps sdk module folders to their resource folder
|
||||
paths['sdk/'] = prefixURI + 'addon-sdk/lib/sdk/';
|
||||
paths['toolkit/'] = prefixURI + 'addon-sdk/lib/toolkit/';
|
||||
// test.js is usually found in root commonjs or SDK_ROOT/lib/ folder,
|
||||
// so that it isn't shipped in the xpi. Keep a copy of it in sdk/ folder
|
||||
// until we no longer support SDK modules in XPI:
|
||||
paths['test'] = prefixURI + 'addon-sdk/lib/sdk/test.js';
|
||||
// Starting with Firefox 21.0a1, we start using modules shipped into firefox
|
||||
// Still allow using modules from the xpi if the manifest tell us to do so.
|
||||
// And only try to look for sdk modules in xpi if the xpi actually ship them
|
||||
if (options['is-sdk-bundled'] &&
|
||||
(vc.compare(appInfo.version, '21.0a1') < 0 ||
|
||||
options['force-use-bundled-sdk'])) {
|
||||
// Maps sdk module folders to their resource folder
|
||||
paths[''] = prefixURI + 'addon-sdk/lib/';
|
||||
// test.js is usually found in root commonjs or SDK_ROOT/lib/ folder,
|
||||
// so that it isn't shipped in the xpi. Keep a copy of it in sdk/ folder
|
||||
// until we no longer support SDK modules in XPI:
|
||||
paths['test'] = prefixURI + 'addon-sdk/lib/sdk/test.js';
|
||||
}
|
||||
|
||||
// Retrieve list of module folder overloads based on preferences in order to
|
||||
// eventually used a local modules instead of files shipped into Firefox.
|
||||
let branch = prefService.getBranch('extensions.modules.' + id + '.path');
|
||||
paths = branch.getChildList('', {}).reduce(function (result, name) {
|
||||
// Allows overloading of any sub folder by replacing . by / in pref name
|
||||
let path = name.substr(1).split('.').join('/');
|
||||
// Only accept overloading folder by ensuring always ending with `/`
|
||||
if (path) path += '/';
|
||||
let fileURI = branch.getCharPref(name);
|
||||
|
||||
// Maps the given file:// URI to a resource:// in order to avoid various
|
||||
// failure that happens with file:// URI and be close to production env
|
||||
let resourcesURI = ioService.newURI(fileURI, null, null);
|
||||
let resName = 'extensions.modules.' + domain + '.commonjs.path' + name;
|
||||
resourceHandler.setSubstitution(resName, resourcesURI);
|
||||
|
||||
result[path] = 'resource://' + resName + '/';
|
||||
return result;
|
||||
}, paths);
|
||||
|
||||
// Make version 2 of the manifest
|
||||
let manifest = options.manifest;
|
||||
|
||||
// Import `cuddlefish.js` module using a Sandbox and bootstrap loader.
|
||||
let cuddlefishURI = prefixURI + options.loader;
|
||||
let cuddlefishPath = 'loader/cuddlefish.js';
|
||||
let cuddlefishURI = 'resource://gre/modules/commonjs/sdk/' + cuddlefishPath;
|
||||
if (paths['sdk/']) { // sdk folder has been overloaded
|
||||
// (from pref, or cuddlefish is still in the xpi)
|
||||
cuddlefishURI = paths['sdk/'] + cuddlefishPath;
|
||||
}
|
||||
else if (paths['']) { // root modules folder has been overloaded
|
||||
cuddlefishURI = paths[''] + 'sdk/' + cuddlefishPath;
|
||||
}
|
||||
|
||||
cuddlefishSandbox = loadSandbox(cuddlefishURI);
|
||||
let cuddlefish = cuddlefishSandbox.exports;
|
||||
|
||||
|
@ -1,364 +1,364 @@
|
||||
#!/usr/bin/env python
|
||||
# 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
|
||||
import signal
|
||||
import threading
|
||||
import urllib2, urllib
|
||||
import zipfile
|
||||
import tarfile
|
||||
import subprocess
|
||||
import optparse
|
||||
import sys, re
|
||||
#import win32api
|
||||
|
||||
|
||||
class SDK:
|
||||
def __init__(self):
|
||||
try:
|
||||
# Take the current working directory
|
||||
self.default_path = os.getcwd()
|
||||
if sys.platform == "win32":
|
||||
self.mswindows = True
|
||||
else:
|
||||
self.mswindows = False
|
||||
# Take the default home path of the user.
|
||||
home = os.path.expanduser('~')
|
||||
|
||||
# The following are the parameters that can be used to pass a dynamic URL, a specific path or a binry. The binary is not used yet. It will be used in version 2.0
|
||||
# If a dynamic path is to be mentioned, it should start with a '/'. For eg. "/Desktop"
|
||||
parser = optparse.OptionParser()
|
||||
parser.add_option('-u', '--url', dest = 'url', default = 'https://ftp.mozilla.org/pub/mozilla.org/labs/jetpack/addon-sdk-latest.zip')
|
||||
parser.add_option('-p', '--path', dest = 'path', default = self.default_path)
|
||||
parser.add_option('-b', '--binary', dest = 'binary')#, default='/Applications/Firefox.app')
|
||||
(options, args) = parser.parse_args()
|
||||
|
||||
# Get the URL from the parameter
|
||||
self.link = options.url
|
||||
# Set the base path for the user. If the user supplies the path, use the home variable as well. Else, take the default path of this script as the installation directory.
|
||||
if options.path!=self.default_path:
|
||||
if self.mswindows:
|
||||
self.base_path = home + str(options.path).strip() + '\\'
|
||||
else:
|
||||
self.base_path = home + str(options.path).strip() + '/'
|
||||
else:
|
||||
if self.mswindows:
|
||||
self.base_path = str(options.path).strip() + '\\'
|
||||
else:
|
||||
self.base_path = str(options.path).strip() + '/'
|
||||
assert ' ' not in self.base_path, "You cannot have a space in your home path. Please remove the space before you continue."
|
||||
print('Your Base path is =' + self.base_path)
|
||||
|
||||
# This assignment is not used in this program. It will be used in version 2 of this script.
|
||||
self.bin = options.binary
|
||||
# if app or bin is empty, dont pass anything
|
||||
|
||||
# Search for the .zip file or tarball file in the URL.
|
||||
i = self.link.rfind('/')
|
||||
|
||||
self.fname = self.link[i+1:]
|
||||
z = re.search('zip',self.fname,re.I)
|
||||
g = re.search('gz',self.fname,re.I)
|
||||
if z:
|
||||
print 'zip file present in the URL.'
|
||||
self.zip = True
|
||||
self.gz = False
|
||||
elif g:
|
||||
print 'gz file present in the URL'
|
||||
self.gz = True
|
||||
self.zip = False
|
||||
else:
|
||||
print 'zip/gz file not present. Check the URL.'
|
||||
return
|
||||
print("File name is =" + self.fname)
|
||||
|
||||
# Join the base path and the zip/tar file name to crate a complete Local file path.
|
||||
self.fpath = self.base_path + self.fname
|
||||
print('Your local file path will be=' + self.fpath)
|
||||
except AssertionError, e:
|
||||
print e.args[0]
|
||||
sys.exit(1)
|
||||
|
||||
# Download function - to download the SDK from the URL to the local machine.
|
||||
def download(self,url,fpath,fname):
|
||||
try:
|
||||
# Start the download
|
||||
print("Downloading...Please be patient!")
|
||||
urllib.urlretrieve(url,filename = fname)
|
||||
print('Download was successful.')
|
||||
except ValueError: # Handles broken URL errors.
|
||||
print 'The URL is ether broken or the file does not exist. Please enter the correct URL.'
|
||||
raise
|
||||
except urllib2.URLError: # Handles URL errors
|
||||
print '\nURL not correct. Check again!'
|
||||
raise
|
||||
|
||||
# Function to extract the downloaded zipfile.
|
||||
def extract(self, zipfilepath, extfile):
|
||||
try:
|
||||
# Timeout is set to 30 seconds.
|
||||
timeout = 30
|
||||
# Change the directory to the location of the zip file.
|
||||
try:
|
||||
os.chdir(zipfilepath)
|
||||
except OSError:
|
||||
# Will reach here if zip file doesnt exist
|
||||
print 'O/S Error:' + zipfilepath + 'does not exist'
|
||||
raise
|
||||
|
||||
# Get the folder name of Jetpack to get the exact version number.
|
||||
if self.zip:
|
||||
try:
|
||||
f = zipfile.ZipFile(extfile, "r")
|
||||
except IOError as (errno, strerror): # Handles file errors
|
||||
print "I/O error - Cannot perform extract operation: {1}".format(errno, strerror)
|
||||
raise
|
||||
list = f.namelist()[0]
|
||||
temp_name = list.split('/')
|
||||
print('Folder Name= ' +temp_name[0])
|
||||
self.folder_name = temp_name[0]
|
||||
elif self.gz:
|
||||
try:
|
||||
f = tarfile.open(extfile,'r')
|
||||
except IOError as (errno, strerror): # Handles file errors
|
||||
print "I/O error - Cannot perform extract operation: {1}".format(errno, strerror)
|
||||
raise
|
||||
list = f.getnames()[0]
|
||||
temp_name = list.split('/')
|
||||
print('Folder Name= ' +temp_name[0])
|
||||
self.folder_name = temp_name[0]
|
||||
|
||||
print ('Starting to Extract...')
|
||||
|
||||
# Timeout code. The subprocess.popen exeutes the command and the thread waits for a timeout. If the process does not finish within the mentioned-
|
||||
# timeout, the process is killed.
|
||||
kill_check = threading.Event()
|
||||
|
||||
if self.zip:
|
||||
# Call the command to unzip the file.
|
||||
if self.mswindows:
|
||||
zipfile.ZipFile.extractall(f)
|
||||
else:
|
||||
p = subprocess.Popen('unzip '+extfile, stdout=subprocess.PIPE, shell=True)
|
||||
pid = p.pid
|
||||
elif self.gz:
|
||||
# Call the command to untar the file.
|
||||
if self.mswindows:
|
||||
tarfile.TarFile.extractall(f)
|
||||
else:
|
||||
p = subprocess.Popen('tar -xf '+extfile, stdout=subprocess.PIPE, shell=True)
|
||||
pid = p.pid
|
||||
|
||||
#No need to handle for windows because windows automatically replaces old files with new files. It does not ask the user(as it does in Mac/Unix)
|
||||
if self.mswindows==False:
|
||||
watch = threading.Timer(timeout, kill_process, args=(pid, kill_check, self.mswindows ))
|
||||
watch.start()
|
||||
(stdout, stderr) = p.communicate()
|
||||
watch.cancel() # if it's still waiting to run
|
||||
success = not kill_check.isSet()
|
||||
|
||||
# Abort process if process fails.
|
||||
if not success:
|
||||
raise RuntimeError
|
||||
kill_check.clear()
|
||||
print('Extraction Successful.')
|
||||
except RuntimeError:
|
||||
print "Ending the program"
|
||||
sys.exit(1)
|
||||
except:
|
||||
print "Error during file extraction: ", sys.exc_info()[0]
|
||||
raise
|
||||
|
||||
# Function to run the cfx testall comands and to make sure the SDK is not broken.
|
||||
def run_testall(self, home_path, folder_name):
|
||||
try:
|
||||
timeout = 500
|
||||
|
||||
self.new_dir = home_path + folder_name
|
||||
try:
|
||||
os.chdir(self.new_dir)
|
||||
except OSError:
|
||||
# Will reach here if the jetpack 0.X directory doesnt exist
|
||||
print 'O/S Error: Jetpack directory does not exist at ' + self.new_dir
|
||||
raise
|
||||
print '\nStarting tests...'
|
||||
# Timeout code. The subprocess.popen exeutes the command and the thread waits for a timeout. If the process does not finish within the mentioned-
|
||||
# timeout, the process is killed.
|
||||
kill_check = threading.Event()
|
||||
|
||||
# Set the path for the logs. They will be in the parent directory of the Jetpack SDK.
|
||||
log_path = home_path + 'tests.log'
|
||||
|
||||
# Subprocess call to set up the jetpack environment and to start the tests. Also sends the output to a log file.
|
||||
if self.bin != None:
|
||||
if self.mswindows:
|
||||
p = subprocess.Popen("bin\\activate && cfx testall -a firefox -b \"" + self.bin + "\"" , stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
|
||||
proc_handle = p._handle
|
||||
(stdout,stderr) = p.communicate()
|
||||
else:
|
||||
p = subprocess.Popen('. bin/activate; cfx testall -a firefox -b ' + self.bin , stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
|
||||
pid = p.pid
|
||||
(stdout,stderr) = p.communicate()
|
||||
elif self.bin == None:
|
||||
if self.mswindows:
|
||||
p=subprocess.Popen('bin\\activate && cfx testall -a firefox > '+log_path, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
|
||||
proc_handle = p._handle
|
||||
(stdout,stderr) = p.communicate()
|
||||
else:
|
||||
p = subprocess.Popen('. bin/activate; cfx testall -a firefox > '+log_path, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
|
||||
pid = p.pid
|
||||
(stdout,stderr) = p.communicate()
|
||||
|
||||
#Write the output to log file
|
||||
f=open(log_path,"w")
|
||||
f.write(stdout+stderr)
|
||||
f.close()
|
||||
|
||||
#Watchdog for timeout process
|
||||
if self.mswindows:
|
||||
watch = threading.Timer(timeout, kill_process, args=(proc_handle, kill_check, self.mswindows))
|
||||
else:
|
||||
watch = threading.Timer(timeout, kill_process, args=(pid, kill_check, self.mswindows))
|
||||
watch.start()
|
||||
watch.cancel() # if it's still waiting to run
|
||||
success = not kill_check.isSet()
|
||||
if not success:
|
||||
raise RuntimeError
|
||||
kill_check.clear()
|
||||
|
||||
if p.returncode!=0:
|
||||
print('\nAll tests were not successful. Check the test-logs in the jetpack directory.')
|
||||
result_sdk(home_path)
|
||||
#sys.exit(1)
|
||||
raise RuntimeError
|
||||
else:
|
||||
ret_code=result_sdk(home_path)
|
||||
if ret_code==0:
|
||||
print('\nAll tests were successful. Yay \o/ . Running a sample package test now...')
|
||||
else:
|
||||
print ('\nThere were errors during the tests.Take a look at logs')
|
||||
raise RuntimeError
|
||||
except RuntimeError:
|
||||
print "Ending the program"
|
||||
sys.exit(1)
|
||||
except:
|
||||
print "Error during the testall command execution:", sys.exc_info()[0]
|
||||
raise
|
||||
|
||||
def package(self, example_dir):
|
||||
try:
|
||||
timeout = 30
|
||||
|
||||
print '\nNow Running packaging tests...'
|
||||
|
||||
kill_check = threading.Event()
|
||||
|
||||
# Set the path for the example logs. They will be in the parent directory of the Jetpack SDK.
|
||||
exlog_path = example_dir + 'test-example.log'
|
||||
# Subprocess call to test the sample example for packaging.
|
||||
if self.bin!=None:
|
||||
if self.mswindows:
|
||||
p = subprocess.Popen('bin\\activate && cfx run --pkgdir examples\\reading-data --static-args="{\\"quitWhenDone\\":true}" -b \"" + self.bin + "\"' , stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
|
||||
proc_handle = p._handle
|
||||
(stdout, stderr) = p.communicate()
|
||||
else:
|
||||
p = subprocess.Popen('. bin/activate; cfx run --pkgdir examples/reading-data --static-args=\'{\"quitWhenDone\":true}\' -b ' + self.bin , stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
|
||||
pid = p.pid
|
||||
(stdout, stderr) = p.communicate()
|
||||
elif self.bin==None:
|
||||
if self.mswindows:
|
||||
p = subprocess.Popen('bin\\activate && cfx run --pkgdir examples\\reading-data --static-args="{\\"quitWhenDone\\":true}"', stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
|
||||
proc_handle = p._handle
|
||||
(stdout, stderr) = p.communicate()
|
||||
else:
|
||||
p = subprocess.Popen('. bin/activate; cfx run --pkgdir examples/reading-data --static-args=\'{\"quitWhenDone\":true}\' ', stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
|
||||
pid = p.pid
|
||||
(stdout, stderr) = p.communicate()
|
||||
|
||||
#Write the output to log file
|
||||
f=open(exlog_path,"w")
|
||||
f.write(stdout+stderr)
|
||||
f.close()
|
||||
|
||||
#Watch dog for timeout process
|
||||
if self.mswindows:
|
||||
watch = threading.Timer(timeout, kill_process, args=(proc_handle, kill_check, self.mswindows))
|
||||
else:
|
||||
watch = threading.Timer(timeout, kill_process, args=(pid, kill_check, self.mswindows))
|
||||
watch.start()
|
||||
watch.cancel() # if it's still waiting to run
|
||||
success = not kill_check.isSet()
|
||||
if not success:
|
||||
raise RuntimeError
|
||||
kill_check.clear()
|
||||
|
||||
if p.returncode != 0:
|
||||
print('\nSample tests were not executed correctly. Check the test-example log in jetpack diretory.')
|
||||
result_example(example_dir)
|
||||
raise RuntimeError
|
||||
else:
|
||||
ret_code=result_example(example_dir)
|
||||
if ret_code==0:
|
||||
print('\nAll tests pass. The SDK is working! Yay \o/')
|
||||
else:
|
||||
print ('\nTests passed with warning.Take a look at logs')
|
||||
sys.exit(1)
|
||||
|
||||
except RuntimeError:
|
||||
print "Ending program"
|
||||
sys.exit(1)
|
||||
except:
|
||||
print "Error during running sample tests:", sys.exc_info()[0]
|
||||
raise
|
||||
|
||||
def result_sdk(sdk_dir):
|
||||
log_path = sdk_dir + 'tests.log'
|
||||
print 'Results are logged at:' + log_path
|
||||
try:
|
||||
f = open(log_path,'r')
|
||||
# Handles file errors
|
||||
except IOError :
|
||||
print 'I/O error - Cannot open test log at ' + log_path
|
||||
raise
|
||||
|
||||
for line in reversed(open(log_path).readlines()):
|
||||
if line.strip()=='FAIL':
|
||||
print ('\nOverall result - FAIL. Look at the test log at '+log_path)
|
||||
return 1
|
||||
return 0
|
||||
|
||||
|
||||
def result_example(sdk_dir):
|
||||
exlog_path = sdk_dir + 'test-example.log'
|
||||
print 'Sample test results are logged at:' + exlog_path
|
||||
try:
|
||||
f = open(exlog_path,'r')
|
||||
# Handles file errors
|
||||
except IOError :
|
||||
print 'I/O error - Cannot open sample test log at ' + exlog_path
|
||||
raise
|
||||
|
||||
#Read the file in reverse and check for the keyword 'FAIL'.
|
||||
for line in reversed(open(exlog_path).readlines()):
|
||||
if line.strip()=='FAIL':
|
||||
print ('\nOverall result for Sample tests - FAIL. Look at the test log at '+exlog_path)
|
||||
return 1
|
||||
return 0
|
||||
|
||||
def kill_process(process, kill_check, mswindows):
|
||||
print '\nProcess Timedout. Killing the process. Please Rerun this script.'
|
||||
if mswindows:
|
||||
win32api.TerminateProcess(process, -1)
|
||||
else:
|
||||
os.kill(process, signal.SIGKILL)
|
||||
kill_check.set()# tell the main routine to kill. Used SIGKILL to hard kill the process.
|
||||
return
|
||||
|
||||
if __name__ == "__main__":
|
||||
obj = SDK()
|
||||
obj.download(obj.link,obj.fpath,obj.fname)
|
||||
obj.extract(obj.base_path,obj.fname)
|
||||
obj.run_testall(obj.base_path,obj.folder_name)
|
||||
obj.package(obj.base_path)
|
||||
#!/usr/bin/env python
|
||||
# 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
|
||||
import signal
|
||||
import threading
|
||||
import urllib2, urllib
|
||||
import zipfile
|
||||
import tarfile
|
||||
import subprocess
|
||||
import optparse
|
||||
import sys, re
|
||||
#import win32api
|
||||
|
||||
|
||||
class SDK:
|
||||
def __init__(self):
|
||||
try:
|
||||
# Take the current working directory
|
||||
self.default_path = os.getcwd()
|
||||
if sys.platform == "win32":
|
||||
self.mswindows = True
|
||||
else:
|
||||
self.mswindows = False
|
||||
# Take the default home path of the user.
|
||||
home = os.path.expanduser('~')
|
||||
|
||||
# The following are the parameters that can be used to pass a dynamic URL, a specific path or a binry. The binary is not used yet. It will be used in version 2.0
|
||||
# If a dynamic path is to be mentioned, it should start with a '/'. For eg. "/Desktop"
|
||||
parser = optparse.OptionParser()
|
||||
parser.add_option('-u', '--url', dest = 'url', default = 'https://ftp.mozilla.org/pub/mozilla.org/labs/jetpack/addon-sdk-latest.zip')
|
||||
parser.add_option('-p', '--path', dest = 'path', default = self.default_path)
|
||||
parser.add_option('-b', '--binary', dest = 'binary')#, default='/Applications/Firefox.app')
|
||||
(options, args) = parser.parse_args()
|
||||
|
||||
# Get the URL from the parameter
|
||||
self.link = options.url
|
||||
# Set the base path for the user. If the user supplies the path, use the home variable as well. Else, take the default path of this script as the installation directory.
|
||||
if options.path!=self.default_path:
|
||||
if self.mswindows:
|
||||
self.base_path = home + str(options.path).strip() + '\\'
|
||||
else:
|
||||
self.base_path = home + str(options.path).strip() + '/'
|
||||
else:
|
||||
if self.mswindows:
|
||||
self.base_path = str(options.path).strip() + '\\'
|
||||
else:
|
||||
self.base_path = str(options.path).strip() + '/'
|
||||
assert ' ' not in self.base_path, "You cannot have a space in your home path. Please remove the space before you continue."
|
||||
print('Your Base path is =' + self.base_path)
|
||||
|
||||
# This assignment is not used in this program. It will be used in version 2 of this script.
|
||||
self.bin = options.binary
|
||||
# if app or bin is empty, dont pass anything
|
||||
|
||||
# Search for the .zip file or tarball file in the URL.
|
||||
i = self.link.rfind('/')
|
||||
|
||||
self.fname = self.link[i+1:]
|
||||
z = re.search('zip',self.fname,re.I)
|
||||
g = re.search('gz',self.fname,re.I)
|
||||
if z:
|
||||
print 'zip file present in the URL.'
|
||||
self.zip = True
|
||||
self.gz = False
|
||||
elif g:
|
||||
print 'gz file present in the URL'
|
||||
self.gz = True
|
||||
self.zip = False
|
||||
else:
|
||||
print 'zip/gz file not present. Check the URL.'
|
||||
return
|
||||
print("File name is =" + self.fname)
|
||||
|
||||
# Join the base path and the zip/tar file name to crate a complete Local file path.
|
||||
self.fpath = self.base_path + self.fname
|
||||
print('Your local file path will be=' + self.fpath)
|
||||
except AssertionError, e:
|
||||
print e.args[0]
|
||||
sys.exit(1)
|
||||
|
||||
# Download function - to download the SDK from the URL to the local machine.
|
||||
def download(self,url,fpath,fname):
|
||||
try:
|
||||
# Start the download
|
||||
print("Downloading...Please be patient!")
|
||||
urllib.urlretrieve(url,filename = fname)
|
||||
print('Download was successful.')
|
||||
except ValueError: # Handles broken URL errors.
|
||||
print 'The URL is ether broken or the file does not exist. Please enter the correct URL.'
|
||||
raise
|
||||
except urllib2.URLError: # Handles URL errors
|
||||
print '\nURL not correct. Check again!'
|
||||
raise
|
||||
|
||||
# Function to extract the downloaded zipfile.
|
||||
def extract(self, zipfilepath, extfile):
|
||||
try:
|
||||
# Timeout is set to 30 seconds.
|
||||
timeout = 30
|
||||
# Change the directory to the location of the zip file.
|
||||
try:
|
||||
os.chdir(zipfilepath)
|
||||
except OSError:
|
||||
# Will reach here if zip file doesnt exist
|
||||
print 'O/S Error:' + zipfilepath + 'does not exist'
|
||||
raise
|
||||
|
||||
# Get the folder name of Jetpack to get the exact version number.
|
||||
if self.zip:
|
||||
try:
|
||||
f = zipfile.ZipFile(extfile, "r")
|
||||
except IOError as (errno, strerror): # Handles file errors
|
||||
print "I/O error - Cannot perform extract operation: {1}".format(errno, strerror)
|
||||
raise
|
||||
list = f.namelist()[0]
|
||||
temp_name = list.split('/')
|
||||
print('Folder Name= ' +temp_name[0])
|
||||
self.folder_name = temp_name[0]
|
||||
elif self.gz:
|
||||
try:
|
||||
f = tarfile.open(extfile,'r')
|
||||
except IOError as (errno, strerror): # Handles file errors
|
||||
print "I/O error - Cannot perform extract operation: {1}".format(errno, strerror)
|
||||
raise
|
||||
list = f.getnames()[0]
|
||||
temp_name = list.split('/')
|
||||
print('Folder Name= ' +temp_name[0])
|
||||
self.folder_name = temp_name[0]
|
||||
|
||||
print ('Starting to Extract...')
|
||||
|
||||
# Timeout code. The subprocess.popen exeutes the command and the thread waits for a timeout. If the process does not finish within the mentioned-
|
||||
# timeout, the process is killed.
|
||||
kill_check = threading.Event()
|
||||
|
||||
if self.zip:
|
||||
# Call the command to unzip the file.
|
||||
if self.mswindows:
|
||||
zipfile.ZipFile.extractall(f)
|
||||
else:
|
||||
p = subprocess.Popen('unzip '+extfile, stdout=subprocess.PIPE, shell=True)
|
||||
pid = p.pid
|
||||
elif self.gz:
|
||||
# Call the command to untar the file.
|
||||
if self.mswindows:
|
||||
tarfile.TarFile.extractall(f)
|
||||
else:
|
||||
p = subprocess.Popen('tar -xf '+extfile, stdout=subprocess.PIPE, shell=True)
|
||||
pid = p.pid
|
||||
|
||||
#No need to handle for windows because windows automatically replaces old files with new files. It does not ask the user(as it does in Mac/Unix)
|
||||
if self.mswindows==False:
|
||||
watch = threading.Timer(timeout, kill_process, args=(pid, kill_check, self.mswindows ))
|
||||
watch.start()
|
||||
(stdout, stderr) = p.communicate()
|
||||
watch.cancel() # if it's still waiting to run
|
||||
success = not kill_check.isSet()
|
||||
|
||||
# Abort process if process fails.
|
||||
if not success:
|
||||
raise RuntimeError
|
||||
kill_check.clear()
|
||||
print('Extraction Successful.')
|
||||
except RuntimeError:
|
||||
print "Ending the program"
|
||||
sys.exit(1)
|
||||
except:
|
||||
print "Error during file extraction: ", sys.exc_info()[0]
|
||||
raise
|
||||
|
||||
# Function to run the cfx testall comands and to make sure the SDK is not broken.
|
||||
def run_testall(self, home_path, folder_name):
|
||||
try:
|
||||
timeout = 500
|
||||
|
||||
self.new_dir = home_path + folder_name
|
||||
try:
|
||||
os.chdir(self.new_dir)
|
||||
except OSError:
|
||||
# Will reach here if the jetpack 0.X directory doesnt exist
|
||||
print 'O/S Error: Jetpack directory does not exist at ' + self.new_dir
|
||||
raise
|
||||
print '\nStarting tests...'
|
||||
# Timeout code. The subprocess.popen exeutes the command and the thread waits for a timeout. If the process does not finish within the mentioned-
|
||||
# timeout, the process is killed.
|
||||
kill_check = threading.Event()
|
||||
|
||||
# Set the path for the logs. They will be in the parent directory of the Jetpack SDK.
|
||||
log_path = home_path + 'tests.log'
|
||||
|
||||
# Subprocess call to set up the jetpack environment and to start the tests. Also sends the output to a log file.
|
||||
if self.bin != None:
|
||||
if self.mswindows:
|
||||
p = subprocess.Popen("bin\\activate && cfx testall -a firefox -b \"" + self.bin + "\"" , stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
|
||||
proc_handle = p._handle
|
||||
(stdout,stderr) = p.communicate()
|
||||
else:
|
||||
p = subprocess.Popen('. bin/activate; cfx testall -a firefox -b ' + self.bin , stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
|
||||
pid = p.pid
|
||||
(stdout,stderr) = p.communicate()
|
||||
elif self.bin == None:
|
||||
if self.mswindows:
|
||||
p=subprocess.Popen('bin\\activate && cfx testall -a firefox > '+log_path, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
|
||||
proc_handle = p._handle
|
||||
(stdout,stderr) = p.communicate()
|
||||
else:
|
||||
p = subprocess.Popen('. bin/activate; cfx testall -a firefox > '+log_path, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
|
||||
pid = p.pid
|
||||
(stdout,stderr) = p.communicate()
|
||||
|
||||
#Write the output to log file
|
||||
f=open(log_path,"w")
|
||||
f.write(stdout+stderr)
|
||||
f.close()
|
||||
|
||||
#Watchdog for timeout process
|
||||
if self.mswindows:
|
||||
watch = threading.Timer(timeout, kill_process, args=(proc_handle, kill_check, self.mswindows))
|
||||
else:
|
||||
watch = threading.Timer(timeout, kill_process, args=(pid, kill_check, self.mswindows))
|
||||
watch.start()
|
||||
watch.cancel() # if it's still waiting to run
|
||||
success = not kill_check.isSet()
|
||||
if not success:
|
||||
raise RuntimeError
|
||||
kill_check.clear()
|
||||
|
||||
if p.returncode!=0:
|
||||
print('\nAll tests were not successful. Check the test-logs in the jetpack directory.')
|
||||
result_sdk(home_path)
|
||||
#sys.exit(1)
|
||||
raise RuntimeError
|
||||
else:
|
||||
ret_code=result_sdk(home_path)
|
||||
if ret_code==0:
|
||||
print('\nAll tests were successful. Yay \o/ . Running a sample package test now...')
|
||||
else:
|
||||
print ('\nThere were errors during the tests.Take a look at logs')
|
||||
raise RuntimeError
|
||||
except RuntimeError:
|
||||
print "Ending the program"
|
||||
sys.exit(1)
|
||||
except:
|
||||
print "Error during the testall command execution:", sys.exc_info()[0]
|
||||
raise
|
||||
|
||||
def package(self, example_dir):
|
||||
try:
|
||||
timeout = 30
|
||||
|
||||
print '\nNow Running packaging tests...'
|
||||
|
||||
kill_check = threading.Event()
|
||||
|
||||
# Set the path for the example logs. They will be in the parent directory of the Jetpack SDK.
|
||||
exlog_path = example_dir + 'test-example.log'
|
||||
# Subprocess call to test the sample example for packaging.
|
||||
if self.bin!=None:
|
||||
if self.mswindows:
|
||||
p = subprocess.Popen('bin\\activate && cfx run --pkgdir examples\\reading-data --static-args="{\\"quitWhenDone\\":true}" -b \"" + self.bin + "\"' , stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
|
||||
proc_handle = p._handle
|
||||
(stdout, stderr) = p.communicate()
|
||||
else:
|
||||
p = subprocess.Popen('. bin/activate; cfx run --pkgdir examples/reading-data --static-args=\'{\"quitWhenDone\":true}\' -b ' + self.bin , stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
|
||||
pid = p.pid
|
||||
(stdout, stderr) = p.communicate()
|
||||
elif self.bin==None:
|
||||
if self.mswindows:
|
||||
p = subprocess.Popen('bin\\activate && cfx run --pkgdir examples\\reading-data --static-args="{\\"quitWhenDone\\":true}"', stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
|
||||
proc_handle = p._handle
|
||||
(stdout, stderr) = p.communicate()
|
||||
else:
|
||||
p = subprocess.Popen('. bin/activate; cfx run --pkgdir examples/reading-data --static-args=\'{\"quitWhenDone\":true}\' ', stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
|
||||
pid = p.pid
|
||||
(stdout, stderr) = p.communicate()
|
||||
|
||||
#Write the output to log file
|
||||
f=open(exlog_path,"w")
|
||||
f.write(stdout+stderr)
|
||||
f.close()
|
||||
|
||||
#Watch dog for timeout process
|
||||
if self.mswindows:
|
||||
watch = threading.Timer(timeout, kill_process, args=(proc_handle, kill_check, self.mswindows))
|
||||
else:
|
||||
watch = threading.Timer(timeout, kill_process, args=(pid, kill_check, self.mswindows))
|
||||
watch.start()
|
||||
watch.cancel() # if it's still waiting to run
|
||||
success = not kill_check.isSet()
|
||||
if not success:
|
||||
raise RuntimeError
|
||||
kill_check.clear()
|
||||
|
||||
if p.returncode != 0:
|
||||
print('\nSample tests were not executed correctly. Check the test-example log in jetpack diretory.')
|
||||
result_example(example_dir)
|
||||
raise RuntimeError
|
||||
else:
|
||||
ret_code=result_example(example_dir)
|
||||
if ret_code==0:
|
||||
print('\nAll tests pass. The SDK is working! Yay \o/')
|
||||
else:
|
||||
print ('\nTests passed with warning.Take a look at logs')
|
||||
sys.exit(1)
|
||||
|
||||
except RuntimeError:
|
||||
print "Ending program"
|
||||
sys.exit(1)
|
||||
except:
|
||||
print "Error during running sample tests:", sys.exc_info()[0]
|
||||
raise
|
||||
|
||||
def result_sdk(sdk_dir):
|
||||
log_path = sdk_dir + 'tests.log'
|
||||
print 'Results are logged at:' + log_path
|
||||
try:
|
||||
f = open(log_path,'r')
|
||||
# Handles file errors
|
||||
except IOError :
|
||||
print 'I/O error - Cannot open test log at ' + log_path
|
||||
raise
|
||||
|
||||
for line in reversed(open(log_path).readlines()):
|
||||
if line.strip()=='FAIL':
|
||||
print ('\nOverall result - FAIL. Look at the test log at '+log_path)
|
||||
return 1
|
||||
return 0
|
||||
|
||||
|
||||
def result_example(sdk_dir):
|
||||
exlog_path = sdk_dir + 'test-example.log'
|
||||
print 'Sample test results are logged at:' + exlog_path
|
||||
try:
|
||||
f = open(exlog_path,'r')
|
||||
# Handles file errors
|
||||
except IOError :
|
||||
print 'I/O error - Cannot open sample test log at ' + exlog_path
|
||||
raise
|
||||
|
||||
#Read the file in reverse and check for the keyword 'FAIL'.
|
||||
for line in reversed(open(exlog_path).readlines()):
|
||||
if line.strip()=='FAIL':
|
||||
print ('\nOverall result for Sample tests - FAIL. Look at the test log at '+exlog_path)
|
||||
return 1
|
||||
return 0
|
||||
|
||||
def kill_process(process, kill_check, mswindows):
|
||||
print '\nProcess Timedout. Killing the process. Please Rerun this script.'
|
||||
if mswindows:
|
||||
win32api.TerminateProcess(process, -1)
|
||||
else:
|
||||
os.kill(process, signal.SIGKILL)
|
||||
kill_check.set()# tell the main routine to kill. Used SIGKILL to hard kill the process.
|
||||
return
|
||||
|
||||
if __name__ == "__main__":
|
||||
obj = SDK()
|
||||
obj.download(obj.link,obj.fpath,obj.fname)
|
||||
obj.extract(obj.base_path,obj.fname)
|
||||
obj.run_testall(obj.base_path,obj.folder_name)
|
||||
obj.package(obj.base_path)
|
||||
|
@ -1,8 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Generator: Adobe Illustrator 12.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 51448) -->
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
|
||||
<!ENTITY ns_svg "http://www.w3.org/2000/svg">
|
||||
<!ENTITY ns_xlink "http://www.w3.org/1999/xlink">
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
|
||||
<!ENTITY ns_svg "http://www.w3.org/2000/svg">
|
||||
<!ENTITY ns_xlink "http://www.w3.org/1999/xlink">
|
||||
]>
|
||||
<svg version="1.1" id="svg2997" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200" viewBox="-0.5 -0.5 200 200" overflow="visible" enable-background="new -0.5 -0.5 200 200" xml:space="preserve">
|
||||
<path id="path85" fill="#FFFFFF" d="M-2559.936,6359.65c19.127,26.489,46.371,47.744,80.988,44.707 C-2479.339,6371.648-2523.898,6352.641-2559.936,6359.65z"/>
|
||||
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 16 KiB |
@ -139,6 +139,11 @@ opened in the first tab in that window. This is an optional property.
|
||||
If present and true, the new tab will be opened to the right of the active tab
|
||||
and will not be active. This is an optional property.
|
||||
|
||||
@prop isPrivate {boolean}
|
||||
Boolean which will determine if a private tab should be opened.
|
||||
Private browsing mode must be supported in order to do this.
|
||||
See the [private-browsing](modules/sdk/private-browsing.html) documentation for more information.
|
||||
|
||||
@prop [isPinned] {boolean}
|
||||
If present and true, then the new tab will be pinned as an
|
||||
[app tab](http://support.mozilla.com/en-US/kb/what-are-app-tabs).
|
||||
|
@ -118,6 +118,11 @@ If the only option being used is `url`, then a bare string URL can be passed to
|
||||
String URL to be opened in the new window.
|
||||
This is a required property.
|
||||
|
||||
@prop isPrivate {boolean}
|
||||
Boolean which will determine if a private window should be opened.
|
||||
Private browsing mode must be supported in order to do this.
|
||||
See the [private-browsing](modules/sdk/private-browsing.html) documentation for more information.
|
||||
|
||||
@prop [onOpen] {function}
|
||||
A callback function that is called when the window has opened. This does not
|
||||
mean that the URL content has loaded, only that the window itself is fully
|
||||
|
@ -13,6 +13,7 @@ function Options(options) {
|
||||
url: { is: ["string"] },
|
||||
inBackground: { is: ["undefined", "boolean"] },
|
||||
isPinned: { is: ["undefined", "boolean"] },
|
||||
isPrivate: { is: ["undefined", "boolean"] },
|
||||
onOpen: { is: ["undefined", "function"] },
|
||||
onClose: { is: ["undefined", "function"] },
|
||||
onReady: { is: ["undefined", "function"] },
|
||||
|
@ -4,19 +4,61 @@
|
||||
'use strict';
|
||||
|
||||
// TODO: BUG 792670 - remove dependency below
|
||||
const { browserWindows } = require('../windows');
|
||||
const { browserWindows: windows } = require('../windows');
|
||||
const { tabs } = require('../windows/tabs-firefox');
|
||||
const { isPrivate } = require('../private-browsing');
|
||||
const { isWindowPBSupported } = require('../private-browsing/utils')
|
||||
const { isPrivateBrowsingSupported } = require('sdk/self');
|
||||
|
||||
const supportPrivateTabs = isPrivateBrowsingSupported && isWindowPBSupported;
|
||||
|
||||
Object.defineProperties(tabs, {
|
||||
open: { value: function open(options) {
|
||||
if (options.inNewWindow)
|
||||
if (options.inNewWindow) {
|
||||
// `tabs` option is under review and may be removed.
|
||||
return browserWindows.open({ tabs: [ options ] });
|
||||
// Open in active window if new window was not required.
|
||||
return browserWindows.activeWindow.tabs.open(options);
|
||||
windows.open({
|
||||
tabs: [ options ],
|
||||
isPrivate: options.isPrivate
|
||||
});
|
||||
return undefined;
|
||||
}
|
||||
// Open in active window if new window was not required..
|
||||
|
||||
|
||||
let activeWindow = windows.activeWindow;
|
||||
let privateState = !!options.isPrivate;
|
||||
// if the active window is in the state that we need then use it
|
||||
if (!supportPrivateTabs || privateState === isPrivate(activeWindow)) {
|
||||
activeWindow.tabs.open(options);
|
||||
}
|
||||
else {
|
||||
// find a window in the state that we need
|
||||
let window = getWindow(privateState);
|
||||
if (window) {
|
||||
window.tabs.open(options);
|
||||
}
|
||||
// open a window in the state that we need
|
||||
else {
|
||||
windows.open({
|
||||
tabs: [ options ],
|
||||
isPrivate: options.isPrivate
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}}
|
||||
});
|
||||
|
||||
function getWindow(privateState) {
|
||||
for each (let window in windows) {
|
||||
if (privateState === isPrivate(window)) {
|
||||
return window;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// Workaround for bug 674195. Freezing objects from other compartments fail,
|
||||
// so we use `Object.freeze` from the same component as objects
|
||||
// `hasOwnProperty`. Since `hasOwnProperty` here will be from other component
|
||||
|
@ -102,10 +102,13 @@ function openTab(window, url, options) {
|
||||
return window.BrowserApp.addTab(url, {
|
||||
selected: options.inBackground ? false : true,
|
||||
pinned: options.isPinned || false,
|
||||
isPrivate: options.private || false
|
||||
isPrivate: options.isPrivate || false
|
||||
});
|
||||
}
|
||||
return window.gBrowser.addTab(url);
|
||||
let tab = window.gBrowser.addTab(url);
|
||||
if (!options.inBackground)
|
||||
activateTab(tab);
|
||||
return tab;
|
||||
};
|
||||
exports.openTab = openTab;
|
||||
|
||||
|
@ -19,7 +19,8 @@ const { Cc, Ci, Cr } = require('chrome'),
|
||||
{ ns } = require('../core/namespace'),
|
||||
{ observer: windowObserver } = require('./observer'),
|
||||
{ getOwnerWindow } = require('../private-browsing/window/utils'),
|
||||
viewNS = require('sdk/core/namespace').ns();
|
||||
viewNS = require('../core/namespace').ns(),
|
||||
{ isPrivateBrowsingSupported } = require('../self');
|
||||
|
||||
/**
|
||||
* Window trait composes safe wrappers for browser window that are E10S
|
||||
@ -68,7 +69,7 @@ const BrowserWindowTrait = Trait.compose(
|
||||
this._tabOptions = [ Options(options.url) ];
|
||||
}
|
||||
|
||||
this._private = !!options.private;
|
||||
this._isPrivate = isPrivateBrowsingSupported && !!options.isPrivate;
|
||||
|
||||
this._load();
|
||||
|
||||
@ -209,9 +210,13 @@ const browserWindows = Trait.resolve({ toString: null }).compose(
|
||||
return window ? BrowserWindow({window: window}) : null;
|
||||
},
|
||||
open: function open(options) {
|
||||
if (typeof options === "string")
|
||||
if (typeof options === "string") {
|
||||
// `tabs` option is under review and may be removed.
|
||||
options = { tabs: [Options(options)] };
|
||||
options = {
|
||||
tabs: [Options(options)],
|
||||
isPrivate: isPrivateBrowsingSupported && options.isPrivate
|
||||
};
|
||||
}
|
||||
return BrowserWindow(options);
|
||||
},
|
||||
|
||||
|
@ -41,7 +41,7 @@ const WindowLoader = Trait.compose({
|
||||
_load: function _load() {
|
||||
if (this.__window) return;
|
||||
this._window = openDialog({
|
||||
private: this._private,
|
||||
private: this._isPrivate,
|
||||
args: this._tabOptions.map(function(options) options.url).join("|")
|
||||
});
|
||||
},
|
||||
|
@ -17,11 +17,15 @@ const { EventTarget } = require('../event/target');
|
||||
const { when: unload } = require('../system/unload');
|
||||
const { windowIterator } = require('../deprecated/window-utils');
|
||||
const { List, addListItem, removeListItem } = require('../util/list');
|
||||
const { isPrivateBrowsingSupported } = require('sdk/self');
|
||||
const { isTabPBSupported } = require('sdk/private-browsing/utils');
|
||||
|
||||
const mainWindow = windowNS(browserWindows.activeWindow).window;
|
||||
|
||||
const ERR_FENNEC_MSG = 'This method is not yet supported by Fennec';
|
||||
|
||||
const supportPrivateTabs = isPrivateBrowsingSupported && isTabPBSupported;
|
||||
|
||||
const Tabs = Class({
|
||||
implements: [ List ],
|
||||
extends: EventTarget,
|
||||
@ -53,7 +57,8 @@ const Tabs = Class({
|
||||
}
|
||||
|
||||
let rawTab = openTab(windowNS(activeWin).window, options.url, {
|
||||
inBackground: options.inBackground
|
||||
inBackground: options.inBackground,
|
||||
isPrivate: supportPrivateTabs && options.isPrivate
|
||||
});
|
||||
|
||||
// by now the tab has been created
|
||||
|
@ -13,9 +13,10 @@ const { Tab } = require("../tabs/tab");
|
||||
const { EventEmitter } = require("../deprecated/events");
|
||||
const { EVENTS } = require("../tabs/events");
|
||||
const { getOwnerWindow, getActiveTab, getTabs,
|
||||
openTab, activateTab } = require("../tabs/utils");
|
||||
openTab } = require("../tabs/utils");
|
||||
const { Options } = require("../tabs/common");
|
||||
const { observer: tabsObserver } = require("../tabs/observer");
|
||||
const { isWindowPrivate } = require("../private-browsing/utils");
|
||||
|
||||
const TAB_BROWSER = "tabbrowser";
|
||||
|
||||
@ -152,11 +153,14 @@ const TabList = List.resolve({ constructor: "_init" }).compose(
|
||||
_activeTab: null,
|
||||
|
||||
open: function open(options) {
|
||||
let window = this._window;
|
||||
let chromeWindow = window._window;
|
||||
options = Options(options);
|
||||
this._window._tabOptions.push(options);
|
||||
let tab = openTab(this._window._window, options.url);
|
||||
if (!options.inBackground)
|
||||
activateTab(tab);
|
||||
|
||||
// save the tab options
|
||||
window._tabOptions.push(options);
|
||||
// open the tab
|
||||
let tab = openTab(chromeWindow, options.url, options);
|
||||
}
|
||||
// This is ugly, but necessary. Will be removed by #596248
|
||||
}).resolve({ toString: null })
|
||||
|
@ -161,6 +161,28 @@ parser_groups = (
|
||||
default="firefox",
|
||||
cmds=['test', 'run', 'testex', 'testpkgs',
|
||||
'testall'])),
|
||||
(("-o", "--overload-modules",), dict(dest="overload_modules",
|
||||
help=("Overload JS modules integrated into"
|
||||
" Firefox with the one from your SDK"
|
||||
" repository"),
|
||||
action="store_true",
|
||||
default=False,
|
||||
cmds=['run', 'test', 'testex', 'testpkgs',
|
||||
'testall'])),
|
||||
(("", "--strip-sdk",), dict(dest="bundle_sdk",
|
||||
help=("Do not ship SDK modules in the xpi"),
|
||||
action="store_false",
|
||||
default=True,
|
||||
cmds=['run', 'test', 'testex', 'testpkgs',
|
||||
'testall', 'xpi'])),
|
||||
(("", "--force-use-bundled-sdk",), dict(dest="force_use_bundled_sdk",
|
||||
help=("When --strip-sdk isn't passed, "
|
||||
"force using sdk modules shipped in "
|
||||
"the xpi instead of firefox ones"),
|
||||
action="store_true",
|
||||
default=False,
|
||||
cmds=['run', 'test', 'testex', 'testpkgs',
|
||||
'testall', 'xpi'])),
|
||||
(("", "--no-run",), dict(dest="no_run",
|
||||
help=("Instead of launching the "
|
||||
"application, just show the command "
|
||||
@ -764,6 +786,14 @@ def run(arguments=sys.argv[1:], target_cfg=None, pkg_cfg=None,
|
||||
|
||||
harness_options.update(build)
|
||||
|
||||
# When cfx is run from sdk root directory, we will strip sdk modules and
|
||||
# override them with local modules.
|
||||
# So that integration tools will continue to work and use local modules
|
||||
if os.getcwd() == env_root:
|
||||
options.bundle_sdk = True
|
||||
options.force_use_bundled_sdk = False
|
||||
options.overload_modules = True
|
||||
|
||||
extra_environment = {}
|
||||
if command == "test":
|
||||
# This should be contained in the test runner package.
|
||||
@ -792,14 +822,32 @@ def run(arguments=sys.argv[1:], target_cfg=None, pkg_cfg=None,
|
||||
mydir = os.path.dirname(os.path.abspath(__file__))
|
||||
app_extension_dir = os.path.join(mydir, "../../app-extension")
|
||||
|
||||
|
||||
if target_cfg.get('preferences'):
|
||||
harness_options['preferences'] = target_cfg.get('preferences')
|
||||
|
||||
harness_options['manifest'] = manifest.get_harness_options_manifest()
|
||||
harness_options['allTestModules'] = manifest.get_all_test_modules()
|
||||
if len(harness_options['allTestModules']) == 0 and command == "test":
|
||||
sys.exit(0)
|
||||
harness_options['manifest'] = \
|
||||
manifest.get_harness_options_manifest(options.bundle_sdk)
|
||||
|
||||
# Gives an hint to tell if sdk modules are bundled or not
|
||||
harness_options['is-sdk-bundled'] = options.bundle_sdk
|
||||
|
||||
if options.force_use_bundled_sdk:
|
||||
if not options.bundle_sdk:
|
||||
print >>sys.stderr, ("--force-use-bundled-sdk and --strip-sdk "
|
||||
"can't be used at the same time.")
|
||||
sys.exit(1)
|
||||
if options.overload_modules:
|
||||
print >>sys.stderr, ("--force-use-bundled-sdk and --overload-modules "
|
||||
"can't be used at the same time.")
|
||||
sys.exit(1)
|
||||
# Pass a flag in order to force using sdk modules shipped in the xpi
|
||||
harness_options['force-use-bundled-sdk'] = True
|
||||
|
||||
# Pass the list of absolute path for all test modules
|
||||
if command == "test":
|
||||
harness_options['allTestModules'] = manifest.get_all_test_modules()
|
||||
if len(harness_options['allTestModules']) == 0:
|
||||
sys.exit(0)
|
||||
|
||||
from cuddlefish.rdf import gen_manifest, RDFUpdate
|
||||
|
||||
@ -825,7 +873,7 @@ def run(arguments=sys.argv[1:], target_cfg=None, pkg_cfg=None,
|
||||
# build_manifest earlier
|
||||
used_files = None
|
||||
if command == "xpi":
|
||||
used_files = set(manifest.get_used_files())
|
||||
used_files = set(manifest.get_used_files(options.bundle_sdk))
|
||||
|
||||
if options.no_strip_xpi:
|
||||
used_files = None # disables the filter, includes all files
|
||||
@ -872,7 +920,11 @@ def run(arguments=sys.argv[1:], target_cfg=None, pkg_cfg=None,
|
||||
norun=options.no_run,
|
||||
used_files=used_files,
|
||||
enable_mobile=options.enable_mobile,
|
||||
mobile_app_name=options.mobile_app_name)
|
||||
mobile_app_name=options.mobile_app_name,
|
||||
env_root=env_root,
|
||||
is_running_tests=(command == "test"),
|
||||
overload_modules=options.overload_modules,
|
||||
bundle_sdk=options.bundle_sdk)
|
||||
except ValueError, e:
|
||||
print ""
|
||||
print "A given cfx option has an inappropriate value:"
|
||||
|
@ -260,7 +260,7 @@ class ManifestBuilder:
|
||||
used.add(package)
|
||||
return sorted(used)
|
||||
|
||||
def get_used_files(self):
|
||||
def get_used_files(self, bundle_sdk_modules):
|
||||
# returns all .js files that we reference, plus data/ files. You will
|
||||
# need to add the loader, off-manifest files that it needs, and
|
||||
# generated metadata.
|
||||
@ -269,16 +269,22 @@ class ManifestBuilder:
|
||||
yield absname
|
||||
|
||||
for me in self.get_module_entries():
|
||||
yield me.js_filename
|
||||
# Do not add manifest entries for system modules,
|
||||
# so that we won't ship SDK files.
|
||||
if me.packageName != "addon-sdk" or bundle_sdk_modules:
|
||||
yield me.js_filename
|
||||
|
||||
def get_all_test_modules(self):
|
||||
return self.test_modules
|
||||
|
||||
def get_harness_options_manifest(self):
|
||||
def get_harness_options_manifest(self, bundle_sdk_modules):
|
||||
manifest = {}
|
||||
for me in self.get_module_entries():
|
||||
path = me.get_path()
|
||||
manifest[path] = me.get_entry_for_manifest()
|
||||
# Do not add manifest entries for system modules,
|
||||
# so that we won't ship SDK files.
|
||||
if me.packageName != "addon-sdk" or bundle_sdk_modules:
|
||||
manifest[path] = me.get_entry_for_manifest()
|
||||
return manifest
|
||||
|
||||
def get_manifest_entry(self, package, section, module):
|
||||
|
@ -380,7 +380,11 @@ def run_app(harness_root_dir, manifest_rdf, harness_options,
|
||||
logfile=None, addons=None, args=None, extra_environment={},
|
||||
norun=None,
|
||||
used_files=None, enable_mobile=False,
|
||||
mobile_app_name=None):
|
||||
mobile_app_name=None,
|
||||
env_root=None,
|
||||
is_running_tests=False,
|
||||
overload_modules=False,
|
||||
bundle_sdk=True):
|
||||
if binary:
|
||||
binary = os.path.expanduser(binary)
|
||||
|
||||
@ -392,6 +396,22 @@ def run_app(harness_root_dir, manifest_rdf, harness_options,
|
||||
cmdargs = []
|
||||
preferences = dict(DEFAULT_COMMON_PREFS)
|
||||
|
||||
# Overload global commonjs path with lib/ folders
|
||||
file_scheme = "file://"
|
||||
# win32 file scheme needs 3 slashes
|
||||
if not env_root.startswith("/"):
|
||||
file_scheme = file_scheme + "/"
|
||||
addon_id = harness_options["jetpackID"]
|
||||
pref_prefix = "extensions.modules." + addon_id + ".path"
|
||||
if overload_modules:
|
||||
preferences[pref_prefix] = file_scheme + \
|
||||
os.path.join(env_root, "lib").replace("\\", "/") + "/"
|
||||
|
||||
# Overload tests/ mapping with test/ folder, only when running test
|
||||
if is_running_tests:
|
||||
preferences[pref_prefix + ".tests"] = file_scheme + \
|
||||
os.path.join(env_root, "test").replace("\\", "/") + "/"
|
||||
|
||||
# For now, only allow running on Mobile with --force-mobile argument
|
||||
if app_type in ["fennec", "fennec-on-device"] and not enable_mobile:
|
||||
print """
|
||||
@ -483,7 +503,8 @@ def run_app(harness_root_dir, manifest_rdf, harness_options,
|
||||
manifest=manifest_rdf,
|
||||
xpi_path=xpi_path,
|
||||
harness_options=harness_options,
|
||||
limit_to=used_files)
|
||||
limit_to=used_files,
|
||||
bundle_sdk=bundle_sdk)
|
||||
addons.append(xpi_path)
|
||||
|
||||
starttime = last_output_time = time.time()
|
||||
|
@ -43,7 +43,7 @@ class Basic(unittest.TestCase):
|
||||
# target_cfg.dependencies is not provided, so we'll search through
|
||||
# all known packages (everything in 'deps').
|
||||
m = manifest.build_manifest(target_cfg, pkg_cfg, deps, scan_tests=False)
|
||||
m = m.get_harness_options_manifest()
|
||||
m = m.get_harness_options_manifest(False)
|
||||
|
||||
def assertReqIs(modname, reqname, path):
|
||||
reqs = m["one/%s" % modname]["requirements"]
|
||||
@ -72,7 +72,7 @@ class Basic(unittest.TestCase):
|
||||
[target_cfg.name, "addon-sdk"])
|
||||
self.failUnlessEqual(deps, ["addon-sdk", "three"])
|
||||
m = manifest.build_manifest(target_cfg, pkg_cfg, deps, scan_tests=False)
|
||||
m = m.get_harness_options_manifest()
|
||||
m = m.get_harness_options_manifest(False)
|
||||
def assertReqIs(modname, reqname, path):
|
||||
reqs = m["three/%s" % modname]["requirements"]
|
||||
self.failUnlessEqual(reqs[reqname], path)
|
||||
@ -90,7 +90,7 @@ class Basic(unittest.TestCase):
|
||||
self.failUnlessEqual(deps, ["addon-sdk", "five"])
|
||||
# all we care about is that this next call doesn't raise an exception
|
||||
m = manifest.build_manifest(target_cfg, pkg_cfg, deps, scan_tests=False)
|
||||
m = m.get_harness_options_manifest()
|
||||
m = m.get_harness_options_manifest(False)
|
||||
reqs = m["five/main"]["requirements"]
|
||||
self.failUnlessEqual(reqs, {});
|
||||
|
||||
|
@ -202,7 +202,7 @@ class SmallXPI(unittest.TestCase):
|
||||
[target_cfg.name, "addon-sdk"])
|
||||
addon_sdk_dir = pkg_cfg.packages["addon-sdk"].lib[0]
|
||||
m = manifest.build_manifest(target_cfg, pkg_cfg, deps, scan_tests=False)
|
||||
used_files = list(m.get_used_files())
|
||||
used_files = list(m.get_used_files(True))
|
||||
here = up(os.path.abspath(__file__))
|
||||
def absify(*parts):
|
||||
fn = os.path.join(here, "linker-files", *parts)
|
||||
|
@ -22,7 +22,8 @@ def mkzipdir(zf, path):
|
||||
zf.writestr(dirinfo, "")
|
||||
|
||||
def build_xpi(template_root_dir, manifest, xpi_path,
|
||||
harness_options, limit_to=None, extra_harness_options={}):
|
||||
harness_options, limit_to=None, extra_harness_options={},
|
||||
bundle_sdk=True):
|
||||
zf = zipfile.ZipFile(xpi_path, "w", zipfile.ZIP_DEFLATED)
|
||||
|
||||
open('.install.rdf', 'w').write(str(manifest))
|
||||
@ -84,6 +85,10 @@ def build_xpi(template_root_dir, manifest, xpi_path,
|
||||
# of all packages sections directories
|
||||
for packageName in harness_options['packages']:
|
||||
base_arcpath = ZIPSEP.join(['resources', packageName])
|
||||
# Eventually strip sdk files. We need to do that in addition to the
|
||||
# whilelist as the whitelist is only used for `cfx xpi`:
|
||||
if not bundle_sdk and packageName == 'addon-sdk':
|
||||
continue
|
||||
# Always write the top directory, even if it contains no files, since
|
||||
# the harness will try to access it.
|
||||
dirs_to_create.add(base_arcpath)
|
||||
|
@ -3,11 +3,164 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
'use strict';
|
||||
|
||||
const { Ci } = require('chrome');
|
||||
const { isPrivateBrowsingSupported } = require('sdk/self');
|
||||
const tabs = require('sdk/tabs');
|
||||
const { browserWindows: windows } = require('sdk/windows');
|
||||
const { isPrivate } = require('sdk/private-browsing');
|
||||
const { getOwnerWindow } = require('sdk/private-browsing/window/utils');
|
||||
const { is } = require('sdk/system/xul-app');
|
||||
const { isWindowPBSupported, isTabPBSupported } = require('sdk/private-browsing/utils');
|
||||
|
||||
const TAB_URL = 'data:text/html;charset=utf-8,TEST-TAB';
|
||||
|
||||
exports.testIsPrivateBrowsingTrue = function(assert) {
|
||||
assert.ok(isPrivateBrowsingSupported,
|
||||
'isPrivateBrowsingSupported property is true');
|
||||
};
|
||||
|
||||
// test tab.open with isPrivate: true
|
||||
// test isPrivate on a tab
|
||||
// test getOwnerWindow on windows and tabs
|
||||
exports.testGetOwnerWindow = function(assert, done) {
|
||||
let window = windows.activeWindow;
|
||||
let chromeWindow = getOwnerWindow(window);
|
||||
assert.ok(chromeWindow instanceof Ci.nsIDOMWindow, 'associated window is found');
|
||||
|
||||
tabs.open({
|
||||
url: 'about:blank',
|
||||
isPrivate: true,
|
||||
onOpen: function(tab) {
|
||||
// test that getOwnerWindow works as expected
|
||||
if (is('Fennec')) {
|
||||
assert.notStrictEqual(chromeWindow, getOwnerWindow(tab));
|
||||
assert.ok(getOwnerWindow(tab) instanceof Ci.nsIDOMWindow);
|
||||
}
|
||||
else {
|
||||
if (isWindowPBSupported) {
|
||||
assert.notStrictEqual(chromeWindow,
|
||||
getOwnerWindow(tab),
|
||||
'associated window is not the same for window and window\'s tab');
|
||||
}
|
||||
else {
|
||||
assert.strictEqual(chromeWindow,
|
||||
getOwnerWindow(tab),
|
||||
'associated window is the same for window and window\'s tab');
|
||||
}
|
||||
}
|
||||
|
||||
let pbSupported = isTabPBSupported || isWindowPBSupported;
|
||||
|
||||
// test that the tab is private if it should be
|
||||
assert.equal(isPrivate(tab), pbSupported);
|
||||
assert.equal(isPrivate(getOwnerWindow(tab)), pbSupported);
|
||||
|
||||
tab.close(function() done());
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// test that it is possible to open a private tab
|
||||
exports.testTabOpenPrivate = function(assert, done) {
|
||||
tabs.open({
|
||||
url: TAB_URL,
|
||||
isPrivate: true,
|
||||
onReady: function(tab) {
|
||||
assert.equal(tab.url, TAB_URL, 'opened correct tab');
|
||||
assert.equal(isPrivate(tab), (isWindowPBSupported || isTabPBSupported));
|
||||
|
||||
tab.close(function() {
|
||||
done();
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
// test that it is possible to open a non private tab
|
||||
exports.testTabOpenPrivateDefault = function(assert, done) {
|
||||
tabs.open({
|
||||
url: TAB_URL,
|
||||
onReady: function(tab) {
|
||||
assert.equal(tab.url, TAB_URL, 'opened correct tab');
|
||||
assert.equal(isPrivate(tab), false);
|
||||
|
||||
tab.close(function() {
|
||||
done();
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// test that it is possible to open a non private tab in explicit case
|
||||
exports.testTabOpenPrivateOffExplicit = function(assert, done) {
|
||||
tabs.open({
|
||||
url: TAB_URL,
|
||||
isPrivate: false,
|
||||
onReady: function(tab) {
|
||||
assert.equal(tab.url, TAB_URL, 'opened correct tab');
|
||||
assert.equal(isPrivate(tab), false);
|
||||
|
||||
tab.close(function() {
|
||||
done();
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// test windows.open with isPrivate: true
|
||||
// test isPrivate on a window
|
||||
if (!is('Fennec')) {
|
||||
// test that it is possible to open a private window
|
||||
exports.testWindowOpenPrivate = function(assert, done) {
|
||||
windows.open({
|
||||
url: TAB_URL,
|
||||
isPrivate: true,
|
||||
onOpen: function(window) {
|
||||
let tab = window.tabs[0];
|
||||
tab.once('ready', function() {
|
||||
assert.equal(tab.url, TAB_URL, 'opened correct tab');
|
||||
assert.equal(isPrivate(tab), isWindowPBSupported, 'tab is private');
|
||||
|
||||
window.close(function() {
|
||||
done();
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
exports.testIsPrivateOnWindowOn = function(assert, done) {
|
||||
windows.open({
|
||||
isPrivate: true,
|
||||
onOpen: function(window) {
|
||||
assert.equal(isPrivate(window), isWindowPBSupported, 'isPrivate for a window is true when it should be');
|
||||
assert.equal(isPrivate(window.tabs[0]), isWindowPBSupported, 'isPrivate for a tab is false when it should be');
|
||||
window.close(done);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
exports.testIsPrivateOnWindowOffImplicit = function(assert, done) {
|
||||
windows.open({
|
||||
onOpen: function(window) {
|
||||
assert.equal(isPrivate(window), false, 'isPrivate for a window is false when it should be');
|
||||
assert.equal(isPrivate(window.tabs[0]), false, 'isPrivate for a tab is false when it should be');
|
||||
window.close(done);
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
exports.testIsPrivateOnWindowOffExplicit = function(assert, done) {
|
||||
windows.open({
|
||||
isPrivate: false,
|
||||
onOpen: function(window) {
|
||||
assert.equal(isPrivate(window), false, 'isPrivate for a window is false when it should be');
|
||||
assert.equal(isPrivate(window.tabs[0]), false, 'isPrivate for a tab is false when it should be');
|
||||
window.close(done);
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
require('sdk/test/runner').runTestsFromModule(module);
|
||||
|
@ -12,7 +12,7 @@ exports.testIsPrivateOnTab = function(test) {
|
||||
test.assert(!pb.isPrivate(chromeWindow), 'the top level window is not private');
|
||||
|
||||
let rawTab = openTab(chromeWindow, 'data:text/html,<h1>Hi!</h1>', {
|
||||
private: true
|
||||
isPrivate: true
|
||||
});
|
||||
|
||||
// test that the tab is private
|
||||
|
@ -32,10 +32,10 @@ exports.testPerWindowPrivateBrowsingGetter = function(assert, done) {
|
||||
|
||||
exports.testIsPrivateOnWindowOn = function(assert, done) {
|
||||
windows.open({
|
||||
private: true,
|
||||
isPrivate: true,
|
||||
onOpen: function(window) {
|
||||
assert.equal(isPrivate(window), true, 'isPrivate for a window is true when it should be');
|
||||
assert.equal(isPrivate(window.tabs[0]), true, 'isPrivate for a tab is false when it should be');
|
||||
assert.equal(isPrivate(window), false, 'isPrivate for a window is true when it should be');
|
||||
assert.equal(isPrivate(window.tabs[0]), false, 'isPrivate for a tab is false when it should be');
|
||||
window.close(done);
|
||||
}
|
||||
});
|
||||
|
@ -93,7 +93,7 @@ exports.testDeprecateEvent = function(assert, done) {
|
||||
emit(testObj, 'water');
|
||||
});
|
||||
assert.equal(errors.length, 1, "only one error is dispatched");
|
||||
let msg = errors[0];console.log(msg);
|
||||
let msg = errors[0];
|
||||
assert.ok(msg.indexOf("BAD") !== -1, "message contains the given message");
|
||||
assert.ok(msg.indexOf("deprecateEvent") !== -1,
|
||||
"message contains name of the caller function");
|
||||
|
@ -7,6 +7,7 @@ const { Ci } = require('chrome');
|
||||
const { pb, pbUtils, getOwnerWindow } = require('./private-browsing/helper');
|
||||
const { merge } = require('sdk/util/object');
|
||||
const windows = require('sdk/windows').browserWindows;
|
||||
const tabs = require('sdk/tabs');
|
||||
const winUtils = require('sdk/window/utils');
|
||||
const { isPrivateBrowsingSupported } = require('sdk/self');
|
||||
const { is } = require('sdk/system/xul-app');
|
||||
@ -70,9 +71,9 @@ exports.testGetOwnerWindow = function(test) {
|
||||
let chromeWindow = getOwnerWindow(window);
|
||||
test.assert(chromeWindow instanceof Ci.nsIDOMWindow, 'associated window is found');
|
||||
|
||||
window.tabs.open({
|
||||
tabs.open({
|
||||
url: 'about:blank',
|
||||
private: true, // should be ignored in this case
|
||||
isPrivate: true,
|
||||
onOpen: function(tab) {
|
||||
// test that getOwnerWindow works as expected
|
||||
if (is('Fennec')) {
|
||||
@ -86,6 +87,7 @@ exports.testGetOwnerWindow = function(test) {
|
||||
// test that the tab is not private
|
||||
// private flag should be ignored by default
|
||||
test.assert(!isPrivate(tab));
|
||||
test.assert(!isPrivate(getOwnerWindow(tab)));
|
||||
|
||||
tab.close(function() test.done());
|
||||
}
|
||||
|
@ -6,6 +6,8 @@
|
||||
const { Loader } = require('sdk/test/loader');
|
||||
const { browserWindows } = require('sdk/windows');
|
||||
const tabs = require('sdk/tabs');
|
||||
const { isPrivate } = require('sdk/private-browsing');
|
||||
const { isWindowPBSupported, isTabPBSupported } = require('sdk/private-browsing/utils');
|
||||
|
||||
const URL = 'data:text/html;charset=utf-8,<html><head><title>#title#</title></head></html>';
|
||||
|
||||
@ -289,8 +291,29 @@ exports.testTabContentTypeAndReload = function(test) {
|
||||
}
|
||||
else {
|
||||
test.assertEqual(tab.contentType, "text/xml");
|
||||
tab.close(function() test.done());
|
||||
tab.close(function() {
|
||||
test.done();
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// test that it is possible to open a private tab
|
||||
exports.testTabOpenPrivate = function(test) {
|
||||
test.waitUntilDone();
|
||||
|
||||
let url = 'about:blank';
|
||||
tabs.open({
|
||||
url: url,
|
||||
isPrivate: true,
|
||||
onReady: function(tab) {
|
||||
test.assertEqual(tab.url, url, 'opened correct tab');
|
||||
test.assertEqual(isPrivate(tab), false, 'private tabs arenot supported by default');
|
||||
|
||||
tab.close(function() {
|
||||
test.done();
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -12,6 +12,8 @@ const wm = Cc['@mozilla.org/appshell/window-mediator;1'].
|
||||
const { browserWindows } = require("sdk/windows");
|
||||
const tabs = require("sdk/tabs");
|
||||
const { WindowTracker } = require("sdk/deprecated/window-utils");
|
||||
const { isPrivate } = require('sdk/private-browsing');
|
||||
const { isWindowPBSupported } = require('sdk/private-browsing/utils');
|
||||
|
||||
// TEST: open & close window
|
||||
exports.testOpenAndCloseWindow = function(test) {
|
||||
@ -101,7 +103,7 @@ exports.testWindowTabsObject = function(test) {
|
||||
}
|
||||
browserWindows.open({
|
||||
url: "data:text/html;charset=utf-8,<title>tab 1</title>",
|
||||
onActivate: function onOpen(win) {
|
||||
onActivate: function onActivate(win) {
|
||||
window = win;
|
||||
runTest();
|
||||
},
|
||||
@ -370,3 +372,24 @@ exports.testTrackWindows = function(test) {
|
||||
|
||||
openWindow();
|
||||
}
|
||||
|
||||
// test that it is not possible to open a private window by default
|
||||
exports.testWindowOpenPrivateDefault = function(test) {
|
||||
test.waitUntilDone();
|
||||
|
||||
browserWindows.open({
|
||||
url: 'about:mozilla',
|
||||
isPrivate: true,
|
||||
onOpen: function(window) {
|
||||
let tab = window.tabs[0];
|
||||
tab.once('ready', function() {
|
||||
test.assertEqual(tab.url, 'about:mozilla', 'opened correct tab');
|
||||
test.assertEqual(isPrivate(tab), false, 'tab is not private');
|
||||
|
||||
window.close(function() {
|
||||
test.done();
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -86,48 +86,75 @@ WebappsActor.prototype = {
|
||||
});
|
||||
},
|
||||
|
||||
installHostedApp: function wa_actorInstallHosted(aDir, aId, aType) {
|
||||
_getAppType: function wa_actorGetAppType(aType) {
|
||||
let type = Ci.nsIPrincipal.APP_STATUS_INSTALLED;
|
||||
|
||||
if (aType) {
|
||||
type = aType == "privileged" ? Ci.nsIPrincipal.APP_STATUS_PRIVILEGED
|
||||
: aType == "certified" ? Ci.nsIPrincipal.APP_STATUS_CERTIFIED
|
||||
: Ci.nsIPrincipal.APP_STATUS_INSTALLED;
|
||||
}
|
||||
|
||||
return type;
|
||||
},
|
||||
|
||||
installHostedApp: function wa_actorInstallHosted(aDir, aId) {
|
||||
debug("installHostedApp");
|
||||
let self = this;
|
||||
|
||||
let runnable = {
|
||||
run: function run() {
|
||||
try {
|
||||
// The destination directory for this app.
|
||||
let installDir = FileUtils.getDir(DIRECTORY_NAME,
|
||||
["webapps", aId], true);
|
||||
|
||||
// Move manifest.webapp to the destination directory.
|
||||
let manFile = aDir.clone();
|
||||
manFile.append("manifest.webapp");
|
||||
manFile.moveTo(installDir, "manifest.webapp");
|
||||
|
||||
// Read the origin and manifest url from metadata.json
|
||||
let metaFile = aDir.clone();
|
||||
metaFile.append("metadata.json");
|
||||
DOMApplicationRegistry._loadJSONAsync(metaFile, function(aMetadata) {
|
||||
if (!aMetadata) {
|
||||
self._sendError("Error Parsing metadata.json", aId);
|
||||
DOMApplicationRegistry._loadJSONAsync(manFile, function(aManifest) {
|
||||
if (!aManifest) {
|
||||
self._sendError("Error Parsing manifest.webapp", aId);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!aMetadata.origin) {
|
||||
self._sendError("Missing 'origin' propery in metadata.json", aId);
|
||||
let appType = self._getAppType(aManifest.type);
|
||||
|
||||
// In production builds, don't allow installation of certified apps.
|
||||
#ifdef MOZ_OFFICIAL
|
||||
if (appType == Ci.nsIPrincipal.APP_STATUS_CERTIFIED) {
|
||||
self._sendError("Installing certified apps is not allowed.", aId);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
// The destination directory for this app.
|
||||
let installDir = FileUtils.getDir(DIRECTORY_NAME,
|
||||
["webapps", aId], true);
|
||||
manFile.moveTo(installDir, "manifest.webapp");
|
||||
|
||||
let origin = aMetadata.origin;
|
||||
let manifestURL = aMetadata.manifestURL ||
|
||||
origin + "/manifest.webapp";
|
||||
// Create a fake app object with the minimum set of properties we need.
|
||||
let app = {
|
||||
origin: origin,
|
||||
installOrigin: aMetadata.installOrigin || origin,
|
||||
manifestURL: manifestURL,
|
||||
appStatus: aType
|
||||
}
|
||||
// Read the origin and manifest url from metadata.json
|
||||
let metaFile = aDir.clone();
|
||||
metaFile.append("metadata.json");
|
||||
DOMApplicationRegistry._loadJSONAsync(metaFile, function(aMetadata) {
|
||||
if (!aMetadata) {
|
||||
self._sendError("Error Parsing metadata.json", aId);
|
||||
return;
|
||||
}
|
||||
|
||||
self._registerApp(app, aId, aDir);
|
||||
if (!aMetadata.origin) {
|
||||
self._sendError("Missing 'origin' property in metadata.json", aId);
|
||||
return;
|
||||
}
|
||||
|
||||
let origin = aMetadata.origin;
|
||||
let manifestURL = aMetadata.manifestURL ||
|
||||
origin + "/manifest.webapp";
|
||||
// Create a fake app object with the minimum set of properties we need.
|
||||
let app = {
|
||||
origin: origin,
|
||||
installOrigin: aMetadata.installOrigin || origin,
|
||||
manifestURL: manifestURL,
|
||||
appStatus: appType
|
||||
};
|
||||
|
||||
self._registerApp(app, aId, aDir);
|
||||
});
|
||||
});
|
||||
} catch(e) {
|
||||
// If anything goes wrong, just send it back.
|
||||
@ -140,7 +167,7 @@ WebappsActor.prototype = {
|
||||
Ci.nsIThread.DISPATCH_NORMAL);
|
||||
},
|
||||
|
||||
installPackagedApp: function wa_actorInstallPackaged(aDir, aId, aType) {
|
||||
installPackagedApp: function wa_actorInstallPackaged(aDir, aId) {
|
||||
debug("installPackagedApp");
|
||||
let self = this;
|
||||
|
||||
@ -151,34 +178,45 @@ WebappsActor.prototype = {
|
||||
let installDir = FileUtils.getDir(DIRECTORY_NAME,
|
||||
["webapps", aId], true);
|
||||
|
||||
// Move application.zip to the destination directory.
|
||||
// Move application.zip to the destination directory, and
|
||||
// extract manifest.webapp there.
|
||||
let zipFile = aDir.clone();
|
||||
zipFile.append("application.zip");
|
||||
zipFile.moveTo(installDir, "application.zip");
|
||||
|
||||
// Extract the manifest.webapp file from the zip.
|
||||
zipFile = installDir.clone();
|
||||
zipFile.append("application.zip");
|
||||
let zipReader = Cc["@mozilla.org/libjar/zip-reader;1"]
|
||||
.createInstance(Ci.nsIZipReader);
|
||||
zipReader.open(zipFile);
|
||||
|
||||
let manFile = installDir.clone();
|
||||
manFile.append("manifest.webapp");
|
||||
zipReader.extract("manifest.webapp", manFile);
|
||||
zipReader.close();
|
||||
zipFile.moveTo(installDir, "application.zip");
|
||||
|
||||
let origin = "app://" + aId;
|
||||
DOMApplicationRegistry._loadJSONAsync(manFile, function(aManifest) {
|
||||
if (!aManifest) {
|
||||
self._sendError("Error Parsing manifest.webapp", aId);
|
||||
}
|
||||
|
||||
// Create a fake app object with the minimum set of properties we need.
|
||||
let app = {
|
||||
origin: origin,
|
||||
installOrigin: origin,
|
||||
manifestURL: origin + "/manifest.webapp",
|
||||
appStatus: aType
|
||||
}
|
||||
let appType = self._getAppType(aManifest.type);
|
||||
|
||||
self._registerApp(app, aId, aDir);
|
||||
// In production builds, don't allow installation of certified apps.
|
||||
#ifdef MOZ_OFFICIAL
|
||||
if (appType == Ci.nsIPrincipal.APP_STATUS_CERTIFIED) {
|
||||
self._sendError("Installing certified apps is not allowed.", aId);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
let origin = "app://" + aId;
|
||||
|
||||
// Create a fake app object with the minimum set of properties we need.
|
||||
let app = {
|
||||
origin: origin,
|
||||
installOrigin: origin,
|
||||
manifestURL: origin + "/manifest.webapp",
|
||||
appStatus: appType
|
||||
}
|
||||
|
||||
self._registerApp(app, aId, aDir);
|
||||
});
|
||||
} catch(e) {
|
||||
// If anything goes wrong, just send it back.
|
||||
self._sendError(e.toString(), aId);
|
||||
@ -195,9 +233,6 @@ WebappsActor.prototype = {
|
||||
* the files for the app in $TMP/b2g/$appId :
|
||||
* For packaged apps: application.zip
|
||||
* For hosted apps: metadata.json and manifest.webapp
|
||||
* @param appType : The privilege status of the app, as defined in
|
||||
* nsIPrincipal. It's optional and default to
|
||||
* APP_STATUS_INSTALLED
|
||||
*/
|
||||
install: function wa_actorInstall(aRequest) {
|
||||
debug("install");
|
||||
@ -212,8 +247,6 @@ WebappsActor.prototype = {
|
||||
message: "missing parameter appId" }
|
||||
}
|
||||
|
||||
let appType = aRequest.appType || Ci.nsIPrincipal.APP_STATUS_INSTALLED;
|
||||
|
||||
// Check that we are not overriding a preinstalled application.
|
||||
let reg = DOMApplicationRegistry;
|
||||
if (appId in reg.webapps && reg.webapps[appId].removable === false) {
|
||||
@ -222,15 +255,6 @@ WebappsActor.prototype = {
|
||||
}
|
||||
}
|
||||
|
||||
// In production builds, don't allow installation of certified apps.
|
||||
#ifdef MOZ_OFFICIAL
|
||||
if (appType == Ci.nsIPrincipal.APP_STATUS_CERTIFIED) {
|
||||
return { error: "badParameterType",
|
||||
message: "Installing certified apps is not allowed."
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
let appDir = FileUtils.getDir("TmpD", ["b2g", appId], false, false);
|
||||
|
||||
if (!appDir || !appDir.exists()) {
|
||||
@ -243,7 +267,7 @@ WebappsActor.prototype = {
|
||||
testFile.append("application.zip");
|
||||
|
||||
if (testFile.exists()) {
|
||||
this.installPackagedApp(appDir, appId, appType);
|
||||
this.installPackagedApp(appDir, appId);
|
||||
} else {
|
||||
let missing =
|
||||
["manifest.webapp", "metadata.json"]
|
||||
@ -261,7 +285,7 @@ WebappsActor.prototype = {
|
||||
message: "hosted app file is missing" }
|
||||
}
|
||||
|
||||
this.installHostedApp(appDir, appId, appType);
|
||||
this.installHostedApp(appDir, appId);
|
||||
}
|
||||
|
||||
return { appId: appId, path: appDir.path }
|
||||
|
@ -177,15 +177,6 @@ UpdatePrompt.prototype = {
|
||||
showUpdateError: function UP_showUpdateError(aUpdate) {
|
||||
log("Update error, state: " + aUpdate.state + ", errorCode: " +
|
||||
aUpdate.errorCode);
|
||||
if (aUpdate.state == "applied" && aUpdate.errorCode == 0) {
|
||||
// The user chose to apply the update later and then tried to download
|
||||
// it again. If there isn't a new update to download, then the updater
|
||||
// code will detect that there is an update waiting to be installed and
|
||||
// fail. So reprompt the user to apply the update.
|
||||
this.showApplyPrompt(aUpdate);
|
||||
return;
|
||||
}
|
||||
|
||||
this.sendUpdateEvent("update-error", aUpdate);
|
||||
this.setUpdateStatus(aUpdate.statusText);
|
||||
},
|
||||
@ -314,6 +305,14 @@ UpdatePrompt.prototype = {
|
||||
return;
|
||||
}
|
||||
|
||||
// If the update has already been downloaded and applied, then
|
||||
// Services.aus.downloadUpdate will return immediately and not
|
||||
// call showUpdateDownloaded, so we detect this.
|
||||
if (aUpdate.state == "applied" && aUpdate.errorCode == 0) {
|
||||
this.showUpdateDownloaded(aUpdate, true);
|
||||
return;
|
||||
}
|
||||
|
||||
log("Error downloading update " + aUpdate.name + ": " + aUpdate.errorCode);
|
||||
if (aUpdate.errorCode == FILE_ERROR_TOO_BIG) {
|
||||
aUpdate.statusText = "file-too-big";
|
||||
@ -412,7 +411,13 @@ UpdatePrompt.prototype = {
|
||||
break;
|
||||
case "update-available-result":
|
||||
this.handleAvailableResult(detail);
|
||||
this._update = null;
|
||||
// If we started the apply prompt timer, this means that we're waiting
|
||||
// for the user to press Later or Install Now. In this situation we
|
||||
// don't want to clear this._update, becuase handleApplyPromptResult
|
||||
// needs it.
|
||||
if (this._applyPromptTimer == null) {
|
||||
this._update = null;
|
||||
}
|
||||
break;
|
||||
case "update-download-cancel":
|
||||
this.handleDownloadCancel();
|
||||
@ -503,6 +508,7 @@ UpdatePrompt.prototype = {
|
||||
log("Timed out waiting for result, restarting");
|
||||
this._applyPromptTimer = null;
|
||||
this.finishUpdate();
|
||||
this._update = null;
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
"config_version": 1,
|
||||
"tooltool_manifest": "releng-otoro.tt",
|
||||
"mock_target": "mozilla-centos6-i386",
|
||||
"mock_packages": ["ccache", "make", "bison", "flex", "gcc", "g++", "mpfr", "zlib-devel", "ncurses-devel", "zip", "autoconf213", "glibc-static", "perl-Digest-SHA", "wget", "alsa-lib", "atk", "cairo", "dbus-glib", "fontconfig", "freetype", "glib2", "gtk2", "libXRender", "libXt", "pango", "mozilla-python27-mercurial", "openssh-clients", "nss-devel"],
|
||||
"mock_packages": ["ccache", "make", "bison", "flex", "gcc", "g++", "mpfr", "zlib-devel", "ncurses-devel", "zip", "autoconf213", "glibc-static", "perl-Digest-SHA", "wget", "alsa-lib", "atk", "cairo", "dbus-glib", "fontconfig", "freetype", "glib2", "gtk2", "libXRender", "libXt", "pango", "mozilla-python27-mercurial", "openssh-clients", "nss-devel", "java-1.6.0-openjdk-devel"],
|
||||
"mock_files": [["/home/cltbld/.ssh", "/home/mock_mozilla/.ssh"]],
|
||||
"build_targets": [],
|
||||
"upload_files": [
|
||||
|
@ -2,7 +2,7 @@
|
||||
"config_version": 1,
|
||||
"tooltool_manifest": "releng-unagi.tt",
|
||||
"mock_target": "mozilla-centos6-i386",
|
||||
"mock_packages": ["ccache", "make", "bison", "flex", "gcc", "g++", "mpfr", "zlib-devel", "ncurses-devel", "zip", "autoconf213", "glibc-static", "perl-Digest-SHA", "wget", "alsa-lib", "atk", "cairo", "dbus-glib", "fontconfig", "freetype", "glib2", "gtk2", "libXRender", "libXt", "pango", "mozilla-python27-mercurial", "openssh-clients", "nss-devel"],
|
||||
"mock_packages": ["ccache", "make", "bison", "flex", "gcc", "g++", "mpfr", "zlib-devel", "ncurses-devel", "zip", "autoconf213", "glibc-static", "perl-Digest-SHA", "wget", "alsa-lib", "atk", "cairo", "dbus-glib", "fontconfig", "freetype", "glib2", "gtk2", "libXRender", "libXt", "pango", "mozilla-python27-mercurial", "openssh-clients", "nss-devel", "java-1.6.0-openjdk-devel"],
|
||||
"mock_files": [["/home/cltbld/.ssh", "/home/mock_mozilla/.ssh"]],
|
||||
"build_targets": [],
|
||||
"upload_files": [
|
||||
|
@ -1,5 +1,5 @@
|
||||
<?xml version="1.0"?>
|
||||
<blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist" lastupdate="1360959670000">
|
||||
<blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist" lastupdate="1361213668000">
|
||||
<emItems>
|
||||
<emItem blockID="i58" id="webmaster@buzzzzvideos.info">
|
||||
<versionRange minVersion="0" maxVersion="*">
|
||||
@ -211,6 +211,8 @@
|
||||
<versionRange minVersion="0" maxVersion="*">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i10" id="{8CE11043-9A15-4207-A565-0C94C42D590D}">
|
||||
</emItem>
|
||||
<emItem blockID="i258" id="helperbar@helperbar.com">
|
||||
<versionRange minVersion="0" maxVersion="1.0" severity="1">
|
||||
</versionRange>
|
||||
@ -282,8 +284,10 @@
|
||||
<versionRange minVersion="0" maxVersion="*">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i10" id="{8CE11043-9A15-4207-A565-0C94C42D590D}">
|
||||
</emItem>
|
||||
<emItem blockID="i286" id="{58bd07eb-0ee0-4df0-8121-dc9b693373df}">
|
||||
<versionRange minVersion="0" maxVersion="*" severity="3">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i1" id="mozilla_cc@internetdownloadmanager.com">
|
||||
<versionRange minVersion="2.1" maxVersion="3.3">
|
||||
<targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
|
||||
|
@ -7,6 +7,7 @@ let Ci = Components.interfaces;
|
||||
let Cu = Components.utils;
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource:///modules/RecentWindow.jsm");
|
||||
|
||||
const nsIWebNavigation = Ci.nsIWebNavigation;
|
||||
|
||||
@ -4864,9 +4865,8 @@ nsBrowserAccess.prototype = {
|
||||
if (window.toolbar.visible)
|
||||
win = window;
|
||||
else {
|
||||
win = Cc["@mozilla.org/browser/browserglue;1"]
|
||||
.getService(Ci.nsIBrowserGlue)
|
||||
.getMostRecentBrowserWindow();
|
||||
let isPrivate = PrivateBrowsingUtils.isWindowPrivate(aOpener || window);
|
||||
win = RecentWindow.getMostRecentBrowserWindow({private: isPrivate});
|
||||
needToFocusWin = true;
|
||||
}
|
||||
|
||||
@ -7102,25 +7102,27 @@ var gIdentityHandler = {
|
||||
this._identityPopup.hidePopup();
|
||||
},
|
||||
|
||||
_popupOpenTime : null,
|
||||
|
||||
/**
|
||||
* Click handler for the identity-box element in primary chrome.
|
||||
*/
|
||||
handleIdentityButtonEvent : function(event) {
|
||||
this._popupOpenTime = new Date();
|
||||
TelemetryStopwatch.start("FX_IDENTITY_POPUP_OPEN_MS");
|
||||
event.stopPropagation();
|
||||
|
||||
if ((event.type == "click" && event.button != 0) ||
|
||||
(event.type == "keypress" && event.charCode != KeyEvent.DOM_VK_SPACE &&
|
||||
event.keyCode != KeyEvent.DOM_VK_RETURN))
|
||||
event.keyCode != KeyEvent.DOM_VK_RETURN)) {
|
||||
TelemetryStopwatch.cancel("FX_IDENTITY_POPUP_OPEN_MS");
|
||||
return; // Left click, space or enter only
|
||||
}
|
||||
|
||||
// Don't allow left click, space or enter if the location
|
||||
// is chrome UI or the location has been modified.
|
||||
if (this._mode == this.IDENTITY_MODE_CHROMEUI ||
|
||||
gURLBar.getAttribute("pageproxystate") != "valid")
|
||||
gURLBar.getAttribute("pageproxystate") != "valid") {
|
||||
TelemetryStopwatch.cancel("FX_IDENTITY_POPUP_OPEN_MS");
|
||||
return;
|
||||
}
|
||||
|
||||
// Make sure that the display:none style we set in xul is removed now that
|
||||
// the popup is actually needed
|
||||
@ -7142,13 +7144,7 @@ var gIdentityHandler = {
|
||||
},
|
||||
|
||||
onPopupShown : function(event) {
|
||||
let openingDuration = new Date() - this._popupOpenTime;
|
||||
this._popupOpenTime = null;
|
||||
try {
|
||||
Services.telemetry.getHistogramById("FX_IDENTITY_POPUP_OPEN_MS").add(openingDuration);
|
||||
} catch (ex) {
|
||||
Components.utils.reportError("Unable to report telemetry for FX_IDENTITY_POPUP_OPEN_MS.");
|
||||
}
|
||||
TelemetryStopwatch.finish("FX_IDENTITY_POPUP_OPEN_MS");
|
||||
document.getElementById('identity-popup-more-info-button').focus();
|
||||
},
|
||||
|
||||
|
@ -1175,32 +1175,32 @@
|
||||
|
||||
#ifndef XP_UNIX
|
||||
<svg:svg height="0">
|
||||
<svg:clipPath id="winstripe-keyhole-forward-clip-path" clipPathUnits="objectBoundingBox">
|
||||
<svg:clipPath id="windows-keyhole-forward-clip-path" clipPathUnits="objectBoundingBox">
|
||||
<svg:path d="M 0,0 C 0.16,0.11 0.28,0.29 0.28,0.5 0.28,0.71 0.16,0.89 0,1 L 1,1 1,0 0,0 z"/>
|
||||
</svg:clipPath>
|
||||
<svg:clipPath id="winstripe-urlbar-back-button-clip-path" clipPathUnits="userSpaceOnUse">
|
||||
<svg:clipPath id="windows-urlbar-back-button-clip-path" clipPathUnits="userSpaceOnUse">
|
||||
<svg:path d="M 0,0 0,7.8 C 2.5,11 4,14 4,18 4,22 2.5,25 0,28 l 0,22 10000,0 0,-50 L 0,0 z"/>
|
||||
</svg:clipPath>
|
||||
</svg:svg>
|
||||
#endif
|
||||
#ifdef XP_MACOSX
|
||||
<svg:svg height="0">
|
||||
<svg:clipPath id="pinstripe-keyhole-forward-clip-path" clipPathUnits="objectBoundingBox">
|
||||
<svg:clipPath id="osx-keyhole-forward-clip-path" clipPathUnits="objectBoundingBox">
|
||||
<svg:path d="M 0,0 C 0.15,0.12 0.25,0.3 0.25,0.5 0.25,0.7 0.15,0.88 0,1 L 1,1 1,0 0,0 z"/>
|
||||
</svg:clipPath>
|
||||
<svg:clipPath id="pinstripe-urlbar-back-button-clip-path" clipPathUnits="userSpaceOnUse">
|
||||
<svg:clipPath id="osx-urlbar-back-button-clip-path" clipPathUnits="userSpaceOnUse">
|
||||
<svg:path d="m 0,-5 0,4.03 C 3.6,1.8 6,6.1 6,11 6,16 3.6,20 0,23 l 0,27 10000,0 0,-55 L 0,-5 z"/>
|
||||
</svg:clipPath>
|
||||
<svg:clipPath id="pinstripe-tab-ontop-left-curve-clip-path" clipPathUnits="userSpaceOnUse">
|
||||
<svg:clipPath id="osx-tab-ontop-left-curve-clip-path" clipPathUnits="userSpaceOnUse">
|
||||
<svg:path d="M 9,0 C 7.3,0 6,1.3 6,3 l 0,14 c 0,3 -2.2,5 -5,5 l -1,0 0,1 12,0 0,-1 0,-19 0,-3 -3,0 z"/>
|
||||
</svg:clipPath>
|
||||
<svg:clipPath id="pinstripe-tab-ontop-right-curve-clip-path" clipPathUnits="userSpaceOnUse">
|
||||
<svg:clipPath id="osx-tab-ontop-right-curve-clip-path" clipPathUnits="userSpaceOnUse">
|
||||
<svg:path d="m 0,0 0,3 0,19 0,1 12,0 0,-1 -1,0 C 8.2,22 6,20 6,17 L 6,3 C 6,1.3 4.7,0 3,0 L 0,0 z"/>
|
||||
</svg:clipPath>
|
||||
<svg:clipPath id="pinstripe-tab-onbottom-left-curve-clip-path" clipPathUnits="userSpaceOnUse">
|
||||
<svg:clipPath id="osx-tab-onbottom-left-curve-clip-path" clipPathUnits="userSpaceOnUse">
|
||||
<svg:path d="m 0,0 0,1 1,0 c 2.8,0 5,2.2 5,5 l 0,14 c 0,2 1.3,3 3,3 l 3,0 0,-3 L 12,1 12,0 0,0 z"/>
|
||||
</svg:clipPath>
|
||||
<svg:clipPath id="pinstripe-tab-onbottom-right-curve-clip-path" clipPathUnits="userSpaceOnUse">
|
||||
<svg:clipPath id="osx-tab-onbottom-right-curve-clip-path" clipPathUnits="userSpaceOnUse">
|
||||
<svg:path d="m 0,0 0,1 0,19 0,3 3,0 c 1.7,0 3,-1 3,-3 L 6,6 C 6,3.2 8.2,1 11,1 L 12,1 12,0 0,0 z"/>
|
||||
</svg:clipPath>
|
||||
</svg:svg>
|
||||
|
@ -1897,6 +1897,7 @@
|
||||
|
||||
// That's gBrowser for the other window, not the tab's browser!
|
||||
var remoteBrowser = aOtherTab.ownerDocument.defaultView.gBrowser;
|
||||
var isPending = aOtherTab.hasAttribute("pending");
|
||||
|
||||
// First, start teardown of the other browser. Make sure to not
|
||||
// fire the beforeunload event in the process. Close the other
|
||||
@ -1904,21 +1905,34 @@
|
||||
if (!remoteBrowser._beginRemoveTab(aOtherTab, true, true))
|
||||
return;
|
||||
|
||||
// Workarounds for bug 458697
|
||||
// Icon might have been set on DOMLinkAdded, don't override that.
|
||||
let ourBrowser = this.getBrowserForTab(aOurTab);
|
||||
let otherBrowser = aOtherTab.linkedBrowser;
|
||||
if (!ourBrowser.mIconURL && otherBrowser.mIconURL)
|
||||
this.setIcon(aOurTab, otherBrowser.mIconURL);
|
||||
var isBusy = aOtherTab.hasAttribute("busy");
|
||||
if (isBusy) {
|
||||
aOurTab.setAttribute("busy", "true");
|
||||
this._tabAttrModified(aOurTab);
|
||||
if (aOurTab.selected)
|
||||
this.mIsBusy = true;
|
||||
}
|
||||
|
||||
this._swapBrowserDocShells(aOurTab, otherBrowser);
|
||||
// If the other tab is pending (i.e. has not been restored, yet)
|
||||
// then do not switch docShells but retrieve the other tab's state
|
||||
// and apply it to our tab.
|
||||
if (isPending) {
|
||||
let ss = Cc["@mozilla.org/browser/sessionstore;1"]
|
||||
.getService(Ci.nsISessionStore)
|
||||
ss.setTabState(aOurTab, ss.getTabState(aOtherTab));
|
||||
|
||||
// Make sure to unregister any open URIs.
|
||||
this._swapRegisteredOpenURIs(ourBrowser, otherBrowser);
|
||||
} else {
|
||||
// Workarounds for bug 458697
|
||||
// Icon might have been set on DOMLinkAdded, don't override that.
|
||||
if (!ourBrowser.mIconURL && otherBrowser.mIconURL)
|
||||
this.setIcon(aOurTab, otherBrowser.mIconURL);
|
||||
var isBusy = aOtherTab.hasAttribute("busy");
|
||||
if (isBusy) {
|
||||
aOurTab.setAttribute("busy", "true");
|
||||
this._tabAttrModified(aOurTab);
|
||||
if (aOurTab.selected)
|
||||
this.mIsBusy = true;
|
||||
}
|
||||
|
||||
this._swapBrowserDocShells(aOurTab, otherBrowser);
|
||||
}
|
||||
|
||||
// Finish tearing down the tab that's going away.
|
||||
remoteBrowser._endRemoveTab(aOtherTab);
|
||||
@ -1949,15 +1963,8 @@
|
||||
ourBrowser.webProgress.removeProgressListener(filter);
|
||||
filter.removeProgressListener(tabListener);
|
||||
|
||||
// Restore current registered open URI.
|
||||
if (ourBrowser.registeredOpenURI) {
|
||||
this._placesAutocomplete.unregisterOpenPage(ourBrowser.registeredOpenURI);
|
||||
delete ourBrowser.registeredOpenURI;
|
||||
}
|
||||
if (aOtherBrowser.registeredOpenURI) {
|
||||
ourBrowser.registeredOpenURI = aOtherBrowser.registeredOpenURI;
|
||||
delete aOtherBrowser.registeredOpenURI;
|
||||
}
|
||||
// Make sure to unregister any open URIs.
|
||||
this._swapRegisteredOpenURIs(ourBrowser, aOtherBrowser);
|
||||
|
||||
// Swap the docshells
|
||||
ourBrowser.swapDocShells(aOtherBrowser);
|
||||
@ -1973,6 +1980,26 @@
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<method name="_swapRegisteredOpenURIs">
|
||||
<parameter name="aOurBrowser"/>
|
||||
<parameter name="aOtherBrowser"/>
|
||||
<body>
|
||||
<![CDATA[
|
||||
// If the current URI is registered as open remove it from the list.
|
||||
if (aOurBrowser.registeredOpenURI) {
|
||||
this._placesAutocomplete.unregisterOpenPage(aOurBrowser.registeredOpenURI);
|
||||
delete aOurBrowser.registeredOpenURI;
|
||||
}
|
||||
|
||||
// If the other/new URI is registered as open then copy it over.
|
||||
if (aOtherBrowser.registeredOpenURI) {
|
||||
aOurBrowser.registeredOpenURI = aOtherBrowser.registeredOpenURI;
|
||||
delete aOtherBrowser.registeredOpenURI;
|
||||
}
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<method name="reloadAllTabs">
|
||||
<body>
|
||||
<![CDATA[
|
||||
|
@ -161,6 +161,7 @@ _BROWSER_FILES = \
|
||||
browser_bug783614.js \
|
||||
browser_bug797677.js \
|
||||
browser_bug816527.js \
|
||||
browser_bug817947.js \
|
||||
browser_bug822367.js \
|
||||
browser_bug832435.js \
|
||||
browser_canonizeURL.js \
|
||||
|
56
browser/base/content/test/browser_bug817947.js
Normal file
@ -0,0 +1,56 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
const ss = Cc["@mozilla.org/browser/sessionstore;1"]
|
||||
.getService(Ci.nsISessionStore);
|
||||
|
||||
const URL = "http://mochi.test:8888/browser/";
|
||||
const PREF = "browser.sessionstore.restore_on_demand";
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
Services.prefs.setBoolPref(PREF, true);
|
||||
registerCleanupFunction(function () {
|
||||
Services.prefs.clearUserPref(PREF);
|
||||
});
|
||||
|
||||
preparePendingTab(function (aTab) {
|
||||
let win = gBrowser.replaceTabWithWindow(aTab);
|
||||
|
||||
whenDelayedStartupFinished(win, function () {
|
||||
let [tab] = win.gBrowser.tabs;
|
||||
|
||||
whenLoaded(tab.linkedBrowser, function () {
|
||||
is(tab.linkedBrowser.currentURI.spec, URL, "correct url should be loaded");
|
||||
ok(!tab.hasAttribute("pending"), "tab should not be pending");
|
||||
|
||||
win.close();
|
||||
finish();
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function preparePendingTab(aCallback) {
|
||||
let tab = gBrowser.addTab(URL);
|
||||
|
||||
whenLoaded(tab.linkedBrowser, function () {
|
||||
let state = ss.getTabState(tab);
|
||||
gBrowser.removeTab(tab);
|
||||
|
||||
tab = gBrowser.addTab("about:blank");
|
||||
whenLoaded(tab.linkedBrowser, function () {
|
||||
ss.setTabState(tab, state);
|
||||
ok(tab.hasAttribute("pending"), "tab should be pending");
|
||||
aCallback(tab);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function whenLoaded(aElement, aCallback) {
|
||||
aElement.addEventListener("load", function onLoad() {
|
||||
aElement.removeEventListener("load", onLoad, true);
|
||||
executeSoon(aCallback);
|
||||
}, true);
|
||||
}
|
@ -222,14 +222,15 @@ function checkAutocompleteResults(aExpected, aCallback)
|
||||
let uri = gController.getValueAt(i).replace(/^moz-action:[^,]+,/i, "");
|
||||
|
||||
info("Search for '" + uri + "' in open tabs.");
|
||||
ok(uri in aExpected, "Registered open page found in autocomplete.");
|
||||
let expected = uri in aExpected;
|
||||
ok(expected, uri + " was found in autocomplete, was " + (expected ? "" : "not ") + "expected");
|
||||
// Remove the found entry from expected results.
|
||||
delete aExpected[uri];
|
||||
}
|
||||
|
||||
// Make sure there is no reported open page that is not open.
|
||||
for (let entry in aExpected) {
|
||||
ok(false, "'" + entry + "' not found in autocomplete.");
|
||||
ok(false, "'" + entry + "' should be found in autocomplete");
|
||||
}
|
||||
|
||||
executeSoon(aCallback);
|
||||
|
@ -66,6 +66,7 @@ BRANDING_FILES := \
|
||||
endif
|
||||
|
||||
BRANDING_DEST := $(DIST)/branding
|
||||
BRANDING_TARGET := export
|
||||
INSTALL_TARGETS += BRANDING
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
@ -66,6 +66,7 @@ BRANDING_FILES := \
|
||||
endif
|
||||
|
||||
BRANDING_DEST := $(DIST)/branding
|
||||
BRANDING_TARGET := export
|
||||
INSTALL_TARGETS += BRANDING
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
@ -66,6 +66,7 @@ BRANDING_FILES := \
|
||||
endif
|
||||
|
||||
BRANDING_DEST := $(DIST)/branding
|
||||
BRANDING_TARGET := export
|
||||
INSTALL_TARGETS += BRANDING
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
@ -66,6 +66,7 @@ BRANDING_FILES := \
|
||||
endif
|
||||
|
||||
BRANDING_DEST := $(DIST)/branding
|
||||
BRANDING_TARGET := export
|
||||
INSTALL_TARGETS += BRANDING
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
@ -12,9 +12,6 @@ include $(DEPTH)/config/autoconf.mk
|
||||
EXTRA_COMPONENTS = \
|
||||
BrowserDownloads.manifest \
|
||||
DownloadsUI.js \
|
||||
$(NULL)
|
||||
|
||||
EXTRA_PP_COMPONENTS = \
|
||||
DownloadsStartup.js \
|
||||
$(NULL)
|
||||
|
||||
|
@ -16,7 +16,7 @@ browser.jar:
|
||||
content/browser/places/placesOverlay.xul (content/placesOverlay.xul)
|
||||
* content/browser/places/menu.xml (content/menu.xml)
|
||||
content/browser/places/tree.xml (content/tree.xml)
|
||||
* content/browser/places/controller.js (content/controller.js)
|
||||
content/browser/places/controller.js (content/controller.js)
|
||||
content/browser/places/treeView.js (content/treeView.js)
|
||||
* content/browser/places/browserPlacesViews.js (content/browserPlacesViews.js)
|
||||
# keep the Places version of the history sidebar at history/history-panel.xul
|
||||
|
@ -15,7 +15,7 @@ EXTRA_COMPONENTS = \
|
||||
PlacesProtocolHandler.js \
|
||||
$(NULL)
|
||||
|
||||
EXTRA_PP_JS_MODULES = \
|
||||
EXTRA_JS_MODULES = \
|
||||
PlacesUIUtils.jsm \
|
||||
$(NULL)
|
||||
|
||||
|
@ -179,8 +179,8 @@ var gPrivacyPane = {
|
||||
// select the remember forms history option
|
||||
document.getElementById("browser.formfill.enable").value = true;
|
||||
|
||||
// select the accept cookies option
|
||||
document.getElementById("network.cookie.cookieBehavior").value = 0;
|
||||
// select the limit cookies option
|
||||
document.getElementById("network.cookie.cookieBehavior").value = 3;
|
||||
// select the cookie lifetime policy option
|
||||
document.getElementById("network.cookie.lifetimePolicy").value = 0;
|
||||
|
||||
@ -363,9 +363,10 @@ var gPrivacyPane = {
|
||||
* network.cookie.cookieBehavior
|
||||
* - determines how the browser should handle cookies:
|
||||
* 0 means enable all cookies
|
||||
* 1 means reject third party cookies; see
|
||||
* netwerk/cookie/src/nsCookieService.cpp for a hairier definition
|
||||
* 1 means reject all third party cookies
|
||||
* 2 means disable all cookies
|
||||
* 3 means reject third party cookies unless at least one is already set for the eTLD
|
||||
* see netwerk/cookie/src/nsCookieService.cpp for details
|
||||
* network.cookie.lifetimePolicy
|
||||
* - determines how long cookies are stored:
|
||||
* 0 means keep cookies until they expire
|
||||
@ -381,25 +382,20 @@ var gPrivacyPane = {
|
||||
readAcceptCookies: function ()
|
||||
{
|
||||
var pref = document.getElementById("network.cookie.cookieBehavior");
|
||||
var acceptThirdParty = document.getElementById("acceptThirdParty");
|
||||
var acceptThirdPartyLabel = document.getElementById("acceptThirdPartyLabel");
|
||||
var acceptThirdPartyMenu = document.getElementById("acceptThirdPartyMenu");
|
||||
var keepUntil = document.getElementById("keepUntil");
|
||||
var menu = document.getElementById("keepCookiesUntil");
|
||||
|
||||
// enable the rest of the UI for anything other than "disable all cookies"
|
||||
var acceptCookies = (pref.value != 2);
|
||||
|
||||
acceptThirdParty.disabled = !acceptCookies;
|
||||
acceptThirdPartyLabel.disabled = acceptThirdPartyMenu.disabled = !acceptCookies;
|
||||
keepUntil.disabled = menu.disabled = this._autoStartPrivateBrowsing || !acceptCookies;
|
||||
|
||||
|
||||
return acceptCookies;
|
||||
},
|
||||
|
||||
readAcceptThirdPartyCookies: function ()
|
||||
{
|
||||
var pref = document.getElementById("network.cookie.cookieBehavior");
|
||||
return pref.value == 0;
|
||||
},
|
||||
|
||||
/**
|
||||
* Enables/disables the "keep until" label and menulist in response to the
|
||||
* "accept cookies" checkbox being checked or unchecked.
|
||||
@ -407,20 +403,50 @@ var gPrivacyPane = {
|
||||
writeAcceptCookies: function ()
|
||||
{
|
||||
var accept = document.getElementById("acceptCookies");
|
||||
var acceptThirdParty = document.getElementById("acceptThirdParty");
|
||||
var acceptThirdPartyMenu = document.getElementById("acceptThirdPartyMenu");
|
||||
|
||||
// if we're enabling cookies, automatically check 'accept third party'
|
||||
// if we're enabling cookies, automatically select 'accept third party from visited'
|
||||
if (accept.checked)
|
||||
acceptThirdParty.checked = true;
|
||||
acceptThirdPartyMenu.selectedIndex = 1;
|
||||
|
||||
return accept.checked ? (acceptThirdParty.checked ? 0 : 1) : 2;
|
||||
return accept.checked ? 3 : 2;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Converts between network.cookie.cookieBehavior and the third-party cookie UI
|
||||
*/
|
||||
readAcceptThirdPartyCookies: function ()
|
||||
{
|
||||
var pref = document.getElementById("network.cookie.cookieBehavior");
|
||||
switch (pref.value)
|
||||
{
|
||||
case 0:
|
||||
return "always";
|
||||
case 1:
|
||||
return "never";
|
||||
case 2:
|
||||
return "never";
|
||||
case 3:
|
||||
return "visited";
|
||||
default:
|
||||
return undefined;
|
||||
}
|
||||
},
|
||||
|
||||
writeAcceptThirdPartyCookies: function ()
|
||||
{
|
||||
var accept = document.getElementById("acceptCookies");
|
||||
var acceptThirdParty = document.getElementById("acceptThirdParty");
|
||||
return accept.checked ? (acceptThirdParty.checked ? 0 : 1) : 2;
|
||||
var accept = document.getElementById("acceptThirdPartyMenu").selectedItem;
|
||||
switch (accept.value)
|
||||
{
|
||||
case "always":
|
||||
return 0;
|
||||
case "visited":
|
||||
return 3;
|
||||
case "never":
|
||||
return 1;
|
||||
default:
|
||||
return undefined;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -170,11 +170,19 @@
|
||||
label="&cookieExceptions.label;" accesskey="&cookieExceptions.accesskey;"
|
||||
preference="pref.privacy.disable_button.cookie_exceptions"/>
|
||||
</hbox>
|
||||
<checkbox id="acceptThirdParty" label="&acceptThirdParty.label;" class="indent"
|
||||
preference="network.cookie.cookieBehavior"
|
||||
accesskey="&acceptThirdParty.accesskey;"
|
||||
onsyncfrompreference="return gPrivacyPane.readAcceptThirdPartyCookies();"
|
||||
onsynctopreference="return gPrivacyPane.writeAcceptThirdPartyCookies();"/>
|
||||
<hbox id="acceptThirdPartyRow" class="indent">
|
||||
<label id="acceptThirdPartyLabel" control="acceptThirdPartyMenu"
|
||||
accesskey="&acceptThirdParty.pre.accesskey;">&acceptThirdParty.pre.label;</label>
|
||||
<menulist id="acceptThirdPartyMenu" preference="network.cookie.cookieBehavior"
|
||||
onsyncfrompreference="return gPrivacyPane.readAcceptThirdPartyCookies();"
|
||||
onsynctopreference="return gPrivacyPane.writeAcceptThirdPartyCookies();">
|
||||
<menupopup>
|
||||
<menuitem label="&acceptThirdParty.always.label;" value="always"/>
|
||||
<menuitem label="&acceptThirdParty.visited.label;" value="visited"/>
|
||||
<menuitem label="&acceptThirdParty.never.label;" value="never"/>
|
||||
</menupopup>
|
||||
</menulist>
|
||||
</hbox>
|
||||
<hbox id="keepRow" class="indent">
|
||||
<label id="keepUntil"
|
||||
control="keepCookiesUntil"
|
||||
|
@ -15,8 +15,8 @@ function test() {
|
||||
run_test_subset([
|
||||
test_custom_retention("acceptCookies", "remember"),
|
||||
test_custom_retention("acceptCookies", "custom"),
|
||||
test_custom_retention("acceptThirdParty", "remember"),
|
||||
test_custom_retention("acceptThirdParty", "custom"),
|
||||
test_custom_retention("acceptThirdPartyMenu", "remember", "always"),
|
||||
test_custom_retention("acceptThirdPartyMenu", "custom", "visited"),
|
||||
test_custom_retention("keepCookiesUntil", "remember", 1),
|
||||
test_custom_retention("keepCookiesUntil", "custom", 2),
|
||||
test_custom_retention("keepCookiesUntil", "custom", 0),
|
||||
|
@ -59,7 +59,8 @@ function test_dependent_elements(win) {
|
||||
});
|
||||
let independents = [
|
||||
win.document.getElementById("acceptCookies"),
|
||||
win.document.getElementById("acceptThirdParty"),
|
||||
win.document.getElementById("acceptThirdPartyLabel"),
|
||||
win.document.getElementById("acceptThirdPartyMenu")
|
||||
];
|
||||
independents.forEach(function(control) {
|
||||
ok(control, "the independent controls should exist");
|
||||
@ -124,7 +125,8 @@ function test_dependent_cookie_elements(win) {
|
||||
let pbautostart = win.document.getElementById("privateBrowsingAutoStart");
|
||||
ok(pbautostart, "the private browsing auto-start checkbox should exist");
|
||||
let controls = [
|
||||
win.document.getElementById("acceptThirdParty"),
|
||||
win.document.getElementById("acceptThirdPartyLabel"),
|
||||
win.document.getElementById("acceptThirdPartyMenu"),
|
||||
win.document.getElementById("keepUntil"),
|
||||
win.document.getElementById("keepCookiesUntil"),
|
||||
];
|
||||
@ -210,18 +212,22 @@ function test_dependent_prefs(win) {
|
||||
let controls = [
|
||||
win.document.getElementById("rememberHistory"),
|
||||
win.document.getElementById("rememberForms"),
|
||||
win.document.getElementById("acceptCookies"),
|
||||
win.document.getElementById("acceptThirdParty"),
|
||||
win.document.getElementById("acceptCookies")
|
||||
];
|
||||
controls.forEach(function(control) {
|
||||
ok(control, "the micro-management controls should exist");
|
||||
});
|
||||
|
||||
let thirdPartyCookieMenu = win.document.getElementById("acceptThirdPartyMenu");
|
||||
ok(thirdPartyCookieMenu, "the third-party cookie control should exist");
|
||||
|
||||
function expect_checked(checked) {
|
||||
controls.forEach(function(control) {
|
||||
is(control.checked, checked,
|
||||
control.getAttribute("id") + " should " + (checked ? "not " : "") + "be checked");
|
||||
});
|
||||
|
||||
is(thirdPartyCookieMenu.value == "always" || thirdPartyCookieMenu.value == "visited", checked, "third-party cookies should " + (checked ? "not " : "") + "be limited");
|
||||
}
|
||||
|
||||
// controls should be checked in remember mode
|
||||
@ -232,6 +238,8 @@ function test_dependent_prefs(win) {
|
||||
// even if they're unchecked in custom mode
|
||||
historymode.value = "custom";
|
||||
controlChanged(historymode);
|
||||
thirdPartyCookieMenu.value = "never";
|
||||
controlChanged(thirdPartyCookieMenu);
|
||||
controls.forEach(function(control) {
|
||||
control.checked = false;
|
||||
controlChanged(control);
|
||||
|
@ -182,8 +182,8 @@ var gPrivacyPane = {
|
||||
// select the remember forms history option
|
||||
document.getElementById("browser.formfill.enable").value = true;
|
||||
|
||||
// select the accept cookies option
|
||||
document.getElementById("network.cookie.cookieBehavior").value = 0;
|
||||
// select the limit cookies option
|
||||
document.getElementById("network.cookie.cookieBehavior").value = 3;
|
||||
// select the cookie lifetime policy option
|
||||
document.getElementById("network.cookie.lifetimePolicy").value = 0;
|
||||
|
||||
@ -366,9 +366,10 @@ var gPrivacyPane = {
|
||||
* network.cookie.cookieBehavior
|
||||
* - determines how the browser should handle cookies:
|
||||
* 0 means enable all cookies
|
||||
* 1 means reject third party cookies; see
|
||||
* netwerk/cookie/src/nsCookieService.cpp for a hairier definition
|
||||
* 1 means reject all third party cookies
|
||||
* 2 means disable all cookies
|
||||
* 3 means reject third party cookies unless at least one is already set for the eTLD
|
||||
* see netwerk/cookie/src/nsCookieService.cpp for details
|
||||
* network.cookie.lifetimePolicy
|
||||
* - determines how long cookies are stored:
|
||||
* 0 means keep cookies until they expire
|
||||
@ -384,25 +385,20 @@ var gPrivacyPane = {
|
||||
readAcceptCookies: function ()
|
||||
{
|
||||
var pref = document.getElementById("network.cookie.cookieBehavior");
|
||||
var acceptThirdParty = document.getElementById("acceptThirdParty");
|
||||
var acceptThirdPartyLabel = document.getElementById("acceptThirdPartyLabel");
|
||||
var acceptThirdPartyMenu = document.getElementById("acceptThirdPartyMenu");
|
||||
var keepUntil = document.getElementById("keepUntil");
|
||||
var menu = document.getElementById("keepCookiesUntil");
|
||||
|
||||
// enable the rest of the UI for anything other than "disable all cookies"
|
||||
var acceptCookies = (pref.value != 2);
|
||||
|
||||
acceptThirdParty.disabled = !acceptCookies;
|
||||
acceptThirdPartyLabel.disabled = acceptThirdPartyMenu.disabled = !acceptCookies;
|
||||
keepUntil.disabled = menu.disabled = this._autoStartPrivateBrowsing || !acceptCookies;
|
||||
|
||||
return acceptCookies;
|
||||
},
|
||||
|
||||
readAcceptThirdPartyCookies: function ()
|
||||
{
|
||||
var pref = document.getElementById("network.cookie.cookieBehavior");
|
||||
return pref.value == 0;
|
||||
},
|
||||
|
||||
/**
|
||||
* Enables/disables the "keep until" label and menulist in response to the
|
||||
* "accept cookies" checkbox being checked or unchecked.
|
||||
@ -410,20 +406,50 @@ var gPrivacyPane = {
|
||||
writeAcceptCookies: function ()
|
||||
{
|
||||
var accept = document.getElementById("acceptCookies");
|
||||
var acceptThirdParty = document.getElementById("acceptThirdParty");
|
||||
var acceptThirdPartyMenu = document.getElementById("acceptThirdPartyMenu");
|
||||
|
||||
// if we're enabling cookies, automatically check 'accept third party'
|
||||
// if we're enabling cookies, automatically select 'accept third party from visited'
|
||||
if (accept.checked)
|
||||
acceptThirdParty.checked = true;
|
||||
acceptThirdPartyMenu.selectedIndex = 1;
|
||||
|
||||
return accept.checked ? (acceptThirdParty.checked ? 0 : 1) : 2;
|
||||
return accept.checked ? 3 : 2;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Converts between network.cookie.cookieBehavior and the third-party cookie UI
|
||||
*/
|
||||
readAcceptThirdPartyCookies: function ()
|
||||
{
|
||||
var pref = document.getElementById("network.cookie.cookieBehavior");
|
||||
switch (pref.value)
|
||||
{
|
||||
case 0:
|
||||
return "always";
|
||||
case 1:
|
||||
return "never";
|
||||
case 2:
|
||||
return "never";
|
||||
case 3:
|
||||
return "visited";
|
||||
default:
|
||||
return undefined;
|
||||
}
|
||||
},
|
||||
|
||||
writeAcceptThirdPartyCookies: function ()
|
||||
{
|
||||
var accept = document.getElementById("acceptCookies");
|
||||
var acceptThirdParty = document.getElementById("acceptThirdParty");
|
||||
return accept.checked ? (acceptThirdParty.checked ? 0 : 1) : 2;
|
||||
var accept = document.getElementById("acceptThirdPartyMenu").selectedItem;
|
||||
switch (accept.value)
|
||||
{
|
||||
case "always":
|
||||
return 0;
|
||||
case "visited":
|
||||
return 3;
|
||||
case "never":
|
||||
return 1;
|
||||
default:
|
||||
return undefined;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
@ -503,7 +529,7 @@ var gPrivacyPane = {
|
||||
var settingsButton = document.getElementById("clearDataSettings");
|
||||
var sanitizeOnShutdownPref = document.getElementById("privacy.sanitize.sanitizeOnShutdown");
|
||||
|
||||
settingsButton.disabled = !sanitizeOnShutdownPref.value;
|
||||
settingsButton.disabled = !sanitizeOnShutdownPref.value;
|
||||
}
|
||||
|
||||
};
|
||||
|
@ -183,12 +183,23 @@
|
||||
label="&cookieExceptions.label;" accesskey="&cookieExceptions.accesskey;"
|
||||
preference="pref.privacy.disable_button.cookie_exceptions"/>
|
||||
</hbox>
|
||||
<checkbox id="acceptThirdParty" label="&acceptThirdParty.label;" class="indent"
|
||||
preference="network.cookie.cookieBehavior"
|
||||
accesskey="&acceptThirdParty.accesskey;"
|
||||
onsyncfrompreference="return gPrivacyPane.readAcceptThirdPartyCookies();"
|
||||
onsynctopreference="return gPrivacyPane.writeAcceptThirdPartyCookies();"/>
|
||||
|
||||
<hbox id="acceptThirdPartyRow" class="indent">
|
||||
<hbox id="acceptThirdPartyBox" align="center">
|
||||
<label id="acceptThirdPartyLabel" control="acceptThirdPartyMenu"
|
||||
accesskey="&acceptThirdParty.pre.accesskey;">&acceptThirdParty.pre.label;</label>
|
||||
<menulist id="acceptThirdPartyMenu" preference="network.cookie.cookieBehavior"
|
||||
onsyncfrompreference="return gPrivacyPane.readAcceptThirdPartyCookies();"
|
||||
onsynctopreference="return gPrivacyPane.writeAcceptThirdPartyCookies();">
|
||||
<menupopup>
|
||||
<menuitem label="&acceptThirdParty.always.label;" value="always"/>
|
||||
<menuitem label="&acceptThirdParty.visited.label;" value="visited"/>
|
||||
<menuitem label="&acceptThirdParty.never.label;" value="never"/>
|
||||
</menupopup>
|
||||
</menulist>
|
||||
</hbox>
|
||||
</hbox>
|
||||
|
||||
<hbox id="keepRow" class="indent">
|
||||
<hbox id="keepBox" align="center">
|
||||
<label id="keepUntil"
|
||||
|
@ -2,7 +2,12 @@
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
waitForExplicitFinish();
|
||||
// Allow all cookies, then actually set up the test
|
||||
SpecialPowers.pushPrefEnv({"set": [["network.cookie.cookieBehavior", 0]]}, initTest);
|
||||
}
|
||||
|
||||
function initTest() {
|
||||
const searchTerm = "example";
|
||||
const dummyTerm = "elpmaxe";
|
||||
|
||||
|
@ -163,6 +163,9 @@ var tests = [
|
||||
},
|
||||
|
||||
function test_all_sites_permission() {
|
||||
// apply the old default of allowing all cookies
|
||||
Services.prefs.setIntPref("network.cookie.cookieBehavior", 0);
|
||||
|
||||
// there should be no user-set pref for cookie behavior
|
||||
is(Services.prefs.getIntPref("network.cookie.cookieBehavior"), PERM_UNKNOWN,
|
||||
"network.cookie.cookieBehavior is expected default");
|
||||
|
@ -16,8 +16,8 @@ function test() {
|
||||
run_test_subset([
|
||||
test_custom_retention("acceptCookies", "remember"),
|
||||
test_custom_retention("acceptCookies", "custom"),
|
||||
test_custom_retention("acceptThirdParty", "remember"),
|
||||
test_custom_retention("acceptThirdParty", "custom"),
|
||||
test_custom_retention("acceptThirdPartyMenu", "remember", "always"),
|
||||
test_custom_retention("acceptThirdPartyMenu", "custom", "visited"),
|
||||
test_custom_retention("keepCookiesUntil", "remember", 1),
|
||||
test_custom_retention("keepCookiesUntil", "custom", 2),
|
||||
test_custom_retention("keepCookiesUntil", "custom", 0),
|
||||
|
@ -69,7 +69,8 @@ function test_dependent_elements(win) {
|
||||
});
|
||||
let independents = [
|
||||
win.document.getElementById("acceptCookies"),
|
||||
win.document.getElementById("acceptThirdParty"),
|
||||
win.document.getElementById("acceptThirdPartyLabel"),
|
||||
win.document.getElementById("acceptThirdPartyMenu")
|
||||
];
|
||||
independents.forEach(function(control) {
|
||||
ok(control, "the independent controls should exist");
|
||||
@ -133,7 +134,8 @@ function test_dependent_cookie_elements(win) {
|
||||
let pbautostart = win.document.getElementById("privateBrowsingAutoStart");
|
||||
ok(pbautostart, "the private browsing auto-start checkbox should exist");
|
||||
let controls = [
|
||||
win.document.getElementById("acceptThirdParty"),
|
||||
win.document.getElementById("acceptThirdPartyLabel"),
|
||||
win.document.getElementById("acceptThirdPartyMenu"),
|
||||
win.document.getElementById("keepUntil"),
|
||||
win.document.getElementById("keepCookiesUntil"),
|
||||
];
|
||||
@ -220,17 +222,21 @@ function test_dependent_prefs(win) {
|
||||
win.document.getElementById("rememberHistory"),
|
||||
win.document.getElementById("rememberForms"),
|
||||
win.document.getElementById("acceptCookies"),
|
||||
win.document.getElementById("acceptThirdParty"),
|
||||
];
|
||||
controls.forEach(function(control) {
|
||||
ok(control, "the micro-management controls should exist");
|
||||
});
|
||||
|
||||
let thirdPartyCookieMenu = win.document.getElementById("acceptThirdPartyMenu");
|
||||
ok(thirdPartyCookieMenu, "the third-party cookie control should exist");
|
||||
|
||||
function expect_checked(checked) {
|
||||
controls.forEach(function(control) {
|
||||
is(control.checked, checked,
|
||||
control.getAttribute("id") + " should " + (checked ? "not " : "") + "be checked");
|
||||
});
|
||||
|
||||
is(thirdPartyCookieMenu.value == "always" || thirdPartyCookieMenu.value == "visited", checked, "third-party cookies should " + (checked ? "not " : "") + "be limited");
|
||||
}
|
||||
|
||||
// controls should be checked in remember mode
|
||||
@ -241,6 +247,8 @@ function test_dependent_prefs(win) {
|
||||
// even if they're unchecked in custom mode
|
||||
historymode.value = "custom";
|
||||
controlChanged(historymode);
|
||||
thirdPartyCookieMenu.value = "never";
|
||||
controlChanged(thirdPartyCookieMenu);
|
||||
controls.forEach(function(control) {
|
||||
control.checked = false;
|
||||
controlChanged(control);
|
||||
|
@ -13,10 +13,9 @@ include $(topsrcdir)/config/config.mk
|
||||
EXTRA_COMPONENTS = \
|
||||
nsSessionStore.manifest \
|
||||
nsSessionStore.js \
|
||||
nsSessionStartup.js \
|
||||
$(NULL)
|
||||
|
||||
EXTRA_PP_COMPONENTS := nsSessionStartup.js
|
||||
|
||||
JS_MODULES_PATH := $(FINAL_TARGET)/modules/sessionstore
|
||||
|
||||
EXTRA_JS_MODULES := \
|
||||
|
@ -72,8 +72,11 @@ SessionStartup.prototype = {
|
||||
*/
|
||||
init: function sss_init() {
|
||||
// do not need to initialize anything in auto-started private browsing sessions
|
||||
if (PrivateBrowsingUtils.permanentPrivateBrowsing)
|
||||
if (PrivateBrowsingUtils.permanentPrivateBrowsing) {
|
||||
this._initialized = true;
|
||||
gOnceInitializedDeferred.resolve();
|
||||
return;
|
||||
}
|
||||
|
||||
_SessionFile.read().then(
|
||||
this._onSessionFileRead.bind(this)
|
||||
|
@ -3,8 +3,14 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
function test() {
|
||||
TestRunner.run();
|
||||
}
|
||||
|
||||
function runTests() {
|
||||
/** Test (B) for Bug 248970 **/
|
||||
waitForExplicitFinish();
|
||||
|
||||
// Let runTests() be a generator function.
|
||||
yield executeSoon(next);
|
||||
|
||||
let windowsToClose = [];
|
||||
let file = Services.dirsvc.get("TmpD", Ci.nsIFile);
|
||||
@ -157,7 +163,7 @@ function test() {
|
||||
aWin.gBrowser.removeTab(tab_C);
|
||||
aWin.gBrowser.removeTab(tab_B);
|
||||
|
||||
finish();
|
||||
next();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -4,6 +4,7 @@ ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL}
|
||||
ac_add_options --enable-update-packaging
|
||||
ac_add_options --with-l10n-base=../../l10n-central
|
||||
ac_add_options --enable-metro
|
||||
ac_add_options --with-windows-version=601
|
||||
|
||||
export MOZILLA_OFFICIAL=1
|
||||
|
||||
|
@ -4,11 +4,17 @@
|
||||
|
||||
const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
|
||||
|
||||
const BRAND_SHORT_NAME = Cc["@mozilla.org/intl/stringbundle;1"]
|
||||
.getService(Ci.nsIStringBundleService)
|
||||
.createBundle("chrome://branding/locale/brand.properties")
|
||||
.GetStringFromName("brandShortName");
|
||||
|
||||
this.EXPORTED_SYMBOLS = [ "CmdAddonFlags", "CmdCommands" ];
|
||||
|
||||
Cu.import("resource:///modules/devtools/gcli.jsm");
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/osfile.jsm")
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "gDevTools",
|
||||
"resource:///modules/devtools/gDevTools.jsm");
|
||||
@ -768,59 +774,86 @@ XPCOMUtils.defineLazyModuleGetter(this, "TargetFactory",
|
||||
return;
|
||||
}
|
||||
|
||||
let dir = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsILocalFile);
|
||||
dir.initWithPath(dirName);
|
||||
if (!dir.exists() || !dir.isDirectory()) {
|
||||
throw new Error('\'' + dirName + '\' is not a directory.');
|
||||
}
|
||||
|
||||
let en = dir.directoryEntries.QueryInterface(Ci.nsIDirectoryEnumerator);
|
||||
|
||||
while (true) {
|
||||
let file = en.nextFile;
|
||||
if (!file) {
|
||||
break;
|
||||
let promise = OS.File.stat(dirName);
|
||||
promise = promise.then(
|
||||
function onSuccess(stat) {
|
||||
if (!stat.isDir) {
|
||||
throw new Error('\'' + dirName + '\' is not a directory.');
|
||||
} else {
|
||||
return dirName;
|
||||
}
|
||||
},
|
||||
function onFailure(reason) {
|
||||
if (reason instanceof OS.File.Error && reason.becauseNoSuchFile) {
|
||||
throw new Error('\'' + dirName + '\' does not exist.');
|
||||
} else {
|
||||
throw reason;
|
||||
}
|
||||
}
|
||||
if (file.leafName.match(/.*\.mozcmd$/) && file.isFile() && file.isReadable()) {
|
||||
loadCommandFile(file, aSandboxPrincipal);
|
||||
);
|
||||
|
||||
promise.then(
|
||||
function onSuccess() {
|
||||
let iterator = new OS.File.DirectoryIterator(dirName);
|
||||
let iterPromise = iterator.forEach(
|
||||
function onEntry(entry) {
|
||||
if (entry.name.match(/.*\.mozcmd$/) && !entry.isDir) {
|
||||
loadCommandFile(entry, aSandboxPrincipal);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
iterPromise.then(
|
||||
function onSuccess() {
|
||||
iterator.close();
|
||||
},
|
||||
function onFailure(reason) {
|
||||
iterator.close();
|
||||
throw reason;
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Load the commands from a single file
|
||||
* @param nsIFile aFile The file containing the commands that we should read
|
||||
* @param OS.File.DirectoryIterator.Entry aFileEntry The DirectoryIterator
|
||||
* Entry of the file containing the commands that we should read
|
||||
* @param nsIPrincipal aSandboxPrincipal Scope object for the Sandbox in which
|
||||
* we eval the script from the .mozcmd file. This should be a chrome window.
|
||||
*/
|
||||
function loadCommandFile(aFile, aSandboxPrincipal) {
|
||||
NetUtil.asyncFetch(aFile, function refresh_fetch(aStream, aStatus) {
|
||||
if (!Components.isSuccessCode(aStatus)) {
|
||||
console.error("NetUtil.asyncFetch(" + aFile.path + ",..) failed. Status=" + aStatus);
|
||||
return;
|
||||
function loadCommandFile(aFileEntry, aSandboxPrincipal) {
|
||||
let promise = OS.File.read(aFileEntry.path);
|
||||
promise = promise.then(
|
||||
function onSuccess(array) {
|
||||
let decoder = new TextDecoder();
|
||||
let source = decoder.decode(array);
|
||||
|
||||
let sandbox = new Cu.Sandbox(aSandboxPrincipal, {
|
||||
sandboxPrototype: aSandboxPrincipal,
|
||||
wantXrays: false,
|
||||
sandboxName: aFileEntry.path
|
||||
});
|
||||
let data = Cu.evalInSandbox(source, sandbox, "1.8", aFileEntry.name, 1);
|
||||
|
||||
if (!Array.isArray(data)) {
|
||||
console.error("Command file '" + aFileEntry.name + "' does not have top level array.");
|
||||
return;
|
||||
}
|
||||
|
||||
data.forEach(function(commandSpec) {
|
||||
gcli.addCommand(commandSpec);
|
||||
commands.push(commandSpec.name);
|
||||
});
|
||||
|
||||
},
|
||||
function onError(reason) {
|
||||
console.error("OS.File.read(" + aFileEntry.path + ") failed.");
|
||||
throw reason;
|
||||
}
|
||||
|
||||
let source = NetUtil.readInputStreamToString(aStream, aStream.available());
|
||||
aStream.close();
|
||||
|
||||
let sandbox = new Cu.Sandbox(aSandboxPrincipal, {
|
||||
sandboxPrototype: aSandboxPrincipal,
|
||||
wantXrays: false,
|
||||
sandboxName: aFile.path
|
||||
});
|
||||
let data = Cu.evalInSandbox(source, sandbox, "1.8", aFile.leafName, 1);
|
||||
|
||||
if (!Array.isArray(data)) {
|
||||
console.error("Command file '" + aFile.leafName + "' does not have top level array.");
|
||||
return;
|
||||
}
|
||||
|
||||
data.forEach(function(commandSpec) {
|
||||
gcli.addCommand(commandSpec);
|
||||
commands.push(commandSpec.name);
|
||||
});
|
||||
}.bind(this));
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1763,14 +1796,15 @@ XPCOMUtils.defineLazyModuleGetter(this, "TargetFactory",
|
||||
* >> restart --nocache
|
||||
* - restarts immediately and starts Firefox without using cache
|
||||
*/
|
||||
|
||||
gcli.addCommand({
|
||||
name: "restart",
|
||||
description: gcli.lookup("restartFirefoxDesc"),
|
||||
description: gcli.lookupFormat("restartBrowserDesc", [BRAND_SHORT_NAME]),
|
||||
params: [
|
||||
{
|
||||
name: "nocache",
|
||||
type: "boolean",
|
||||
description: gcli.lookup("restartFirefoxNocacheDesc")
|
||||
description: gcli.lookup("restartBrowserNocacheDesc")
|
||||
}
|
||||
],
|
||||
returnType: "string",
|
||||
@ -1779,7 +1813,7 @@ XPCOMUtils.defineLazyModuleGetter(this, "TargetFactory",
|
||||
.createInstance(Ci.nsISupportsPRBool);
|
||||
Services.obs.notifyObservers(canceled, "quit-application-requested", "restart");
|
||||
if (canceled.data) {
|
||||
return gcli.lookup("restartFirefoxRequestCancelled");
|
||||
return gcli.lookup("restartBrowserRequestCancelled");
|
||||
}
|
||||
|
||||
// disable loading content from cache.
|
||||
@ -1791,7 +1825,7 @@ XPCOMUtils.defineLazyModuleGetter(this, "TargetFactory",
|
||||
Cc['@mozilla.org/toolkit/app-startup;1']
|
||||
.getService(Ci.nsIAppStartup)
|
||||
.quit(Ci.nsIAppStartup.eAttemptQuit | Ci.nsIAppStartup.eRestart);
|
||||
return gcli.lookup("restartFirefoxRestarting");
|
||||
return gcli.lookupFormat("restartBrowserRestarting", [BRAND_SHORT_NAME]);
|
||||
}
|
||||
});
|
||||
}(this));
|
||||
@ -1834,8 +1868,8 @@ XPCOMUtils.defineLazyModuleGetter(this, "TargetFactory",
|
||||
{
|
||||
name: "chrome",
|
||||
type: "boolean",
|
||||
description: gcli.lookup("screenshotChromeDesc"),
|
||||
manual: gcli.lookup("screenshotChromeManual")
|
||||
description: gcli.lookupFormat("screenshotChromeDesc", [BRAND_SHORT_NAME]),
|
||||
manual: gcli.lookupFormat("screenshotChromeManual", [BRAND_SHORT_NAME])
|
||||
},
|
||||
{
|
||||
name: "delay",
|
||||
|
@ -223,13 +223,23 @@ exports.StringType = StringType;
|
||||
|
||||
|
||||
/**
|
||||
* We don't currently plan to distinguish between integers and floats
|
||||
* We distinguish between integers and floats with the _allowFloat flag.
|
||||
*/
|
||||
function NumberType(typeSpec) {
|
||||
// Default to integer values
|
||||
this._allowFloat = !!typeSpec.allowFloat;
|
||||
|
||||
if (typeSpec) {
|
||||
this._min = typeSpec.min;
|
||||
this._max = typeSpec.max;
|
||||
this._step = typeSpec.step || 1;
|
||||
|
||||
if (!this._allowFloat &&
|
||||
(this._isFloat(this._min) ||
|
||||
this._isFloat(this._max) ||
|
||||
this._isFloat(this._step))) {
|
||||
throw new Error('allowFloat is false, but non-integer values given in type spec');
|
||||
}
|
||||
}
|
||||
else {
|
||||
this._step = 1;
|
||||
@ -274,7 +284,19 @@ NumberType.prototype.parse = function(arg) {
|
||||
return new Conversion(undefined, arg, Status.INCOMPLETE, '');
|
||||
}
|
||||
|
||||
var value = parseInt(arg.text, 10);
|
||||
if (!this._allowFloat && (arg.text.indexOf('.') !== -1)) {
|
||||
return new Conversion(undefined, arg, Status.ERROR,
|
||||
l10n.lookupFormat('typesNumberNotInt', [ arg.text ]));
|
||||
}
|
||||
|
||||
var value;
|
||||
if (this._allowFloat) {
|
||||
value = parseFloat(arg.text);
|
||||
}
|
||||
else {
|
||||
value = parseInt(arg.text, 10);
|
||||
}
|
||||
|
||||
if (isNaN(value)) {
|
||||
return new Conversion(undefined, arg, Status.ERROR,
|
||||
l10n.lookupFormat('typesNumberNan', [ arg.text ]));
|
||||
@ -336,6 +358,14 @@ NumberType.prototype._boundsCheck = function(value) {
|
||||
return value;
|
||||
};
|
||||
|
||||
/**
|
||||
* Return true if the given value is a finite number and not an integer, else
|
||||
* return false.
|
||||
*/
|
||||
NumberType.prototype._isFloat = function(value) {
|
||||
return ((typeof value === 'number') && isFinite(value) && (value % 1 !== 0));
|
||||
};
|
||||
|
||||
NumberType.prototype.name = 'number';
|
||||
|
||||
exports.NumberType = NumberType;
|
||||
|
@ -324,6 +324,52 @@ exports.testSingleNumber = function() {
|
||||
assert.is('tsu', requ.commandAssignment.value.name);
|
||||
assert.is('x', assign1.arg.text);
|
||||
assert.is(undefined, assign1.value);
|
||||
|
||||
update({ typed: 'tsu 1.5', cursor: { start: 7, end: 7 } });
|
||||
assert.is( 'VVVVEEE', statuses);
|
||||
assert.is(Status.ERROR, status);
|
||||
assert.is('tsu', requ.commandAssignment.value.name);
|
||||
assert.is('1.5', assign1.arg.text);
|
||||
assert.is(undefined, assign1.value);
|
||||
};
|
||||
|
||||
exports.testSingleFloat = function() {
|
||||
update({ typed: 'tsf', cursor: { start: 3, end: 3 } });
|
||||
assert.is( 'VVV', statuses);
|
||||
assert.is(Status.ERROR, status);
|
||||
assert.is('tsf', requ.commandAssignment.value.name);
|
||||
assert.is('', assign1.arg.text);
|
||||
assert.is(undefined, assign1.value);
|
||||
|
||||
update({ typed: 'tsf ', cursor: { start: 4, end: 4 } });
|
||||
assert.is( 'VVVV', statuses);
|
||||
assert.is(Status.ERROR, status);
|
||||
assert.is('tsf', requ.commandAssignment.value.name);
|
||||
assert.is('', assign1.arg.text);
|
||||
assert.is(undefined, assign1.value);
|
||||
|
||||
update({ typed: 'tsf 1', cursor: { start: 5, end: 5 } });
|
||||
assert.is( 'VVVVV', statuses);
|
||||
assert.is(Status.VALID, status);
|
||||
assert.is('tsf', requ.commandAssignment.value.name);
|
||||
assert.is('1', assign1.arg.text);
|
||||
assert.is(1, assign1.value);
|
||||
assert.is('number', typeof assign1.value);
|
||||
|
||||
update({ typed: 'tsf x', cursor: { start: 5, end: 5 } });
|
||||
assert.is( 'VVVVE', statuses);
|
||||
assert.is(Status.ERROR, status);
|
||||
assert.is('tsf', requ.commandAssignment.value.name);
|
||||
assert.is('x', assign1.arg.text);
|
||||
assert.is(undefined, assign1.value);
|
||||
|
||||
update({ typed: 'tsf 1.5', cursor: { start: 7, end: 7 } });
|
||||
assert.is( 'VVVVVVV', statuses);
|
||||
assert.is(Status.VALID, status);
|
||||
assert.is('tsf', requ.commandAssignment.value.name);
|
||||
assert.is('1.5', assign1.arg.text);
|
||||
assert.is(1.5, assign1.value);
|
||||
assert.is('number', typeof assign1.value);
|
||||
};
|
||||
|
||||
exports.testElement = function(options) {
|
||||
|
@ -203,6 +203,34 @@ exports.testIncrDecr = function() {
|
||||
check('tsu 10', KEY_DOWNS_TO, 'tsu 9');
|
||||
check('tsu 100', KEY_DOWNS_TO, 'tsu 10');
|
||||
|
||||
check('tsf -70', KEY_UPS_TO, 'tsf -6.5');
|
||||
check('tsf -6.5', KEY_UPS_TO, 'tsf -6');
|
||||
check('tsf -6', KEY_UPS_TO, 'tsf -4.5');
|
||||
check('tsf -4.5', KEY_UPS_TO, 'tsf -3');
|
||||
check('tsf -4', KEY_UPS_TO, 'tsf -3');
|
||||
check('tsf -3', KEY_UPS_TO, 'tsf -1.5');
|
||||
check('tsf -1.5', KEY_UPS_TO, 'tsf 0');
|
||||
check('tsf 0', KEY_UPS_TO, 'tsf 1.5');
|
||||
check('tsf 1.5', KEY_UPS_TO, 'tsf 3');
|
||||
check('tsf 2', KEY_UPS_TO, 'tsf 3');
|
||||
check('tsf 3', KEY_UPS_TO, 'tsf 4.5');
|
||||
check('tsf 5', KEY_UPS_TO, 'tsf 6');
|
||||
check('tsf 100', KEY_UPS_TO, 'tsf -6.5');
|
||||
|
||||
check('tsf -70', KEY_DOWNS_TO, 'tsf 11.5');
|
||||
check('tsf -6.5', KEY_DOWNS_TO, 'tsf -6.5');
|
||||
check('tsf -6', KEY_DOWNS_TO, 'tsf -6.5');
|
||||
check('tsf -4.5', KEY_DOWNS_TO, 'tsf -6');
|
||||
check('tsf -4', KEY_DOWNS_TO, 'tsf -4.5');
|
||||
check('tsf -3', KEY_DOWNS_TO, 'tsf -4.5');
|
||||
check('tsf -1.5', KEY_DOWNS_TO, 'tsf -3');
|
||||
check('tsf 0', KEY_DOWNS_TO, 'tsf -1.5');
|
||||
check('tsf 1.5', KEY_DOWNS_TO, 'tsf 0');
|
||||
check('tsf 2', KEY_DOWNS_TO, 'tsf 1.5');
|
||||
check('tsf 3', KEY_DOWNS_TO, 'tsf 1.5');
|
||||
check('tsf 5', KEY_DOWNS_TO, 'tsf 4.5');
|
||||
check('tsf 100', KEY_DOWNS_TO, 'tsf 11.5');
|
||||
|
||||
// Bug 707007 - GCLI increment and decrement operations cycle through
|
||||
// selection options in the wrong order
|
||||
check('tselarr 1', KEY_DOWNS_TO, 'tselarr 2');
|
||||
|
@ -60,6 +60,11 @@ exports.shutdown = function(options) {
|
||||
};
|
||||
|
||||
exports.testPredictions = function(options) {
|
||||
if (options.isJsdom) {
|
||||
assert.log('Skipping checks due to jsdom document.stylsheets support.');
|
||||
return;
|
||||
}
|
||||
|
||||
var resource1 = types.getType('resource');
|
||||
var options1 = resource1.getLookup();
|
||||
// firefox doesn't support digging into scripts/stylesheets
|
||||
@ -67,7 +72,7 @@ exports.testPredictions = function(options) {
|
||||
assert.ok(options1.length > 1, 'have all resources');
|
||||
}
|
||||
else {
|
||||
assert.log('Skipping checks due to jsdom/firefox document.stylsheets support.');
|
||||
assert.log('Skipping checks due to firefox document.stylsheets support.');
|
||||
}
|
||||
options1.forEach(function(prediction) {
|
||||
checkPrediction(resource1, prediction);
|
||||
@ -80,7 +85,7 @@ exports.testPredictions = function(options) {
|
||||
assert.ok(options2.length > 1, 'have js resources');
|
||||
}
|
||||
else {
|
||||
assert.log('Skipping checks due to jsdom/firefox document.stylsheets support.');
|
||||
assert.log('Skipping checks due to firefox document.stylsheets support.');
|
||||
}
|
||||
options2.forEach(function(prediction) {
|
||||
checkPrediction(resource2, prediction);
|
||||
@ -93,7 +98,7 @@ exports.testPredictions = function(options) {
|
||||
assert.ok(options3.length >= 1, 'have css resources');
|
||||
}
|
||||
else {
|
||||
assert.log('Skipping checks due to jsdom/firefox document.stylsheets support.');
|
||||
assert.log('Skipping checks due to firefox document.stylsheets support.');
|
||||
}
|
||||
options3.forEach(function(prediction) {
|
||||
checkPrediction(resource3, prediction);
|
||||
|
@ -114,10 +114,10 @@ exports.testActivate = function(options) {
|
||||
options: [ 'true' ]
|
||||
}, options);
|
||||
|
||||
type('asdf', {
|
||||
type('wxqy', {
|
||||
important: false,
|
||||
options: [ ],
|
||||
error: 'Can\'t use \'asdf\'.'
|
||||
error: 'Can\'t use \'wxqy\'.'
|
||||
}, options);
|
||||
|
||||
type('', { }, options);
|
||||
|
@ -72,6 +72,7 @@ mockCommands.setup = function() {
|
||||
canon.addCommand(mockCommands.tsb);
|
||||
canon.addCommand(mockCommands.tss);
|
||||
canon.addCommand(mockCommands.tsu);
|
||||
canon.addCommand(mockCommands.tsf);
|
||||
canon.addCommand(mockCommands.tsn);
|
||||
canon.addCommand(mockCommands.tsnDif);
|
||||
canon.addCommand(mockCommands.tsnExt);
|
||||
@ -99,6 +100,7 @@ mockCommands.shutdown = function() {
|
||||
canon.removeCommand(mockCommands.tsb);
|
||||
canon.removeCommand(mockCommands.tss);
|
||||
canon.removeCommand(mockCommands.tsu);
|
||||
canon.removeCommand(mockCommands.tsf);
|
||||
canon.removeCommand(mockCommands.tsn);
|
||||
canon.removeCommand(mockCommands.tsnDif);
|
||||
canon.removeCommand(mockCommands.tsnExt);
|
||||
@ -231,6 +233,12 @@ mockCommands.tsu = {
|
||||
exec: createExec('tsu')
|
||||
};
|
||||
|
||||
mockCommands.tsf = {
|
||||
name: 'tsf',
|
||||
params: [ { name: 'num', type: { name: 'number', allowFloat: true, max: 11.5, min: -6.5, step: 1.5 } } ],
|
||||
exec: createExec('tsf')
|
||||
};
|
||||
|
||||
mockCommands.tsn = {
|
||||
name: 'tsn'
|
||||
};
|
||||
|
@ -4,6 +4,11 @@
|
||||
|
||||
const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
|
||||
|
||||
const BRAND_SHORT_NAME = Cc["@mozilla.org/intl/stringbundle;1"].
|
||||
getService(Ci.nsIStringBundleService).
|
||||
createBundle("chrome://branding/locale/brand.properties").
|
||||
GetStringFromName("brandShortName");
|
||||
|
||||
this.EXPORTED_SYMBOLS = [ ];
|
||||
|
||||
Cu.import("resource:///modules/devtools/gcli.jsm");
|
||||
@ -17,14 +22,14 @@ gcli.addCommand({
|
||||
gcli.addCommand({
|
||||
name: 'resize on',
|
||||
description: gcli.lookup('resizeModeOnDesc'),
|
||||
manual: gcli.lookup('resizeModeManual'),
|
||||
manual: gcli.lookupFormat('resizeModeManual', [BRAND_SHORT_NAME]),
|
||||
exec: gcli_cmd_resize
|
||||
});
|
||||
|
||||
gcli.addCommand({
|
||||
name: 'resize off',
|
||||
description: gcli.lookup('resizeModeOffDesc'),
|
||||
manual: gcli.lookup('resizeModeManual'),
|
||||
manual: gcli.lookupFormat('resizeModeManual', [BRAND_SHORT_NAME]),
|
||||
exec: gcli_cmd_resize
|
||||
});
|
||||
|
||||
@ -34,7 +39,7 @@ gcli.addCommand({
|
||||
buttonClass: "command-button",
|
||||
tooltipText: gcli.lookup("resizeModeToggleTooltip"),
|
||||
description: gcli.lookup('resizeModeToggleDesc'),
|
||||
manual: gcli.lookup('resizeModeManual'),
|
||||
manual: gcli.lookupFormat('resizeModeManual', [BRAND_SHORT_NAME]),
|
||||
state: {
|
||||
isChecked: function(aTarget) {
|
||||
let browserWindow = aTarget.tab.ownerDocument.defaultView;
|
||||
|
@ -747,6 +747,7 @@ bin/libfreebl_32int64_3.so
|
||||
|
||||
#ifdef MOZ_METRO
|
||||
@BINPATH@/components/MetroUIUtils.js
|
||||
@BINPATH@/components/MetroUIUtils.manifest
|
||||
[metro]
|
||||
; gre resources
|
||||
@BINPATH@/CommandExecuteHandler@BIN_SUFFIX@
|
||||
|
@ -92,6 +92,10 @@ typesNumberMax=%1$S is greater than maximum allowed: %2$S.
|
||||
# message is displayed.
|
||||
typesNumberMin=%1$S is smaller than minimum allowed: %2$S.
|
||||
|
||||
# LOCALIZATION NOTE (typesNumberNotInt): When the command line is passed a
|
||||
# number, but the number has a decimal part and floats are not allowed.
|
||||
typesNumberNotInt='%S' must be an integer.
|
||||
|
||||
# LOCALIZATION NOTE (typesSelectionNomatch): When the command line is passed
|
||||
# an option with a limited number of correct values, but the passed value is
|
||||
# not one of them, this error message is displayed.
|
||||
@ -333,7 +337,7 @@ introManual=Redisplay the message that is shown to new users until they click th
|
||||
# first opens the developer toolbar to explain the command line, and is shown
|
||||
# each time it is opened until the user clicks the 'Got it!' button. This
|
||||
# string is the opening paragraph of the intro text.
|
||||
introTextOpening=The Firefox command line is designed for developers. It focuses on speed of input over JavaScript syntax and a rich display over monospace output.
|
||||
introTextOpening=This command line is designed for developers. It focuses on speed of input over JavaScript syntax and a rich display over monospace output.
|
||||
|
||||
# LOCALIZATION NOTE (introTextCommands): For information about the 'intro
|
||||
# text' see introTextOpening. The second paragraph is in 2 sections, the first
|
||||
|
@ -73,12 +73,14 @@ screenshotClipboardManual=True if you want to copy the screenshot instead of sav
|
||||
# LOCALIZATION NOTE (screenshotChromeDesc) A very short string to describe
|
||||
# the 'chrome' parameter to the 'screenshot' command, which is displayed in
|
||||
# a dialog when the user is using this command.
|
||||
screenshotChromeDesc=Capture Firefox chrome window? (true/false)
|
||||
# The argument (%1$S) is the browser name.
|
||||
screenshotChromeDesc=Capture %1$S chrome window? (true/false)
|
||||
|
||||
# LOCALIZATION NOTE (screenshotChromeManual) A fuller description of the
|
||||
# 'chrome' parameter to the 'screenshot' command, displayed when the user
|
||||
# asks for help on what it does.
|
||||
screenshotChromeManual=True if you want to take the screenshot of the Firefox window rather than the web page's content window.
|
||||
# The argument (%1$S) is the browser name.
|
||||
screenshotChromeManual=True if you want to take the screenshot of the %1$S window rather than the web page's content window.
|
||||
|
||||
# LOCALIZATION NOTE (screenshotGroupOptions) A label for the optional options of
|
||||
# the screenshot command.
|
||||
@ -131,23 +133,25 @@ screenshotErrorCopying=Error occurred while copying to clipboard.
|
||||
# screenshot is successfully copied to the clipboard.
|
||||
screenshotCopied=Copied to clipboard.
|
||||
|
||||
# LOCALIZATION NOTE (restartFirefoxDesc) A very short description of the
|
||||
# LOCALIZATION NOTE (restartBrowserDesc) A very short description of the
|
||||
# 'restart' command. This string is designed to be shown in a menu alongside the
|
||||
# command name, which is why it should be as short as possible.
|
||||
restartFirefoxDesc=Restart Firefox
|
||||
# The argument (%1$S) is the browser name.
|
||||
restartBrowserDesc=Restart %1$S
|
||||
|
||||
# LOCALIZATION NOTE (restartFirefoxNocacheDesc) A very short string to
|
||||
# LOCALIZATION NOTE (restartBrowserNocacheDesc) A very short string to
|
||||
# describe the 'nocache' parameter to the 'restart' command, which is
|
||||
# displayed in a dialog when the user is using this command.
|
||||
restartFirefoxNocacheDesc=Disables loading content from cache upon restart
|
||||
restartBrowserNocacheDesc=Disables loading content from cache upon restart
|
||||
|
||||
# LOCALIZATION NOTE (restartFirefoxRequestCancelled) A string displayed to the
|
||||
# LOCALIZATION NOTE (restartBrowserRequestCancelled) A string displayed to the
|
||||
# user when a scheduled restart has been aborted by the user.
|
||||
restartFirefoxRequestCancelled=Restart request cancelled by user.
|
||||
restartBrowserRequestCancelled=Restart request cancelled by user.
|
||||
|
||||
# LOCALIZATION NOTE (restartFirefoxRestarting) A string displayed to the
|
||||
# LOCALIZATION NOTE (restartBrowserRestarting) A string displayed to the
|
||||
# user when a restart has been initiated without a delay.
|
||||
restartFirefoxRestarting=Restarting Firefox…
|
||||
# The argument (%1$S) is the browser name.
|
||||
restartBrowserRestarting=Restarting %1$S…
|
||||
|
||||
# LOCALIZATION NOTE (inspectDesc) A very short description of the 'inspect'
|
||||
# command. See inspectManual for a fuller description of what it does. This
|
||||
@ -504,7 +508,8 @@ resizeModeDesc=Control Responsive Design Mode
|
||||
|
||||
# LOCALIZATION NOTE (resizeModeManual) A fuller description of the 'resize'
|
||||
# command, displayed when the user asks for help on what it does.
|
||||
resizeModeManual=Responsive websites respond to their environment, so they look good on a mobile display, a cinema display and everything in-between. Responsive Design Mode allows you to easily test a variety of page sizes in Firefox without needing to resize your whole browser.
|
||||
# The argument (%1$S) is the browser name.
|
||||
resizeModeManual=Responsive websites respond to their environment, so they look good on a mobile display, a cinema display and everything in-between. Responsive Design Mode allows you to easily test a variety of page sizes in %1$S without needing to resize your whole browser.
|
||||
|
||||
# LOCALIZATION NOTE (cmdDesc) A very short description of the 'cmd'
|
||||
# command. This string is designed to be shown in a menu alongside the command
|
||||
|
@ -27,8 +27,11 @@
|
||||
<!ENTITY acceptCookies.label "Accept cookies from sites">
|
||||
<!ENTITY acceptCookies.accesskey "A">
|
||||
|
||||
<!ENTITY acceptThirdParty.label "Accept third-party cookies">
|
||||
<!ENTITY acceptThirdParty.accesskey "c">
|
||||
<!ENTITY acceptThirdParty.pre.label "Accept third-party cookies:">
|
||||
<!ENTITY acceptThirdParty.pre.accesskey "c">
|
||||
<!ENTITY acceptThirdParty.always.label "Always">
|
||||
<!ENTITY acceptThirdParty.never.label "Never">
|
||||
<!ENTITY acceptThirdParty.visited.label "From visited">
|
||||
|
||||
<!ENTITY keepUntil.label "Keep until:">
|
||||
<!ENTITY keepUntil.accesskey "K">
|
||||
|
@ -8,7 +8,6 @@ all = browser/locales/all-locales
|
||||
|
||||
[compare]
|
||||
dirs = browser
|
||||
browser/metro
|
||||
extensions/reporter
|
||||
other-licenses/branding/firefox
|
||||
browser/branding/official
|
||||
|
@ -79,18 +79,18 @@ fi
|
||||
|
||||
if [ "$MOZ_WIDGET_TOOLKIT" = "gtk2" -o "$MOZ_WIDGET_TOOLKIT" = "qt" ]; then
|
||||
add_makefiles "
|
||||
browser/themes/gnomestripe/Makefile
|
||||
browser/themes/gnomestripe/communicator/Makefile
|
||||
browser/themes/linux/Makefile
|
||||
browser/themes/linux/communicator/Makefile
|
||||
"
|
||||
elif [ "$MOZ_WIDGET_TOOLKIT" = "cocoa" ]; then
|
||||
add_makefiles "
|
||||
browser/themes/pinstripe/Makefile
|
||||
browser/themes/pinstripe/communicator/Makefile
|
||||
browser/themes/osx/Makefile
|
||||
browser/themes/osx/communicator/Makefile
|
||||
"
|
||||
else
|
||||
add_makefiles "
|
||||
browser/themes/winstripe/Makefile
|
||||
browser/themes/winstripe/communicator/Makefile
|
||||
browser/themes/windows/Makefile
|
||||
browser/themes/windows/communicator/Makefile
|
||||
"
|
||||
fi
|
||||
|
||||
|
@ -145,6 +145,7 @@
|
||||
<key id="key_findPrevious2" key="g" modifiers="accel,shift" command="cmd_findPrevious"/>
|
||||
<key id="key_quit" key="q" modifiers="accel" command="cmd_quit"/>
|
||||
<key id="key_addBoomkark" key="d" modifiers="accel" command="cmd_addBookmark"/>
|
||||
<key id="key_console" key="j" modifiers="accel,shift" oncommand="PanelUI.show('console-container')"/>
|
||||
|
||||
<!-- manage tabs -->
|
||||
<key id="key_newTab" key="t" modifiers="accel" command="cmd_newTab"/>
|
||||
|
@ -80,15 +80,20 @@ function handleRequest(aSubject, aTopic, aData) {
|
||||
function (error) {
|
||||
// bug 827146 -- In the future, the UI should catch NO_DEVICES_FOUND
|
||||
// and allow the user to plug in a device, instead of immediately failing.
|
||||
let msg = Cc["@mozilla.org/supports-string;1"].
|
||||
createInstance(Ci.nsISupportsString);
|
||||
msg.data = error;
|
||||
Services.obs.notifyObservers(msg, "getUserMedia:response:deny", callID);
|
||||
Cu.reportError(error);
|
||||
denyRequest(callID, error);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function denyRequest(aCallID, aError) {
|
||||
let msg = null;
|
||||
if (aError) {
|
||||
msg = Cc["@mozilla.org/supports-string;1"].createInstance(Ci.nsISupportsString);
|
||||
msg.data = aError;
|
||||
}
|
||||
Services.obs.notifyObservers(msg, "getUserMedia:response:deny", aCallID);
|
||||
}
|
||||
|
||||
function prompt(aBrowser, aCallID, aAudioRequested, aVideoRequested, aDevices) {
|
||||
let audioDevices = [];
|
||||
let videoDevices = [];
|
||||
@ -113,8 +118,10 @@ function prompt(aBrowser, aCallID, aAudioRequested, aVideoRequested, aDevices) {
|
||||
requestType = "Microphone";
|
||||
else if (videoDevices.length)
|
||||
requestType = "Camera";
|
||||
else
|
||||
else {
|
||||
denyRequest(aCallID, "NO_DEVICES_FOUND");
|
||||
return;
|
||||
}
|
||||
|
||||
let host = aBrowser.contentDocument.documentURIObject.asciiHost;
|
||||
let chromeDoc = aBrowser.ownerDocument;
|
||||
@ -173,7 +180,7 @@ function prompt(aBrowser, aCallID, aAudioRequested, aVideoRequested, aDevices) {
|
||||
}
|
||||
|
||||
if (allowedDevices.Count() == 0) {
|
||||
Services.obs.notifyObservers(null, "getUserMedia:response:deny", aCallID);
|
||||
denyRequest(aCallID);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -197,7 +204,7 @@ function prompt(aBrowser, aCallID, aAudioRequested, aVideoRequested, aDevices) {
|
||||
label: stringBundle.getString("getUserMedia.denyRequest.label"),
|
||||
accessKey: stringBundle.getString("getUserMedia.denyRequest.accesskey"),
|
||||
callback: function () {
|
||||
Services.obs.notifyObservers(null, "getUserMedia:response:deny", aCallID);
|
||||
denyRequest(aCallID);
|
||||
}
|
||||
}];
|
||||
|
||||
|
@ -9,21 +9,13 @@ VPATH = @srcdir@
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
#
|
||||
# Theme Selection
|
||||
#
|
||||
# Windows Winstripe
|
||||
# GNOME/Linux Gnomestripe
|
||||
# MacOS X Pinstripe
|
||||
#
|
||||
|
||||
ifeq (cocoa,$(MOZ_WIDGET_TOOLKIT))
|
||||
DIRS = pinstripe
|
||||
DIRS = osx
|
||||
else
|
||||
DIRS = winstripe
|
||||
DIRS = windows
|
||||
endif
|
||||
ifneq (,$(filter gtk2 qt,$(MOZ_WIDGET_TOOLKIT)))
|
||||
DIRS = gnomestripe
|
||||
DIRS = linux
|
||||
endif
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
Before Width: | Height: | Size: 606 B After Width: | Height: | Size: 606 B |
Before Width: | Height: | Size: 7.9 KiB After Width: | Height: | Size: 7.9 KiB |
Before Width: | Height: | Size: 573 B After Width: | Height: | Size: 573 B |
Before Width: | Height: | Size: 767 B After Width: | Height: | Size: 767 B |
Before Width: | Height: | Size: 822 B After Width: | Height: | Size: 822 B |
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 2.0 KiB |
Before Width: | Height: | Size: 3.3 KiB After Width: | Height: | Size: 3.3 KiB |
Before Width: | Height: | Size: 4.7 KiB After Width: | Height: | Size: 4.7 KiB |
Before Width: | Height: | Size: 865 B After Width: | Height: | Size: 865 B |
Before Width: | Height: | Size: 928 B After Width: | Height: | Size: 928 B |
Before Width: | Height: | Size: 4.6 KiB After Width: | Height: | Size: 4.6 KiB |
Before Width: | Height: | Size: 7.2 KiB After Width: | Height: | Size: 7.2 KiB |
Before Width: | Height: | Size: 791 B After Width: | Height: | Size: 791 B |
Before Width: | Height: | Size: 776 B After Width: | Height: | Size: 776 B |
Before Width: | Height: | Size: 767 B After Width: | Height: | Size: 767 B |
Before Width: | Height: | Size: 405 B After Width: | Height: | Size: 405 B |