зеркало из https://github.com/mozilla/gecko-dev.git
Merge mozilla-central to tabcandy-central.
This commit is contained in:
Коммит
63becd4137
|
@ -120,9 +120,6 @@ export::
|
|||
ifdef ENABLE_TESTS
|
||||
# Additional makefile targets to call automated test suites
|
||||
include $(topsrcdir)/testing/testsuite-targets.mk
|
||||
else
|
||||
# OS X Universal builds will want to call this, so stub it out
|
||||
package-tests:
|
||||
endif
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
|
|
@ -73,10 +73,10 @@
|
|||
var jar = getJar(rootDir);
|
||||
if (jar) {
|
||||
var tmpdir = extractJarToTmp(jar);
|
||||
rootDir = "file://" + tmpdir.path;
|
||||
rootDir = "file://" + tmpdir.path + '/';
|
||||
}
|
||||
|
||||
var url = rootDir + "/scroll.html#link1";
|
||||
var url = rootDir + "scroll.html#link1";
|
||||
var tabBrowser = document.getElementById("tabBrowser");
|
||||
tabBrowser.loadURI(url);
|
||||
}
|
||||
|
|
|
@ -39,7 +39,7 @@
|
|||
}
|
||||
|
||||
var rootDir = getRootDirectory(window.location.href);
|
||||
var href = rootDir.path + "/foo";
|
||||
var href = rootDir.path + "foo";
|
||||
|
||||
// roles that can't live as nsHTMLLinkAccessibles
|
||||
testValue("aria_menuitem_link", "");
|
||||
|
|
|
@ -1042,10 +1042,8 @@ pref("services.sync.prefs.sync.spellchecker.dictionary", true);
|
|||
pref("services.sync.prefs.sync.xpinstall.whitelist.required", true);
|
||||
#endif
|
||||
|
||||
// Disable the Error Console
|
||||
// Disable the error console and inspector
|
||||
pref("devtools.errorconsole.enabled", false);
|
||||
|
||||
// disable the Inspector
|
||||
pref("devtools.inspector.enabled", false);
|
||||
|
||||
// Whether the character encoding menu is under the main Firefox button. This
|
||||
|
|
|
@ -147,7 +147,7 @@ toolbar[mode="icons"] > #reload-button[displaystop] {
|
|||
}
|
||||
|
||||
#urlbar-progress {
|
||||
-moz-binding: url("chrome://global/content/bindings/progressmeter.xml#progressmeter");
|
||||
-moz-binding: url("chrome://browser/content/urlbarBindings.xml#urlbar-progress");
|
||||
}
|
||||
|
||||
/* Some child nodes want to be ordered based on the locale's direction, while
|
||||
|
|
|
@ -1582,7 +1582,8 @@ function delayedStartup(isLoadingBlank, mustLoadSidebar) {
|
|||
}
|
||||
|
||||
// Enable Error Console?
|
||||
let consoleEnabled = gPrefService.getBoolPref("devtools.errorconsole.enabled");
|
||||
// XXX Temporarily always-enabled, see bug 601201
|
||||
let consoleEnabled = true || gPrefService.getBoolPref("devtools.errorconsole.enabled");
|
||||
if (consoleEnabled) {
|
||||
document.getElementById("javascriptConsole").hidden = false;
|
||||
document.getElementById("key_errorConsole").removeAttribute("disabled");
|
||||
|
|
|
@ -23,11 +23,15 @@
|
|||
}
|
||||
|
||||
.tab-label[pinned] {
|
||||
display: none;
|
||||
width: 0;
|
||||
margin-left: 0 !important;
|
||||
margin-right: 0 !important;
|
||||
padding-left: 0 !important;
|
||||
padding-right: 0 !important;
|
||||
}
|
||||
|
||||
.tab-stack {
|
||||
vertical-align: middle; /* for pinned tabs */
|
||||
vertical-align: top; /* for pinned tabs */
|
||||
}
|
||||
|
||||
tabpanels {
|
||||
|
|
|
@ -590,7 +590,7 @@ GroupItem.prototype = Utils.extend(new Item(), new Subscribable(), {
|
|||
this.$undoContainer = iQ("<div/>")
|
||||
.addClass("undo")
|
||||
.attr("type", "button")
|
||||
.text("Undo Close Group")
|
||||
.text(tabviewString("groupItem.undoCloseGroup"))
|
||||
.appendTo("body");
|
||||
let undoClose = iQ("<span/>")
|
||||
.addClass("close")
|
||||
|
|
|
@ -355,7 +355,7 @@ function test9()
|
|||
gBrowser.removeTab(tab, {animate: false});
|
||||
|
||||
// Next test
|
||||
executeSoon(finish);
|
||||
executeSoon(test10);
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -372,3 +372,38 @@ function test9()
|
|||
|
||||
tab.linkedBrowser.loadURI(uri);
|
||||
}
|
||||
|
||||
/**
|
||||
* In this test, we check that the author defined error message is shown.
|
||||
*/
|
||||
function test10()
|
||||
{
|
||||
let uri = "data:text/html,<iframe name='t'></iframe><form target='t' action='data:text/html,'><input x-moz-errormessage='foo' required id='i'><input id='s' type='submit'></form>";
|
||||
let tab = gBrowser.addTab();
|
||||
|
||||
gInvalidFormPopup.addEventListener("popupshown", function() {
|
||||
gInvalidFormPopup.removeEventListener("popupshown", arguments.callee, false);
|
||||
|
||||
let doc = gBrowser.contentDocument;
|
||||
is(doc.activeElement, doc.getElementById('i'),
|
||||
"First invalid element should be focused");
|
||||
|
||||
checkPopupShow();
|
||||
|
||||
is(gInvalidFormPopup.firstChild.nodeValue, "foo",
|
||||
"The panel should show the author defined error message");
|
||||
|
||||
// Clean-up and next test.
|
||||
gBrowser.removeTab(gBrowser.selectedTab, {animate: false});
|
||||
executeSoon(finish);
|
||||
}, false);
|
||||
|
||||
tab.linkedBrowser.addEventListener("load", function(aEvent) {
|
||||
tab.linkedBrowser.removeEventListener("load", arguments.callee, true);
|
||||
|
||||
gBrowser.contentDocument.getElementById('s').click();
|
||||
}, true);
|
||||
|
||||
gBrowser.selectedTab = tab;
|
||||
gBrowser.selectedTab.linkedBrowser.loadURI(uri);
|
||||
}
|
||||
|
|
|
@ -11,8 +11,8 @@ function test()
|
|||
// Now run the tests again and then close C.
|
||||
// The test results does not matter, all this is just to exercise some code to
|
||||
// catch assertions or crashes.
|
||||
var uri = "chrome://mochikit/content/browser/" +
|
||||
"browser/base/content/test/browser_tab_dragdrop2_frame1.xul";
|
||||
var chromeroot = getRootDirectory(gTestPath);
|
||||
var uri = chromeroot + "browser_tab_dragdrop2_frame1.xul";
|
||||
let window_B = openDialog(location, "_blank", "chrome,all,dialog=no,left=200,top=200,width=200,height=200", uri);
|
||||
window_B.addEventListener("load", function(aEvent) {
|
||||
window_B.removeEventListener("load", arguments.callee, false);
|
||||
|
|
|
@ -951,4 +951,16 @@
|
|||
]]></constructor>
|
||||
</implementation>
|
||||
</binding>
|
||||
|
||||
<binding id="urlbar-progress" extends="chrome://global/content/bindings/progressmeter.xml#progressmeter">
|
||||
<handlers>
|
||||
<handler event="transitionend"><![CDATA[
|
||||
if (this.hasAttribute("slideback") || this.value > 0)
|
||||
this.removeAttribute("slideback");
|
||||
else
|
||||
this.setAttribute("slideback", true);
|
||||
]]></handler>
|
||||
</handlers>
|
||||
</binding>
|
||||
|
||||
</bindings>
|
||||
|
|
|
@ -531,8 +531,7 @@ nsBrowserContentHandler.prototype = {
|
|||
}
|
||||
if (cmdLine.handleFlag("silent", false))
|
||||
cmdLine.preventDefault = true;
|
||||
if (cmdLine.findFlag("private-toggle", false) >= 0 &&
|
||||
cmdLine.state != cmdLine.STATE_INITIAL_LAUNCH)
|
||||
if (cmdLine.findFlag("private-toggle", false) >= 0)
|
||||
cmdLine.preventDefault = true;
|
||||
|
||||
var searchParam = cmdLine.handleFlagWithParam("search", false);
|
||||
|
|
|
@ -165,6 +165,10 @@ BrowserGlue.prototype = {
|
|||
case "final-ui-startup":
|
||||
this._onProfileStartup();
|
||||
break;
|
||||
case "browser-delayed-startup-finished":
|
||||
this._onFirstWindowLoaded();
|
||||
Services.obs.removeObserver(this, "browser-delayed-startup-finished");
|
||||
break;
|
||||
case "sessionstore-windows-restored":
|
||||
this._onBrowserStartup();
|
||||
break;
|
||||
|
@ -260,6 +264,7 @@ BrowserGlue.prototype = {
|
|||
os.addObserver(this, "xpcom-shutdown", false);
|
||||
os.addObserver(this, "prefservice:after-app-defaults", false);
|
||||
os.addObserver(this, "final-ui-startup", false);
|
||||
os.addObserver(this, "browser-delayed-startup-finished", false);
|
||||
os.addObserver(this, "sessionstore-windows-restored", false);
|
||||
os.addObserver(this, "browser:purge-session-history", false);
|
||||
os.addObserver(this, "quit-application-requested", false);
|
||||
|
@ -347,6 +352,22 @@ BrowserGlue.prototype = {
|
|||
Services.obs.notifyObservers(null, "browser-ui-startup-complete", "");
|
||||
},
|
||||
|
||||
// the first browser window has finished initializing
|
||||
_onFirstWindowLoaded: function BG__onFirstWindowLoaded() {
|
||||
#ifdef XP_WIN
|
||||
#ifndef WINCE
|
||||
// For windows seven, initialize the jump list module.
|
||||
const WINTASKBAR_CONTRACTID = "@mozilla.org/windows-taskbar;1";
|
||||
if (WINTASKBAR_CONTRACTID in Cc &&
|
||||
Cc[WINTASKBAR_CONTRACTID].getService(Ci.nsIWinTaskbar).available) {
|
||||
let temp = {};
|
||||
Cu.import("resource://gre/modules/WindowsJumpLists.jsm", temp);
|
||||
temp.WinTaskbarJumpList.startup();
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
},
|
||||
|
||||
// profile shutdown handler (contains profile cleanup routines)
|
||||
_onProfileShutdown: function BG__onProfileShutdown() {
|
||||
#ifdef MOZ_UPDATER
|
||||
|
@ -408,19 +429,6 @@ BrowserGlue.prototype = {
|
|||
// been warned about them yet, open the plugins update page.
|
||||
if (Services.prefs.getBoolPref(PREF_PLUGINS_NOTIFYUSER))
|
||||
this._showPluginUpdatePage();
|
||||
|
||||
#ifdef XP_WIN
|
||||
#ifndef WINCE
|
||||
// For windows seven, initialize the jump list module.
|
||||
const WINTASKBAR_CONTRACTID = "@mozilla.org/windows-taskbar;1";
|
||||
if (WINTASKBAR_CONTRACTID in Cc &&
|
||||
Cc[WINTASKBAR_CONTRACTID].getService(Ci.nsIWinTaskbar).available) {
|
||||
let temp = {};
|
||||
Cu.import("resource://gre/modules/WindowsJumpLists.jsm", temp);
|
||||
temp.WinTaskbarJumpList.startup();
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
},
|
||||
|
||||
_onQuitRequest: function BG__onQuitRequest(aCancelQuit, aQuitType) {
|
||||
|
|
|
@ -43,9 +43,9 @@ function test() {
|
|||
let jar = getJar(rootDir);
|
||||
if (jar) {
|
||||
let tmpdir = extractJarToTmp(jar);
|
||||
rootDir = "file://" + tmpdir.path;
|
||||
rootDir = "file://" + tmpdir.path + '/';
|
||||
}
|
||||
loader.loadSubScript(rootDir + "/privacypane_tests.js", this);
|
||||
loader.loadSubScript(rootDir + "privacypane_tests.js", this);
|
||||
|
||||
run_test_subset([
|
||||
test_pane_visibility,
|
||||
|
|
|
@ -43,9 +43,9 @@ function test() {
|
|||
let jar = getJar(rootDir);
|
||||
if (jar) {
|
||||
let tmpdir = extractJarToTmp(jar);
|
||||
rootDir = "file://" + tmpdir.path;
|
||||
rootDir = "file://" + tmpdir.path + '/';
|
||||
}
|
||||
loader.loadSubScript(rootDir + "/privacypane_tests.js", this);
|
||||
loader.loadSubScript(rootDir + "privacypane_tests.js", this);
|
||||
|
||||
run_test_subset([
|
||||
test_historymode_retention("remember", undefined),
|
||||
|
|
|
@ -42,9 +42,9 @@ function test() {
|
|||
let jar = getJar(rootDir);
|
||||
if (jar) {
|
||||
let tmpdir = extractJarToTmp(jar);
|
||||
rootDir = "file://" + tmpdir.path;
|
||||
rootDir = "file://" + tmpdir.path + '/';
|
||||
}
|
||||
loader.loadSubScript(rootDir + "/privacypane_tests.js", this);
|
||||
loader.loadSubScript(rootDir + "privacypane_tests.js", this);
|
||||
|
||||
run_test_subset([
|
||||
test_custom_retention("rememberHistory", "remember"),
|
||||
|
|
|
@ -42,9 +42,9 @@ function test() {
|
|||
let jar = getJar(rootDir);
|
||||
if (jar) {
|
||||
let tmpdir = extractJarToTmp(jar);
|
||||
rootDir = "file://" + tmpdir.path;
|
||||
rootDir = "file://" + tmpdir.path + '/';
|
||||
}
|
||||
loader.loadSubScript(rootDir + "/privacypane_tests.js", this);
|
||||
loader.loadSubScript(rootDir + "privacypane_tests.js", this);
|
||||
|
||||
run_test_subset([
|
||||
test_custom_retention("acceptCookies", "remember"),
|
||||
|
|
|
@ -42,9 +42,9 @@ function test() {
|
|||
let jar = getJar(rootDir);
|
||||
if (jar) {
|
||||
let tmpdir = extractJarToTmp(jar);
|
||||
rootDir = "file://" + tmpdir.path;
|
||||
rootDir = "file://" + tmpdir.path + '/';
|
||||
}
|
||||
loader.loadSubScript(rootDir + "/privacypane_tests.js", this);
|
||||
loader.loadSubScript(rootDir + "privacypane_tests.js", this);
|
||||
|
||||
run_test_subset([
|
||||
test_locbar_suggestion_retention(-1, undefined),
|
||||
|
|
|
@ -42,9 +42,9 @@ function test() {
|
|||
let jar = getJar(rootDir);
|
||||
if (jar) {
|
||||
let tmpdir = extractJarToTmp(jar);
|
||||
rootDir = "file://" + tmpdir.path;
|
||||
rootDir = "file://" + tmpdir.path + '/';
|
||||
}
|
||||
loader.loadSubScript(rootDir + "/privacypane_tests.js", this);
|
||||
loader.loadSubScript(rootDir + "privacypane_tests.js", this);
|
||||
|
||||
run_test_subset([
|
||||
test_privatebrowsing_toggle,
|
||||
|
|
|
@ -42,9 +42,9 @@ function test() {
|
|||
let jar = getJar(rootDir);
|
||||
if (jar) {
|
||||
let tmpdir = extractJarToTmp(jar);
|
||||
rootDir = "file://" + tmpdir.path;
|
||||
rootDir = "file://" + tmpdir.path + '/';
|
||||
}
|
||||
loader.loadSubScript(rootDir + "/privacypane_tests.js", this);
|
||||
loader.loadSubScript(rootDir + "privacypane_tests.js", this);
|
||||
|
||||
run_test_subset([
|
||||
test_privatebrowsing_ui,
|
||||
|
|
|
@ -41,9 +41,9 @@ function test() {
|
|||
let jar = getJar(rootDir);
|
||||
if (jar) {
|
||||
let tmpdir = extractJarToTmp(jar);
|
||||
rootDir = "file://" + tmpdir.path;
|
||||
rootDir = "file://" + tmpdir.path + '/';
|
||||
}
|
||||
loader.loadSubScript(rootDir + "/privacypane_tests.js", this);
|
||||
loader.loadSubScript(rootDir + "privacypane_tests.js", this);
|
||||
|
||||
run_test_subset([
|
||||
// history mode should be initialized to remember
|
||||
|
|
|
@ -129,6 +129,9 @@ PrivateBrowsingService.prototype = {
|
|||
// List of nsIXULWindows we are going to be closing during the transition
|
||||
_windowsToClose: [],
|
||||
|
||||
// Whether private browsing has been turned on from the command line
|
||||
_lastChangedByCommandLine: false,
|
||||
|
||||
// XPCOM registration
|
||||
classID: Components.ID("{c31f4883-839b-45f6-82ad-a6a9bc5ad599}"),
|
||||
|
||||
|
@ -231,6 +234,9 @@ PrivateBrowsingService.prototype = {
|
|||
// to be restored, do it now
|
||||
if (!this._inPrivateBrowsing) {
|
||||
this._currentStatus = STATE_WAITING_FOR_RESTORE;
|
||||
if (!this._getBrowserWindow()) {
|
||||
ss.init(null);
|
||||
}
|
||||
ss.setBrowserState(this._savedBrowserState);
|
||||
this._savedBrowserState = null;
|
||||
|
||||
|
@ -273,6 +279,9 @@ PrivateBrowsingService.prototype = {
|
|||
};
|
||||
// Transition into private browsing mode
|
||||
this._currentStatus = STATE_WAITING_FOR_RESTORE;
|
||||
if (!this._getBrowserWindow()) {
|
||||
ss.init(null);
|
||||
}
|
||||
ss.setBrowserState(JSON.stringify(privateBrowsingState));
|
||||
}
|
||||
}
|
||||
|
@ -439,6 +448,10 @@ PrivateBrowsingService.prototype = {
|
|||
if (aSubject.findFlag("private", false) >= 0) {
|
||||
this.privateBrowsingEnabled = true;
|
||||
this._autoStarted = true;
|
||||
this._lastChangedByCommandLine = true;
|
||||
}
|
||||
else if (aSubject.findFlag("private-toggle", false) >= 0) {
|
||||
this._lastChangedByCommandLine = true;
|
||||
}
|
||||
break;
|
||||
case "sessionstore-browser-state-restored":
|
||||
|
@ -458,6 +471,7 @@ PrivateBrowsingService.prototype = {
|
|||
else if (aCmdLine.handleFlag("private-toggle", false)) {
|
||||
this.privateBrowsingEnabled = !this.privateBrowsingEnabled;
|
||||
this._autoStarted = false;
|
||||
this._lastChangedByCommandLine = true;
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -534,6 +548,7 @@ PrivateBrowsingService.prototype = {
|
|||
} finally {
|
||||
this._windowsToClose = [];
|
||||
this._notifyIfTransitionComplete();
|
||||
this._lastChangedByCommandLine = false;
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -544,6 +559,13 @@ PrivateBrowsingService.prototype = {
|
|||
return this._inPrivateBrowsing && this._autoStarted;
|
||||
},
|
||||
|
||||
/**
|
||||
* Whether the latest transition was initiated from the command line.
|
||||
*/
|
||||
get lastChangedByCommandLine() {
|
||||
return this._lastChangedByCommandLine;
|
||||
},
|
||||
|
||||
removeDataFromDomain: function PBS_removeDataFromDomain(aDomain)
|
||||
{
|
||||
|
||||
|
|
|
@ -106,6 +106,15 @@ nsPrivateBrowsingServiceWrapper::GetAutoStarted(PRBool *aAutoStarted)
|
|||
return mPBService->GetAutoStarted(aAutoStarted);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsPrivateBrowsingServiceWrapper::GetLastChangedByCommandLine(PRBool *aReason)
|
||||
{
|
||||
if (!aReason)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
JSStackGuard guard;
|
||||
return mPBService->GetLastChangedByCommandLine(aReason);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsPrivateBrowsingServiceWrapper::RemoveDataFromDomain(const nsACString & aDomain)
|
||||
{
|
||||
|
|
|
@ -128,6 +128,8 @@ function test() {
|
|||
is(browser.contentWindow.location, "about:", "The correct page has been loaded");
|
||||
|
||||
simulatePrivateCommandLineArgument();
|
||||
is(pb.lastChangedByCommandLine, true,
|
||||
"The status change reason should reflect the PB mode being set from the command line");
|
||||
tab = gBrowser.selectedTab;
|
||||
browser = gBrowser.getBrowserForTab(tab);
|
||||
browser.addEventListener("load", function() {
|
||||
|
@ -137,6 +139,8 @@ function test() {
|
|||
"about:privatebrowsing should now be loaded");
|
||||
|
||||
simulatePrivateCommandLineArgument();
|
||||
is(pb.lastChangedByCommandLine, true,
|
||||
"The status change reason should reflect the PB mode being set from the command line");
|
||||
tab = gBrowser.selectedTab;
|
||||
browser = gBrowser.getBrowserForTab(tab);
|
||||
browser.addEventListener("load", function() {
|
||||
|
|
|
@ -0,0 +1,250 @@
|
|||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Private Browsing Tests.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Ehsan Akhgari.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2008
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Ehsan Akhgari <ehsan.akhgari@gmail.com> (Original Author)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
// This tests the private browsing service to make sure it implements its
|
||||
// documented interface correctly.
|
||||
|
||||
// This test should run before the rest of private browsing service unit tests,
|
||||
// hence the naming used for this file.
|
||||
|
||||
function do_test() {
|
||||
// initialization
|
||||
var os = Cc["@mozilla.org/observer-service;1"].
|
||||
getService(Ci.nsIObserverService);
|
||||
|
||||
// the contract ID should be available
|
||||
do_check_true(PRIVATEBROWSING_CONTRACT_ID in Cc);
|
||||
|
||||
// the interface should be available
|
||||
do_check_true("nsIPrivateBrowsingService" in Ci);
|
||||
|
||||
// it should be possible to initialize the component
|
||||
try {
|
||||
var pb = Cc[PRIVATEBROWSING_CONTRACT_ID].
|
||||
getService(Ci.nsIPrivateBrowsingService);
|
||||
} catch (ex) {
|
||||
LOG("exception thrown when trying to get the service: " + ex);
|
||||
do_throw("private browsing service could not be initialized");
|
||||
}
|
||||
|
||||
// private browsing should be turned off initially
|
||||
do_check_false(pb.privateBrowsingEnabled);
|
||||
// private browsing not auto-started
|
||||
do_check_false(pb.autoStarted);
|
||||
// and the status should have never been changed
|
||||
do_check_eq(pb.lastChangedByCommandLine, false);
|
||||
|
||||
// it should be possible to toggle its status
|
||||
pb.privateBrowsingEnabled = true;
|
||||
do_check_true(pb.privateBrowsingEnabled);
|
||||
do_check_false(pb.autoStarted);
|
||||
do_check_eq(pb.lastChangedByCommandLine, false);
|
||||
pb.privateBrowsingEnabled = false;
|
||||
do_check_false(pb.privateBrowsingEnabled);
|
||||
do_check_false(pb.autoStarted);
|
||||
do_check_eq(pb.lastChangedByCommandLine, false);
|
||||
|
||||
// test the private-browsing notification
|
||||
var observer = {
|
||||
observe: function(aSubject, aTopic, aData) {
|
||||
if (aTopic == kPrivateBrowsingNotification)
|
||||
this.data = aData;
|
||||
},
|
||||
data: null
|
||||
};
|
||||
os.addObserver(observer, kPrivateBrowsingNotification, false);
|
||||
pb.privateBrowsingEnabled = true;
|
||||
do_check_eq(observer.data, kEnter);
|
||||
pb.privateBrowsingEnabled = false;
|
||||
do_check_eq(observer.data, kExit);
|
||||
os.removeObserver(observer, kPrivateBrowsingNotification);
|
||||
|
||||
// make sure that setting the private browsing mode from within an observer throws
|
||||
observer = {
|
||||
observe: function(aSubject, aTopic, aData) {
|
||||
if (aTopic == kPrivateBrowsingNotification) {
|
||||
try {
|
||||
pb.privateBrowsingEnabled = (aData == kEnter);
|
||||
do_throw("Setting privateBrowsingEnabled inside the " + aData +
|
||||
" notification should throw");
|
||||
} catch (ex) {
|
||||
if (!("result" in ex && ex.result == Cr.NS_ERROR_FAILURE))
|
||||
do_throw("Unexpected exception caught: " + ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
os.addObserver(observer, kPrivateBrowsingNotification, false);
|
||||
pb.privateBrowsingEnabled = true;
|
||||
do_check_true(pb.privateBrowsingEnabled); // the exception should not interfere with the mode change
|
||||
pb.privateBrowsingEnabled = false;
|
||||
do_check_false(pb.privateBrowsingEnabled); // the exception should not interfere with the mode change
|
||||
os.removeObserver(observer, kPrivateBrowsingNotification);
|
||||
|
||||
// make sure that getting the private browsing mode from within an observer doesn't throw
|
||||
observer = {
|
||||
observe: function(aSubject, aTopic, aData) {
|
||||
if (aTopic == kPrivateBrowsingNotification) {
|
||||
try {
|
||||
var dummy = pb.privateBrowsingEnabled;
|
||||
if (aData == kEnter)
|
||||
do_check_true(dummy);
|
||||
else if (aData == kExit)
|
||||
do_check_false(dummy);
|
||||
} catch (ex) {
|
||||
do_throw("Unexpected exception caught: " + ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
os.addObserver(observer, kPrivateBrowsingNotification, false);
|
||||
pb.privateBrowsingEnabled = true;
|
||||
do_check_true(pb.privateBrowsingEnabled); // just a sanity check
|
||||
pb.privateBrowsingEnabled = false;
|
||||
do_check_false(pb.privateBrowsingEnabled); // just a sanity check
|
||||
os.removeObserver(observer, kPrivateBrowsingNotification);
|
||||
|
||||
// check that the private-browsing-cancel-vote notification is sent before the
|
||||
// private-browsing notification
|
||||
observer = {
|
||||
observe: function(aSubject, aTopic, aData) {
|
||||
switch (aTopic) {
|
||||
case kPrivateBrowsingCancelVoteNotification:
|
||||
case kPrivateBrowsingNotification:
|
||||
this.notifications.push(aTopic + " " + aData);
|
||||
}
|
||||
},
|
||||
notifications: []
|
||||
};
|
||||
os.addObserver(observer, kPrivateBrowsingCancelVoteNotification, false);
|
||||
os.addObserver(observer, kPrivateBrowsingNotification, false);
|
||||
pb.privateBrowsingEnabled = true;
|
||||
do_check_true(pb.privateBrowsingEnabled); // just a sanity check
|
||||
pb.privateBrowsingEnabled = false;
|
||||
do_check_false(pb.privateBrowsingEnabled); // just a sanity check
|
||||
os.removeObserver(observer, kPrivateBrowsingNotification);
|
||||
os.removeObserver(observer, kPrivateBrowsingCancelVoteNotification);
|
||||
var reference_order = [
|
||||
kPrivateBrowsingCancelVoteNotification + " " + kEnter,
|
||||
kPrivateBrowsingNotification + " " + kEnter,
|
||||
kPrivateBrowsingCancelVoteNotification + " " + kExit,
|
||||
kPrivateBrowsingNotification + " " + kExit
|
||||
];
|
||||
do_check_eq(observer.notifications.join(","), reference_order.join(","));
|
||||
|
||||
// make sure that the private-browsing-cancel-vote notification can be used
|
||||
// to cancel the mode switch
|
||||
observer = {
|
||||
observe: function(aSubject, aTopic, aData) {
|
||||
switch (aTopic) {
|
||||
case kPrivateBrowsingCancelVoteNotification:
|
||||
do_check_neq(aSubject, null);
|
||||
try {
|
||||
aSubject.QueryInterface(Ci.nsISupportsPRBool);
|
||||
} catch (ex) {
|
||||
do_throw("aSubject in " + kPrivateBrowsingCancelVoteNotification +
|
||||
" should implement nsISupportsPRBool");
|
||||
}
|
||||
do_check_false(aSubject.data);
|
||||
aSubject.data = true; // cancel the mode switch
|
||||
|
||||
// fall through
|
||||
case kPrivateBrowsingNotification:
|
||||
this.notifications.push(aTopic + " " + aData);
|
||||
}
|
||||
},
|
||||
nextPhase: function() {
|
||||
this.notifications.push("enter phase " + (++this._phase));
|
||||
},
|
||||
notifications: [],
|
||||
_phase: 0
|
||||
};
|
||||
os.addObserver(observer, kPrivateBrowsingCancelVoteNotification, false);
|
||||
os.addObserver(observer, kPrivateBrowsingNotification, false);
|
||||
pb.privateBrowsingEnabled = true;
|
||||
do_check_false(pb.privateBrowsingEnabled); // should have been canceled
|
||||
// temporarily disable the observer
|
||||
os.removeObserver(observer, kPrivateBrowsingCancelVoteNotification);
|
||||
observer.nextPhase();
|
||||
pb.privateBrowsingEnabled = true; // this time, should enter successfully
|
||||
do_check_true(pb.privateBrowsingEnabled); // should have been canceled
|
||||
// re-enable the observer
|
||||
os.addObserver(observer, kPrivateBrowsingCancelVoteNotification, false);
|
||||
pb.privateBrowsingEnabled = false;
|
||||
do_check_true(pb.privateBrowsingEnabled); // should have been canceled
|
||||
os.removeObserver(observer, kPrivateBrowsingCancelVoteNotification);
|
||||
observer.nextPhase();
|
||||
pb.privateBrowsingEnabled = false; // this time, should exit successfully
|
||||
do_check_false(pb.privateBrowsingEnabled);
|
||||
os.removeObserver(observer, kPrivateBrowsingNotification);
|
||||
reference_order = [
|
||||
kPrivateBrowsingCancelVoteNotification + " " + kEnter,
|
||||
"enter phase 1",
|
||||
kPrivateBrowsingNotification + " " + kEnter,
|
||||
kPrivateBrowsingCancelVoteNotification + " " + kExit,
|
||||
"enter phase 2",
|
||||
kPrivateBrowsingNotification + " " + kExit,
|
||||
];
|
||||
do_check_eq(observer.notifications.join(","), reference_order.join(","));
|
||||
|
||||
// make sure that the private browsing transition complete notification is
|
||||
// raised correctly.
|
||||
observer = {
|
||||
observe: function(aSubject, aTopic, aData) {
|
||||
this.notifications.push(aTopic + " " + aData);
|
||||
},
|
||||
notifications: []
|
||||
};
|
||||
os.addObserver(observer, kPrivateBrowsingNotification, false);
|
||||
os.addObserver(observer, kPrivateBrowsingTransitionCompleteNotification, false);
|
||||
pb.privateBrowsingEnabled = true;
|
||||
pb.privateBrowsingEnabled = false;
|
||||
os.removeObserver(observer, kPrivateBrowsingNotification);
|
||||
os.removeObserver(observer, kPrivateBrowsingTransitionCompleteNotification);
|
||||
reference_order = [
|
||||
kPrivateBrowsingNotification + " " + kEnter,
|
||||
kPrivateBrowsingTransitionCompleteNotification + " ",
|
||||
kPrivateBrowsingNotification + " " + kExit,
|
||||
kPrivateBrowsingTransitionCompleteNotification + " ",
|
||||
];
|
||||
do_check_eq(observer.notifications.join(","), reference_order.join(","));
|
||||
}
|
||||
|
||||
// Support running tests on both the service itself and its wrapper
|
||||
function run_test() {
|
||||
run_test_on_all_services();
|
||||
}
|
|
@ -118,4 +118,6 @@ function do_test() {
|
|||
do_check_true(pb.privateBrowsingEnabled);
|
||||
// and should appear as auto-started!
|
||||
do_check_true(pb.autoStarted);
|
||||
// and should be coming from the command line!
|
||||
do_check_eq(pb.lastChangedByCommandLine, true);
|
||||
}
|
||||
|
|
|
@ -38,209 +38,8 @@
|
|||
// This tests the private browsing service to make sure it implements its
|
||||
// documented interface correctly.
|
||||
|
||||
// This test should run before the rest of private browsing service unit tests,
|
||||
// hence the naming used for this file.
|
||||
|
||||
function run_test_on_service() {
|
||||
// initialization
|
||||
var os = Cc["@mozilla.org/observer-service;1"].
|
||||
getService(Ci.nsIObserverService);
|
||||
|
||||
// the contract ID should be available
|
||||
do_check_true(PRIVATEBROWSING_CONTRACT_ID in Cc);
|
||||
|
||||
// the interface should be available
|
||||
do_check_true("nsIPrivateBrowsingService" in Ci);
|
||||
|
||||
// it should be possible to initialize the component
|
||||
try {
|
||||
var pb = Cc[PRIVATEBROWSING_CONTRACT_ID].
|
||||
getService(Ci.nsIPrivateBrowsingService);
|
||||
} catch (ex) {
|
||||
LOG("exception thrown when trying to get the service: " + ex);
|
||||
do_throw("private browsing service could not be initialized");
|
||||
}
|
||||
|
||||
// private browsing should be turned off initially
|
||||
do_check_false(pb.privateBrowsingEnabled);
|
||||
// private browsing not auto-started
|
||||
do_check_false(pb.autoStarted);
|
||||
|
||||
// it should be possible to toggle its status
|
||||
pb.privateBrowsingEnabled = true;
|
||||
do_check_true(pb.privateBrowsingEnabled);
|
||||
do_check_false(pb.autoStarted);
|
||||
pb.privateBrowsingEnabled = false;
|
||||
do_check_false(pb.privateBrowsingEnabled);
|
||||
do_check_false(pb.autoStarted);
|
||||
|
||||
// test the private-browsing notification
|
||||
var observer = {
|
||||
observe: function(aSubject, aTopic, aData) {
|
||||
if (aTopic == kPrivateBrowsingNotification)
|
||||
this.data = aData;
|
||||
},
|
||||
data: null
|
||||
};
|
||||
os.addObserver(observer, kPrivateBrowsingNotification, false);
|
||||
pb.privateBrowsingEnabled = true;
|
||||
do_check_eq(observer.data, kEnter);
|
||||
pb.privateBrowsingEnabled = false;
|
||||
do_check_eq(observer.data, kExit);
|
||||
os.removeObserver(observer, kPrivateBrowsingNotification);
|
||||
|
||||
// make sure that setting the private browsing mode from within an observer throws
|
||||
observer = {
|
||||
observe: function(aSubject, aTopic, aData) {
|
||||
if (aTopic == kPrivateBrowsingNotification) {
|
||||
try {
|
||||
pb.privateBrowsingEnabled = (aData == kEnter);
|
||||
do_throw("Setting privateBrowsingEnabled inside the " + aData +
|
||||
" notification should throw");
|
||||
} catch (ex) {
|
||||
if (!("result" in ex && ex.result == Cr.NS_ERROR_FAILURE))
|
||||
do_throw("Unexpected exception caught: " + ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
os.addObserver(observer, kPrivateBrowsingNotification, false);
|
||||
pb.privateBrowsingEnabled = true;
|
||||
do_check_true(pb.privateBrowsingEnabled); // the exception should not interfere with the mode change
|
||||
pb.privateBrowsingEnabled = false;
|
||||
do_check_false(pb.privateBrowsingEnabled); // the exception should not interfere with the mode change
|
||||
os.removeObserver(observer, kPrivateBrowsingNotification);
|
||||
|
||||
// make sure that getting the private browsing mode from within an observer doesn't throw
|
||||
observer = {
|
||||
observe: function(aSubject, aTopic, aData) {
|
||||
if (aTopic == kPrivateBrowsingNotification) {
|
||||
try {
|
||||
var dummy = pb.privateBrowsingEnabled;
|
||||
if (aData == kEnter)
|
||||
do_check_true(dummy);
|
||||
else if (aData == kExit)
|
||||
do_check_false(dummy);
|
||||
} catch (ex) {
|
||||
do_throw("Unexpected exception caught: " + ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
os.addObserver(observer, kPrivateBrowsingNotification, false);
|
||||
pb.privateBrowsingEnabled = true;
|
||||
do_check_true(pb.privateBrowsingEnabled); // just a sanity check
|
||||
pb.privateBrowsingEnabled = false;
|
||||
do_check_false(pb.privateBrowsingEnabled); // just a sanity check
|
||||
os.removeObserver(observer, kPrivateBrowsingNotification);
|
||||
|
||||
// check that the private-browsing-cancel-vote notification is sent before the
|
||||
// private-browsing notification
|
||||
observer = {
|
||||
observe: function(aSubject, aTopic, aData) {
|
||||
switch (aTopic) {
|
||||
case kPrivateBrowsingCancelVoteNotification:
|
||||
case kPrivateBrowsingNotification:
|
||||
this.notifications.push(aTopic + " " + aData);
|
||||
}
|
||||
},
|
||||
notifications: []
|
||||
};
|
||||
os.addObserver(observer, kPrivateBrowsingCancelVoteNotification, false);
|
||||
os.addObserver(observer, kPrivateBrowsingNotification, false);
|
||||
pb.privateBrowsingEnabled = true;
|
||||
do_check_true(pb.privateBrowsingEnabled); // just a sanity check
|
||||
pb.privateBrowsingEnabled = false;
|
||||
do_check_false(pb.privateBrowsingEnabled); // just a sanity check
|
||||
os.removeObserver(observer, kPrivateBrowsingNotification);
|
||||
os.removeObserver(observer, kPrivateBrowsingCancelVoteNotification);
|
||||
var reference_order = [
|
||||
kPrivateBrowsingCancelVoteNotification + " " + kEnter,
|
||||
kPrivateBrowsingNotification + " " + kEnter,
|
||||
kPrivateBrowsingCancelVoteNotification + " " + kExit,
|
||||
kPrivateBrowsingNotification + " " + kExit
|
||||
];
|
||||
do_check_eq(observer.notifications.join(","), reference_order.join(","));
|
||||
|
||||
// make sure that the private-browsing-cancel-vote notification can be used
|
||||
// to cancel the mode switch
|
||||
observer = {
|
||||
observe: function(aSubject, aTopic, aData) {
|
||||
switch (aTopic) {
|
||||
case kPrivateBrowsingCancelVoteNotification:
|
||||
do_check_neq(aSubject, null);
|
||||
try {
|
||||
aSubject.QueryInterface(Ci.nsISupportsPRBool);
|
||||
} catch (ex) {
|
||||
do_throw("aSubject in " + kPrivateBrowsingCancelVoteNotification +
|
||||
" should implement nsISupportsPRBool");
|
||||
}
|
||||
do_check_false(aSubject.data);
|
||||
aSubject.data = true; // cancel the mode switch
|
||||
|
||||
// fall through
|
||||
case kPrivateBrowsingNotification:
|
||||
this.notifications.push(aTopic + " " + aData);
|
||||
}
|
||||
},
|
||||
nextPhase: function() {
|
||||
this.notifications.push("enter phase " + (++this._phase));
|
||||
},
|
||||
notifications: [],
|
||||
_phase: 0
|
||||
};
|
||||
os.addObserver(observer, kPrivateBrowsingCancelVoteNotification, false);
|
||||
os.addObserver(observer, kPrivateBrowsingNotification, false);
|
||||
pb.privateBrowsingEnabled = true;
|
||||
do_check_false(pb.privateBrowsingEnabled); // should have been canceled
|
||||
// temporarily disable the observer
|
||||
os.removeObserver(observer, kPrivateBrowsingCancelVoteNotification);
|
||||
observer.nextPhase();
|
||||
pb.privateBrowsingEnabled = true; // this time, should enter successfully
|
||||
do_check_true(pb.privateBrowsingEnabled); // should have been canceled
|
||||
// re-enable the observer
|
||||
os.addObserver(observer, kPrivateBrowsingCancelVoteNotification, false);
|
||||
pb.privateBrowsingEnabled = false;
|
||||
do_check_true(pb.privateBrowsingEnabled); // should have been canceled
|
||||
os.removeObserver(observer, kPrivateBrowsingCancelVoteNotification);
|
||||
observer.nextPhase();
|
||||
pb.privateBrowsingEnabled = false; // this time, should exit successfully
|
||||
do_check_false(pb.privateBrowsingEnabled);
|
||||
os.removeObserver(observer, kPrivateBrowsingNotification);
|
||||
reference_order = [
|
||||
kPrivateBrowsingCancelVoteNotification + " " + kEnter,
|
||||
"enter phase 1",
|
||||
kPrivateBrowsingNotification + " " + kEnter,
|
||||
kPrivateBrowsingCancelVoteNotification + " " + kExit,
|
||||
"enter phase 2",
|
||||
kPrivateBrowsingNotification + " " + kExit,
|
||||
];
|
||||
do_check_eq(observer.notifications.join(","), reference_order.join(","));
|
||||
|
||||
// make sure that the private browsing transition complete notification is
|
||||
// raised correctly.
|
||||
observer = {
|
||||
observe: function(aSubject, aTopic, aData) {
|
||||
this.notifications.push(aTopic + " " + aData);
|
||||
},
|
||||
notifications: []
|
||||
};
|
||||
os.addObserver(observer, kPrivateBrowsingNotification, false);
|
||||
os.addObserver(observer, kPrivateBrowsingTransitionCompleteNotification, false);
|
||||
pb.privateBrowsingEnabled = true;
|
||||
pb.privateBrowsingEnabled = false;
|
||||
os.removeObserver(observer, kPrivateBrowsingNotification);
|
||||
os.removeObserver(observer, kPrivateBrowsingTransitionCompleteNotification);
|
||||
reference_order = [
|
||||
kPrivateBrowsingNotification + " " + kEnter,
|
||||
kPrivateBrowsingTransitionCompleteNotification + " ",
|
||||
kPrivateBrowsingNotification + " " + kExit,
|
||||
kPrivateBrowsingTransitionCompleteNotification + " ",
|
||||
];
|
||||
do_check_eq(observer.notifications.join(","), reference_order.join(","));
|
||||
}
|
||||
|
||||
// Support running tests on both the service itself and its wrapper
|
||||
function run_test() {
|
||||
run_test_on_all_services();
|
||||
PRIVATEBROWSING_CONTRACT_ID = "@mozilla.org/privatebrowsing;1";
|
||||
load("do_test_0-privatebrowsing.js");
|
||||
do_test();
|
||||
}
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Private Browsing Tests.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Ehsan Akhgari.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2008
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Ehsan Akhgari <ehsan.akhgari@gmail.com> (Original Author)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
// This tests the private browsing service to make sure it implements its
|
||||
// documented interface correctly.
|
||||
|
||||
function run_test() {
|
||||
PRIVATEBROWSING_CONTRACT_ID = "@mozilla.org/privatebrowsing-wrapper;1";
|
||||
load("do_test_0-privatebrowsing.js");
|
||||
do_test();
|
||||
}
|
|
@ -101,7 +101,7 @@ SessionStartup.prototype = {
|
|||
// do not need to initialize anything in auto-started private browsing sessions
|
||||
let pbs = Cc["@mozilla.org/privatebrowsing;1"].
|
||||
getService(Ci.nsIPrivateBrowsingService);
|
||||
if (pbs.autoStarted)
|
||||
if (pbs.autoStarted || pbs.lastChangedByCommandLine)
|
||||
return;
|
||||
|
||||
let prefBranch = Cc["@mozilla.org/preferences-service;1"].
|
||||
|
@ -237,7 +237,12 @@ SessionStartup.prototype = {
|
|||
aWindow.arguments[0] == defaultArgs)
|
||||
aWindow.arguments[0] = null;
|
||||
|
||||
try {
|
||||
Services.obs.removeObserver(this, "domwindowopened");
|
||||
} catch (e) {
|
||||
// This might throw if we're removing the observer multiple times,
|
||||
// but this is safe to ignore.
|
||||
}
|
||||
},
|
||||
|
||||
/* ........ Public API ................*/
|
||||
|
|
|
@ -214,6 +214,9 @@ SessionStoreService.prototype = {
|
|||
// The state from the previous session (after restoring pinned tabs)
|
||||
_lastSessionState: null,
|
||||
|
||||
// Whether we've been initialized
|
||||
_initialized: false,
|
||||
|
||||
/* ........ Public Getters .............. */
|
||||
|
||||
get canRestoreLastSession() {
|
||||
|
@ -233,15 +236,7 @@ SessionStoreService.prototype = {
|
|||
/**
|
||||
* Initialize the component
|
||||
*/
|
||||
init: function sss_init(aWindow) {
|
||||
if (!aWindow || this._loadState == STATE_RUNNING) {
|
||||
// make sure that all browser windows which try to initialize
|
||||
// SessionStore are really tracked by it
|
||||
if (aWindow && (!aWindow.__SSi || !this._windows[aWindow.__SSi]))
|
||||
this.onLoad(aWindow);
|
||||
return;
|
||||
}
|
||||
|
||||
initService: function() {
|
||||
this._prefBranch = Services.prefs.getBranch("browser.");
|
||||
this._prefBranch.QueryInterface(Ci.nsIPrefBranch2);
|
||||
|
||||
|
@ -354,6 +349,34 @@ SessionStoreService.prototype = {
|
|||
this._prefBranch.getBoolPref("sessionstore.resume_session_once"))
|
||||
this._prefBranch.setBoolPref("sessionstore.resume_session_once", false);
|
||||
|
||||
this._initialized = true;
|
||||
},
|
||||
|
||||
/**
|
||||
* Start tracking a window.
|
||||
* Important note: despite its name, this function doesn't initialize
|
||||
* the component!
|
||||
*/
|
||||
init: function sss_init(aWindow) {
|
||||
if (!aWindow || this._loadState == STATE_RUNNING) {
|
||||
// make sure that all browser windows which try to initialize
|
||||
// SessionStore are really tracked by it
|
||||
if (aWindow && (!aWindow.__SSi || !this._windows[aWindow.__SSi]))
|
||||
this.onLoad(aWindow);
|
||||
// If init is being called with a null window, it's possible that we
|
||||
// just want to tell sessionstore that a session is live (as is the case
|
||||
// with starting Firefox with -private, for example; see bug 568816),
|
||||
// so we should mark the load state as running to make sure that
|
||||
// things like setBrowserState calls will succeed in restoring the session.
|
||||
if (!aWindow && this._loadState == STATE_STOPPED)
|
||||
this._loadState = STATE_RUNNING;
|
||||
return;
|
||||
}
|
||||
|
||||
// Initialize the service if needed.
|
||||
if (!this._initialized)
|
||||
this.initService();
|
||||
|
||||
// As this is called at delayedStartup, restoration must be initiated here
|
||||
this.onLoad(aWindow);
|
||||
},
|
||||
|
@ -3539,10 +3562,15 @@ SessionStoreService.prototype = {
|
|||
function sss__resetTabRestoringState(aTab, aRestoreNextTab, aRestoreThisTab) {
|
||||
let browser = aTab.linkedBrowser;
|
||||
|
||||
// Always delete the session history listener off the browser
|
||||
delete browser.__SS_shistoryListener;
|
||||
|
||||
if (browser.__SS_restoring) {
|
||||
// If the session history listener hasn't been detached, make sure we
|
||||
// remove it and delete the reference.
|
||||
if (browser.__SS_shistoryListener) {
|
||||
browser.webNavigation.sessionHistory.
|
||||
removeSHistoryListener(browser.__SS_shistoryListener);
|
||||
delete browser.__SS_shistoryListener;
|
||||
}
|
||||
|
||||
delete browser.__SS_restoring;
|
||||
if (aRestoreNextTab) {
|
||||
// this._tabsRestoringCount is decremented in restoreNextTab.
|
||||
|
@ -3721,8 +3749,12 @@ let gRestoreTabsProgressListener = {
|
|||
aStateFlags & Ci.nsIWebProgressListener.STATE_STOP &&
|
||||
aStateFlags & Ci.nsIWebProgressListener.STATE_IS_NETWORK &&
|
||||
aStateFlags & Ci.nsIWebProgressListener.STATE_IS_WINDOW) {
|
||||
delete aBrowser.__SS_restoring;
|
||||
this.ss.restoreNextTab(true);
|
||||
// We need to reset the tab before starting the next restore.
|
||||
// _resetTabRestoringState will make sure we remove the session history
|
||||
// listener and will call restoreNextTab.
|
||||
let window = aBrowser.ownerDocument.defaultView;
|
||||
let tab = window.gBrowser._getTabForContentWindow(aBrowser.contentWindow);
|
||||
this.ss._resetTabRestoringState(tab, true, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -577,7 +577,7 @@ function test_reload() {
|
|||
|
||||
if (loadCount == state.windows[0].tabs.length) {
|
||||
window.gBrowser.removeTabsProgressListener(progressListener);
|
||||
runNextTest();
|
||||
test_reload2(state);
|
||||
}
|
||||
else {
|
||||
// reload the next tab
|
||||
|
@ -592,6 +592,62 @@ function test_reload() {
|
|||
}
|
||||
|
||||
|
||||
// This test shouldn't be added to tests. It will be called directly from
|
||||
// test_reload. This guarantees that we're already in a tested restored state
|
||||
// and we know what the state should be.
|
||||
function test_reload2(aState) {
|
||||
info("starting test_reload2");
|
||||
let progressListener = {
|
||||
onStateChange: function (aBrowser, aWebProgress, aRequest, aStateFlags, aStatus) {
|
||||
if (aStateFlags & Ci.nsIWebProgressListener.STATE_STOP &&
|
||||
aStateFlags & Ci.nsIWebProgressListener.STATE_IS_NETWORK &&
|
||||
aStateFlags & Ci.nsIWebProgressListener.STATE_IS_WINDOW)
|
||||
test_reload2_progressCallback(aBrowser);
|
||||
}
|
||||
}
|
||||
|
||||
// Simulate a left mouse button click with no modifiers, which is what
|
||||
// Command-R, or clicking reload does.
|
||||
let fakeEvent = {
|
||||
button: 0,
|
||||
metaKey: false,
|
||||
altKey: false,
|
||||
ctrlKey: false,
|
||||
shiftKey: false,
|
||||
}
|
||||
|
||||
let loadCount = 0;
|
||||
function test_reload2_progressCallback(aBrowser) {
|
||||
loadCount++;
|
||||
|
||||
if (loadCount <= aState.windows[0].tabs.length) {
|
||||
// double check that this tab was the right one
|
||||
let expectedData = aState.windows[0].tabs[loadCount - 1].extData.uniq;
|
||||
let tab;
|
||||
for (let i = 0; i < window.gBrowser.tabs.length; i++) {
|
||||
if (!tab && window.gBrowser.tabs[i].linkedBrowser == aBrowser)
|
||||
tab = window.gBrowser.tabs[i];
|
||||
}
|
||||
is(ss.getTabValue(tab, "uniq"), expectedData,
|
||||
"test_reload2: load " + loadCount + " - correct tab was reloaded");
|
||||
|
||||
if (loadCount == aState.windows[0].tabs.length) {
|
||||
window.gBrowser.removeTabsProgressListener(progressListener);
|
||||
runNextTest();
|
||||
}
|
||||
else {
|
||||
// reload the next tab
|
||||
window.gBrowser.selectTabAtIndex(loadCount);
|
||||
BrowserReloadOrDuplicate(fakeEvent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
window.gBrowser.addTabsProgressListener(progressListener);
|
||||
BrowserReloadOrDuplicate(fakeEvent);
|
||||
}
|
||||
|
||||
|
||||
function countTabs() {
|
||||
let needsRestore = 0,
|
||||
isRestoring = 0,
|
||||
|
|
|
@ -150,7 +150,7 @@ var tasksCfg = [
|
|||
close: false, // no point
|
||||
},
|
||||
|
||||
// Privacy mode
|
||||
// Toggle the Private Browsing mode
|
||||
{
|
||||
get title() {
|
||||
if (_privateBrowsingSvc.privateBrowsingEnabled)
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
tabview.groupItem.newTabButton=New tab
|
||||
tabview.groupItem.defaultName=Name this tab group…
|
||||
tabview.groupItem.undoCloseGroup=Undo Close Group
|
||||
tabview.search.otherWindowTabs=Tabs from other windows
|
|
@ -964,9 +964,18 @@ toolbar[iconsize="small"] #sync-button[status="active"] {
|
|||
background-color: transparent;
|
||||
}
|
||||
|
||||
.tab-progress[busy][stalled][value="0"],
|
||||
#urlbar-progress[busy][stalled][value="0"] {
|
||||
/* TODO: add connecting state (bug 596812) */
|
||||
#urlbar-progress[value="0"] > .progress-remainder {
|
||||
background-image: -moz-linear-gradient(left, rgba(255,255,255,0), rgb(255,255,255), rgba(255,255,255,0)) !important;
|
||||
background-size: 10%;
|
||||
background-repeat: no-repeat;
|
||||
background-position: right;
|
||||
-moz-transition-property: background-position;
|
||||
-moz-transition-duration: 2s;
|
||||
-moz-transition-timing-function: linear;
|
||||
}
|
||||
|
||||
#urlbar-progress[value="0"][slideback] > .progress-remainder {
|
||||
background-position: left;
|
||||
}
|
||||
|
||||
.tab-progress > .progress-bar,
|
||||
|
|
|
@ -450,26 +450,26 @@ input.defaultName {
|
|||
opacity: .70;
|
||||
}
|
||||
|
||||
#otherresults{
|
||||
#otherresults {
|
||||
left: 0px;
|
||||
bottom: 0px;
|
||||
width: 100%;
|
||||
height: 30px;
|
||||
background-color: rgba(0,0,0,.3);
|
||||
-moz-box-shadow: 0px -1px 0px rgba(255,255,255,.1), inset 0px 2px 5px rgba(0,0,0,.3);
|
||||
box-shadow: 0px -1px 0px rgba(255,255,255,.1), inset 0px 2px 5px rgba(0,0,0,.3);
|
||||
}
|
||||
|
||||
#otherresults .label{
|
||||
#otherresults .label {
|
||||
color: #999;
|
||||
line-height:30px;
|
||||
margin-left:5px;
|
||||
line-height: 30px;
|
||||
margin-left: 5px;
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
.inlineMatch{
|
||||
.inlineMatch {
|
||||
background-color: #EBEBEB;
|
||||
border-radius: 0.4em;
|
||||
-moz-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.6);
|
||||
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.6);
|
||||
border: 1px solid rgba(255, 255, 255, 0.5);
|
||||
padding-left: 3px;
|
||||
padding-right: 3px;
|
||||
|
@ -478,17 +478,17 @@ input.defaultName {
|
|||
cursor: pointer;
|
||||
}
|
||||
|
||||
.inlineMatch:hover{
|
||||
.inlineMatch:hover {
|
||||
opacity: 1.0;
|
||||
}
|
||||
|
||||
.inlineMatch>img{
|
||||
.inlineMatch > img {
|
||||
margin-right: 5px;
|
||||
position: relative;
|
||||
top: 2px;
|
||||
}
|
||||
|
||||
.inlineMatch>span{
|
||||
max-width:200px;
|
||||
.inlineMatch > span {
|
||||
max-width: 200px;
|
||||
height: 15px;
|
||||
}
|
||||
|
|
|
@ -912,9 +912,18 @@ toolbar[mode="icons"] #zoom-in-button {
|
|||
margin: -2px 0 -1px;
|
||||
}
|
||||
|
||||
.tab-progress[busy][stalled][value="0"],
|
||||
#urlbar-progress[busy][stalled][value="0"] {
|
||||
/* TODO: add connecting state (bug 596812) */
|
||||
#urlbar-progress[value="0"] > .progress-remainder {
|
||||
background-image: -moz-linear-gradient(left, rgba(255,255,255,0), rgb(255,255,255), rgba(255,255,255,0)) !important;
|
||||
background-size: 10%;
|
||||
background-repeat: no-repeat;
|
||||
background-position: right;
|
||||
-moz-transition-property: background-position;
|
||||
-moz-transition-duration: 2s;
|
||||
-moz-transition-timing-function: linear;
|
||||
}
|
||||
|
||||
#urlbar-progress[value="0"][slideback] > .progress-remainder {
|
||||
background-position: left;
|
||||
}
|
||||
|
||||
.tab-progress > .progress-bar,
|
||||
|
@ -961,13 +970,8 @@ toolbar[mode="icons"] #zoom-in-button {
|
|||
|
||||
/* tab progress */
|
||||
|
||||
.tab-progress-container {
|
||||
margin-top: -2px;
|
||||
}
|
||||
|
||||
#tabbrowser-tabs[tabsontop="false"] > .tabbrowser-tab > .tab-stack > .tab-progress-container {
|
||||
-moz-box-pack: end;
|
||||
margin-bottom: -2px;
|
||||
}
|
||||
|
||||
/* ----- AUTOCOMPLETE ----- */
|
||||
|
@ -1549,6 +1553,11 @@ toolbarbutton.chevron > .toolbarbutton-menu-dropmarker {
|
|||
font-weight: bold;
|
||||
}
|
||||
|
||||
.tab-stack {
|
||||
/* ensure stable tab height with and without toolbarbuttons on the tab bar */
|
||||
height: 19px;
|
||||
}
|
||||
|
||||
.tabbrowser-tab,
|
||||
.tabs-newtab-button {
|
||||
-moz-appearance: none;
|
||||
|
@ -1565,7 +1574,6 @@ toolbarbutton.chevron > .toolbarbutton-menu-dropmarker {
|
|||
-moz-border-left-colors: rgba(0,0,0,.04) rgba(0,0,0,.17) rgba(255,255,255,.1);
|
||||
background-clip: padding-box;
|
||||
text-align: center;
|
||||
height: 24px;
|
||||
background-image: url(chrome://browser/skin/tabbrowser/tab-bkgnd.png);
|
||||
}
|
||||
|
||||
|
|
|
@ -1098,9 +1098,18 @@ html|*.urlbar-input:-moz-lwtheme:-moz-placeholder,
|
|||
background-color: transparent;
|
||||
}
|
||||
|
||||
.tab-progress[busy][stalled][value="0"],
|
||||
#urlbar-progress[busy][stalled][value="0"] {
|
||||
/* TODO: add connecting state (bug 596812) */
|
||||
#urlbar-progress[value="0"] > .progress-remainder {
|
||||
background-image: -moz-linear-gradient(left, rgba(255,255,255,0), rgb(255,255,255), rgba(255,255,255,0)) !important;
|
||||
background-size: 10%;
|
||||
background-repeat: no-repeat;
|
||||
background-position: right;
|
||||
-moz-transition-property: background-position;
|
||||
-moz-transition-duration: 2s;
|
||||
-moz-transition-timing-function: linear;
|
||||
}
|
||||
|
||||
#urlbar-progress[value="0"][slideback] > .progress-remainder {
|
||||
background-position: left;
|
||||
}
|
||||
|
||||
.tab-progress > .progress-bar,
|
||||
|
|
|
@ -461,3 +461,46 @@ input.defaultName {
|
|||
.notMainMatch{
|
||||
opacity: .70;
|
||||
}
|
||||
|
||||
#otherresults {
|
||||
left: 0px;
|
||||
bottom: 0px;
|
||||
width: 100%;
|
||||
height: 30px;
|
||||
background-color: rgba(0,0,0,.3);
|
||||
box-shadow: 0px -1px 0px rgba(255,255,255,.1), inset 0px 2px 5px rgba(0,0,0,.3);
|
||||
}
|
||||
|
||||
#otherresults .label {
|
||||
color: #999;
|
||||
line-height: 30px;
|
||||
margin-left: 5px;
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
.inlineMatch {
|
||||
background-color: #EBEBEB;
|
||||
border-radius: 0.4em;
|
||||
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.6);
|
||||
border: 1px solid rgba(255, 255, 255, 0.5);
|
||||
padding-left: 3px;
|
||||
padding-right: 3px;
|
||||
height: 20px;
|
||||
margin-right: 5px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.inlineMatch:hover {
|
||||
opacity: 1.0;
|
||||
}
|
||||
|
||||
.inlineMatch > img {
|
||||
margin-right: 5px;
|
||||
position: relative;
|
||||
top: 2px;
|
||||
}
|
||||
|
||||
.inlineMatch > span {
|
||||
max-width: 200px;
|
||||
height: 15px;
|
||||
}
|
||||
|
|
|
@ -121,8 +121,8 @@ postflight_all:
|
|||
# A universal .dmg can now be produced by making in either architecture's
|
||||
# INSTALLER_DIR.
|
||||
# Now, repeat the process for the test package.
|
||||
$(MAKE) -C $(OBJDIR_ARCH_1) UNIVERSAL_BINARY= package-tests
|
||||
$(MAKE) -C $(OBJDIR_ARCH_2) UNIVERSAL_BINARY= package-tests
|
||||
$(MAKE) -C $(OBJDIR_ARCH_1) UNIVERSAL_BINARY= CHROME_JAR= package-tests
|
||||
$(MAKE) -C $(OBJDIR_ARCH_2) UNIVERSAL_BINARY= CHROME_JAR= package-tests
|
||||
rm -rf $(DIST_UNI)/test-package-stage
|
||||
# automation.py differs because it hardcodes a path to
|
||||
# dist/bin. It doesn't matter which one we use.
|
||||
|
|
|
@ -111,4 +111,12 @@ public class ASMozStub extends android.app.Service {
|
|||
|
||||
System.exit(0);
|
||||
}
|
||||
|
||||
public void SendToDataChannel(String strToSend)
|
||||
{
|
||||
if (runDataThrd.isAlive())
|
||||
{
|
||||
runDataThrd.SendToDataChannel(strToSend);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
android:versionName="1.0" android:sharedUserId="org.mozilla.sharedID">
|
||||
<application android:icon="@drawable/icon" android:label="@string/app_name" android:debuggable="true">
|
||||
<activity android:name=".SUTAgentAndroid"
|
||||
android:screenOrientation="nosensor"
|
||||
android:label="@string/app_name">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
|
@ -25,7 +26,7 @@
|
|||
|
||||
</application>
|
||||
|
||||
<uses-sdk android:minSdkVersion="5"/>
|
||||
<uses-sdk android:minSdkVersion="5" android:targetSdkVersion="8"/>
|
||||
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"></uses-permission>
|
||||
<uses-permission android:name="android.permission.INTERNET"></uses-permission>
|
||||
|
@ -59,4 +60,9 @@
|
|||
|
||||
<uses-permission android:name="android.permission.VIBRATE"></uses-permission>
|
||||
|
||||
|
||||
|
||||
<uses-permission android:name="android.permission.SET_TIME"></uses-permission>
|
||||
|
||||
|
||||
</manifest>
|
|
@ -55,12 +55,15 @@ public class DataWorkerThread extends Thread
|
|||
private RunDataThread theParent = null;
|
||||
private Socket socket = null;
|
||||
boolean bListening = true;
|
||||
PrintWriter out = null;
|
||||
SimpleDateFormat sdf = null;
|
||||
|
||||
public DataWorkerThread(RunDataThread theParent, Socket workerSocket)
|
||||
{
|
||||
super("DataWorkerThread");
|
||||
this.theParent = theParent;
|
||||
this.socket = workerSocket;
|
||||
this.sdf = new SimpleDateFormat("yyyyMMdd-HH:mm:ss");
|
||||
}
|
||||
|
||||
public void StopListening()
|
||||
|
@ -68,6 +71,19 @@ public class DataWorkerThread extends Thread
|
|||
bListening = false;
|
||||
}
|
||||
|
||||
public void SendString(String strToSend)
|
||||
{
|
||||
if (this.out != null)
|
||||
{
|
||||
Calendar cal = Calendar.getInstance();
|
||||
String strOut = sdf.format(cal.getTime());
|
||||
strOut += " " + strToSend + "\r\n";
|
||||
|
||||
out.write(strOut);
|
||||
out.flush();
|
||||
}
|
||||
}
|
||||
|
||||
private String readLine(BufferedInputStream in)
|
||||
{
|
||||
String sRet = "";
|
||||
|
@ -135,13 +151,12 @@ public class DataWorkerThread extends Thread
|
|||
{
|
||||
OutputStream cmdOut = socket.getOutputStream();
|
||||
InputStream cmdIn = socket.getInputStream();
|
||||
PrintWriter out = new PrintWriter(cmdOut, true);
|
||||
this.out = new PrintWriter(cmdOut, true);
|
||||
BufferedInputStream in = new BufferedInputStream(cmdIn);
|
||||
String inputLine, outputLine;
|
||||
DoCommand dc = new DoCommand(theParent.svc);
|
||||
|
||||
Calendar cal = Calendar.getInstance();
|
||||
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd-HH:mm:ss");
|
||||
sRet = sdf.format(cal.getTime());
|
||||
sRet += " trace output";
|
||||
|
||||
|
|
|
@ -60,7 +60,9 @@ import java.text.SimpleDateFormat;
|
|||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.GregorianCalendar;
|
||||
import java.util.List;
|
||||
import java.util.TimeZone;
|
||||
import java.util.Timer;
|
||||
import java.util.zip.Adler32;
|
||||
import java.util.zip.CheckedInputStream;
|
||||
|
@ -95,6 +97,7 @@ import android.content.pm.PackageManager;
|
|||
import android.content.pm.PackageManager.NameNotFoundException;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Debug;
|
||||
import android.os.Environment;
|
||||
import android.os.StatFs;
|
||||
import android.os.SystemClock;
|
||||
|
@ -113,9 +116,9 @@ public class DoCommand {
|
|||
ContextWrapper contextWrapper = null;
|
||||
|
||||
String currentDir = "/";
|
||||
String sErrorPrefix = "##AGENT-ERROR## ";
|
||||
String sErrorPrefix = "##AGENT-WARNING## ";
|
||||
|
||||
private final String prgVersion = "SUTAgentAndroid Version 0.80";
|
||||
private final String prgVersion = "SUTAgentAndroid Version 0.85";
|
||||
|
||||
public enum Command
|
||||
{
|
||||
|
@ -128,6 +131,7 @@ public class DoCommand {
|
|||
OS ("os"),
|
||||
ID ("id"),
|
||||
UPTIME ("uptime"),
|
||||
SETTIME ("settime"),
|
||||
SYSTIME ("systime"),
|
||||
SCREEN ("screen"),
|
||||
MEMORY ("memory"),
|
||||
|
@ -215,10 +219,18 @@ public class DoCommand {
|
|||
strReturn = prgVersion;
|
||||
break;
|
||||
|
||||
case CLOK:
|
||||
strReturn = GetClok();
|
||||
break;
|
||||
|
||||
case UPDT:
|
||||
strReturn = StartUpdateOMatic(Argv[1], Argv[2]);
|
||||
break;
|
||||
|
||||
case SETTIME:
|
||||
strReturn = SetSystemTime(Argv[1], Argv[2], cmdOut);
|
||||
break;
|
||||
|
||||
case CWD:
|
||||
try {
|
||||
strReturn = new java.io.File(currentDir).getCanonicalPath();
|
||||
|
@ -244,7 +256,7 @@ public class DoCommand {
|
|||
if (Argc == 2)
|
||||
strReturn = GetAppRoot(Argv[1]);
|
||||
else
|
||||
strReturn = sErrorPrefix + "Wrong number of arguments for cd command!";
|
||||
strReturn = sErrorPrefix + "Wrong number of arguments for getapproot command!";
|
||||
break;
|
||||
|
||||
case TESTROOT:
|
||||
|
@ -1929,6 +1941,84 @@ public class DoCommand {
|
|||
return (sRet);
|
||||
}
|
||||
|
||||
public String SetSystemTime(String sDate, String sTime, OutputStream out)
|
||||
{
|
||||
// Debug.waitForDebugger();
|
||||
String sRet = "";
|
||||
|
||||
// Intent prgIntent = new Intent(android.provider.Settings.ACTION_DATE_SETTINGS);
|
||||
// prgIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
// contextWrapper.startActivity(prgIntent);
|
||||
|
||||
// 2010/09/22
|
||||
// 15:41:00
|
||||
// 0123456789012345678
|
||||
|
||||
if (((sDate != null) && (sTime != null)) &&
|
||||
(sDate.contains("/") || sDate.contains(".")) &&
|
||||
(sTime.contains(":")))
|
||||
{
|
||||
int year = Integer.parseInt(sDate.substring(0,4));
|
||||
int month = Integer.parseInt(sDate.substring(5,7));
|
||||
int day = Integer.parseInt(sDate.substring(8,10));
|
||||
|
||||
int hour = Integer.parseInt(sTime.substring(0,2));
|
||||
int mins = Integer.parseInt(sTime.substring(3,5));
|
||||
int secs = Integer.parseInt(sTime.substring(6,8));
|
||||
|
||||
Calendar cal = new GregorianCalendar(TimeZone.getTimeZone("GMT"));
|
||||
cal.set(year, month - 1, day, hour, mins, secs);
|
||||
long lMillisecs = cal.getTime().getTime();
|
||||
|
||||
// boolean bRet = SystemClock.setCurrentTimeMillis(lMillisecs);
|
||||
String sM = Long.toString(lMillisecs);
|
||||
// long lm = 1285175618316L;
|
||||
String sTest = cal.getTime().toGMTString();
|
||||
String sMillis = sM.substring(0, sM.length() - 3) + "." + sM.substring(sM.length() - 3);
|
||||
String [] theArgs = new String [3];
|
||||
|
||||
theArgs[0] = "su";
|
||||
theArgs[1] = "-c";
|
||||
theArgs[2] = "date -u " + sMillis;
|
||||
|
||||
try
|
||||
{
|
||||
pProc = Runtime.getRuntime().exec(theArgs);
|
||||
RedirOutputThread outThrd = new RedirOutputThread(pProc, null);
|
||||
outThrd.start();
|
||||
outThrd.join(10000);
|
||||
sRet = GetSystemTime();
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
sRet = e.getMessage();
|
||||
e.printStackTrace();
|
||||
}
|
||||
catch (InterruptedException e)
|
||||
{
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sRet = "Invalid argument(s)";
|
||||
}
|
||||
|
||||
return (sRet);
|
||||
}
|
||||
|
||||
public String GetClok()
|
||||
{
|
||||
long lMillisecs = System.currentTimeMillis();
|
||||
String sRet = "";
|
||||
|
||||
if (lMillisecs > 0)
|
||||
sRet = Long.toString(lMillisecs);
|
||||
|
||||
return(sRet);
|
||||
}
|
||||
|
||||
public String GetUptime()
|
||||
{
|
||||
String sRet = "";
|
||||
|
@ -2140,6 +2230,9 @@ public class DoCommand {
|
|||
|
||||
try
|
||||
{
|
||||
// Tell all of the data channels we are rebooting
|
||||
((ASMozStub)this.contextWrapper).SendToDataChannel("Rebooting ...");
|
||||
|
||||
pProc = Runtime.getRuntime().exec(theArgs);
|
||||
RedirOutputThread outThrd = new RedirOutputThread(pProc, out);
|
||||
outThrd.start();
|
||||
|
@ -2551,6 +2644,9 @@ public class DoCommand {
|
|||
"rebt - reboot device\n" +
|
||||
"inst /path/filename.apk - install the referenced apk file\n" +
|
||||
"uninst packagename - uninstall the referenced package\n" +
|
||||
"updt pkgname pkgfile - unpdate the referenced package\n" +
|
||||
"clok - the current device time expressed as the number of millisecs since epoch\n" +
|
||||
"settime date time - sets the device date and time (YYYY/MM/DD HH:MM:SS)\n" +
|
||||
"rebt - reboot device\n" +
|
||||
"quit - disconnect SUTAgent\n" +
|
||||
"exit - close SUTAgent\n" +
|
||||
|
|
|
@ -67,6 +67,19 @@ public class RunDataThread extends Thread
|
|||
bListening = false;
|
||||
}
|
||||
|
||||
public void SendToDataChannel(String strToSend)
|
||||
{
|
||||
int nNumWorkers = theWorkers.size();
|
||||
for (int lcv = 0; lcv < nNumWorkers; lcv++)
|
||||
{
|
||||
if (theWorkers.get(lcv).isAlive())
|
||||
{
|
||||
theWorkers.get(lcv).SendString(strToSend);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
public void run() {
|
||||
try {
|
||||
SvrSocket.setSoTimeout(5000);
|
||||
|
|
|
@ -65,6 +65,7 @@ import android.net.wifi.WifiManager;
|
|||
import android.net.wifi.WifiManager.WifiLock;
|
||||
import android.os.BatteryManager;
|
||||
import android.os.Bundle;
|
||||
import android.os.Debug;
|
||||
import android.os.PowerManager;
|
||||
import android.telephony.TelephonyManager;
|
||||
import android.util.Log;
|
||||
|
@ -134,6 +135,8 @@ public class SUTAgentAndroid extends Activity
|
|||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.main);
|
||||
|
||||
// Debug.waitForDebugger();
|
||||
|
||||
// long lHeapSize = VMRuntime.getRuntime().getMinimumHeapSize();
|
||||
// lHeapSize = 16000000;
|
||||
// VMRuntime.getRuntime().setMinimumHeapSize(lHeapSize);
|
||||
|
|
|
@ -525,6 +525,7 @@ MOZ_ENABLE_XREMOTE = @MOZ_ENABLE_XREMOTE@
|
|||
MOZ_ENABLE_DWRITE_FONT = @MOZ_ENABLE_DWRITE_FONT@
|
||||
MOZ_ENABLE_D2D_SURFACE = @MOZ_ENABLE_D2D_SURFACE@
|
||||
MOZ_ENABLE_D3D9_LAYER = @MOZ_ENABLE_D3D9_LAYER@
|
||||
MOZ_ENABLE_D3D10_LAYER = @MOZ_ENABLE_D3D10_LAYER@
|
||||
|
||||
MOZ_GTK2_CFLAGS = @MOZ_GTK2_CFLAGS@
|
||||
MOZ_GTK2_LIBS = @MOZ_GTK2_LIBS@
|
||||
|
|
10
configure.in
10
configure.in
|
@ -4958,6 +4958,7 @@ MOZ_XTF=1
|
|||
MOZ_XUL=1
|
||||
MOZ_ZIPWRITER=1
|
||||
NS_PRINTING=1
|
||||
MOZ_DISABLE_DOMCRYPTO=
|
||||
NSS_DISABLE_DBM=
|
||||
NECKO_WIFI=1
|
||||
NECKO_COOKIES=1
|
||||
|
@ -6611,6 +6612,13 @@ fi
|
|||
|
||||
AC_SUBST(MOZ_DISABLE_PARENTAL_CONTROLS)
|
||||
|
||||
dnl ========================================================
|
||||
dnl = Disable DOMCrypto
|
||||
dnl ========================================================
|
||||
if test -n "$MOZ_DISABLE_DOMCRYPTO"; then
|
||||
AC_DEFINE(MOZ_DISABLE_DOMCRYPTO)
|
||||
fi
|
||||
|
||||
dnl ========================================================
|
||||
dnl =
|
||||
dnl = Module specific options
|
||||
|
@ -8425,6 +8433,7 @@ if test "$MOZ_TREE_CAIRO"; then
|
|||
fi
|
||||
|
||||
AC_CHECK_HEADER(d3d9.h, MOZ_ENABLE_D3D9_LAYER=1)
|
||||
AC_CHECK_HEADER(d3d10.h, MOZ_ENABLE_D3D10_LAYER=1)
|
||||
|
||||
AC_TRY_COMPILE([#include <ddraw.h>], [int foo = DDLOCK_WAITNOTBUSY;], HAS_DDRAW=1, HAS_DDRAW=)
|
||||
if test -z "$HAS_DDRAW"; then
|
||||
|
@ -8474,6 +8483,7 @@ if test "$MOZ_TREE_CAIRO"; then
|
|||
AC_SUBST(MOZ_ENABLE_DWRITE_FONT)
|
||||
AC_SUBST(MOZ_ENABLE_D2D_SURFACE)
|
||||
AC_SUBST(MOZ_ENABLE_D3D9_LAYER)
|
||||
AC_SUBST(MOZ_ENABLE_D3D10_LAYER)
|
||||
AC_SUBST(CAIRO_FT_CFLAGS)
|
||||
AC_SUBST(HAS_OGLES)
|
||||
|
||||
|
|
|
@ -155,7 +155,7 @@ NS_IMETHODIMP
|
|||
nsCrossSiteListenerProxy::OnStartRequest(nsIRequest* aRequest,
|
||||
nsISupports* aContext)
|
||||
{
|
||||
mRequestApproved = NS_SUCCEEDED(CheckRequestApproved(aRequest, PR_FALSE));
|
||||
mRequestApproved = NS_SUCCEEDED(CheckRequestApproved(aRequest));
|
||||
if (!mRequestApproved) {
|
||||
if (nsXMLHttpRequest::sAccessControlCache) {
|
||||
nsCOMPtr<nsIChannel> channel = do_QueryInterface(aRequest);
|
||||
|
@ -219,8 +219,7 @@ IsValidHTTPToken(const nsCSubstring& aToken)
|
|||
}
|
||||
|
||||
nsresult
|
||||
nsCrossSiteListenerProxy::CheckRequestApproved(nsIRequest* aRequest,
|
||||
PRBool aIsRedirect)
|
||||
nsCrossSiteListenerProxy::CheckRequestApproved(nsIRequest* aRequest)
|
||||
{
|
||||
// Check if this was actually a cross domain request
|
||||
if (!mHasBeenCrossSite) {
|
||||
|
@ -241,21 +240,6 @@ nsCrossSiteListenerProxy::CheckRequestApproved(nsIRequest* aRequest,
|
|||
nsCOMPtr<nsIHttpChannel> http = do_QueryInterface(aRequest);
|
||||
NS_ENSURE_TRUE(http, NS_ERROR_DOM_BAD_URI);
|
||||
|
||||
// Redirects aren't success-codes. But necko already checked that it was a
|
||||
// valid redirect.
|
||||
if (!aIsRedirect) {
|
||||
PRBool succeeded;
|
||||
rv = http->GetRequestSucceeded(&succeeded);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (!succeeded) {
|
||||
PRUint32 responseStatus;
|
||||
rv = http->GetResponseStatus(&responseStatus);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
NS_ENSURE_TRUE(mAllowedHTTPErrors.Contains(responseStatus),
|
||||
NS_ERROR_DOM_BAD_URI);
|
||||
}
|
||||
}
|
||||
|
||||
// Check the Access-Control-Allow-Origin header
|
||||
nsCAutoString allowedOriginHeader;
|
||||
rv = http->GetResponseHeader(
|
||||
|
@ -286,12 +270,20 @@ nsCrossSiteListenerProxy::CheckRequestApproved(nsIRequest* aRequest,
|
|||
}
|
||||
|
||||
if (mIsPreflight) {
|
||||
PRBool succeeded;
|
||||
rv = http->GetRequestSucceeded(&succeeded);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (!succeeded) {
|
||||
return NS_ERROR_DOM_BAD_URI;
|
||||
}
|
||||
|
||||
nsCAutoString headerVal;
|
||||
// The "Access-Control-Allow-Methods" header contains a comma separated
|
||||
// list of method names.
|
||||
http->GetResponseHeader(NS_LITERAL_CSTRING("Access-Control-Allow-Methods"),
|
||||
headerVal);
|
||||
PRBool foundMethod = mPreflightMethod.EqualsLiteral("GET") ||
|
||||
mPreflightMethod.EqualsLiteral("HEAD") ||
|
||||
mPreflightMethod.EqualsLiteral("POST");
|
||||
nsCCharSeparatedTokenizer methodTokens(headerVal, ',');
|
||||
while(methodTokens.hasMoreTokens()) {
|
||||
|
@ -379,7 +371,7 @@ nsCrossSiteListenerProxy::AsyncOnChannelRedirect(nsIChannel *aOldChannel,
|
|||
{
|
||||
nsresult rv;
|
||||
if (!NS_IsInternalSameURIRedirect(aOldChannel, aNewChannel, aFlags)) {
|
||||
rv = CheckRequestApproved(aOldChannel, PR_TRUE);
|
||||
rv = CheckRequestApproved(aOldChannel);
|
||||
if (NS_FAILED(rv)) {
|
||||
if (nsXMLHttpRequest::sAccessControlCache) {
|
||||
nsCOMPtr<nsIURI> oldURI;
|
||||
|
|
|
@ -84,14 +84,9 @@ public:
|
|||
// Must be called at startup.
|
||||
static void Startup();
|
||||
|
||||
void AllowHTTPResult(PRUint32 aResultCode)
|
||||
{
|
||||
mAllowedHTTPErrors.AppendElement(aResultCode);
|
||||
}
|
||||
|
||||
private:
|
||||
nsresult UpdateChannel(nsIChannel* aChannel);
|
||||
nsresult CheckRequestApproved(nsIRequest* aRequest, PRBool aIsRedirect);
|
||||
nsresult CheckRequestApproved(nsIRequest* aRequest);
|
||||
|
||||
nsCOMPtr<nsIStreamListener> mOuterListener;
|
||||
nsCOMPtr<nsIPrincipal> mRequestingPrincipal;
|
||||
|
@ -102,7 +97,6 @@ private:
|
|||
PRBool mIsPreflight;
|
||||
nsCString mPreflightMethod;
|
||||
nsTArray<nsCString> mPreflightHeaders;
|
||||
nsTArray<PRUint32> mAllowedHTTPErrors;
|
||||
nsCOMPtr<nsIAsyncVerifyRedirectCallback> mRedirectCallback;
|
||||
nsCOMPtr<nsIChannel> mOldRedirectChannel;
|
||||
nsCOMPtr<nsIChannel> mNewRedirectChannel;
|
||||
|
|
|
@ -59,6 +59,9 @@
|
|||
#include "nsDOMError.h"
|
||||
#include "nsIDOMWindow.h"
|
||||
#include "nsPIDOMWindow.h"
|
||||
#include "mozilla/AutoRestore.h"
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
// nsIDOMEventListener
|
||||
nsresult
|
||||
|
@ -263,6 +266,7 @@ nsDOMParser::ParseFromStream(nsIInputStream *stream,
|
|||
// Tell the document to start loading
|
||||
nsCOMPtr<nsIStreamListener> listener;
|
||||
|
||||
AutoRestore<PRPackedBool> restoreSyncLoop(mLoopingForSyncLoad);
|
||||
mLoopingForSyncLoad = PR_TRUE;
|
||||
|
||||
// Have to pass PR_FALSE for reset here, else the reset will remove
|
||||
|
|
|
@ -587,6 +587,7 @@ GK_ATOM(mouseover, "mouseover")
|
|||
GK_ATOM(mousethrough, "mousethrough")
|
||||
GK_ATOM(mouseup, "mouseup")
|
||||
GK_ATOM(moz_opaque, "moz-opaque")
|
||||
GK_ATOM(x_moz_errormessage, "x-moz-errormessage")
|
||||
GK_ATOM(msthemecompatible, "msthemecompatible")
|
||||
GK_ATOM(multicol, "multicol")
|
||||
GK_ATOM(multiple, "multiple")
|
||||
|
|
|
@ -1416,7 +1416,13 @@ nsXMLHttpRequest::GetResponseHeader(const nsACString& header,
|
|||
nsACString& _retval)
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
_retval.Truncate();
|
||||
_retval.SetIsVoid(PR_TRUE);
|
||||
|
||||
nsCOMPtr<nsIHttpChannel> httpChannel = GetCurrentHttpChannel();
|
||||
|
||||
if (!httpChannel) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// See bug #380418. Hide "Set-Cookie" headers from non-chrome scripts.
|
||||
PRBool chrome = PR_FALSE; // default to false in case IsCapabilityEnabled fails
|
||||
|
@ -1425,13 +1431,11 @@ nsXMLHttpRequest::GetResponseHeader(const nsACString& header,
|
|||
(header.LowerCaseEqualsASCII("set-cookie") ||
|
||||
header.LowerCaseEqualsASCII("set-cookie2"))) {
|
||||
NS_WARNING("blocked access to response header");
|
||||
_retval.SetIsVoid(PR_TRUE);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Check for dangerous headers
|
||||
if (mState & XML_HTTP_REQUEST_USE_XSITE_AC) {
|
||||
|
||||
// Make sure we don't leak header information from denied cross-site
|
||||
// requests.
|
||||
if (mChannel) {
|
||||
|
@ -1455,17 +1459,34 @@ nsXMLHttpRequest::GetResponseHeader(const nsACString& header,
|
|||
}
|
||||
}
|
||||
|
||||
if (!safeHeader) {
|
||||
nsCAutoString headerVal;
|
||||
// The "Access-Control-Expose-Headers" header contains a comma separated
|
||||
// list of method names.
|
||||
httpChannel->
|
||||
GetResponseHeader(NS_LITERAL_CSTRING("Access-Control-Expose-Headers"),
|
||||
headerVal);
|
||||
nsCCharSeparatedTokenizer exposeTokens(headerVal, ',');
|
||||
while(exposeTokens.hasMoreTokens()) {
|
||||
const nsDependentCSubstring& token = exposeTokens.nextToken();
|
||||
if (token.IsEmpty()) {
|
||||
continue;
|
||||
}
|
||||
if (!IsValidHTTPToken(token)) {
|
||||
return NS_OK;
|
||||
}
|
||||
if (header.Equals(token, nsCaseInsensitiveCStringComparator())) {
|
||||
safeHeader = PR_TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!safeHeader) {
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIHttpChannel> httpChannel = GetCurrentHttpChannel();
|
||||
|
||||
if (httpChannel) {
|
||||
rv = httpChannel->GetResponseHeader(header, _retval);
|
||||
}
|
||||
|
||||
if (rv == NS_ERROR_NOT_AVAILABLE) {
|
||||
// Means no header
|
||||
_retval.SetIsVoid(PR_TRUE);
|
||||
|
@ -1586,8 +1607,6 @@ nsXMLHttpRequest::GetCurrentHttpChannel()
|
|||
nsresult
|
||||
nsXMLHttpRequest::CheckChannelForCrossSiteRequest(nsIChannel* aChannel)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
// First check if cross-site requests are enabled
|
||||
if ((mState & XML_HTTP_REQUEST_XSITEENABLED)) {
|
||||
return NS_OK;
|
||||
|
@ -1611,24 +1630,10 @@ nsXMLHttpRequest::CheckChannelForCrossSiteRequest(nsIChannel* aChannel)
|
|||
httpChannel->GetRequestMethod(method);
|
||||
if (!mACUnsafeHeaders.IsEmpty() ||
|
||||
HasListenersFor(NS_LITERAL_STRING(UPLOADPROGRESS_STR)) ||
|
||||
(mUpload && mUpload->HasListeners())) {
|
||||
mState |= XML_HTTP_REQUEST_NEED_AC_PREFLIGHT;
|
||||
}
|
||||
else if (method.LowerCaseEqualsLiteral("post")) {
|
||||
nsCAutoString contentTypeHeader;
|
||||
httpChannel->GetRequestHeader(NS_LITERAL_CSTRING("Content-Type"),
|
||||
contentTypeHeader);
|
||||
|
||||
nsCAutoString contentType, charset;
|
||||
rv = NS_ParseContentType(contentTypeHeader, contentType, charset);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (!contentType.LowerCaseEqualsLiteral("text/plain")) {
|
||||
mState |= XML_HTTP_REQUEST_NEED_AC_PREFLIGHT;
|
||||
}
|
||||
}
|
||||
else if (!method.LowerCaseEqualsLiteral("get") &&
|
||||
!method.LowerCaseEqualsLiteral("head")) {
|
||||
(mUpload && mUpload->HasListeners()) ||
|
||||
(!method.LowerCaseEqualsLiteral("get") &&
|
||||
!method.LowerCaseEqualsLiteral("post") &&
|
||||
!method.LowerCaseEqualsLiteral("head"))) {
|
||||
mState |= XML_HTTP_REQUEST_NEED_AC_PREFLIGHT;
|
||||
}
|
||||
|
||||
|
@ -2488,7 +2493,7 @@ nsXMLHttpRequest::Send(nsIVariant *aBody)
|
|||
// ignore the necessary headers for an empty Content-Type.
|
||||
nsCOMPtr<nsIUploadChannel2> uploadChannel2(do_QueryInterface(httpChannel));
|
||||
// This assertion will fire if buggy extensions are installed
|
||||
NS_ASSERTION(uploadChannel2, "http must support nsIUploadChannel");
|
||||
NS_ASSERTION(uploadChannel2, "http must support nsIUploadChannel2");
|
||||
if (uploadChannel2) {
|
||||
uploadChannel2->ExplicitSetUploadStream(postDataStream, contentType,
|
||||
-1, method, PR_FALSE);
|
||||
|
@ -2508,6 +2513,23 @@ nsXMLHttpRequest::Send(nsIVariant *aBody)
|
|||
}
|
||||
}
|
||||
|
||||
if (httpChannel) {
|
||||
nsCAutoString contentTypeHeader;
|
||||
rv = httpChannel->GetRequestHeader(NS_LITERAL_CSTRING("Content-Type"),
|
||||
contentTypeHeader);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
nsCAutoString contentType, charset;
|
||||
rv = NS_ParseContentType(contentTypeHeader, contentType, charset);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (!contentType.LowerCaseEqualsLiteral("text/plain") &&
|
||||
!contentType.LowerCaseEqualsLiteral("application/x-www-form-urlencoded") &&
|
||||
!contentType.LowerCaseEqualsLiteral("multipart/form-data")) {
|
||||
mACUnsafeHeaders.AppendElement(NS_LITERAL_CSTRING("Content-Type"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Reset responseBody
|
||||
mResponseBody.Truncate();
|
||||
mResponseBodyUnicode.SetIsVoid(PR_TRUE);
|
||||
|
@ -2765,8 +2787,10 @@ nsXMLHttpRequest::SetRequestHeader(const nsACString& header,
|
|||
// Check for dangerous cross-site headers
|
||||
PRBool safeHeader = !!(mState & XML_HTTP_REQUEST_XSITEENABLED);
|
||||
if (!safeHeader) {
|
||||
// Content-Type isn't always safe, but we'll deal with it in Send()
|
||||
const char *kCrossOriginSafeHeaders[] = {
|
||||
"accept", "accept-language", "content-type"
|
||||
"accept", "accept-language", "content-language", "content-type",
|
||||
"last-event-id"
|
||||
};
|
||||
for (i = 0; i < NS_ARRAY_LENGTH(kCrossOriginSafeHeaders); ++i) {
|
||||
if (header.LowerCaseEqualsASCII(kCrossOriginSafeHeaders[i])) {
|
||||
|
|
|
@ -260,6 +260,7 @@ _TEST_FILES1 = test_bug5141.html \
|
|||
test_bug505783.html \
|
||||
test_bug457746.html \
|
||||
test_bug587931.html \
|
||||
test_bug592829.html \
|
||||
test_bug518104.html \
|
||||
bug457746.sjs \
|
||||
test_CrossSiteXHR.html \
|
||||
|
|
|
@ -43,17 +43,10 @@ window.addEventListener("message", function(e) {
|
|||
}, false);
|
||||
}
|
||||
}
|
||||
xhr.onload = function () {
|
||||
res.status = xhr.status;
|
||||
res.statusText = xhr.statusText;
|
||||
res.responseXML = xhr.responseXML ?
|
||||
(new XMLSerializer()).serializeToString(xhr.responseXML) :
|
||||
null;
|
||||
res.responseText = xhr.responseText;
|
||||
post(e, res);
|
||||
};
|
||||
xhr.onerror = function () {
|
||||
xhr.onload = xhr.onerror = function (event) {
|
||||
if (event.type == "error") {
|
||||
res.didFail = true;
|
||||
}
|
||||
res.status = xhr.status;
|
||||
try {
|
||||
res.statusText = xhr.statusText;
|
||||
|
@ -63,6 +56,13 @@ window.addEventListener("message", function(e) {
|
|||
(new XMLSerializer()).serializeToString(xhr.responseXML) :
|
||||
null;
|
||||
res.responseText = xhr.responseText;
|
||||
|
||||
res.responseHeaders = {};
|
||||
for (responseHeader in req.responseHeaders) {
|
||||
res.responseHeaders[responseHeader] =
|
||||
xhr.getResponseHeader(responseHeader);
|
||||
}
|
||||
|
||||
post(e, res);
|
||||
}
|
||||
|
||||
|
|
|
@ -101,6 +101,13 @@ function handleRequest(request, response)
|
|||
query.allowHeaders = hops[query.hop-1].allowHeaders;
|
||||
}
|
||||
|
||||
if (!isPreflight && query.status) {
|
||||
response.setStatusLine(null, query.status, query.statusMessage);
|
||||
}
|
||||
if (isPreflight && query.preflightStatus) {
|
||||
response.setStatusLine(null, query.preflightStatus, "preflight status");
|
||||
}
|
||||
|
||||
if (query.allowOrigin && (!isPreflight || !query.noAllowPreflight))
|
||||
response.setHeader("Access-Control-Allow-Origin", query.allowOrigin);
|
||||
|
||||
|
@ -117,6 +124,17 @@ function handleRequest(request, response)
|
|||
if (query.allowMethods)
|
||||
response.setHeader("Access-Control-Allow-Methods", query.allowMethods);
|
||||
}
|
||||
else {
|
||||
if (query.responseHeaders) {
|
||||
let responseHeaders = eval(query.responseHeaders);
|
||||
for (let responseHeader in responseHeaders) {
|
||||
response.setHeader(responseHeader, responseHeaders[responseHeader]);
|
||||
}
|
||||
}
|
||||
|
||||
if (query.exposeHeaders)
|
||||
response.setHeader("Access-Control-Expose-Headers", query.exposeHeaders);
|
||||
}
|
||||
|
||||
if (query.hop && query.hop < hops.length) {
|
||||
newURL = hops[query.hop].server +
|
||||
|
|
|
@ -43,299 +43,541 @@ function runTest() {
|
|||
origin = "http://example.org";
|
||||
yield;
|
||||
|
||||
passTests = [{ method: "GET",
|
||||
tests = [// Plain request
|
||||
{ pass: 1,
|
||||
method: "GET",
|
||||
noAllowPreflight: 1,
|
||||
},
|
||||
{ method: "GET",
|
||||
headers: { "Content-Type": "baz/bin",
|
||||
|
||||
// Default allowed headers
|
||||
{ pass: 1,
|
||||
method: "GET",
|
||||
headers: { "Content-Type": "text/plain",
|
||||
"Accept": "foo/bar",
|
||||
"Accept-Language": "sv-SE" },
|
||||
noAllowPreflight: 1,
|
||||
},
|
||||
{ method: "GET",
|
||||
{ pass: 0,
|
||||
method: "GET",
|
||||
headers: { "Content-Type": "foo/bar",
|
||||
"Accept": "foo/bar",
|
||||
"Accept-Language": "sv-SE" },
|
||||
noAllowPreflight: 1,
|
||||
},
|
||||
|
||||
// Custom headers
|
||||
{ pass: 1,
|
||||
method: "GET",
|
||||
headers: { "x-my-header": "myValue" },
|
||||
allowHeaders: "x-my-header",
|
||||
},
|
||||
{ method: "GET",
|
||||
{ pass: 1,
|
||||
method: "GET",
|
||||
headers: { "x-my-header": "myValue" },
|
||||
allowHeaders: "X-My-Header",
|
||||
},
|
||||
{ pass: 1,
|
||||
method: "GET",
|
||||
headers: { "x-my-header": "myValue",
|
||||
"long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header": "secondValue" },
|
||||
allowHeaders: "x-my-header, long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header",
|
||||
},
|
||||
{ pass: 1,
|
||||
method: "GET",
|
||||
headers: { "x-my%-header": "myValue" },
|
||||
allowHeaders: "x-my%-header",
|
||||
},
|
||||
{ pass: 0,
|
||||
method: "GET",
|
||||
headers: { "x-my-header": "myValue" },
|
||||
},
|
||||
{ pass: 0,
|
||||
method: "GET",
|
||||
headers: { "x-my-header": "" },
|
||||
},
|
||||
{ pass: 0,
|
||||
method: "GET",
|
||||
headers: { "x-my-header": "myValue" },
|
||||
allowHeaders: "",
|
||||
},
|
||||
{ pass: 0,
|
||||
method: "GET",
|
||||
headers: { "x-my-header": "myValue" },
|
||||
allowHeaders: "y-my-header",
|
||||
},
|
||||
{ pass: 0,
|
||||
method: "GET",
|
||||
headers: { "x-my-header": "myValue" },
|
||||
allowHeaders: "x-my-header y-my-header",
|
||||
},
|
||||
{ pass: 0,
|
||||
method: "GET",
|
||||
headers: { "x-my-header": "myValue" },
|
||||
allowHeaders: "x-my-header, y-my-header z",
|
||||
},
|
||||
{ pass: 0,
|
||||
method: "GET",
|
||||
headers: { "x-my-header": "myValue" },
|
||||
allowHeaders: "x-my-header, y-my-he(ader",
|
||||
},
|
||||
{ pass: 0,
|
||||
method: "GET",
|
||||
headers: { "myheader": "" },
|
||||
allowMethods: "myheader",
|
||||
},
|
||||
|
||||
// Multiple custom headers
|
||||
{ pass: 1,
|
||||
method: "GET",
|
||||
headers: { "x-my-header": "myValue",
|
||||
"second-header": "secondValue",
|
||||
"third-header": "thirdValue" },
|
||||
allowHeaders: "x-my-header, second-header, third-header",
|
||||
},
|
||||
{ method: "GET",
|
||||
{ pass: 1,
|
||||
method: "GET",
|
||||
headers: { "x-my-header": "myValue",
|
||||
"second-header": "secondValue",
|
||||
"third-header": "thirdValue" },
|
||||
allowHeaders: "x-my-header,second-header,third-header",
|
||||
},
|
||||
{ method: "GET",
|
||||
{ pass: 1,
|
||||
method: "GET",
|
||||
headers: { "x-my-header": "myValue",
|
||||
"second-header": "secondValue",
|
||||
"third-header": "thirdValue" },
|
||||
allowHeaders: "x-my-header ,second-header ,third-header",
|
||||
},
|
||||
{ method: "GET",
|
||||
{ pass: 1,
|
||||
method: "GET",
|
||||
headers: { "x-my-header": "myValue",
|
||||
"second-header": "secondValue",
|
||||
"third-header": "thirdValue" },
|
||||
allowHeaders: "x-my-header , second-header , third-header",
|
||||
},
|
||||
{ method: "GET",
|
||||
{ pass: 1,
|
||||
method: "GET",
|
||||
headers: { "x-my-header": "myValue",
|
||||
"second-header": "secondValue" },
|
||||
allowHeaders: ", x-my-header, , ,, second-header, , ",
|
||||
},
|
||||
{ method: "GET",
|
||||
{ pass: 1,
|
||||
method: "GET",
|
||||
headers: { "x-my-header": "myValue",
|
||||
"second-header": "secondValue" },
|
||||
allowHeaders: "x-my-header, second-header, unused-header",
|
||||
},
|
||||
{ method: "GET",
|
||||
headers: { "x-my-header": "myValue" },
|
||||
allowHeaders: "X-My-Header",
|
||||
},
|
||||
{ method: "GET",
|
||||
{ pass: 0,
|
||||
method: "GET",
|
||||
headers: { "x-my-header": "myValue",
|
||||
"long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header": "secondValue" },
|
||||
allowHeaders: "x-my-header, long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header",
|
||||
"y-my-header": "secondValue" },
|
||||
allowHeaders: "x-my-header",
|
||||
},
|
||||
{ method: "GET",
|
||||
headers: { "x-my%-header": "myValue" },
|
||||
allowHeaders: "x-my%-header",
|
||||
{ pass: 0,
|
||||
method: "GET",
|
||||
headers: { "x-my-header": "",
|
||||
"y-my-header": "" },
|
||||
allowHeaders: "x-my-header",
|
||||
},
|
||||
{ method: "HEAD",
|
||||
|
||||
// HEAD requests
|
||||
{ pass: 1,
|
||||
method: "HEAD",
|
||||
noAllowPreflight: 1,
|
||||
},
|
||||
{ method: "HEAD",
|
||||
headers: { "Content-Type": "baz/bin",
|
||||
|
||||
// HEAD with safe headers
|
||||
{ pass: 1,
|
||||
method: "HEAD",
|
||||
headers: { "Content-Type": "text/plain",
|
||||
"Accept": "foo/bar",
|
||||
"Accept-Language": "sv-SE" },
|
||||
noAllowPreflight: 1,
|
||||
},
|
||||
{ method: "POST",
|
||||
{ pass: 0,
|
||||
method: "HEAD",
|
||||
headers: { "Content-Type": "foo/bar",
|
||||
"Accept": "foo/bar",
|
||||
"Accept-Language": "sv-SE" },
|
||||
noAllowPreflight: 1,
|
||||
},
|
||||
|
||||
// HEAD with custom headers
|
||||
{ pass: 1,
|
||||
method: "HEAD",
|
||||
headers: { "x-my-header": "myValue" },
|
||||
allowHeaders: "x-my-header",
|
||||
},
|
||||
{ pass: 0,
|
||||
method: "HEAD",
|
||||
headers: { "x-my-header": "myValue" },
|
||||
},
|
||||
{ pass: 0,
|
||||
method: "HEAD",
|
||||
headers: { "x-my-header": "myValue" },
|
||||
allowHeaders: "",
|
||||
},
|
||||
{ pass: 0,
|
||||
method: "HEAD",
|
||||
headers: { "x-my-header": "myValue" },
|
||||
allowHeaders: "y-my-header",
|
||||
},
|
||||
{ pass: 0,
|
||||
method: "HEAD",
|
||||
headers: { "x-my-header": "myValue" },
|
||||
allowHeaders: "x-my-header y-my-header",
|
||||
},
|
||||
|
||||
// POST tests
|
||||
{ pass: 1,
|
||||
method: "POST",
|
||||
body: "hi there",
|
||||
noAllowPreflight: 1,
|
||||
},
|
||||
{ method: "POST",
|
||||
{ pass: 1,
|
||||
method: "POST",
|
||||
},
|
||||
{ method: "POST",
|
||||
{ pass: 1,
|
||||
method: "POST",
|
||||
noAllowPreflight: 1,
|
||||
},
|
||||
|
||||
// POST with standard headers
|
||||
{ pass: 1,
|
||||
method: "POST",
|
||||
body: "hi there",
|
||||
headers: { "Content-Type": "text/plain" },
|
||||
noAllowPreflight: 1,
|
||||
},
|
||||
{ method: "POST",
|
||||
{ pass: 1,
|
||||
method: "POST",
|
||||
body: "hi there",
|
||||
headers: { "Content-Type": "multipart/form-data" },
|
||||
noAllowPreflight: 1,
|
||||
},
|
||||
{ pass: 1,
|
||||
method: "POST",
|
||||
body: "hi there",
|
||||
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
||||
noAllowPreflight: 1,
|
||||
},
|
||||
{ pass: 0,
|
||||
method: "POST",
|
||||
body: "hi there",
|
||||
headers: { "Content-Type": "foo/bar" },
|
||||
},
|
||||
{ method: "POST",
|
||||
{ pass: 0,
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "foo/bar" },
|
||||
},
|
||||
{ pass: 1,
|
||||
method: "POST",
|
||||
body: "hi there",
|
||||
headers: { "Content-Type": "text/plain",
|
||||
"Accept": "foo/bar",
|
||||
"Accept-Language": "sv-SE" },
|
||||
noAllowPreflight: 1,
|
||||
},
|
||||
{ method: "POST",
|
||||
|
||||
// POST with custom headers
|
||||
{ pass: 1,
|
||||
method: "POST",
|
||||
body: "hi there",
|
||||
headers: { "Accept": "foo/bar",
|
||||
"Accept-Language": "sv-SE",
|
||||
"x-my-header": "myValue" },
|
||||
allowHeaders: "x-my-header",
|
||||
},
|
||||
{ method: "POST",
|
||||
{ pass: 1,
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "text/plain",
|
||||
"x-my-header": "myValue" },
|
||||
allowHeaders: "x-my-header",
|
||||
},
|
||||
{ method: "POST",
|
||||
{ pass: 1,
|
||||
method: "POST",
|
||||
body: "hi there",
|
||||
headers: { "Content-Type": "text/plain",
|
||||
"x-my-header": "myValue" },
|
||||
allowHeaders: "x-my-header",
|
||||
},
|
||||
{ pass: 1,
|
||||
method: "POST",
|
||||
body: "hi there",
|
||||
headers: { "Content-Type": "foo/bar",
|
||||
"x-my-header": "myValue" },
|
||||
allowHeaders: "x-my-header, content-type",
|
||||
},
|
||||
{ pass: 0,
|
||||
method: "POST",
|
||||
body: "hi there",
|
||||
headers: { "Content-Type": "foo/bar" },
|
||||
noAllowPreflight: 1,
|
||||
},
|
||||
{ pass: 0,
|
||||
method: "POST",
|
||||
body: "hi there",
|
||||
headers: { "Content-Type": "foo/bar",
|
||||
"x-my-header": "myValue" },
|
||||
allowHeaders: "x-my-header",
|
||||
},
|
||||
{ method: "POST",
|
||||
{ pass: 1,
|
||||
method: "POST",
|
||||
headers: { "x-my-header": "myValue" },
|
||||
allowHeaders: "x-my-header",
|
||||
},
|
||||
{ method: "POST",
|
||||
{ pass: 1,
|
||||
method: "POST",
|
||||
body: "hi there",
|
||||
headers: { "x-my-header": "myValue" },
|
||||
allowHeaders: "x-my-header, $_%",
|
||||
},
|
||||
{ method: "DELETE",
|
||||
|
||||
// Other methods
|
||||
{ pass: 1,
|
||||
method: "DELETE",
|
||||
allowMethods: "DELETE",
|
||||
},
|
||||
{ method: "DELETE",
|
||||
allowMethods: "POST, PUT, DELETE",
|
||||
},
|
||||
{ method: "DELETE",
|
||||
allowMethods: "POST, DELETE, PUT",
|
||||
},
|
||||
{ method: "DELETE",
|
||||
allowMethods: "DELETE, POST, PUT",
|
||||
},
|
||||
{ method: "DELETE",
|
||||
allowMethods: "POST ,PUT ,DELETE",
|
||||
},
|
||||
{ method: "DELETE",
|
||||
allowMethods: "POST,PUT,DELETE",
|
||||
},
|
||||
{ method: "DELETE",
|
||||
allowMethods: "POST , PUT , DELETE",
|
||||
},
|
||||
{ method: "DELETE",
|
||||
allowMethods: " ,, PUT ,, , , DELETE , ,",
|
||||
},
|
||||
{ method: "POST",
|
||||
body: "hi there",
|
||||
headers: { "Content-Type": "text/plain" },
|
||||
uploadProgress: "uploadprogress",
|
||||
},
|
||||
{ method: "POST",
|
||||
body: "hi there",
|
||||
headers: { "Content-Type": "text/plain" },
|
||||
uploadProgress: "progress",
|
||||
},
|
||||
];
|
||||
failTests = [{ method: "GET",
|
||||
headers: { "x-my-header": "myValue" },
|
||||
},
|
||||
{ method: "GET",
|
||||
headers: { "x-my-header": "myValue" },
|
||||
allowHeaders: "",
|
||||
},
|
||||
{ method: "GET",
|
||||
headers: { "x-my-header": "myValue" },
|
||||
allowHeaders: "y-my-header",
|
||||
},
|
||||
{ method: "GET",
|
||||
headers: { "x-my-header": "myValue" },
|
||||
allowHeaders: "x-my-header y-my-header",
|
||||
},
|
||||
{ method: "GET",
|
||||
headers: { "x-my-header": "myValue" },
|
||||
allowHeaders: "x-my-header, y-my-header z",
|
||||
},
|
||||
{ method: "GET",
|
||||
headers: { "x-my-header": "myValue" },
|
||||
allowHeaders: "x-my-header, y-my-he(ader",
|
||||
},
|
||||
{ method: "GET",
|
||||
headers: { "x-my-header": "myValue",
|
||||
"y-my-header": "secondValue" },
|
||||
allowHeaders: "x-my-header",
|
||||
},
|
||||
{ method: "GET",
|
||||
headers: { "x-my-header": "" },
|
||||
},
|
||||
{ method: "GET",
|
||||
headers: { "x-my-header": "",
|
||||
"y-my-header": "" },
|
||||
allowHeaders: "x-my-header",
|
||||
},
|
||||
{ method: "GET",
|
||||
headers: { "myheader": "" },
|
||||
allowMethods: "myheader",
|
||||
},
|
||||
{ method: "HEAD",
|
||||
headers: { "x-my-header": "myValue" },
|
||||
},
|
||||
{ method: "HEAD",
|
||||
headers: { "x-my-header": "myValue" },
|
||||
allowHeaders: "",
|
||||
},
|
||||
{ method: "HEAD",
|
||||
headers: { "x-my-header": "myValue" },
|
||||
allowHeaders: "y-my-header",
|
||||
},
|
||||
{ method: "HEAD",
|
||||
headers: { "x-my-header": "myValue" },
|
||||
allowHeaders: "x-my-header y-my-header",
|
||||
},
|
||||
{ method: "DELETE",
|
||||
{ pass: 0,
|
||||
method: "DELETE",
|
||||
allowHeaders: "DELETE",
|
||||
},
|
||||
{ method: "POST",
|
||||
noAllowPreflight: 1,
|
||||
{ pass: 0,
|
||||
method: "DELETE",
|
||||
},
|
||||
{ method: "POST",
|
||||
body: "hi there",
|
||||
headers: { "Content-Type": "foo/bar" },
|
||||
noAllowPreflight: 1,
|
||||
},
|
||||
{ method: "DELETE",
|
||||
},
|
||||
{ method: "DELETE",
|
||||
{ pass: 0,
|
||||
method: "DELETE",
|
||||
allowMethods: "",
|
||||
},
|
||||
{ method: "DELETE",
|
||||
{ pass: 1,
|
||||
method: "DELETE",
|
||||
allowMethods: "POST, PUT, DELETE",
|
||||
},
|
||||
{ pass: 1,
|
||||
method: "DELETE",
|
||||
allowMethods: "POST, DELETE, PUT",
|
||||
},
|
||||
{ pass: 1,
|
||||
method: "DELETE",
|
||||
allowMethods: "DELETE, POST, PUT",
|
||||
},
|
||||
{ pass: 1,
|
||||
method: "DELETE",
|
||||
allowMethods: "POST ,PUT ,DELETE",
|
||||
},
|
||||
{ pass: 1,
|
||||
method: "DELETE",
|
||||
allowMethods: "POST,PUT,DELETE",
|
||||
},
|
||||
{ pass: 1,
|
||||
method: "DELETE",
|
||||
allowMethods: "POST , PUT , DELETE",
|
||||
},
|
||||
{ pass: 1,
|
||||
method: "DELETE",
|
||||
allowMethods: " ,, PUT ,, , , DELETE , ,",
|
||||
},
|
||||
{ pass: 0,
|
||||
method: "DELETE",
|
||||
allowMethods: "PUT",
|
||||
},
|
||||
{ method: "DELETE",
|
||||
{ pass: 0,
|
||||
method: "DELETE",
|
||||
allowMethods: "DELETEZ",
|
||||
},
|
||||
{ method: "DELETE",
|
||||
{ pass: 0,
|
||||
method: "DELETE",
|
||||
allowMethods: "DELETE PUT",
|
||||
},
|
||||
{ method: "DELETE",
|
||||
{ pass: 0,
|
||||
method: "DELETE",
|
||||
allowMethods: "DELETE, PUT Z",
|
||||
},
|
||||
{ method: "DELETE",
|
||||
{ pass: 0,
|
||||
method: "DELETE",
|
||||
allowMethods: "DELETE, PU(T",
|
||||
},
|
||||
{ method: "DELETE",
|
||||
{ pass: 0,
|
||||
method: "DELETE",
|
||||
allowMethods: "PUT DELETE",
|
||||
},
|
||||
{ method: "DELETE",
|
||||
{ pass: 0,
|
||||
method: "DELETE",
|
||||
allowMethods: "PUT Z, DELETE",
|
||||
},
|
||||
{ method: "DELETE",
|
||||
{ pass: 0,
|
||||
method: "DELETE",
|
||||
allowMethods: "PU(T, DELETE",
|
||||
},
|
||||
{ method: "MYMETHOD",
|
||||
{ pass: 0,
|
||||
method: "MYMETHOD",
|
||||
allowMethods: "myMethod",
|
||||
},
|
||||
{ method: "PUT",
|
||||
{ pass: 0,
|
||||
method: "PUT",
|
||||
allowMethods: "put",
|
||||
},
|
||||
{ method: "POST",
|
||||
|
||||
// Progress events
|
||||
{ pass: 1,
|
||||
method: "POST",
|
||||
body: "hi there",
|
||||
headers: { "Content-Type": "text/plain" },
|
||||
noAllowPreflight: 1,
|
||||
uploadProgress: "uploadprogress",
|
||||
},
|
||||
{ method: "POST",
|
||||
{ pass: 1,
|
||||
method: "POST",
|
||||
body: "hi there",
|
||||
headers: { "Content-Type": "text/plain" },
|
||||
noAllowPreflight: 1,
|
||||
uploadProgress: "progress",
|
||||
},
|
||||
{ pass: 0,
|
||||
method: "POST",
|
||||
body: "hi there",
|
||||
headers: { "Content-Type": "text/plain" },
|
||||
uploadProgress: "uploadprogress",
|
||||
noAllowPreflight: 1,
|
||||
},
|
||||
{ pass: 0,
|
||||
method: "POST",
|
||||
body: "hi there",
|
||||
headers: { "Content-Type": "text/plain" },
|
||||
uploadProgress: "progress",
|
||||
noAllowPreflight: 1,
|
||||
},
|
||||
|
||||
// Status messages
|
||||
{ pass: 1,
|
||||
method: "GET",
|
||||
noAllowPreflight: 1,
|
||||
status: 404,
|
||||
statusMessage: "nothin' here",
|
||||
},
|
||||
{ pass: 1,
|
||||
method: "GET",
|
||||
noAllowPreflight: 1,
|
||||
status: 401,
|
||||
statusMessage: "no can do",
|
||||
},
|
||||
{ pass: 1,
|
||||
method: "POST",
|
||||
body: "hi there",
|
||||
headers: { "Content-Type": "foo/bar" },
|
||||
allowHeaders: "content-type",
|
||||
status: 500,
|
||||
statusMessage: "server boo",
|
||||
},
|
||||
{ pass: 1,
|
||||
method: "GET",
|
||||
noAllowPreflight: 1,
|
||||
status: 200,
|
||||
statusMessage: "Yes!!",
|
||||
},
|
||||
{ pass: 0,
|
||||
method: "GET",
|
||||
headers: { "x-my-header": "header value" },
|
||||
allowHeaders: "x-my-header",
|
||||
preflightStatus: 400
|
||||
},
|
||||
{ pass: 1,
|
||||
method: "GET",
|
||||
headers: { "x-my-header": "header value" },
|
||||
allowHeaders: "x-my-header",
|
||||
preflightStatus: 200
|
||||
},
|
||||
|
||||
// exposed headers
|
||||
{ pass: 1,
|
||||
method: "GET",
|
||||
responseHeaders: { "x-my-header": "x header" },
|
||||
exposeHeaders: "x-my-header",
|
||||
expectedResponseHeaders: ["x-my-header"],
|
||||
},
|
||||
{ pass: 0,
|
||||
method: "GET",
|
||||
origin: "http://invalid",
|
||||
responseHeaders: { "x-my-header": "x header" },
|
||||
exposeHeaders: "x-my-header",
|
||||
expectedResponseHeaders: [],
|
||||
},
|
||||
{ pass: 1,
|
||||
method: "GET",
|
||||
responseHeaders: { "x-my-header": "x header" },
|
||||
expectedResponseHeaders: [],
|
||||
},
|
||||
{ pass: 1,
|
||||
method: "GET",
|
||||
responseHeaders: { "x-my-header": "x header" },
|
||||
exposeHeaders: "x-my-header y",
|
||||
expectedResponseHeaders: [],
|
||||
},
|
||||
{ pass: 1,
|
||||
method: "GET",
|
||||
responseHeaders: { "x-my-header": "x header" },
|
||||
exposeHeaders: "y x-my-header",
|
||||
expectedResponseHeaders: [],
|
||||
},
|
||||
{ pass: 1,
|
||||
method: "GET",
|
||||
responseHeaders: { "x-my-header": "x header" },
|
||||
exposeHeaders: "x-my-header, y-my-header z",
|
||||
expectedResponseHeaders: [],
|
||||
},
|
||||
{ pass: 1,
|
||||
method: "GET",
|
||||
responseHeaders: { "x-my-header": "x header" },
|
||||
exposeHeaders: "x-my-header, y-my-hea(er",
|
||||
expectedResponseHeaders: [],
|
||||
},
|
||||
{ pass: 1,
|
||||
method: "GET",
|
||||
responseHeaders: { "x-my-header": "x header",
|
||||
"y-my-header": "y header" },
|
||||
exposeHeaders: " , ,,y-my-header,z-my-header, ",
|
||||
expectedResponseHeaders: ["y-my-header"],
|
||||
},
|
||||
];
|
||||
|
||||
if (!runPreflightTests) {
|
||||
passTests = failTests = [];
|
||||
tests = [];
|
||||
}
|
||||
|
||||
for each(test in passTests) {
|
||||
req = {
|
||||
url: baseURL + "&allowOrigin=" + escape(origin) +
|
||||
"&origin=" + escape(origin) +
|
||||
"&requestMethod=" + test.method,
|
||||
for each(test in tests) {
|
||||
var req = {
|
||||
url: baseURL + "allowOrigin=" + escape(test.origin || origin),
|
||||
method: test.method,
|
||||
headers: test.headers,
|
||||
uploadProgress: test.uploadProgress,
|
||||
body: test.body,
|
||||
responseHeaders: test.responseHeaders,
|
||||
};
|
||||
|
||||
if (test.pass) {
|
||||
req.url += "&origin=" + escape(origin) +
|
||||
"&requestMethod=" + test.method;
|
||||
}
|
||||
|
||||
if (test.noAllowPreflight)
|
||||
req.url += "&noAllowPreflight";
|
||||
|
||||
if ("headers" in test) {
|
||||
if (test.pass && "headers" in test) {
|
||||
function isUnsafeHeader(name) {
|
||||
lName = name.toLowerCase();
|
||||
return lName != "accept" &&
|
||||
lName != "accept-language" &&
|
||||
(lName != "content-type" ||
|
||||
["text/plain",
|
||||
"multipart/form-data",
|
||||
"application/x-www-form-urlencoded"]
|
||||
.indexOf(test.headers[name].toLowerCase()) == -1);
|
||||
}
|
||||
req.url += "&headers=" + escape(test.headers.toSource());
|
||||
reqHeaders =
|
||||
escape([name for (name in test.headers)].map(String.toLowerCase).filter(function(name)
|
||||
name != "content-type" &&
|
||||
name != "accept" &&
|
||||
name != "accept-language").sort().join(","));
|
||||
escape([name for (name in test.headers)]
|
||||
.filter(isUnsafeHeader)
|
||||
.map(String.toLowerCase)
|
||||
.sort()
|
||||
.join(","));
|
||||
req.url += reqHeaders ? "&requestHeaders=" + reqHeaders : "";
|
||||
}
|
||||
if ("allowHeaders" in test)
|
||||
|
@ -344,15 +586,31 @@ function runTest() {
|
|||
req.url += "&allowMethods=" + escape(test.allowMethods);
|
||||
if (test.body)
|
||||
req.url += "&body=" + escape(test.body);
|
||||
|
||||
if (test.status) {
|
||||
req.url += "&status=" + test.status;
|
||||
req.url += "&statusMessage=" + escape(test.statusMessage);
|
||||
}
|
||||
if (test.preflightStatus)
|
||||
req.url += "&preflightStatus=" + test.preflightStatus;
|
||||
if (test.responseHeaders)
|
||||
req.url += "&responseHeaders=" + escape(test.responseHeaders.toSource());
|
||||
if (test.exposeHeaders)
|
||||
req.url += "&exposeHeaders=" + escape(test.exposeHeaders);
|
||||
|
||||
loaderWindow.postMessage(req.toSource(), origin);
|
||||
|
||||
res = eval(yield);
|
||||
|
||||
if (test.pass) {
|
||||
is(res.didFail, false,
|
||||
"shouldn't have failed in test for " + test.toSource());
|
||||
if (test.status) {
|
||||
is(res.status, test.status, "wrong status in test for " + test.toSource());
|
||||
is(res.statusText, test.statusMessage, "wrong status text for " + test.toSource());
|
||||
}
|
||||
else {
|
||||
is(res.status, 200, "wrong status in test for " + test.toSource());
|
||||
is(res.statusText, "OK", "wrong status text for " + test.toSource());
|
||||
}
|
||||
if (test.method !== "HEAD") {
|
||||
is(res.responseXML, "<res>hello pass</res>",
|
||||
"wrong responseXML in test for " + test.toSource());
|
||||
|
@ -371,28 +629,22 @@ function runTest() {
|
|||
"opening,rs1,sending,rs1,loadstart,rs2,rs4,load",
|
||||
"wrong responseText in test for " + test.toSource());
|
||||
}
|
||||
if (test.responseHeaders) {
|
||||
for (header in test.responseHeaders) {
|
||||
if (test.expectedResponseHeaders.indexOf(header) == -1) {
|
||||
is(res.responseHeaders[header], null,
|
||||
"wrong response header (" + header + ") in test for " +
|
||||
test.toSource());
|
||||
}
|
||||
|
||||
for each(test in failTests) {
|
||||
req = {
|
||||
url: baseURL + "allowOrigin=" + escape(origin),
|
||||
method: test.method,
|
||||
headers: test.headers,
|
||||
uploadProgress: test.uploadProgress,
|
||||
body: test.body,
|
||||
};
|
||||
|
||||
if (test.noAllowPreflight)
|
||||
req.url += "&noAllowPreflight";
|
||||
|
||||
if ("allowHeaders" in test)
|
||||
req.url += "&allowHeaders=" + escape(test.allowHeaders);
|
||||
if ("allowMethods" in test)
|
||||
req.url += "&allowMethods=" + escape(test.allowMethods);
|
||||
|
||||
loaderWindow.postMessage(req.toSource(), origin);
|
||||
|
||||
res = eval(yield);
|
||||
else {
|
||||
is(res.responseHeaders[header], test.responseHeaders[header],
|
||||
"wrong response header (" + header + ") in test for " +
|
||||
test.toSource());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
is(res.didFail, true,
|
||||
"should have failed in test for " + test.toSource());
|
||||
is(res.status, 0, "wrong status in test for " + test.toSource());
|
||||
|
@ -406,8 +658,15 @@ function runTest() {
|
|||
"wrong events in test for " + test.toSource());
|
||||
is(res.progressEvents, 0,
|
||||
"wrong events in test for " + test.toSource());
|
||||
if (test.responseHeaders) {
|
||||
for (header in test.responseHeaders) {
|
||||
is(res.responseHeaders[header], null,
|
||||
"wrong response header (" + header + ") in test for " +
|
||||
test.toSource());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Test cookie behavior
|
||||
tests = [{ pass: 1,
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=592829
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 592829</title>
|
||||
<script type="application/javascript" src="/MochiKit/packed.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=592829">Mozilla Bug 592829</a>
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
/** Test for Bug 592829 **/
|
||||
|
||||
// NOTE! It's imperative that we don't call .init() here. Otherwise we're not
|
||||
// testing what happens if parsing fails.
|
||||
// If we ever change how DOMParser initilization works, just update this code
|
||||
// to create a DOMParser which is not allowed to parse XUL.
|
||||
|
||||
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||||
|
||||
var isXUL = true;
|
||||
try {
|
||||
var x =
|
||||
Components.classes["@mozilla.org/xmlextras/domparser;1"]
|
||||
.getService(Components.interfaces.nsIDOMParser)
|
||||
.parseFromString('<overlay xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"/>', "text/xml");
|
||||
isXUL = x.documentElement.namespaceURI ==
|
||||
"http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
|
||||
}
|
||||
catch (ex) {
|
||||
isXUL = false;
|
||||
}
|
||||
|
||||
is(isXUL, false, "We didn't create XUL and we didn't crash!");
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
|
@ -46,8 +46,6 @@ class nsIURI;
|
|||
|
||||
#define NS_FORM_METHOD_GET 0
|
||||
#define NS_FORM_METHOD_POST 1
|
||||
#define NS_FORM_METHOD_PUT 2
|
||||
#define NS_FORM_METHOD_DELETE 3
|
||||
#define NS_FORM_ENCTYPE_URLENCODED 0
|
||||
#define NS_FORM_ENCTYPE_MULTIPART 1
|
||||
#define NS_FORM_ENCTYPE_TEXTPLAIN 2
|
||||
|
|
|
@ -41,8 +41,6 @@
|
|||
static const nsAttrValue::EnumTable kFormMethodTable[] = {
|
||||
{ "get", NS_FORM_METHOD_GET },
|
||||
{ "post", NS_FORM_METHOD_POST },
|
||||
{ "put", NS_FORM_METHOD_PUT },
|
||||
{ "delete", NS_FORM_METHOD_DELETE },
|
||||
{ 0 }
|
||||
};
|
||||
// Default method is 'get'.
|
||||
|
|
|
@ -508,19 +508,6 @@ public:
|
|||
*/
|
||||
NS_HIDDEN_(nsresult) GetURIAttr(nsIAtom* aAttr, nsIAtom* aBaseAttr, nsAString& aResult);
|
||||
|
||||
/**
|
||||
* Helper method for NS_IMPL_ENUM_ATTR_DEFAULT_VALUE.
|
||||
* Gets the enum value string of an attribute and using a default value if
|
||||
* the attribute is missing or the string is an invalid enum value.
|
||||
*
|
||||
* @param aType the name of the attribute.
|
||||
* @param aDefault the default value if the attribute is missing or invalid.
|
||||
* @param aResult string corresponding to the value [out].
|
||||
*/
|
||||
NS_HIDDEN_(nsresult) GetEnumAttr(nsIAtom* aAttr,
|
||||
const char* aDefault,
|
||||
nsAString& aResult);
|
||||
|
||||
/**
|
||||
* Returns the current disabled state of the element.
|
||||
*/
|
||||
|
@ -714,6 +701,19 @@ protected:
|
|||
*/
|
||||
NS_HIDDEN_(nsresult) GetURIListAttr(nsIAtom* aAttr, nsAString& aResult);
|
||||
|
||||
/**
|
||||
* Helper method for NS_IMPL_ENUM_ATTR_DEFAULT_VALUE.
|
||||
* Gets the enum value string of an attribute and using a default value if
|
||||
* the attribute is missing or the string is an invalid enum value.
|
||||
*
|
||||
* @param aType the name of the attribute.
|
||||
* @param aDefault the default value if the attribute is missing or invalid.
|
||||
* @param aResult string corresponding to the value [out].
|
||||
*/
|
||||
NS_HIDDEN_(nsresult) GetEnumAttr(nsIAtom* aAttr,
|
||||
const char* aDefault,
|
||||
nsAString& aResult);
|
||||
|
||||
/**
|
||||
* Locates the nsIEditor associated with this node. In general this is
|
||||
* equivalent to GetEditorInternal(), but for designmode or contenteditable,
|
||||
|
|
|
@ -898,25 +898,11 @@ nsHTMLFormElement::SubmitSubmission(nsFormSubmission* aFormSubmission)
|
|||
getter_AddRefs(postDataStream));
|
||||
NS_ENSURE_SUBMIT_SUCCESS(rv);
|
||||
|
||||
nsAutoString method;
|
||||
if (originatingElement &&
|
||||
originatingElement->HasAttr(kNameSpaceID_None,
|
||||
nsGkAtoms::formmethod)) {
|
||||
if (!originatingElement->IsHTML()) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
static_cast<nsGenericHTMLElement*>(originatingElement)->
|
||||
GetEnumAttr(nsGkAtoms::formmethod, kFormDefaultMethod->tag, method);
|
||||
} else {
|
||||
GetEnumAttr(nsGkAtoms::method, kFormDefaultMethod->tag, method);
|
||||
}
|
||||
|
||||
rv = linkHandler->OnLinkClickSync(this, actionURI,
|
||||
target.get(),
|
||||
postDataStream, nsnull,
|
||||
getter_AddRefs(docShell),
|
||||
getter_AddRefs(mSubmittingRequest),
|
||||
NS_LossyConvertUTF16toASCII(method).get());
|
||||
getter_AddRefs(mSubmittingRequest));
|
||||
NS_ENSURE_SUBMIT_SUCCESS(rv);
|
||||
}
|
||||
|
||||
|
|
|
@ -973,7 +973,6 @@ nsresult nsHTMLMediaElement::LoadResource(nsIURI* aURI)
|
|||
listener = crossSiteListener;
|
||||
NS_ENSURE_TRUE(crossSiteListener, NS_ERROR_OUT_OF_MEMORY);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
crossSiteListener->AllowHTTPResult(HTTP_REQUESTED_RANGE_NOT_SATISFIABLE_CODE);
|
||||
} else {
|
||||
rv = nsContentUtils::GetSecurityManager()->
|
||||
CheckLoadURIWithPrincipal(NodePrincipal(),
|
||||
|
|
|
@ -78,7 +78,16 @@ nsIConstraintValidation::GetValidationMessage(nsAString& aValidationMessage)
|
|||
aValidationMessage.Truncate();
|
||||
|
||||
if (IsCandidateForConstraintValidation() && !IsValid()) {
|
||||
if (GetValidityState(VALIDITY_STATE_CUSTOM_ERROR)) {
|
||||
nsCOMPtr<nsIContent> content = do_QueryInterface(this);
|
||||
NS_ASSERTION(content, "This class should be inherited by HTML elements only!");
|
||||
|
||||
nsAutoString authorMessage;
|
||||
content->GetAttr(kNameSpaceID_None, nsGkAtoms::x_moz_errormessage,
|
||||
authorMessage);
|
||||
|
||||
if (!authorMessage.IsEmpty()) {
|
||||
aValidationMessage.Assign(authorMessage);
|
||||
} else if (GetValidityState(VALIDITY_STATE_CUSTOM_ERROR)) {
|
||||
aValidationMessage.Assign(mCustomValidity);
|
||||
} else if (GetValidityState(VALIDITY_STATE_TOO_LONG)) {
|
||||
GetValidationMessage(aValidationMessage, VALIDITY_STATE_TOO_LONG);
|
||||
|
|
|
@ -1,8 +0,0 @@
|
|||
function handleRequest(request, response)
|
||||
{
|
||||
// Redirect to another domain.
|
||||
// Using 307 to keep the method.
|
||||
response.setStatusLine(null, 307, "Temp");
|
||||
response.setHeader("Location",
|
||||
"http://example.org:80/tests/content/html/content/test/583288_submit_server.sjs");
|
||||
}
|
|
@ -1,5 +0,0 @@
|
|||
function handleRequest(request, response)
|
||||
{
|
||||
// Send the HTTP method.
|
||||
response.write(request.method);
|
||||
}
|
|
@ -212,11 +212,6 @@ _TEST_FILES = \
|
|||
test_bug590353-1.html \
|
||||
test_bug590353-2.html \
|
||||
test_bug593689.html \
|
||||
test_bug583288-1.html \
|
||||
test_bug583288-2.html \
|
||||
test_bug583288-3.html \
|
||||
583288_submit_server.sjs \
|
||||
583288_redirect_server.sjs \
|
||||
test_bug555840.html \
|
||||
test_bug561636.html \
|
||||
test_bug556013.html \
|
||||
|
@ -235,6 +230,7 @@ _TEST_FILES = \
|
|||
test_bug557087-4.html \
|
||||
test_bug557087-5.html \
|
||||
test_bug557087-6.html \
|
||||
test_bug600155.html \
|
||||
$(NULL)
|
||||
|
||||
libs:: $(_TEST_FILES)
|
||||
|
|
|
@ -1,143 +0,0 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=583288
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 583288</title>
|
||||
<script type="application/javascript" src="/MochiKit/packed.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body onload='runTests();'>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=583288">Mozilla Bug 583288</a>
|
||||
<p id="display"></p>
|
||||
<style>
|
||||
iframe { width: 70px; height: 40px;}
|
||||
</style>
|
||||
<!--<div id="content" style="display: none">-->
|
||||
<div id="content">
|
||||
<iframe name='get' id='get'></iframe>
|
||||
<iframe name='post' id='post'></iframe>
|
||||
<iframe name='put' id='put'></iframe>
|
||||
<iframe name='del' id='del'></iframe>
|
||||
<iframe name='get2' id='get2'></iframe>
|
||||
<iframe name='post2' id='post2'></iframe>
|
||||
<iframe name='put2' id='put2'></iframe>
|
||||
<iframe name='del2' id='del2'></iframe>
|
||||
|
||||
<form action="583288_submit_server.sjs" target='get' method='get'>
|
||||
</form>
|
||||
<form action="583288_submit_server.sjs" target='post' method='post'>
|
||||
</form>
|
||||
<form action="583288_submit_server.sjs" target='put' method='put'>
|
||||
</form>
|
||||
<form action="583288_submit_server.sjs" target='del' method='delete'>
|
||||
</form>
|
||||
|
||||
<form action="583288_submit_server.sjs">
|
||||
<input type='submit' id='iget' value='get' formtarget='get2' formmethod='get'>
|
||||
</form>
|
||||
<form action="583288_submit_server.sjs">
|
||||
<input type='submit' id='ipost' value='post' formtarget='post2' formmethod='post'>
|
||||
</form>
|
||||
<form action="583288_submit_server.sjs">
|
||||
<input type='submit' id='iput' value='put' formtarget='put2' formmethod='put'>
|
||||
</form>
|
||||
<form action="583288_submit_server.sjs">
|
||||
<input type='submit' id='idel' value='delete' formtarget='del2' formmethod='delete'>
|
||||
</form>
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
|
||||
/** Test for Bug 583288 **/
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
var gTestResults = {
|
||||
get: "GET",
|
||||
get2: "GET",
|
||||
post: "POST",
|
||||
post2: "POST",
|
||||
put: "PUT",
|
||||
put2: "PUT",
|
||||
del: "DELETE",
|
||||
del2: "DELETE",
|
||||
};
|
||||
|
||||
var gPendingLoad = 0; // Has to be set after depending on the frames number.
|
||||
|
||||
function runTests()
|
||||
{
|
||||
// We add a load event for the frames which will be called when the forms
|
||||
// will be submitted.
|
||||
var frames = [ document.getElementById('get'),
|
||||
document.getElementById('get2'),
|
||||
document.getElementById('post'),
|
||||
document.getElementById('post2'),
|
||||
document.getElementById('put'),
|
||||
document.getElementById('put2'),
|
||||
document.getElementById('del'),
|
||||
document.getElementById('del2'),
|
||||
];
|
||||
gPendingLoad = frames.length;
|
||||
|
||||
for (var i=0; i<frames.length; ++i) {
|
||||
frames[i].setAttribute('onload', "frameLoaded(this);");
|
||||
}
|
||||
|
||||
// The four first forms can be submitted with .submit().
|
||||
for (var i=0; i<4; ++i) {
|
||||
document.forms[i].submit();
|
||||
}
|
||||
|
||||
/**
|
||||
* We are going to focus each element before interacting with them so we are
|
||||
* sure they will be visible in the iframe.
|
||||
* Considering we are using synthesizeKey that may be not required.
|
||||
*
|
||||
* Focusing the first element (id='iget') is launching the tests.
|
||||
*/
|
||||
document.getElementById('iget').addEventListener('focus', function(aEvent) {
|
||||
aEvent.target.removeEventListener('focus', arguments.callee, false);
|
||||
synthesizeKey("VK_RETURN", {});
|
||||
document.getElementById('ipost').focus();
|
||||
}, false);
|
||||
|
||||
document.getElementById('ipost').addEventListener('focus', function(aEvent) {
|
||||
aEvent.target.removeEventListener('focus', arguments.callee, false);
|
||||
synthesizeKey("VK_RETURN", {});
|
||||
document.getElementById('iput').focus();
|
||||
}, false);
|
||||
|
||||
document.getElementById('iput').addEventListener('focus', function(aEvent) {
|
||||
aEvent.target.removeEventListener('focus', arguments.callee, false);
|
||||
synthesizeKey("VK_RETURN", {});
|
||||
document.getElementById('idel').focus();
|
||||
}, false);
|
||||
|
||||
document.getElementById('idel').addEventListener('focus', function(aEvent) {
|
||||
aEvent.target.removeEventListener('focus', arguments.callee, false);
|
||||
synthesizeKey("VK_RETURN", {});
|
||||
}, false);
|
||||
|
||||
document.getElementById('iget').focus();
|
||||
}
|
||||
|
||||
function frameLoaded(aFrame) {
|
||||
// Check if formaction/action has the correct behavior.
|
||||
is(aFrame.contentDocument.documentElement.textContent, gTestResults[aFrame.name],
|
||||
"the method used during the form submission should be " +
|
||||
gTestResults[aFrame.name]);
|
||||
|
||||
if (--gPendingLoad == 0) {
|
||||
SimpleTest.finish();
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
|
@ -1,99 +0,0 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=583288
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 583288</title>
|
||||
<script type="application/javascript" src="/MochiKit/packed.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body onload='runTests();'>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=583288">Mozilla Bug 583288</a>
|
||||
<p id="display"></p>
|
||||
<style>
|
||||
iframe { width: 70px; height: 40px;}
|
||||
</style>
|
||||
<!--<div id="content" style="display: none">-->
|
||||
<div id="content">
|
||||
<iframe name='get' id='get'></iframe>
|
||||
<iframe name='post' id='post'></iframe>
|
||||
<iframe name='put' id='put'></iframe>
|
||||
<iframe name='del' id='del'></iframe>
|
||||
|
||||
<form action="http://example.org:80/tests/content/html/content/test/583288_submit_server.sjs" target='get' method='get'>
|
||||
</form>
|
||||
<form action="http://example.org:80/tests/content/html/content/test/583288_submit_server.sjs" target='post' method='post'>
|
||||
</form>
|
||||
<form action="http://example.org:80/tests/content/html/content/test/583288_submit_server.sjs" target='put' method='put'>
|
||||
</form>
|
||||
<form action="http://example.org:80/tests/content/html/content/test/583288_submit_server.sjs" target='del' method='delete'>
|
||||
</form>
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
|
||||
/** Test for Bug 583288 **/
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
var gLoaded = 0;
|
||||
|
||||
function runTests()
|
||||
{
|
||||
// We add a load event for the frames which will be called when the forms
|
||||
// will be submitted.
|
||||
var frames = [ document.getElementById('get'),
|
||||
document.getElementById('post'),
|
||||
document.getElementById('put'),
|
||||
document.getElementById('del'),
|
||||
];
|
||||
|
||||
for (var i=0; i<2; ++i) {
|
||||
frames[i].setAttribute('onload', "frameShouldLoad();");
|
||||
}
|
||||
for (var i=2; i<4; ++i) {
|
||||
frames[i].setAttribute('onload', "frameShouldNotLoad();");
|
||||
}
|
||||
|
||||
// The four forms can be submitted with .submit().
|
||||
// Submitting those which should be blocked so we can considering if the the
|
||||
// last ones are submitted, that means the firsts were blocked.
|
||||
for (var i=3; i>=0; --i) {
|
||||
document.forms[i].submit();
|
||||
}
|
||||
|
||||
// After the two first succefull submissions, we are going to stop the test.
|
||||
// The expected successfull submissions have been requested at the end so we
|
||||
// expect them at the end. So if the two firsts ones didn't show up, we are
|
||||
// assuming they have been blocked.
|
||||
// Unfortunately, it doesn't sound like there is a better way to test that.
|
||||
// The worst thing that can happen here is to have a random green (if the
|
||||
// first two submissions were not blocked but came after the last two).
|
||||
}
|
||||
|
||||
function frameShouldLoad() {
|
||||
ok(true, "The form submission should succeed.");
|
||||
if (++gLoaded == 2) {
|
||||
finished();
|
||||
}
|
||||
}
|
||||
|
||||
function frameShouldNotLoad() {
|
||||
ok(false, "The form submission should have been blocked");
|
||||
if (++gLoaded == 2) {
|
||||
finished();
|
||||
}
|
||||
}
|
||||
|
||||
function finished()
|
||||
{
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
|
@ -1,85 +0,0 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=583288
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 583288</title>
|
||||
<script type="application/javascript" src="/MochiKit/packed.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body onload='runTests();'>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=583288">Mozilla Bug 583288</a>
|
||||
<p id="display"></p>
|
||||
<style>
|
||||
iframe { width: 70px; height: 40px;}
|
||||
</style>
|
||||
<!--<div id="content" style="display: none">-->
|
||||
<div id="content">
|
||||
<iframe name='get' id='get'></iframe>
|
||||
<iframe name='post' id='post'></iframe>
|
||||
<iframe name='put' id='put'></iframe>
|
||||
<iframe name='del' id='del'></iframe>
|
||||
|
||||
<form action="583288_redirect_server.sjs" target='get' method='get'>
|
||||
</form>
|
||||
<form action="583288_redirect_server.sjs" target='post' method='post'>
|
||||
</form>
|
||||
<form action="583288_redirect_server.sjs" target='put' method='put'>
|
||||
</form>
|
||||
<form action="583288_redirect_server.sjs" target='del' method='delete'>
|
||||
</form>
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
|
||||
/** Test for Bug 583288 **/
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
var gTestResults = {
|
||||
get: "GET",
|
||||
post: "POST",
|
||||
put: "",
|
||||
del: "",
|
||||
};
|
||||
|
||||
var gPendingLoad = 0; // Has to be set after depending on the frames number.
|
||||
|
||||
function runTests()
|
||||
{
|
||||
// We add a load event for the frames which will be called when the forms
|
||||
// will be submitted.
|
||||
var frames = [ document.getElementById('get'),
|
||||
document.getElementById('post'),
|
||||
document.getElementById('put'),
|
||||
document.getElementById('del'),
|
||||
];
|
||||
gPendingLoad = frames.length;
|
||||
|
||||
for (var i=0; i<gPendingLoad; ++i) {
|
||||
frames[i].setAttribute('onload', "frameLoaded(this);");
|
||||
}
|
||||
|
||||
// The four forms can be submitted with .submit().
|
||||
for (var i=0; i<4; ++i) {
|
||||
document.forms[i].submit();
|
||||
}
|
||||
}
|
||||
|
||||
function frameLoaded(aFrame) {
|
||||
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
|
||||
is(aFrame.contentDocument.documentElement.textContent, gTestResults[aFrame.name],
|
||||
"cross-origin submission with redirection should work");
|
||||
|
||||
if (--gPendingLoad == 0) {
|
||||
SimpleTest.finish();
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
|
@ -30,9 +30,11 @@ var methodTestData = [
|
|||
// Default value.
|
||||
[ "get" ],
|
||||
// Valid values.
|
||||
[ "get", "post", "put", "delete" ],
|
||||
[ "get", "post" ],
|
||||
// Invalid values.
|
||||
[ "", " ", "foo" ],
|
||||
// TODO values, see bug 583289 and bug 583288.
|
||||
[ "delete", "put" ],
|
||||
];
|
||||
|
||||
function checkAttribute(form, attrName, idlName, data)
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=600155
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 600155</title>
|
||||
<script type="application/javascript" src="/MochiKit/packed.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=600155">Mozilla Bug 600155</a>
|
||||
<p id="display"></p>
|
||||
<div id='content' style='display:none;'>
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
|
||||
/** Test for Bug 600155 **/
|
||||
|
||||
var subjectForConstraintValidation = [ "button", "input", "select", "textarea" ];
|
||||
var content = document.getElementById('content');
|
||||
|
||||
for each (var eName in subjectForConstraintValidation) {
|
||||
var e = document.createElement(eName);
|
||||
content.appendChild(e);
|
||||
e.setAttribute("x-moz-errormessage", "foo");
|
||||
if ("required" in e) {
|
||||
e.required = true;
|
||||
} else {
|
||||
e.setCustomValidity("bar");
|
||||
}
|
||||
|
||||
// At this point, the element is invalid.
|
||||
is(e.validationMessage, "foo",
|
||||
"the validation message should be the author one");
|
||||
|
||||
content.removeChild(e);
|
||||
}
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
|
@ -449,7 +449,6 @@ nsresult nsMediaChannelStream::OpenChannel(nsIStreamListener** aStreamListener)
|
|||
listener = crossSiteListener;
|
||||
NS_ENSURE_TRUE(crossSiteListener, NS_ERROR_OUT_OF_MEMORY);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
crossSiteListener->AllowHTTPResult(HTTP_REQUESTED_RANGE_NOT_SATISFIABLE_CODE);
|
||||
} else {
|
||||
nsresult rv = nsContentUtils::GetSecurityManager()->
|
||||
CheckLoadURIWithPrincipal(element->NodePrincipal(),
|
||||
|
|
|
@ -871,15 +871,14 @@ nsXMLContentSink::GetCurrentContent()
|
|||
if (mContentStack.Length() == 0) {
|
||||
return nsnull;
|
||||
}
|
||||
return GetCurrentStackNode().mContent;
|
||||
return GetCurrentStackNode()->mContent;
|
||||
}
|
||||
|
||||
StackNode &
|
||||
StackNode*
|
||||
nsXMLContentSink::GetCurrentStackNode()
|
||||
{
|
||||
PRInt32 count = mContentStack.Length();
|
||||
NS_ASSERTION(count > 0, "Bogus Length()");
|
||||
return mContentStack[count-1];
|
||||
return count != 0 ? &mContentStack[count-1] : nsnull;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1116,11 +1115,14 @@ nsXMLContentSink::HandleEndElement(const PRUnichar *aName,
|
|||
|
||||
FlushText();
|
||||
|
||||
StackNode & sn = GetCurrentStackNode();
|
||||
StackNode* sn = GetCurrentStackNode();
|
||||
if (!sn) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIContent> content;
|
||||
sn.mContent.swap(content);
|
||||
PRUint32 numFlushed = sn.mNumFlushed;
|
||||
sn->mContent.swap(content);
|
||||
PRUint32 numFlushed = sn->mNumFlushed;
|
||||
|
||||
PopContent();
|
||||
NS_ASSERTION(content, "failed to pop content");
|
||||
|
|
|
@ -148,7 +148,7 @@ protected:
|
|||
nsresult AddContentAsLeaf(nsIContent *aContent);
|
||||
|
||||
nsIContent* GetCurrentContent();
|
||||
StackNode & GetCurrentStackNode();
|
||||
StackNode* GetCurrentStackNode();
|
||||
nsresult PushContent(nsIContent *aContent);
|
||||
void PopContent();
|
||||
PRBool HaveNotifiedForCurrentContent() const;
|
||||
|
|
|
@ -1412,8 +1412,7 @@ nsDocShell::LoadURI(nsIURI * aURI,
|
|||
nsnull, // No SHEntry
|
||||
aFirstParty,
|
||||
nsnull, // No nsIDocShell
|
||||
nsnull, // No nsIRequest
|
||||
nsnull); // Use default HTTP method
|
||||
nsnull); // No nsIRequest
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -4096,7 +4095,7 @@ nsDocShell::LoadErrorPage(nsIURI *aURI, const PRUnichar *aURL,
|
|||
return InternalLoad(errorPageURI, nsnull, nsnull,
|
||||
INTERNAL_LOAD_FLAGS_INHERIT_OWNER, nsnull, nsnull,
|
||||
nsnull, nsnull, LOAD_ERROR_PAGE,
|
||||
nsnull, PR_TRUE, nsnull, nsnull, nsnull);
|
||||
nsnull, PR_TRUE, nsnull, nsnull);
|
||||
}
|
||||
|
||||
|
||||
|
@ -4160,8 +4159,7 @@ nsDocShell::Reload(PRUint32 aReloadFlags)
|
|||
nsnull, // No SHEntry
|
||||
PR_TRUE,
|
||||
nsnull, // No nsIDocShell
|
||||
nsnull, // No nsIRequest
|
||||
nsnull); // Use default HTTP method
|
||||
nsnull); // No nsIRequest
|
||||
}
|
||||
|
||||
|
||||
|
@ -5871,7 +5869,7 @@ nsDocShell::OnLocationChange(nsIWebProgress * aProgress,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
void
|
||||
nsDocShell::OnRedirectStateChange(nsIChannel* aOldChannel,
|
||||
nsIChannel* aNewChannel,
|
||||
PRUint32 aRedirectFlags,
|
||||
|
@ -5880,44 +5878,13 @@ nsDocShell::OnRedirectStateChange(nsIChannel* aOldChannel,
|
|||
NS_ASSERTION(aStateFlags & STATE_REDIRECTING,
|
||||
"Calling OnRedirectStateChange when there is no redirect");
|
||||
if (!(aStateFlags & STATE_IS_DOCUMENT))
|
||||
return NS_OK; // not a toplevel document
|
||||
return; // not a toplevel document
|
||||
|
||||
nsCOMPtr<nsIURI> oldURI, newURI;
|
||||
aOldChannel->GetURI(getter_AddRefs(oldURI));
|
||||
aNewChannel->GetURI(getter_AddRefs(newURI));
|
||||
if (!oldURI || !newURI) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// HTTP channel with unsafe methods should not be redirected to a cross-domain.
|
||||
if (!ChannelIsSafeHTTPMethod(aNewChannel)) {
|
||||
// This code is very similar to the code of nsSameOriginChecker in
|
||||
// nsContentUtils but we can't use nsSameOriginChecker because it
|
||||
// needs to use a channel callback (which we already use).
|
||||
// If nsSameOriginChecker happens to not use a channel callback
|
||||
// anymore, this code would be a good candidate for refactoring.
|
||||
nsCOMPtr<nsIPrincipal> oldPrincipal;
|
||||
nsresult rv;
|
||||
|
||||
nsCOMPtr<nsIScriptSecurityManager> secMan =
|
||||
do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv);
|
||||
|
||||
rv = secMan->GetChannelPrincipal(aOldChannel,
|
||||
getter_AddRefs(oldPrincipal));
|
||||
NS_ENSURE_SUCCESS(rv, NS_OK);
|
||||
|
||||
NS_ASSERTION(oldPrincipal, "oldPrincipal should not be null!");
|
||||
|
||||
nsCOMPtr<nsIURI> newOriginalURI;
|
||||
aNewChannel->GetOriginalURI(getter_AddRefs(newOriginalURI));
|
||||
|
||||
rv = oldPrincipal->CheckMayLoad(newURI, PR_FALSE);
|
||||
if (NS_SUCCEEDED(rv) && newOriginalURI != newURI) {
|
||||
rv = oldPrincipal->CheckMayLoad(newOriginalURI, PR_FALSE);
|
||||
}
|
||||
|
||||
// The requested tried to be redirected, we have to cancel it.
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
return;
|
||||
}
|
||||
|
||||
// Below a URI visit is saved (see AddURIVisit method doc).
|
||||
|
@ -5968,8 +5935,6 @@ nsDocShell::OnRedirectStateChange(nsIChannel* aOldChannel,
|
|||
mLoadType = LOAD_NORMAL_REPLACE;
|
||||
SetHistoryEntry(&mLSHE, nsnull);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -6341,8 +6306,7 @@ nsDocShell::EndPageLoad(nsIWebProgress * aProgress,
|
|||
nsnull, // No SHEntry
|
||||
PR_TRUE, // first party site
|
||||
nsnull, // No nsIDocShell
|
||||
nsnull, // No nsIRequest
|
||||
nsnull); // Use default HTTP method
|
||||
nsnull); // No nsIRequest
|
||||
}
|
||||
else {
|
||||
DisplayLoadError(aStatus, url, nsnull, aChannel);
|
||||
|
@ -7784,7 +7748,7 @@ public:
|
|||
return mDocShell->InternalLoad(mURI, mReferrer, mOwner, mFlags,
|
||||
nsnull, mTypeHint.get(),
|
||||
mPostData, mHeadersData, mLoadType,
|
||||
mSHEntry, mFirstParty, nsnull, nsnull, nsnull);
|
||||
mSHEntry, mFirstParty, nsnull, nsnull);
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -7818,8 +7782,7 @@ nsDocShell::InternalLoad(nsIURI * aURI,
|
|||
nsISHEntry * aSHEntry,
|
||||
PRBool aFirstParty,
|
||||
nsIDocShell** aDocShell,
|
||||
nsIRequest** aRequest,
|
||||
const char* aHttpMethod)
|
||||
nsIRequest** aRequest)
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
|
@ -8021,8 +7984,7 @@ nsDocShell::InternalLoad(nsIURI * aURI,
|
|||
aSHEntry,
|
||||
aFirstParty,
|
||||
aDocShell,
|
||||
aRequest,
|
||||
aHttpMethod);
|
||||
aRequest);
|
||||
if (rv == NS_ERROR_NO_CONTENT) {
|
||||
// XXXbz except we never reach this code!
|
||||
if (isNewWindow) {
|
||||
|
@ -8457,8 +8419,7 @@ nsDocShell::InternalLoad(nsIURI * aURI,
|
|||
aDocShell, getter_AddRefs(req),
|
||||
(aFlags & INTERNAL_LOAD_FLAGS_FIRST_LOAD) != 0,
|
||||
(aFlags & INTERNAL_LOAD_FLAGS_BYPASS_CLASSIFIER) != 0,
|
||||
(aFlags & INTERNAL_LOAD_FLAGS_FORCE_ALLOW_COOKIES) != 0,
|
||||
aHttpMethod);
|
||||
(aFlags & INTERNAL_LOAD_FLAGS_FORCE_ALLOW_COOKIES) != 0);
|
||||
if (req && aRequest)
|
||||
NS_ADDREF(*aRequest = req);
|
||||
|
||||
|
@ -8539,8 +8500,7 @@ nsDocShell::DoURILoad(nsIURI * aURI,
|
|||
nsIRequest ** aRequest,
|
||||
PRBool aIsNewWindowTarget,
|
||||
PRBool aBypassClassifier,
|
||||
PRBool aForceAllowCookies,
|
||||
const char* aHttpMethod)
|
||||
PRBool aForceAllowCookies)
|
||||
{
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIURILoader> uriLoader;
|
||||
|
@ -8723,20 +8683,6 @@ nsDocShell::DoURILoad(nsIURI * aURI,
|
|||
// Referrer is currenly only set for link clicks here.
|
||||
httpChannel->SetReferrer(aReferrerURI);
|
||||
}
|
||||
|
||||
// If a specific HTTP method has been requested, set it.
|
||||
if (aHttpMethod) {
|
||||
// Tell the cache it _has_ to open a cache entry.
|
||||
PRUint32 loadFlags;
|
||||
if (NS_SUCCEEDED(channel->GetLoadFlags(&loadFlags))) {
|
||||
channel->SetLoadFlags(loadFlags | nsICachingChannel::FORCE_OPEN_CACHE_ENTRY);
|
||||
}
|
||||
|
||||
// The method name have to be correct.
|
||||
// Otherwise SetRequestMethod will return a failure.
|
||||
rv = httpChannel->SetRequestMethod(nsDependentCString(aHttpMethod));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
}
|
||||
//
|
||||
// Set the owner of the channel, but only for channels that can't
|
||||
|
@ -8787,14 +8733,6 @@ nsDocShell::DoURILoad(nsIURI * aURI,
|
|||
}
|
||||
}
|
||||
|
||||
// If a specific HTTP channel has been set and it is not a safe method,
|
||||
// we should prevent cross-origin requests.
|
||||
if (aHttpMethod && ownerPrincipal && !ChannelIsSafeHTTPMethod(channel)) {
|
||||
if (NS_FAILED(ownerPrincipal->CheckMayLoad(aURI, PR_FALSE))) {
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIScriptChannel> scriptChannel = do_QueryInterface(channel);
|
||||
if (scriptChannel) {
|
||||
// Allow execution against our context if the principals match
|
||||
|
@ -10006,8 +9944,7 @@ nsDocShell::LoadHistoryEntry(nsISHEntry * aEntry, PRUint32 aLoadType)
|
|||
aEntry, // SHEntry
|
||||
PR_TRUE,
|
||||
nsnull, // No nsIDocShell
|
||||
nsnull, // No nsIRequest
|
||||
nsnull); // Use default HTTP method
|
||||
nsnull); // No nsIRequest
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
@ -10420,7 +10357,6 @@ NS_IMETHODIMP nsDocShell::MakeEditable(PRBool inWaitForUriLoad)
|
|||
return mEditorData->MakeEditable(inWaitForUriLoad);
|
||||
}
|
||||
|
||||
/* static */
|
||||
bool
|
||||
nsDocShell::ChannelIsPost(nsIChannel* aChannel)
|
||||
{
|
||||
|
@ -10434,21 +10370,6 @@ nsDocShell::ChannelIsPost(nsIChannel* aChannel)
|
|||
return method.Equals("POST");
|
||||
}
|
||||
|
||||
/* static */
|
||||
bool
|
||||
nsDocShell::ChannelIsSafeHTTPMethod(nsIChannel* aChannel)
|
||||
{
|
||||
nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(aChannel));
|
||||
if (!httpChannel) {
|
||||
return true;
|
||||
}
|
||||
|
||||
nsCAutoString method;
|
||||
httpChannel->GetRequestMethod(method);
|
||||
return method.Equals("GET") || method.Equals("POST") ||
|
||||
method.Equals("HEAD");
|
||||
}
|
||||
|
||||
void
|
||||
nsDocShell::ExtractLastVisit(nsIChannel* aChannel,
|
||||
nsIURI** aURI,
|
||||
|
@ -11379,8 +11300,7 @@ nsDocShell::OnLinkClickSync(nsIContent *aContent,
|
|||
nsIInputStream* aPostDataStream,
|
||||
nsIInputStream* aHeadersDataStream,
|
||||
nsIDocShell** aDocShell,
|
||||
nsIRequest** aRequest,
|
||||
const char* aHttpMethod)
|
||||
nsIRequest** aRequest)
|
||||
{
|
||||
// Initialize the DocShell / Request
|
||||
if (aDocShell) {
|
||||
|
@ -11456,8 +11376,7 @@ nsDocShell::OnLinkClickSync(nsIContent *aContent,
|
|||
nsnull, // No SHEntry
|
||||
PR_TRUE, // first party site
|
||||
aDocShell, // DocShell out-param
|
||||
aRequest, // Request out-param
|
||||
aHttpMethod); // HTTP Method
|
||||
aRequest); // Request out-param
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
DispatchPings(aContent, referer);
|
||||
}
|
||||
|
|
|
@ -243,8 +243,7 @@ public:
|
|||
nsIInputStream* aPostDataStream = 0,
|
||||
nsIInputStream* aHeadersDataStream = 0,
|
||||
nsIDocShell** aDocShell = 0,
|
||||
nsIRequest** aRequest = 0,
|
||||
const char* aHttpMethod = 0);
|
||||
nsIRequest** aRequest = 0);
|
||||
NS_IMETHOD OnOverLink(nsIContent* aContent,
|
||||
nsIURI* aURI,
|
||||
const PRUnichar* aTargetSpec);
|
||||
|
@ -326,8 +325,7 @@ protected:
|
|||
nsIRequest ** aRequest,
|
||||
PRBool aIsNewWindowTarget,
|
||||
PRBool aBypassClassifier,
|
||||
PRBool aForceAllowCookies,
|
||||
const char* aHttpMethod);
|
||||
PRBool aForceAllowCookies);
|
||||
NS_IMETHOD AddHeadersToChannel(nsIInputStream * aHeadersData,
|
||||
nsIChannel * aChannel);
|
||||
virtual nsresult DoChannelLoad(nsIChannel * aChannel,
|
||||
|
@ -436,7 +434,7 @@ protected:
|
|||
|
||||
// overridden from nsDocLoader, this provides more information than the
|
||||
// normal OnStateChange with flags STATE_REDIRECTING
|
||||
virtual nsresult OnRedirectStateChange(nsIChannel* aOldChannel,
|
||||
virtual void OnRedirectStateChange(nsIChannel* aOldChannel,
|
||||
nsIChannel* aNewChannel,
|
||||
PRUint32 aRedirectFlags,
|
||||
PRUint32 aStateFlags);
|
||||
|
@ -449,17 +447,7 @@ protected:
|
|||
*
|
||||
* @return True iff channel is an HTTP post.
|
||||
*/
|
||||
static bool ChannelIsPost(nsIChannel* aChannel);
|
||||
|
||||
/**
|
||||
* Helper function that determines if the HTTP channel has a safe method
|
||||
*
|
||||
* @param aChannel The channel to test
|
||||
*
|
||||
* @return Whether the channel has a safe HTTP method.
|
||||
* @note Will return true if the channel isn't an HTTP channel.
|
||||
*/
|
||||
static bool ChannelIsSafeHTTPMethod(nsIChannel* aChannel);
|
||||
bool ChannelIsPost(nsIChannel* aChannel);
|
||||
|
||||
/**
|
||||
* Helper function that finds the last URI and its transition flags for a
|
||||
|
|
|
@ -71,7 +71,7 @@ interface nsIPrincipal;
|
|||
interface nsIWebBrowserPrint;
|
||||
interface nsIVariant;
|
||||
|
||||
[scriptable, uuid(0e1e1ee5-5baa-4e27-98af-3197d70d0304)]
|
||||
[scriptable, uuid(74470127-87eb-4f79-8293-1616fe9cb689)]
|
||||
interface nsIDocShell : nsISupports
|
||||
{
|
||||
/**
|
||||
|
@ -155,10 +155,6 @@ interface nsIDocShell : nsISupports
|
|||
* @param aLoadFlags - Flags to modify load behaviour. Flags are defined
|
||||
* in nsIWebNavigation.
|
||||
* @param aSHEntry - Active Session History entry (if loading from SH)
|
||||
* @param firstParty -
|
||||
* @param aDocShell -
|
||||
* @param aRequest -
|
||||
* @param aHttpMethod - Force the HTTP channel to use a specific HTTP method
|
||||
*/
|
||||
[noscript]void internalLoad(in nsIURI aURI,
|
||||
in nsIURI aReferrer,
|
||||
|
@ -172,8 +168,7 @@ interface nsIDocShell : nsISupports
|
|||
in nsISHEntry aSHEntry,
|
||||
in boolean firstParty,
|
||||
out nsIDocShell aDocShell,
|
||||
out nsIRequest aRequest,
|
||||
in string aHttpMethod);
|
||||
out nsIRequest aRequest);
|
||||
|
||||
/**
|
||||
* Do either a history.pushState() or history.replaceState() operation,
|
||||
|
|
|
@ -14,7 +14,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=428288
|
|||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
<iframe name="target"></iframe>
|
||||
<a id="crashy" target="target" href="http://www.mozilla.com">crash me</a>
|
||||
<a id="crashy" target="target" href="about:blank">crash me</a>
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
|
|
@ -104,7 +104,9 @@
|
|||
#include "nsIHTMLDocument.h"
|
||||
#include "nsIDOMHTMLDocument.h"
|
||||
#include "nsIDOMHTMLElement.h"
|
||||
#ifndef MOZ_DISABLE_DOMCRYPTO
|
||||
#include "nsIDOMCrypto.h"
|
||||
#endif
|
||||
#include "nsIDOMDocument.h"
|
||||
#include "nsIDOM3Document.h"
|
||||
#include "nsIDOMNSDocument.h"
|
||||
|
@ -391,10 +393,10 @@ static PRBool gDOMWindowDumpEnabled = PR_FALSE;
|
|||
static NS_DEFINE_CID(kXULControllersCID, NS_XULCONTROLLERS_CID);
|
||||
|
||||
static const char sJSStackContractID[] = "@mozilla.org/js/xpc/ContextStack;1";
|
||||
|
||||
#ifndef MOZ_DISABLE_DOMCRYPTO
|
||||
static const char kCryptoContractID[] = NS_CRYPTO_CONTRACTID;
|
||||
static const char kPkcs11ContractID[] = NS_PKCS11_CONTRACTID;
|
||||
|
||||
#endif
|
||||
static const char sPopStatePrefStr[] = "browser.history.allowPopState";
|
||||
|
||||
static PRBool
|
||||
|
@ -1652,12 +1654,12 @@ nsGlobalWindow::SetNewDocument(nsIDocument* aDocument,
|
|||
NS_ENSURE_TRUE(scx, NS_ERROR_NOT_INITIALIZED);
|
||||
|
||||
JSContext *cx = (JSContext *)scx->GetNativeContext();
|
||||
|
||||
#ifndef MOZ_DISABLE_DOMCRYPTO
|
||||
// clear smartcard events, our document has gone away.
|
||||
if (mCrypto) {
|
||||
mCrypto->SetEnableSmartCardEvents(PR_FALSE);
|
||||
}
|
||||
|
||||
#endif
|
||||
if (!mDocument) {
|
||||
// First document load.
|
||||
|
||||
|
@ -3091,6 +3093,9 @@ nsGlobalWindow::RevokeBlobURL(const nsAString& aURL)
|
|||
NS_IMETHODIMP
|
||||
nsGlobalWindow::GetCrypto(nsIDOMCrypto** aCrypto)
|
||||
{
|
||||
#ifdef MOZ_DISABLE_DOMCRYPTO
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
#else
|
||||
FORWARD_TO_OUTER(GetCrypto, (aCrypto), NS_ERROR_NOT_INITIALIZED);
|
||||
|
||||
if (!mCrypto) {
|
||||
|
@ -3100,6 +3105,7 @@ nsGlobalWindow::GetCrypto(nsIDOMCrypto** aCrypto)
|
|||
NS_IF_ADDREF(*aCrypto = mCrypto);
|
||||
|
||||
return NS_OK;
|
||||
#endif
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
|
|
@ -86,7 +86,9 @@
|
|||
#include "nsIScriptSecurityManager.h"
|
||||
#include "nsIEventListenerManager.h"
|
||||
#include "nsIDOMDocument.h"
|
||||
#ifndef MOZ_DISABLE_DOMCRYPTO
|
||||
#include "nsIDOMCrypto.h"
|
||||
#endif
|
||||
#include "nsIPrincipal.h"
|
||||
#include "nsPluginArray.h"
|
||||
#include "nsMimeTypeArray.h"
|
||||
|
@ -142,6 +144,10 @@ class nsRunnable;
|
|||
class nsDOMOfflineResourceList;
|
||||
class nsGeolocation;
|
||||
|
||||
#ifdef MOZ_DISABLE_DOMCRYPTO
|
||||
class nsIDOMCrypto;
|
||||
#endif
|
||||
|
||||
extern nsresult
|
||||
NS_CreateJSTimeoutHandler(nsGlobalWindow *aWindow,
|
||||
PRBool *aIsInterval,
|
||||
|
@ -845,9 +851,9 @@ protected:
|
|||
nsString mDefaultStatus;
|
||||
// index 0->language_id 1, so index MAX-1 == language_id MAX
|
||||
nsGlobalWindowObserver* mObserver;
|
||||
|
||||
#ifndef MOZ_DISABLE_DOMCRYPTO
|
||||
nsCOMPtr<nsIDOMCrypto> mCrypto;
|
||||
|
||||
#endif
|
||||
nsCOMPtr<nsIDOMStorage> mLocalStorage;
|
||||
nsCOMPtr<nsIDOMStorage> mSessionStorage;
|
||||
|
||||
|
|
|
@ -57,6 +57,8 @@
|
|||
#include "nsServiceManagerUtils.h"
|
||||
#include "nsXULAppAPI.h"
|
||||
#include "nsWeakReference.h"
|
||||
#include "nsIScriptError.h"
|
||||
#include "nsIConsoleService.h"
|
||||
|
||||
#include "History.h"
|
||||
#include "nsDocShellCID.h"
|
||||
|
@ -112,6 +114,59 @@ private:
|
|||
nsString mData;
|
||||
};
|
||||
|
||||
class ConsoleListener : public nsIConsoleListener
|
||||
{
|
||||
public:
|
||||
ConsoleListener(ContentChild* aChild)
|
||||
: mChild(aChild) {}
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSICONSOLELISTENER
|
||||
|
||||
private:
|
||||
ContentChild* mChild;
|
||||
friend class ContentChild;
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS1(ConsoleListener, nsIConsoleListener)
|
||||
|
||||
NS_IMETHODIMP
|
||||
ConsoleListener::Observe(nsIConsoleMessage* aMessage)
|
||||
{
|
||||
if (!mChild)
|
||||
return NS_OK;
|
||||
|
||||
nsCOMPtr<nsIScriptError> scriptError = do_QueryInterface(aMessage);
|
||||
if (scriptError) {
|
||||
nsString msg, sourceName, sourceLine;
|
||||
nsXPIDLCString category;
|
||||
PRUint32 lineNum, colNum, flags;
|
||||
|
||||
nsresult rv = scriptError->GetErrorMessage(msg);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = scriptError->GetSourceName(sourceName);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = scriptError->GetSourceLine(sourceLine);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = scriptError->GetCategory(getter_Copies(category));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = scriptError->GetLineNumber(&lineNum);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = scriptError->GetColumnNumber(&colNum);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = scriptError->GetFlags(&flags);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
mChild->SendScriptError(msg, sourceName, sourceLine,
|
||||
lineNum, colNum, flags, category);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsXPIDLString msg;
|
||||
nsresult rv = aMessage->GetMessageMoz(getter_Copies(msg));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
mChild->SendConsoleMessage(msg);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
ContentChild* ContentChild::sSingleton;
|
||||
|
||||
|
@ -146,6 +201,20 @@ ContentChild::Init(MessageLoop* aIOLoop,
|
|||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
ContentChild::InitXPCOM()
|
||||
{
|
||||
nsCOMPtr<nsIConsoleService> svc(do_GetService(NS_CONSOLESERVICE_CONTRACTID));
|
||||
if (!svc) {
|
||||
NS_WARNING("Couldn't acquire console service");
|
||||
return;
|
||||
}
|
||||
|
||||
mConsoleListener = new ConsoleListener(this);
|
||||
if (NS_FAILED(svc->RegisterListener(mConsoleListener)))
|
||||
NS_WARNING("Couldn't register console listener for child process");
|
||||
}
|
||||
|
||||
PBrowserChild*
|
||||
ContentChild::AllocPBrowser(const PRUint32& aChromeFlags)
|
||||
{
|
||||
|
@ -253,6 +322,13 @@ ContentChild::ActorDestroy(ActorDestroyReason why)
|
|||
#endif
|
||||
|
||||
mAlertObservers.Clear();
|
||||
|
||||
nsCOMPtr<nsIConsoleService> svc(do_GetService(NS_CONSOLESERVICE_CONTRACTID));
|
||||
if (svc) {
|
||||
svc->UnregisterListener(mConsoleListener);
|
||||
mConsoleListener->mChild = nsnull;
|
||||
}
|
||||
|
||||
XRE_ShutdownChildProcess();
|
||||
}
|
||||
|
||||
|
|
|
@ -43,6 +43,7 @@
|
|||
#include "mozilla/dom/PContentChild.h"
|
||||
|
||||
#include "nsTArray.h"
|
||||
#include "nsIConsoleListener.h"
|
||||
|
||||
struct ChromePackage;
|
||||
class nsIObserver;
|
||||
|
@ -54,6 +55,7 @@ namespace dom {
|
|||
|
||||
class AlertObserver;
|
||||
class PrefObserver;
|
||||
class ConsoleListener;
|
||||
|
||||
class ContentChild : public PContentChild
|
||||
{
|
||||
|
@ -64,6 +66,7 @@ public:
|
|||
bool Init(MessageLoop* aIOLoop,
|
||||
base::ProcessHandle aParentHandle,
|
||||
IPC::Channel* aChannel);
|
||||
void InitXPCOM();
|
||||
|
||||
static ContentChild* GetSingleton() {
|
||||
NS_ASSERTION(sSingleton, "not initialized");
|
||||
|
@ -124,6 +127,7 @@ private:
|
|||
|
||||
nsTArray<nsAutoPtr<AlertObserver> > mAlertObservers;
|
||||
nsTArray<nsAutoPtr<PrefObserver> > mPrefObservers;
|
||||
nsRefPtr<ConsoleListener> mConsoleListener;
|
||||
bool mDead;
|
||||
|
||||
static ContentChild* sSingleton;
|
||||
|
|
|
@ -60,6 +60,9 @@
|
|||
#include "nsIAlertsService.h"
|
||||
#include "nsToolkitCompsCID.h"
|
||||
#include "nsIDOMGeoGeolocation.h"
|
||||
#include "nsIConsoleService.h"
|
||||
#include "nsIScriptError.h"
|
||||
#include "nsConsoleMessage.h"
|
||||
|
||||
#include "mozilla/dom/ExternalHelperAppParent.h"
|
||||
|
||||
|
@ -547,5 +550,40 @@ ContentParent::HandleEvent(nsIDOMGeoPosition* postion)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
bool
|
||||
ContentParent::RecvConsoleMessage(const nsString& aMessage)
|
||||
{
|
||||
nsCOMPtr<nsIConsoleService> svc(do_GetService(NS_CONSOLESERVICE_CONTRACTID));
|
||||
if (!svc)
|
||||
return true;
|
||||
|
||||
nsRefPtr<nsConsoleMessage> msg(new nsConsoleMessage(aMessage.get()));
|
||||
svc->LogMessage(msg);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
ContentParent::RecvScriptError(const nsString& aMessage,
|
||||
const nsString& aSourceName,
|
||||
const nsString& aSourceLine,
|
||||
const PRUint32& aLineNumber,
|
||||
const PRUint32& aColNumber,
|
||||
const PRUint32& aFlags,
|
||||
const nsCString& aCategory)
|
||||
{
|
||||
nsCOMPtr<nsIConsoleService> svc(do_GetService(NS_CONSOLESERVICE_CONTRACTID));
|
||||
if (!svc)
|
||||
return true;
|
||||
|
||||
nsCOMPtr<nsIScriptError> msg(do_CreateInstance(NS_SCRIPTERROR_CONTRACTID));
|
||||
nsresult rv = msg->Init(aMessage.get(), aSourceName.get(), aSourceLine.get(),
|
||||
aLineNumber, aColNumber, aFlags, aCategory.get());
|
||||
if (NS_FAILED(rv))
|
||||
return true;
|
||||
|
||||
svc->LogMessage(msg);
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -157,6 +157,15 @@ private:
|
|||
virtual bool RecvGeolocationStart();
|
||||
virtual bool RecvGeolocationStop();
|
||||
|
||||
virtual bool RecvConsoleMessage(const nsString& aMessage);
|
||||
virtual bool RecvScriptError(const nsString& aMessage,
|
||||
const nsString& aSourceName,
|
||||
const nsString& aSourceLine,
|
||||
const PRUint32& aLineNumber,
|
||||
const PRUint32& aColNumber,
|
||||
const PRUint32& aFlags,
|
||||
const nsCString& aCategory);
|
||||
|
||||
mozilla::Monitor mMonitor;
|
||||
|
||||
GeckoChildProcessHost* mSubprocess;
|
||||
|
|
|
@ -53,6 +53,7 @@ ContentProcess::Init()
|
|||
ParentHandle(),
|
||||
IOThreadChild::channel());
|
||||
mXREEmbed.Start();
|
||||
mContent.InitXPCOM();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -80,6 +80,7 @@ LOCAL_INCLUDES += \
|
|||
-I$(topsrcdir)/uriloader/exthandler \
|
||||
-I$(srcdir)/../../netwerk/base/src \
|
||||
-I$(srcdir)/../src/base \
|
||||
-I$(srcdir)/../../xpcom/base \
|
||||
$(NULL)
|
||||
|
||||
DEFINES += -DBIN_SUFFIX='"$(BIN_SUFFIX)"'
|
||||
|
|
|
@ -91,6 +91,26 @@ parent:
|
|||
sync SyncMessage(nsString aMessage, nsString aJSON)
|
||||
returns (nsString[] retval);
|
||||
|
||||
/**
|
||||
* The IME sequence number (seqno) parameter is used to make sure
|
||||
* that a notification is discarded if it arrives at the chrome process
|
||||
* too late. If the notification is late and we accept it, we will have
|
||||
* an out-of-date view of the content process, which means events that we
|
||||
* dispatch based on this out-of-date view will be wrong also.
|
||||
* (see Bug 599550 and Bug 591047 comments 44, 50, and 54)
|
||||
*
|
||||
* Chrome increments seqno and includes it in each IME event sent to
|
||||
* content, and content sends its current seqno back to chrome with each
|
||||
* notification. A notification is up-to-date only if the content
|
||||
* seqno is the same as the current chrome seqno, meaning no additional
|
||||
* event was sent to content before the notification was received
|
||||
*
|
||||
* On blur, chrome returns the current seqno to content, and content
|
||||
* uses it to discard subsequent events until the content seqno and
|
||||
* chrome seqno-on-blur match again. These events, meant for the blurred
|
||||
* textfield, are discarded to prevent events going to the wrong target
|
||||
*/
|
||||
|
||||
/**
|
||||
* Notifies chrome that there is a focus change involving an editable
|
||||
* object (input, textarea, document, contentEditable. etc.)
|
||||
|
@ -98,9 +118,10 @@ parent:
|
|||
* focus PR_TRUE if editable object is receiving focus
|
||||
* PR_FALSE if losing focus
|
||||
* preference Native widget preference for IME updates
|
||||
* seqno Current seqno value on the chrome side
|
||||
*/
|
||||
sync NotifyIMEFocus(PRBool focus)
|
||||
returns (nsIMEUpdatePreference preference);
|
||||
returns (nsIMEUpdatePreference preference, PRUint32 seqno);
|
||||
|
||||
/**
|
||||
* Notifies chrome that there has been a change in text content
|
||||
|
@ -120,10 +141,11 @@ parent:
|
|||
* Notifies chrome that there has been a change in selection
|
||||
* Only called when NotifyIMEFocus returns PR_TRUE for mWantUpdates
|
||||
*
|
||||
* seqno Current seqno value on the content side
|
||||
* anchor Offset where the selection started
|
||||
* focus Offset where the caret is
|
||||
*/
|
||||
NotifyIMESelection(PRUint32 anchor, PRUint32 focus);
|
||||
NotifyIMESelection(PRUint32 seqno, PRUint32 anchor, PRUint32 focus);
|
||||
|
||||
/**
|
||||
* Notifies chrome to refresh its text cache
|
||||
|
|
|
@ -115,6 +115,11 @@ parent:
|
|||
GeolocationStart();
|
||||
GeolocationStop();
|
||||
|
||||
ConsoleMessage(nsString message);
|
||||
ScriptError(nsString message, nsString sourceName, nsString sourceLine,
|
||||
PRUint32 lineNumber, PRUint32 colNumber, PRUint32 flags,
|
||||
nsCString category);
|
||||
|
||||
both:
|
||||
AsyncMessage(nsString aMessage, nsString aJSON);
|
||||
|
||||
|
|
|
@ -317,12 +317,14 @@ TabParent::RecvAsyncMessage(const nsString& aMessage,
|
|||
|
||||
bool
|
||||
TabParent::RecvNotifyIMEFocus(const PRBool& aFocus,
|
||||
nsIMEUpdatePreference* aPreference)
|
||||
nsIMEUpdatePreference* aPreference,
|
||||
PRUint32* aSeqno)
|
||||
{
|
||||
nsCOMPtr<nsIWidget> widget = GetWidget();
|
||||
if (!widget)
|
||||
return true;
|
||||
|
||||
*aSeqno = mIMESeqno;
|
||||
mIMETabParent = aFocus ? this : nsnull;
|
||||
mIMESelectionAnchor = 0;
|
||||
mIMESelectionFocus = 0;
|
||||
|
@ -355,16 +357,19 @@ TabParent::RecvNotifyIMETextChange(const PRUint32& aStart,
|
|||
}
|
||||
|
||||
bool
|
||||
TabParent::RecvNotifyIMESelection(const PRUint32& aAnchor,
|
||||
TabParent::RecvNotifyIMESelection(const PRUint32& aSeqno,
|
||||
const PRUint32& aAnchor,
|
||||
const PRUint32& aFocus)
|
||||
{
|
||||
nsCOMPtr<nsIWidget> widget = GetWidget();
|
||||
if (!widget)
|
||||
return true;
|
||||
|
||||
if (aSeqno == mIMESeqno) {
|
||||
mIMESelectionAnchor = aAnchor;
|
||||
mIMESelectionFocus = aFocus;
|
||||
widget->OnIMESelectionChange();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -444,12 +449,13 @@ TabParent::HandleQueryContentEvent(nsQueryContentEvent& aEvent)
|
|||
}
|
||||
|
||||
bool
|
||||
TabParent::SendCompositionEvent(const nsCompositionEvent& event)
|
||||
TabParent::SendCompositionEvent(nsCompositionEvent& event)
|
||||
{
|
||||
mIMEComposing = event.message == NS_COMPOSITION_START;
|
||||
mIMECompositionStart = PR_MIN(mIMESelectionAnchor, mIMESelectionFocus);
|
||||
if (mIMECompositionEnding)
|
||||
return true;
|
||||
event.seqno = ++mIMESeqno;
|
||||
return PBrowserParent::SendCompositionEvent(event);
|
||||
}
|
||||
|
||||
|
@ -461,7 +467,7 @@ TabParent::SendCompositionEvent(const nsCompositionEvent& event)
|
|||
* here and pass the text as the EndIMEComposition return value
|
||||
*/
|
||||
bool
|
||||
TabParent::SendTextEvent(const nsTextEvent& event)
|
||||
TabParent::SendTextEvent(nsTextEvent& event)
|
||||
{
|
||||
if (mIMECompositionEnding) {
|
||||
mIMECompositionText = event.theText;
|
||||
|
@ -476,14 +482,16 @@ TabParent::SendTextEvent(const nsTextEvent& event)
|
|||
mIMESelectionAnchor = mIMESelectionFocus =
|
||||
mIMECompositionStart + event.theText.Length();
|
||||
|
||||
event.seqno = ++mIMESeqno;
|
||||
return PBrowserParent::SendTextEvent(event);
|
||||
}
|
||||
|
||||
bool
|
||||
TabParent::SendSelectionEvent(const nsSelectionEvent& event)
|
||||
TabParent::SendSelectionEvent(nsSelectionEvent& event)
|
||||
{
|
||||
mIMESelectionAnchor = event.mOffset + (event.mReversed ? event.mLength : 0);
|
||||
mIMESelectionFocus = event.mOffset + (!event.mReversed ? event.mLength : 0);
|
||||
event.seqno = ++mIMESeqno;
|
||||
return PBrowserParent::SendSelectionEvent(event);
|
||||
}
|
||||
|
||||
|
|
|
@ -92,11 +92,13 @@ public:
|
|||
virtual bool RecvAsyncMessage(const nsString& aMessage,
|
||||
const nsString& aJSON);
|
||||
virtual bool RecvNotifyIMEFocus(const PRBool& aFocus,
|
||||
nsIMEUpdatePreference* aPreference);
|
||||
nsIMEUpdatePreference* aPreference,
|
||||
PRUint32* aSeqno);
|
||||
virtual bool RecvNotifyIMETextChange(const PRUint32& aStart,
|
||||
const PRUint32& aEnd,
|
||||
const PRUint32& aNewEnd);
|
||||
virtual bool RecvNotifyIMESelection(const PRUint32& aAnchor,
|
||||
virtual bool RecvNotifyIMESelection(const PRUint32& aSeqno,
|
||||
const PRUint32& aAnchor,
|
||||
const PRUint32& aFocus);
|
||||
virtual bool RecvNotifyIMETextHint(const nsString& aText);
|
||||
virtual bool RecvEndIMEComposition(const PRBool& aCancel,
|
||||
|
@ -179,9 +181,9 @@ public:
|
|||
|
||||
static TabParent *GetIMETabParent() { return mIMETabParent; }
|
||||
bool HandleQueryContentEvent(nsQueryContentEvent& aEvent);
|
||||
bool SendCompositionEvent(const nsCompositionEvent& event);
|
||||
bool SendTextEvent(const nsTextEvent& event);
|
||||
bool SendSelectionEvent(const nsSelectionEvent& event);
|
||||
bool SendCompositionEvent(nsCompositionEvent& event);
|
||||
bool SendTextEvent(nsTextEvent& event);
|
||||
bool SendSelectionEvent(nsSelectionEvent& event);
|
||||
protected:
|
||||
bool ReceiveMessage(const nsString& aMessage,
|
||||
PRBool aSync,
|
||||
|
@ -232,6 +234,7 @@ protected:
|
|||
// Compositions in almost all cases are small enough for nsAutoString
|
||||
nsAutoString mIMECompositionText;
|
||||
PRUint32 mIMECompositionStart;
|
||||
PRUint32 mIMESeqno;
|
||||
|
||||
private:
|
||||
already_AddRefed<nsFrameLoader> GetFrameLoader() const;
|
||||
|
|
|
@ -142,7 +142,7 @@ PluginInstanceChild::PluginInstanceChild(const NPPluginFuncs* aPluginIface,
|
|||
#ifdef MOZ_X11
|
||||
, mFlash10Quirks(PR_FALSE)
|
||||
#endif
|
||||
#if (MOZ_PLATFORM_MAEMO == 5)
|
||||
#if (MOZ_PLATFORM_MAEMO == 5) || (MOZ_PLATFORM_MAEMO == 6)
|
||||
, mMaemoImageRendering(PR_FALSE)
|
||||
#endif
|
||||
{
|
||||
|
@ -303,7 +303,7 @@ PluginInstanceChild::NPN_GetValue(NPNVariable aVar,
|
|||
#endif
|
||||
return NPERR_NO_ERROR;
|
||||
|
||||
#if (MOZ_PLATFORM_MAEMO == 5)
|
||||
#if (MOZ_PLATFORM_MAEMO == 5) || (MOZ_PLATFORM_MAEMO == 6)
|
||||
case NPNVSupportsWindowlessLocal: {
|
||||
#ifdef MOZ_WIDGET_QT
|
||||
const char *graphicsSystem = PR_GetEnv("MOZ_QT_GRAPHICSSYSTEM");
|
||||
|
@ -2052,7 +2052,7 @@ PluginInstanceChild::CreateOptSurface(void)
|
|||
mIsTransparent ? gfxASurface::ImageFormatARGB32 :
|
||||
gfxASurface::ImageFormatRGB24;
|
||||
|
||||
#if (MOZ_PLATFORM_MAEMO == 5)
|
||||
#if (MOZ_PLATFORM_MAEMO == 5) || (MOZ_PLATFORM_MAEMO == 6)
|
||||
// On Maemo 5, we must send the Visibility event to activate the plugin
|
||||
if (mMaemoImageRendering) {
|
||||
NPEvent pluginEvent;
|
||||
|
@ -2128,7 +2128,7 @@ PluginInstanceChild::MaybeCreatePlatformHelperSurface(void)
|
|||
mDoAlphaExtraction = mIsTransparent;
|
||||
}
|
||||
} else if (mCurrentSurface->GetType() == gfxASurface::SurfaceTypeImage) {
|
||||
#if (MOZ_PLATFORM_MAEMO == 5)
|
||||
#if (MOZ_PLATFORM_MAEMO == 5) || (MOZ_PLATFORM_MAEMO == 6)
|
||||
if (mMaemoImageRendering) {
|
||||
// No helper surface needed, when mMaemoImageRendering is TRUE.
|
||||
// we can rendering directly into image memory
|
||||
|
@ -2206,7 +2206,7 @@ PluginInstanceChild::UpdateWindowAttributes(PRBool aForceSetWindow)
|
|||
needWindowUpdate = PR_TRUE;
|
||||
}
|
||||
}
|
||||
#if (MOZ_PLATFORM_MAEMO == 5)
|
||||
#if (MOZ_PLATFORM_MAEMO == 5) || (MOZ_PLATFORM_MAEMO == 6)
|
||||
else if (curSurface && curSurface->GetType() == gfxASurface::SurfaceTypeImage
|
||||
&& mMaemoImageRendering) {
|
||||
// For maemo5 we need to setup window/colormap to 0
|
||||
|
@ -2254,7 +2254,7 @@ PluginInstanceChild::PaintRectToPlatformSurface(const nsIntRect& aRect,
|
|||
{
|
||||
UpdateWindowAttributes();
|
||||
#ifdef MOZ_X11
|
||||
#if (MOZ_PLATFORM_MAEMO == 5)
|
||||
#if (MOZ_PLATFORM_MAEMO == 5) || (MOZ_PLATFORM_MAEMO == 6)
|
||||
// On maemo5 we do support Image rendering NPAPI
|
||||
if (mMaemoImageRendering &&
|
||||
aSurface->GetType() == gfxASurface::SurfaceTypeImage) {
|
||||
|
@ -2337,7 +2337,7 @@ PluginInstanceChild::PaintRectToSurface(const nsIntRect& aRect,
|
|||
}
|
||||
if (renderSurface->GetType() != gfxASurface::SurfaceTypeXlib) {
|
||||
// On X11 we can paint to non Xlib surface only with HelperSurface
|
||||
#if (MOZ_PLATFORM_MAEMO == 5)
|
||||
#if (MOZ_PLATFORM_MAEMO == 5) || (MOZ_PLATFORM_MAEMO == 6)
|
||||
// Don't use mHelperSurface if surface is image and mMaemoImageRendering is TRUE
|
||||
if (!mMaemoImageRendering ||
|
||||
renderSurface->GetType() != gfxASurface::SurfaceTypeImage)
|
||||
|
|
|
@ -482,7 +482,7 @@ private:
|
|||
// Used with windowless flash plugin only, see bug 574583
|
||||
PRPackedBool mFlash10Quirks;
|
||||
#endif
|
||||
#if (MOZ_PLATFORM_MAEMO == 5)
|
||||
#if (MOZ_PLATFORM_MAEMO == 5) || (MOZ_PLATFORM_MAEMO == 6)
|
||||
// Maemo5 Flash does not remember WindowlessLocal state
|
||||
// we should listen for NPP values negotiation and remember it
|
||||
PRPackedBool mMaemoImageRendering;
|
||||
|
|
|
@ -3,8 +3,14 @@
|
|||
<head>
|
||||
<title>postMessage chrome message receiver</title>
|
||||
<script type="application/javascript">
|
||||
var gPrePath = "";
|
||||
|
||||
function receiveMessage(evt)
|
||||
{
|
||||
if (evt.data.substring(0,9) == "chrome://") {
|
||||
gPrePath = evt.data;
|
||||
respond("path-is-set");
|
||||
} else {
|
||||
// Content cannot post to chrome without privileges
|
||||
window.parent.postMessage("SHOULD NOT GET THIS!", "*");
|
||||
|
||||
|
@ -16,13 +22,14 @@
|
|||
msg += " unexpected-untrusted-event";
|
||||
if (evt.type !== "message")
|
||||
msg += " wrong-type(" + evt.type + ")";
|
||||
if (evt.origin !== "chrome://mochikit")
|
||||
if (evt.origin !== gPrePath)
|
||||
msg += " wrong-origin(" + evt.origin + ")";
|
||||
if (evt.data !== "post-to-content")
|
||||
msg += " wrong-message(" + evt.data + ")";
|
||||
|
||||
respond(msg);
|
||||
}
|
||||
}
|
||||
|
||||
function respond(msg)
|
||||
{
|
||||
|
|
|
@ -45,6 +45,10 @@ function messageReceiver(evt)
|
|||
|
||||
switch (evt.data)
|
||||
{
|
||||
case "path-is-set":
|
||||
chromePathIsSet(evt);
|
||||
break;
|
||||
|
||||
case "post-to-self":
|
||||
checkSelf(evt);
|
||||
break;
|
||||
|
@ -73,11 +77,16 @@ function checkSelf(evt)
|
|||
is(evt.origin, prepath, "wrong origin for chrome: URL");
|
||||
is(evt.source, null, "chrome posters get a null source, for security");
|
||||
|
||||
window.frames.contentDomain.postMessage(prepath, "*");
|
||||
}
|
||||
|
||||
|
||||
function chromePathIsSet(evt)
|
||||
{
|
||||
window.frames.contentDomain.postMessage("post-to-content",
|
||||
"http://example.org");
|
||||
}
|
||||
|
||||
|
||||
/*************
|
||||
* RECEIVERS *
|
||||
*************/
|
||||
|
|
|
@ -0,0 +1,106 @@
|
|||
/* -*- Mode: Java; tab-width: 20; indent-tabs-mode: nil; -*-
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla Android code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Mozilla Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2010
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Alex Pakhotin <alexp@mozilla.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
package org.mozilla.gecko;
|
||||
|
||||
import android.app.Notification;
|
||||
import android.app.NotificationManager;
|
||||
import android.content.Context;
|
||||
import android.widget.RemoteViews;
|
||||
|
||||
public class AlertNotification
|
||||
extends Notification
|
||||
{
|
||||
Context mContext;
|
||||
int mId;
|
||||
int mIcon;
|
||||
String mTitle;
|
||||
boolean mProgressStyle;
|
||||
NotificationManager mNotificationManager;
|
||||
|
||||
public AlertNotification(Context aContext, int aNotificationId, int aIcon, String aTitle, long aWhen) {
|
||||
super(aIcon, aTitle, aWhen);
|
||||
|
||||
mContext = aContext;
|
||||
mIcon = aIcon;
|
||||
mTitle = aTitle;
|
||||
mProgressStyle = false;
|
||||
mId = aNotificationId;
|
||||
|
||||
mNotificationManager = (NotificationManager)
|
||||
mContext.getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
}
|
||||
|
||||
public boolean isProgressStyle() {
|
||||
return mProgressStyle;
|
||||
}
|
||||
|
||||
public void show() {
|
||||
mNotificationManager.notify(mId, this);
|
||||
}
|
||||
|
||||
public void updateProgress(String aAlertText, long aProgress, long aProgressMax) {
|
||||
if (!mProgressStyle) {
|
||||
// Custom view
|
||||
int layout = aAlertText.length() > 0 ? R.layout.notification_progress_text : R.layout.notification_progress;
|
||||
|
||||
RemoteViews view = new RemoteViews("org.mozilla." + GeckoApp.mAppContext.getAppName(), layout);
|
||||
view.setImageViewResource(R.id.notificationImage, mIcon);
|
||||
view.setTextViewText(R.id.notificationTitle, mTitle);
|
||||
contentView = view;
|
||||
flags |= FLAG_ONGOING_EVENT;
|
||||
|
||||
mProgressStyle = true;
|
||||
}
|
||||
|
||||
String text;
|
||||
if (aAlertText.length() > 0) {
|
||||
text = aAlertText;
|
||||
} else {
|
||||
int percent = 0;
|
||||
if (aProgressMax > 0)
|
||||
percent = (int)(100 * aProgress / aProgressMax);
|
||||
text = percent + "%";
|
||||
}
|
||||
|
||||
contentView.setTextViewText(R.id.notificationText, text);
|
||||
contentView.setProgressBar(R.id.notificationProgressbar, (int)aProgressMax, (int)aProgress, false);
|
||||
|
||||
// Update the notification
|
||||
mNotificationManager.notify(mId, this);
|
||||
}
|
||||
}
|
|
@ -20,7 +20,7 @@
|
|||
android:label="@MOZ_APP_DISPLAYNAME@"
|
||||
android:configChanges="keyboard|keyboardHidden|orientation|mcc|mnc"
|
||||
android:windowSoftInputMode="stateUnspecified|adjustResize"
|
||||
android:launchMode="singleTop">
|
||||
android:launchMode="singleInstance">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
|
|
|
@ -42,7 +42,6 @@ import java.util.*;
|
|||
import java.util.zip.*;
|
||||
import java.nio.*;
|
||||
import java.nio.channels.FileChannel;
|
||||
import java.util.concurrent.*;
|
||||
|
||||
import android.os.*;
|
||||
import android.app.*;
|
||||
|
@ -55,7 +54,6 @@ import android.widget.*;
|
|||
import android.hardware.*;
|
||||
|
||||
import android.util.*;
|
||||
import android.net.*;
|
||||
|
||||
abstract public class GeckoApp
|
||||
extends Activity
|
||||
|
@ -374,40 +372,6 @@ abstract public class GeckoApp
|
|||
unpackFile(zip, buf, entry, entry.getName());
|
||||
}
|
||||
}
|
||||
|
||||
ZipEntry componentsList = zip.getEntry("components/components.manifest");
|
||||
if (componentsList == null) {
|
||||
Log.i("GeckoAppJava", "Can't find components.manifest!");
|
||||
return;
|
||||
}
|
||||
|
||||
listStream = new BufferedInputStream(zip.getInputStream(componentsList));
|
||||
|
||||
StreamTokenizer tkn = new StreamTokenizer(new InputStreamReader(listStream));
|
||||
String line = "components/";
|
||||
int status;
|
||||
boolean addnext = false;
|
||||
tkn.eolIsSignificant(true);
|
||||
do {
|
||||
status = tkn.nextToken();
|
||||
switch (status) {
|
||||
case StreamTokenizer.TT_WORD:
|
||||
if (tkn.sval.equals("binary-component"))
|
||||
addnext = true;
|
||||
else if (addnext) {
|
||||
line += tkn.sval;
|
||||
addnext = false;
|
||||
}
|
||||
break;
|
||||
case StreamTokenizer.TT_NUMBER:
|
||||
break;
|
||||
case StreamTokenizer.TT_EOF:
|
||||
case StreamTokenizer.TT_EOL:
|
||||
unpackFile(zip, buf, null, line);
|
||||
line = "components/";
|
||||
break;
|
||||
}
|
||||
} while (status != StreamTokenizer.TT_EOF);
|
||||
}
|
||||
|
||||
private void unpackFile(ZipFile zip, byte[] buf, ZipEntry fileEntry,
|
||||
|
@ -541,64 +505,4 @@ abstract public class GeckoApp
|
|||
if (statusCode == 0)
|
||||
System.exit(0);
|
||||
}
|
||||
|
||||
static final int FILE_PICKER_REQUEST = 1;
|
||||
|
||||
private SynchronousQueue<String> mFilePickerResult = new SynchronousQueue();
|
||||
public String showFilePicker() {
|
||||
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
|
||||
intent.addCategory(Intent.CATEGORY_OPENABLE);
|
||||
intent.setType("*/*");
|
||||
GeckoApp.this.
|
||||
startActivityForResult(
|
||||
Intent.createChooser(intent,"choose a file"),
|
||||
FILE_PICKER_REQUEST);
|
||||
String filePickerResult = "";
|
||||
try {
|
||||
filePickerResult = mFilePickerResult.take();
|
||||
} catch (InterruptedException e) {
|
||||
Log.i("GeckoApp", "error: " + e);
|
||||
}
|
||||
|
||||
return filePickerResult;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onActivityResult(int requestCode, int resultCode,
|
||||
Intent data) {
|
||||
String filePickerResult = "";
|
||||
if (data != null && resultCode == RESULT_OK) {
|
||||
try {
|
||||
ContentResolver cr = getContentResolver();
|
||||
Uri uri = data.getData();
|
||||
String mimeType = cr.getType(uri);
|
||||
String fileExt = "." +
|
||||
mimeType.substring(mimeType.lastIndexOf('/') + 1);
|
||||
File file =
|
||||
File.createTempFile("tmp_" +
|
||||
(int)Math.floor(1000 * Math.random()),
|
||||
fileExt,
|
||||
new File("/data/data/org.mozilla." +
|
||||
getAppName()));
|
||||
|
||||
FileOutputStream fos = new FileOutputStream(file);
|
||||
InputStream is = cr.openInputStream(uri);
|
||||
byte[] buf = new byte[4096];
|
||||
int len = is.read(buf);
|
||||
while (len != -1) {
|
||||
fos.write(buf, 0, len);
|
||||
len = is.read(buf);
|
||||
}
|
||||
fos.close();
|
||||
filePickerResult = file.getAbsolutePath();
|
||||
}catch (Exception e) {
|
||||
Log.e("GeckoApp", "error : "+ e);
|
||||
}
|
||||
}
|
||||
try {
|
||||
mFilePickerResult.put(filePickerResult);
|
||||
} catch (InterruptedException e) {
|
||||
Log.i("GeckoApp", "error: " + e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -41,6 +41,7 @@ import java.io.*;
|
|||
import java.util.*;
|
||||
import java.util.zip.*;
|
||||
import java.nio.*;
|
||||
import java.lang.reflect.*;
|
||||
|
||||
import android.os.*;
|
||||
import android.app.*;
|
||||
|
@ -73,6 +74,8 @@ class GeckoAppShell
|
|||
static private boolean gRestartScheduled = false;
|
||||
|
||||
static private final Timer mIMETimer = new Timer();
|
||||
static private final HashMap<Integer, AlertNotification>
|
||||
mAlertNotifications = new HashMap<Integer, AlertNotification>();
|
||||
|
||||
static private final int NOTIFY_IME_RESETINPUTSTATE = 0;
|
||||
static private final int NOTIFY_IME_SETOPENSTATE = 1;
|
||||
|
@ -407,10 +410,11 @@ class GeckoAppShell
|
|||
}
|
||||
|
||||
static boolean openUriExternal(String aUriSpec, String aMimeType, String aPackageName,
|
||||
String aClassName, String aAction) {
|
||||
String aClassName, String aAction, String aTitle) {
|
||||
Intent intent = getIntentForActionString(aAction);
|
||||
if (aAction.equalsIgnoreCase(Intent.ACTION_SEND)) {
|
||||
intent.putExtra(Intent.EXTRA_TEXT, aUriSpec);
|
||||
intent.putExtra(Intent.EXTRA_SUBJECT, aTitle);
|
||||
if (aMimeType != null && aMimeType.length() > 0)
|
||||
intent.setType(aMimeType);
|
||||
} else if (aMimeType.length() > 0) {
|
||||
|
@ -446,31 +450,36 @@ class GeckoAppShell
|
|||
cm.setText(text);
|
||||
}
|
||||
|
||||
static void showAlertNotification(String imageUrl, String alertTitle, String alertText,
|
||||
String alertCookie, String alertName) {
|
||||
public static void showAlertNotification(String aImageUrl, String aAlertTitle, String aAlertText,
|
||||
String aAlertCookie, String aAlertName) {
|
||||
Log.i("GeckoAppJava", "GeckoAppShell.showAlertNotification\n" +
|
||||
"- image = '" + imageUrl + "'\n" +
|
||||
"- title = '" + alertTitle + "'\n" +
|
||||
"- text = '" + alertText +"'\n" +
|
||||
"- cookie = '" + alertCookie +"'\n" +
|
||||
"- name = '" + alertName + "'");
|
||||
"- image = '" + aImageUrl + "'\n" +
|
||||
"- title = '" + aAlertTitle + "'\n" +
|
||||
"- text = '" + aAlertText +"'\n" +
|
||||
"- cookie = '" + aAlertCookie +"'\n" +
|
||||
"- name = '" + aAlertName + "'");
|
||||
|
||||
int icon = R.drawable.icon; // Just use the app icon by default
|
||||
|
||||
Uri imageUri = Uri.parse(imageUrl);
|
||||
Uri imageUri = Uri.parse(aImageUrl);
|
||||
String scheme = imageUri.getScheme();
|
||||
|
||||
if ("drawable".equals(scheme)) {
|
||||
String resource = imageUri.getSchemeSpecificPart();
|
||||
if ("//alertdownloads".equals(resource))
|
||||
icon = R.drawable.alertdownloads;
|
||||
else if ("//alertaddons".equals(resource))
|
||||
icon = R.drawable.alertaddons;
|
||||
resource = resource.substring(resource.lastIndexOf('/') + 1);
|
||||
try {
|
||||
Class drawableClass = R.drawable.class;
|
||||
Field f = drawableClass.getField(resource);
|
||||
icon = f.getInt(null);
|
||||
} catch (Exception e) {} // just means the resource doesn't exist
|
||||
}
|
||||
|
||||
int notificationID = alertName.hashCode();
|
||||
int notificationID = aAlertName.hashCode();
|
||||
|
||||
Notification notification = new Notification(icon, alertTitle, System.currentTimeMillis());
|
||||
// Remove the old notification with the same ID, if any
|
||||
removeNotification(notificationID);
|
||||
|
||||
AlertNotification notification = new AlertNotification(GeckoApp.mAppContext,
|
||||
notificationID, icon, aAlertTitle, System.currentTimeMillis());
|
||||
|
||||
// The intent to launch when the user clicks the expanded notification
|
||||
Intent notificationIntent = new Intent(GeckoApp.ACTION_ALERT_CLICK);
|
||||
|
@ -478,11 +487,11 @@ class GeckoAppShell
|
|||
"org.mozilla." + GeckoApp.mAppContext.getAppName() + ".NotificationHandler");
|
||||
|
||||
// Put the strings into the intent as an URI "alert:<name>#<cookie>"
|
||||
Uri dataUri = Uri.fromParts("alert", alertName, alertCookie);
|
||||
Uri dataUri = Uri.fromParts("alert", aAlertName, aAlertCookie);
|
||||
notificationIntent.setData(dataUri);
|
||||
|
||||
PendingIntent contentIntent = PendingIntent.getActivity(GeckoApp.mAppContext, 0, notificationIntent, 0);
|
||||
notification.setLatestEventInfo(GeckoApp.mAppContext, alertTitle, alertText, contentIntent);
|
||||
notification.setLatestEventInfo(GeckoApp.mAppContext, aAlertTitle, aAlertText, contentIntent);
|
||||
|
||||
// The intent to execute when the status entry is deleted by the user with the "Clear All Notifications" button
|
||||
Intent clearNotificationIntent = new Intent(GeckoApp.ACTION_ALERT_CLEAR);
|
||||
|
@ -493,24 +502,51 @@ class GeckoAppShell
|
|||
PendingIntent pendingClearIntent = PendingIntent.getActivity(GeckoApp.mAppContext, 0, clearNotificationIntent, 0);
|
||||
notification.deleteIntent = pendingClearIntent;
|
||||
|
||||
// Show the notification
|
||||
NotificationManager notificationManager = (NotificationManager)
|
||||
GeckoApp.mAppContext.getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
notificationManager.notify(notificationID, notification);
|
||||
mAlertNotifications.put(notificationID, notification);
|
||||
|
||||
notification.show();
|
||||
|
||||
Log.i("GeckoAppJava", "Created notification ID " + notificationID);
|
||||
}
|
||||
|
||||
public static void handleNotification(String action, String alertName, String alertCookie) {
|
||||
if (GeckoApp.ACTION_ALERT_CLICK.equals(action)) {
|
||||
Log.i("GeckoAppJava", "GeckoAppShell.handleNotification: callObserver(alertclickcallback)");
|
||||
callObserver(alertName, "alertclickcallback", alertCookie);
|
||||
public static void alertsProgressListener_OnProgress(String aAlertName, long aProgress, long aProgressMax, String aAlertText) {
|
||||
Log.i("GeckoAppJava", "GeckoAppShell.alertsProgressListener_OnProgress\n" +
|
||||
"- name = '" + aAlertName +"', " +
|
||||
"progress = " + aProgress +" / " + aProgressMax + ", text = '" + aAlertText + "'");
|
||||
|
||||
int notificationID = aAlertName.hashCode();
|
||||
AlertNotification notification = mAlertNotifications.get(notificationID);
|
||||
if (notification != null)
|
||||
notification.updateProgress(aAlertText, aProgress, aProgressMax);
|
||||
}
|
||||
|
||||
Log.i("GeckoAppJava", "GeckoAppShell.handleNotification: callObserver(alertfinished)");
|
||||
callObserver(alertName, "alertfinished", alertCookie);
|
||||
removeObserver(alertName);
|
||||
public static void handleNotification(String aAction, String aAlertName, String aAlertCookie) {
|
||||
int notificationID = aAlertName.hashCode();
|
||||
|
||||
if (GeckoApp.ACTION_ALERT_CLICK.equals(aAction)) {
|
||||
Log.i("GeckoAppJava", "GeckoAppShell.handleNotification: callObserver(alertclickcallback)");
|
||||
callObserver(aAlertName, "alertclickcallback", aAlertCookie);
|
||||
|
||||
AlertNotification notification = mAlertNotifications.get(notificationID);
|
||||
if (notification != null && notification.isProgressStyle()) {
|
||||
// When clicked, keep the notification, if it displays a progress
|
||||
return;
|
||||
}
|
||||
public static String showFilePicker() {
|
||||
return GeckoApp.mAppContext.showFilePicker();
|
||||
}
|
||||
|
||||
callObserver(aAlertName, "alertfinished", aAlertCookie);
|
||||
|
||||
removeObserver(aAlertName);
|
||||
|
||||
removeNotification(notificationID);
|
||||
}
|
||||
|
||||
private static void removeNotification(int notificationID) {
|
||||
mAlertNotifications.remove(notificationID);
|
||||
|
||||
NotificationManager notificationManager = (NotificationManager)
|
||||
GeckoApp.mAppContext.getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
notificationManager.cancel(notificationID);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -49,6 +49,7 @@ JAVAFILES = \
|
|||
GeckoEvent.java \
|
||||
GeckoSurfaceView.java \
|
||||
GeckoInputConnection.java \
|
||||
AlertNotification.java \
|
||||
$(NULL)
|
||||
|
||||
PROCESSEDJAVAFILES = \
|
||||
|
@ -97,14 +98,9 @@ ICON_PATH = $(topsrcdir)/$(MOZ_BRANDING_DIRECTORY)/content/icon48.png
|
|||
ICON_PATH_HDPI = $(topsrcdir)/$(MOZ_BRANDING_DIRECTORY)/content/icon64.png
|
||||
endif
|
||||
|
||||
RES_DRAWABLE = \
|
||||
res/drawable/alertaddons.png \
|
||||
res/drawable/alertdownloads.png \
|
||||
$(NULL)
|
||||
|
||||
RES_DRAWABLE_HDPI = \
|
||||
res/drawable-hdpi/alertaddons.png \
|
||||
res/drawable-hdpi/alertdownloads.png \
|
||||
RES_LAYOUT = \
|
||||
res/layout/notification_progress.xml \
|
||||
res/layout/notification_progress_text.xml
|
||||
$(NULL)
|
||||
|
||||
NATIVE_LIBS = $(shell cat $(DIST)/bin/dependentlibs.list) libxpcom.so libnssckbi.so libfreebl3.so libmozutils.so
|
||||
|
@ -168,18 +164,22 @@ res/drawable-hdpi/icon.png: $(MOZ_APP_ICON)
|
|||
$(NSINSTALL) -D res/drawable-hdpi
|
||||
cp $(ICON_PATH_HDPI) $@
|
||||
|
||||
$(RES_DRAWABLE):
|
||||
ifdef MOZ_ANDROID_DRAWABLES
|
||||
RES_DRAWABLE = $(addprefix res/drawable/,$(notdir $(MOZ_ANDROID_DRAWABLES)))
|
||||
|
||||
$(RES_DRAWABLE): $(addprefix $(topsrcdir)/,$(MOZ_ANDROID_DRAWABLES))
|
||||
$(NSINSTALL) -D res/drawable
|
||||
cp $(topsrcdir)/mobile/app/android/drawable/* res/drawable/
|
||||
$(NSINSTALL) $^ res/drawable/
|
||||
endif
|
||||
|
||||
$(RES_DRAWABLE_HDPI):
|
||||
$(NSINSTALL) -D res/drawable-hdpi
|
||||
cp $(topsrcdir)/mobile/app/android/drawable-hdpi/* res/drawable-hdpi/
|
||||
$(RES_LAYOUT): $(subst res/,$(srcdir)/resources/,$(RES_LAYOUT))
|
||||
$(NSINSTALL) -D res/layout
|
||||
$(NSINSTALL) $(srcdir)/resources/layout/* res/layout/
|
||||
|
||||
R.java: $(MOZ_APP_ICON) $(RES_DRAWABLE) $(RES_DRAWABLE_HDPI) res/values/strings.xml $(LOCALIZED_STRINGS_XML) AndroidManifest.xml
|
||||
R.java: $(MOZ_APP_ICON) $(RES_LAYOUT) $(RES_DRAWABLE) res/values/strings.xml $(LOCALIZED_STRINGS_XML) AndroidManifest.xml
|
||||
$(AAPT) package -f -M AndroidManifest.xml -I $(ANDROID_SDK)/android.jar -S res -J . --custom-package org.mozilla.gecko
|
||||
|
||||
gecko.ap_: AndroidManifest.xml res/drawable/icon.png res/drawable-hdpi/icon.png $(RES_DRAWABLE) $(RES_DRAWABLE_HDPI) res/values/strings.xml $(LOCALIZED_STRINGS_XML)
|
||||
gecko.ap_: AndroidManifest.xml res/drawable/icon.png res/drawable-hdpi/icon.png $(RES_LAYOUT) $(RES_DRAWABLE) res/values/strings.xml $(LOCALIZED_STRINGS_XML)
|
||||
$(AAPT) package -f -M AndroidManifest.xml -I $(ANDROID_SDK)/android.jar -S res -F $@
|
||||
|
||||
libs/armeabi/%: $(DIST)/lib/%
|
||||
|
|
|
@ -82,12 +82,13 @@ public class NotificationHandler
|
|||
|
||||
Log.i("GeckoAppJava", "Handle notification ID " + notificationID);
|
||||
|
||||
NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
|
||||
notificationManager.cancel(notificationID);
|
||||
|
||||
if (App.mAppContext != null) {
|
||||
// This should call the observer, if any
|
||||
App.mAppContext.handleNotification(action, alertName, alertCookie);
|
||||
} else {
|
||||
// The app is not running, just cancel this notification
|
||||
NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
|
||||
notificationManager.cancel(notificationID);
|
||||
}
|
||||
|
||||
if (App.ACTION_ALERT_CLICK.equals(action)) {
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче