mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-14 05:45:37 +00:00
Merge last PGO-green changeset of mozilla-inbound to mozilla-central
This commit is contained in:
commit
f26dc0969e
@ -43,6 +43,27 @@ LeafAccessible::ChildAtPoint(int32_t aX, int32_t aY,
|
||||
return this;
|
||||
}
|
||||
|
||||
bool
|
||||
LeafAccessible::AppendChild(Accessible* aChild)
|
||||
{
|
||||
NS_NOTREACHED("AppendChild called on leaf accessible!");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
LeafAccessible::InsertChildAt(uint32_t aIndex, Accessible* aChild)
|
||||
{
|
||||
NS_NOTREACHED("InsertChildAt called on leaf accessible!");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
LeafAccessible::RemoveChild(Accessible* aChild)
|
||||
{
|
||||
NS_NOTREACHED("RemoveChild called on leaf accessible!");
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// LeafAccessible: Accessible private
|
||||
|
||||
|
@ -34,6 +34,10 @@ public:
|
||||
// Accessible
|
||||
virtual Accessible* ChildAtPoint(int32_t aX, int32_t aY,
|
||||
EWhichChildAtPoint aWhichChild);
|
||||
|
||||
virtual bool AppendChild(Accessible* aChild) MOZ_OVERRIDE MOZ_FINAL;
|
||||
virtual bool InsertChildAt(uint32_t aIndex, Accessible* aChild) MOZ_OVERRIDE MOZ_FINAL;
|
||||
virtual bool RemoveChild(Accessible* aChild) MOZ_OVERRIDE MOZ_FINAL;
|
||||
|
||||
protected:
|
||||
|
||||
|
@ -23,13 +23,14 @@
|
||||
<script type="application/javascript">
|
||||
//gA11yEventDumpToConsole = true; // debug stuff
|
||||
|
||||
var gLinkWindow = null;
|
||||
function closeDocChecker()
|
||||
{
|
||||
this.__proto__ = new asyncInvokerChecker(EVENT_DOCUMENT_LOAD_COMPLETE);
|
||||
|
||||
this.check = function closeDocChecker_check(aEvent)
|
||||
{
|
||||
aEvent.accessible.rootDocument.window.close();
|
||||
gLinkWindow = aEvent.accessible.rootDocument.window;
|
||||
}
|
||||
|
||||
this.match = function closeDocChecker_match(aEvent)
|
||||
@ -56,8 +57,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
gA11yEventDumpToConsole = true;
|
||||
|
||||
var gQueue = null;
|
||||
function doTest()
|
||||
{
|
||||
@ -89,6 +88,7 @@ gA11yEventDumpToConsole = true;
|
||||
// a: traversed state
|
||||
gQueue = new eventQueue();
|
||||
gQueue.push(new clickLink("link_traversed"));
|
||||
gQueue.onFinish = function() { gLinkWindow.close(); }
|
||||
gQueue.invoke(); // will call SimpleTest.finsih();
|
||||
}
|
||||
|
||||
|
@ -587,3 +587,7 @@ pref("general.useragent.override.facebook.com", "\(Mobile#(Android; Mobile");
|
||||
pref("general.useragent.override.youtube.com", "\(Mobile#(Android; Mobile");
|
||||
|
||||
pref("jsloader.reuseGlobal", true);
|
||||
|
||||
// Enable freeing dirty pages when minimizing memory; this reduces memory
|
||||
// consumption when applications are sent to the background.
|
||||
pref("memory.free_dirty_pages", true);
|
||||
|
@ -5329,11 +5329,7 @@ function contentAreaClick(event, isPanelClick)
|
||||
return;
|
||||
}
|
||||
|
||||
let postData = {};
|
||||
let url = getShortcutOrURI(href, postData);
|
||||
if (!url)
|
||||
return;
|
||||
loadURI(url, null, postData.value, false);
|
||||
loadURI(href, null, null, false);
|
||||
event.preventDefault();
|
||||
return;
|
||||
}
|
||||
|
@ -113,7 +113,7 @@ let gTests = [
|
||||
clean: function() {},
|
||||
event: {},
|
||||
targets: [ "panellink" ],
|
||||
expectedInvokedMethods: [ "urlSecurityCheck", "getShortcutOrURI", "loadURI" ],
|
||||
expectedInvokedMethods: [ "urlSecurityCheck", "loadURI" ],
|
||||
preventDefault: true,
|
||||
},
|
||||
|
||||
|
@ -337,9 +337,9 @@ Preferences.prototype = {
|
||||
this._set("WebKitDefaultTextEncodingName", "intl.charset.default",
|
||||
function(webkitCharset) {
|
||||
// We don't support x-mac-korean (see bug 713516), but it mostly matches
|
||||
// x-windows-949.
|
||||
// EUC-KR.
|
||||
if (webkitCharset == "x-mac-korean")
|
||||
return "x-windows-949";
|
||||
return "EUC-KR";
|
||||
|
||||
// getCharsetAlias throws if an invalid value is passed in.
|
||||
try {
|
||||
|
@ -28,6 +28,7 @@ MOCHITEST_BROWSER_FILES = \
|
||||
browser_privatebrowsing_localStorage_page1.html \
|
||||
browser_privatebrowsing_localStorage_page2.html \
|
||||
browser_privatebrowsing_opendir.js \
|
||||
browser_privatebrowsing_openlocation.js \
|
||||
browser_privatebrowsing_theming.js \
|
||||
browser_privatebrowsing_zoomrestore.js \
|
||||
$(NULL)
|
||||
|
@ -0,0 +1,97 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
// This test makes sure that Open Location dialog is usable inside the private browsing
|
||||
// mode without leaving any trace of the URLs visited.
|
||||
|
||||
function test() {
|
||||
// initialization
|
||||
waitForExplicitFinish();
|
||||
|
||||
function openLocation(aWindow, url, autofilled, callback) {
|
||||
function observer(aSubject, aTopic, aData) {
|
||||
switch (aTopic) {
|
||||
case "domwindowopened":
|
||||
let dialog = aSubject.QueryInterface(Ci.nsIDOMWindow);
|
||||
dialog.addEventListener("load", function () {
|
||||
dialog.removeEventListener("load", arguments.callee, false);
|
||||
|
||||
let browser = aWindow.gBrowser.selectedBrowser;
|
||||
browser.addEventListener("load", function() {
|
||||
browser.removeEventListener("load", arguments.callee, true);
|
||||
|
||||
is(browser.currentURI.spec, url,
|
||||
"The correct URL should be loaded via the open location dialog");
|
||||
executeSoon(callback);
|
||||
}, true);
|
||||
|
||||
SimpleTest.waitForFocus(function() {
|
||||
let input = dialog.document.getElementById("dialog.input");
|
||||
is(input.value, autofilled, "The input field should be correctly auto-filled");
|
||||
input.focus();
|
||||
for (let i = 0; i < url.length; ++i)
|
||||
EventUtils.synthesizeKey(url[i], {}, dialog);
|
||||
EventUtils.synthesizeKey("VK_RETURN", {}, dialog);
|
||||
}, dialog);
|
||||
}, false);
|
||||
break;
|
||||
|
||||
case "domwindowclosed":
|
||||
Services.ww.unregisterNotification(arguments.callee);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
executeSoon(function() {
|
||||
Services.ww.registerNotification(observer);
|
||||
gPrefService.setIntPref("general.open_location.last_window_choice", 0);
|
||||
aWindow.openDialog("chrome://browser/content/openLocation.xul", "_blank",
|
||||
"chrome,titlebar", aWindow);
|
||||
});
|
||||
}
|
||||
|
||||
let windowsToClose = [];
|
||||
function testOnWindow(options, callback) {
|
||||
let win = OpenBrowserWindow(options);
|
||||
win.addEventListener("load", function onLoad() {
|
||||
win.removeEventListener("load", onLoad, false);
|
||||
windowsToClose.push(win);
|
||||
callback(win);
|
||||
}, false);
|
||||
};
|
||||
|
||||
registerCleanupFunction(function() {
|
||||
windowsToClose.forEach(function(win) {
|
||||
win.close();
|
||||
});
|
||||
});
|
||||
|
||||
if (gPrefService.prefHasUserValue("general.open_location.last_url"))
|
||||
gPrefService.clearUserPref("general.open_location.last_url");
|
||||
|
||||
testOnWindow({private: false}, function(win) {
|
||||
openLocation(win, "http://example.com/", "", function() {
|
||||
testOnWindow({private: false}, function(win) {
|
||||
openLocation(win, "http://example.org/", "http://example.com/", function() {
|
||||
testOnWindow({private: true}, function(win) {
|
||||
openLocation(win, "about:logo", "", function() {
|
||||
testOnWindow({private: true}, function(win) {
|
||||
openLocation(win, "about:buildconfig", "about:logo", function() {
|
||||
testOnWindow({private: false}, function(win) {
|
||||
openLocation(win, "about:blank", "http://example.org/", function() {
|
||||
gPrefService.clearUserPref("general.open_location.last_url");
|
||||
if (gPrefService.prefHasUserValue("general.open_location.last_window_choice"))
|
||||
gPrefService.clearUserPref("general.open_location.last_window_choice");
|
||||
finish();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
@ -79,6 +79,7 @@ Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/debug.js");
|
||||
Cu.import("resource:///modules/TelemetryTimestamps.jsm");
|
||||
Cu.import("resource://gre/modules/TelemetryStopwatch.jsm");
|
||||
Cu.import("resource://gre/modules/osfile.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "NetUtil",
|
||||
"resource://gre/modules/NetUtil.jsm");
|
||||
@ -441,9 +442,18 @@ let SessionStoreInternal = {
|
||||
this._prefBranch.getBoolPref("sessionstore.resume_session_once"))
|
||||
this._prefBranch.setBoolPref("sessionstore.resume_session_once", false);
|
||||
|
||||
this._initEncoding();
|
||||
|
||||
this._initialized = true;
|
||||
},
|
||||
|
||||
_initEncoding : function ssi_initEncoding() {
|
||||
// The (UTF-8) encoder used to write to files.
|
||||
XPCOMUtils.defineLazyGetter(this, "_writeFileEncoder", function () {
|
||||
return new TextEncoder();
|
||||
});
|
||||
},
|
||||
|
||||
_initPrefs : function() {
|
||||
XPCOMUtils.defineLazyGetter(this, "_prefBranch", function () {
|
||||
return Services.prefs.getBranch("browser.");
|
||||
@ -4435,27 +4445,21 @@ let SessionStoreInternal = {
|
||||
_writeFile: function ssi_writeFile(aFile, aData) {
|
||||
let refObj = {};
|
||||
TelemetryStopwatch.start("FX_SESSION_RESTORE_WRITE_FILE_MS", refObj);
|
||||
// Initialize the file output stream.
|
||||
var ostream = Cc["@mozilla.org/network/safe-file-output-stream;1"].
|
||||
createInstance(Ci.nsIFileOutputStream);
|
||||
ostream.init(aFile, 0x02 | 0x08 | 0x20, 0600, ostream.DEFER_OPEN);
|
||||
let path = aFile.path;
|
||||
let encoded = this._writeFileEncoder.encode(aData);
|
||||
let promise = OS.File.writeAtomic(path, encoded, {tmpPath: path + ".tmp"});
|
||||
|
||||
// Obtain a converter to convert our data to a UTF-8 encoded input stream.
|
||||
var converter = Cc["@mozilla.org/intl/scriptableunicodeconverter"].
|
||||
createInstance(Ci.nsIScriptableUnicodeConverter);
|
||||
converter.charset = "UTF-8";
|
||||
|
||||
// Asynchronously copy the data to the file.
|
||||
var istream = converter.convertToInputStream(aData);
|
||||
var self = this;
|
||||
NetUtil.asyncCopy(istream, ostream, function(rc) {
|
||||
if (Components.isSuccessCode(rc)) {
|
||||
promise.then(
|
||||
function onSuccess() {
|
||||
TelemetryStopwatch.finish("FX_SESSION_RESTORE_WRITE_FILE_MS", refObj);
|
||||
Services.obs.notifyObservers(null,
|
||||
"sessionstore-state-write-complete",
|
||||
"");
|
||||
}
|
||||
});
|
||||
"sessionstore-state-write-complete",
|
||||
"");
|
||||
},
|
||||
function onFailure(reason) {
|
||||
TelemetryStopwatch.cancel("FX_SESSION_RESTORE_WRITE_FILE_MS", refObj);
|
||||
Components.reportError("ssi_writeFile failure " + reason);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -35,7 +35,7 @@
|
||||
!define BETA_UPDATE_CHANNEL
|
||||
!endif
|
||||
|
||||
!define BaseURLStubPing "http://download-stats.mozilla.org/stub/v1/"
|
||||
!define BaseURLStubPing "http://download-stats.mozilla.org/stub/v2/"
|
||||
|
||||
# NO_INSTDIR_FROM_REG is defined for pre-releases which have a PreReleaseSuffix
|
||||
# (e.g. Alpha X, Beta X, etc.) to prevent finding a non-default installation
|
||||
|
@ -68,6 +68,7 @@ Var TmpVal
|
||||
Var InstallCounterStep
|
||||
|
||||
Var ExitCode
|
||||
Var DownloadStartTime
|
||||
Var SecondsToDownload
|
||||
Var ExistingProfile
|
||||
Var ExistingInstall
|
||||
@ -892,7 +893,7 @@ Function createInstall
|
||||
System::Int64Op $1 * 0x100000000
|
||||
Pop $1
|
||||
System::Int64Op $1 + $0
|
||||
Pop $SecondsToDownload
|
||||
Pop $DownloadStartTime
|
||||
|
||||
${NSD_CreateTimer} StartDownload ${DownloadIntervalMS}
|
||||
|
||||
@ -910,10 +911,8 @@ Function leaveInstall
|
||||
# Need a ping?
|
||||
FunctionEnd
|
||||
|
||||
; This function is not idempotent. It calculates the amount of time between now
|
||||
; and $SecondsToDownload and stores the results back into $SecondsToDownload.
|
||||
; For that reason it should only be called once for the purpose of determining
|
||||
; the number of elapsed seconds to download.
|
||||
; GetSecondsToDownload calculates the amount of time between $DownloadStartTime
|
||||
; and now, and stores the results into $SecondsToDownload.
|
||||
Function GetSecondsToDownload
|
||||
GetTempFileName $2
|
||||
GetFileTime $2 $1 $0
|
||||
@ -922,9 +921,9 @@ Function GetSecondsToDownload
|
||||
Pop $1
|
||||
System::Int64Op $1 + $0
|
||||
Pop $0
|
||||
System::Int64Op $0 - $SecondsToDownload
|
||||
Pop $SecondsToDownload
|
||||
System::Int64Op $SecondsToDownload / 10000000
|
||||
System::Int64Op $0 - $DownloadStartTime
|
||||
Pop $4
|
||||
System::Int64Op $4 / 10000000
|
||||
Pop $SecondsToDownload
|
||||
FunctionEnd
|
||||
|
||||
|
@ -262,7 +262,8 @@ toolbar[iconsize="large"] #downloads-indicator-icon {
|
||||
-moz-appearance: none;
|
||||
min-width: 0;
|
||||
min-height: 0;
|
||||
background-image: -moz-linear-gradient(#5ab9ff, #37a4ff);
|
||||
background-color: rgb(90, 185, 255);
|
||||
background-image: linear-gradient(transparent 1px, rgba(255, 255, 255, 0.4) 1px, rgba(255, 255, 255, 0.4) 2px, transparent 2px);
|
||||
border: 1px solid;
|
||||
border-color: rgba(0,43,86,.6) rgba(0,43,86,.4) rgba(0,43,86,.4);
|
||||
border-radius: 2px 0 0 2px;
|
||||
@ -280,7 +281,7 @@ toolbar[iconsize="large"] #downloads-indicator-icon {
|
||||
}
|
||||
|
||||
#downloads-indicator[paused] > #downloads-indicator-anchor > #downloads-indicator-progress-area > #downloads-indicator-progress > .progress-bar {
|
||||
background-image: -moz-linear-gradient(#dce651, #dae631);
|
||||
background-color: rgb(220, 230, 81);
|
||||
}
|
||||
|
||||
#downloads-indicator[paused] > #downloads-indicator-anchor > #downloads-indicator-progress-area > #downloads-indicator-progress > .progress-remainder {
|
||||
|
@ -260,7 +260,8 @@ richlistitem[type="download"][state="1"]:hover > .downloadButton.downloadShow:ac
|
||||
-moz-appearance: none;
|
||||
min-width: 0;
|
||||
min-height: 0;
|
||||
background-image: -moz-linear-gradient(#5ab9ff, #37a4ff);
|
||||
background-color: rgb(90, 185, 255);
|
||||
background-image: linear-gradient(transparent 1px, rgba(255, 255, 255, 0.4) 1px, rgba(255, 255, 255, 0.4) 2px, transparent 2px);
|
||||
border: 1px solid;
|
||||
border-color: rgba(0,43,86,.6) rgba(0,43,86,.4) rgba(0,43,86,.4);
|
||||
border-radius: 2px 0 0 2px;
|
||||
@ -278,7 +279,7 @@ richlistitem[type="download"][state="1"]:hover > .downloadButton.downloadShow:ac
|
||||
}
|
||||
|
||||
#downloads-indicator[paused] > #downloads-indicator-anchor > #downloads-indicator-progress-area > #downloads-indicator-progress > .progress-bar {
|
||||
background-image: -moz-linear-gradient(#dce651, #dae631);
|
||||
background-color: rgb(220, 230, 81);
|
||||
}
|
||||
|
||||
#downloads-indicator[paused] > #downloads-indicator-anchor > #downloads-indicator-progress-area > #downloads-indicator-progress > .progress-remainder {
|
||||
|
@ -259,7 +259,8 @@ richlistitem[type="download"][state="1"]:hover > .downloadButton.downloadShow:ac
|
||||
-moz-appearance: none;
|
||||
min-width: 0;
|
||||
min-height: 0;
|
||||
background-image: -moz-linear-gradient(#5ab9ff, #37a4ff);
|
||||
background-color: rgb(90, 185, 255);
|
||||
background-image: linear-gradient(transparent 1px, rgba(255, 255, 255, 0.4) 1px, rgba(255, 255, 255, 0.4) 2px, transparent 2px);
|
||||
border: 1px solid;
|
||||
border-color: rgba(0,43,86,.6) rgba(0,43,86,.4) rgba(0,43,86,.4);
|
||||
border-radius: 2px 0 0 2px;
|
||||
@ -277,7 +278,7 @@ richlistitem[type="download"][state="1"]:hover > .downloadButton.downloadShow:ac
|
||||
}
|
||||
|
||||
#downloads-indicator[paused] > #downloads-indicator-anchor > #downloads-indicator-progress-area > #downloads-indicator-progress > .progress-bar {
|
||||
background-image: -moz-linear-gradient(#dce651, #dae631);
|
||||
background-color: rgb(220, 230, 81);
|
||||
}
|
||||
|
||||
#downloads-indicator[paused] > #downloads-indicator-anchor > #downloads-indicator-progress-area > #downloads-indicator-progress > .progress-remainder {
|
||||
|
@ -62,6 +62,7 @@ xpcshell-tests-remote:
|
||||
$(topsrcdir)/testing/xpcshell/remotexpcshelltests.py \
|
||||
--symbols-path=$(DIST)/crashreporter-symbols \
|
||||
--build-info-json=$(DEPTH)/mozinfo.json \
|
||||
--testing-modules-dir=$(DEPTH)/_tests/modules \
|
||||
$(EXTRA_TEST_ARGS) \
|
||||
--dm_trans=$(DM_TRANS) \
|
||||
--deviceIP=${TEST_DEVICE} \
|
||||
@ -112,6 +113,7 @@ check-one-remote:
|
||||
--symbols-path=$(DIST)/crashreporter-symbols \
|
||||
--build-info-json=$(DEPTH)/mozinfo.json \
|
||||
--test-path=$(SOLO_FILE) \
|
||||
--testing-modules-dir=$(DEPTH)/_tests/modules \
|
||||
--profile-name=$(MOZ_APP_NAME) \
|
||||
--verbose \
|
||||
$(EXTRA_TEST_ARGS) \
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -11,9 +11,8 @@
|
||||
#include "mozilla/RefPtr.h"
|
||||
#include "nsColor.h"
|
||||
#include "nsHTMLCanvasElement.h"
|
||||
#include "CanvasUtils.h"
|
||||
#include "nsHTMLImageElement.h"
|
||||
#include "nsHTMLVideoElement.h"
|
||||
#include "CanvasUtils.h"
|
||||
#include "gfxFont.h"
|
||||
#include "mozilla/ErrorResult.h"
|
||||
#include "mozilla/dom/ImageData.h"
|
||||
@ -24,6 +23,8 @@
|
||||
#define NS_CANVASPATTERNAZURE_PRIVATE_IID \
|
||||
{0xc9bacc25, 0x28da, 0x421e, {0x9a, 0x4b, 0xbb, 0xd6, 0x93, 0x05, 0x12, 0xbc}}
|
||||
|
||||
class nsIDOMXULElement;
|
||||
|
||||
namespace mozilla {
|
||||
namespace gfx {
|
||||
struct Rect;
|
||||
@ -127,7 +128,6 @@ class CanvasRenderingContext2DUserData;
|
||||
** CanvasRenderingContext2D
|
||||
**/
|
||||
class CanvasRenderingContext2D :
|
||||
public nsIDOMCanvasRenderingContext2D,
|
||||
public nsICanvasRenderingContextInternal,
|
||||
public nsWrapperCache
|
||||
{
|
||||
@ -428,8 +428,7 @@ public:
|
||||
{
|
||||
return CurrentState().dashOffset;
|
||||
}
|
||||
|
||||
void SetMozDashOffset(double mozDashOffset, mozilla::ErrorResult& error);
|
||||
void SetMozDashOffset(double mozDashOffset);
|
||||
|
||||
void GetMozTextStyle(nsAString& mozTextStyle)
|
||||
{
|
||||
@ -496,11 +495,13 @@ public:
|
||||
// nsISupports interface + CC
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
|
||||
NS_DECL_CYCLE_COLLECTION_SKIPPABLE_SCRIPT_HOLDER_CLASS_AMBIGUOUS(CanvasRenderingContext2D,
|
||||
nsIDOMCanvasRenderingContext2D)
|
||||
NS_DECL_CYCLE_COLLECTION_SKIPPABLE_SCRIPT_HOLDER_CLASS(CanvasRenderingContext2D)
|
||||
|
||||
// nsIDOMCanvasRenderingContext2D interface
|
||||
NS_DECL_NSIDOMCANVASRENDERINGCONTEXT2D
|
||||
enum CanvasMultiGetterType {
|
||||
CMG_STYLE_STRING = 0,
|
||||
CMG_STYLE_PATTERN = 1,
|
||||
CMG_STYLE_GRADIENT = 2
|
||||
};
|
||||
|
||||
enum Style {
|
||||
STYLE_STROKE = 0,
|
||||
@ -543,6 +544,11 @@ protected:
|
||||
uint32_t aWidth, uint32_t aHeight,
|
||||
JSObject** aRetval);
|
||||
|
||||
nsresult PutImageData_explicit(int32_t x, int32_t y, uint32_t w, uint32_t h,
|
||||
unsigned char *aData, uint32_t aDataLen,
|
||||
bool hasDirtyRect, int32_t dirtyX, int32_t dirtyY,
|
||||
int32_t dirtyWidth, int32_t dirtyHeight);
|
||||
|
||||
/**
|
||||
* Internal method to complete initialisation, expects mTarget to have been set
|
||||
*/
|
||||
@ -583,7 +589,6 @@ protected:
|
||||
CurrentState().SetPatternStyle(whichStyle, pattern);
|
||||
}
|
||||
|
||||
void SetStyleFromStringOrInterface(const nsAString& aStr, nsISupports *aInterface, Style aWhichStyle);
|
||||
nsISupports* GetStyleAsStringOrInterface(nsAString& aStr, CanvasMultiGetterType& aType, Style aWhichStyle);
|
||||
|
||||
// Returns whether a color was successfully parsed.
|
||||
@ -664,32 +669,6 @@ protected:
|
||||
return CurrentState().font;
|
||||
}
|
||||
|
||||
static bool
|
||||
ToHTMLImageOrCanvasOrVideoElement(nsIDOMElement* html,
|
||||
HTMLImageOrCanvasOrVideoElement& element)
|
||||
{
|
||||
nsCOMPtr<nsIContent> content = do_QueryInterface(html);
|
||||
if (content) {
|
||||
if (content->IsHTML(nsGkAtoms::canvas)) {
|
||||
element.SetAsHTMLCanvasElement() =
|
||||
static_cast<nsHTMLCanvasElement*>(html);
|
||||
return true;
|
||||
}
|
||||
if (content->IsHTML(nsGkAtoms::img)) {
|
||||
element.SetAsHTMLImageElement() =
|
||||
static_cast<nsHTMLImageElement*>(html);
|
||||
return true;
|
||||
}
|
||||
if (content->IsHTML(nsGkAtoms::video)) {
|
||||
element.SetAsHTMLVideoElement() =
|
||||
static_cast<nsHTMLVideoElement*>(html);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Member vars
|
||||
int32_t mWidth, mHeight;
|
||||
|
||||
|
@ -19,6 +19,7 @@ LIBXUL_LIBRARY = 1
|
||||
EXPORTS_NAMESPACES = mozilla/dom
|
||||
|
||||
EXPORTS_mozilla/dom = \
|
||||
CanvasUtils.h \
|
||||
CanvasRenderingContext2D.h \
|
||||
ImageData.h \
|
||||
$(NULL)
|
||||
|
@ -60,6 +60,7 @@ MOCHITEST_FILES = \
|
||||
test_bug764125.html \
|
||||
test_drawImage_edge_cases.html \
|
||||
test_drawImage_document_domain.html \
|
||||
test_mozDashOffset.html \
|
||||
file_drawImage_document_domain.html \
|
||||
$(NULL)
|
||||
|
||||
|
39
content/canvas/test/test_mozDashOffset.html
Normal file
39
content/canvas/test/test_mozDashOffset.html
Normal file
@ -0,0 +1,39 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test for mozDashOffset</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<p id="display">
|
||||
<canvas id="c" width="100" height="100"><p class="fallback">FAIL (fallback content)</p></canvas>
|
||||
</p>
|
||||
<div id="content" style="display: none">
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script>
|
||||
try {
|
||||
var canvas = document.getElementById('c');
|
||||
var ctx = canvas.getContext('2d');
|
||||
|
||||
ctx.mozDash = [1, 1];
|
||||
|
||||
ctx.mozDashOffset = 1;
|
||||
ctx.mozDashOffset = Infinity;
|
||||
ok(ctx.mozDashOffset === 1, "ctx.mozDashOffset === 1");
|
||||
|
||||
ctx.mozDashOffset = 1;
|
||||
ctx.mozDashOffset = -Infinity;
|
||||
ok(ctx.mozDashOffset === 1, "ctx.mozDashOffset === 1");
|
||||
|
||||
ctx.mozDashOffset = 1;
|
||||
ctx.mozDashOffset = NaN;
|
||||
ok(ctx.mozDashOffset === 1, "ctx.mozDashOffset === 1");
|
||||
} catch(e) {
|
||||
ok(false, "unexpected exception thrown in: test_mozDashOffset.html");
|
||||
}
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
@ -107,6 +107,7 @@ function runTest(videoElement)
|
||||
runOneIteration(videoElement, true, false, green, red);
|
||||
|
||||
glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors");
|
||||
videoElement.removeEventListener("playing", runTest);
|
||||
finishTest();
|
||||
}
|
||||
</script>
|
||||
|
@ -139,6 +139,7 @@ function runTest(videoElement)
|
||||
runOneIteration(videoElement, true, false, red, green, false, false, false);
|
||||
|
||||
glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors");
|
||||
videoElement.removeEventListener("playing", runTest);
|
||||
finishTest();
|
||||
}
|
||||
</script>
|
||||
|
@ -775,6 +775,8 @@ nsTextStateManager::Destroy(void)
|
||||
false, false))->RunDOMEventWhenSafe();
|
||||
}
|
||||
mWidget->OnIMEFocusChange(false);
|
||||
// Even if there are some pending notification, it'll never notify the widget.
|
||||
mWidget = nullptr;
|
||||
if (mObserving && mSel) {
|
||||
nsCOMPtr<nsISelectionPrivate> selPrivate(do_QueryInterface(mSel));
|
||||
if (selPrivate)
|
||||
@ -786,7 +788,6 @@ nsTextStateManager::Destroy(void)
|
||||
}
|
||||
mRootContent = nullptr;
|
||||
mEditableNode = nullptr;
|
||||
mWidget = nullptr;
|
||||
mObserving = false;
|
||||
}
|
||||
|
||||
@ -811,21 +812,21 @@ NS_IMPL_ISUPPORTS2(nsTextStateManager,
|
||||
// Helper class, used for selection change notification
|
||||
class SelectionChangeEvent : public nsRunnable {
|
||||
public:
|
||||
SelectionChangeEvent(nsIWidget *widget)
|
||||
: mWidget(widget)
|
||||
SelectionChangeEvent(nsTextStateManager *aDispatcher)
|
||||
: mDispatcher(aDispatcher)
|
||||
{
|
||||
MOZ_ASSERT(mWidget);
|
||||
MOZ_ASSERT(mDispatcher);
|
||||
}
|
||||
|
||||
NS_IMETHOD Run() {
|
||||
if(mWidget) {
|
||||
mWidget->OnIMESelectionChange();
|
||||
if (mDispatcher->mWidget) {
|
||||
mDispatcher->mWidget->OnIMESelectionChange();
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
nsCOMPtr<nsIWidget> mWidget;
|
||||
nsRefPtr<nsTextStateManager> mDispatcher;
|
||||
};
|
||||
|
||||
nsresult
|
||||
@ -837,7 +838,7 @@ nsTextStateManager::NotifySelectionChanged(nsIDOMDocument* aDoc,
|
||||
nsresult rv = aSel->GetRangeCount(&count);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (count > 0 && mWidget) {
|
||||
nsContentUtils::AddScriptRunner(new SelectionChangeEvent(mWidget));
|
||||
nsContentUtils::AddScriptRunner(new SelectionChangeEvent(this));
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
@ -845,25 +846,25 @@ nsTextStateManager::NotifySelectionChanged(nsIDOMDocument* aDoc,
|
||||
// Helper class, used for text change notification
|
||||
class TextChangeEvent : public nsRunnable {
|
||||
public:
|
||||
TextChangeEvent(nsIWidget *widget,
|
||||
TextChangeEvent(nsTextStateManager* aDispatcher,
|
||||
uint32_t start, uint32_t oldEnd, uint32_t newEnd)
|
||||
: mWidget(widget)
|
||||
: mDispatcher(aDispatcher)
|
||||
, mStart(start)
|
||||
, mOldEnd(oldEnd)
|
||||
, mNewEnd(newEnd)
|
||||
{
|
||||
MOZ_ASSERT(mWidget);
|
||||
MOZ_ASSERT(mDispatcher);
|
||||
}
|
||||
|
||||
NS_IMETHOD Run() {
|
||||
if(mWidget) {
|
||||
mWidget->OnIMETextChange(mStart, mOldEnd, mNewEnd);
|
||||
if (mDispatcher->mWidget) {
|
||||
mDispatcher->mWidget->OnIMETextChange(mStart, mOldEnd, mNewEnd);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
nsCOMPtr<nsIWidget> mWidget;
|
||||
nsRefPtr<nsTextStateManager> mDispatcher;
|
||||
uint32_t mStart, mOldEnd, mNewEnd;
|
||||
};
|
||||
|
||||
@ -885,7 +886,7 @@ nsTextStateManager::CharacterDataChanged(nsIDocument* aDocument,
|
||||
uint32_t newEnd = offset + aInfo->mReplaceLength;
|
||||
|
||||
nsContentUtils::AddScriptRunner(
|
||||
new TextChangeEvent(mWidget, offset, oldEnd, newEnd));
|
||||
new TextChangeEvent(this, offset, oldEnd, newEnd));
|
||||
}
|
||||
|
||||
void
|
||||
@ -907,7 +908,7 @@ nsTextStateManager::NotifyContentAdded(nsINode* aContainer,
|
||||
// fire notification
|
||||
if (newOffset)
|
||||
nsContentUtils::AddScriptRunner(
|
||||
new TextChangeEvent(mWidget, offset, offset, offset + newOffset));
|
||||
new TextChangeEvent(this, offset, offset, offset + newOffset));
|
||||
}
|
||||
|
||||
void
|
||||
@ -956,7 +957,7 @@ nsTextStateManager::ContentRemoved(nsIDocument* aDocument,
|
||||
// fire notification
|
||||
if (childOffset)
|
||||
nsContentUtils::AddScriptRunner(
|
||||
new TextChangeEvent(mWidget, offset, offset + childOffset, offset));
|
||||
new TextChangeEvent(this, offset, offset + childOffset, offset));
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include "nsDOMMediaStream.h"
|
||||
#include "mozilla/Mutex.h"
|
||||
#include "nsTimeRanges.h"
|
||||
#include "nsIDOMWakeLock.h"
|
||||
|
||||
// Define to output information on decoding and painting framerate
|
||||
/* #define DEBUG_FRAME_RATE 1 */
|
||||
@ -388,6 +389,19 @@ protected:
|
||||
class MediaLoadListener;
|
||||
class StreamListener;
|
||||
|
||||
class WakeLockBoolWrapper {
|
||||
public:
|
||||
WakeLockBoolWrapper(bool val = false) : mValue(val), mOuter(NULL), mWakeLock(NULL) {}
|
||||
void SetOuter(nsHTMLMediaElement* outer) { mOuter = outer; }
|
||||
operator bool() { return mValue; }
|
||||
WakeLockBoolWrapper& operator=(bool val);
|
||||
bool operator !() const { return !mValue; }
|
||||
private:
|
||||
bool mValue;
|
||||
nsHTMLMediaElement* mOuter;
|
||||
nsCOMPtr<nsIDOMMozWakeLock> mWakeLock;
|
||||
};
|
||||
|
||||
/**
|
||||
* Logs a warning message to the web console to report various failures.
|
||||
* aMsg is the localized message identifier, aParams is the parameters to
|
||||
@ -814,7 +828,7 @@ protected:
|
||||
|
||||
// Playback of the video is paused either due to calling the
|
||||
// 'Pause' method, or playback not yet having started.
|
||||
bool mPaused;
|
||||
WakeLockBoolWrapper mPaused;
|
||||
|
||||
// True if the sound is muted.
|
||||
bool mMuted;
|
||||
|
@ -14,8 +14,7 @@
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsDOMFile.h"
|
||||
|
||||
#include "nsICanvasRenderingContextInternal.h"
|
||||
#include "nsIDOMCanvasRenderingContext2D.h"
|
||||
#include "mozilla/dom/CanvasRenderingContext2D.h"
|
||||
#include "nsIScriptSecurityManager.h"
|
||||
#include "nsIXPConnect.h"
|
||||
#include "jsapi.h"
|
||||
@ -43,6 +42,9 @@ using namespace mozilla::layers;
|
||||
|
||||
namespace {
|
||||
|
||||
typedef mozilla::dom::HTMLImageElementOrHTMLCanvasElementOrHTMLVideoElement
|
||||
HTMLImageOrCanvasOrVideoElement;
|
||||
|
||||
class ToBlobRunnable : public nsRunnable
|
||||
{
|
||||
public:
|
||||
@ -311,7 +313,6 @@ nsHTMLCanvasElement::GetOriginalCanvas()
|
||||
return mOriginalCanvas ? mOriginalCanvas.get() : this;
|
||||
}
|
||||
|
||||
|
||||
nsresult
|
||||
nsHTMLCanvasElement::CopyInnerTo(nsGenericElement* aDest)
|
||||
{
|
||||
@ -322,12 +323,17 @@ nsHTMLCanvasElement::CopyInnerTo(nsGenericElement* aDest)
|
||||
nsHTMLCanvasElement* self = const_cast<nsHTMLCanvasElement*>(this);
|
||||
dest->mOriginalCanvas = self;
|
||||
|
||||
HTMLImageOrCanvasOrVideoElement element;
|
||||
element.SetAsHTMLCanvasElement() = this;
|
||||
nsCOMPtr<nsISupports> cxt;
|
||||
dest->GetContext(NS_LITERAL_STRING("2d"), JSVAL_VOID, getter_AddRefs(cxt));
|
||||
nsCOMPtr<nsIDOMCanvasRenderingContext2D> context2d = do_QueryInterface(cxt);
|
||||
nsRefPtr<CanvasRenderingContext2D> context2d =
|
||||
static_cast<CanvasRenderingContext2D*>(cxt.get());
|
||||
if (context2d && !self->mPrintCallback) {
|
||||
context2d->DrawImage(self,
|
||||
0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0);
|
||||
ErrorResult err;
|
||||
context2d->DrawImage(element,
|
||||
0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, err);
|
||||
rv = err.ErrorCode();
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
@ -691,6 +697,16 @@ nsHTMLCanvasElement::GetContextHelper(const nsAString& aContextId,
|
||||
{
|
||||
NS_ENSURE_ARG(aContext);
|
||||
|
||||
if (aContextId.EqualsLiteral("2d")) {
|
||||
Telemetry::Accumulate(Telemetry::CANVAS_2D_USED, 1);
|
||||
nsRefPtr<CanvasRenderingContext2D> ctx =
|
||||
new CanvasRenderingContext2D();
|
||||
|
||||
ctx->SetCanvasElement(this);
|
||||
ctx.forget(aContext);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_ConvertUTF16toUTF8 ctxId(aContextId);
|
||||
|
||||
// check that ctxId is clamped to A-Za-z0-9_-
|
||||
|
@ -70,6 +70,7 @@
|
||||
#include "nsIMediaList.h"
|
||||
|
||||
#include "ImageContainer.h"
|
||||
#include "nsIPowerManagerService.h"
|
||||
|
||||
#ifdef MOZ_OGG
|
||||
#include "nsOggDecoder.h"
|
||||
@ -1747,6 +1748,8 @@ nsHTMLMediaElement::nsHTMLMediaElement(already_AddRefed<nsINodeInfo> aNodeInfo)
|
||||
}
|
||||
#endif
|
||||
|
||||
mPaused.SetOuter(this);
|
||||
|
||||
RegisterFreezableElement();
|
||||
NotifyOwnerDocumentActivityChanged();
|
||||
}
|
||||
@ -1869,6 +1872,23 @@ NS_IMETHODIMP nsHTMLMediaElement::Play()
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsHTMLMediaElement::WakeLockBoolWrapper& nsHTMLMediaElement::WakeLockBoolWrapper::operator=(bool val) {
|
||||
if (mValue == val)
|
||||
return *this;
|
||||
if (!mWakeLock && !val && mOuter) {
|
||||
nsCOMPtr<nsIPowerManagerService> pmService =
|
||||
do_GetService(POWERMANAGERSERVICE_CONTRACTID);
|
||||
NS_ENSURE_TRUE(pmService, *this);
|
||||
|
||||
pmService->NewWakeLock(NS_LITERAL_STRING("Playing_media"), mOuter->OwnerDoc()->GetWindow(), getter_AddRefs(mWakeLock));
|
||||
} else if (mWakeLock && val) {
|
||||
mWakeLock->Unlock();
|
||||
mWakeLock = NULL;
|
||||
}
|
||||
mValue = val;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool nsHTMLMediaElement::ParseAttribute(int32_t aNamespaceID,
|
||||
nsIAtom* aAttribute,
|
||||
const nsAString& aValue,
|
||||
|
@ -730,7 +730,6 @@ nsDocShell::nsDocShell():
|
||||
mCharsetReloadState(eCharsetReloadInit),
|
||||
mChildOffset(0),
|
||||
mBusyFlags(BUSY_FLAGS_NONE),
|
||||
mFrameType(eFrameTypeRegular),
|
||||
mAppType(nsIDocShell::APP_TYPE_UNKNOWN),
|
||||
mLoadType(0),
|
||||
mMarginWidth(-1),
|
||||
@ -768,6 +767,7 @@ nsDocShell::nsDocShell():
|
||||
#ifdef DEBUG
|
||||
mInEnsureScriptEnv(false),
|
||||
#endif
|
||||
mFrameType(eFrameTypeRegular),
|
||||
mOwnOrContainingAppId(nsIScriptSecurityManager::UNKNOWN_APP_ID),
|
||||
mParentCharsetSource(0)
|
||||
{
|
||||
|
@ -21,7 +21,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=454235
|
||||
/** Test for Bug 454235 **/
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
addLoadEvent(doTest);
|
||||
SimpleTest.waitForFocus(doTest);
|
||||
|
||||
function doTest() {
|
||||
var shownBrowser = document.getElementById("shownBrowser");
|
||||
|
@ -25,11 +25,13 @@ nsContentPermissionRequestProxy::~nsContentPermissionRequestProxy()
|
||||
|
||||
nsresult
|
||||
nsContentPermissionRequestProxy::Init(const nsACString & type,
|
||||
const nsACString & access,
|
||||
ContentPermissionRequestParent* parent)
|
||||
{
|
||||
NS_ASSERTION(parent, "null parent");
|
||||
mParent = parent;
|
||||
mType = type;
|
||||
mAccess = access;
|
||||
|
||||
nsCOMPtr<nsIContentPermissionPrompt> prompt = do_CreateInstance(NS_CONTENT_PERMISSION_PROMPT_CONTRACTID);
|
||||
if (!prompt) {
|
||||
@ -55,6 +57,13 @@ nsContentPermissionRequestProxy::GetType(nsACString & aType)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsContentPermissionRequestProxy::GetAccess(nsACString & aAccess)
|
||||
{
|
||||
aAccess = mAccess;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsContentPermissionRequestProxy::GetWindow(nsIDOMWindow * *aRequestingWindow)
|
||||
{
|
||||
@ -114,6 +123,7 @@ namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
ContentPermissionRequestParent::ContentPermissionRequestParent(const nsACString& aType,
|
||||
const nsACString& aAccess,
|
||||
nsIDOMElement *aElement,
|
||||
const IPC::Principal& aPrincipal)
|
||||
{
|
||||
@ -122,6 +132,7 @@ ContentPermissionRequestParent::ContentPermissionRequestParent(const nsACString&
|
||||
mPrincipal = aPrincipal;
|
||||
mElement = aElement;
|
||||
mType = aType;
|
||||
mAccess = aAccess;
|
||||
}
|
||||
|
||||
ContentPermissionRequestParent::~ContentPermissionRequestParent()
|
||||
@ -134,7 +145,7 @@ ContentPermissionRequestParent::Recvprompt()
|
||||
{
|
||||
mProxy = new nsContentPermissionRequestProxy();
|
||||
NS_ASSERTION(mProxy, "Alloc of request proxy failed");
|
||||
if (NS_FAILED(mProxy->Init(mType, this))) {
|
||||
if (NS_FAILED(mProxy->Init(mType, mAccess, this))) {
|
||||
mProxy->Cancel();
|
||||
}
|
||||
return true;
|
||||
|
@ -22,13 +22,14 @@ namespace dom {
|
||||
class ContentPermissionRequestParent : public PContentPermissionRequestParent
|
||||
{
|
||||
public:
|
||||
ContentPermissionRequestParent(const nsACString& type, nsIDOMElement *element, const IPC::Principal& principal);
|
||||
ContentPermissionRequestParent(const nsACString& type, const nsACString& access, nsIDOMElement *element, const IPC::Principal& principal);
|
||||
virtual ~ContentPermissionRequestParent();
|
||||
|
||||
nsCOMPtr<nsIPrincipal> mPrincipal;
|
||||
nsCOMPtr<nsIDOMElement> mElement;
|
||||
nsCOMPtr<nsContentPermissionRequestProxy> mProxy;
|
||||
nsCString mType;
|
||||
nsCString mAccess;
|
||||
|
||||
private:
|
||||
virtual bool Recvprompt();
|
||||
@ -44,7 +45,7 @@ class nsContentPermissionRequestProxy : public nsIContentPermissionRequest
|
||||
nsContentPermissionRequestProxy();
|
||||
virtual ~nsContentPermissionRequestProxy();
|
||||
|
||||
nsresult Init(const nsACString& type, mozilla::dom::ContentPermissionRequestParent* parent);
|
||||
nsresult Init(const nsACString& type, const nsACString& access, mozilla::dom::ContentPermissionRequestParent* parent);
|
||||
void OnParentDestroyed();
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
@ -54,6 +55,7 @@ class nsContentPermissionRequestProxy : public nsIContentPermissionRequest
|
||||
// Non-owning pointer to the ContentPermissionRequestParent object which owns this proxy.
|
||||
mozilla::dom::ContentPermissionRequestParent* mParent;
|
||||
nsCString mType;
|
||||
nsCString mAccess;
|
||||
};
|
||||
#endif // nsContentPermissionHelper_h
|
||||
|
||||
|
@ -1755,6 +1755,8 @@ nsFocusManager::Focus(nsPIDOMWindow* aWindow,
|
||||
// if switching to a new document, first fire the focus event on the
|
||||
// document and then the window.
|
||||
if (aIsNewDocument) {
|
||||
nsIMEStateManager::OnChangeFocus(presShell->GetPresContext(), nullptr,
|
||||
GetFocusMoveActionCause(aFlags));
|
||||
nsIDocument* doc = aWindow->GetExtantDoc();
|
||||
if (doc)
|
||||
SendFocusOrBlurEvent(NS_FOCUS_CONTENT, presShell, doc,
|
||||
|
@ -191,6 +191,14 @@ BluetoothOppManager::Connect(const nsAString& aDeviceObjectPath,
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
if (GetConnectionStatus() == SocketConnectionStatus::SOCKET_CONNECTED ||
|
||||
GetConnectionStatus() == SocketConnectionStatus::SOCKET_CONNECTING) {
|
||||
NS_WARNING("BluetoothOppManager has been already connected");
|
||||
return false;
|
||||
}
|
||||
|
||||
CloseSocket();
|
||||
|
||||
BluetoothService* bs = BluetoothService::Get();
|
||||
if (!bs) {
|
||||
NS_WARNING("BluetoothService not available!");
|
||||
@ -200,7 +208,7 @@ BluetoothOppManager::Connect(const nsAString& aDeviceObjectPath,
|
||||
nsString serviceUuidStr =
|
||||
NS_ConvertUTF8toUTF16(BluetoothServiceUuidStr::ObjectPush);
|
||||
|
||||
nsRefPtr<BluetoothReplyRunnable> runnable = aRunnable;
|
||||
mRunnable = aRunnable;
|
||||
|
||||
nsresult rv = bs->GetSocketViaService(aDeviceObjectPath,
|
||||
serviceUuidStr,
|
||||
@ -208,15 +216,19 @@ BluetoothOppManager::Connect(const nsAString& aDeviceObjectPath,
|
||||
true,
|
||||
true,
|
||||
this,
|
||||
runnable);
|
||||
mRunnable);
|
||||
|
||||
runnable.forget();
|
||||
return NS_FAILED(rv) ? false : true;
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothOppManager::Disconnect()
|
||||
{
|
||||
if (GetConnectionStatus() == SocketConnectionStatus::SOCKET_DISCONNECTED) {
|
||||
NS_WARNING("BluetoothOppManager has been disconnected!");
|
||||
return;
|
||||
}
|
||||
|
||||
CloseSocket();
|
||||
}
|
||||
|
||||
@ -269,6 +281,15 @@ BluetoothOppManager::SendFile(BlobParent* aActor)
|
||||
*/
|
||||
mBlob = aActor->GetBlob();
|
||||
|
||||
nsCOMPtr<nsIDOMFile> file = do_QueryInterface(mBlob);
|
||||
if (file) {
|
||||
file->GetName(sFileName);
|
||||
}
|
||||
|
||||
if (sFileName.IsEmpty()) {
|
||||
sFileName.AssignLiteral("Unknown");
|
||||
}
|
||||
|
||||
SendConnectRequest();
|
||||
|
||||
return true;
|
||||
@ -463,57 +484,51 @@ BluetoothOppManager::ReceiveSocketData(UnixSocketRawData* aMessage)
|
||||
mRemoteMaxPacketLength =
|
||||
(((int)(aMessage->mData[5]) << 8) | aMessage->mData[6]);
|
||||
|
||||
if (mBlob) {
|
||||
/*
|
||||
* Before sending content, we have to send a header including
|
||||
* information such as file name, file length and content type.
|
||||
*/
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIDOMFile> file = do_QueryInterface(mBlob);
|
||||
if (file) {
|
||||
rv = file->GetName(sFileName);
|
||||
}
|
||||
|
||||
if (!file || sFileName.IsEmpty()) {
|
||||
sFileName.AssignLiteral("Unknown");
|
||||
}
|
||||
|
||||
rv = mBlob->GetType(sContentType);
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_WARNING("Can't get content type");
|
||||
return;
|
||||
}
|
||||
|
||||
uint64_t fileLength;
|
||||
rv = mBlob->GetSize(&fileLength);
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_WARNING("Can't get file size");
|
||||
return;
|
||||
}
|
||||
|
||||
// Currently we keep the size of files which were sent/received via
|
||||
// Bluetooth not exceed UINT32_MAX because the Length header in OBEX
|
||||
// is only 4-byte long. Although it is possible to transfer a file
|
||||
// larger than UINT32_MAX, it needs to parse another OBEX Header
|
||||
// and I would like to leave it as a feature.
|
||||
if (fileLength <= UINT32_MAX) {
|
||||
NS_WARNING("The file size is too large for now");
|
||||
SendDisconnectRequest();
|
||||
return;
|
||||
}
|
||||
|
||||
sFileLength = fileLength;
|
||||
|
||||
if (NS_FAILED(NS_NewThread(getter_AddRefs(mReadFileThread)))) {
|
||||
NS_WARNING("Can't create thread");
|
||||
SendDisconnectRequest();
|
||||
return;
|
||||
}
|
||||
|
||||
sInstance->SendPutHeaderRequest(sFileName, sFileLength);
|
||||
StartFileTransfer(mConnectedDeviceAddress, false,
|
||||
sFileName, sFileLength, sContentType);
|
||||
MOZ_ASSERT(!sFileName.IsEmpty());
|
||||
MOZ_ASSERT(mBlob);
|
||||
/*
|
||||
* Before sending content, we have to send a header including
|
||||
* information such as file name, file length and content type.
|
||||
*/
|
||||
nsresult rv = mBlob->GetType(sContentType);
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_WARNING("Can't get content type");
|
||||
SendDisconnectRequest();
|
||||
return;
|
||||
}
|
||||
|
||||
uint64_t fileLength;
|
||||
rv = mBlob->GetSize(&fileLength);
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_WARNING("Can't get file size");
|
||||
SendDisconnectRequest();
|
||||
return;
|
||||
}
|
||||
|
||||
// Currently we keep the size of files which were sent/received via
|
||||
// Bluetooth not exceed UINT32_MAX because the Length header in OBEX
|
||||
// is only 4-byte long. Although it is possible to transfer a file
|
||||
// larger than UINT32_MAX, it needs to parse another OBEX Header
|
||||
// and I would like to leave it as a feature.
|
||||
if (fileLength > (uint64_t)UINT32_MAX) {
|
||||
NS_WARNING("The file size is too large for now");
|
||||
SendDisconnectRequest();
|
||||
return;
|
||||
}
|
||||
|
||||
sFileLength = fileLength;
|
||||
|
||||
if (NS_FAILED(NS_NewThread(getter_AddRefs(mReadFileThread)))) {
|
||||
NS_WARNING("Can't create thread");
|
||||
SendDisconnectRequest();
|
||||
return;
|
||||
}
|
||||
|
||||
sInstance->SendPutHeaderRequest(sFileName, sFileLength);
|
||||
StartFileTransfer(mConnectedDeviceAddress, false,
|
||||
sFileName, sFileLength, sContentType);
|
||||
} else {
|
||||
SendDisconnectRequest();
|
||||
}
|
||||
} else if (mLastCommand == ObexRequestCode::Disconnect) {
|
||||
if (opCode != ObexResponseCode::Success) {
|
||||
@ -524,12 +539,14 @@ BluetoothOppManager::ReceiveSocketData(UnixSocketRawData* aMessage)
|
||||
AfterOppDisconnected();
|
||||
} else if (mLastCommand == ObexRequestCode::Put) {
|
||||
if (opCode != ObexResponseCode::Continue) {
|
||||
// FIXME: Needs error handling here
|
||||
NS_WARNING("[OPP] Put failed");
|
||||
FileTransferComplete(mConnectedDeviceAddress, false, false, sFileName,
|
||||
sSentFileLength, sContentType);
|
||||
SendDisconnectRequest();
|
||||
return;
|
||||
}
|
||||
|
||||
if (mAbortFlag || mReadFileThread) {
|
||||
if (mAbortFlag) {
|
||||
SendAbortRequest();
|
||||
return;
|
||||
}
|
||||
@ -540,10 +557,13 @@ BluetoothOppManager::ReceiveSocketData(UnixSocketRawData* aMessage)
|
||||
mUpdateProgressCounter = sSentFileLength / kUpdateProgressBase + 1;
|
||||
}
|
||||
|
||||
if (mInputStream) {
|
||||
if (!mInputStream) {
|
||||
nsresult rv = mBlob->GetInternalStream(getter_AddRefs(mInputStream));
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_WARNING("Can't get internal stream of blob");
|
||||
FileTransferComplete(mConnectedDeviceAddress, false, false, sFileName,
|
||||
sSentFileLength, sContentType);
|
||||
SendDisconnectRequest();
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -551,11 +571,16 @@ BluetoothOppManager::ReceiveSocketData(UnixSocketRawData* aMessage)
|
||||
nsRefPtr<ReadFileTask> task = new ReadFileTask(mInputStream);
|
||||
if (NS_FAILED(mReadFileThread->Dispatch(task, NS_DISPATCH_NORMAL))) {
|
||||
NS_WARNING("Cannot dispatch ring task!");
|
||||
FileTransferComplete(mConnectedDeviceAddress, false, false, sFileName,
|
||||
sSentFileLength, sContentType);
|
||||
SendDisconnectRequest();
|
||||
}
|
||||
} else if (mLastCommand == ObexRequestCode::PutFinal) {
|
||||
if (opCode != ObexResponseCode::Success) {
|
||||
// FIXME: Needs error handling here
|
||||
NS_WARNING("[OPP] PutFinal failed");
|
||||
FileTransferComplete(mConnectedDeviceAddress, false, false, sFileName,
|
||||
sSentFileLength, sContentType);
|
||||
SendDisconnectRequest();
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1041,6 +1066,15 @@ BluetoothOppManager::ReceivingFileConfirmation(const nsString& aAddress,
|
||||
void
|
||||
BluetoothOppManager::OnConnectSuccess()
|
||||
{
|
||||
if (mRunnable) {
|
||||
BluetoothReply* reply = new BluetoothReply(BluetoothReplySuccess(true));
|
||||
mRunnable->SetReply(reply);
|
||||
if (NS_FAILED(NS_DispatchToMainThread(mRunnable))) {
|
||||
NS_WARNING("Failed to dispatch to main thread!");
|
||||
}
|
||||
mRunnable.forget();
|
||||
}
|
||||
|
||||
// Cache device address since we can't get socket address when a remote
|
||||
// device disconnect with us.
|
||||
GetSocketAddr(mConnectedDeviceAddress);
|
||||
@ -1051,6 +1085,17 @@ BluetoothOppManager::OnConnectSuccess()
|
||||
void
|
||||
BluetoothOppManager::OnConnectError()
|
||||
{
|
||||
if (mRunnable) {
|
||||
nsString errorStr;
|
||||
errorStr.AssignLiteral("Failed to connect with a bluetooth opp manager!");
|
||||
BluetoothReply* reply = new BluetoothReply(BluetoothReplyError(errorStr));
|
||||
mRunnable->SetReply(reply);
|
||||
if (NS_FAILED(NS_DispatchToMainThread(mRunnable))) {
|
||||
NS_WARNING("Failed to dispatch to main thread!");
|
||||
}
|
||||
mRunnable.forget();
|
||||
}
|
||||
|
||||
CloseSocket();
|
||||
mSocketStatus = GetConnectionStatus();
|
||||
Listen();
|
||||
|
@ -118,6 +118,8 @@ private:
|
||||
nsCOMPtr<nsIThread> mReadFileThread;
|
||||
nsCOMPtr<nsIOutputStream> mOutputStream;
|
||||
nsCOMPtr<nsIInputStream> mInputStream;
|
||||
|
||||
nsRefPtr<BluetoothReplyRunnable> mRunnable;
|
||||
};
|
||||
|
||||
END_BLUETOOTH_NAMESPACE
|
||||
|
@ -148,8 +148,14 @@ public:
|
||||
|
||||
for (int i = 0; i < length; ++i) {
|
||||
if (mHeaders[i]->mId == ObexHeaderId::Name) {
|
||||
/*
|
||||
* According to section 2.2.2 [Name] of IrOBEX spec, we know that
|
||||
* the Name header is "a null terminated Unicode text string describing
|
||||
* the name of the object.", and that's the reason why we need to minus
|
||||
* 1 to get the real length of the file name.
|
||||
*/
|
||||
int nameLength = mHeaders[i]->mDataLength / 2 - 1;
|
||||
uint8_t* ptr = mHeaders[i]->mData.get();
|
||||
int nameLength = mHeaders[i]->mDataLength / 2;
|
||||
|
||||
for (int j = 0; j < nameLength; ++j) {
|
||||
PRUnichar c = ((((uint32_t)ptr[j * 2]) << 8) | ptr[j * 2 + 1]);
|
||||
|
@ -200,6 +200,25 @@ DeviceStorageTypeChecker::GetPermissionForType(const nsAString& aType, nsACStrin
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
DeviceStorageTypeChecker::GetAccessForRequest(const DeviceStorageRequestType aRequestType, nsACString& aAccessResult)
|
||||
{
|
||||
switch(aRequestType) {
|
||||
case DEVICE_STORAGE_REQUEST_READ:
|
||||
case DEVICE_STORAGE_REQUEST_WATCH:
|
||||
case DEVICE_STORAGE_REQUEST_STAT:
|
||||
aAccessResult.AssignLiteral("read");
|
||||
break;
|
||||
case DEVICE_STORAGE_REQUEST_WRITE:
|
||||
case DEVICE_STORAGE_REQUEST_DELETE:
|
||||
aAccessResult.AssignLiteral("write");
|
||||
break;
|
||||
default:
|
||||
aAccessResult.AssignLiteral("undefined");
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
class IOEventComplete : public nsRunnable
|
||||
{
|
||||
public:
|
||||
@ -1039,6 +1058,13 @@ nsDOMDeviceStorageCursor::GetType(nsACString & aType)
|
||||
return DeviceStorageTypeChecker::GetPermissionForType(mFile->mStorageType, aType);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMDeviceStorageCursor::GetAccess(nsACString & aAccess)
|
||||
{
|
||||
aAccess = NS_LITERAL_CSTRING("read");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMDeviceStorageCursor::GetPrincipal(nsIPrincipal * *aRequestingPrincipal)
|
||||
{
|
||||
@ -1392,14 +1418,6 @@ class DeviceStorageRequest MOZ_FINAL
|
||||
{
|
||||
public:
|
||||
|
||||
enum DeviceStorageRequestType {
|
||||
DEVICE_STORAGE_REQUEST_READ,
|
||||
DEVICE_STORAGE_REQUEST_WRITE,
|
||||
DEVICE_STORAGE_REQUEST_DELETE,
|
||||
DEVICE_STORAGE_REQUEST_WATCH,
|
||||
DEVICE_STORAGE_REQUEST_STAT
|
||||
};
|
||||
|
||||
DeviceStorageRequest(const DeviceStorageRequestType aRequestType,
|
||||
nsPIDOMWindow *aWindow,
|
||||
nsIPrincipal *aPrincipal,
|
||||
@ -1456,7 +1474,12 @@ public:
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
child->SendPContentPermissionRequestConstructor(this, type, IPC::Principal(mPrincipal));
|
||||
nsCString access;
|
||||
rv = DeviceStorageTypeChecker::GetAccessForRequest(DeviceStorageRequestType(mRequestType), access);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
child->SendPContentPermissionRequestConstructor(this, type, access, IPC::Principal(mPrincipal));
|
||||
|
||||
Sendprompt();
|
||||
return NS_OK;
|
||||
@ -1479,6 +1502,15 @@ public:
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHOD GetAccess(nsACString & aAccess)
|
||||
{
|
||||
nsresult rv = DeviceStorageTypeChecker::GetAccessForRequest(DeviceStorageRequestType(mRequestType), aAccess);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHOD GetPrincipal(nsIPrincipal * *aRequestingPrincipal)
|
||||
{
|
||||
NS_IF_ADDREF(*aRequestingPrincipal = mPrincipal);
|
||||
@ -1814,7 +1846,7 @@ nsDOMDeviceStorage::AddNamed(nsIDOMBlob *aBlob,
|
||||
r = new PostErrorEvent(request, POST_ERROR_EVENT_ILLEGAL_TYPE);
|
||||
}
|
||||
else {
|
||||
r = new DeviceStorageRequest(DeviceStorageRequest::DEVICE_STORAGE_REQUEST_WRITE,
|
||||
r = new DeviceStorageRequest(DEVICE_STORAGE_REQUEST_WRITE,
|
||||
win, mPrincipal, dsf, request, aBlob);
|
||||
}
|
||||
|
||||
@ -1867,7 +1899,7 @@ nsDOMDeviceStorage::GetInternal(const JS::Value & aPath,
|
||||
if (!dsf->IsSafePath()) {
|
||||
r = new PostErrorEvent(request, POST_ERROR_EVENT_PERMISSION_DENIED);
|
||||
} else {
|
||||
r = new DeviceStorageRequest(DeviceStorageRequest::DEVICE_STORAGE_REQUEST_READ,
|
||||
r = new DeviceStorageRequest(DEVICE_STORAGE_REQUEST_READ,
|
||||
win, mPrincipal, dsf, request);
|
||||
}
|
||||
NS_DispatchToMainThread(r);
|
||||
@ -1901,7 +1933,7 @@ nsDOMDeviceStorage::Delete(const JS::Value & aPath, JSContext* aCx, nsIDOMDOMReq
|
||||
r = new PostErrorEvent(request, POST_ERROR_EVENT_PERMISSION_DENIED);
|
||||
}
|
||||
else {
|
||||
r = new DeviceStorageRequest(DeviceStorageRequest::DEVICE_STORAGE_REQUEST_DELETE,
|
||||
r = new DeviceStorageRequest(DEVICE_STORAGE_REQUEST_DELETE,
|
||||
win, mPrincipal, dsf, request);
|
||||
}
|
||||
NS_DispatchToMainThread(r);
|
||||
@ -1920,7 +1952,7 @@ nsDOMDeviceStorage::Stat(nsIDOMDOMRequest** aRetval)
|
||||
NS_ADDREF(*aRetval = request);
|
||||
|
||||
nsRefPtr<DeviceStorageFile> dsf = new DeviceStorageFile(mStorageType, mRootDirectory);
|
||||
nsCOMPtr<nsIRunnable> r = new DeviceStorageRequest(DeviceStorageRequest::DEVICE_STORAGE_REQUEST_STAT,
|
||||
nsCOMPtr<nsIRunnable> r = new DeviceStorageRequest(DEVICE_STORAGE_REQUEST_STAT,
|
||||
win,
|
||||
mPrincipal,
|
||||
dsf,
|
||||
@ -2042,7 +2074,7 @@ nsDOMDeviceStorage::EnumerateInternal(const JS::Value & aName,
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
child->SendPContentPermissionRequestConstructor(r, type, IPC::Principal(mPrincipal));
|
||||
child->SendPContentPermissionRequestConstructor(r, type, NS_LITERAL_CSTRING("read"), IPC::Principal(mPrincipal));
|
||||
|
||||
r->Sendprompt();
|
||||
|
||||
@ -2229,7 +2261,7 @@ nsDOMDeviceStorage::AddEventListener(const nsAString & aType,
|
||||
|
||||
nsRefPtr<DOMRequest> request = new DOMRequest(win);
|
||||
nsRefPtr<DeviceStorageFile> dsf = new DeviceStorageFile(mStorageType, mRootDirectory);
|
||||
nsCOMPtr<nsIRunnable> r = new DeviceStorageRequest(DeviceStorageRequest::DEVICE_STORAGE_REQUEST_WATCH,
|
||||
nsCOMPtr<nsIRunnable> r = new DeviceStorageRequest(DEVICE_STORAGE_REQUEST_WATCH,
|
||||
win, mPrincipal, dsf, request, this, aListener);
|
||||
NS_DispatchToMainThread(r);
|
||||
return nsDOMEventTargetHelper::AddEventListener(aType, aListener, aUseCapture, aWantsUntrusted, aArgc);
|
||||
|
@ -43,6 +43,14 @@ using namespace mozilla;
|
||||
using namespace mozilla::dom;
|
||||
using namespace mozilla::dom::devicestorage;
|
||||
|
||||
enum DeviceStorageRequestType {
|
||||
DEVICE_STORAGE_REQUEST_READ,
|
||||
DEVICE_STORAGE_REQUEST_WRITE,
|
||||
DEVICE_STORAGE_REQUEST_DELETE,
|
||||
DEVICE_STORAGE_REQUEST_WATCH,
|
||||
DEVICE_STORAGE_REQUEST_STAT
|
||||
};
|
||||
|
||||
class DeviceStorageTypeChecker MOZ_FINAL
|
||||
{
|
||||
public:
|
||||
@ -57,6 +65,7 @@ public:
|
||||
bool Check(const nsAString& aType, nsIFile* aFile);
|
||||
|
||||
static nsresult GetPermissionForType(const nsAString& aType, nsACString& aPermissionResult);
|
||||
static nsresult GetAccessForRequest(const DeviceStorageRequestType aRequestType, nsACString& aAccessResult);
|
||||
|
||||
private:
|
||||
nsString mPicturesExtensions;
|
||||
|
@ -206,13 +206,6 @@ TextDecoder::GetEncoding(nsAString& aEncoding)
|
||||
return;
|
||||
}
|
||||
|
||||
// Similarly, "x-windows-949" is used for the "euc-kr" family. Therefore, if
|
||||
// the internal encoding name is "x-windows-949", "euc-kr" is returned.
|
||||
if (mEncoding.EqualsLiteral("x-windows-949")) {
|
||||
aEncoding.AssignLiteral("euc-kr");
|
||||
return;
|
||||
}
|
||||
|
||||
CopyASCIItoUTF16(mEncoding, aEncoding);
|
||||
nsContentUtils::ASCIIToLower(aEncoding);
|
||||
}
|
||||
|
@ -205,16 +205,16 @@ shift_jis=Shift_JIS
|
||||
sjis=Shift_JIS
|
||||
windows-31j=Shift_JIS
|
||||
x-sjis=Shift_JIS
|
||||
cseuckr=x-windows-949
|
||||
csksc56011987=x-windows-949
|
||||
euc-kr=x-windows-949
|
||||
iso-ir-149=x-windows-949
|
||||
korean=x-windows-949
|
||||
ks_c_5601-1987=x-windows-949
|
||||
ks_c_5601-1989=x-windows-949
|
||||
ksc5601=x-windows-949
|
||||
ksc_5601=x-windows-949
|
||||
windows-949=x-windows-949
|
||||
cseuckr=EUC-KR
|
||||
csksc56011987=EUC-KR
|
||||
euc-kr=EUC-KR
|
||||
iso-ir-149=EUC-KR
|
||||
korean=EUC-KR
|
||||
ks_c_5601-1987=EUC-KR
|
||||
ks_c_5601-1989=EUC-KR
|
||||
ksc5601=EUC-KR
|
||||
ksc_5601=EUC-KR
|
||||
windows-949=EUC-KR
|
||||
csiso2022kr=ISO-2022-KR
|
||||
iso-2022-kr=ISO-2022-KR
|
||||
utf-16=UTF-16LE
|
||||
|
@ -13,7 +13,7 @@ interface nsIDOMElement;
|
||||
* permission to perform a privileged operation such as
|
||||
* geolocation.
|
||||
*/
|
||||
[scriptable, uuid(E1F3796C-ADFA-414B-B2A7-AC62F29395EE)]
|
||||
[scriptable, uuid(1de67000-2de8-11e2-81c1-0800200c9a66)]
|
||||
interface nsIContentPermissionRequest : nsISupports {
|
||||
|
||||
/**
|
||||
@ -22,6 +22,12 @@ interface nsIContentPermissionRequest : nsISupports {
|
||||
*/
|
||||
readonly attribute ACString type;
|
||||
|
||||
/**
|
||||
* The access of the permission request, such as
|
||||
* "read".
|
||||
*/
|
||||
readonly attribute ACString access;
|
||||
|
||||
/**
|
||||
* The principal of the permission request.
|
||||
*/
|
||||
|
@ -4,14 +4,6 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsISupports.idl"
|
||||
#include "nsIVariant.idl"
|
||||
|
||||
interface nsIDOMWindow;
|
||||
interface nsIDOMElement;
|
||||
interface nsIDOMHTMLElement;
|
||||
interface nsIDOMHTMLImageElement;
|
||||
interface nsIDOMHTMLCanvasElement;
|
||||
interface nsIDOMXULElement;
|
||||
|
||||
[scriptable, uuid(bbb20a59-524e-4662-981e-5e142814b20c)]
|
||||
interface nsIDOMCanvasGradient : nsISupports
|
||||
@ -30,178 +22,17 @@ interface nsIDOMTextMetrics : nsISupports
|
||||
readonly attribute float width;
|
||||
};
|
||||
|
||||
[scriptable, uuid(438fe14d-6501-40ab-b6c2-130fa38bd2c9)]
|
||||
/**
|
||||
* This interface remains only for the constants, for a context, use the
|
||||
* WebIDL/Paris bindings instead (CanvasRenderingContext2D.webidl).
|
||||
* The constants are used by CanvasRenderingContext2D::DrawWindow and are
|
||||
* used in WindowsPreviewPerTab.jsm and some extensions. The constants can
|
||||
* be referenced directly via a canvas context 2d rather than this interface,
|
||||
* and that should be preferred in new code.
|
||||
*/
|
||||
[scriptable, uuid(4417cab7-c7eb-4e0c-b00a-c43842f0cba8)]
|
||||
interface nsIDOMCanvasRenderingContext2D : nsISupports
|
||||
{
|
||||
// back-reference to the canvas element for which
|
||||
// this context was created
|
||||
readonly attribute nsIDOMHTMLCanvasElement canvas;
|
||||
|
||||
// state
|
||||
[binaryname(MozSave)]
|
||||
void save();
|
||||
[binaryname(MozRestore)]
|
||||
void restore();
|
||||
|
||||
// transformations
|
||||
void scale(in float x, in float y);
|
||||
void rotate(in float angle);
|
||||
void translate(in float x, in float y);
|
||||
void transform(in float m11, in float m12, in float m21, in float m22, in float dx, in float dy);
|
||||
void setTransform(in float m11, in float m12, in float m21, in float m22, in float dx, in float dy);
|
||||
[implicit_jscontext]
|
||||
attribute jsval mozCurrentTransform; // [ m11, m12, m21, m22, dx, dy ], i.e. row major
|
||||
[implicit_jscontext]
|
||||
attribute jsval mozCurrentTransformInverse;
|
||||
|
||||
// compositing
|
||||
attribute float globalAlpha; /* default 1.0 -- opaque */
|
||||
attribute DOMString globalCompositeOperation; /* default "over" */
|
||||
|
||||
// Colors and Styles
|
||||
|
||||
// These attributes work, but are quickstubbed for JS code. Native
|
||||
// code should use the _multi variants below.
|
||||
attribute nsIVariant strokeStyle;
|
||||
attribute nsIVariant fillStyle;
|
||||
|
||||
// These do the actual work. Use these from c++ -- only one of str or iface
|
||||
// should be specified; the one that's not null/void is used. For the getter,
|
||||
// ifaceType is 0 if it's a string, 1 if it's a pattern, or 2 if it's a gradient
|
||||
%{C++
|
||||
enum CanvasMultiGetterType {
|
||||
CMG_STYLE_STRING = 0,
|
||||
CMG_STYLE_PATTERN = 1,
|
||||
CMG_STYLE_GRADIENT = 2
|
||||
};
|
||||
%}
|
||||
[noscript] void setStrokeStyle_multi(in DOMString str, in nsISupports iface);
|
||||
[noscript] void getStrokeStyle_multi(out DOMString str, out nsISupports iface, out long type);
|
||||
[noscript] void setFillStyle_multi(in DOMString str, in nsISupports iface);
|
||||
[noscript] void getFillStyle_multi(out DOMString str, out nsISupports iface, out long type);
|
||||
|
||||
//attribute DOMString fillRule;
|
||||
attribute DOMString mozFillRule; /* "evenodd", "nonzero" (default) */
|
||||
|
||||
nsIDOMCanvasGradient createLinearGradient (in float x0, in float y0, in float x1, in float y1);
|
||||
nsIDOMCanvasGradient createRadialGradient(in float x0, in float y0, in float r0, in float x1, in float y1, in float r1);
|
||||
nsIDOMCanvasPattern createPattern(in nsIDOMHTMLElement image, in DOMString repetition);
|
||||
attribute float lineWidth; /* default 1 */
|
||||
[binaryname(MozLineCap)]
|
||||
attribute DOMString lineCap; /* "butt", "round", "square" (default) */
|
||||
[binaryname(MozLineJoin)]
|
||||
attribute DOMString lineJoin; /* "round", "bevel", "miter" (default) */
|
||||
attribute float miterLimit; /* default 10 */
|
||||
|
||||
[implicit_jscontext]
|
||||
attribute jsval mozDash; /* default |null| */
|
||||
attribute float mozDashOffset; /* default 0.0 */
|
||||
|
||||
// shadows
|
||||
attribute float shadowOffsetX;
|
||||
attribute float shadowOffsetY;
|
||||
attribute float shadowBlur;
|
||||
[binaryname(MozShadowColor)]
|
||||
attribute DOMString shadowColor;
|
||||
|
||||
// rects
|
||||
void clearRect(in float x, in float y, in float w, in float h);
|
||||
void fillRect(in float x, in float y, in float w, in float h);
|
||||
void strokeRect(in float x, in float y, in float w, in float h);
|
||||
|
||||
// path API
|
||||
[binaryname(MozBeginPath)]
|
||||
void beginPath();
|
||||
[binaryname(MozClosePath)]
|
||||
void closePath();
|
||||
|
||||
void moveTo(in float x, in float y);
|
||||
void lineTo(in float x, in float y);
|
||||
void quadraticCurveTo(in float cpx, in float cpy, in float x, in float y);
|
||||
void bezierCurveTo(in float cp1x, in float cp1y, in float cp2x, in float cp2y, in float x, in float y);
|
||||
void arcTo(in float x1, in float y1, in float x2, in float y2, in float radius);
|
||||
void arc(in float x, in float y, in float r, in float startAngle, in float endAngle, [optional] in boolean anticlockwise);
|
||||
void rect(in float x, in float y, in float w, in float h);
|
||||
|
||||
[binaryname(MozFill)]
|
||||
void fill();
|
||||
[binaryname(MozStroke)]
|
||||
void stroke();
|
||||
[binaryname(MozClip)]
|
||||
void clip();
|
||||
|
||||
// text api
|
||||
[binaryname(MozFont)]
|
||||
attribute DOMString font; /* default "10px sans-serif" */
|
||||
[binaryname(MozTextAlign)]
|
||||
attribute DOMString textAlign; /* "start" (default), "end", "left", "right",
|
||||
"center" */
|
||||
[binaryname(MozTextBaseline)]
|
||||
attribute DOMString textBaseline; /* "alphabetic" (default), "top", "hanging",
|
||||
"middle", "ideographic", "bottom" */
|
||||
|
||||
void fillText(in DOMString text, in float x, in float y, [optional] in float maxWidth);
|
||||
void strokeText(in DOMString text, in float x, in float y, [optional] in float maxWidth);
|
||||
nsIDOMTextMetrics measureText(in DOMString text);
|
||||
|
||||
[binaryname(TextStyle)]
|
||||
attribute DOMString mozTextStyle;
|
||||
|
||||
// image api
|
||||
|
||||
[optional_argc] void drawImage(in nsIDOMElement image,
|
||||
in float a1, in float a2,
|
||||
[optional] in float a3,
|
||||
[optional] in float a4,
|
||||
[optional] in float a5,
|
||||
[optional] in float a6,
|
||||
[optional] in float a7,
|
||||
[optional] in float a8);
|
||||
|
||||
/*
|
||||
void drawImage(in HTMLImageElement image, in float dx, in float dy);
|
||||
void drawImage(in HTMLImageElement image, in float dx, in float dy, in float sw, in float sh);
|
||||
void drawImage(in HTMLImageElement image, in float sx, in float sy, in float sw, in float sh, in float dx, in float dy, in float dw, in float dh);
|
||||
*/
|
||||
|
||||
// point-membership test
|
||||
boolean isPointInPath(in float x, in float y);
|
||||
boolean mozIsPointInStroke(in float x, in float y);
|
||||
|
||||
// pixel manipulation
|
||||
// ImageData getImageData (in float x, in float y, in float width, in float height);
|
||||
// void putImageData (in ImageData d, in float x, in float y);
|
||||
// ImageData = { width: #, height: #, data: [r, g, b, a, ...] }
|
||||
|
||||
// nsISupports is OK, because the binding code will deal correctly
|
||||
[implicit_jscontext]
|
||||
nsISupports getImageData(in double sx, in double sy, in double sw, in double sh);
|
||||
|
||||
|
||||
// void putImageData(ImageData imagedata, double dx, double dy);
|
||||
// void putImageDataHD(ImageData imagedata, double dx, double dy, double dirtyX, double dirtyY, double dirtyWidth, double dirtyHeight);
|
||||
// We use jsval for the imageData because that's what our C++ code wants
|
||||
[implicit_jscontext, optional_argc]
|
||||
void putImageData(in jsval imageData, in double dx, in double dy,
|
||||
[optional] in double dirtyX, [optional] in double dirtyY,
|
||||
[optional] in double dirtyWidth,
|
||||
[optional] in double dirtyHeight);
|
||||
|
||||
// dataLen must be == width*height*4 in this call
|
||||
[noscript] void putImageData_explicit(in long x, in long y, in unsigned long width, in unsigned long height,
|
||||
[array, size_is(dataLen)] in octet dataPtr, in unsigned long dataLen, in boolean hasDirtyRect,
|
||||
in long dirtyX, in long dirtyY, in long dirtyWidth, in long dirtyHeight);
|
||||
|
||||
// ImageData createImageData(double w, double h);
|
||||
// ImageData createImageData(ImageData data);
|
||||
// nsISupports is OK, because the binding code will deal correctly
|
||||
[implicit_jscontext, optional_argc]
|
||||
nsISupports createImageData(in jsval arg1, [optional] in jsval arg2);
|
||||
|
||||
// image smoothing mode -- if disabled, images won't be smoothed
|
||||
// if scaled.
|
||||
attribute boolean mozImageSmoothingEnabled;
|
||||
|
||||
// Show the caret if appropriate when drawing
|
||||
const unsigned long DRAWWINDOW_DRAW_CARET = 0x01;
|
||||
// Don't flush pending layout notifications that could otherwise
|
||||
@ -216,46 +47,4 @@ enum CanvasMultiGetterType {
|
||||
const unsigned long DRAWWINDOW_USE_WIDGET_LAYERS = 0x08;
|
||||
// Don't synchronously decode images - draw what we have
|
||||
const unsigned long DRAWWINDOW_ASYNC_DECODE_IMAGES = 0x10;
|
||||
|
||||
/**
|
||||
* Renders a region of a window into the canvas. The contents of
|
||||
* the window's viewport are rendered, ignoring viewport clipping
|
||||
* and scrolling.
|
||||
*
|
||||
* @param x
|
||||
* @param y
|
||||
* @param w
|
||||
* @param h specify the area of the window to render, in CSS
|
||||
* pixels.
|
||||
*
|
||||
* @param backgroundColor the canvas is filled with this color
|
||||
* before we render the window into it. This color may be
|
||||
* transparent/translucent. It is given as a CSS color string
|
||||
* (e.g., rgb() or rgba()).
|
||||
*
|
||||
* @param flags Used to better control the drawWindow call.
|
||||
* Flags can be ORed together.
|
||||
*
|
||||
* Of course, the rendering obeys the current scale, transform and
|
||||
* globalAlpha values.
|
||||
*
|
||||
* Hints:
|
||||
* -- If 'rgba(0,0,0,0)' is used for the background color, the
|
||||
* drawing will be transparent wherever the window is transparent.
|
||||
* -- Top-level browsed documents are usually not transparent
|
||||
* because the user's background-color preference is applied,
|
||||
* but IFRAMEs are transparent if the page doesn't set a background.
|
||||
* -- If an opaque color is used for the background color, rendering
|
||||
* will be faster because we won't have to compute the window's
|
||||
* transparency.
|
||||
*
|
||||
* This API cannot currently be used by Web content. It is chrome
|
||||
* only.
|
||||
*/
|
||||
void drawWindow(in nsIDOMWindow window, in float x, in float y,
|
||||
in float w, in float h, in DOMString bgColor,
|
||||
[optional] in unsigned long flags);
|
||||
void asyncDrawXULElement(in nsIDOMXULElement elem, in float x, in float y,
|
||||
in float w, in float h, in DOMString bgColor,
|
||||
[optional] in unsigned long flags);
|
||||
};
|
||||
|
@ -186,6 +186,8 @@ parent:
|
||||
*
|
||||
* @param aType
|
||||
* The type of permission to request.
|
||||
* @param aAccess
|
||||
* Access type. "read" for example.
|
||||
* @param aPrincipal
|
||||
* The principal of the request.
|
||||
*
|
||||
@ -193,7 +195,7 @@ parent:
|
||||
* principals that can live in the content process should
|
||||
* provided.
|
||||
*/
|
||||
PContentPermissionRequest(nsCString aType, Principal principal);
|
||||
PContentPermissionRequest(nsCString aType, nsCString aAccess, Principal principal);
|
||||
|
||||
PContentDialog(uint32_t aType, nsCString aName, nsCString aFeatures,
|
||||
int32_t[] aIntParams, nsString[] aStringParams);
|
||||
|
@ -1500,7 +1500,7 @@ TabChild::DeallocPContentDialog(PContentDialogChild* aDialog)
|
||||
}
|
||||
|
||||
PContentPermissionRequestChild*
|
||||
TabChild::AllocPContentPermissionRequest(const nsCString& aType, const IPC::Principal&)
|
||||
TabChild::AllocPContentPermissionRequest(const nsCString& aType, const nsCString& aAccess, const IPC::Principal&)
|
||||
{
|
||||
NS_RUNTIMEABORT("unused");
|
||||
return nullptr;
|
||||
|
@ -258,16 +258,19 @@ public:
|
||||
#ifdef DEBUG
|
||||
virtual PContentPermissionRequestChild* SendPContentPermissionRequestConstructor(PContentPermissionRequestChild* aActor,
|
||||
const nsCString& aType,
|
||||
const nsCString& aAccess,
|
||||
const IPC::Principal& aPrincipal)
|
||||
{
|
||||
PCOMContentPermissionRequestChild* child = static_cast<PCOMContentPermissionRequestChild*>(aActor);
|
||||
PContentPermissionRequestChild* request = PBrowserChild::SendPContentPermissionRequestConstructor(aActor, aType, aPrincipal);
|
||||
PContentPermissionRequestChild* request = PBrowserChild::SendPContentPermissionRequestConstructor(aActor, aType, aAccess, aPrincipal);
|
||||
child->mIPCOpen = true;
|
||||
return request;
|
||||
}
|
||||
#endif /* DEBUG */
|
||||
|
||||
virtual PContentPermissionRequestChild* AllocPContentPermissionRequest(const nsCString& aType, const IPC::Principal& aPrincipal);
|
||||
virtual PContentPermissionRequestChild* AllocPContentPermissionRequest(const nsCString& aType,
|
||||
const nsCString& aAccess,
|
||||
const IPC::Principal& aPrincipal);
|
||||
virtual bool DeallocPContentPermissionRequest(PContentPermissionRequestChild* actor);
|
||||
|
||||
virtual POfflineCacheUpdateChild* AllocPOfflineCacheUpdate(
|
||||
|
@ -323,9 +323,9 @@ TabParent::DeallocPDocumentRenderer(PDocumentRendererParent* actor)
|
||||
}
|
||||
|
||||
PContentPermissionRequestParent*
|
||||
TabParent::AllocPContentPermissionRequest(const nsCString& type, const IPC::Principal& principal)
|
||||
TabParent::AllocPContentPermissionRequest(const nsCString& type, const nsCString& access, const IPC::Principal& principal)
|
||||
{
|
||||
return new ContentPermissionRequestParent(type, mFrameElement, principal);
|
||||
return new ContentPermissionRequestParent(type, access, mFrameElement, principal);
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -184,7 +184,7 @@ public:
|
||||
virtual bool DeallocPDocumentRenderer(PDocumentRendererParent* actor);
|
||||
|
||||
virtual PContentPermissionRequestParent*
|
||||
AllocPContentPermissionRequest(const nsCString& aType, const IPC::Principal& aPrincipal);
|
||||
AllocPContentPermissionRequest(const nsCString& aType, const nsCString& aAccess, const IPC::Principal& aPrincipal);
|
||||
virtual bool DeallocPContentPermissionRequest(PContentPermissionRequestParent* actor);
|
||||
|
||||
virtual POfflineCacheUpdateParent* AllocPOfflineCacheUpdate(
|
||||
|
@ -43,7 +43,6 @@ gbk.title = Chinese Simplified (GBK)
|
||||
iso-2022-cn.title = Chinese Simplified (ISO-2022-CN)
|
||||
euc-kr.title = Korean (EUC-KR)
|
||||
x-johab.title = Korean (JOHAB)
|
||||
x-windows-949.title = Korean (UHC)
|
||||
iso-2022-kr.title = Korean (ISO-2022-KR)
|
||||
utf-7.title = Unicode (UTF-7)
|
||||
utf-8.title = Unicode (UTF-8)
|
||||
|
@ -229,7 +229,6 @@ public:
|
||||
GetUserMediaStreamRunnable(
|
||||
already_AddRefed<nsIDOMGetUserMediaSuccessCallback> aSuccess,
|
||||
already_AddRefed<nsIDOMGetUserMediaErrorCallback> aError,
|
||||
StreamListeners* aListeners,
|
||||
uint64_t aWindowID,
|
||||
MediaEngineSource* aAudioSource,
|
||||
MediaEngineSource* aVideoSource)
|
||||
@ -237,7 +236,6 @@ public:
|
||||
, mError(aError)
|
||||
, mAudioSource(aAudioSource)
|
||||
, mVideoSource(aVideoSource)
|
||||
, mListeners(aListeners)
|
||||
, mWindowID(aWindowID) {}
|
||||
|
||||
~GetUserMediaStreamRunnable() {}
|
||||
@ -247,29 +245,29 @@ public:
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");
|
||||
|
||||
// We're on main-thread, and the windowlist can only
|
||||
// be invalidated from the main-thread (see OnNavigation)
|
||||
StreamListeners* listeners = MediaManager::Get()->GetWindowListeners(mWindowID);
|
||||
if (!listeners) {
|
||||
// This window is no longer live.
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Create a media stream.
|
||||
nsRefPtr<nsDOMLocalMediaStream> stream;
|
||||
uint32_t hints = (mAudioSource ? nsDOMMediaStream::HINT_CONTENTS_AUDIO : 0);
|
||||
hints |= (mVideoSource ? nsDOMMediaStream::HINT_CONTENTS_VIDEO : 0);
|
||||
|
||||
stream = nsDOMLocalMediaStream::CreateSourceStream(hints);
|
||||
if (!stream) {
|
||||
nsCOMPtr<nsIDOMGetUserMediaErrorCallback> error(mError);
|
||||
LOG(("Returning error for getUserMedia() - no stream"));
|
||||
error->OnError(NS_LITERAL_STRING("NO_STREAM"));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsPIDOMWindow *window = static_cast<nsPIDOMWindow*>
|
||||
(nsGlobalWindow::GetInnerWindowWithId(mWindowID));
|
||||
{
|
||||
if (!stream) {
|
||||
if (!(MediaManager::Get()->IsWindowStillActive(mWindowID))) {
|
||||
return NS_OK;
|
||||
}
|
||||
// This is safe since we're on main-thread, and the windowlist can only
|
||||
// be invalidated from the main-thread (see OnNavigation)
|
||||
nsCOMPtr<nsIDOMGetUserMediaErrorCallback> error(mError);
|
||||
LOG(("Returning error for getUserMedia() - no stream"));
|
||||
error->OnError(NS_LITERAL_STRING("NO_STREAM"));
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
if (window && window->GetExtantDoc()) {
|
||||
stream->CombineWithPrincipal(window->GetExtantDoc()->NodePrincipal());
|
||||
}
|
||||
@ -287,7 +285,7 @@ public:
|
||||
stream->GetStream()->AddListener(listener);
|
||||
|
||||
// No need for locking because we always do this in the main thread.
|
||||
mListeners->AppendElement(listener);
|
||||
listeners->AppendElement(listener);
|
||||
|
||||
// Dispatch to the media thread to ask it to start the sources,
|
||||
// because that can take a while
|
||||
@ -316,7 +314,6 @@ private:
|
||||
already_AddRefed<nsIDOMGetUserMediaErrorCallback> mError;
|
||||
nsRefPtr<MediaEngineSource> mAudioSource;
|
||||
nsRefPtr<MediaEngineSource> mVideoSource;
|
||||
StreamListeners* mListeners;
|
||||
uint64_t mWindowID;
|
||||
};
|
||||
|
||||
@ -339,14 +336,12 @@ public:
|
||||
GetUserMediaRunnable(bool aAudio, bool aVideo, bool aPicture,
|
||||
already_AddRefed<nsIDOMGetUserMediaSuccessCallback> aSuccess,
|
||||
already_AddRefed<nsIDOMGetUserMediaErrorCallback> aError,
|
||||
StreamListeners* aListeners, uint64_t aWindowID,
|
||||
MediaDevice* aAudioDevice, MediaDevice* aVideoDevice)
|
||||
uint64_t aWindowID, MediaDevice* aAudioDevice, MediaDevice* aVideoDevice)
|
||||
: mAudio(aAudio)
|
||||
, mVideo(aVideo)
|
||||
, mPicture(aPicture)
|
||||
, mSuccess(aSuccess)
|
||||
, mError(aError)
|
||||
, mListeners(aListeners)
|
||||
, mWindowID(aWindowID)
|
||||
, mDeviceChosen(true)
|
||||
, mBackendChosen(false)
|
||||
@ -362,13 +357,12 @@ public:
|
||||
GetUserMediaRunnable(bool aAudio, bool aVideo, bool aPicture,
|
||||
already_AddRefed<nsIDOMGetUserMediaSuccessCallback> aSuccess,
|
||||
already_AddRefed<nsIDOMGetUserMediaErrorCallback> aError,
|
||||
StreamListeners* aListeners, uint64_t aWindowID)
|
||||
uint64_t aWindowID)
|
||||
: mAudio(aAudio)
|
||||
, mVideo(aVideo)
|
||||
, mPicture(aPicture)
|
||||
, mSuccess(aSuccess)
|
||||
, mError(aError)
|
||||
, mListeners(aListeners)
|
||||
, mWindowID(aWindowID)
|
||||
, mDeviceChosen(false)
|
||||
, mBackendChosen(false) {}
|
||||
@ -380,13 +374,12 @@ public:
|
||||
GetUserMediaRunnable(bool aAudio, bool aVideo,
|
||||
already_AddRefed<nsIDOMGetUserMediaSuccessCallback> aSuccess,
|
||||
already_AddRefed<nsIDOMGetUserMediaErrorCallback> aError,
|
||||
StreamListeners* aListeners, uint64_t aWindowID, MediaEngine* aBackend)
|
||||
uint64_t aWindowID, MediaEngine* aBackend)
|
||||
: mAudio(aAudio)
|
||||
, mVideo(aVideo)
|
||||
, mPicture(false)
|
||||
, mSuccess(aSuccess)
|
||||
, mError(aError)
|
||||
, mListeners(aListeners)
|
||||
, mWindowID(aWindowID)
|
||||
, mDeviceChosen(false)
|
||||
, mBackendChosen(true)
|
||||
@ -571,7 +564,7 @@ public:
|
||||
}
|
||||
|
||||
NS_DispatchToMainThread(new GetUserMediaStreamRunnable(
|
||||
mSuccess, mError, mListeners, mWindowID, aAudioSource, aVideoSource
|
||||
mSuccess, mError, mWindowID, aAudioSource, aVideoSource
|
||||
));
|
||||
return;
|
||||
}
|
||||
@ -611,7 +604,6 @@ private:
|
||||
|
||||
already_AddRefed<nsIDOMGetUserMediaSuccessCallback> mSuccess;
|
||||
already_AddRefed<nsIDOMGetUserMediaErrorCallback> mError;
|
||||
StreamListeners* mListeners;
|
||||
uint64_t mWindowID;
|
||||
nsRefPtr<MediaDevice> mAudioDevice;
|
||||
nsRefPtr<MediaDevice> mVideoDevice;
|
||||
@ -824,22 +816,20 @@ MediaManager::GetUserMedia(bool aPrivileged, nsPIDOMWindow* aWindow,
|
||||
if (fake) {
|
||||
// Fake stream from default backend.
|
||||
gUMRunnable = new GetUserMediaRunnable(
|
||||
audio, video, onSuccess.forget(), onError.forget(), listeners,
|
||||
windowID, new MediaEngineDefault()
|
||||
audio, video, onSuccess.forget(), onError.forget(), windowID,
|
||||
new MediaEngineDefault()
|
||||
);
|
||||
} else if (audiodevice || videodevice) {
|
||||
// Stream from provided device.
|
||||
gUMRunnable = new GetUserMediaRunnable(
|
||||
audio, video, picture, onSuccess.forget(), onError.forget(), listeners,
|
||||
windowID,
|
||||
audio, video, picture, onSuccess.forget(), onError.forget(), windowID,
|
||||
static_cast<MediaDevice*>(audiodevice.get()),
|
||||
static_cast<MediaDevice*>(videodevice.get())
|
||||
);
|
||||
} else {
|
||||
// Stream from default device from WebRTC backend.
|
||||
gUMRunnable = new GetUserMediaRunnable(
|
||||
audio, video, picture, onSuccess.forget(), onError.forget(), listeners,
|
||||
windowID
|
||||
audio, video, picture, onSuccess.forget(), onError.forget(), windowID
|
||||
);
|
||||
}
|
||||
|
||||
@ -948,7 +938,7 @@ MediaManager::OnNavigation(uint64_t aWindowID)
|
||||
|
||||
// This is safe since we're on main-thread, and the windowlist can only
|
||||
// be added to from the main-thread (see OnNavigation)
|
||||
StreamListeners* listeners = GetActiveWindows()->Get(aWindowID);
|
||||
StreamListeners* listeners = GetWindowListeners(aWindowID);
|
||||
if (!listeners) {
|
||||
return;
|
||||
}
|
||||
|
@ -294,10 +294,13 @@ public:
|
||||
NS_DECL_NSIOBSERVER
|
||||
|
||||
MediaEngine* GetBackend();
|
||||
bool IsWindowStillActive(uint64_t aWindowId) {
|
||||
StreamListeners *GetWindowListeners(uint64_t aWindowId) {
|
||||
NS_ASSERTION(NS_IsMainThread(), "Only access windowlist on main thread");
|
||||
|
||||
return !!mActiveWindows.Get(aWindowId);
|
||||
return mActiveWindows.Get(aWindowId);
|
||||
}
|
||||
bool IsWindowStillActive(uint64_t aWindowId) {
|
||||
return !!GetWindowListeners(aWindowId);
|
||||
}
|
||||
|
||||
nsresult GetUserMedia(bool aPrivileged, nsPIDOMWindow* aWindow,
|
||||
|
@ -964,7 +964,7 @@ static const moz2javaCharset charsets[] =
|
||||
{"windows-1257", "Cp1257"},
|
||||
{"windows-1258", "Cp1258"},
|
||||
{"EUC-JP", "EUC_JP"},
|
||||
{"EUC-KR", "EUC_KR"},
|
||||
{"EUC-KR", "MS949"},
|
||||
{"x-euc-tw", "EUC_TW"},
|
||||
{"gb18030", "GB18030"},
|
||||
{"gbk", "GBK"},
|
||||
@ -982,7 +982,6 @@ static const moz2javaCharset charsets[] =
|
||||
{"x-johab", "Johab"},
|
||||
{"KOI8-R", "KOI8_R"},
|
||||
{"TIS-620", "MS874"},
|
||||
{"x-windows-949", "MS949"},
|
||||
{"x-mac-arabic", "MacArabic"},
|
||||
{"x-mac-croatian", "MacCroatia"},
|
||||
{"x-mac-cyrillic", "MacCyrillic"},
|
||||
|
@ -11,3 +11,6 @@ qemu = true
|
||||
[test_outgoing_delete.js]
|
||||
[test_getmessage.js]
|
||||
[test_getmessage_notfound.js]
|
||||
[test_filter_read.js]
|
||||
[test_filter_unread.js]
|
||||
[test_number_of_messages.js]
|
||||
|
229
dom/sms/tests/marionette/test_filter_read.js
Normal file
229
dom/sms/tests/marionette/test_filter_read.js
Normal file
@ -0,0 +1,229 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
MARIONETTE_TIMEOUT = 20000;
|
||||
|
||||
SpecialPowers.addPermission("sms", true, document);
|
||||
SpecialPowers.setBoolPref("dom.sms.enabled", true);
|
||||
|
||||
let sms = window.navigator.mozSms;
|
||||
let numberMsgs = 10;
|
||||
let smsList = new Array();
|
||||
|
||||
function verifyInitialState() {
|
||||
log("Verifying initial state.");
|
||||
ok(sms, "mozSms");
|
||||
// Ensure test is starting clean with no existing sms messages
|
||||
deleteAllMsgs(simulateIncomingSms);
|
||||
}
|
||||
|
||||
function deleteAllMsgs(nextFunction) {
|
||||
let msgList = new Array();
|
||||
let filter = new MozSmsFilter;
|
||||
|
||||
let request = sms.getMessages(filter, false);
|
||||
ok(request instanceof MozSmsRequest,
|
||||
"request is instanceof " + request.constructor);
|
||||
|
||||
request.onsuccess = function(event) {
|
||||
ok(event.target.result, "smsrequest event.target.result");
|
||||
cursor = event.target.result;
|
||||
// Check if message was found
|
||||
if (cursor.message) {
|
||||
msgList.push(cursor.message.id);
|
||||
// Now get next message in the list
|
||||
cursor.continue();
|
||||
} else {
|
||||
// No (more) messages found
|
||||
if (msgList.length) {
|
||||
log("Found " + msgList.length + " SMS messages to delete.");
|
||||
deleteMsgs(msgList, nextFunction);
|
||||
} else {
|
||||
log("No SMS messages found.");
|
||||
nextFunction();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
request.onerror = function(event) {
|
||||
log("Received 'onerror' smsrequest event.");
|
||||
ok(event.target.error, "domerror obj");
|
||||
log("sms.getMessages error: " + event.target.error.name);
|
||||
ok(false,"Could not get SMS messages");
|
||||
cleanUp();
|
||||
};
|
||||
}
|
||||
|
||||
function deleteMsgs(msgList, nextFunction) {
|
||||
let smsId = msgList.shift();
|
||||
|
||||
log("Deleting SMS (id: " + smsId + ").");
|
||||
let request = sms.delete(smsId);
|
||||
ok(request instanceof MozSmsRequest,
|
||||
"request is instanceof " + request.constructor);
|
||||
|
||||
request.onsuccess = function(event) {
|
||||
log("Received 'onsuccess' smsrequest event.");
|
||||
if (event.target.result) {
|
||||
// Message deleted, continue until none are left
|
||||
if (msgList.length) {
|
||||
deleteMsgs(msgList, nextFunction);
|
||||
} else {
|
||||
log("Finished deleting SMS messages.");
|
||||
nextFunction();
|
||||
}
|
||||
} else {
|
||||
log("SMS delete failed.");
|
||||
ok(false,"sms.delete request returned false");
|
||||
cleanUp();
|
||||
}
|
||||
};
|
||||
|
||||
request.onerror = function(event) {
|
||||
log("Received 'onerror' smsrequest event.");
|
||||
ok(event.target.error, "domerror obj");
|
||||
ok(false, "sms.delete request returned unexpected error: "
|
||||
+ event.target.error.name );
|
||||
cleanUp();
|
||||
};
|
||||
}
|
||||
|
||||
function simulateIncomingSms() {
|
||||
let text = "Incoming SMS number " + (smsList.length + 1);
|
||||
let remoteNumber = "5552229797";
|
||||
|
||||
log("Simulating incoming SMS number " + (smsList.length + 1) + " of "
|
||||
+ numberMsgs + ".");
|
||||
|
||||
// Simulate incoming sms sent from remoteNumber to our emulator
|
||||
rcvdEmulatorCallback = false;
|
||||
runEmulatorCmd("sms send " + remoteNumber + " " + text, function(result) {
|
||||
is(result[0], "OK", "emulator callback");
|
||||
rcvdEmulatorCallback = true;
|
||||
});
|
||||
}
|
||||
|
||||
// Callback for incoming sms
|
||||
sms.onreceived = function onreceived(event) {
|
||||
log("Received 'onreceived' sms event.");
|
||||
let incomingSms = event.message;
|
||||
log("Received SMS (id: " + incomingSms.id + ").");
|
||||
|
||||
// Add newly received message to array of received msgs
|
||||
smsList.push(incomingSms);
|
||||
|
||||
// Wait for emulator to catch up before continuing
|
||||
waitFor(nextRep,function() {
|
||||
return(rcvdEmulatorCallback);
|
||||
});
|
||||
};
|
||||
|
||||
function nextRep() {
|
||||
if (smsList.length < numberMsgs) {
|
||||
simulateIncomingSms();
|
||||
} else {
|
||||
// Marking all messages except first as read
|
||||
// Can remove first one from smsList array
|
||||
smsList.shift();
|
||||
markMsgRead(smsList.slice(0));
|
||||
}
|
||||
}
|
||||
|
||||
function markMsgRead(smsMsgs) {
|
||||
nextSms = smsMsgs.shift();
|
||||
log("Marking SMS (id: " + nextSms.id + ") as read.");
|
||||
let request = sms.markMessageRead(nextSms.id, true);
|
||||
ok(request instanceof MozSmsRequest,
|
||||
"request is instanceof " + request.constructor);
|
||||
|
||||
request.onsuccess = function(event) {
|
||||
log("Received 'onsuccess' smsrequest event.");
|
||||
if (event.target.result) {
|
||||
// Message marked as read, continue until none are left
|
||||
if (smsMsgs.length) {
|
||||
markMsgRead(smsMsgs);
|
||||
} else {
|
||||
// Done, now test the filter
|
||||
getMsgs();
|
||||
}
|
||||
} else {
|
||||
log("SMS markMessageRead failed.");
|
||||
ok(false,"sms.markMessageRead request returned false");
|
||||
cleanUp();
|
||||
}
|
||||
};
|
||||
|
||||
request.onerror = function(event) {
|
||||
log("Received 'onerror' smsrequest event.");
|
||||
ok(event.target.error, "domerror obj");
|
||||
ok(false, "sms.markMessageRead request returned unexpected error: "
|
||||
+ event.target.error.name );
|
||||
cleanUp();
|
||||
};
|
||||
}
|
||||
|
||||
function getMsgs() {
|
||||
var filter = new MozSmsFilter();
|
||||
let foundSmsList = new Array();
|
||||
|
||||
// Set filter for read messages
|
||||
filter.read = true;
|
||||
|
||||
log("Getting the read SMS messages.");
|
||||
let request = sms.getMessages(filter, false);
|
||||
ok(request instanceof MozSmsRequest,
|
||||
"request is instanceof " + request.constructor);
|
||||
|
||||
request.onsuccess = function(event) {
|
||||
log("Received 'onsuccess' smsrequest event.");
|
||||
ok(event.target.result, "smsrequest event.target.result");
|
||||
cursor = event.target.result;
|
||||
|
||||
if (cursor.message) {
|
||||
// Another message found
|
||||
log("Got SMS (id: " + cursor.message.id + ").");
|
||||
// Store found message
|
||||
foundSmsList.push(cursor.message);
|
||||
// Now get next message in the list
|
||||
cursor.continue();
|
||||
} else {
|
||||
// No more messages; ensure correct number found
|
||||
if (foundSmsList.length == smsList.length) {
|
||||
log("SMS getMessages returned " + foundSmsList.length +
|
||||
" messages as expected.");
|
||||
verifyFoundMsgs(foundSmsList);
|
||||
} else {
|
||||
log("SMS getMessages returned " + foundSmsList.length +
|
||||
" messages, but expected " + smsList.length + ".");
|
||||
ok(false, "Incorrect number of messages returned by sms.getMessages");
|
||||
deleteAllMsgs(cleanUp);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
request.onerror = function(event) {
|
||||
log("Received 'onerror' smsrequest event.");
|
||||
ok(event.target.error, "domerror obj");
|
||||
log("sms.getMessages error: " + event.target.error.name);
|
||||
ok(false,"Could not get SMS messages");
|
||||
cleanUp();
|
||||
};
|
||||
}
|
||||
|
||||
function verifyFoundMsgs(foundSmsList) {
|
||||
for (var x = 0; x < foundSmsList.length; x++) {
|
||||
is(foundSmsList[x].id, smsList[x].id, "id");
|
||||
is(foundSmsList[x].read, true, "read");
|
||||
}
|
||||
deleteAllMsgs(cleanUp);
|
||||
}
|
||||
|
||||
function cleanUp() {
|
||||
sms.onreceived = null;
|
||||
SpecialPowers.removePermission("sms", document);
|
||||
SpecialPowers.clearUserPref("dom.sms.enabled");
|
||||
finish();
|
||||
}
|
||||
|
||||
// Start the test
|
||||
verifyInitialState();
|
223
dom/sms/tests/marionette/test_filter_unread.js
Normal file
223
dom/sms/tests/marionette/test_filter_unread.js
Normal file
@ -0,0 +1,223 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
MARIONETTE_TIMEOUT = 20000;
|
||||
|
||||
SpecialPowers.addPermission("sms", true, document);
|
||||
SpecialPowers.setBoolPref("dom.sms.enabled", true);
|
||||
|
||||
let sms = window.navigator.mozSms;
|
||||
let numberMsgs = 10;
|
||||
let smsList = new Array();
|
||||
|
||||
function verifyInitialState() {
|
||||
log("Verifying initial state.");
|
||||
ok(sms, "mozSms");
|
||||
// Ensure test is starting clean with no existing sms messages
|
||||
deleteAllMsgs(simulateIncomingSms);
|
||||
}
|
||||
|
||||
function deleteAllMsgs(nextFunction) {
|
||||
let msgList = new Array();
|
||||
let filter = new MozSmsFilter;
|
||||
|
||||
let request = sms.getMessages(filter, false);
|
||||
ok(request instanceof MozSmsRequest,
|
||||
"request is instanceof " + request.constructor);
|
||||
|
||||
request.onsuccess = function(event) {
|
||||
ok(event.target.result, "smsrequest event.target.result");
|
||||
cursor = event.target.result;
|
||||
// Check if message was found
|
||||
if (cursor.message) {
|
||||
msgList.push(cursor.message.id);
|
||||
// Now get next message in the list
|
||||
cursor.continue();
|
||||
} else {
|
||||
// No (more) messages found
|
||||
if (msgList.length) {
|
||||
log("Found " + msgList.length + " SMS messages to delete.");
|
||||
deleteMsgs(msgList, nextFunction);
|
||||
} else {
|
||||
log("No SMS messages found.");
|
||||
nextFunction();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
request.onerror = function(event) {
|
||||
log("Received 'onerror' smsrequest event.");
|
||||
ok(event.target.error, "domerror obj");
|
||||
log("sms.getMessages error: " + event.target.error.name);
|
||||
ok(false,"Could not get SMS messages");
|
||||
cleanUp();
|
||||
};
|
||||
}
|
||||
|
||||
function deleteMsgs(msgList, nextFunction) {
|
||||
let smsId = msgList.shift();
|
||||
|
||||
log("Deleting SMS (id: " + smsId + ").");
|
||||
let request = sms.delete(smsId);
|
||||
ok(request instanceof MozSmsRequest,
|
||||
"request is instanceof " + request.constructor);
|
||||
|
||||
request.onsuccess = function(event) {
|
||||
log("Received 'onsuccess' smsrequest event.");
|
||||
if (event.target.result) {
|
||||
// Message deleted, continue until none are left
|
||||
if (msgList.length) {
|
||||
deleteMsgs(msgList, nextFunction);
|
||||
} else {
|
||||
log("Finished deleting SMS messages.");
|
||||
nextFunction();
|
||||
}
|
||||
} else {
|
||||
log("SMS delete failed.");
|
||||
ok(false,"sms.delete request returned false");
|
||||
cleanUp();
|
||||
}
|
||||
};
|
||||
|
||||
request.onerror = function(event) {
|
||||
log("Received 'onerror' smsrequest event.");
|
||||
ok(event.target.error, "domerror obj");
|
||||
ok(false, "sms.delete request returned unexpected error: "
|
||||
+ event.target.error.name );
|
||||
cleanUp();
|
||||
};
|
||||
}
|
||||
|
||||
function simulateIncomingSms() {
|
||||
let text = "Incoming SMS number " + (smsList.length + 1);
|
||||
let remoteNumber = "5552229797";
|
||||
|
||||
log("Simulating incoming SMS number " + (smsList.length + 1) + " of "
|
||||
+ numberMsgs + ".");
|
||||
|
||||
// Simulate incoming sms sent from remoteNumber to our emulator
|
||||
rcvdEmulatorCallback = false;
|
||||
runEmulatorCmd("sms send " + remoteNumber + " " + text, function(result) {
|
||||
is(result[0], "OK", "emulator callback");
|
||||
rcvdEmulatorCallback = true;
|
||||
});
|
||||
}
|
||||
|
||||
// Callback for incoming sms
|
||||
sms.onreceived = function onreceived(event) {
|
||||
log("Received 'onreceived' sms event.");
|
||||
let incomingSms = event.message;
|
||||
log("Received SMS (id: " + incomingSms.id + ").");
|
||||
|
||||
// Add newly received message to array of received msgs
|
||||
smsList.push(incomingSms);
|
||||
|
||||
// Wait for emulator to catch up before continuing
|
||||
waitFor(nextRep,function() {
|
||||
return(rcvdEmulatorCallback);
|
||||
});
|
||||
};
|
||||
|
||||
function nextRep() {
|
||||
if (smsList.length < numberMsgs) {
|
||||
simulateIncomingSms();
|
||||
} else {
|
||||
markMsgRead();
|
||||
}
|
||||
}
|
||||
|
||||
function markMsgRead() {
|
||||
// Mark first message read so not all will be found by filter
|
||||
log("Marking SMS (id: " + smsList[0].id + ") as read.");
|
||||
let request = sms.markMessageRead(smsList[0].id, true);
|
||||
ok(request instanceof MozSmsRequest,
|
||||
"request is instanceof " + request.constructor);
|
||||
|
||||
request.onsuccess = function(event) {
|
||||
log("Received 'onsuccess' smsrequest event.");
|
||||
if (event.target.result) {
|
||||
// First message was marked read, so remove from expected smsList
|
||||
smsList.shift();
|
||||
// Now test the filter
|
||||
getMsgs();
|
||||
} else {
|
||||
log("SMS markMessageRead failed.");
|
||||
ok(false,"sms.markMessageRead request returned false");
|
||||
cleanUp();
|
||||
}
|
||||
};
|
||||
|
||||
request.onerror = function(event) {
|
||||
log("Received 'onerror' smsrequest event.");
|
||||
ok(event.target.error, "domerror obj");
|
||||
ok(false, "sms.markMessageRead request returned unexpected error: "
|
||||
+ event.target.error.name );
|
||||
cleanUp();
|
||||
};
|
||||
}
|
||||
|
||||
function getMsgs() {
|
||||
var filter = new MozSmsFilter();
|
||||
let foundSmsList = new Array();
|
||||
|
||||
// Set filter for read messages
|
||||
filter.read = false;
|
||||
|
||||
log("Getting the unread SMS messages.");
|
||||
let request = sms.getMessages(filter, false);
|
||||
ok(request instanceof MozSmsRequest,
|
||||
"request is instanceof " + request.constructor);
|
||||
|
||||
request.onsuccess = function(event) {
|
||||
log("Received 'onsuccess' smsrequest event.");
|
||||
ok(event.target.result, "smsrequest event.target.result");
|
||||
cursor = event.target.result;
|
||||
|
||||
if (cursor.message) {
|
||||
// Another message found
|
||||
log("Got SMS (id: " + cursor.message.id + ").");
|
||||
// Store found message
|
||||
foundSmsList.push(cursor.message);
|
||||
// Now get next message in the list
|
||||
cursor.continue();
|
||||
} else {
|
||||
// No more messages; ensure correct number found
|
||||
if (foundSmsList.length == smsList.length) {
|
||||
log("SMS getMessages returned " + foundSmsList.length +
|
||||
" messages as expected.");
|
||||
verifyFoundMsgs(foundSmsList);
|
||||
} else {
|
||||
log("SMS getMessages returned " + foundSmsList.length +
|
||||
" messages, but expected " + smsList.length + ".");
|
||||
ok(false, "Incorrect number of messages returned by sms.getMessages");
|
||||
deleteAllMsgs(cleanUp);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
request.onerror = function(event) {
|
||||
log("Received 'onerror' smsrequest event.");
|
||||
ok(event.target.error, "domerror obj");
|
||||
log("sms.getMessages error: " + event.target.error.name);
|
||||
ok(false,"Could not get SMS messages");
|
||||
cleanUp();
|
||||
};
|
||||
}
|
||||
|
||||
function verifyFoundMsgs(foundSmsList) {
|
||||
for (var x = 0; x < foundSmsList.length; x++) {
|
||||
is(foundSmsList[x].id, smsList[x].id, "id");
|
||||
is(foundSmsList[x].read, false, "read");
|
||||
}
|
||||
deleteAllMsgs(cleanUp);
|
||||
}
|
||||
|
||||
function cleanUp() {
|
||||
sms.onreceived = null;
|
||||
SpecialPowers.removePermission("sms", document);
|
||||
SpecialPowers.clearUserPref("dom.sms.enabled");
|
||||
finish();
|
||||
}
|
||||
|
||||
// Start the test
|
||||
verifyInitialState();
|
76
dom/sms/tests/marionette/test_number_of_messages.js
Normal file
76
dom/sms/tests/marionette/test_number_of_messages.js
Normal file
@ -0,0 +1,76 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
MARIONETTE_TIMEOUT = 10000;
|
||||
|
||||
SpecialPowers.addPermission("sms", true, document);
|
||||
SpecialPowers.setBoolPref("dom.sms.enabled", true);
|
||||
|
||||
let sms = window.navigator.mozSms;
|
||||
|
||||
// Specified here: https://developer.mozilla.org/en-US/docs/DOM/SmsManager
|
||||
let maxCharsPerSms = 160;
|
||||
|
||||
function verifyInitialState() {
|
||||
log("Verifying initial state.");
|
||||
ok(sms, "mozSms");
|
||||
// Ensure test is starting clean with no existing SMS messages
|
||||
startTest();
|
||||
}
|
||||
|
||||
function startTest() {
|
||||
// Build test data strings
|
||||
let testData = ["", "a",
|
||||
buildString("b", maxCharsPerSms / 2),
|
||||
buildString("c", maxCharsPerSms - 1),
|
||||
buildString("d", maxCharsPerSms),
|
||||
buildString("e", maxCharsPerSms + 1),
|
||||
buildString("f", maxCharsPerSms * 1.5),
|
||||
buildString("g", maxCharsPerSms * 10.5)];
|
||||
|
||||
// Test with each data string
|
||||
testData.forEach(function(text){ testGetNumberOfMsgs(text); });
|
||||
|
||||
// We're done
|
||||
cleanUp();
|
||||
}
|
||||
|
||||
function buildString(char, numChars) {
|
||||
// Build string that contains the specified character repeated x times
|
||||
let string = new Array(numChars + 1).join(char);
|
||||
return string;
|
||||
}
|
||||
|
||||
function testGetNumberOfMsgs(text) {
|
||||
// Test that getNumberOfMessagesForText returns expected value for given txt
|
||||
log("getNumberOfMessagesForText length " + text.length + ".");
|
||||
|
||||
if (text.length) {
|
||||
if (text.length > maxCharsPerSms) {
|
||||
expNumSms = Math.ceil(text.length / maxCharsPerSms);
|
||||
} else {
|
||||
expNumSms = 1;
|
||||
}
|
||||
} else {
|
||||
expNumSms = 0;
|
||||
}
|
||||
|
||||
numMultiPartSms = sms.getNumberOfMessagesForText(text);
|
||||
|
||||
if (numMultiPartSms == expNumSms) {
|
||||
log("Returned " + expNumSms + " as expected.");
|
||||
ok(true, "getNumberOfMessagesForText returned expected value");
|
||||
} else {
|
||||
log("Returned " + numMultiPartSms + " but expected " + expNumSms + ".");
|
||||
ok(false, "getNumberOfMessagesForText returned unexpected value");
|
||||
}
|
||||
}
|
||||
|
||||
function cleanUp() {
|
||||
SpecialPowers.removePermission("sms", document);
|
||||
SpecialPowers.clearUserPref("dom.sms.enabled");
|
||||
finish();
|
||||
}
|
||||
|
||||
// Start the test
|
||||
verifyInitialState();
|
@ -353,6 +353,13 @@ nsGeolocationRequest::GetType(nsACString & aType)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsGeolocationRequest::GetAccess(nsACString & aAccess)
|
||||
{
|
||||
aAccess = "unused";
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsGeolocationRequest::GetWindow(nsIDOMWindow * *aRequestingWindow)
|
||||
{
|
||||
@ -746,11 +753,10 @@ nsGeolocationService::HandleMozsettingValue(const bool aValue)
|
||||
}
|
||||
|
||||
if (sGeoInitPending) {
|
||||
sGeoInitPending = false;
|
||||
for (uint32_t i = 0, length = mGeolocators.Length(); i < length; ++i) {
|
||||
mGeolocators[i]->ServiceReady();
|
||||
}
|
||||
|
||||
sGeoInitPending = false;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1412,9 +1418,10 @@ nsGeolocation::RegisterRequestWithPrompt(nsGeolocationRequest* request)
|
||||
// Retain a reference so the object isn't deleted without IPDL's knowledge.
|
||||
// Corresponding release occurs in DeallocPContentPermissionRequest.
|
||||
request->AddRef();
|
||||
|
||||
nsCString type = NS_LITERAL_CSTRING("geolocation");
|
||||
child->SendPContentPermissionRequestConstructor(request, type, IPC::Principal(mPrincipal));
|
||||
child->SendPContentPermissionRequestConstructor(request,
|
||||
NS_LITERAL_CSTRING("geolocation"),
|
||||
NS_LITERAL_CSTRING("unused"),
|
||||
IPC::Principal(mPrincipal));
|
||||
|
||||
request->Sendprompt();
|
||||
return true;
|
||||
|
@ -106,8 +106,10 @@ nsDOMDesktopNotification::nsDOMDesktopNotification(const nsAString & title,
|
||||
// Corresponding release occurs in DeallocPContentPermissionRequest.
|
||||
nsRefPtr<nsDesktopNotificationRequest> copy = request;
|
||||
|
||||
nsCString type = NS_LITERAL_CSTRING("desktop-notification");
|
||||
child->SendPContentPermissionRequestConstructor(copy.forget().get(), type, IPC::Principal(mPrincipal));
|
||||
child->SendPContentPermissionRequestConstructor(request,
|
||||
NS_LITERAL_CSTRING("desktop-notification"),
|
||||
NS_LITERAL_CSTRING("unused"),
|
||||
IPC::Principal(mPrincipal));
|
||||
|
||||
request->Sendprompt();
|
||||
return;
|
||||
@ -271,3 +273,9 @@ nsDesktopNotificationRequest::GetType(nsACString & aType)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDesktopNotificationRequest::GetAccess(nsACString & aAccess)
|
||||
{
|
||||
aAccess = "unused";
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -281,6 +281,8 @@ function RadioInterfaceLayer() {
|
||||
|
||||
this.portAddressedSmsApps = {};
|
||||
this.portAddressedSmsApps[WAP.WDP_PORT_PUSH] = this.handleSmsWdpPortPush.bind(this);
|
||||
|
||||
this._targetMessageQueue = [];
|
||||
}
|
||||
RadioInterfaceLayer.prototype = {
|
||||
|
||||
@ -657,6 +659,12 @@ RadioInterfaceLayer.prototype = {
|
||||
},
|
||||
|
||||
_sendTargetMessage: function _sendTargetMessage(permission, message, options) {
|
||||
|
||||
if (!this._sysMsgListenerReady) {
|
||||
this._enqueueTargetMessage(permission, message, options);
|
||||
return;
|
||||
}
|
||||
|
||||
let targets = this._messageManagerByPermission[permission];
|
||||
if (!targets) {
|
||||
return;
|
||||
@ -924,6 +932,36 @@ RadioInterfaceLayer.prototype = {
|
||||
this._ensureRadioState();
|
||||
},
|
||||
|
||||
_enqueueTargetMessage: function _enqueueTargetMessage(permission, message, options) {
|
||||
let msg = { permission : permission,
|
||||
message : message,
|
||||
options : options };
|
||||
// Remove previous queued message of same message type, only one message
|
||||
// per message type is allowed in queue.
|
||||
let messageQueue = this._targetMessageQueue;
|
||||
for(let i = 0; i < messageQueue.length; i++) {
|
||||
if (messageQueue[i].message === message) {
|
||||
messageQueue.splice(i, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
messageQueue.push(msg);
|
||||
},
|
||||
|
||||
_resendQueuedTargetMessage: function _resendQueuedTargetMessage() {
|
||||
// Here uses this._sendTargetMessage() to resend message, which will
|
||||
// enqueue message if listener is not ready.
|
||||
// So only resend after listener is ready, or it will cause infinate loop and
|
||||
// hang the system.
|
||||
|
||||
// Dequeue and resend messages.
|
||||
for each (let msg in this._targetMessageQueue) {
|
||||
this._sendTargetMessage(msg.permission, msg.message, msg.options);
|
||||
}
|
||||
this._targetMessageQueue = null;
|
||||
},
|
||||
|
||||
_ensureRadioState: function _ensureRadioState() {
|
||||
debug("Reported radio state is " + this.rilContext.radioState +
|
||||
", desired radio enabled state is " + this._radioEnabled);
|
||||
@ -1490,6 +1528,7 @@ RadioInterfaceLayer.prototype = {
|
||||
case kSysMsgListenerReadyObserverTopic:
|
||||
Services.obs.removeObserver(this, kSysMsgListenerReadyObserverTopic);
|
||||
this._sysMsgListenerReady = true;
|
||||
this._resendQueuedTargetMessage();
|
||||
this._ensureRadioState();
|
||||
break;
|
||||
case kMozSettingsChangedObserverTopic:
|
||||
|
@ -587,63 +587,108 @@ BasicBufferOGL::BeginPaint(ContentType aContentType,
|
||||
// TEXTURE_2D. This isn't the case on some older X1600-era Radeons.
|
||||
if (mOGLLayer->OGLManager()->FBOTextureTarget() == LOCAL_GL_TEXTURE_2D) {
|
||||
nsIntRect overlap;
|
||||
|
||||
// The buffer looks like:
|
||||
// ______
|
||||
// |1 |2 | Where the center point is offset by mBufferRotation from the top-left corner.
|
||||
// |___|__|
|
||||
// |3 |4 |
|
||||
// |___|__|
|
||||
//
|
||||
// This is drawn to the screen as:
|
||||
// ______
|
||||
// |4 |3 | Where the center point is { width - mBufferRotation.x, height - mBufferRotation.y } from
|
||||
// |___|__| from the top left corner - rotationPoint.
|
||||
// |2 |1 |
|
||||
// |___|__|
|
||||
//
|
||||
|
||||
// The basic idea below is to take all quadrant rectangles from the src and transform them into rectangles
|
||||
// in the destination. Unfortunately, it seems it is overly complex and could perhaps be simplified.
|
||||
|
||||
nsIntRect srcBufferSpaceBottomRight(mBufferRotation.x, mBufferRotation.y, mBufferRect.width - mBufferRotation.x, mBufferRect.height - mBufferRotation.y);
|
||||
nsIntRect srcBufferSpaceTopRight(mBufferRotation.x, 0, mBufferRect.width - mBufferRotation.x, mBufferRotation.y);
|
||||
nsIntRect srcBufferSpaceTopLeft(0, 0, mBufferRotation.x, mBufferRotation.y);
|
||||
nsIntRect srcBufferSpaceBottomLeft(0, mBufferRotation.y, mBufferRotation.x, mBufferRect.height - mBufferRotation.y);
|
||||
|
||||
overlap.IntersectRect(mBufferRect, destBufferRect);
|
||||
|
||||
nsIntRect srcRect(overlap), dstRect(overlap);
|
||||
srcRect.MoveBy(- mBufferRect.TopLeft() + mBufferRotation);
|
||||
dstRect.MoveBy(- destBufferRect.TopLeft());
|
||||
|
||||
if (mBufferRotation != nsIntPoint(0, 0)) {
|
||||
// If mBuffer is rotated, then BlitTextureImage will only be copying the bottom-right section
|
||||
// of the buffer. We need to invalidate the remaining sections so that they get redrawn too.
|
||||
// Alternatively we could teach BlitTextureImage to rearrange the rotated segments onto
|
||||
// the new buffer.
|
||||
|
||||
// When the rotated buffer is reorganised, the bottom-right section will be drawn in the top left.
|
||||
// Find the point where this content ends.
|
||||
nsIntPoint rotationPoint(mBufferRect.x + mBufferRect.width - mBufferRotation.x,
|
||||
mBufferRect.y + mBufferRect.height - mBufferRotation.y);
|
||||
|
||||
// The buffer looks like:
|
||||
// ______
|
||||
// |1 |2 | Where the center point is offset by mBufferRotation from the top-left corner.
|
||||
// |___|__|
|
||||
// |3 |4 |
|
||||
// |___|__|
|
||||
//
|
||||
// This is drawn to the screen as:
|
||||
// ______
|
||||
// |4 |3 | Where the center point is { width - mBufferRotation.x, height - mBufferRotation.y } from
|
||||
// |___|__| from the top left corner - rotationPoint. Since only quadrant 4 will actually be copied,
|
||||
// |2 |1 | we need to invalidate the others.
|
||||
// |___|__|
|
||||
//
|
||||
// Quadrants 2 and 1
|
||||
nsIntRect bottom(mBufferRect.x, rotationPoint.y, mBufferRect.width, mBufferRotation.y);
|
||||
// Quadrant 3
|
||||
nsIntRect topright(rotationPoint.x, mBufferRect.y, mBufferRotation.x, rotationPoint.y - mBufferRect.y);
|
||||
nsIntRect srcRectDrawTopRight(srcRect);
|
||||
nsIntRect srcRectDrawTopLeft(srcRect);
|
||||
nsIntRect srcRectDrawBottomLeft(srcRect);
|
||||
// transform into the different quadrants
|
||||
srcRectDrawTopRight .MoveBy(-nsIntPoint(0, mBufferRect.height));
|
||||
srcRectDrawTopLeft .MoveBy(-nsIntPoint(mBufferRect.width, mBufferRect.height));
|
||||
srcRectDrawBottomLeft.MoveBy(-nsIntPoint(mBufferRect.width, 0));
|
||||
|
||||
if (!bottom.IsEmpty()) {
|
||||
nsIntRegion temp;
|
||||
temp.And(destBufferRect, bottom);
|
||||
result.mRegionToDraw.Or(result.mRegionToDraw, temp);
|
||||
}
|
||||
if (!topright.IsEmpty()) {
|
||||
nsIntRegion temp;
|
||||
temp.And(destBufferRect, topright);
|
||||
result.mRegionToDraw.Or(result.mRegionToDraw, temp);
|
||||
}
|
||||
}
|
||||
// Intersect with the quadrant
|
||||
srcRect = srcRect .Intersect(srcBufferSpaceBottomRight);
|
||||
srcRectDrawTopRight = srcRectDrawTopRight .Intersect(srcBufferSpaceTopRight);
|
||||
srcRectDrawTopLeft = srcRectDrawTopLeft .Intersect(srcBufferSpaceTopLeft);
|
||||
srcRectDrawBottomLeft = srcRectDrawBottomLeft.Intersect(srcBufferSpaceBottomLeft);
|
||||
|
||||
dstRect = srcRect;
|
||||
nsIntRect dstRectDrawTopRight(srcRectDrawTopRight);
|
||||
nsIntRect dstRectDrawTopLeft(srcRectDrawTopLeft);
|
||||
nsIntRect dstRectDrawBottomLeft(srcRectDrawBottomLeft);
|
||||
|
||||
// transform back to src buffer space
|
||||
dstRect .MoveBy(-mBufferRotation);
|
||||
dstRectDrawTopRight .MoveBy(-mBufferRotation + nsIntPoint(0, mBufferRect.height));
|
||||
dstRectDrawTopLeft .MoveBy(-mBufferRotation + nsIntPoint(mBufferRect.width, mBufferRect.height));
|
||||
dstRectDrawBottomLeft.MoveBy(-mBufferRotation + nsIntPoint(mBufferRect.width, 0));
|
||||
|
||||
// transform back to draw coordinates
|
||||
dstRect .MoveBy(mBufferRect.TopLeft());
|
||||
dstRectDrawTopRight .MoveBy(mBufferRect.TopLeft());
|
||||
dstRectDrawTopLeft .MoveBy(mBufferRect.TopLeft());
|
||||
dstRectDrawBottomLeft.MoveBy(mBufferRect.TopLeft());
|
||||
|
||||
// transform to destBuffer space
|
||||
dstRect .MoveBy(-destBufferRect.TopLeft());
|
||||
dstRectDrawTopRight .MoveBy(-destBufferRect.TopLeft());
|
||||
dstRectDrawTopLeft .MoveBy(-destBufferRect.TopLeft());
|
||||
dstRectDrawBottomLeft.MoveBy(-destBufferRect.TopLeft());
|
||||
|
||||
destBuffer->Resize(destBufferRect.Size());
|
||||
|
||||
gl()->BlitTextureImage(mTexImage, srcRect,
|
||||
destBuffer, dstRect);
|
||||
if (mBufferRotation != nsIntPoint(0, 0)) {
|
||||
// Draw the remaining quadrants. We call BlitTextureImage 3 extra
|
||||
// times instead of doing a single draw call because supporting that
|
||||
// with a tiled source is quite tricky.
|
||||
if (!srcRectDrawTopRight.IsEmpty())
|
||||
gl()->BlitTextureImage(mTexImage, srcRectDrawTopRight,
|
||||
destBuffer, dstRectDrawTopRight);
|
||||
if (!srcRectDrawTopLeft.IsEmpty())
|
||||
gl()->BlitTextureImage(mTexImage, srcRectDrawTopLeft,
|
||||
destBuffer, dstRectDrawTopLeft);
|
||||
if (!srcRectDrawBottomLeft.IsEmpty())
|
||||
gl()->BlitTextureImage(mTexImage, srcRectDrawBottomLeft,
|
||||
destBuffer, dstRectDrawBottomLeft);
|
||||
}
|
||||
destBuffer->MarkValid();
|
||||
if (mode == Layer::SURFACE_COMPONENT_ALPHA) {
|
||||
destBufferOnWhite->Resize(destBufferRect.Size());
|
||||
gl()->BlitTextureImage(mTexImageOnWhite, srcRect,
|
||||
destBufferOnWhite, dstRect);
|
||||
if (mBufferRotation != nsIntPoint(0, 0)) {
|
||||
// draw the remaining quadrants
|
||||
if (!srcRectDrawTopRight.IsEmpty())
|
||||
gl()->BlitTextureImage(mTexImageOnWhite, srcRectDrawTopRight,
|
||||
destBufferOnWhite, dstRectDrawTopRight);
|
||||
if (!srcRectDrawTopLeft.IsEmpty())
|
||||
gl()->BlitTextureImage(mTexImageOnWhite, srcRectDrawTopLeft,
|
||||
destBufferOnWhite, dstRectDrawTopLeft);
|
||||
if (!srcRectDrawBottomLeft.IsEmpty())
|
||||
gl()->BlitTextureImage(mTexImageOnWhite, srcRectDrawBottomLeft,
|
||||
destBufferOnWhite, dstRectDrawBottomLeft);
|
||||
}
|
||||
|
||||
destBufferOnWhite->MarkValid();
|
||||
}
|
||||
} else {
|
||||
|
@ -3393,8 +3393,8 @@ RasterImage::DecodeWorker::Run()
|
||||
EnsurePendingInEventLoop();
|
||||
}
|
||||
|
||||
Telemetry::Accumulate(Telemetry::IMAGE_DECODE_LATENCY,
|
||||
uint32_t((TimeStamp::Now() - eventStart).ToMilliseconds()));
|
||||
Telemetry::Accumulate(Telemetry::IMAGE_DECODE_LATENCY_US,
|
||||
uint32_t((TimeStamp::Now() - eventStart).ToMicroseconds()));
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -117,7 +117,6 @@ x-iso-10646-ucs-2-be=UTF-16BE
|
||||
x-iso-10646-ucs-2-le=UTF-16LE
|
||||
x-user-defined=x-user-defined
|
||||
x-johab=x-johab
|
||||
x-windows-949=x-windows-949
|
||||
#
|
||||
# Aliases for ISO-8859-1
|
||||
#
|
||||
@ -277,8 +276,7 @@ zh_tw-big5=Big5
|
||||
# Aliases for EUC-KR
|
||||
#
|
||||
cseuckr=EUC-KR
|
||||
# The following are really not aliases EUC-KR, add them only for MS FrontPage
|
||||
#ks_c_5601-1987=EUC-KR
|
||||
ks_c_5601-1987=EUC-KR
|
||||
iso-ir-149=EUC-KR
|
||||
ks_c_5601-1989=EUC-KR
|
||||
ksc_5601=EUC-KR
|
||||
@ -286,11 +284,7 @@ ksc5601=EUC-KR
|
||||
korean=EUC-KR
|
||||
csksc56011987=EUC-KR
|
||||
5601=EUC-KR
|
||||
#
|
||||
# Aliases for X-Windows-949, CP949, Unified Hangul Code (UHC)
|
||||
#
|
||||
# Microsoft uses ks_c_5601-1987 to mean Windows-949 or its subset EUC-KR.
|
||||
ks_c_5601-1987=x-windows-949
|
||||
windows-949=EUC-KR
|
||||
#
|
||||
# Aliases for GB2312
|
||||
#
|
||||
|
@ -9,7 +9,7 @@
|
||||
acp.874=TIS-620
|
||||
acp.932=Shift_JIS
|
||||
acp.936=gb18030
|
||||
acp.949=x-windows-949
|
||||
acp.949=EUC-KR
|
||||
acp.950=Big5
|
||||
acp.951=Big5-HKSCS
|
||||
acp.1250=windows-1250
|
||||
|
@ -15,7 +15,7 @@ The following directories contain different charset converters:
|
||||
ucvcn - Simplified Chinese charsets - GB2312, HZ, ISO-2022-CN, GBK, GB18030
|
||||
ucvibm - IBM charsets - CP850, 852, 855, 857, 862, 864, 869, 1125, 1131
|
||||
ucvja - Japanese charsets - Shift-JIS, ISO-2022-JP, EUC-JP
|
||||
ucvko - Korean charsets - ISO-2022-KR, EUC-KR, CP949
|
||||
ucvko - Korean charsets - ISO-2022-KR, EUC-KR, Johab
|
||||
ucvlatin - Latin charsets and others - ISO-8859-x, CP1250-1258
|
||||
CP866, 874, ARMSCII, ISO-IR-111, KOI8,
|
||||
Mac charsets, T61, TIS620, TCVN, VISCII, VPS
|
||||
|
@ -69,7 +69,6 @@ ibm1131.notForOutgoing = true
|
||||
iso-8859-8-e.notForOutgoing = true
|
||||
iso-8859-8.notForOutgoing = true
|
||||
iso-2022-kr.notForOutgoing = true
|
||||
x-windows-949.notForOutgoing = true
|
||||
x-johab.notForOutgoing = true
|
||||
|
||||
|
||||
@ -186,7 +185,6 @@ x-mac-romanian.LangGroup = x-central-euro
|
||||
x-user-defined.LangGroup = x-user-def
|
||||
ks_c_5601-1987.LangGroup = ko
|
||||
x-johab.LangGroup = ko
|
||||
x-windows-949.LangGroup = ko
|
||||
x-mac-hebrew.LangGroup = he
|
||||
x-mac-arabic.LangGroup = ar
|
||||
x-sun-unicode-india-0.LangGroup = x-devanagari
|
||||
@ -204,6 +202,5 @@ hz-gb-2312.isMultibyte = true
|
||||
iso-2022-kr.isMultibyte = true
|
||||
euc-kr.isMultibyte = true
|
||||
x-johab.isMultibyte = true
|
||||
x-windows-949.isMultibyte = true
|
||||
utf-7.isMultibyte = true
|
||||
utf-8.isMultibyte = true
|
||||
|
@ -210,8 +210,6 @@
|
||||
// ucvko
|
||||
#include "nsUCvKOCID.h"
|
||||
#include "nsUCvKODll.h"
|
||||
#include "nsEUCKRToUnicode.h"
|
||||
#include "nsUnicodeToEUCKR.h"
|
||||
#include "nsJohabToUnicode.h"
|
||||
#include "nsUnicodeToJohab.h"
|
||||
#include "nsCP949ToUnicode.h"
|
||||
@ -333,7 +331,6 @@ NS_UCONV_REG_UNREG_ENCODER("hkscs-1" , NS_UNICODETOHKSCS_CID)
|
||||
// ucvko
|
||||
NS_UCONV_REG_UNREG("EUC-KR", NS_EUCKRTOUNICODE_CID, NS_UNICODETOEUCKR_CID)
|
||||
NS_UCONV_REG_UNREG("x-johab", NS_JOHABTOUNICODE_CID, NS_UNICODETOJOHAB_CID)
|
||||
NS_UCONV_REG_UNREG("x-windows-949", NS_CP949TOUNICODE_CID, NS_UNICODETOCP949_CID)
|
||||
NS_UCONV_REG_UNREG_DECODER("ISO-2022-KR", NS_ISO2022KRTOUNICODE_CID)
|
||||
|
||||
// ucvcn
|
||||
@ -687,8 +684,6 @@ NS_DEFINE_NAMED_CID(NS_EUCKRTOUNICODE_CID);
|
||||
NS_DEFINE_NAMED_CID(NS_UNICODETOEUCKR_CID);
|
||||
NS_DEFINE_NAMED_CID(NS_JOHABTOUNICODE_CID);
|
||||
NS_DEFINE_NAMED_CID(NS_UNICODETOJOHAB_CID);
|
||||
NS_DEFINE_NAMED_CID(NS_CP949TOUNICODE_CID);
|
||||
NS_DEFINE_NAMED_CID(NS_UNICODETOCP949_CID);
|
||||
NS_DEFINE_NAMED_CID(NS_ISO2022KRTOUNICODE_CID);
|
||||
NS_DEFINE_NAMED_CID(NS_GB2312TOUNICODE_CID);
|
||||
NS_DEFINE_NAMED_CID(NS_UNICODETOGB2312_CID);
|
||||
@ -870,12 +865,10 @@ static const mozilla::Module::CIDEntry kUConvCIDs[] = {
|
||||
{ &kNS_UNICODETOBIG5HKSCS_CID, false, nullptr, nsUnicodeToBIG5HKSCSConstructor },
|
||||
{ &kNS_UNICODETOHKSCS_CID, false, nullptr, nsUnicodeToHKSCSConstructor },
|
||||
{ &kNS_BIG5HKSCSTOUNICODE_CID, false, nullptr, nsBIG5HKSCSToUnicodeConstructor },
|
||||
{ &kNS_EUCKRTOUNICODE_CID, false, nullptr, nsEUCKRToUnicodeConstructor },
|
||||
{ &kNS_UNICODETOEUCKR_CID, false, nullptr, nsUnicodeToEUCKRConstructor },
|
||||
{ &kNS_EUCKRTOUNICODE_CID, false, nullptr, nsCP949ToUnicodeConstructor },
|
||||
{ &kNS_UNICODETOEUCKR_CID, false, nullptr, nsUnicodeToCP949Constructor },
|
||||
{ &kNS_JOHABTOUNICODE_CID, false, nullptr, nsJohabToUnicodeConstructor },
|
||||
{ &kNS_UNICODETOJOHAB_CID, false, nullptr, nsUnicodeToJohabConstructor },
|
||||
{ &kNS_CP949TOUNICODE_CID, false, nullptr, nsCP949ToUnicodeConstructor },
|
||||
{ &kNS_UNICODETOCP949_CID, false, nullptr, nsUnicodeToCP949Constructor },
|
||||
{ &kNS_ISO2022KRTOUNICODE_CID, false, nullptr, nsISO2022KRToUnicodeConstructor },
|
||||
{ &kNS_GB2312TOUNICODE_CID, false, nullptr, nsGB2312ToUnicodeV2Constructor },
|
||||
{ &kNS_UNICODETOGB2312_CID, false, nullptr, nsUnicodeToGB2312V2Constructor },
|
||||
@ -1063,8 +1056,6 @@ static const mozilla::Module::ContractIDEntry kUConvContracts[] = {
|
||||
{ NS_UNICODEENCODER_CONTRACTID_BASE "EUC-KR", &kNS_UNICODETOEUCKR_CID },
|
||||
{ NS_UNICODEDECODER_CONTRACTID_BASE "x-johab", &kNS_JOHABTOUNICODE_CID },
|
||||
{ NS_UNICODEENCODER_CONTRACTID_BASE "x-johab", &kNS_UNICODETOJOHAB_CID },
|
||||
{ NS_UNICODEDECODER_CONTRACTID_BASE "x-windows-949", &kNS_CP949TOUNICODE_CID },
|
||||
{ NS_UNICODEENCODER_CONTRACTID_BASE "x-windows-949", &kNS_UNICODETOCP949_CID },
|
||||
{ NS_UNICODEDECODER_CONTRACTID_BASE "ISO-2022-KR", &kNS_ISO2022KRTOUNICODE_CID },
|
||||
{ NS_UNICODEDECODER_CONTRACTID_BASE "GB2312", &kNS_GB2312TOUNICODE_CID },
|
||||
{ NS_UNICODEENCODER_CONTRACTID_BASE "GB2312", &kNS_UNICODETOGB2312_CID },
|
||||
|
@ -95,7 +95,6 @@ var encoderList = [
|
||||
"hkscs-1",
|
||||
"EUC-KR",
|
||||
"x-johab",
|
||||
"x-windows-949",
|
||||
"GB2312",
|
||||
"gbk",
|
||||
"HZ-GB-2312",
|
||||
@ -178,7 +177,6 @@ var decoderList = [
|
||||
"Big5-HKSCS",
|
||||
"EUC-KR",
|
||||
"x-johab",
|
||||
"x-windows-949",
|
||||
"GB2312",
|
||||
"gbk",
|
||||
"HZ-GB-2312",
|
||||
|
@ -4,7 +4,7 @@
|
||||
load('CharsetConversionTests.js');
|
||||
load('hangulTestStrings.js');
|
||||
|
||||
const aliases = [ "euc-kr", "EUC-KR", "iso-ir-149", "ks_c_5601-1989", "ksc_5601", "ksc5601", "korean", "csksc56011987", "5601", "x-windows-949", "ks_c_5601-1987", "cseuckr"];
|
||||
const aliases = [ "euc-kr", "EUC-KR", "iso-ir-149", "ks_c_5601-1989", "ksc_5601", "ksc5601", "korean", "csksc56011987", "5601", "windows-949", "ks_c_5601-1987", "cseuckr"];
|
||||
|
||||
function to8byteHangul(byte3, byte5, byte7)
|
||||
{
|
||||
|
@ -17,8 +17,6 @@ LIBXUL_LIBRARY = 1
|
||||
|
||||
|
||||
CPPSRCS = \
|
||||
nsEUCKRToUnicode.cpp \
|
||||
nsUnicodeToEUCKR.cpp \
|
||||
nsISO2022KRToUnicode.cpp \
|
||||
nsCP949ToUnicode.cpp \
|
||||
nsUnicodeToCP949.cpp \
|
||||
|
@ -1,15 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsEUCKRToUnicode.h"
|
||||
#include "nsUCvKODll.h"
|
||||
#include "nsUCConstructors.h"
|
||||
|
||||
nsresult
|
||||
nsEUCKRToUnicodeConstructor(nsISupports *aOuter, REFNSIID aIID,
|
||||
void **aResult)
|
||||
{
|
||||
return nsCP949ToUnicodeConstructor(aOuter, aIID, aResult);
|
||||
}
|
@ -1,22 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef nsEUCKRToUnicode_h___
|
||||
#define nsEUCKRToUnicode_h___
|
||||
|
||||
#include "nsCP949ToUnicode.h"
|
||||
|
||||
/**
|
||||
* A character set converter from EUCKR to Unicode.
|
||||
*
|
||||
* @created 06/Apr/1999
|
||||
* @author Catalin Rotaru [CATA]
|
||||
*/
|
||||
// Just make it an alias to CP949 decoder. bug 131388
|
||||
nsresult
|
||||
nsEUCKRToUnicodeConstructor(nsISupports *aOuter, REFNSIID aIID,
|
||||
void **aResult);
|
||||
|
||||
#endif /* nsEUCKRToUnicode_h___ */
|
@ -28,14 +28,6 @@
|
||||
#define NS_UNICODETOISO2022KR_CID \
|
||||
{ 0xba6151a0, 0x1dfa, 0x11d3, {0xb3, 0xbf, 0x0, 0x80, 0x5f, 0x8a, 0x66, 0x70}}
|
||||
|
||||
// Class ID for our UnicodeToCP949 charset converter
|
||||
#define NS_UNICODETOCP949_CID \
|
||||
{ 0x9416bfbe, 0x1f93, 0x11d3, {0xb3, 0xbf, 0x0, 0x80, 0x5f, 0x8a, 0x66, 0x70}}
|
||||
|
||||
// Class ID for our CP949ToUnicode charset converter
|
||||
#define NS_CP949TOUNICODE_CID \
|
||||
{ 0x9416bfbf, 0x1f93, 0x11d3, {0xb3, 0xbf, 0x0, 0x80, 0x5f, 0x8a, 0x66, 0x70}}
|
||||
|
||||
// Class ID for our UnicodeToJohab charset converter
|
||||
// {D9B1F97E-CFA0-80b6-FB92-9972E48E3DCC}
|
||||
#define NS_UNICODETOJOHAB_CID \
|
||||
|
@ -1,37 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsUnicodeToEUCKR.h"
|
||||
#include "nsUCvKODll.h"
|
||||
#include "nsUCConstructors.h"
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// Global functions and data [declaration]
|
||||
|
||||
|
||||
static const uint16_t *g_EUCKRMappingTable[3] = {
|
||||
g_ASCIIMappingTable,
|
||||
g_ufKSC5601Mapping,
|
||||
g_HangulNullMapping
|
||||
};
|
||||
|
||||
static const uScanClassID g_EUCKRScanCellIDTable[3] = {
|
||||
u1ByteCharset,
|
||||
u2BytesGRCharset,
|
||||
uDecomposedHangulCharset
|
||||
};
|
||||
|
||||
nsresult
|
||||
nsUnicodeToEUCKRConstructor(nsISupports *aOuter, REFNSIID aIID,
|
||||
void **aResult)
|
||||
{
|
||||
return CreateMultiTableEncoder(3,
|
||||
(uScanClassID*) g_EUCKRScanCellIDTable,
|
||||
(uMappingTable**) g_EUCKRMappingTable,
|
||||
// change from 2 to 8 because of composed jamo
|
||||
8 /* max length = src * 8 */,
|
||||
aOuter, aIID, aResult);
|
||||
}
|
||||
|
@ -1,21 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef nsUnicodeToEUCKR_h___
|
||||
#define nsUnicodeToEUCKR_h___
|
||||
|
||||
#include "nsISupports.h"
|
||||
|
||||
/**
|
||||
* A character set converter from Unicode to EUCKR.
|
||||
*
|
||||
* @created 06/Apr/1999
|
||||
* @author Catalin Rotaru [CATA]
|
||||
*/
|
||||
nsresult
|
||||
nsUnicodeToEUCKRConstructor(nsISupports *aOuter, REFNSIID aIID,
|
||||
void **aResult);
|
||||
|
||||
#endif /* nsUnicodeToEUCKR_h___ */
|
@ -955,7 +955,7 @@ FlagHistogram::FactoryGet(const std::string &name, Flags flags)
|
||||
fh->InitializeBucketRange();
|
||||
fh->SetFlags(flags);
|
||||
size_t zero_index = fh->BucketIndex(0);
|
||||
fh->Histogram::Accumulate(1, 1, zero_index);
|
||||
fh->Histogram::Accumulate(0, 1, zero_index);
|
||||
h = StatisticsRecorder::RegisterOrDeleteDuplicate(fh);
|
||||
}
|
||||
|
||||
@ -983,7 +983,7 @@ FlagHistogram::Accumulate(Sample value, Count count, size_t index)
|
||||
DCHECK_EQ(value, 1);
|
||||
Histogram::Accumulate(value, 1, index);
|
||||
size_t zero_index = BucketIndex(0);
|
||||
Histogram::Accumulate(1, -1, zero_index);
|
||||
Histogram::Accumulate(0, -1, zero_index);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -212,6 +212,13 @@ public:
|
||||
//JS_ASSERT(m_pools.empty()); // if this asserts we have a pool leak
|
||||
}
|
||||
|
||||
void purge() {
|
||||
for (size_t i = 0; i < m_smallPools.length(); i++)
|
||||
m_smallPools[i]->release();
|
||||
|
||||
m_smallPools.clear();
|
||||
}
|
||||
|
||||
// alloc() returns a pointer to some memory, and also (by reference) a
|
||||
// pointer to reference-counted pool. The caller owns a reference to the
|
||||
// pool; i.e. alloc() increments the count before returning the object.
|
||||
|
@ -62,6 +62,7 @@ xpcshell-tests-remote:
|
||||
$(topsrcdir)/testing/xpcshell/remotexpcshelltests.py \
|
||||
--symbols-path=$(DIST)/crashreporter-symbols \
|
||||
--build-info-json=$(DEPTH)/mozinfo.json \
|
||||
--testing-modules-dir=$(DEPTH)/_tests/modules \
|
||||
$(EXTRA_TEST_ARGS) \
|
||||
--dm_trans=$(DM_TRANS) \
|
||||
--deviceIP=${TEST_DEVICE} \
|
||||
@ -112,6 +113,7 @@ check-one-remote:
|
||||
--symbols-path=$(DIST)/crashreporter-symbols \
|
||||
--build-info-json=$(DEPTH)/mozinfo.json \
|
||||
--test-path=$(SOLO_FILE) \
|
||||
--testing-modules-dir=$(DEPTH)/_tests/modules \
|
||||
--profile-name=$(MOZ_APP_NAME) \
|
||||
--verbose \
|
||||
$(EXTRA_TEST_ARGS) \
|
||||
|
@ -390,7 +390,7 @@ GetPageFaultCount()
|
||||
int err = getrusage(RUSAGE_SELF, &usage);
|
||||
if (err)
|
||||
return 0;
|
||||
return usage.ru_minflt + usage.ru_majflt;
|
||||
return usage.ru_majflt;
|
||||
}
|
||||
|
||||
#else
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include "jsnum.h"
|
||||
#include "jsmath.h"
|
||||
#include "jsinterpinlines.h"
|
||||
#include "ExecutionModeInlines.h"
|
||||
|
||||
#include "vm/StringObject-inl.h"
|
||||
|
||||
@ -798,6 +799,17 @@ CodeGenerator::emitCallInvokeFunction(LInstruction *call, Register calleereg,
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline int32_t ionOffset(ExecutionMode executionMode)
|
||||
{
|
||||
switch (executionMode) {
|
||||
case SequentialExecution: return offsetof(JSScript, ion);
|
||||
case ParallelExecution: return offsetof(JSScript, parallelIon);
|
||||
}
|
||||
|
||||
JS_ASSERT(false);
|
||||
return offsetof(JSScript, ion);
|
||||
}
|
||||
|
||||
bool
|
||||
CodeGenerator::visitCallGeneric(LCallGeneric *call)
|
||||
{
|
||||
@ -831,7 +843,8 @@ CodeGenerator::visitCallGeneric(LCallGeneric *call)
|
||||
|
||||
// Knowing that calleereg is a non-native function, load the JSScript.
|
||||
masm.movePtr(Address(calleereg, offsetof(JSFunction, u.i.script_)), objreg);
|
||||
masm.movePtr(Address(objreg, offsetof(JSScript, ion)), objreg);
|
||||
ExecutionMode executionMode = gen->info().executionMode();
|
||||
masm.movePtr(Address(objreg, ionOffset(executionMode)), objreg);
|
||||
|
||||
// Guard that the IonScript has been compiled.
|
||||
masm.branchPtr(Assembler::BelowOrEqual, objreg, ImmWord(ION_COMPILING_SCRIPT), &invoke);
|
||||
@ -889,6 +902,7 @@ CodeGenerator::visitCallGeneric(LCallGeneric *call)
|
||||
bool
|
||||
CodeGenerator::visitCallKnown(LCallKnown *call)
|
||||
{
|
||||
JSContext *cx = GetIonContext()->cx;
|
||||
Register calleereg = ToRegister(call->getFunction());
|
||||
Register objreg = ToRegister(call->getTempObject());
|
||||
uint32 unusedStack = StackOffsetOfPassedArg(call->argslot());
|
||||
@ -903,7 +917,9 @@ CodeGenerator::visitCallKnown(LCallKnown *call)
|
||||
masm.checkStackAlignment();
|
||||
|
||||
// If the function is known to be uncompilable, only emit the call to InvokeFunction.
|
||||
if (target->script()->ion == ION_DISABLED_SCRIPT) {
|
||||
ExecutionMode executionMode = gen->info().executionMode();
|
||||
RootedScript targetScript(cx, target->script());
|
||||
if (GetIonScript(targetScript, executionMode) == ION_DISABLED_SCRIPT) {
|
||||
if (!emitCallInvokeFunction(call, calleereg, call->numActualArgs(), unusedStack))
|
||||
return false;
|
||||
|
||||
@ -920,7 +936,7 @@ CodeGenerator::visitCallKnown(LCallKnown *call)
|
||||
|
||||
// Knowing that calleereg is a non-native function, load the JSScript.
|
||||
masm.movePtr(Address(calleereg, offsetof(JSFunction, u.i.script_)), objreg);
|
||||
masm.movePtr(Address(objreg, offsetof(JSScript, ion)), objreg);
|
||||
masm.movePtr(Address(objreg, ionOffset(executionMode)), objreg);
|
||||
|
||||
// Guard that the IonScript has been compiled.
|
||||
masm.branchPtr(Assembler::BelowOrEqual, objreg, ImmWord(ION_COMPILING_SCRIPT), &invoke);
|
||||
@ -1088,6 +1104,8 @@ CodeGenerator::emitPopArguments(LApplyArgsGeneric *apply, Register extraStackSpa
|
||||
bool
|
||||
CodeGenerator::visitApplyArgsGeneric(LApplyArgsGeneric *apply)
|
||||
{
|
||||
JSContext *cx = GetIonContext()->cx;
|
||||
|
||||
// Holds the function object.
|
||||
Register calleereg = ToRegister(apply->getFunction());
|
||||
|
||||
@ -1112,14 +1130,15 @@ CodeGenerator::visitApplyArgsGeneric(LApplyArgsGeneric *apply)
|
||||
masm.checkStackAlignment();
|
||||
|
||||
// If the function is known to be uncompilable, only emit the call to InvokeFunction.
|
||||
if (apply->hasSingleTarget() &&
|
||||
(!apply->getSingleTarget()->isInterpreted() ||
|
||||
apply->getSingleTarget()->script()->ion == ION_DISABLED_SCRIPT))
|
||||
{
|
||||
if (!emitCallInvokeFunction(apply, copyreg))
|
||||
return false;
|
||||
emitPopArguments(apply, copyreg);
|
||||
return true;
|
||||
ExecutionMode executionMode = gen->info().executionMode();
|
||||
if (apply->hasSingleTarget()) {
|
||||
RootedFunction target(cx, apply->getSingleTarget());
|
||||
if (!CanIonCompile(cx, target, executionMode)) {
|
||||
if (!emitCallInvokeFunction(apply, copyreg))
|
||||
return false;
|
||||
emitPopArguments(apply, copyreg);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
Label end, invoke;
|
||||
@ -1134,7 +1153,7 @@ CodeGenerator::visitApplyArgsGeneric(LApplyArgsGeneric *apply)
|
||||
|
||||
// Knowing that calleereg is a non-native function, load the JSScript.
|
||||
masm.movePtr(Address(calleereg, offsetof(JSFunction, u.i.script_)), objreg);
|
||||
masm.movePtr(Address(objreg, offsetof(JSScript, ion)), objreg);
|
||||
masm.movePtr(Address(objreg, ionOffset(executionMode)), objreg);
|
||||
|
||||
// Guard that the IonScript has been compiled.
|
||||
masm.branchPtr(Assembler::BelowOrEqual, objreg, ImmWord(ION_COMPILING_SCRIPT), &invoke);
|
||||
@ -2985,7 +3004,8 @@ CodeGenerator::generate()
|
||||
encodeSafepoints();
|
||||
|
||||
RootedScript script(cx, gen->info().script());
|
||||
JS_ASSERT(!script->hasIonScript());
|
||||
ExecutionMode executionMode = gen->info().executionMode();
|
||||
JS_ASSERT(!HasIonScript(script, executionMode));
|
||||
|
||||
uint32 scriptFrameSize = frameClass_ == FrameSizeClass::None()
|
||||
? frameDepth_
|
||||
@ -2996,48 +3016,51 @@ CodeGenerator::generate()
|
||||
if (cx->compartment->types.compiledInfo.compilerOutput(cx)->isInvalidated())
|
||||
return true;
|
||||
|
||||
script->ion = IonScript::New(cx, slots, scriptFrameSize, snapshots_.size(),
|
||||
bailouts_.length(), graph.numConstants(),
|
||||
safepointIndices_.length(), osiIndices_.length(),
|
||||
cacheList_.length(), barrierOffsets_.length(),
|
||||
safepoints_.size(), graph.mir().numScripts());
|
||||
if (!script->ion)
|
||||
IonScript *ionScript =
|
||||
IonScript::New(cx, slots, scriptFrameSize, snapshots_.size(),
|
||||
bailouts_.length(), graph.numConstants(),
|
||||
safepointIndices_.length(), osiIndices_.length(),
|
||||
cacheList_.length(), barrierOffsets_.length(),
|
||||
safepoints_.size(), graph.mir().numScripts());
|
||||
SetIonScript(script, executionMode, ionScript);
|
||||
|
||||
if (!ionScript)
|
||||
return false;
|
||||
invalidateEpilogueData_.fixup(&masm);
|
||||
Assembler::patchDataWithValueCheck(CodeLocationLabel(code, invalidateEpilogueData_),
|
||||
ImmWord(uintptr_t(script->ion)),
|
||||
ImmWord(uintptr_t(ionScript)),
|
||||
ImmWord(uintptr_t(-1)));
|
||||
|
||||
IonSpew(IonSpew_Codegen, "Created IonScript %p (raw %p)",
|
||||
(void *) script->ion, (void *) code->raw());
|
||||
(void *) ionScript, (void *) code->raw());
|
||||
|
||||
script->ion->setInvalidationEpilogueDataOffset(invalidateEpilogueData_.offset());
|
||||
script->ion->setOsrPc(gen->info().osrPc());
|
||||
script->ion->setOsrEntryOffset(getOsrEntryOffset());
|
||||
ionScript->setInvalidationEpilogueDataOffset(invalidateEpilogueData_.offset());
|
||||
ionScript->setOsrPc(gen->info().osrPc());
|
||||
ionScript->setOsrEntryOffset(getOsrEntryOffset());
|
||||
ptrdiff_t real_invalidate = masm.actualOffset(invalidate_.offset());
|
||||
script->ion->setInvalidationEpilogueOffset(real_invalidate);
|
||||
ionScript->setInvalidationEpilogueOffset(real_invalidate);
|
||||
|
||||
script->ion->setMethod(code);
|
||||
script->ion->setDeoptTable(deoptTable_);
|
||||
ionScript->setMethod(code);
|
||||
ionScript->setDeoptTable(deoptTable_);
|
||||
if (snapshots_.size())
|
||||
script->ion->copySnapshots(&snapshots_);
|
||||
ionScript->copySnapshots(&snapshots_);
|
||||
if (bailouts_.length())
|
||||
script->ion->copyBailoutTable(&bailouts_[0]);
|
||||
ionScript->copyBailoutTable(&bailouts_[0]);
|
||||
if (graph.numConstants())
|
||||
script->ion->copyConstants(graph.constantPool());
|
||||
ionScript->copyConstants(graph.constantPool());
|
||||
if (safepointIndices_.length())
|
||||
script->ion->copySafepointIndices(&safepointIndices_[0], masm);
|
||||
ionScript->copySafepointIndices(&safepointIndices_[0], masm);
|
||||
if (osiIndices_.length())
|
||||
script->ion->copyOsiIndices(&osiIndices_[0], masm);
|
||||
ionScript->copyOsiIndices(&osiIndices_[0], masm);
|
||||
if (cacheList_.length())
|
||||
script->ion->copyCacheEntries(&cacheList_[0], masm);
|
||||
ionScript->copyCacheEntries(&cacheList_[0], masm);
|
||||
if (barrierOffsets_.length())
|
||||
script->ion->copyPrebarrierEntries(&barrierOffsets_[0], masm);
|
||||
ionScript->copyPrebarrierEntries(&barrierOffsets_[0], masm);
|
||||
if (safepoints_.size())
|
||||
script->ion->copySafepoints(&safepoints_);
|
||||
ionScript->copySafepoints(&safepoints_);
|
||||
|
||||
JS_ASSERT(graph.mir().numScripts() > 0);
|
||||
script->ion->copyScriptEntries(graph.mir().scripts());
|
||||
ionScript->copyScriptEntries(graph.mir().scripts());
|
||||
|
||||
linkAbsoluteLabels();
|
||||
|
||||
@ -3045,7 +3068,7 @@ CodeGenerator::generate()
|
||||
// since a GC can occur during code generation. All barriers are emitted
|
||||
// off-by-default, and are toggled on here if necessary.
|
||||
if (cx->compartment->needsBarrier())
|
||||
script->ion->toggleBarriers(true);
|
||||
ionScript->toggleBarriers(true);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -17,12 +17,23 @@ CountArgSlots(JSFunction *fun)
|
||||
return fun ? fun->nargs + 2 : 1; // +2 for |scopeChain| and |this|, or +1 for |scopeChain|
|
||||
}
|
||||
|
||||
enum ExecutionMode {
|
||||
// Normal JavaScript execution
|
||||
SequentialExecution,
|
||||
|
||||
// JavaScript code to be executed in parallel worker threads,
|
||||
// e.g. by ParallelArray
|
||||
ParallelExecution
|
||||
};
|
||||
|
||||
// Contains information about the compilation source for IR being generated.
|
||||
class CompileInfo
|
||||
{
|
||||
public:
|
||||
CompileInfo(JSScript *script, JSFunction *fun, jsbytecode *osrPc, bool constructing)
|
||||
: script_(script), fun_(fun), osrPc_(osrPc), constructing_(constructing)
|
||||
CompileInfo(JSScript *script, JSFunction *fun, jsbytecode *osrPc, bool constructing,
|
||||
ExecutionMode executionMode)
|
||||
: script_(script), fun_(fun), osrPc_(osrPc), constructing_(constructing),
|
||||
executionMode_(executionMode)
|
||||
{
|
||||
JS_ASSERT_IF(osrPc, JSOp(*osrPc) == JSOP_LOOPENTRY);
|
||||
nslots_ = script->nslots + CountArgSlots(fun);
|
||||
@ -133,12 +144,21 @@ class CompileInfo
|
||||
return script()->argumentsHasVarBinding();
|
||||
}
|
||||
|
||||
ExecutionMode executionMode() const {
|
||||
return executionMode_;
|
||||
}
|
||||
|
||||
bool isParallelExecution() const {
|
||||
return executionMode_ == ParallelExecution;
|
||||
}
|
||||
|
||||
private:
|
||||
JSScript *script_;
|
||||
JSFunction *fun_;
|
||||
unsigned nslots_;
|
||||
jsbytecode *osrPc_;
|
||||
bool constructing_;
|
||||
ExecutionMode executionMode_;
|
||||
};
|
||||
|
||||
} // namespace ion
|
||||
|
103
js/src/ion/ExecutionModeInlines.h
Normal file
103
js/src/ion/ExecutionModeInlines.h
Normal file
@ -0,0 +1,103 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* vim: set ts=4 sw=4 et tw=99:
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef jsion_compilemode_h__
|
||||
#define jsion_compilemode_h__
|
||||
|
||||
namespace js {
|
||||
namespace ion {
|
||||
|
||||
static inline bool HasIonScript(JSScript *script, ExecutionMode cmode)
|
||||
{
|
||||
switch (cmode) {
|
||||
case SequentialExecution: return script->hasIonScript();
|
||||
case ParallelExecution: return script->hasParallelIonScript();
|
||||
}
|
||||
JS_NOT_REACHED("No such execution mode");
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline IonScript *GetIonScript(JSScript *script, ExecutionMode cmode)
|
||||
{
|
||||
switch (cmode) {
|
||||
case SequentialExecution: return script->ion;
|
||||
case ParallelExecution: return script->parallelIon;
|
||||
}
|
||||
JS_NOT_REACHED("No such execution mode");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline void SetIonScript(JSScript *script, ExecutionMode cmode, IonScript *ionScript)
|
||||
{
|
||||
switch (cmode) {
|
||||
case SequentialExecution: script->ion = ionScript; return;
|
||||
case ParallelExecution: script->parallelIon = ionScript; return;
|
||||
}
|
||||
JS_NOT_REACHED("No such execution mode");
|
||||
}
|
||||
|
||||
static inline bool CanIonCompile(HandleScript script, ExecutionMode cmode)
|
||||
{
|
||||
switch (cmode) {
|
||||
case SequentialExecution: return script->canIonCompile();
|
||||
case ParallelExecution: return script->canParallelIonCompile();
|
||||
}
|
||||
JS_NOT_REACHED("No such execution mode");
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline bool CanIonCompile(JSContext *cx, HandleFunction fun, ExecutionMode cmode)
|
||||
{
|
||||
if (!fun->isInterpreted())
|
||||
return false;
|
||||
RootedScript script(cx, fun->script());
|
||||
return CanIonCompile(script, cmode);
|
||||
}
|
||||
|
||||
static inline bool CompilingOffThread(JSScript *script, ExecutionMode cmode)
|
||||
{
|
||||
switch (cmode) {
|
||||
case SequentialExecution: return script->isIonCompilingOffThread();
|
||||
case ParallelExecution: return script->isParallelIonCompilingOffThread();
|
||||
}
|
||||
JS_NOT_REACHED("No such execution mode");
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline bool CompilingOffThread(HandleScript script, ExecutionMode cmode)
|
||||
{
|
||||
switch (cmode) {
|
||||
case SequentialExecution: return script->isIonCompilingOffThread();
|
||||
case ParallelExecution: return script->isParallelIonCompilingOffThread();
|
||||
}
|
||||
JS_NOT_REACHED("No such execution mode");
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline bool Disabled(JSScript *script, ExecutionMode cmode) {
|
||||
switch (cmode) {
|
||||
case SequentialExecution: return script->isIonCompilingOffThread();
|
||||
case ParallelExecution: return script->isParallelIonCompilingOffThread();
|
||||
}
|
||||
JS_NOT_REACHED("No such execution mode");
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline types::CompilerOutput::Kind CompilerOutputKind(ExecutionMode cmode)
|
||||
{
|
||||
switch (cmode) {
|
||||
case SequentialExecution: return types::CompilerOutput::Ion;
|
||||
case ParallelExecution: return types::CompilerOutput::ParallelIon;
|
||||
}
|
||||
JS_NOT_REACHED("No such execution mode");
|
||||
return types::CompilerOutput::Ion;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
@ -37,6 +37,7 @@
|
||||
#include "ion/IonFrames-inl.h"
|
||||
#include "ion/CompilerRoot.h"
|
||||
#include "methodjit/Retcon.h"
|
||||
#include "ExecutionModeInlines.h"
|
||||
|
||||
#if JS_TRACE_LOGGING
|
||||
#include "TraceLogging.h"
|
||||
@ -963,6 +964,16 @@ class AutoDestroyAllocator
|
||||
}
|
||||
};
|
||||
|
||||
class SequentialCompileContext {
|
||||
public:
|
||||
ExecutionMode executionMode() {
|
||||
return SequentialExecution;
|
||||
}
|
||||
|
||||
bool compile(IonBuilder *builder, MIRGraph *graph,
|
||||
AutoDestroyAllocator &autoDestroy);
|
||||
};
|
||||
|
||||
void
|
||||
AttachFinishedCompilations(JSContext *cx)
|
||||
{
|
||||
@ -988,7 +999,8 @@ AttachFinishedCompilations(JSContext *cx)
|
||||
|
||||
CodeGenerator codegen(builder, *builder->backgroundCompiledLir);
|
||||
|
||||
types::AutoEnterCompilation enterCompiler(cx, types::AutoEnterCompilation::Ion);
|
||||
ExecutionMode executionMode = builder->info().executionMode();
|
||||
types::AutoEnterCompilation enterCompiler(cx, CompilerOutputKind(executionMode));
|
||||
enterCompiler.initExisting(builder->recompileInfo);
|
||||
|
||||
bool success;
|
||||
@ -1018,8 +1030,10 @@ AttachFinishedCompilations(JSContext *cx)
|
||||
|
||||
static const size_t BUILDER_LIFO_ALLOC_PRIMARY_CHUNK_SIZE = 1 << 12;
|
||||
|
||||
template <typename CompileContext>
|
||||
static bool
|
||||
IonCompile(JSContext *cx, JSScript *script, JSFunction *fun, jsbytecode *osrPc, bool constructing)
|
||||
IonCompile(JSContext *cx, JSScript *script, JSFunction *fun, jsbytecode *osrPc, bool constructing,
|
||||
CompileContext &compileContext)
|
||||
{
|
||||
AssertCanGC();
|
||||
#if JS_TRACE_LOGGING
|
||||
@ -1045,7 +1059,9 @@ IonCompile(JSContext *cx, JSScript *script, JSFunction *fun, jsbytecode *osrPc,
|
||||
return false;
|
||||
|
||||
MIRGraph *graph = alloc->new_<MIRGraph>(temp);
|
||||
CompileInfo *info = alloc->new_<CompileInfo>(script, fun, osrPc, constructing);
|
||||
ExecutionMode executionMode = compileContext.executionMode();
|
||||
CompileInfo *info = alloc->new_<CompileInfo>(script, fun, osrPc, constructing,
|
||||
executionMode);
|
||||
if (!info)
|
||||
return false;
|
||||
|
||||
@ -1057,13 +1073,26 @@ IonCompile(JSContext *cx, JSScript *script, JSFunction *fun, jsbytecode *osrPc,
|
||||
|
||||
AutoFlushCache afc("IonCompile");
|
||||
|
||||
types::AutoEnterCompilation enterCompiler(cx, types::AutoEnterCompilation::Ion);
|
||||
types::AutoEnterCompilation enterCompiler(cx, CompilerOutputKind(executionMode));
|
||||
enterCompiler.init(script, false, 0);
|
||||
|
||||
AutoTempAllocatorRooter root(cx, temp);
|
||||
|
||||
IonBuilder *builder = alloc->new_<IonBuilder>(cx, temp, graph, &oracle, info);
|
||||
if (!compileContext.compile(builder, graph, autoDestroy)) {
|
||||
IonSpew(IonSpew_Abort, "IM Compilation failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
SequentialCompileContext::compile(IonBuilder *builder, MIRGraph *graph,
|
||||
AutoDestroyAllocator &autoDestroy)
|
||||
{
|
||||
JS_ASSERT(!builder->script()->ion);
|
||||
JSContext *cx = GetIonContext()->cx;
|
||||
|
||||
IonSpewNewFunction(graph, builder->script().unsafeGet());
|
||||
|
||||
@ -1108,7 +1137,8 @@ IonCompile(JSContext *cx, JSScript *script, JSFunction *fun, jsbytecode *osrPc,
|
||||
bool
|
||||
TestIonCompile(JSContext *cx, JSScript *script, JSFunction *fun, jsbytecode *osrPc, bool constructing)
|
||||
{
|
||||
if (!IonCompile(cx, script, fun, osrPc, constructing)) {
|
||||
SequentialCompileContext compileContext;
|
||||
if (!IonCompile(cx, script, fun, osrPc, constructing, compileContext)) {
|
||||
if (!cx->isExceptionPending())
|
||||
ForbidCompilation(cx, script);
|
||||
return false;
|
||||
@ -1228,7 +1258,8 @@ Compile(JSContext *cx, JSScript *script, JSFunction *fun, jsbytecode *osrPc, boo
|
||||
return Method_Skipped;
|
||||
}
|
||||
|
||||
if (!IonCompile(cx, script, fun, osrPc, constructing))
|
||||
SequentialCompileContext compileContext;
|
||||
if (!IonCompile(cx, script, fun, osrPc, constructing, compileContext))
|
||||
return Method_CantCompile;
|
||||
|
||||
// Compilation succeeded, but we invalidated right away.
|
||||
@ -1344,7 +1375,7 @@ ion::CanEnter(JSContext *cx, HandleScript script, StackFrame *fp, bool newType)
|
||||
}
|
||||
|
||||
MethodStatus
|
||||
ion::CanEnterUsingFastInvoke(JSContext *cx, HandleScript script)
|
||||
ion::CanEnterUsingFastInvoke(JSContext *cx, HandleScript script, uint32_t numActualArgs)
|
||||
{
|
||||
JS_ASSERT(ion::IsEnabled(cx));
|
||||
|
||||
@ -1352,6 +1383,11 @@ ion::CanEnterUsingFastInvoke(JSContext *cx, HandleScript script)
|
||||
if (!script->hasIonScript() || script->ion->bailoutExpected())
|
||||
return Method_Skipped;
|
||||
|
||||
// Don't handle arguments underflow, to make this work we would have to pad
|
||||
// missing arguments with |undefined|.
|
||||
if (numActualArgs < script->function()->nargs)
|
||||
return Method_Skipped;
|
||||
|
||||
if (!cx->compartment->ensureIonCompartmentExists(cx))
|
||||
return Method_Error;
|
||||
|
||||
@ -1552,11 +1588,12 @@ ion::FastInvoke(JSContext *cx, HandleFunction fun, CallArgsList &args)
|
||||
EnterIonCode enter = cx->compartment->ionCompartment()->enterJITInfallible();
|
||||
void *calleeToken = CalleeToToken(fun);
|
||||
|
||||
Value result = Int32Value(fun->nargs);
|
||||
Value result = Int32Value(args.length());
|
||||
JS_ASSERT(args.length() >= fun->nargs);
|
||||
|
||||
JSAutoResolveFlags rf(cx, RESOLVE_INFER);
|
||||
args.setActive();
|
||||
enter(jitcode, args.length() + 1, &args[0] - 1, fp, calleeToken, &result);
|
||||
enter(jitcode, args.length() + 1, args.array() - 1, fp, calleeToken, &result);
|
||||
args.setInactive();
|
||||
|
||||
if (clearCallingIntoIon)
|
||||
@ -1724,7 +1761,11 @@ ion::Invalidate(types::TypeCompartment &types, FreeOp *fop,
|
||||
bool anyInvalidation = false;
|
||||
for (size_t i = 0; i < invalid.length(); i++) {
|
||||
const types::CompilerOutput &co = *invalid[i].compilerOutput(types);
|
||||
if (co.isIon()) {
|
||||
switch (co.kind()) {
|
||||
case types::CompilerOutput::MethodJIT:
|
||||
break;
|
||||
case types::CompilerOutput::Ion:
|
||||
case types::CompilerOutput::ParallelIon:
|
||||
JS_ASSERT(co.isValid());
|
||||
IonSpew(IonSpew_Invalidate, " Invalidate %s:%u, IonScript %p",
|
||||
co.script->filename, co.script->lineno, co.ion());
|
||||
@ -1750,29 +1791,38 @@ ion::Invalidate(types::TypeCompartment &types, FreeOp *fop,
|
||||
// until its last invalidated frame is destroyed.
|
||||
for (size_t i = 0; i < invalid.length(); i++) {
|
||||
types::CompilerOutput &co = *invalid[i].compilerOutput(types);
|
||||
if (co.isIon()) {
|
||||
JS_ASSERT(co.isValid());
|
||||
JSScript *script = co.script;
|
||||
IonScript *ionScript = script->ionScript();
|
||||
|
||||
JSCompartment *compartment = script->compartment();
|
||||
if (compartment->needsBarrier()) {
|
||||
// We're about to remove edges from the JSScript to gcthings
|
||||
// embedded in the IonScript. Perform one final trace of the
|
||||
// IonScript for the incremental GC, as it must know about
|
||||
// those edges.
|
||||
IonScript::Trace(compartment->barrierTracer(), ionScript);
|
||||
}
|
||||
|
||||
ionScript->decref(fop);
|
||||
script->ion = NULL;
|
||||
co.invalidate();
|
||||
|
||||
// Wait for the scripts to get warm again before doing another
|
||||
// compile, unless we are recompiling *because* a script got hot.
|
||||
if (resetUses)
|
||||
script->resetUseCount();
|
||||
ExecutionMode executionMode;
|
||||
switch (co.kind()) {
|
||||
case types::CompilerOutput::MethodJIT:
|
||||
continue;
|
||||
case types::CompilerOutput::Ion:
|
||||
executionMode = SequentialExecution;
|
||||
break;
|
||||
case types::CompilerOutput::ParallelIon:
|
||||
executionMode = ParallelExecution;
|
||||
break;
|
||||
}
|
||||
JS_ASSERT(co.isValid());
|
||||
JSScript *script = co.script;
|
||||
IonScript *ionScript = GetIonScript(script, executionMode);
|
||||
|
||||
JSCompartment *compartment = script->compartment();
|
||||
if (compartment->needsBarrier()) {
|
||||
// We're about to remove edges from the JSScript to gcthings
|
||||
// embedded in the IonScript. Perform one final trace of the
|
||||
// IonScript for the incremental GC, as it must know about
|
||||
// those edges.
|
||||
IonScript::Trace(compartment->barrierTracer(), ionScript);
|
||||
}
|
||||
|
||||
ionScript->decref(fop);
|
||||
SetIonScript(script, executionMode, NULL);
|
||||
co.invalidate();
|
||||
|
||||
// Wait for the scripts to get warm again before doing another
|
||||
// compile, unless we are recompiling *because* a script got hot.
|
||||
if (resetUses)
|
||||
script->resetUseCount();
|
||||
}
|
||||
}
|
||||
|
||||
@ -1891,3 +1941,42 @@ AutoFlushCache::AutoFlushCache(const char *nonce, IonCompartment *comp)
|
||||
}
|
||||
int js::ion::LabelBase::id_count = 0;
|
||||
|
||||
void
|
||||
ion::PurgeCaches(JSScript *script, JSCompartment *c) {
|
||||
if (script->hasIonScript())
|
||||
script->ion->purgeCaches(c);
|
||||
|
||||
if (script->hasParallelIonScript())
|
||||
script->ion->purgeCaches(c);
|
||||
}
|
||||
|
||||
size_t
|
||||
ion::MemoryUsed(JSScript *script, JSMallocSizeOfFun mallocSizeOf) {
|
||||
size_t result = 0;
|
||||
|
||||
if (script->hasIonScript())
|
||||
result += script->ion->sizeOfIncludingThis(mallocSizeOf);
|
||||
|
||||
if (script->hasParallelIonScript())
|
||||
result += script->parallelIon->sizeOfIncludingThis(mallocSizeOf);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void
|
||||
ion::DestroyIonScripts(FreeOp *fop, JSScript *script) {
|
||||
if (script->hasIonScript())
|
||||
ion::IonScript::Destroy(fop, script->ion);
|
||||
|
||||
if (script->hasParallelIonScript())
|
||||
ion::IonScript::Destroy(fop, script->parallelIon);
|
||||
}
|
||||
|
||||
void
|
||||
ion::TraceIonScripts(JSTracer* trc, JSScript *script) {
|
||||
if (script->hasIonScript())
|
||||
ion::IonScript::Trace(trc, script->ion);
|
||||
|
||||
if (script->hasParallelIonScript())
|
||||
ion::IonScript::Trace(trc, script->parallelIon);
|
||||
}
|
||||
|
@ -226,7 +226,7 @@ bool SetIonContext(IonContext *ctx);
|
||||
MethodStatus CanEnterAtBranch(JSContext *cx, HandleScript script,
|
||||
StackFrame *fp, jsbytecode *pc);
|
||||
MethodStatus CanEnter(JSContext *cx, HandleScript script, StackFrame *fp, bool newType);
|
||||
MethodStatus CanEnterUsingFastInvoke(JSContext *cx, HandleScript script);
|
||||
MethodStatus CanEnterUsingFastInvoke(JSContext *cx, HandleScript script, uint32_t numActualArgs);
|
||||
|
||||
enum IonExecStatus
|
||||
{
|
||||
@ -268,6 +268,11 @@ static inline bool IsEnabled(JSContext *cx)
|
||||
void ForbidCompilation(JSContext *cx, JSScript *script);
|
||||
uint32_t UsesBeforeIonRecompile(JSScript *script, jsbytecode *pc);
|
||||
|
||||
void PurgeCaches(JSScript *script, JSCompartment *c);
|
||||
size_t MemoryUsed(JSScript *script, JSMallocSizeOfFun mallocSizeOf);
|
||||
void DestroyIonScripts(FreeOp *fop, JSScript *script);
|
||||
void TraceIonScripts(JSTracer* trc, JSScript *script);
|
||||
|
||||
} // namespace ion
|
||||
} // namespace js
|
||||
|
||||
|
@ -15,6 +15,7 @@
|
||||
|
||||
#include "jsscriptinlines.h"
|
||||
#include "jstypedarrayinlines.h"
|
||||
#include "ExecutionModeInlines.h"
|
||||
|
||||
#ifdef JS_THREADSAFE
|
||||
# include "prthread.h"
|
||||
@ -204,8 +205,8 @@ IonBuilder::canInlineTarget(JSFunction *target)
|
||||
}
|
||||
|
||||
RootedScript inlineScript(cx, target->script());
|
||||
|
||||
if (!inlineScript->canIonCompile()) {
|
||||
ExecutionMode executionMode = info().executionMode();
|
||||
if (!CanIonCompile(inlineScript, executionMode)) {
|
||||
IonSpew(IonSpew_Inlining, "Cannot inline due to disable Ion compilation");
|
||||
return false;
|
||||
}
|
||||
@ -2829,7 +2830,8 @@ IonBuilder::jsop_call_inline(HandleFunction callee, uint32 argc, bool constructi
|
||||
// lifetime.
|
||||
RootedScript calleeScript(cx, callee->script());
|
||||
CompileInfo *info = cx->tempLifoAlloc().new_<CompileInfo>(calleeScript.get(), callee,
|
||||
(jsbytecode *)NULL, constructing);
|
||||
(jsbytecode *)NULL, constructing,
|
||||
SequentialExecution);
|
||||
if (!info)
|
||||
return false;
|
||||
|
||||
|
73
js/src/jit-test/tests/ion/bug809021.js
Normal file
73
js/src/jit-test/tests/ion/bug809021.js
Normal file
@ -0,0 +1,73 @@
|
||||
// nactuals > nformals
|
||||
function testOverflow() {
|
||||
var called = false;
|
||||
function f(a) {
|
||||
assertEq(a, 173);
|
||||
assertEq(arguments.length, 2);
|
||||
assertEq(arguments[0], a);
|
||||
assertEq(arguments[1], a);
|
||||
called = true;
|
||||
}
|
||||
|
||||
for (var i=0; i<10; i++)
|
||||
[173, 173, 173].sort(f);
|
||||
assertEq(called, true);
|
||||
}
|
||||
testOverflow();
|
||||
|
||||
// nactuals == nformals
|
||||
function testEqual() {
|
||||
var called = false;
|
||||
function f(a, b) {
|
||||
assertEq(a, 173);
|
||||
assertEq(arguments.length, 2);
|
||||
assertEq(arguments[0], a);
|
||||
assertEq(arguments[1], b);
|
||||
called = true;
|
||||
}
|
||||
|
||||
for (var i=0; i<10; i++)
|
||||
[173, 173, 173].sort(f);
|
||||
assertEq(called, true);
|
||||
}
|
||||
testEqual();
|
||||
|
||||
// nactuals < nformals
|
||||
function testUnderflow() {
|
||||
var called = false;
|
||||
function f(a, b, c) {
|
||||
assertEq(a, 173);
|
||||
assertEq(c, undefined);
|
||||
assertEq(arguments.length, 2);
|
||||
assertEq(arguments[0], a);
|
||||
assertEq(arguments[1], b);
|
||||
called = true;
|
||||
}
|
||||
|
||||
for (var i=0; i<10; i++)
|
||||
[173, 173, 173].sort(f);
|
||||
assertEq(called, true);
|
||||
}
|
||||
testUnderflow();
|
||||
|
||||
function testUnderflowMany() {
|
||||
var called = 0;
|
||||
function f(a, b, c, d, e, f, g, h) {
|
||||
assertEq(a, 173);
|
||||
assertEq(arguments.length, 3);
|
||||
assertEq(arguments[0], a);
|
||||
assertEq(arguments[1] < 3, true);
|
||||
assertEq(c.length, 3);
|
||||
assertEq(d, undefined);
|
||||
assertEq(e, undefined);
|
||||
assertEq(f, undefined);
|
||||
assertEq(g, undefined);
|
||||
assertEq(h, undefined);
|
||||
called += 1;
|
||||
}
|
||||
|
||||
for (var i=0; i<10; i++)
|
||||
[173, 173, 173].map(f);
|
||||
assertEq(called, 30);
|
||||
}
|
||||
testUnderflowMany();
|
@ -514,6 +514,9 @@ struct JSRuntime : js::RuntimeFriendFields
|
||||
JS_ASSERT(execAlloc_);
|
||||
return *execAlloc_;
|
||||
}
|
||||
JSC::ExecutableAllocator *maybeExecAlloc() {
|
||||
return execAlloc_;
|
||||
}
|
||||
WTF::BumpPointerAllocator *getBumpPointerAllocator(JSContext *cx) {
|
||||
return bumpAlloc_ ? bumpAlloc_ : createBumpPointerAllocator(cx);
|
||||
}
|
||||
|
@ -552,8 +552,9 @@ JS_SetTopFrameAnnotation(JSContext *cx, void *annotation)
|
||||
ReleaseAllJITCode(cx->runtime->defaultFreeOp());
|
||||
|
||||
// Ensure that we'll never try to compile this again.
|
||||
JS_ASSERT(!script->hasIonScript());
|
||||
JS_ASSERT(!script->hasAnyIonScript());
|
||||
script->ion = ION_DISABLED_SCRIPT;
|
||||
script->parallelIon = ION_DISABLED_SCRIPT;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSObject *)
|
||||
|
@ -132,7 +132,7 @@ fun_getProperty(JSContext *cx, HandleObject obj_, HandleId id, MutableHandleValu
|
||||
// fully recovered, so we try to mitigate observing this behavior by
|
||||
// detecting its use early.
|
||||
RawScript script = iter.script().get(nogc);
|
||||
if (!script->hasIonScript())
|
||||
if (!script->hasAnyIonScript())
|
||||
ion::ForbidCompilation(cx, script);
|
||||
#endif
|
||||
|
||||
|
@ -4010,6 +4010,10 @@ EndSweepPhase(JSRuntime *rt, JSGCInvocationKind gckind, bool lastGC)
|
||||
if (rt->gcIsFull)
|
||||
SweepScriptFilenames(rt);
|
||||
|
||||
/* Clear out any small pools that we're hanging on to. */
|
||||
if (JSC::ExecutableAllocator *execAlloc = rt->maybeExecAlloc())
|
||||
execAlloc->purge();
|
||||
|
||||
/*
|
||||
* This removes compartments from rt->compartment, so we do it last to make
|
||||
* sure we don't miss sweeping any compartments.
|
||||
@ -4574,7 +4578,7 @@ IsDeterministicGCReason(gcreason::Reason reason)
|
||||
#endif
|
||||
|
||||
static bool
|
||||
ShouldCleanUpEverything(JSRuntime *rt, gcreason::Reason reason)
|
||||
ShouldCleanUpEverything(JSRuntime *rt, gcreason::Reason reason, JSGCInvocationKind gckind)
|
||||
{
|
||||
// During shutdown, we must clean everything up, for the sake of leak
|
||||
// detection. When a runtime has no contexts, or we're doing a GC before a
|
||||
@ -4585,7 +4589,8 @@ ShouldCleanUpEverything(JSRuntime *rt, gcreason::Reason reason)
|
||||
// we need to clear everything away.
|
||||
return !rt->hasContexts() ||
|
||||
reason == gcreason::SHUTDOWN_CC ||
|
||||
reason == gcreason::DEBUG_MODE_GC;
|
||||
reason == gcreason::DEBUG_MODE_GC ||
|
||||
gckind == GC_SHRINK;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -4653,7 +4658,7 @@ Collect(JSRuntime *rt, bool incremental, int64_t budget,
|
||||
collectedCount++;
|
||||
}
|
||||
|
||||
rt->gcShouldCleanUpEverything = ShouldCleanUpEverything(rt, reason);
|
||||
rt->gcShouldCleanUpEverything = ShouldCleanUpEverything(rt, reason, gckind);
|
||||
|
||||
gcstats::AutoGCSlice agc(rt->gcStats, collectedCount, compartmentCount, reason);
|
||||
|
||||
@ -5876,8 +5881,7 @@ PurgeJITCaches(JSCompartment *c)
|
||||
#ifdef JS_ION
|
||||
|
||||
/* Discard Ion caches. */
|
||||
if (script->hasIonScript())
|
||||
script->ion->purgeCaches(c);
|
||||
ion::PurgeCaches(script, c);
|
||||
|
||||
#endif
|
||||
}
|
||||
|
@ -1997,7 +1997,7 @@ JITCodeHasCheck(HandleScript script, jsbytecode *pc, RecompileKind kind)
|
||||
}
|
||||
#endif
|
||||
|
||||
if (script->hasIonScript())
|
||||
if (script->hasAnyIonScript())
|
||||
return false;
|
||||
|
||||
return true;
|
||||
@ -2026,8 +2026,14 @@ AddPendingRecompile(JSContext *cx, HandleScript script, jsbytecode *pc,
|
||||
RecompileInfo& info = cx->compartment->types.compiledInfo;
|
||||
if (info.outputIndex != RecompileInfo::NoCompilerRunning) {
|
||||
CompilerOutput *co = info.compilerOutput(cx);
|
||||
if (co->isIon() && co->script == script) {
|
||||
co->invalidate();
|
||||
switch (co->kind()) {
|
||||
case CompilerOutput::MethodJIT:
|
||||
break;
|
||||
case CompilerOutput::Ion:
|
||||
case CompilerOutput::ParallelIon:
|
||||
if (co->script == script)
|
||||
co->invalidate();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -2417,11 +2423,16 @@ TypeCompartment::processPendingRecompiles(FreeOp *fop)
|
||||
|
||||
for (unsigned i = 0; i < pending->length(); i++) {
|
||||
CompilerOutput &co = *(*pending)[i].compilerOutput(*this);
|
||||
if (co.isJM()) {
|
||||
switch (co.kind()) {
|
||||
case CompilerOutput::MethodJIT:
|
||||
JS_ASSERT(co.isValid());
|
||||
mjit::Recompiler::clearStackReferences(fop, co.script);
|
||||
co.mjit()->destroyChunk(fop, co.chunkIndex);
|
||||
JS_ASSERT(co.script == NULL);
|
||||
break;
|
||||
case CompilerOutput::Ion:
|
||||
case CompilerOutput::ParallelIon:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -2518,7 +2529,7 @@ TypeCompartment::addPendingRecompile(JSContext *cx, const RecompileInfo &info)
|
||||
bool hasJITCode = jit && jit->chunkDescriptor(co->chunkIndex).chunk;
|
||||
|
||||
# if defined(JS_ION)
|
||||
hasJITCode |= !!co->script->hasIonScript();
|
||||
hasJITCode |= !!co->script->hasAnyIonScript();
|
||||
# endif
|
||||
|
||||
if (!hasJITCode) {
|
||||
@ -2585,6 +2596,9 @@ TypeCompartment::addPendingRecompile(JSContext *cx, HandleScript script, jsbytec
|
||||
|
||||
if (script->hasIonScript())
|
||||
addPendingRecompile(cx, script->ionScript()->recompileInfo());
|
||||
|
||||
if (script->hasParallelIonScript())
|
||||
addPendingRecompile(cx, script->parallelIonScript()->recompileInfo());
|
||||
# endif
|
||||
#endif
|
||||
}
|
||||
|
@ -1213,17 +1213,27 @@ typedef HashMap<AllocationSiteKey,ReadBarriered<TypeObject>,AllocationSiteKey,Sy
|
||||
*/
|
||||
struct CompilerOutput
|
||||
{
|
||||
enum Kind {
|
||||
MethodJIT,
|
||||
Ion,
|
||||
ParallelIon
|
||||
};
|
||||
|
||||
JSScript *script;
|
||||
bool isIonFlag : 1;
|
||||
|
||||
// This integer will always be a member of CompilerOutput::Kind,
|
||||
// but, for portability, bitfields are limited to bool, int, and
|
||||
// unsigned int. You should really use the accessor below.
|
||||
unsigned kindInt : 2;
|
||||
bool constructing : 1;
|
||||
bool barriers : 1;
|
||||
bool pendingRecompilation : 1;
|
||||
uint32_t chunkIndex:28;
|
||||
uint32_t chunkIndex:27;
|
||||
|
||||
CompilerOutput();
|
||||
|
||||
bool isJM() const { return !isIonFlag; }
|
||||
bool isIon() const { return isIonFlag; }
|
||||
Kind kind() const { return static_cast<Kind>(kindInt); }
|
||||
void setKind(Kind k) { kindInt = k; }
|
||||
|
||||
mjit::JITScript *mjit() const;
|
||||
ion::IonScript *ion() const;
|
||||
|
@ -88,7 +88,7 @@ namespace types {
|
||||
inline
|
||||
CompilerOutput::CompilerOutput()
|
||||
: script(NULL),
|
||||
isIonFlag(false),
|
||||
kindInt(MethodJIT),
|
||||
constructing(false),
|
||||
barriers(false),
|
||||
chunkIndex(false)
|
||||
@ -99,7 +99,7 @@ inline mjit::JITScript *
|
||||
CompilerOutput::mjit() const
|
||||
{
|
||||
#ifdef JS_METHODJIT
|
||||
JS_ASSERT(isJM() && isValid());
|
||||
JS_ASSERT(kind() == MethodJIT && isValid());
|
||||
return script->getJIT(constructing, barriers);
|
||||
#else
|
||||
return NULL;
|
||||
@ -110,11 +110,15 @@ inline ion::IonScript *
|
||||
CompilerOutput::ion() const
|
||||
{
|
||||
#ifdef JS_ION
|
||||
JS_ASSERT(isIon() && isValid());
|
||||
return script->ionScript();
|
||||
#else
|
||||
return NULL;
|
||||
JS_ASSERT(kind() != MethodJIT && isValid());
|
||||
switch (kind()) {
|
||||
case MethodJIT: break;
|
||||
case Ion: return script->ionScript();
|
||||
case ParallelIon: return script->parallelIonScript();
|
||||
}
|
||||
#endif
|
||||
JS_NOT_REACHED("Invalid kind of CompilerOutput");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
inline bool
|
||||
@ -127,8 +131,9 @@ CompilerOutput::isValid() const
|
||||
TypeCompartment &types = script->compartment()->types;
|
||||
#endif
|
||||
|
||||
switch (kind()) {
|
||||
case MethodJIT: {
|
||||
#ifdef JS_METHODJIT
|
||||
if (isJM()) {
|
||||
mjit::JITScript *jit = script->getJIT(constructing, barriers);
|
||||
if (!jit)
|
||||
return false;
|
||||
@ -137,20 +142,31 @@ CompilerOutput::isValid() const
|
||||
return false;
|
||||
JS_ASSERT(this == chunk->recompileInfo.compilerOutput(types));
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
case Ion:
|
||||
#ifdef JS_ION
|
||||
if (isIon()) {
|
||||
if (script->hasIonScript()) {
|
||||
JS_ASSERT(this == script->ion->recompileInfo().compilerOutput(types));
|
||||
return true;
|
||||
}
|
||||
if (script->isIonCompilingOffThread())
|
||||
return true;
|
||||
#endif
|
||||
return false;
|
||||
|
||||
case ParallelIon:
|
||||
#ifdef JS_ION
|
||||
if (script->hasParallelIonScript()) {
|
||||
JS_ASSERT(this == script->parallelIonScript()->recompileInfo().compilerOutput(types));
|
||||
return true;
|
||||
}
|
||||
if (script->isParallelIonCompilingOffThread())
|
||||
return true;
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -387,17 +403,12 @@ struct AutoEnterCompilation
|
||||
{
|
||||
JSContext *cx;
|
||||
RecompileInfo &info;
|
||||
CompilerOutput::Kind kind;
|
||||
|
||||
enum Compiler {
|
||||
JM,
|
||||
Ion
|
||||
};
|
||||
Compiler mode;
|
||||
|
||||
AutoEnterCompilation(JSContext *cx, Compiler mode)
|
||||
AutoEnterCompilation(JSContext *cx, CompilerOutput::Kind kind)
|
||||
: cx(cx),
|
||||
info(cx->compartment->types.compiledInfo),
|
||||
mode(mode)
|
||||
kind(kind)
|
||||
{
|
||||
JS_ASSERT(cx->compartment->activeAnalysis);
|
||||
JS_ASSERT(info.outputIndex == RecompileInfo::NoCompilerRunning);
|
||||
@ -407,7 +418,7 @@ struct AutoEnterCompilation
|
||||
{
|
||||
CompilerOutput co;
|
||||
co.script = script;
|
||||
co.isIonFlag = (mode == Ion);
|
||||
co.setKind(kind);
|
||||
co.constructing = constructing;
|
||||
co.barriers = cx->compartment->compileBarriers();
|
||||
co.chunkIndex = chunkIndex;
|
||||
|
@ -1007,11 +1007,11 @@ class FastInvokeGuard
|
||||
|
||||
public:
|
||||
FastInvokeGuard(JSContext *cx, const Value &fval)
|
||||
: fun_(cx),
|
||||
script_(cx)
|
||||
: fun_(cx)
|
||||
, script_(cx)
|
||||
#ifdef JS_ION
|
||||
, ictx_(cx, cx->compartment, NULL),
|
||||
useIon_(ion::IsEnabled(cx))
|
||||
, ictx_(cx, cx->compartment, NULL)
|
||||
, useIon_(ion::IsEnabled(cx))
|
||||
#endif
|
||||
{
|
||||
initFunction(fval);
|
||||
@ -1036,7 +1036,7 @@ class FastInvokeGuard
|
||||
if (useIon_ && fun_) {
|
||||
JS_ASSERT(fun_->script() == script_);
|
||||
|
||||
ion::MethodStatus status = ion::CanEnterUsingFastInvoke(cx, script_);
|
||||
ion::MethodStatus status = ion::CanEnterUsingFastInvoke(cx, script_, args_.length());
|
||||
if (status == ion::Method_Error)
|
||||
return false;
|
||||
if (status == ion::Method_Compiled) {
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include "jsobjinlines.h"
|
||||
|
||||
#include "ion/IonCode.h"
|
||||
#include "ion/Ion.h"
|
||||
|
||||
namespace js {
|
||||
|
||||
@ -232,8 +233,7 @@ StatsCellCallback(JSRuntime *rt, void *data, void *thing, JSGCTraceKind traceKin
|
||||
#ifdef JS_METHODJIT
|
||||
cStats->jaegerData += script->sizeOfJitScripts(rtStats->mallocSizeOf);
|
||||
# ifdef JS_ION
|
||||
if (script->hasIonScript())
|
||||
cStats->ionData += script->ion->sizeOfIncludingThis(rtStats->mallocSizeOf);
|
||||
cStats->ionData += ion::MemoryUsed(script, rtStats->mallocSizeOf);
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
@ -1906,8 +1906,7 @@ JSScript::finalize(FreeOp *fop)
|
||||
#ifdef JS_METHODJIT
|
||||
mjit::ReleaseScriptCode(fop, this);
|
||||
# ifdef JS_ION
|
||||
if (hasIonScript())
|
||||
ion::IonScript::Destroy(fop, ion);
|
||||
ion::DestroyIonScripts(fop, this);
|
||||
# endif
|
||||
#endif
|
||||
|
||||
@ -2599,8 +2598,7 @@ JSScript::markChildren(JSTracer *trc)
|
||||
}
|
||||
|
||||
#ifdef JS_ION
|
||||
if (hasIonScript())
|
||||
ion::IonScript::Trace(trc, ion);
|
||||
ion::TraceIonScripts(trc, this);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -549,26 +549,50 @@ struct JSScript : public js::gc::Cell
|
||||
return needsArgsObj() && !strictModeCode;
|
||||
}
|
||||
|
||||
js::ion::IonScript *ion; /* Information attached by Ion */
|
||||
bool hasAnyIonScript() const {
|
||||
return hasIonScript() || hasParallelIonScript();
|
||||
}
|
||||
|
||||
#if defined(JS_METHODJIT) && JS_BITS_PER_WORD == 32
|
||||
void *padding_;
|
||||
#endif
|
||||
/* Information attached by Ion: script for sequential mode execution */
|
||||
js::ion::IonScript *ion;
|
||||
|
||||
bool hasIonScript() const {
|
||||
return ion && ion != ION_DISABLED_SCRIPT && ion != ION_COMPILING_SCRIPT;
|
||||
}
|
||||
|
||||
bool canIonCompile() const {
|
||||
return ion != ION_DISABLED_SCRIPT;
|
||||
}
|
||||
|
||||
bool isIonCompilingOffThread() const {
|
||||
return ion == ION_COMPILING_SCRIPT;
|
||||
}
|
||||
|
||||
js::ion::IonScript *ionScript() const {
|
||||
JS_ASSERT(hasIonScript());
|
||||
return ion;
|
||||
}
|
||||
|
||||
/* Information attached by Ion: script for parallel mode execution */
|
||||
js::ion::IonScript *parallelIon;
|
||||
|
||||
bool hasParallelIonScript() const {
|
||||
return parallelIon && parallelIon != ION_DISABLED_SCRIPT && parallelIon != ION_COMPILING_SCRIPT;
|
||||
}
|
||||
|
||||
bool canParallelIonCompile() const {
|
||||
return parallelIon != ION_DISABLED_SCRIPT;
|
||||
}
|
||||
|
||||
bool isParallelIonCompilingOffThread() const {
|
||||
return parallelIon == ION_COMPILING_SCRIPT;
|
||||
}
|
||||
|
||||
js::ion::IonScript *parallelIonScript() const {
|
||||
JS_ASSERT(hasParallelIonScript());
|
||||
return parallelIon;
|
||||
}
|
||||
|
||||
/*
|
||||
* Original compiled function for the script, if it has a function.
|
||||
* NULL for global and eval scripts.
|
||||
|
@ -8,6 +8,7 @@
|
||||
|
||||
#if JS_ION
|
||||
# include "ion/IonBuilder.h"
|
||||
# include "ion/ExecutionModeInlines.h"
|
||||
#endif
|
||||
|
||||
using namespace js;
|
||||
@ -294,7 +295,8 @@ WorkerThread::threadLoop()
|
||||
|
||||
ionBuilder = state.ionWorklist.popCopy();
|
||||
|
||||
JS_ASSERT(ionBuilder->script()->ion == ION_COMPILING_SCRIPT);
|
||||
ion::ExecutionMode executionMode = ionBuilder->info().executionMode();
|
||||
JS_ASSERT(GetIonScript(ionBuilder->script().unsafeGet(), executionMode) == ION_COMPILING_SCRIPT);
|
||||
|
||||
state.unlock();
|
||||
|
||||
|
@ -539,7 +539,7 @@ mjit::Compiler::performCompilation()
|
||||
JS_ASSERT(cx->compartment->activeInference);
|
||||
|
||||
{
|
||||
types::AutoEnterCompilation enter(cx, types::AutoEnterCompilation::JM);
|
||||
types::AutoEnterCompilation enter(cx, types::CompilerOutput::MethodJIT);
|
||||
if (!enter.init(outerScript, isConstructing, chunkIndex)) {
|
||||
js_ReportOutOfMemory(cx);
|
||||
return Compile_Error;
|
||||
|
@ -2052,6 +2052,7 @@ ContainerState::ProcessDisplayItems(const nsDisplayList& aList,
|
||||
|
||||
// Assign the item to a layer
|
||||
if (layerState == LAYER_ACTIVE_FORCE ||
|
||||
(layerState == LAYER_INACTIVE && !mManager->IsWidgetLayerManager()) ||
|
||||
(!forceInactive &&
|
||||
(layerState == LAYER_ACTIVE_EMPTY ||
|
||||
layerState == LAYER_ACTIVE))) {
|
||||
@ -2696,7 +2697,7 @@ ChooseScaleAndSetTransform(FrameLayerBuilder* aLayerBuilder,
|
||||
gfxMatrix transform2d;
|
||||
bool canDraw2D = transform.CanDraw2D(&transform2d);
|
||||
gfxSize scale;
|
||||
bool isRetained = aLayerBuilder->GetRetainingLayerManager() == aLayer->Manager();
|
||||
bool isRetained = aLayer->Manager()->IsWidgetLayerManager();
|
||||
// Only fiddle with scale factors for the retaining layer manager, since
|
||||
// it only matters for retained layers
|
||||
// XXX Should we do something for 3D transforms?
|
||||
|
@ -2619,30 +2619,36 @@ void nsDisplayWrapList::Paint(nsDisplayListBuilder* aBuilder,
|
||||
NS_ERROR("nsDisplayWrapList should have been flattened away for painting");
|
||||
}
|
||||
|
||||
bool nsDisplayWrapList::ChildrenCanBeInactive(nsDisplayListBuilder* aBuilder,
|
||||
LayerManager* aManager,
|
||||
const ContainerParameters& aParameters,
|
||||
const nsDisplayList& aList,
|
||||
nsIFrame* aActiveScrolledRoot) {
|
||||
LayerState
|
||||
nsDisplayWrapList::RequiredLayerStateForChildren(nsDisplayListBuilder* aBuilder,
|
||||
LayerManager* aManager,
|
||||
const ContainerParameters& aParameters,
|
||||
const nsDisplayList& aList,
|
||||
nsIFrame* aActiveScrolledRoot) {
|
||||
LayerState result = LAYER_INACTIVE;
|
||||
for (nsDisplayItem* i = aList.GetBottom(); i; i = i->GetAbove()) {
|
||||
nsIFrame* f = i->GetUnderlyingFrame();
|
||||
if (f) {
|
||||
nsIFrame* activeScrolledRoot =
|
||||
nsLayoutUtils::GetActiveScrolledRootFor(f, nullptr);
|
||||
if (activeScrolledRoot != aActiveScrolledRoot)
|
||||
return false;
|
||||
if (activeScrolledRoot != aActiveScrolledRoot && result == LAYER_INACTIVE)
|
||||
result = LAYER_ACTIVE;
|
||||
}
|
||||
|
||||
LayerState state = i->GetLayerState(aBuilder, aManager, aParameters);
|
||||
if (state == LAYER_ACTIVE || state == LAYER_ACTIVE_FORCE)
|
||||
return false;
|
||||
if ((state == LAYER_ACTIVE || state == LAYER_ACTIVE_FORCE) && (state > result))
|
||||
result = state;
|
||||
if (state == LAYER_NONE) {
|
||||
nsDisplayList* list = i->GetSameCoordinateSystemChildren();
|
||||
if (list && !ChildrenCanBeInactive(aBuilder, aManager, aParameters, *list, aActiveScrolledRoot))
|
||||
return false;
|
||||
if (list) {
|
||||
LayerState childState = RequiredLayerStateForChildren(aBuilder, aManager, aParameters, *list, aActiveScrolledRoot);
|
||||
if (childState > result) {
|
||||
result = childState;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
return result;
|
||||
}
|
||||
|
||||
nsRect nsDisplayWrapList::GetComponentAlphaBounds(nsDisplayListBuilder* aBuilder)
|
||||
@ -2792,8 +2798,7 @@ nsDisplayOpacity::GetLayerState(nsDisplayListBuilder* aBuilder,
|
||||
}
|
||||
nsIFrame* activeScrolledRoot =
|
||||
nsLayoutUtils::GetActiveScrolledRootFor(mFrame, nullptr);
|
||||
return !ChildrenCanBeInactive(aBuilder, aManager, aParameters, mList, activeScrolledRoot)
|
||||
? LAYER_ACTIVE : LAYER_INACTIVE;
|
||||
return RequiredLayerStateForChildren(aBuilder, aManager, aParameters, mList, activeScrolledRoot);
|
||||
}
|
||||
|
||||
bool
|
||||
@ -3938,13 +3943,17 @@ nsDisplayItem::LayerState
|
||||
nsDisplayTransform::GetLayerState(nsDisplayListBuilder* aBuilder,
|
||||
LayerManager* aManager,
|
||||
const ContainerParameters& aParameters) {
|
||||
// If the transform is 3d, or the layer takes part in preserve-3d sorting
|
||||
// then we *always* want this to be an active layer.
|
||||
if (!GetTransform(mFrame->PresContext()->AppUnitsPerDevPixel()).Is2D() ||
|
||||
mFrame->Preserves3D()) {
|
||||
return LAYER_ACTIVE_FORCE;
|
||||
}
|
||||
// Here we check if the *post-transform* bounds of this item are big enough
|
||||
// to justify an active layer.
|
||||
if (mFrame->AreLayersMarkedActive(nsChangeHint_UpdateTransformLayer) &&
|
||||
!IsItemTooSmallForActiveLayer(this))
|
||||
return LAYER_ACTIVE;
|
||||
if (!GetTransform(mFrame->PresContext()->AppUnitsPerDevPixel()).Is2D() || mFrame->Preserves3D())
|
||||
return LAYER_ACTIVE;
|
||||
if (mFrame->GetContent()) {
|
||||
if (nsLayoutUtils::HasAnimationsForCompositor(mFrame->GetContent(),
|
||||
eCSSProperty_transform)) {
|
||||
@ -3953,12 +3962,11 @@ nsDisplayTransform::GetLayerState(nsDisplayListBuilder* aBuilder,
|
||||
}
|
||||
nsIFrame* activeScrolledRoot =
|
||||
nsLayoutUtils::GetActiveScrolledRootFor(mFrame, nullptr);
|
||||
return !mStoredList.ChildrenCanBeInactive(aBuilder,
|
||||
aManager,
|
||||
aParameters,
|
||||
*mStoredList.GetChildren(),
|
||||
activeScrolledRoot)
|
||||
? LAYER_ACTIVE : LAYER_INACTIVE;
|
||||
return mStoredList.RequiredLayerStateForChildren(aBuilder,
|
||||
aManager,
|
||||
aParameters,
|
||||
*mStoredList.GetChildren(),
|
||||
activeScrolledRoot);
|
||||
}
|
||||
|
||||
bool nsDisplayTransform::ComputeVisibility(nsDisplayListBuilder *aBuilder,
|
||||
|
@ -1886,6 +1886,12 @@ public:
|
||||
virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
|
||||
HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames) MOZ_OVERRIDE;
|
||||
|
||||
virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) MOZ_OVERRIDE
|
||||
{
|
||||
*aSnap = true;
|
||||
return nsRect(ToReferenceFrame(), GetUnderlyingFrame()->GetSize());
|
||||
}
|
||||
|
||||
NS_DISPLAY_DECL_NAME("BackgroundColor", TYPE_BACKGROUND_COLOR)
|
||||
|
||||
nscolor mColor;
|
||||
@ -2123,11 +2129,11 @@ public:
|
||||
* ThebesLayer --- GetLayerState returns LAYER_INACTIVE or LAYER_NONE,
|
||||
* and they all have the given aActiveScrolledRoot.
|
||||
*/
|
||||
static bool ChildrenCanBeInactive(nsDisplayListBuilder* aBuilder,
|
||||
LayerManager* aManager,
|
||||
const ContainerParameters& aParameters,
|
||||
const nsDisplayList& aList,
|
||||
nsIFrame* aActiveScrolledRoot);
|
||||
static LayerState RequiredLayerStateForChildren(nsDisplayListBuilder* aBuilder,
|
||||
LayerManager* aManager,
|
||||
const ContainerParameters& aParameters,
|
||||
const nsDisplayList& aList,
|
||||
nsIFrame* aActiveScrolledRoot);
|
||||
|
||||
protected:
|
||||
nsDisplayWrapList() {}
|
||||
|
@ -2617,7 +2617,13 @@ nsRootPresContext::ComputePluginGeometryUpdates(nsIFrame* aFrame,
|
||||
aList->ComputeVisibilityForRoot(aBuilder, ®ion);
|
||||
}
|
||||
|
||||
#ifdef XP_MACOSX
|
||||
// We control painting of Mac plugins, so just apply geometry updates now.
|
||||
// This is not happening during a paint event.
|
||||
ApplyPluginGeometryUpdates();
|
||||
#else
|
||||
InitApplyPluginGeometryTimer();
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user