Merge last PGO-green changeset of mozilla-inbound to mozilla-central

This commit is contained in:
Ed Morley 2012-11-14 14:35:55 +00:00
commit f26dc0969e
171 changed files with 2832 additions and 1934 deletions

View File

@ -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

View File

@ -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:

View File

@ -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();
}

View File

@ -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);

View File

@ -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;
}

View File

@ -113,7 +113,7 @@ let gTests = [
clean: function() {},
event: {},
targets: [ "panellink" ],
expectedInvokedMethods: [ "urlSecurityCheck", "getShortcutOrURI", "loadURI" ],
expectedInvokedMethods: [ "urlSecurityCheck", "loadURI" ],
preventDefault: true,
},

View File

@ -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 {

View File

@ -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)

View File

@ -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();
});
});
});
});
});
});
});
});
});
});
}

View File

@ -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);
});
}
};

View File

@ -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

View File

@ -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

View File

@ -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 {

View File

@ -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 {

View File

@ -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 {

View File

@ -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

View File

@ -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;

View File

@ -19,6 +19,7 @@ LIBXUL_LIBRARY = 1
EXPORTS_NAMESPACES = mozilla/dom
EXPORTS_mozilla/dom = \
CanvasUtils.h \
CanvasRenderingContext2D.h \
ImageData.h \
$(NULL)

View File

@ -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)

View 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>

View File

@ -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>

View File

@ -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>

View File

@ -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

View File

@ -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;

View File

@ -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_-

View File

@ -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,

View File

@ -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)
{

View File

@ -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");

View File

@ -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;

View File

@ -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

View File

@ -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,

View File

@ -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();

View File

@ -118,6 +118,8 @@ private:
nsCOMPtr<nsIThread> mReadFileThread;
nsCOMPtr<nsIOutputStream> mOutputStream;
nsCOMPtr<nsIInputStream> mInputStream;
nsRefPtr<BluetoothReplyRunnable> mRunnable;
};
END_BLUETOOTH_NAMESPACE

View File

@ -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]);

View File

@ -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);

View File

@ -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;

View File

@ -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);
}

View File

@ -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

View File

@ -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.
*/

View File

@ -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);
};

View File

@ -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);

View File

@ -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;

View File

@ -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(

View File

@ -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

View File

@ -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(

View File

@ -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)

View File

@ -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;
}

View File

@ -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,

View File

@ -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"},

View File

@ -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]

View 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();

View 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();

View 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();

View File

@ -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;

View File

@ -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;
}

View File

@ -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:

View File

@ -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 {

View File

@ -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;
}

View File

@ -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
#

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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 },

View File

@ -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",

View File

@ -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)
{

View File

@ -17,8 +17,6 @@ LIBXUL_LIBRARY = 1
CPPSRCS = \
nsEUCKRToUnicode.cpp \
nsUnicodeToEUCKR.cpp \
nsISO2022KRToUnicode.cpp \
nsCP949ToUnicode.cpp \
nsUnicodeToCP949.cpp \

View File

@ -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);
}

View File

@ -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___ */

View File

@ -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 \

View File

@ -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);
}

View File

@ -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___ */

View File

@ -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

View File

@ -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.

View File

@ -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) \

View File

@ -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

View File

@ -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;
}

View File

@ -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

View 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

View File

@ -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);
}

View File

@ -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

View File

@ -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;

View 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();

View File

@ -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);
}

View File

@ -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 *)

View File

@ -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

View File

@ -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
}

View File

@ -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
}

View File

@ -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;

View File

@ -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;

View File

@ -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) {

View File

@ -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

View File

@ -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
}

View File

@ -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.

View File

@ -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();

View File

@ -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;

View File

@ -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?

View File

@ -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,

View File

@ -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() {}

View File

@ -2617,7 +2617,13 @@ nsRootPresContext::ComputePluginGeometryUpdates(nsIFrame* aFrame,
aList->ComputeVisibilityForRoot(aBuilder, &region);
}
#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