зеркало из https://github.com/mozilla/pjs.git
merge m-c to devtools
This commit is contained in:
Коммит
54e867b3be
|
@ -38,6 +38,9 @@
|
||||||
|
|
||||||
#include "nsAccessNodeWrap.h"
|
#include "nsAccessNodeWrap.h"
|
||||||
#include "nsApplicationAccessibleWrap.h"
|
#include "nsApplicationAccessibleWrap.h"
|
||||||
|
#include "nsMaiInterfaceText.h"
|
||||||
|
|
||||||
|
PRBool nsAccessNodeWrap::gHaveNewTextSignals = PR_FALSE;
|
||||||
|
|
||||||
/* For documentation of the accessibility architecture,
|
/* For documentation of the accessibility architecture,
|
||||||
* see http://lxr.mozilla.org/seamonkey/source/accessible/accessible-docs.html
|
* see http://lxr.mozilla.org/seamonkey/source/accessible/accessible-docs.html
|
||||||
|
@ -68,6 +71,7 @@ nsAccessNodeWrap::~nsAccessNodeWrap()
|
||||||
void nsAccessNodeWrap::InitAccessibility()
|
void nsAccessNodeWrap::InitAccessibility()
|
||||||
{
|
{
|
||||||
nsAccessNode::InitXPAccessibility();
|
nsAccessNode::InitXPAccessibility();
|
||||||
|
gHaveNewTextSignals = g_signal_lookup("text-insert", ATK_TYPE_TEXT);
|
||||||
}
|
}
|
||||||
|
|
||||||
void nsAccessNodeWrap::ShutdownAccessibility()
|
void nsAccessNodeWrap::ShutdownAccessibility()
|
||||||
|
|
|
@ -53,6 +53,13 @@ public: // construction, destruction
|
||||||
|
|
||||||
static void InitAccessibility();
|
static void InitAccessibility();
|
||||||
static void ShutdownAccessibility();
|
static void ShutdownAccessibility();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* do we have text-remove and text-insert signals if not we need to use
|
||||||
|
* text-changed see nsAccessibleWrap::FireAtkTextChangedEvent() and
|
||||||
|
* bug 619002
|
||||||
|
*/
|
||||||
|
static PRBool gHaveNewTextSignals;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1361,14 +1361,27 @@ nsAccessibleWrap::FireAtkTextChangedEvent(AccEvent* aEvent,
|
||||||
PRInt32 start = event->GetStartOffset();
|
PRInt32 start = event->GetStartOffset();
|
||||||
PRUint32 length = event->GetLength();
|
PRUint32 length = event->GetLength();
|
||||||
PRBool isInserted = event->IsTextInserted();
|
PRBool isInserted = event->IsTextInserted();
|
||||||
|
|
||||||
PRBool isFromUserInput = aEvent->IsFromUserInput();
|
PRBool isFromUserInput = aEvent->IsFromUserInput();
|
||||||
|
char* signal_name = nsnull;
|
||||||
|
|
||||||
char *signal_name = g_strconcat(isInserted ? "text_changed::insert" : "text_changed::delete",
|
if (gHaveNewTextSignals) {
|
||||||
isFromUserInput ? "" : kNonUserInputEvent, NULL);
|
nsAutoString text;
|
||||||
g_signal_emit_by_name(aObject, signal_name, start, length);
|
event->GetModifiedText(text);
|
||||||
g_free (signal_name);
|
signal_name = g_strconcat(isInserted ? "text-insert" : "text-remove",
|
||||||
|
isFromUserInput ? "" : "::system", NULL);
|
||||||
|
g_signal_emit_by_name(aObject, signal_name, start, length,
|
||||||
|
NS_ConvertUTF16toUTF8(text).get());
|
||||||
|
} else {
|
||||||
|
// XXX remove this code and the gHaveNewTextSignals check when we can
|
||||||
|
// stop supporting old atk since it doesn't really work anyway
|
||||||
|
// see bug 619002
|
||||||
|
signal_name = g_strconcat(isInserted ? "text_changed::insert" :
|
||||||
|
"text_changed::delete",
|
||||||
|
isFromUserInput ? "" : kNonUserInputEvent, NULL);
|
||||||
|
g_signal_emit_by_name(aObject, signal_name, start, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_free(signal_name);
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -422,6 +422,9 @@ nsHTMLTextFieldAccessible::GetNameInternal(nsAString& aName)
|
||||||
|
|
||||||
NS_IMETHODIMP nsHTMLTextFieldAccessible::GetValue(nsAString& _retval)
|
NS_IMETHODIMP nsHTMLTextFieldAccessible::GetValue(nsAString& _retval)
|
||||||
{
|
{
|
||||||
|
if (IsDefunct())
|
||||||
|
return NS_ERROR_FAILURE;
|
||||||
|
|
||||||
if (NativeState() & states::PROTECTED) // Don't return password text!
|
if (NativeState() & states::PROTECTED) // Don't return password text!
|
||||||
return NS_ERROR_FAILURE;
|
return NS_ERROR_FAILURE;
|
||||||
|
|
||||||
|
|
|
@ -65,9 +65,9 @@ function init(aEvent)
|
||||||
// Pref is unset
|
// Pref is unset
|
||||||
}
|
}
|
||||||
|
|
||||||
// Include the build ID if this is a "pre" (i.e. non-release) build
|
// Include the build ID if this is an "a#" (nightly or aurora) build
|
||||||
let version = Services.appinfo.version;
|
let version = Services.appinfo.version;
|
||||||
if (version.indexOf("pre") != -1) {
|
if (/a\d+$/.test(version)) {
|
||||||
let buildID = Services.appinfo.appBuildID;
|
let buildID = Services.appinfo.appBuildID;
|
||||||
let buildDate = buildID.slice(0,4) + "-" + buildID.slice(4,6) + "-" + buildID.slice(6,8);
|
let buildDate = buildID.slice(0,4) + "-" + buildID.slice(4,6) + "-" + buildID.slice(6,8);
|
||||||
document.getElementById("version").value += " (" + buildDate + ")";
|
document.getElementById("version").value += " (" + buildDate + ")";
|
||||||
|
|
|
@ -172,10 +172,9 @@ let TabView = {
|
||||||
if (this.isVisible())
|
if (this.isVisible())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
let self = this;
|
||||||
this._initFrame(function() {
|
this._initFrame(function() {
|
||||||
let event = document.createEvent("Events");
|
self._window.UI.showTabView(true);
|
||||||
event.initEvent("tabviewshow", false, false);
|
|
||||||
dispatchEvent(event);
|
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -184,9 +183,7 @@ let TabView = {
|
||||||
if (!this.isVisible())
|
if (!this.isVisible())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
let event = document.createEvent("Events");
|
this._window.UI.exit();
|
||||||
event.initEvent("tabviewhide", false, false);
|
|
||||||
dispatchEvent(event);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
// ----------
|
// ----------
|
||||||
|
|
|
@ -132,7 +132,7 @@ var TabUtils = {
|
||||||
// of active Panoramas as well as for windows in which
|
// of active Panoramas as well as for windows in which
|
||||||
// Panorama has yet to be activated. We uses object sniffing to
|
// Panorama has yet to be activated. We uses object sniffing to
|
||||||
// determine the type of tab and then returns its name.
|
// determine the type of tab and then returns its name.
|
||||||
return tab.label != undefined ? tab.label : tab.$tabTitle[0].innerHTML;
|
return tab.label != undefined ? tab.label : tab.$tabTitle[0].textContent;
|
||||||
},
|
},
|
||||||
|
|
||||||
// ---------
|
// ---------
|
||||||
|
|
|
@ -163,11 +163,6 @@ let UI = {
|
||||||
this._storageSanity(data);
|
this._storageSanity(data);
|
||||||
this._pageBounds = data.pageBounds;
|
this._pageBounds = data.pageBounds;
|
||||||
|
|
||||||
// ___ hook into the browser
|
|
||||||
gWindow.addEventListener("tabviewshow", function() {
|
|
||||||
self.showTabView(true);
|
|
||||||
}, false);
|
|
||||||
|
|
||||||
// ___ currentTab
|
// ___ currentTab
|
||||||
this._currentTab = gBrowser.selectedTab;
|
this._currentTab = gBrowser.selectedTab;
|
||||||
|
|
||||||
|
@ -226,10 +221,6 @@ let UI = {
|
||||||
self.uninit();
|
self.uninit();
|
||||||
});
|
});
|
||||||
|
|
||||||
gWindow.addEventListener("tabviewhide", function() {
|
|
||||||
self.exit();
|
|
||||||
}, false);
|
|
||||||
|
|
||||||
// ___ setup key handlers
|
// ___ setup key handlers
|
||||||
this._setTabViewFrameKeyHandlers();
|
this._setTabViewFrameKeyHandlers();
|
||||||
|
|
||||||
|
|
|
@ -25,8 +25,10 @@ function onTabViewWindowLoaded() {
|
||||||
window.removeEventListener("tabviewshown", onTabViewWindowLoaded, false);
|
window.removeEventListener("tabviewshown", onTabViewWindowLoaded, false);
|
||||||
ok(TabView.isVisible(), "Tab View is visible");
|
ok(TabView.isVisible(), "Tab View is visible");
|
||||||
|
|
||||||
let contentWindow = document.getElementById("tab-view").contentWindow;
|
afterAllTabItemsUpdated(function() {
|
||||||
testOne(contentWindow);
|
let contentWindow = document.getElementById("tab-view").contentWindow;
|
||||||
|
testOne(contentWindow);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function testOne(contentWindow) {
|
function testOne(contentWindow) {
|
||||||
|
|
|
@ -20,10 +20,6 @@ function test() {
|
||||||
prefix + ": panorama button should not be in the toolbar");
|
prefix + ": panorama button should not be in the toolbar");
|
||||||
}
|
}
|
||||||
|
|
||||||
let assertNumberOfGroups = function (num) {
|
|
||||||
is(cw.GroupItems.groupItems.length, num, prefix + ': there are ' + num + ' groups');
|
|
||||||
}
|
|
||||||
|
|
||||||
let assertNumberOfTabs = function (num) {
|
let assertNumberOfTabs = function (num) {
|
||||||
is(win.gBrowser.tabs.length, num, prefix + ': there are ' + num + ' tabs');
|
is(win.gBrowser.tabs.length, num, prefix + ': there are ' + num + ' tabs');
|
||||||
}
|
}
|
||||||
|
@ -91,7 +87,7 @@ function test() {
|
||||||
assertToolbarButtonExists();
|
assertToolbarButtonExists();
|
||||||
|
|
||||||
next();
|
next();
|
||||||
});
|
}, win);
|
||||||
}
|
}
|
||||||
|
|
||||||
let testDragToCreateOrphan = function (tab) {
|
let testDragToCreateOrphan = function (tab) {
|
||||||
|
@ -124,14 +120,19 @@ function test() {
|
||||||
prefix = 're-adding-after-removal';
|
prefix = 're-adding-after-removal';
|
||||||
assertToolbarButtonNotExists();
|
assertToolbarButtonNotExists();
|
||||||
|
|
||||||
TabView.firstUseExperienced = true;
|
win.TabView.firstUseExperienced = true;
|
||||||
|
assertToolbarButtonExists();
|
||||||
removeToolbarButton();
|
removeToolbarButton();
|
||||||
|
|
||||||
TabView.firstUseExperienced = true;
|
|
||||||
TabView._addToolbarButton();
|
|
||||||
|
|
||||||
assertToolbarButtonNotExists();
|
assertToolbarButtonNotExists();
|
||||||
next();
|
|
||||||
|
win.close();
|
||||||
|
|
||||||
|
newWindowWithTabView(function (newWin) {
|
||||||
|
win = newWin;
|
||||||
|
win.TabView.firstUseExperienced = true;
|
||||||
|
assertToolbarButtonNotExists();
|
||||||
|
next();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
let tests = [testNameGroup, testDragToCreateGroup, testCreateOrphan,
|
let tests = [testNameGroup, testDragToCreateGroup, testCreateOrphan,
|
||||||
|
@ -140,39 +141,39 @@ function test() {
|
||||||
let next = function () {
|
let next = function () {
|
||||||
let test = tests.shift();
|
let test = tests.shift();
|
||||||
|
|
||||||
if (win)
|
|
||||||
win.close();
|
|
||||||
|
|
||||||
if (!test) {
|
if (!test) {
|
||||||
finish();
|
finish();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
newWindowWithTabView(
|
if (win)
|
||||||
function (newWin) {
|
win.close();
|
||||||
cw = win.TabView.getContentWindow();
|
|
||||||
let groupItem = cw.GroupItems.groupItems[0];
|
|
||||||
groupItem.setSize(200, 200, true);
|
|
||||||
groupItem.setUserSize();
|
|
||||||
|
|
||||||
|
TabView.firstUseExperienced = false;
|
||||||
|
|
||||||
|
let onLoad = function (newWin) {
|
||||||
|
win = newWin;
|
||||||
|
removeToolbarButton();
|
||||||
|
}
|
||||||
|
|
||||||
|
let onShow = function () {
|
||||||
|
cw = win.TabView.getContentWindow();
|
||||||
|
|
||||||
|
let groupItem = cw.GroupItems.groupItems[0];
|
||||||
|
groupItem.setSize(200, 200, true);
|
||||||
|
groupItem.setUserSize();
|
||||||
|
|
||||||
|
SimpleTest.waitForFocus(function () {
|
||||||
assertToolbarButtonNotExists();
|
assertToolbarButtonNotExists();
|
||||||
test();
|
test();
|
||||||
},
|
}, cw);
|
||||||
function(newWin) {
|
}
|
||||||
win = newWin;
|
|
||||||
removeToolbarButton();
|
newWindowWithTabView(onShow, onLoad);
|
||||||
TabView.firstUseExperienced = false;
|
|
||||||
TabView.init();
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
waitForExplicitFinish();
|
waitForExplicitFinish();
|
||||||
|
registerCleanupFunction(function () win && win.close());
|
||||||
registerCleanupFunction(function () {
|
|
||||||
if (win && !win.closed)
|
|
||||||
win.close();
|
|
||||||
});
|
|
||||||
|
|
||||||
next();
|
next();
|
||||||
}
|
}
|
||||||
|
|
|
@ -760,6 +760,3 @@ function countTabs() {
|
||||||
return [needsRestore, isRestoring, wasRestored];
|
return [needsRestore, isRestoring, wasRestored];
|
||||||
}
|
}
|
||||||
|
|
||||||
function r() {
|
|
||||||
return "" + Date.now() + Math.random();
|
|
||||||
}
|
|
||||||
|
|
|
@ -170,8 +170,3 @@ function test() {
|
||||||
// Restore state
|
// Restore state
|
||||||
ss.setBrowserState(JSON.stringify(state));
|
ss.setBrowserState(JSON.stringify(state));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Helper function to create a random value
|
|
||||||
function r() {
|
|
||||||
return "" + Date.now() + Math.random();
|
|
||||||
}
|
|
||||||
|
|
|
@ -50,54 +50,6 @@ function testBug600545() {
|
||||||
// Set the pref to false to cause non-app tabs to be stripped out on a save
|
// Set the pref to false to cause non-app tabs to be stripped out on a save
|
||||||
Services.prefs.setBoolPref("browser.sessionstore.resume_from_crash", false);
|
Services.prefs.setBoolPref("browser.sessionstore.resume_from_crash", false);
|
||||||
|
|
||||||
// Need to wait for SessionStore's saveState function to be called
|
|
||||||
// so that non-pinned tabs will be stripped from non-active window
|
|
||||||
function waitForSaveState(aSaveStateCallback) {
|
|
||||||
let topic = "sessionstore-state-write";
|
|
||||||
Services.obs.addObserver(function() {
|
|
||||||
Services.obs.removeObserver(arguments.callee, topic, false);
|
|
||||||
executeSoon(aSaveStateCallback);
|
|
||||||
}, topic, false);
|
|
||||||
};
|
|
||||||
|
|
||||||
// Need to wait for all tabs to be restored before reading browser state
|
|
||||||
function waitForBrowserState(aState, aSetStateCallback) {
|
|
||||||
let tabsRestored = 0;
|
|
||||||
let expectedTabs = getStateTabCount(aState);
|
|
||||||
|
|
||||||
// We know that there are only 2 windows total, so just be specific
|
|
||||||
let newWin;
|
|
||||||
|
|
||||||
// Used to determine when tabs have been restored
|
|
||||||
function onTabRestored(aEvent) {
|
|
||||||
if (++tabsRestored == expectedTabs) {
|
|
||||||
gBrowser.tabContainer.removeEventListener("SSTabRestored", onTabRestored, true);
|
|
||||||
newWin.gBrowser.tabContainer.removeEventListener("SSTabRestored", onTabRestored, true);
|
|
||||||
executeSoon(aSetStateCallback);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// We also want to catch the 2nd window, so we need to observe domwindowopened
|
|
||||||
function windowObserver(aSubject, aTopic, aData) {
|
|
||||||
let theWin = aSubject.QueryInterface(Ci.nsIDOMWindow);
|
|
||||||
if (aTopic == "domwindowopened") {
|
|
||||||
theWin.addEventListener("load", function() {
|
|
||||||
theWin.removeEventListener("load", arguments.callee, false);
|
|
||||||
|
|
||||||
// So we can remove the event listener in onTabRestored
|
|
||||||
newWin = theWin;
|
|
||||||
|
|
||||||
Services.ww.unregisterNotification(windowObserver);
|
|
||||||
theWin.gBrowser.tabContainer.addEventListener("SSTabRestored", onTabRestored, true);
|
|
||||||
}, false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Services.ww.registerNotification(windowObserver);
|
|
||||||
gBrowser.tabContainer.addEventListener("SSTabRestored", onTabRestored, true);
|
|
||||||
ss.setBrowserState(JSON.stringify(aState));
|
|
||||||
}
|
|
||||||
|
|
||||||
// This tests the following use case:
|
// This tests the following use case:
|
||||||
// When multiple windows are open and browser.sessionstore.resume_from_crash
|
// When multiple windows are open and browser.sessionstore.resume_from_crash
|
||||||
// preference is false, tab session data for non-active window is stripped for
|
// preference is false, tab session data for non-active window is stripped for
|
||||||
|
@ -124,6 +76,8 @@ function testBug600545() {
|
||||||
] };
|
] };
|
||||||
|
|
||||||
waitForBrowserState(state, function() {
|
waitForBrowserState(state, function() {
|
||||||
|
// Need to wait for SessionStore's saveState function to be called
|
||||||
|
// so that non-pinned tabs will be stripped from non-active window
|
||||||
waitForSaveState(function () {
|
waitForSaveState(function () {
|
||||||
let expectedNumberOfTabs = getStateTabCount(state);
|
let expectedNumberOfTabs = getStateTabCount(state);
|
||||||
let retrievedState = JSON.parse(ss.getBrowserState());
|
let retrievedState = JSON.parse(ss.getBrowserState());
|
||||||
|
|
|
@ -148,7 +148,3 @@ function test() {
|
||||||
ss.setBrowserState(JSON.stringify(state));
|
ss.setBrowserState(JSON.stringify(state));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Helper function to create a random value
|
|
||||||
function r() {
|
|
||||||
return "" + Date.now() + Math.random();
|
|
||||||
}
|
|
||||||
|
|
|
@ -80,19 +80,6 @@ function runNextTest() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// helper, works only for single window
|
|
||||||
function waitForBrowserState(aState, aSetStateCallback) {
|
|
||||||
let tabsRestored = 0;
|
|
||||||
gBrowser.tabContainer.addEventListener("SSTabRestored", function() {
|
|
||||||
if (++tabsRestored == aState.windows[0].tabs.length) {
|
|
||||||
gBrowser.tabContainer.removeEventListener("SSTabRestored", arguments.callee, true);
|
|
||||||
executeSoon(aSetStateCallback);
|
|
||||||
}
|
|
||||||
}, true);
|
|
||||||
ss.setBrowserState(JSON.stringify(aState));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function test_setup() {
|
function test_setup() {
|
||||||
function onSSTabRestored(aEvent) {
|
function onSSTabRestored(aEvent) {
|
||||||
gBrowser.tabContainer.removeEventListener("SSTabRestored", onSSTabRestored, false);
|
gBrowser.tabContainer.removeEventListener("SSTabRestored", onSSTabRestored, false);
|
||||||
|
|
|
@ -106,20 +106,23 @@ nsGNOMEShellService::Init()
|
||||||
{
|
{
|
||||||
nsresult rv;
|
nsresult rv;
|
||||||
|
|
||||||
// GConf _must_ be available, or we do not allow
|
// GConf or GIO _must_ be available, or we do not allow
|
||||||
// CreateInstance to succeed.
|
// CreateInstance to succeed.
|
||||||
|
|
||||||
nsCOMPtr<nsIGConfService> gconf = do_GetService(NS_GCONFSERVICE_CONTRACTID);
|
nsCOMPtr<nsIGConfService> gconf = do_GetService(NS_GCONFSERVICE_CONTRACTID);
|
||||||
nsCOMPtr<nsIGIOService> giovfs =
|
nsCOMPtr<nsIGIOService> giovfs =
|
||||||
do_GetService(NS_GIOSERVICE_CONTRACTID);
|
do_GetService(NS_GIOSERVICE_CONTRACTID);
|
||||||
|
|
||||||
if (!gconf)
|
if (!gconf && !giovfs)
|
||||||
return NS_ERROR_NOT_AVAILABLE;
|
return NS_ERROR_NOT_AVAILABLE;
|
||||||
|
|
||||||
// Check G_BROKEN_FILENAMES. If it's set, then filenames in glib use
|
// Check G_BROKEN_FILENAMES. If it's set, then filenames in glib use
|
||||||
// the locale encoding. If it's not set, they use UTF-8.
|
// the locale encoding. If it's not set, they use UTF-8.
|
||||||
mUseLocaleFilenames = PR_GetEnv("G_BROKEN_FILENAMES") != nsnull;
|
mUseLocaleFilenames = PR_GetEnv("G_BROKEN_FILENAMES") != nsnull;
|
||||||
|
|
||||||
|
if (GetAppPathFromLauncher())
|
||||||
|
return NS_OK;
|
||||||
|
|
||||||
nsCOMPtr<nsIProperties> dirSvc
|
nsCOMPtr<nsIProperties> dirSvc
|
||||||
(do_GetService("@mozilla.org/file/directory_service;1"));
|
(do_GetService("@mozilla.org/file/directory_service;1"));
|
||||||
NS_ENSURE_TRUE(dirSvc, NS_ERROR_NOT_AVAILABLE);
|
NS_ENSURE_TRUE(dirSvc, NS_ERROR_NOT_AVAILABLE);
|
||||||
|
@ -137,6 +140,34 @@ nsGNOMEShellService::Init()
|
||||||
|
|
||||||
NS_IMPL_ISUPPORTS1(nsGNOMEShellService, nsIShellService)
|
NS_IMPL_ISUPPORTS1(nsGNOMEShellService, nsIShellService)
|
||||||
|
|
||||||
|
PRBool
|
||||||
|
nsGNOMEShellService::GetAppPathFromLauncher()
|
||||||
|
{
|
||||||
|
gchar *tmp;
|
||||||
|
|
||||||
|
const char *launcher = PR_GetEnv("MOZ_APP_LAUNCHER");
|
||||||
|
if (!launcher)
|
||||||
|
return PR_FALSE;
|
||||||
|
|
||||||
|
if (g_path_is_absolute(launcher)) {
|
||||||
|
mAppPath = launcher;
|
||||||
|
tmp = g_path_get_basename(launcher);
|
||||||
|
gchar *fullpath = g_find_program_in_path(tmp);
|
||||||
|
if (fullpath && mAppPath.Equals(fullpath))
|
||||||
|
mAppIsInPath = PR_TRUE;
|
||||||
|
g_free(fullpath);
|
||||||
|
} else {
|
||||||
|
tmp = g_find_program_in_path(launcher);
|
||||||
|
if (!tmp)
|
||||||
|
return PR_FALSE;
|
||||||
|
mAppPath = tmp;
|
||||||
|
mAppIsInPath = PR_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_free(tmp);
|
||||||
|
return PR_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
PRBool
|
PRBool
|
||||||
nsGNOMEShellService::KeyMatchesAppName(const char *aKeyValue) const
|
nsGNOMEShellService::KeyMatchesAppName(const char *aKeyValue) const
|
||||||
{
|
{
|
||||||
|
@ -163,6 +194,27 @@ nsGNOMEShellService::KeyMatchesAppName(const char *aKeyValue) const
|
||||||
return matches;
|
return matches;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PRBool
|
||||||
|
nsGNOMEShellService::CheckHandlerMatchesAppName(const nsACString &handler) const
|
||||||
|
{
|
||||||
|
gint argc;
|
||||||
|
gchar **argv;
|
||||||
|
nsCAutoString command(handler);
|
||||||
|
|
||||||
|
// The string will be something of the form: [/path/to/]browser "%s"
|
||||||
|
// We want to remove all of the parameters and get just the binary name.
|
||||||
|
|
||||||
|
if (g_shell_parse_argv(command.get(), &argc, &argv, NULL) && argc > 0) {
|
||||||
|
command.Assign(argv[0]);
|
||||||
|
g_strfreev(argv);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!KeyMatchesAppName(command.get()))
|
||||||
|
return PR_FALSE; // the handler is set to another app
|
||||||
|
|
||||||
|
return PR_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsGNOMEShellService::IsDefaultBrowser(PRBool aStartupCheck,
|
nsGNOMEShellService::IsDefaultBrowser(PRBool aStartupCheck,
|
||||||
PRBool* aIsDefaultBrowser)
|
PRBool* aIsDefaultBrowser)
|
||||||
|
@ -172,31 +224,37 @@ nsGNOMEShellService::IsDefaultBrowser(PRBool aStartupCheck,
|
||||||
mCheckedThisSession = PR_TRUE;
|
mCheckedThisSession = PR_TRUE;
|
||||||
|
|
||||||
nsCOMPtr<nsIGConfService> gconf = do_GetService(NS_GCONFSERVICE_CONTRACTID);
|
nsCOMPtr<nsIGConfService> gconf = do_GetService(NS_GCONFSERVICE_CONTRACTID);
|
||||||
|
nsCOMPtr<nsIGIOService> giovfs = do_GetService(NS_GIOSERVICE_CONTRACTID);
|
||||||
|
|
||||||
PRBool enabled;
|
PRBool enabled;
|
||||||
nsCAutoString handler;
|
nsCAutoString handler;
|
||||||
|
nsCOMPtr<nsIGIOMimeApp> gioApp;
|
||||||
|
|
||||||
for (unsigned int i = 0; i < NS_ARRAY_LENGTH(appProtocols); ++i) {
|
for (unsigned int i = 0; i < NS_ARRAY_LENGTH(appProtocols); ++i) {
|
||||||
if (!appProtocols[i].essential)
|
if (!appProtocols[i].essential)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
handler.Truncate();
|
if (gconf) {
|
||||||
gconf->GetAppForProtocol(nsDependentCString(appProtocols[i].name),
|
handler.Truncate();
|
||||||
&enabled, handler);
|
gconf->GetAppForProtocol(nsDependentCString(appProtocols[i].name),
|
||||||
|
&enabled, handler);
|
||||||
|
|
||||||
// The string will be something of the form: [/path/to/]browser "%s"
|
if (!CheckHandlerMatchesAppName(handler) || !enabled)
|
||||||
// We want to remove all of the parameters and get just the binary name.
|
return NS_OK; // the handler is disabled or set to another app
|
||||||
|
|
||||||
gint argc;
|
|
||||||
gchar **argv;
|
|
||||||
|
|
||||||
if (g_shell_parse_argv(handler.get(), &argc, &argv, NULL) && argc > 0) {
|
|
||||||
handler.Assign(argv[0]);
|
|
||||||
g_strfreev(argv);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!KeyMatchesAppName(handler.get()) || !enabled)
|
if (giovfs) {
|
||||||
return NS_OK; // the handler is disabled or set to another app
|
handler.Truncate();
|
||||||
|
giovfs->GetAppForURIScheme(nsDependentCString(appProtocols[i].name),
|
||||||
|
getter_AddRefs(gioApp));
|
||||||
|
if (!gioApp)
|
||||||
|
return NS_OK;
|
||||||
|
|
||||||
|
gioApp->GetCommand(handler);
|
||||||
|
|
||||||
|
if (!CheckHandlerMatchesAppName(handler))
|
||||||
|
return NS_OK; // the handler is set to another app
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
*aIsDefaultBrowser = PR_TRUE;
|
*aIsDefaultBrowser = PR_TRUE;
|
||||||
|
@ -214,9 +272,20 @@ nsGNOMEShellService::SetDefaultBrowser(PRBool aClaimAllTypes,
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
nsCOMPtr<nsIGConfService> gconf = do_GetService(NS_GCONFSERVICE_CONTRACTID);
|
nsCOMPtr<nsIGConfService> gconf = do_GetService(NS_GCONFSERVICE_CONTRACTID);
|
||||||
|
nsCOMPtr<nsIGIOService> giovfs = do_GetService(NS_GIOSERVICE_CONTRACTID);
|
||||||
if (gconf) {
|
if (gconf) {
|
||||||
nsCAutoString appKeyValue(mAppPath);
|
nsCAutoString appKeyValue;
|
||||||
appKeyValue.Append(" \"%s\"");
|
if (mAppIsInPath) {
|
||||||
|
// mAppPath is in the users path, so use only the basename as the launcher
|
||||||
|
gchar *tmp = g_path_get_basename(mAppPath.get());
|
||||||
|
appKeyValue = tmp;
|
||||||
|
g_free(tmp);
|
||||||
|
} else {
|
||||||
|
appKeyValue = mAppPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
appKeyValue.AppendLiteral(" %s");
|
||||||
|
|
||||||
for (unsigned int i = 0; i < NS_ARRAY_LENGTH(appProtocols); ++i) {
|
for (unsigned int i = 0; i < NS_ARRAY_LENGTH(appProtocols); ++i) {
|
||||||
if (appProtocols[i].essential || aClaimAllTypes) {
|
if (appProtocols[i].essential || aClaimAllTypes) {
|
||||||
gconf->SetAppForProtocol(nsDependentCString(appProtocols[i].name),
|
gconf->SetAppForProtocol(nsDependentCString(appProtocols[i].name),
|
||||||
|
@ -225,13 +294,8 @@ nsGNOMEShellService::SetDefaultBrowser(PRBool aClaimAllTypes,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// set handler for .html and xhtml files and MIME types:
|
if (giovfs) {
|
||||||
if (aClaimAllTypes) {
|
|
||||||
nsresult rv;
|
nsresult rv;
|
||||||
nsCOMPtr<nsIGIOService> giovfs =
|
|
||||||
do_GetService(NS_GIOSERVICE_CONTRACTID, &rv);
|
|
||||||
NS_ENSURE_SUCCESS(rv, NS_OK);
|
|
||||||
|
|
||||||
nsCOMPtr<nsIStringBundleService> bundleService =
|
nsCOMPtr<nsIStringBundleService> bundleService =
|
||||||
do_GetService(NS_STRINGBUNDLE_CONTRACTID, &rv);
|
do_GetService(NS_STRINGBUNDLE_CONTRACTID, &rv);
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
@ -254,10 +318,20 @@ nsGNOMEShellService::SetDefaultBrowser(PRBool aClaimAllTypes,
|
||||||
getter_AddRefs(appInfo));
|
getter_AddRefs(appInfo));
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
// Add mime types for html, xhtml extension and set app to just created appinfo.
|
// set handler for the protocols
|
||||||
for (unsigned int i = 0; i < NS_ARRAY_LENGTH(appTypes); ++i) {
|
for (unsigned int i = 0; i < NS_ARRAY_LENGTH(appProtocols); ++i) {
|
||||||
appInfo->SetAsDefaultForMimeType(nsDependentCString(appTypes[i].mimeType));
|
if (appProtocols[i].essential || aClaimAllTypes) {
|
||||||
appInfo->SetAsDefaultForFileExtensions(nsDependentCString(appTypes[i].extensions));
|
appInfo->SetAsDefaultForURIScheme(nsDependentCString(appProtocols[i].name));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// set handler for .html and xhtml files and MIME types:
|
||||||
|
if (aClaimAllTypes) {
|
||||||
|
// Add mime types for html, xhtml extension and set app to just created appinfo.
|
||||||
|
for (unsigned int i = 0; i < NS_ARRAY_LENGTH(appTypes); ++i) {
|
||||||
|
appInfo->SetAsDefaultForMimeType(nsDependentCString(appTypes[i].mimeType));
|
||||||
|
appInfo->SetAsDefaultForFileExtensions(nsDependentCString(appTypes[i].extensions));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -367,24 +441,26 @@ nsGNOMEShellService::SetDesktopBackground(nsIDOMElement* aElement,
|
||||||
// if the file was written successfully, set it as the system wallpaper
|
// if the file was written successfully, set it as the system wallpaper
|
||||||
nsCOMPtr<nsIGConfService> gconf = do_GetService(NS_GCONFSERVICE_CONTRACTID);
|
nsCOMPtr<nsIGConfService> gconf = do_GetService(NS_GCONFSERVICE_CONTRACTID);
|
||||||
|
|
||||||
nsCAutoString options;
|
if (gconf) {
|
||||||
if (aPosition == BACKGROUND_TILE)
|
nsCAutoString options;
|
||||||
options.Assign("wallpaper");
|
if (aPosition == BACKGROUND_TILE)
|
||||||
else if (aPosition == BACKGROUND_STRETCH)
|
options.Assign("wallpaper");
|
||||||
options.Assign("stretched");
|
else if (aPosition == BACKGROUND_STRETCH)
|
||||||
else
|
options.Assign("stretched");
|
||||||
options.Assign("centered");
|
else
|
||||||
|
options.Assign("centered");
|
||||||
|
|
||||||
gconf->SetString(NS_LITERAL_CSTRING(kDesktopOptionsKey), options);
|
gconf->SetString(NS_LITERAL_CSTRING(kDesktopOptionsKey), options);
|
||||||
|
|
||||||
// Set the image to an empty string first to force a refresh
|
// Set the image to an empty string first to force a refresh
|
||||||
// (since we could be writing a new image on top of an existing
|
// (since we could be writing a new image on top of an existing
|
||||||
// Firefox_wallpaper.png and nautilus doesn't monitor the file for changes)
|
// Firefox_wallpaper.png and nautilus doesn't monitor the file for changes)
|
||||||
gconf->SetString(NS_LITERAL_CSTRING(kDesktopImageKey),
|
gconf->SetString(NS_LITERAL_CSTRING(kDesktopImageKey),
|
||||||
EmptyCString());
|
EmptyCString());
|
||||||
|
|
||||||
gconf->SetString(NS_LITERAL_CSTRING(kDesktopImageKey), filePath);
|
gconf->SetString(NS_LITERAL_CSTRING(kDesktopImageKey), filePath);
|
||||||
gconf->SetBool(NS_LITERAL_CSTRING(kDesktopDrawBGKey), PR_TRUE);
|
gconf->SetBool(NS_LITERAL_CSTRING(kDesktopDrawBGKey), PR_TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
@ -398,7 +474,9 @@ nsGNOMEShellService::GetDesktopBackgroundColor(PRUint32 *aColor)
|
||||||
nsCOMPtr<nsIGConfService> gconf = do_GetService(NS_GCONFSERVICE_CONTRACTID);
|
nsCOMPtr<nsIGConfService> gconf = do_GetService(NS_GCONFSERVICE_CONTRACTID);
|
||||||
|
|
||||||
nsCAutoString background;
|
nsCAutoString background;
|
||||||
gconf->GetString(NS_LITERAL_CSTRING(kDesktopColorKey), background);
|
if (gconf) {
|
||||||
|
gconf->GetString(NS_LITERAL_CSTRING(kDesktopColorKey), background);
|
||||||
|
}
|
||||||
|
|
||||||
if (background.IsEmpty()) {
|
if (background.IsEmpty()) {
|
||||||
*aColor = 0;
|
*aColor = 0;
|
||||||
|
@ -437,10 +515,12 @@ nsGNOMEShellService::SetDesktopBackgroundColor(PRUint32 aColor)
|
||||||
NS_ASSERTION(aColor <= 0xffffff, "aColor has extra bits");
|
NS_ASSERTION(aColor <= 0xffffff, "aColor has extra bits");
|
||||||
nsCOMPtr<nsIGConfService> gconf = do_GetService(NS_GCONFSERVICE_CONTRACTID);
|
nsCOMPtr<nsIGConfService> gconf = do_GetService(NS_GCONFSERVICE_CONTRACTID);
|
||||||
|
|
||||||
nsCAutoString colorString;
|
if (gconf) {
|
||||||
ColorToCString(aColor, colorString);
|
nsCAutoString colorString;
|
||||||
|
ColorToCString(aColor, colorString);
|
||||||
|
|
||||||
gconf->SetString(NS_LITERAL_CSTRING(kDesktopColorKey), colorString);
|
gconf->SetString(NS_LITERAL_CSTRING(kDesktopColorKey), colorString);
|
||||||
|
}
|
||||||
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
@ -456,7 +536,17 @@ nsGNOMEShellService::OpenApplication(PRInt32 aApplication)
|
||||||
else
|
else
|
||||||
return NS_ERROR_NOT_AVAILABLE;
|
return NS_ERROR_NOT_AVAILABLE;
|
||||||
|
|
||||||
|
nsCOMPtr<nsIGIOService> giovfs = do_GetService(NS_GIOSERVICE_CONTRACTID);
|
||||||
|
if (giovfs) {
|
||||||
|
nsCOMPtr<nsIGIOMimeApp> gioApp;
|
||||||
|
giovfs->GetAppForURIScheme(scheme, getter_AddRefs(gioApp));
|
||||||
|
if (gioApp)
|
||||||
|
return gioApp->Launch(EmptyCString());
|
||||||
|
}
|
||||||
|
|
||||||
nsCOMPtr<nsIGConfService> gconf = do_GetService(NS_GCONFSERVICE_CONTRACTID);
|
nsCOMPtr<nsIGConfService> gconf = do_GetService(NS_GCONFSERVICE_CONTRACTID);
|
||||||
|
if (!gconf)
|
||||||
|
return NS_ERROR_FAILURE;
|
||||||
|
|
||||||
PRBool enabled;
|
PRBool enabled;
|
||||||
nsCAutoString appCommand;
|
nsCAutoString appCommand;
|
||||||
|
|
|
@ -43,7 +43,7 @@
|
||||||
class nsGNOMEShellService : public nsIShellService
|
class nsGNOMEShellService : public nsIShellService
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
nsGNOMEShellService() : mCheckedThisSession(PR_FALSE) { }
|
nsGNOMEShellService() : mCheckedThisSession(PR_FALSE), mAppIsInPath(PR_FALSE) { }
|
||||||
|
|
||||||
NS_DECL_ISUPPORTS
|
NS_DECL_ISUPPORTS
|
||||||
NS_DECL_NSISHELLSERVICE
|
NS_DECL_NSISHELLSERVICE
|
||||||
|
@ -54,10 +54,13 @@ private:
|
||||||
~nsGNOMEShellService() {}
|
~nsGNOMEShellService() {}
|
||||||
|
|
||||||
NS_HIDDEN_(PRBool) KeyMatchesAppName(const char *aKeyValue) const;
|
NS_HIDDEN_(PRBool) KeyMatchesAppName(const char *aKeyValue) const;
|
||||||
|
NS_HIDDEN_(PRBool) CheckHandlerMatchesAppName(const nsACString& handler) const;
|
||||||
|
|
||||||
|
NS_HIDDEN_(PRBool) GetAppPathFromLauncher();
|
||||||
PRPackedBool mCheckedThisSession;
|
PRPackedBool mCheckedThisSession;
|
||||||
PRPackedBool mUseLocaleFilenames;
|
PRPackedBool mUseLocaleFilenames;
|
||||||
nsCString mAppPath;
|
nsCString mAppPath;
|
||||||
|
PRPackedBool mAppIsInPath;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // nsgnomeshellservice_h____
|
#endif // nsgnomeshellservice_h____
|
||||||
|
|
|
@ -634,10 +634,7 @@ user_pref("camino.use_system_proxy_settings", false); // Camino-only, harmless t
|
||||||
pExitCode = ctypes.wintypes.DWORD()
|
pExitCode = ctypes.wintypes.DWORD()
|
||||||
ctypes.windll.kernel32.GetExitCodeProcess(pHandle, ctypes.byref(pExitCode))
|
ctypes.windll.kernel32.GetExitCodeProcess(pHandle, ctypes.byref(pExitCode))
|
||||||
ctypes.windll.kernel32.CloseHandle(pHandle)
|
ctypes.windll.kernel32.CloseHandle(pHandle)
|
||||||
if (pExitCode.value == STILL_ACTIVE):
|
return pExitCode.value == STILL_ACTIVE
|
||||||
return True
|
|
||||||
else:
|
|
||||||
return False
|
|
||||||
|
|
||||||
def killPid(self, pid):
|
def killPid(self, pid):
|
||||||
PROCESS_TERMINATE = 0x0001
|
PROCESS_TERMINATE = 0x0001
|
||||||
|
@ -668,10 +665,7 @@ user_pref("camino.use_system_proxy_settings", false); // Camino-only, harmless t
|
||||||
# Wait on it to see if it's a zombie. This can throw OSError.ECHILD if
|
# Wait on it to see if it's a zombie. This can throw OSError.ECHILD if
|
||||||
# the process terminates before we get to this point.
|
# the process terminates before we get to this point.
|
||||||
wpid, wstatus = os.waitpid(pid, os.WNOHANG)
|
wpid, wstatus = os.waitpid(pid, os.WNOHANG)
|
||||||
if wpid == 0:
|
return wpid == 0
|
||||||
return True
|
|
||||||
|
|
||||||
return False
|
|
||||||
except OSError, err:
|
except OSError, err:
|
||||||
# Catch the errors we might expect from os.kill/os.waitpid,
|
# Catch the errors we might expect from os.kill/os.waitpid,
|
||||||
# and re-raise any others
|
# and re-raise any others
|
||||||
|
@ -918,48 +912,34 @@ user_pref("camino.use_system_proxy_settings", false); // Camino-only, harmless t
|
||||||
return status
|
return status
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Copies an "installed" extension into the extensions directory of the given profile
|
Copies an extension into the extensions directory of the given profile.
|
||||||
extensionSource - the source location of the extension files. This can be either
|
extensionSource - the source location of the extension files. This can be either
|
||||||
a directory or a path to an xpi file.
|
a directory or a path to an xpi file.
|
||||||
profileDir - the profile directory we are copying into. We will create the
|
profileDir - the profile directory we are copying into. We will create the
|
||||||
"extensions" directory there if it doesn't exist
|
"extensions" directory there if it doesn't exist.
|
||||||
extensionID - the id of the extension to be used as the containing directory for the
|
extensionID - the id of the extension to be used as the containing directory for the
|
||||||
extension, i.e.
|
extension, if extensionSource is a directory, i.e.
|
||||||
this is the name of the folder in the <profileDir>/extensions/<extensionID>
|
this is the name of the folder in the <profileDir>/extensions/<extensionID>
|
||||||
"""
|
"""
|
||||||
def installExtension(self, extensionSource, profileDir, extensionID):
|
def installExtension(self, extensionSource, profileDir, extensionID = None):
|
||||||
if (not os.path.exists(extensionSource)):
|
if not os.path.isdir(profileDir):
|
||||||
self.log.info("INFO | automation.py | Cannot install extension no source at: %s", extensionSource)
|
self.log.info("INFO | automation.py | Cannot install extension, invalid profileDir at: %s", profileDir)
|
||||||
return
|
return
|
||||||
|
|
||||||
if (not os.path.exists(profileDir)):
|
|
||||||
self.log.info("INFO | automation.py | Cannot install extension invalid profileDir at: %s", profileDir)
|
|
||||||
return
|
|
||||||
|
|
||||||
# See if we have an XPI or a directory
|
|
||||||
if (os.path.isfile(extensionSource)):
|
|
||||||
tmpd = tempfile.mkdtemp()
|
|
||||||
extrootdir = self.extractZip(extensionSource, tmpd)
|
|
||||||
else:
|
|
||||||
extrootdir = extensionSource
|
|
||||||
extnsdir = os.path.join(profileDir, "extensions")
|
extnsdir = os.path.join(profileDir, "extensions")
|
||||||
extnshome = os.path.join(extnsdir, extensionID)
|
|
||||||
|
|
||||||
# Now we copy the extension source into the extnshome
|
if os.path.isfile(extensionSource):
|
||||||
shutil.copytree(extrootdir, extnshome)
|
# Copy extension xpi directly.
|
||||||
|
# "destination file is created or overwritten".
|
||||||
def extractZip(self, filename, dest):
|
shutil.copy2(extensionSource, extnsdir)
|
||||||
z = zipfile.ZipFile(filename, 'r')
|
elif os.path.isdir(extensionSource):
|
||||||
for n in z.namelist():
|
if extensionID == None:
|
||||||
fullpath = os.path.join(dest, n)
|
self.log.info("INFO | automation.py | Cannot install extension, missing extensionID")
|
||||||
parentdir = os.path.dirname(fullpath)
|
return
|
||||||
if not os.path.isdir(parentdir):
|
|
||||||
os.makedirs(parentdir)
|
|
||||||
if (not n.endswith(os.sep)):
|
|
||||||
data = z.read(n)
|
|
||||||
f = open(fullpath, 'w')
|
|
||||||
f.write(data)
|
|
||||||
f.close()
|
|
||||||
z.close()
|
|
||||||
return dest
|
|
||||||
|
|
||||||
|
# Copy extension tree into its own directory.
|
||||||
|
# "destination directory must not already exist".
|
||||||
|
shutil.copytree(extensionSource, os.path.join(extnsdir, extensionID))
|
||||||
|
else:
|
||||||
|
self.log.info("INFO | automation.py | Cannot install extension, invalid extensionSource at: %s", extensionSource)
|
||||||
|
return
|
||||||
|
|
|
@ -342,6 +342,11 @@ ifdef SIMPLE_PROGRAMS
|
||||||
NO_PROFILE_GUIDED_OPTIMIZE = 1
|
NO_PROFILE_GUIDED_OPTIMIZE = 1
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
# No sense in profiling unit tests
|
||||||
|
ifdef CPP_UNIT_TESTS
|
||||||
|
NO_PROFILE_GUIDED_OPTIMIZE = 1
|
||||||
|
endif
|
||||||
|
|
||||||
# Enable profile-based feedback
|
# Enable profile-based feedback
|
||||||
ifndef NO_PROFILE_GUIDED_OPTIMIZE
|
ifndef NO_PROFILE_GUIDED_OPTIMIZE
|
||||||
ifdef MOZ_PROFILE_GENERATE
|
ifdef MOZ_PROFILE_GENERATE
|
||||||
|
@ -442,11 +447,10 @@ PURIFY = purify $(PURIFYOPTIONS)
|
||||||
QUANTIFY = quantify $(QUANTIFYOPTIONS)
|
QUANTIFY = quantify $(QUANTIFYOPTIONS)
|
||||||
ifdef CROSS_COMPILE
|
ifdef CROSS_COMPILE
|
||||||
XPIDL_COMPILE = $(LIBXUL_DIST)/host/bin/host_xpidl$(HOST_BIN_SUFFIX)
|
XPIDL_COMPILE = $(LIBXUL_DIST)/host/bin/host_xpidl$(HOST_BIN_SUFFIX)
|
||||||
XPIDL_LINK = $(LIBXUL_DIST)/host/bin/host_xpt_link$(HOST_BIN_SUFFIX)
|
|
||||||
else
|
else
|
||||||
XPIDL_COMPILE = $(LIBXUL_DIST)/bin/xpidl$(BIN_SUFFIX)
|
XPIDL_COMPILE = $(LIBXUL_DIST)/bin/xpidl$(BIN_SUFFIX)
|
||||||
XPIDL_LINK = $(LIBXUL_DIST)/bin/xpt_link$(BIN_SUFFIX)
|
|
||||||
endif
|
endif
|
||||||
|
XPIDL_LINK = $(PYTHON) $(SDK_BIN_DIR)/xpt.py link
|
||||||
|
|
||||||
# Java macros
|
# Java macros
|
||||||
JAVA_GEN_DIR = _javagen
|
JAVA_GEN_DIR = _javagen
|
||||||
|
|
|
@ -361,6 +361,11 @@ ifeq (,$(filter-out WINNT WINCE,$(HOST_OS_ARCH)))
|
||||||
HOST_PDBFILE=$(basename $(@F)).pdb
|
HOST_PDBFILE=$(basename $(@F)).pdb
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
# Don't build SIMPLE_PROGRAMS during the MOZ_PROFILE_GENERATE pass
|
||||||
|
ifdef MOZ_PROFILE_GENERATE
|
||||||
|
SIMPLE_PROGRAMS :=
|
||||||
|
endif
|
||||||
|
|
||||||
ifndef TARGETS
|
ifndef TARGETS
|
||||||
TARGETS = $(LIBRARY) $(SHARED_LIBRARY) $(PROGRAM) $(SIMPLE_PROGRAMS) $(HOST_LIBRARY) $(HOST_PROGRAM) $(HOST_SIMPLE_PROGRAMS) $(JAVA_LIBRARY)
|
TARGETS = $(LIBRARY) $(SHARED_LIBRARY) $(PROGRAM) $(SIMPLE_PROGRAMS) $(HOST_LIBRARY) $(HOST_PROGRAM) $(HOST_SIMPLE_PROGRAMS) $(JAVA_LIBRARY)
|
||||||
endif
|
endif
|
||||||
|
@ -1570,7 +1575,7 @@ $(XPIDL_GEN_DIR)/%.xpt: %.idl $(XPIDL_COMPILE) $(XPIDL_GEN_DIR)/.done
|
||||||
|
|
||||||
# no need to link together if XPIDLSRCS contains only XPIDL_MODULE
|
# no need to link together if XPIDLSRCS contains only XPIDL_MODULE
|
||||||
ifneq ($(XPIDL_MODULE).idl,$(strip $(XPIDLSRCS)))
|
ifneq ($(XPIDL_MODULE).idl,$(strip $(XPIDLSRCS)))
|
||||||
$(XPIDL_GEN_DIR)/$(XPIDL_MODULE).xpt: $(patsubst %.idl,$(XPIDL_GEN_DIR)/%.xpt,$(XPIDLSRCS)) $(GLOBAL_DEPS) $(XPIDL_LINK)
|
$(XPIDL_GEN_DIR)/$(XPIDL_MODULE).xpt: $(patsubst %.idl,$(XPIDL_GEN_DIR)/%.xpt,$(XPIDLSRCS)) $(GLOBAL_DEPS)
|
||||||
$(XPIDL_LINK) $(XPIDL_GEN_DIR)/$(XPIDL_MODULE).xpt $(patsubst %.idl,$(XPIDL_GEN_DIR)/%.xpt,$(XPIDLSRCS))
|
$(XPIDL_LINK) $(XPIDL_GEN_DIR)/$(XPIDL_MODULE).xpt $(patsubst %.idl,$(XPIDL_GEN_DIR)/%.xpt,$(XPIDLSRCS))
|
||||||
endif # XPIDL_MODULE.xpt != XPIDLSRCS
|
endif # XPIDL_MODULE.xpt != XPIDLSRCS
|
||||||
|
|
||||||
|
@ -1701,7 +1706,7 @@ endif
|
||||||
|
|
||||||
endif # SDK_LIBRARY
|
endif # SDK_LIBRARY
|
||||||
|
|
||||||
ifneq (,$(SDK_BINARY))
|
ifneq (,$(strip $(SDK_BINARY)))
|
||||||
$(SDK_BIN_DIR)::
|
$(SDK_BIN_DIR)::
|
||||||
$(NSINSTALL) -D $@
|
$(NSINSTALL) -D $@
|
||||||
|
|
||||||
|
|
61
configure.in
61
configure.in
|
@ -3589,36 +3589,39 @@ AC_SUBST(XEXT_LIBS)
|
||||||
AC_SUBST(XT_LIBS)
|
AC_SUBST(XT_LIBS)
|
||||||
AC_SUBST(XSS_LIBS)
|
AC_SUBST(XSS_LIBS)
|
||||||
|
|
||||||
AC_MSG_CHECKING(for ARM SIMD support in compiler)
|
if test "$CPU_ARCH" = "arm"; then
|
||||||
# We try to link so that this also fails when
|
AC_MSG_CHECKING(for ARM SIMD support in compiler)
|
||||||
# building with LTO.
|
# We try to link so that this also fails when
|
||||||
AC_TRY_LINK([],
|
# building with LTO.
|
||||||
[asm("uqadd8 r1, r1, r2");],
|
AC_TRY_LINK([],
|
||||||
result="yes", result="no")
|
[asm("uqadd8 r1, r1, r2");],
|
||||||
AC_MSG_RESULT("$result")
|
result="yes", result="no")
|
||||||
if test "$result" = "yes"; then
|
AC_MSG_RESULT("$result")
|
||||||
AC_DEFINE(HAVE_ARM_SIMD)
|
if test "$result" = "yes"; then
|
||||||
HAVE_ARM_SIMD=1
|
AC_DEFINE(HAVE_ARM_SIMD)
|
||||||
fi
|
HAVE_ARM_SIMD=1
|
||||||
AC_SUBST(HAVE_ARM_SIMD)
|
fi
|
||||||
|
|
||||||
AC_MSG_CHECKING(for ARM NEON support in compiler)
|
AC_MSG_CHECKING(for ARM NEON support in compiler)
|
||||||
_SAVE_CFLAGS="$CFLAGS"
|
_SAVE_CFLAGS="$CFLAGS"
|
||||||
if test "$GNU_CC"; then
|
if test "$GNU_CC"; then
|
||||||
# gcc needs -mfpu=neon to recognize NEON instructions
|
# gcc needs -mfpu=neon to recognize NEON instructions
|
||||||
CFLAGS="$CFLAGS -mfpu=neon -mfloat-abi=softfp"
|
CFLAGS="$CFLAGS -mfpu=neon -mfloat-abi=softfp"
|
||||||
fi
|
fi
|
||||||
# We try to link so that this also fails when
|
# We try to link so that this also fails when
|
||||||
# building with LTO.
|
# building with LTO.
|
||||||
AC_TRY_LINK([],
|
AC_TRY_LINK([],
|
||||||
[asm("vadd.i8 d0, d0, d0");],
|
[asm("vadd.i8 d0, d0, d0");],
|
||||||
result="yes", result="no")
|
result="yes", result="no")
|
||||||
AC_MSG_RESULT("$result")
|
AC_MSG_RESULT("$result")
|
||||||
if test "$result" = "yes"; then
|
if test "$result" = "yes"; then
|
||||||
AC_DEFINE(HAVE_ARM_NEON)
|
AC_DEFINE(HAVE_ARM_NEON)
|
||||||
HAVE_ARM_NEON=1
|
HAVE_ARM_NEON=1
|
||||||
fi
|
fi
|
||||||
CFLAGS="$_SAVE_CFLAGS"
|
CFLAGS="$_SAVE_CFLAGS"
|
||||||
|
fi # CPU_ARCH = arm
|
||||||
|
|
||||||
|
AC_SUBST(HAVE_ARM_SIMD)
|
||||||
AC_SUBST(HAVE_ARM_NEON)
|
AC_SUBST(HAVE_ARM_NEON)
|
||||||
|
|
||||||
dnl ========================================================
|
dnl ========================================================
|
||||||
|
|
|
@ -44,6 +44,7 @@
|
||||||
#include "nsIDOMFileList.h"
|
#include "nsIDOMFileList.h"
|
||||||
#include "nsIDOMFileError.h"
|
#include "nsIDOMFileError.h"
|
||||||
#include "nsIInputStream.h"
|
#include "nsIInputStream.h"
|
||||||
|
#include "nsIJSNativeInitializer.h"
|
||||||
#include "nsCOMArray.h"
|
#include "nsCOMArray.h"
|
||||||
#include "nsCOMPtr.h"
|
#include "nsCOMPtr.h"
|
||||||
#include "mozilla/AutoRestore.h"
|
#include "mozilla/AutoRestore.h"
|
||||||
|
@ -57,13 +58,16 @@ class nsIInputStream;
|
||||||
class nsIClassInfo;
|
class nsIClassInfo;
|
||||||
|
|
||||||
class nsDOMFile : public nsIDOMFile,
|
class nsDOMFile : public nsIDOMFile,
|
||||||
|
public nsIDOMBlob_MOZILLA_2_0_BRANCH,
|
||||||
public nsIXHRSendable,
|
public nsIXHRSendable,
|
||||||
public nsICharsetDetectionObserver
|
public nsICharsetDetectionObserver,
|
||||||
|
public nsIJSNativeInitializer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
NS_DECL_ISUPPORTS
|
NS_DECL_ISUPPORTS
|
||||||
NS_DECL_NSIDOMBLOB
|
NS_DECL_NSIDOMBLOB
|
||||||
NS_DECL_NSIDOMFILE
|
NS_DECL_NSIDOMFILE
|
||||||
|
NS_DECL_NSIDOMBLOB_MOZILLA_2_0_BRANCH
|
||||||
NS_DECL_NSIXHRSENDABLE
|
NS_DECL_NSIXHRSENDABLE
|
||||||
|
|
||||||
nsDOMFile(nsIFile *aFile, const nsAString& aContentType)
|
nsDOMFile(nsIFile *aFile, const nsAString& aContentType)
|
||||||
|
@ -96,6 +100,17 @@ public:
|
||||||
// from nsICharsetDetectionObserver
|
// from nsICharsetDetectionObserver
|
||||||
NS_IMETHOD Notify(const char *aCharset, nsDetectionConfident aConf);
|
NS_IMETHOD Notify(const char *aCharset, nsDetectionConfident aConf);
|
||||||
|
|
||||||
|
// nsIJSNativeInitializer
|
||||||
|
NS_IMETHOD Initialize(nsISupports* aOwner,
|
||||||
|
JSContext* aCx,
|
||||||
|
JSObject* aObj,
|
||||||
|
PRUint32 aArgc,
|
||||||
|
jsval* aArgv);
|
||||||
|
|
||||||
|
// DOMClassInfo constructor (for File("foo"))
|
||||||
|
static nsresult
|
||||||
|
NewFile(nsISupports* *aNewObject);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
nsCOMPtr<nsIFile> mFile;
|
nsCOMPtr<nsIFile> mFile;
|
||||||
|
|
||||||
|
@ -149,8 +164,9 @@ public:
|
||||||
NS_IMETHOD GetSize(PRUint64*);
|
NS_IMETHOD GetSize(PRUint64*);
|
||||||
NS_IMETHOD GetInternalStream(nsIInputStream**);
|
NS_IMETHOD GetInternalStream(nsIInputStream**);
|
||||||
NS_IMETHOD GetMozFullPathInternal(nsAString&);
|
NS_IMETHOD GetMozFullPathInternal(nsAString&);
|
||||||
NS_IMETHOD Slice(PRUint64 aStart, PRUint64 aLength,
|
NS_IMETHOD MozSlice(PRInt64 aStart, PRInt64 aEnd,
|
||||||
const nsAString& aContentType, nsIDOMBlob **aBlob);
|
const nsAString& aContentType, PRUint8 optional_argc,
|
||||||
|
nsIDOMBlob **aBlob);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
friend class DataOwnerAdapter; // Needs to see DataOwner
|
friend class DataOwnerAdapter; // Needs to see DataOwner
|
||||||
|
|
|
@ -49,9 +49,9 @@ interface nsIDOMBlob : nsISupports
|
||||||
readonly attribute unsigned long long size;
|
readonly attribute unsigned long long size;
|
||||||
readonly attribute DOMString type;
|
readonly attribute DOMString type;
|
||||||
|
|
||||||
nsIDOMBlob slice(in unsigned long long start,
|
[noscript] nsIDOMBlob slice(in unsigned long long start,
|
||||||
in unsigned long long length,
|
in unsigned long long length,
|
||||||
[optional] in DOMString contentType);
|
[optional] in DOMString contentType);
|
||||||
|
|
||||||
[noscript] readonly attribute nsIInputStream internalStream;
|
[noscript] readonly attribute nsIInputStream internalStream;
|
||||||
// The caller is responsible for releasing the internalUrl from the
|
// The caller is responsible for releasing the internalUrl from the
|
||||||
|
@ -59,6 +59,14 @@ interface nsIDOMBlob : nsISupports
|
||||||
[noscript] DOMString getInternalUrl(in nsIPrincipal principal);
|
[noscript] DOMString getInternalUrl(in nsIPrincipal principal);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
[scriptable, uuid(cb5b4191-a555-4e57-b8d2-88091184b59f)]
|
||||||
|
interface nsIDOMBlob_MOZILLA_2_0_BRANCH : nsISupports
|
||||||
|
{
|
||||||
|
[optional_argc] nsIDOMBlob mozSlice(in long long start,
|
||||||
|
[optional] in long long end,
|
||||||
|
[optional] in DOMString contentType);
|
||||||
|
};
|
||||||
|
|
||||||
[scriptable, uuid(ae1405b0-e411-481e-9606-b29ec7982687)]
|
[scriptable, uuid(ae1405b0-e411-481e-9606-b29ec7982687)]
|
||||||
interface nsIDOMFile : nsIDOMBlob
|
interface nsIDOMFile : nsIDOMBlob
|
||||||
{
|
{
|
||||||
|
|
|
@ -58,8 +58,6 @@ NS_NewDOMDocumentType(nsIDOMDocumentType** aDocType,
|
||||||
nsNodeInfoManager *aNodeInfoManager,
|
nsNodeInfoManager *aNodeInfoManager,
|
||||||
nsIPrincipal *aPrincipal,
|
nsIPrincipal *aPrincipal,
|
||||||
nsIAtom *aName,
|
nsIAtom *aName,
|
||||||
nsIDOMNamedNodeMap *aEntities,
|
|
||||||
nsIDOMNamedNodeMap *aNotations,
|
|
||||||
const nsAString& aPublicId,
|
const nsAString& aPublicId,
|
||||||
const nsAString& aSystemId,
|
const nsAString& aSystemId,
|
||||||
const nsAString& aInternalSubset)
|
const nsAString& aInternalSubset)
|
||||||
|
@ -69,17 +67,13 @@ NS_NewDOMDocumentType(nsIDOMDocumentType** aDocType,
|
||||||
NS_ENSURE_ARG_POINTER(aDocType);
|
NS_ENSURE_ARG_POINTER(aDocType);
|
||||||
NS_ENSURE_ARG_POINTER(aName);
|
NS_ENSURE_ARG_POINTER(aName);
|
||||||
|
|
||||||
nsresult rv;
|
|
||||||
|
|
||||||
nsRefPtr<nsNodeInfoManager> nimgr;
|
nsRefPtr<nsNodeInfoManager> nimgr;
|
||||||
if (aNodeInfoManager) {
|
if (aNodeInfoManager) {
|
||||||
nimgr = aNodeInfoManager;
|
nimgr = aNodeInfoManager;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
nimgr = new nsNodeInfoManager();
|
nimgr = new nsNodeInfoManager();
|
||||||
NS_ENSURE_TRUE(nimgr, NS_ERROR_OUT_OF_MEMORY);
|
nsresult rv = nimgr->Init(nsnull);
|
||||||
|
|
||||||
rv = nimgr->Init(nsnull);
|
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
nimgr->SetDocumentPrincipal(aPrincipal);
|
nimgr->SetDocumentPrincipal(aPrincipal);
|
||||||
|
@ -90,12 +84,8 @@ NS_NewDOMDocumentType(nsIDOMDocumentType** aDocType,
|
||||||
kNameSpaceID_None);
|
kNameSpaceID_None);
|
||||||
NS_ENSURE_TRUE(ni, NS_ERROR_OUT_OF_MEMORY);
|
NS_ENSURE_TRUE(ni, NS_ERROR_OUT_OF_MEMORY);
|
||||||
|
|
||||||
*aDocType = new nsDOMDocumentType(ni.forget(), aName, aEntities, aNotations,
|
*aDocType = new nsDOMDocumentType(ni.forget(), aName, aPublicId, aSystemId,
|
||||||
aPublicId, aSystemId, aInternalSubset);
|
aInternalSubset);
|
||||||
if (!*aDocType) {
|
|
||||||
return NS_ERROR_OUT_OF_MEMORY;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_ADDREF(*aDocType);
|
NS_ADDREF(*aDocType);
|
||||||
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
|
@ -103,15 +93,11 @@ NS_NewDOMDocumentType(nsIDOMDocumentType** aDocType,
|
||||||
|
|
||||||
nsDOMDocumentType::nsDOMDocumentType(already_AddRefed<nsINodeInfo> aNodeInfo,
|
nsDOMDocumentType::nsDOMDocumentType(already_AddRefed<nsINodeInfo> aNodeInfo,
|
||||||
nsIAtom *aName,
|
nsIAtom *aName,
|
||||||
nsIDOMNamedNodeMap *aEntities,
|
|
||||||
nsIDOMNamedNodeMap *aNotations,
|
|
||||||
const nsAString& aPublicId,
|
const nsAString& aPublicId,
|
||||||
const nsAString& aSystemId,
|
const nsAString& aSystemId,
|
||||||
const nsAString& aInternalSubset) :
|
const nsAString& aInternalSubset) :
|
||||||
nsGenericDOMDataNode(aNodeInfo),
|
nsGenericDOMDataNode(aNodeInfo),
|
||||||
mName(aName),
|
mName(aName),
|
||||||
mEntities(aEntities),
|
|
||||||
mNotations(aNotations),
|
|
||||||
mPublicId(aPublicId),
|
mPublicId(aPublicId),
|
||||||
mSystemId(aSystemId),
|
mSystemId(aSystemId),
|
||||||
mInternalSubset(aInternalSubset)
|
mInternalSubset(aInternalSubset)
|
||||||
|
@ -158,30 +144,6 @@ nsDOMDocumentType::GetName(nsAString& aName)
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
nsDOMDocumentType::GetEntities(nsIDOMNamedNodeMap** aEntities)
|
|
||||||
{
|
|
||||||
NS_ENSURE_ARG_POINTER(aEntities);
|
|
||||||
|
|
||||||
*aEntities = mEntities;
|
|
||||||
|
|
||||||
NS_IF_ADDREF(*aEntities);
|
|
||||||
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
nsDOMDocumentType::GetNotations(nsIDOMNamedNodeMap** aNotations)
|
|
||||||
{
|
|
||||||
NS_ENSURE_ARG_POINTER(aNotations);
|
|
||||||
|
|
||||||
*aNotations = mNotations;
|
|
||||||
|
|
||||||
NS_IF_ADDREF(*aNotations);
|
|
||||||
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsDOMDocumentType::GetPublicId(nsAString& aPublicId)
|
nsDOMDocumentType::GetPublicId(nsAString& aPublicId)
|
||||||
{
|
{
|
||||||
|
@ -238,8 +200,8 @@ nsGenericDOMDataNode*
|
||||||
nsDOMDocumentType::CloneDataNode(nsINodeInfo *aNodeInfo, PRBool aCloneText) const
|
nsDOMDocumentType::CloneDataNode(nsINodeInfo *aNodeInfo, PRBool aCloneText) const
|
||||||
{
|
{
|
||||||
nsCOMPtr<nsINodeInfo> ni = aNodeInfo;
|
nsCOMPtr<nsINodeInfo> ni = aNodeInfo;
|
||||||
return new nsDOMDocumentType(ni.forget(), mName, mEntities, mNotations,
|
return new nsDOMDocumentType(ni.forget(), mName, mPublicId, mSystemId,
|
||||||
mPublicId, mSystemId, mInternalSubset);
|
mInternalSubset);
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
|
|
|
@ -39,8 +39,8 @@
|
||||||
* Implementation of DOM Core's nsIDOMDocumentType node.
|
* Implementation of DOM Core's nsIDOMDocumentType node.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef nsDOMDocumentType_h___
|
#ifndef nsDOMDocumentType_h
|
||||||
#define nsDOMDocumentType_h___
|
#define nsDOMDocumentType_h
|
||||||
|
|
||||||
#include "nsCOMPtr.h"
|
#include "nsCOMPtr.h"
|
||||||
#include "nsIDOMDocumentType.h"
|
#include "nsIDOMDocumentType.h"
|
||||||
|
@ -59,8 +59,6 @@ class nsDOMDocumentType : public nsGenericDOMDataNode,
|
||||||
public:
|
public:
|
||||||
nsDOMDocumentType(already_AddRefed<nsINodeInfo> aNodeInfo,
|
nsDOMDocumentType(already_AddRefed<nsINodeInfo> aNodeInfo,
|
||||||
nsIAtom *aName,
|
nsIAtom *aName,
|
||||||
nsIDOMNamedNodeMap *aEntities,
|
|
||||||
nsIDOMNamedNodeMap *aNotations,
|
|
||||||
const nsAString& aPublicId,
|
const nsAString& aPublicId,
|
||||||
const nsAString& aSystemId,
|
const nsAString& aSystemId,
|
||||||
const nsAString& aInternalSubset);
|
const nsAString& aInternalSubset);
|
||||||
|
@ -86,8 +84,6 @@ public:
|
||||||
virtual nsXPCClassInfo* GetClassInfo();
|
virtual nsXPCClassInfo* GetClassInfo();
|
||||||
protected:
|
protected:
|
||||||
nsCOMPtr<nsIAtom> mName;
|
nsCOMPtr<nsIAtom> mName;
|
||||||
nsCOMPtr<nsIDOMNamedNodeMap> mEntities;
|
|
||||||
nsCOMPtr<nsIDOMNamedNodeMap> mNotations;
|
|
||||||
nsString mPublicId;
|
nsString mPublicId;
|
||||||
nsString mSystemId;
|
nsString mSystemId;
|
||||||
nsString mInternalSubset;
|
nsString mInternalSubset;
|
||||||
|
@ -98,10 +94,8 @@ NS_NewDOMDocumentType(nsIDOMDocumentType** aDocType,
|
||||||
nsNodeInfoManager *aOwnerDoc,
|
nsNodeInfoManager *aOwnerDoc,
|
||||||
nsIPrincipal *aPrincipal,
|
nsIPrincipal *aPrincipal,
|
||||||
nsIAtom *aName,
|
nsIAtom *aName,
|
||||||
nsIDOMNamedNodeMap *aEntities,
|
|
||||||
nsIDOMNamedNodeMap *aNotations,
|
|
||||||
const nsAString& aPublicId,
|
const nsAString& aPublicId,
|
||||||
const nsAString& aSystemId,
|
const nsAString& aSystemId,
|
||||||
const nsAString& aInternalSubset);
|
const nsAString& aInternalSubset);
|
||||||
|
|
||||||
#endif // nsDOMDocument_h___
|
#endif // nsDOMDocumentType_h
|
||||||
|
|
|
@ -64,6 +64,7 @@
|
||||||
#include "nsFileDataProtocolHandler.h"
|
#include "nsFileDataProtocolHandler.h"
|
||||||
#include "nsStringStream.h"
|
#include "nsStringStream.h"
|
||||||
#include "CheckedInt.h"
|
#include "CheckedInt.h"
|
||||||
|
#include "nsJSUtils.h"
|
||||||
|
|
||||||
#include "plbase64.h"
|
#include "plbase64.h"
|
||||||
#include "prmem.h"
|
#include "prmem.h"
|
||||||
|
@ -139,9 +140,11 @@ DOMCI_DATA(Blob, nsDOMFile)
|
||||||
NS_INTERFACE_MAP_BEGIN(nsDOMFile)
|
NS_INTERFACE_MAP_BEGIN(nsDOMFile)
|
||||||
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMFile)
|
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMFile)
|
||||||
NS_INTERFACE_MAP_ENTRY(nsIDOMBlob)
|
NS_INTERFACE_MAP_ENTRY(nsIDOMBlob)
|
||||||
|
NS_INTERFACE_MAP_ENTRY(nsIDOMBlob_MOZILLA_2_0_BRANCH)
|
||||||
NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIDOMFile, mIsFullFile)
|
NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIDOMFile, mIsFullFile)
|
||||||
NS_INTERFACE_MAP_ENTRY(nsIXHRSendable)
|
NS_INTERFACE_MAP_ENTRY(nsIXHRSendable)
|
||||||
NS_INTERFACE_MAP_ENTRY(nsICharsetDetectionObserver)
|
NS_INTERFACE_MAP_ENTRY(nsICharsetDetectionObserver)
|
||||||
|
NS_INTERFACE_MAP_ENTRY(nsIJSNativeInitializer)
|
||||||
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO_CONDITIONAL(File, mIsFullFile)
|
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO_CONDITIONAL(File, mIsFullFile)
|
||||||
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO_CONDITIONAL(Blob, !mIsFullFile)
|
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO_CONDITIONAL(Blob, !mIsFullFile)
|
||||||
NS_INTERFACE_MAP_END
|
NS_INTERFACE_MAP_END
|
||||||
|
@ -163,6 +166,14 @@ DOMFileResult(nsresult rv)
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* static */ nsresult
|
||||||
|
nsDOMFile::NewFile(nsISupports* *aNewObject)
|
||||||
|
{
|
||||||
|
nsCOMPtr<nsISupports> file = do_QueryObject(new nsDOMFile(nsnull));
|
||||||
|
file.forget(aNewObject);
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsDOMFile::GetFileName(nsAString &aFileName)
|
nsDOMFile::GetFileName(nsAString &aFileName)
|
||||||
{
|
{
|
||||||
|
@ -245,23 +256,54 @@ nsDOMFile::GetType(nsAString &aType)
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Makes sure that aStart and aStart + aLength is less then or equal to aSize
|
// Makes sure that aStart and aEnd is less then or equal to aSize and greater
|
||||||
|
// than 0
|
||||||
void
|
void
|
||||||
ClampToSize(PRUint64 aSize, PRUint64& aStart, PRUint64& aLength)
|
ParseSize(PRInt64 aSize, PRInt64& aStart, PRInt64& aEnd)
|
||||||
{
|
{
|
||||||
if (aStart > aSize) {
|
CheckedInt64 newStartOffset = aStart;
|
||||||
aStart = aLength = 0;
|
if (aStart < -aSize) {
|
||||||
|
newStartOffset = 0;
|
||||||
}
|
}
|
||||||
CheckedUint64 endOffset = aStart;
|
else if (aStart < 0) {
|
||||||
endOffset += aLength;
|
newStartOffset += aSize;
|
||||||
if (!endOffset.valid() || endOffset.value() > aSize) {
|
}
|
||||||
aLength = aSize - aStart;
|
else if (aStart > aSize) {
|
||||||
|
newStartOffset = aSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
CheckedInt64 newEndOffset = aEnd;
|
||||||
|
if (aEnd < -aSize) {
|
||||||
|
newEndOffset = 0;
|
||||||
|
}
|
||||||
|
else if (aEnd < 0) {
|
||||||
|
newEndOffset += aSize;
|
||||||
|
}
|
||||||
|
else if (aEnd > aSize) {
|
||||||
|
newEndOffset = aSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!newStartOffset.valid() || !newEndOffset.valid() ||
|
||||||
|
newStartOffset.value() >= newEndOffset.value()) {
|
||||||
|
aStart = aEnd = 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
aStart = newStartOffset.value();
|
||||||
|
aEnd = newEndOffset.value();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsDOMFile::Slice(PRUint64 aStart, PRUint64 aLength,
|
nsDOMFile::Slice(PRUint64 aStart, PRUint64 aLength,
|
||||||
const nsAString& aContentType, nsIDOMBlob **aBlob)
|
const nsAString& aContentType, nsIDOMBlob **aBlob)
|
||||||
|
{
|
||||||
|
return MozSlice(aStart, aStart + aLength, aContentType, 2, aBlob);
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
nsDOMFile::MozSlice(PRInt64 aStart, PRInt64 aEnd,
|
||||||
|
const nsAString& aContentType, PRUint8 optional_argc,
|
||||||
|
nsIDOMBlob **aBlob)
|
||||||
{
|
{
|
||||||
*aBlob = nsnull;
|
*aBlob = nsnull;
|
||||||
|
|
||||||
|
@ -269,10 +311,15 @@ nsDOMFile::Slice(PRUint64 aStart, PRUint64 aLength,
|
||||||
PRUint64 thisLength;
|
PRUint64 thisLength;
|
||||||
nsresult rv = GetSize(&thisLength);
|
nsresult rv = GetSize(&thisLength);
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
ClampToSize(thisLength, aStart, aLength);
|
|
||||||
|
if (!optional_argc) {
|
||||||
|
aEnd = (PRInt64)thisLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
ParseSize((PRInt64)thisLength, aStart, aEnd);
|
||||||
|
|
||||||
// Create the new file
|
// Create the new file
|
||||||
NS_ADDREF(*aBlob = new nsDOMFile(this, aStart, aLength, aContentType));
|
NS_ADDREF(*aBlob = new nsDOMFile(this, aStart, aEnd - aStart, aContentType));
|
||||||
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
@ -574,6 +621,48 @@ nsDOMFile::Notify(const char* aCharset, nsDetectionConfident aConf)
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
nsDOMFile::Initialize(nsISupports* aOwner,
|
||||||
|
JSContext* aCx,
|
||||||
|
JSObject* aObj,
|
||||||
|
PRUint32 aArgc,
|
||||||
|
jsval* aArgv)
|
||||||
|
{
|
||||||
|
if (!nsContentUtils::IsCallerChrome()) {
|
||||||
|
return NS_ERROR_DOM_SECURITY_ERR; // Real short trip
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_ENSURE_TRUE(aArgc > 0, NS_ERROR_UNEXPECTED);
|
||||||
|
|
||||||
|
// We expect to get a path to represent as a File object
|
||||||
|
if (!JSVAL_IS_STRING(aArgv[0]))
|
||||||
|
return NS_ERROR_UNEXPECTED;
|
||||||
|
|
||||||
|
JSString* str = JS_ValueToString(aCx, aArgv[0]);
|
||||||
|
NS_ENSURE_TRUE(str, NS_ERROR_XPC_BAD_CONVERT_JS);
|
||||||
|
|
||||||
|
nsDependentJSString xpcomStr;
|
||||||
|
if (!xpcomStr.init(aCx, str)) {
|
||||||
|
return NS_ERROR_XPC_BAD_CONVERT_JS;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsCOMPtr<nsILocalFile> localFile;
|
||||||
|
nsresult rv = NS_NewLocalFile(xpcomStr,
|
||||||
|
PR_FALSE, getter_AddRefs(localFile));
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
|
nsCOMPtr<nsIFile> file = do_QueryInterface(localFile, &rv);
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
|
PRBool exists;
|
||||||
|
rv = file->Exists(&exists);
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
NS_ENSURE_TRUE(exists, NS_ERROR_FILE_NOT_FOUND);
|
||||||
|
|
||||||
|
mFile = file;
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
nsDOMFile::ConvertStream(nsIInputStream *aStream,
|
nsDOMFile::ConvertStream(nsIInputStream *aStream,
|
||||||
const char *aCharset,
|
const char *aCharset,
|
||||||
|
@ -627,16 +716,22 @@ nsDOMMemoryFile::GetSize(PRUint64 *aFileSize)
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsDOMMemoryFile::Slice(PRUint64 aStart, PRUint64 aLength,
|
nsDOMMemoryFile::MozSlice(PRInt64 aStart, PRInt64 aEnd,
|
||||||
const nsAString& aContentType, nsIDOMBlob **aBlob)
|
const nsAString& aContentType, PRUint8 optional_argc,
|
||||||
|
nsIDOMBlob **aBlob)
|
||||||
{
|
{
|
||||||
*aBlob = nsnull;
|
*aBlob = nsnull;
|
||||||
|
|
||||||
|
if (!optional_argc) {
|
||||||
|
aEnd = (PRInt64)mLength;
|
||||||
|
}
|
||||||
|
|
||||||
// Truncate aLength and aStart so that we stay within this file.
|
// Truncate aLength and aStart so that we stay within this file.
|
||||||
ClampToSize(mLength, aStart, aLength);
|
ParseSize((PRInt64)mLength, aStart, aEnd);
|
||||||
|
|
||||||
// Create the new file
|
// Create the new file
|
||||||
NS_ADDREF(*aBlob = new nsDOMMemoryFile(this, aStart, aLength, aContentType));
|
NS_ADDREF(*aBlob = new nsDOMMemoryFile(this, aStart, aEnd - aStart,
|
||||||
|
aContentType));
|
||||||
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1441,8 +1441,8 @@ nsDOMImplementation::CreateDocumentType(const nsAString& aQualifiedName,
|
||||||
// Indicate that there is no internal subset (not just an empty one)
|
// Indicate that there is no internal subset (not just an empty one)
|
||||||
nsAutoString voidString;
|
nsAutoString voidString;
|
||||||
voidString.SetIsVoid(PR_TRUE);
|
voidString.SetIsVoid(PR_TRUE);
|
||||||
return NS_NewDOMDocumentType(aReturn, nsnull, mPrincipal, name, nsnull,
|
return NS_NewDOMDocumentType(aReturn, nsnull, mPrincipal, name, aPublicId,
|
||||||
nsnull, aPublicId, aSystemId, voidString);
|
aSystemId, voidString);
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
|
@ -1507,8 +1507,6 @@ nsDOMImplementation::CreateHTMLDocument(const nsAString& aTitle,
|
||||||
NULL, // aNodeInfoManager
|
NULL, // aNodeInfoManager
|
||||||
mPrincipal, // aPrincipal
|
mPrincipal, // aPrincipal
|
||||||
nsGkAtoms::html, // aName
|
nsGkAtoms::html, // aName
|
||||||
NULL, // aEntities
|
|
||||||
NULL, // aNotations
|
|
||||||
EmptyString(), // aPublicId
|
EmptyString(), // aPublicId
|
||||||
EmptyString(), // aSystemId
|
EmptyString(), // aSystemId
|
||||||
voidString); // aInternalSubset
|
voidString); // aInternalSubset
|
||||||
|
@ -8285,7 +8283,10 @@ nsDocument::RemoveImage(imgIRequest* aImage)
|
||||||
|
|
||||||
// Get the old count. It should exist and be > 0.
|
// Get the old count. It should exist and be > 0.
|
||||||
PRUint32 count;
|
PRUint32 count;
|
||||||
PRBool found = mImageTracker.Get(aImage, &count);
|
#ifdef DEBUG
|
||||||
|
PRBool found =
|
||||||
|
#endif
|
||||||
|
mImageTracker.Get(aImage, &count);
|
||||||
NS_ABORT_IF_FALSE(found, "Removing image that wasn't in the tracker!");
|
NS_ABORT_IF_FALSE(found, "Removing image that wasn't in the tracker!");
|
||||||
NS_ABORT_IF_FALSE(count > 0, "Entry in the cache tracker with count 0!");
|
NS_ABORT_IF_FALSE(count > 0, "Entry in the cache tracker with count 0!");
|
||||||
|
|
||||||
|
|
|
@ -4582,7 +4582,9 @@ nsGenericElement::MaybeCheckSameAttrVal(PRInt32 aNamespaceID, nsIAtom* aName,
|
||||||
// Need to store the old value
|
// Need to store the old value
|
||||||
info.mValue->ToString(*aOldValue);
|
info.mValue->ToString(*aOldValue);
|
||||||
valueMatches = aValue.Equals(*aOldValue);
|
valueMatches = aValue.Equals(*aOldValue);
|
||||||
} else if (aNotify) {
|
} else {
|
||||||
|
NS_ABORT_IF_FALSE(aNotify,
|
||||||
|
"Either hasListeners or aNotify should be true.");
|
||||||
valueMatches = info.mValue->Equals(aValue, eCaseMatters);
|
valueMatches = info.mValue->Equals(aValue, eCaseMatters);
|
||||||
}
|
}
|
||||||
if (valueMatches && aPrefix == info.mName->GetPrefix()) {
|
if (valueMatches && aPrefix == info.mName->GetPrefix()) {
|
||||||
|
|
|
@ -129,7 +129,10 @@ nsInProcessTabChildGlobal::~nsInProcessTabChildGlobal()
|
||||||
nsresult
|
nsresult
|
||||||
nsInProcessTabChildGlobal::Init()
|
nsInProcessTabChildGlobal::Init()
|
||||||
{
|
{
|
||||||
nsresult rv = InitTabChildGlobal();
|
#ifdef DEBUG
|
||||||
|
nsresult rv =
|
||||||
|
#endif
|
||||||
|
InitTabChildGlobal();
|
||||||
NS_WARN_IF_FALSE(NS_SUCCEEDED(rv),
|
NS_WARN_IF_FALSE(NS_SUCCEEDED(rv),
|
||||||
"Couldn't initialize nsInProcessTabChildGlobal");
|
"Couldn't initialize nsInProcessTabChildGlobal");
|
||||||
mMessageManager = new nsFrameMessageManager(PR_FALSE,
|
mMessageManager = new nsFrameMessageManager(PR_FALSE,
|
||||||
|
|
|
@ -138,8 +138,6 @@ protected:
|
||||||
nsNodeInfoManager *,
|
nsNodeInfoManager *,
|
||||||
nsIPrincipal *,
|
nsIPrincipal *,
|
||||||
nsIAtom *,
|
nsIAtom *,
|
||||||
nsIDOMNamedNodeMap *,
|
|
||||||
nsIDOMNamedNodeMap *,
|
|
||||||
const nsAString& ,
|
const nsAString& ,
|
||||||
const nsAString& ,
|
const nsAString& ,
|
||||||
const nsAString& );
|
const nsAString& );
|
||||||
|
|
|
@ -1077,6 +1077,10 @@ nsObjectLoadingContent::ObjectState() const
|
||||||
case ePluginUnsupported:
|
case ePluginUnsupported:
|
||||||
state |= NS_EVENT_STATE_TYPE_UNSUPPORTED;
|
state |= NS_EVENT_STATE_TYPE_UNSUPPORTED;
|
||||||
break;
|
break;
|
||||||
|
case ePluginOutdated:
|
||||||
|
case ePluginOtherState:
|
||||||
|
// Do nothing, but avoid a compile warning
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
return state;
|
return state;
|
||||||
};
|
};
|
||||||
|
|
|
@ -897,6 +897,9 @@ IMPL_RUNNABLE_ON_MAIN_THREAD_METHOD_BEGIN(DoInitialRequest)
|
||||||
buf->AppendLiteral("\r\n");
|
buf->AppendLiteral("\r\n");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case numberRequestHeaders:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
headersToSend.RemoveElementAt(headerPosToSendNow);
|
headersToSend.RemoveElementAt(headerPosToSendNow);
|
||||||
|
@ -1733,10 +1736,9 @@ IMPL_RUNNABLE_ON_MAIN_THREAD_METHOD_BEGIN(AddWSConnecting)
|
||||||
NS_ASSERTION(index == nsTArray<PRNetAddr>::NoIndex,
|
NS_ASSERTION(index == nsTArray<PRNetAddr>::NoIndex,
|
||||||
"The ws connection shouldn't be already added in the "
|
"The ws connection shouldn't be already added in the "
|
||||||
"serialization list.");
|
"serialization list.");
|
||||||
|
bool inserted = !!
|
||||||
#endif
|
#endif
|
||||||
|
sWSsConnecting->InsertElementSorted(this, nsWSNetAddressComparator());
|
||||||
PRBool inserted =
|
|
||||||
!!(sWSsConnecting->InsertElementSorted(this, nsWSNetAddressComparator()));
|
|
||||||
NS_ASSERTION(inserted, "Couldn't insert the ws connection into the "
|
NS_ASSERTION(inserted, "Couldn't insert the ws connection into the "
|
||||||
"serialization list.");
|
"serialization list.");
|
||||||
}
|
}
|
||||||
|
|
|
@ -1319,7 +1319,8 @@ void
|
||||||
nsXMLContentSerializer::IncrIndentation(nsIAtom* aName)
|
nsXMLContentSerializer::IncrIndentation(nsIAtom* aName)
|
||||||
{
|
{
|
||||||
// we want to keep the source readable
|
// we want to keep the source readable
|
||||||
if(mDoWrap && mIndent.Length() >= mMaxColumn - MIN_INDENTED_LINE_LENGTH) {
|
if (mDoWrap &&
|
||||||
|
mIndent.Length() >= PRUint32(mMaxColumn) - MIN_INDENTED_LINE_LENGTH) {
|
||||||
++mIndentOverflow;
|
++mIndentOverflow;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -1658,7 +1659,7 @@ nsXMLContentSerializer::AppendToStringFormatedWrapped(const nsASingleFragmentStr
|
||||||
PRBool mayIgnoreStartOfLineWhitespaceSequence =
|
PRBool mayIgnoreStartOfLineWhitespaceSequence =
|
||||||
(!mColPos || (mIsIndentationAddedOnCurrentLine &&
|
(!mColPos || (mIsIndentationAddedOnCurrentLine &&
|
||||||
sequenceStartAfterAWhitespace &&
|
sequenceStartAfterAWhitespace &&
|
||||||
mColPos == mIndent.Length()));
|
PRUint32(mColPos) == mIndent.Length()));
|
||||||
|
|
||||||
while (pos < end) {
|
while (pos < end) {
|
||||||
sequenceStart = pos;
|
sequenceStart = pos;
|
||||||
|
|
|
@ -60,6 +60,8 @@ _CHROME_FILES = \
|
||||||
test_bug616841.xul \
|
test_bug616841.xul \
|
||||||
file_bug616841.xul \
|
file_bug616841.xul \
|
||||||
test_bug635835.xul \
|
test_bug635835.xul \
|
||||||
|
test_fileconstructor.xul \
|
||||||
|
fileconstructor_file.png \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
||||||
libs:: $(_TEST_FILES)
|
libs:: $(_TEST_FILES)
|
||||||
|
|
Двоичный файл не отображается.
После Ширина: | Высота: | Размер: 95 B |
|
@ -0,0 +1,70 @@
|
||||||
|
<?xml version="1.0"?>
|
||||||
|
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
|
||||||
|
<?xml-stylesheet
|
||||||
|
href="chrome://mochikit/content/tests/SimpleTest/test.css"
|
||||||
|
type="text/css"?>
|
||||||
|
<!--
|
||||||
|
https://bugzilla.mozilla.org/show_bug.cgi?id=607114.xul
|
||||||
|
-->
|
||||||
|
<window title="Mozilla Bug 607114"
|
||||||
|
xmlns:html="http://www.w3.org/1999/xhtml"
|
||||||
|
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||||
|
|
||||||
|
<title>Test for Bug 607114</title>
|
||||||
|
<script type="application/javascript"
|
||||||
|
src="chrome://mochikit/content/MochiKit/packed.js"></script>
|
||||||
|
<script type="application/javascript"
|
||||||
|
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||||
|
|
||||||
|
<body xmlns="http://www.w3.org/1999/xhtml">
|
||||||
|
<a target="_blank"
|
||||||
|
href="https://bugzilla.mozilla.org/show_bug.cgi?id=607114">
|
||||||
|
Mozilla Bug 607114</a>
|
||||||
|
<p id="display"></p>
|
||||||
|
<div id="content" style="display: none">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<pre id="test">
|
||||||
|
</pre>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
<script class="testbody" type="application/javascript">
|
||||||
|
<![CDATA[
|
||||||
|
|
||||||
|
/** Test for Bug 607114 **/
|
||||||
|
|
||||||
|
var file = Components.classes["@mozilla.org/file/directory_service;1"]
|
||||||
|
.getService(Components.interfaces.nsIProperties)
|
||||||
|
.get("CurWorkD", Components.interfaces.nsIFile);
|
||||||
|
|
||||||
|
// man I wish this were simpler ...
|
||||||
|
file.append("chrome");
|
||||||
|
file.append("content");
|
||||||
|
file.append("base");
|
||||||
|
file.append("test");
|
||||||
|
file.append("chrome");
|
||||||
|
file.append("fileconstructor_file.png");
|
||||||
|
|
||||||
|
var domfile = new File(file.path);
|
||||||
|
ok(domfile instanceof File, "File() should return a File");
|
||||||
|
is(domfile.type, "image/png", "File should be a PNG");
|
||||||
|
is(domfile.size, 95, "File has size 95 (and more importantly we can read it)");
|
||||||
|
|
||||||
|
try {
|
||||||
|
var boomfile = new File();
|
||||||
|
ok(false, "This should never be reached!");
|
||||||
|
} catch (e) {
|
||||||
|
ok(true, "Botched file constructor attempts throw and do not crash.");
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
var nonexistentfile = new File("i/sure/hope/this/does/not/exist/anywhere.txt");
|
||||||
|
ok(false, "This should never be reached!");
|
||||||
|
} catch (e) {
|
||||||
|
ok(true, "Attempt to construct a non-existent file should fail.")
|
||||||
|
}
|
||||||
|
|
||||||
|
]]>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
</window>
|
|
@ -20,6 +20,15 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=414796
|
||||||
|
|
||||||
<pre id="test">
|
<pre id="test">
|
||||||
<script class="testbody" type="text/javascript">
|
<script class="testbody" type="text/javascript">
|
||||||
|
|
||||||
|
// File constructors should not work from non-chrome code
|
||||||
|
try {
|
||||||
|
var file = File("/etc/passwd");
|
||||||
|
ok(false, "Did not throw on unprivileged attempt to construct a File");
|
||||||
|
} catch (e) {
|
||||||
|
ok(true, "Threw on an unprivileged attempt to construct a File");
|
||||||
|
}
|
||||||
|
|
||||||
const minFileSize = 20000;
|
const minFileSize = 20000;
|
||||||
var fileNum = 1;
|
var fileNum = 1;
|
||||||
var testRanCounter = 0;
|
var testRanCounter = 0;
|
||||||
|
|
|
@ -69,104 +69,83 @@ ok(size > 65536, "test data sufficiently large");
|
||||||
|
|
||||||
|
|
||||||
// Test that basic properties work
|
// Test that basic properties work
|
||||||
function testBasics(file, size, type) {
|
function testFile(file, size, type, contents, fileType) {
|
||||||
is(file.type, type, "[B0] mozGetAsFile type");
|
is(file.type, type, fileType + " file is correct type");
|
||||||
is(file.size, size, "[B0] file is correct size");
|
is(file.size, size, fileType + " file is correct size");
|
||||||
ok(file instanceof File, "[B0] file is a File");
|
ok(file instanceof File, fileType + " file is a File");
|
||||||
ok(file instanceof Blob, "[B0] file is also a Blob");
|
ok(file instanceof Blob, fileType + " file is also a Blob");
|
||||||
|
|
||||||
var slice = file.slice(0, size);
|
var slice = file.mozSlice(0, size);
|
||||||
is(slice.type, "", "[B1] full-size type");
|
ok(slice instanceof Blob, fileType + " fullsize slice is a Blob");
|
||||||
is(slice.size, size, "[B1] full-size size");
|
ok(!(slice instanceof File), fileType + " fullsize slice is not a File");
|
||||||
ok(slice instanceof Blob, "[B1] slice is a Blob");
|
|
||||||
ok(!(slice instanceof File), "[B1] slice is not a File");
|
|
||||||
|
|
||||||
slice = file.slice(0, 1234);
|
slice = file.mozSlice(0, 1234);
|
||||||
is(slice.type, "", "[B2] sized type");
|
ok(slice instanceof Blob, fileType + " sized slice is a Blob");
|
||||||
is(slice.size, 1234, "[B2] sized size");
|
ok(!(slice instanceof File), fileType + " sized slice is not a File");
|
||||||
ok(slice instanceof Blob, "[B2] slice is a Blob");
|
|
||||||
ok(!(slice instanceof File), "[B2] slice is not a File");
|
|
||||||
|
|
||||||
slice = file.slice(size-500, 1000);
|
slice = file.mozSlice(0, size, "foo/bar");
|
||||||
is(slice.type, "", "[B3] end-sized type");
|
is(slice.type, "foo/bar", fileType + " fullsize slice foo/bar type");
|
||||||
is(slice.size, 500, "[B3] end-sized size");
|
|
||||||
|
|
||||||
slice = file.slice(size+500, 1000);
|
slice = file.mozSlice(0, 5432, "foo/bar");
|
||||||
is(slice.type, "", "[B4] sized type");
|
is(slice.type, "foo/bar", fileType + " sized slice foo/bar type");
|
||||||
is(slice.size, 0, "[B4] sized size");
|
|
||||||
|
|
||||||
slice = file.slice(0, 0);
|
is(slice.mozSlice(0, 10).type, "", fileType + " slice-slice type");
|
||||||
is(slice.type, "", "[B5] sized type");
|
is(slice.mozSlice(0, 10).size, 10, fileType + " slice-slice size");
|
||||||
is(slice.size, 0, "[B5] sized size");
|
is(slice.mozSlice(0, 10, "hello/world").type, "hello/world", fileType + " slice-slice hello/world type");
|
||||||
|
is(slice.mozSlice(0, 10, "hello/world").size, 10, fileType + " slice-slice hello/world size");
|
||||||
|
|
||||||
slice = file.slice(1000, 0);
|
var indexes = [[0, size, size],
|
||||||
is(slice.type, "", "[B6] sized type");
|
[0, 1234, 1234],
|
||||||
is(slice.size, 0, "[B6] sized size");
|
[size-500, size, 500],
|
||||||
|
[size-500, size+500, 500],
|
||||||
|
[size+500, size+1500, 0],
|
||||||
|
[0, 0, 0],
|
||||||
|
[1000, 1000, 0],
|
||||||
|
[size, size, 0],
|
||||||
|
[0, undefined, size],
|
||||||
|
[100, undefined, size-100],
|
||||||
|
[-100, undefined, 100],
|
||||||
|
[100, -100, size-200],
|
||||||
|
[-size-100, undefined, size],
|
||||||
|
[-2*size-100, 500, 500],
|
||||||
|
[0, -size-100, 0],
|
||||||
|
[100, -size-100, 0],
|
||||||
|
[50, -size+100, 50],
|
||||||
|
[0, 33000, 33000],
|
||||||
|
[1000, 34000, 33000],
|
||||||
|
];
|
||||||
|
|
||||||
slice = file.slice(0, size, "foo/bar");
|
for (var i = 0; i < indexes.length; ++i) {
|
||||||
is(slice.type, "foo/bar", "[B7] full-size foo/bar type");
|
var sliceContents;
|
||||||
is(slice.size, size, "[B7] full-size foo/bar size");
|
var testName;
|
||||||
|
if (indexes[i][1] == undefined) {
|
||||||
|
slice = file.mozSlice(indexes[i][0]);
|
||||||
|
sliceContents = contents.slice(indexes[i][0]);
|
||||||
|
testName = fileType + " slice(" + indexes[i][0] + ")";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
slice = file.mozSlice(indexes[i][0], indexes[i][1]);
|
||||||
|
sliceContents = contents.slice(indexes[i][0], indexes[i][1]);
|
||||||
|
testName = fileType + " slice(" + indexes[i][0] + ", " + indexes[i][1] + ")";
|
||||||
|
}
|
||||||
|
is(slice.type, "", testName + " type");
|
||||||
|
is(slice.size, indexes[i][2], testName + " size");
|
||||||
|
is(sliceContents.length, indexes[i][2], testName + " data size");
|
||||||
|
checkFileContents(slice, sliceContents, testName);
|
||||||
|
}
|
||||||
|
|
||||||
slice = file.slice(0, 5432, "foo/bar");
|
// Slice of slice
|
||||||
is(slice.type, "foo/bar", "[B8] sized foo/bar type");
|
var slice = file.mozSlice(0, 40000);
|
||||||
is(slice.size, 5432, "[B8] sized foo/bar size");
|
checkFileContents(slice.mozSlice(5000, 42000), contents.slice(5000, 40000), "file slice slice");
|
||||||
|
|
||||||
is(slice.slice(0, 10).type, "", "[B9] slice-slice type");
|
// ...of slice of slice
|
||||||
is(slice.slice(0, 10).size, 10, "[B9] slice-slice size");
|
slice = slice.mozSlice(5000, 42000).mozSlice(400, 700);
|
||||||
is(slice.slice(0, 10, "hello/world").type, "hello/world", "[B9] slice-slice hello/world type");
|
gc();
|
||||||
is(slice.slice(0, 10, "hello/world").size, 10, "[B9] slice-slice hello/world type");
|
checkFileContents(slice, contents.slice(5400, 5700), "file slice slice slice");
|
||||||
}
|
}
|
||||||
|
|
||||||
testBasics(memFile, size, "image/png");
|
testFile(memFile, size, "image/png", fileData, "memFile");
|
||||||
testBasics(fileFile, size, "");
|
testFile(fileFile, size, "", fileData, "fileFile");
|
||||||
|
|
||||||
|
|
||||||
// Test reading various slices
|
|
||||||
|
|
||||||
// Full file
|
|
||||||
testFile(memFile, fileData, "mem file");
|
|
||||||
testFile(fileFile, fileData, "file file");
|
|
||||||
|
|
||||||
// Simple slice
|
|
||||||
testFile(memFile.slice(0, 33000), fileData.substr(0, 33000), "mem file slice");
|
|
||||||
testFile(fileFile.slice(0, 33000), fileData.substr(0, 33000), "file file slice");
|
|
||||||
|
|
||||||
// Simple slice not starting at beginning
|
|
||||||
testFile(memFile.slice(1000, 33000), fileData.substr(1000, 33000), "mem file slice starting at non-zero");
|
|
||||||
testFile(fileFile.slice(1000, 33000), fileData.substr(1000, 33000), "file file slice starting at non-zero");
|
|
||||||
|
|
||||||
// Slice of slice
|
|
||||||
var memSlice = memFile.slice(0, 40000);
|
|
||||||
var fileSlice = fileFile.slice(0, 40000);
|
|
||||||
testFile(memSlice.slice(5000, 37000), fileData.substr(5000, 35000), "mem file slice slice");
|
|
||||||
testFile(fileSlice.slice(5000, 37000), fileData.substr(5000, 35000), "file file slice slice");
|
|
||||||
|
|
||||||
// ...of slice of slice
|
|
||||||
memSlice = memSlice.slice(5000, 37000).slice(400, 300);
|
|
||||||
fileSlice = fileSlice.slice(5000, 37000).slice(400, 300);
|
|
||||||
gc();
|
|
||||||
testFile(memSlice, fileData.substr(5400, 300), "mem file slice slice slice");
|
|
||||||
testFile(fileSlice, fileData.substr(5400, 300), "file file slice slice slice");
|
|
||||||
|
|
||||||
// empty slice
|
|
||||||
testFile(memFile.slice(4711, 0), "", "mem file empty slice (1)");
|
|
||||||
testFile(fileFile.slice(4711, 0), "", "file file empty slice (1)");
|
|
||||||
testFile(memFile.slice(0, 0), "", "mem file empty slice (2)");
|
|
||||||
testFile(fileFile.slice(0, 0), "", "file file empty slice (2)");
|
|
||||||
|
|
||||||
// slice at end
|
|
||||||
testFile(memFile.slice(size-1000, 1000), fileData.substr(size-1000, 1000), "mem file slice at end");
|
|
||||||
testFile(fileFile.slice(size-1000, 1000), fileData.substr(size-1000, 1000), "file file slice at end");
|
|
||||||
|
|
||||||
// slice across end
|
|
||||||
testFile(memFile.slice(size-500, 1000), fileData.substr(size-500, 500), "mem file slice across end");
|
|
||||||
testFile(fileFile.slice(size-500, 1000), fileData.substr(size-500, 500), "file file slice across end");
|
|
||||||
|
|
||||||
// slice past end
|
|
||||||
testFile(memFile.slice(size, 1000), "", "mem file slice past end (1)");
|
|
||||||
testFile(fileFile.slice(size, 1000), "", "file file slice past end (1)");
|
|
||||||
testFile(memFile.slice(size + 1000, 1000), "", "mem file slice past end (2)");
|
|
||||||
testFile(fileFile.slice(size + 1000, 1000), "", "file file slice past end (2)");
|
|
||||||
|
|
||||||
|
|
||||||
// Try loading directly from slice into an image
|
// Try loading directly from slice into an image
|
||||||
|
@ -202,7 +181,7 @@ function imageLoadHandler(event) {
|
||||||
var imgfile = createFileWithData(testBinaryData + fileData + testBinaryData);
|
var imgfile = createFileWithData(testBinaryData + fileData + testBinaryData);
|
||||||
is(imgfile.size, size + testBinaryData.length * 2, "correct file size (middle)");
|
is(imgfile.size, size + testBinaryData.length * 2, "correct file size (middle)");
|
||||||
var img = new Image;
|
var img = new Image;
|
||||||
img.src = URL.createObjectURL(imgfile.slice(testBinaryData.length, size));
|
img.src = URL.createObjectURL(imgfile.mozSlice(testBinaryData.length, testBinaryData.length + size));
|
||||||
img.onload = imageLoadHandler;
|
img.onload = imageLoadHandler;
|
||||||
expectedTestCount++;
|
expectedTestCount++;
|
||||||
|
|
||||||
|
@ -210,7 +189,7 @@ expectedTestCount++;
|
||||||
var imgfile = createFileWithData(fileData + testBinaryData);
|
var imgfile = createFileWithData(fileData + testBinaryData);
|
||||||
is(imgfile.size, size + testBinaryData.length, "correct file size (start)");
|
is(imgfile.size, size + testBinaryData.length, "correct file size (start)");
|
||||||
var img = new Image;
|
var img = new Image;
|
||||||
img.src = URL.createObjectURL(imgfile.slice(0, size));
|
img.src = URL.createObjectURL(imgfile.mozSlice(0, size));
|
||||||
img.onload = imageLoadHandler;
|
img.onload = imageLoadHandler;
|
||||||
expectedTestCount++;
|
expectedTestCount++;
|
||||||
|
|
||||||
|
@ -218,7 +197,7 @@ expectedTestCount++;
|
||||||
var imgfile = createFileWithData(testBinaryData + fileData);
|
var imgfile = createFileWithData(testBinaryData + fileData);
|
||||||
is(imgfile.size, size + testBinaryData.length, "correct file size (end)");
|
is(imgfile.size, size + testBinaryData.length, "correct file size (end)");
|
||||||
var img = new Image;
|
var img = new Image;
|
||||||
img.src = URL.createObjectURL(imgfile.slice(testBinaryData.length, size));
|
img.src = URL.createObjectURL(imgfile.mozSlice(testBinaryData.length, testBinaryData.length + size));
|
||||||
img.onload = imageLoadHandler;
|
img.onload = imageLoadHandler;
|
||||||
expectedTestCount++;
|
expectedTestCount++;
|
||||||
|
|
||||||
|
@ -226,13 +205,15 @@ expectedTestCount++;
|
||||||
var imgfile = createFileWithData(testBinaryData + fileData);
|
var imgfile = createFileWithData(testBinaryData + fileData);
|
||||||
is(imgfile.size, size + testBinaryData.length, "correct file size (past end)");
|
is(imgfile.size, size + testBinaryData.length, "correct file size (past end)");
|
||||||
var img = new Image;
|
var img = new Image;
|
||||||
img.src = URL.createObjectURL(imgfile.slice(testBinaryData.length, size + 1000));
|
img.src = URL.createObjectURL(imgfile.mozSlice(testBinaryData.length, testBinaryData.length + size + 1000));
|
||||||
img.onload = imageLoadHandler;
|
img.onload = imageLoadHandler;
|
||||||
expectedTestCount++;
|
expectedTestCount++;
|
||||||
|
|
||||||
|
|
||||||
// Utility functions
|
// Utility functions
|
||||||
function testFile(file, contents, test) {
|
function checkFileContents(file, contents, test) {
|
||||||
|
SimpleTest.requestLongerTimeout(2);
|
||||||
|
|
||||||
// Load file using FileReader
|
// Load file using FileReader
|
||||||
var r = new FileReader();
|
var r = new FileReader();
|
||||||
r.onload = getFileReaderLoadHandler(contents, contents.length, "FileReader.readAsBinaryString of " + test);
|
r.onload = getFileReaderLoadHandler(contents, contents.length, "FileReader.readAsBinaryString of " + test);
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
/* -*- Mode: C++; tab-width: 40; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
/* -*- Mode: C++; tab-width: 40; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||||
*
|
/* ***** BEGIN LICENSE BLOCK *****
|
||||||
* ***** BEGIN LICENSE BLOCK *****
|
|
||||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||||
*
|
*
|
||||||
* The contents of this file are subject to the Mozilla Public License Version
|
* The contents of this file are subject to the Mozilla Public License Version
|
||||||
|
@ -58,8 +57,7 @@ Canvas2D_SetStyleHelper(JSContext *cx, JSObject *obj, jsid id, jsval *vp,
|
||||||
if (!xpc_qsUnwrapThis(cx, obj, nsnull, &self, &selfref.ptr, tvr.jsval_addr(), nsnull))
|
if (!xpc_qsUnwrapThis(cx, obj, nsnull, &self, &selfref.ptr, tvr.jsval_addr(), nsnull))
|
||||||
return JS_FALSE;
|
return JS_FALSE;
|
||||||
|
|
||||||
nsresult rv;
|
nsresult rv = NS_OK;
|
||||||
|
|
||||||
if (JSVAL_IS_STRING(*vp)) {
|
if (JSVAL_IS_STRING(*vp)) {
|
||||||
xpc_qsDOMString arg0(cx, *vp, vp,
|
xpc_qsDOMString arg0(cx, *vp, vp,
|
||||||
xpc_qsDOMString::eDefaultNullBehavior,
|
xpc_qsDOMString::eDefaultNullBehavior,
|
||||||
|
|
|
@ -671,8 +671,6 @@ helper_nsIDOMWebGLRenderingContext_UniformMatrix_x_fv(JSContext *cx, uintN argc,
|
||||||
if (!obj)
|
if (!obj)
|
||||||
return JS_FALSE;
|
return JS_FALSE;
|
||||||
|
|
||||||
nsresult rv;
|
|
||||||
|
|
||||||
nsIDOMWebGLRenderingContext *self;
|
nsIDOMWebGLRenderingContext *self;
|
||||||
xpc_qsSelfRef selfref;
|
xpc_qsSelfRef selfref;
|
||||||
js::AutoValueRooter tvr(cx);
|
js::AutoValueRooter tvr(cx);
|
||||||
|
@ -686,7 +684,7 @@ helper_nsIDOMWebGLRenderingContext_UniformMatrix_x_fv(JSContext *cx, uintN argc,
|
||||||
|
|
||||||
nsIWebGLUniformLocation *location;
|
nsIWebGLUniformLocation *location;
|
||||||
xpc_qsSelfRef location_selfref;
|
xpc_qsSelfRef location_selfref;
|
||||||
rv = xpc_qsUnwrapArg(cx, argv[0], &location, &location_selfref.ptr, &argv[0]);
|
nsresult rv = xpc_qsUnwrapArg(cx, argv[0], &location, &location_selfref.ptr, &argv[0]);
|
||||||
if (NS_FAILED(rv)) {
|
if (NS_FAILED(rv)) {
|
||||||
xpc_qsThrowBadArg(cx, rv, vp, 0);
|
xpc_qsThrowBadArg(cx, rv, vp, 0);
|
||||||
return JS_FALSE;
|
return JS_FALSE;
|
||||||
|
@ -746,8 +744,6 @@ helper_nsIDOMWebGLRenderingContext_VertexAttrib_x_fv(JSContext *cx, uintN argc,
|
||||||
if (!obj)
|
if (!obj)
|
||||||
return JS_FALSE;
|
return JS_FALSE;
|
||||||
|
|
||||||
nsresult rv;
|
|
||||||
|
|
||||||
nsIDOMWebGLRenderingContext *self;
|
nsIDOMWebGLRenderingContext *self;
|
||||||
xpc_qsSelfRef selfref;
|
xpc_qsSelfRef selfref;
|
||||||
js::AutoValueRooter tvr(cx);
|
js::AutoValueRooter tvr(cx);
|
||||||
|
@ -790,6 +786,7 @@ helper_nsIDOMWebGLRenderingContext_VertexAttrib_x_fv(JSContext *cx, uintN argc,
|
||||||
return JS_FALSE;
|
return JS_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nsresult rv = NS_OK;
|
||||||
if (nElements == 1) {
|
if (nElements == 1) {
|
||||||
rv = self->VertexAttrib1fv_array(location, wa);
|
rv = self->VertexAttrib1fv_array(location, wa);
|
||||||
} else if (nElements == 2) {
|
} else if (nElements == 2) {
|
||||||
|
@ -953,8 +950,7 @@ helper_nsIDOMWebGLRenderingContext_Uniform_x_iv_tn(JSContext *cx, JSObject *obj,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult rv;
|
nsresult rv = NS_OK;
|
||||||
|
|
||||||
if (nElements == 1) {
|
if (nElements == 1) {
|
||||||
rv = self->Uniform1iv_array(location, wa);
|
rv = self->Uniform1iv_array(location, wa);
|
||||||
} else if (nElements == 2) {
|
} else if (nElements == 2) {
|
||||||
|
@ -1025,8 +1021,7 @@ helper_nsIDOMWebGLRenderingContext_Uniform_x_fv_tn(JSContext *cx, JSObject *obj,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult rv;
|
nsresult rv = NS_OK;
|
||||||
|
|
||||||
if (nElements == 1) {
|
if (nElements == 1) {
|
||||||
rv = self->Uniform1fv_array(location, wa);
|
rv = self->Uniform1fv_array(location, wa);
|
||||||
} else if (nElements == 2) {
|
} else if (nElements == 2) {
|
||||||
|
@ -1099,7 +1094,7 @@ helper_nsIDOMWebGLRenderingContext_UniformMatrix_x_fv_tn(JSContext *cx, JSObject
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult rv;
|
nsresult rv = NS_OK;
|
||||||
if (nElements == 2) {
|
if (nElements == 2) {
|
||||||
rv = self->UniformMatrix2fv_array(location, transpose, wa);
|
rv = self->UniformMatrix2fv_array(location, transpose, wa);
|
||||||
} else if (nElements == 3) {
|
} else if (nElements == 3) {
|
||||||
|
|
|
@ -697,8 +697,6 @@ nsEventListenerManager::AddScriptEventListener(nsISupports *aObject,
|
||||||
return NS_ERROR_FAILURE;
|
return NS_ERROR_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult rv;
|
|
||||||
|
|
||||||
nsCOMPtr<nsINode> node(do_QueryInterface(aObject));
|
nsCOMPtr<nsINode> node(do_QueryInterface(aObject));
|
||||||
|
|
||||||
nsCOMPtr<nsIDocument> doc;
|
nsCOMPtr<nsIDocument> doc;
|
||||||
|
@ -734,6 +732,7 @@ nsEventListenerManager::AddScriptEventListener(nsISupports *aObject,
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nsresult rv = NS_OK;
|
||||||
// return early preventing the event listener from being added
|
// return early preventing the event listener from being added
|
||||||
// 'doc' is fetched above
|
// 'doc' is fetched above
|
||||||
if (doc) {
|
if (doc) {
|
||||||
|
|
|
@ -624,9 +624,11 @@ nsMouseWheelTransaction::SetTimeout()
|
||||||
timer.swap(sTimer);
|
timer.swap(sTimer);
|
||||||
}
|
}
|
||||||
sTimer->Cancel();
|
sTimer->Cancel();
|
||||||
|
#ifdef DEBUG
|
||||||
nsresult rv =
|
nsresult rv =
|
||||||
sTimer->InitWithFuncCallback(OnTimeout, nsnull, GetTimeoutTime(),
|
#endif
|
||||||
nsITimer::TYPE_ONE_SHOT);
|
sTimer->InitWithFuncCallback(OnTimeout, nsnull, GetTimeoutTime(),
|
||||||
|
nsITimer::TYPE_ONE_SHOT);
|
||||||
NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "nsITimer::InitWithFuncCallback failed");
|
NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "nsITimer::InitWithFuncCallback failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3278,11 +3280,12 @@ nsEventStateManager::PostHandleEvent(nsPresContext* aPresContext,
|
||||||
// Shift focus forward or back depending on shift key
|
// Shift focus forward or back depending on shift key
|
||||||
PRBool isDocMove = ((nsInputEvent*)aEvent)->isControl ||
|
PRBool isDocMove = ((nsInputEvent*)aEvent)->isControl ||
|
||||||
(keyEvent->keyCode == NS_VK_F6);
|
(keyEvent->keyCode == NS_VK_F6);
|
||||||
PRUint32 dir = ((nsInputEvent*)aEvent)->isShift ?
|
PRUint32 dir =
|
||||||
(isDocMove ? nsIFocusManager::MOVEFOCUS_BACKWARDDOC :
|
static_cast<nsInputEvent*>(aEvent)->isShift ?
|
||||||
nsIFocusManager::MOVEFOCUS_BACKWARD) :
|
(isDocMove ? static_cast<PRUint32>(nsIFocusManager::MOVEFOCUS_BACKWARDDOC) :
|
||||||
(isDocMove ? nsIFocusManager::MOVEFOCUS_FORWARDDOC :
|
static_cast<PRUint32>(nsIFocusManager::MOVEFOCUS_BACKWARD)) :
|
||||||
nsIFocusManager::MOVEFOCUS_FORWARD);
|
(isDocMove ? static_cast<PRUint32>(nsIFocusManager::MOVEFOCUS_FORWARDDOC) :
|
||||||
|
static_cast<PRUint32>(nsIFocusManager::MOVEFOCUS_FORWARD));
|
||||||
nsCOMPtr<nsIDOMElement> result;
|
nsCOMPtr<nsIDOMElement> result;
|
||||||
fm->MoveFocus(mDocument->GetWindow(), nsnull, dir,
|
fm->MoveFocus(mDocument->GetWindow(), nsnull, dir,
|
||||||
nsIFocusManager::FLAG_BYKEY,
|
nsIFocusManager::FLAG_BYKEY,
|
||||||
|
|
|
@ -1193,7 +1193,7 @@ nsGenericHTMLElement::SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
|
||||||
PRBool accessKey = aName == nsGkAtoms::accesskey &&
|
PRBool accessKey = aName == nsGkAtoms::accesskey &&
|
||||||
aNameSpaceID == kNameSpaceID_None;
|
aNameSpaceID == kNameSpaceID_None;
|
||||||
|
|
||||||
PRInt32 change;
|
PRInt32 change = 0;
|
||||||
if (contentEditable) {
|
if (contentEditable) {
|
||||||
change = GetContentEditableValue() == eTrue ? -1 : 0;
|
change = GetContentEditableValue() == eTrue ? -1 : 0;
|
||||||
SetMayHaveContentEditableAttr();
|
SetMayHaveContentEditableAttr();
|
||||||
|
@ -1228,7 +1228,7 @@ nsGenericHTMLElement::UnsetAttr(PRInt32 aNameSpaceID, nsIAtom* aAttribute,
|
||||||
PRBool aNotify)
|
PRBool aNotify)
|
||||||
{
|
{
|
||||||
PRBool contentEditable = PR_FALSE;
|
PRBool contentEditable = PR_FALSE;
|
||||||
PRInt32 contentEditableChange;
|
PRInt32 contentEditableChange = 0;
|
||||||
|
|
||||||
// Check for event handlers
|
// Check for event handlers
|
||||||
if (aNameSpaceID == kNameSpaceID_None) {
|
if (aNameSpaceID == kNameSpaceID_None) {
|
||||||
|
|
|
@ -83,6 +83,9 @@ class nsHTMLBodyElement : public nsGenericHTMLElement,
|
||||||
public nsIDOMHTMLBodyElement
|
public nsIDOMHTMLBodyElement
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
using nsGenericElement::GetText;
|
||||||
|
using nsGenericElement::SetText;
|
||||||
|
|
||||||
nsHTMLBodyElement(already_AddRefed<nsINodeInfo> aNodeInfo);
|
nsHTMLBodyElement(already_AddRefed<nsINodeInfo> aNodeInfo);
|
||||||
virtual ~nsHTMLBodyElement();
|
virtual ~nsHTMLBodyElement();
|
||||||
|
|
||||||
|
|
|
@ -2310,8 +2310,7 @@ nsHTMLInputElement::PostHandleEvent(nsEventChainPostVisitor& aVisitor)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If this is input type=text, and the user hit enter, fire onChange
|
* For some input types, if the user hits enter, the form is submitted.
|
||||||
* and submit the form (if we are in one)
|
|
||||||
*
|
*
|
||||||
* Bug 99920, bug 109463 and bug 147850:
|
* Bug 99920, bug 109463 and bug 147850:
|
||||||
* (a) if there is a submit control in the form, click the first
|
* (a) if there is a submit control in the form, click the first
|
||||||
|
@ -2325,42 +2324,19 @@ nsHTMLInputElement::PostHandleEvent(nsEventChainPostVisitor& aVisitor)
|
||||||
if (aVisitor.mEvent->message == NS_KEY_PRESS &&
|
if (aVisitor.mEvent->message == NS_KEY_PRESS &&
|
||||||
(keyEvent->keyCode == NS_VK_RETURN ||
|
(keyEvent->keyCode == NS_VK_RETURN ||
|
||||||
keyEvent->keyCode == NS_VK_ENTER) &&
|
keyEvent->keyCode == NS_VK_ENTER) &&
|
||||||
(mType == NS_FORM_INPUT_TEXT ||
|
IsSingleLineTextControl(PR_FALSE, mType)) {
|
||||||
mType == NS_FORM_INPUT_EMAIL ||
|
nsIFrame* primaryFrame = GetPrimaryFrame();
|
||||||
mType == NS_FORM_INPUT_SEARCH ||
|
if (primaryFrame) {
|
||||||
mType == NS_FORM_INPUT_PASSWORD ||
|
nsITextControlFrame* textFrame = do_QueryFrame(primaryFrame);
|
||||||
mType == NS_FORM_INPUT_TEL ||
|
|
||||||
mType == NS_FORM_INPUT_URL ||
|
|
||||||
mType == NS_FORM_INPUT_FILE)) {
|
|
||||||
|
|
||||||
PRBool isButton = PR_FALSE;
|
// Fire onChange (if necessary)
|
||||||
// If this is an enter on the button of a file input, don't submit
|
if (textFrame) {
|
||||||
// -- that's supposed to put up the filepicker
|
textFrame->CheckFireOnChange();
|
||||||
if (mType == NS_FORM_INPUT_FILE) {
|
|
||||||
nsCOMPtr<nsIContent> maybeButton =
|
|
||||||
do_QueryInterface(aVisitor.mEvent->originalTarget);
|
|
||||||
if (maybeButton) {
|
|
||||||
isButton = maybeButton->AttrValueIs(kNameSpaceID_None,
|
|
||||||
nsGkAtoms::type,
|
|
||||||
nsGkAtoms::button,
|
|
||||||
eCaseMatters);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isButton) {
|
rv = MaybeSubmitForm(aVisitor.mPresContext);
|
||||||
nsIFrame* primaryFrame = GetPrimaryFrame();
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
if (primaryFrame) {
|
|
||||||
nsITextControlFrame* textFrame = do_QueryFrame(primaryFrame);
|
|
||||||
|
|
||||||
// Fire onChange (if necessary)
|
|
||||||
if (textFrame) {
|
|
||||||
textFrame->CheckFireOnChange();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
rv = MaybeSubmitForm(aVisitor.mPresContext);
|
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} break; // NS_KEY_PRESS || NS_KEY_UP
|
} break; // NS_KEY_PRESS || NS_KEY_UP
|
||||||
|
|
|
@ -1820,7 +1820,7 @@ nsresult nsHTMLMediaElement::InitializeDecoderAsClone(nsMediaDecoder* aOriginal)
|
||||||
|
|
||||||
double duration = aOriginal->GetDuration();
|
double duration = aOriginal->GetDuration();
|
||||||
if (duration >= 0) {
|
if (duration >= 0) {
|
||||||
decoder->SetDuration(PRInt64(NS_round(duration * 1000)));
|
decoder->SetDuration(duration);
|
||||||
decoder->SetSeekable(aOriginal->GetSeekable());
|
decoder->SetSeekable(aOriginal->GetSeekable());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -309,6 +309,9 @@ class nsHTMLScriptElement : public nsGenericHTMLElement,
|
||||||
public nsScriptElement
|
public nsScriptElement
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
using nsGenericElement::GetText;
|
||||||
|
using nsGenericElement::SetText;
|
||||||
|
|
||||||
nsHTMLScriptElement(already_AddRefed<nsINodeInfo> aNodeInfo,
|
nsHTMLScriptElement(already_AddRefed<nsINodeInfo> aNodeInfo,
|
||||||
FromParser aFromParser);
|
FromParser aFromParser);
|
||||||
virtual ~nsHTMLScriptElement();
|
virtual ~nsHTMLScriptElement();
|
||||||
|
|
|
@ -49,6 +49,9 @@ class nsHTMLTitleElement : public nsGenericHTMLElement,
|
||||||
public nsStubMutationObserver
|
public nsStubMutationObserver
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
using nsGenericElement::GetText;
|
||||||
|
using nsGenericElement::SetText;
|
||||||
|
|
||||||
nsHTMLTitleElement(already_AddRefed<nsINodeInfo> aNodeInfo);
|
nsHTMLTitleElement(already_AddRefed<nsINodeInfo> aNodeInfo);
|
||||||
virtual ~nsHTMLTitleElement();
|
virtual ~nsHTMLTitleElement();
|
||||||
|
|
||||||
|
|
|
@ -82,11 +82,13 @@ struct SelectionState {
|
||||||
|
|
||||||
class RestoreSelectionState : public nsRunnable {
|
class RestoreSelectionState : public nsRunnable {
|
||||||
public:
|
public:
|
||||||
RestoreSelectionState(nsTextControlFrame *aFrame, PRInt32 aStart, PRInt32 aEnd)
|
RestoreSelectionState(nsTextEditorState *aState, nsTextControlFrame *aFrame,
|
||||||
|
PRInt32 aStart, PRInt32 aEnd)
|
||||||
: mFrame(aFrame),
|
: mFrame(aFrame),
|
||||||
mWeakFrame(aFrame),
|
mWeakFrame(aFrame),
|
||||||
mStart(aStart),
|
mStart(aStart),
|
||||||
mEnd(aEnd)
|
mEnd(aEnd),
|
||||||
|
mTextEditorState(aState)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -96,6 +98,7 @@ public:
|
||||||
// need to block script to avoid nested PrepareEditor calls (bug 642800).
|
// need to block script to avoid nested PrepareEditor calls (bug 642800).
|
||||||
nsAutoScriptBlocker scriptBlocker;
|
nsAutoScriptBlocker scriptBlocker;
|
||||||
mFrame->SetSelectionRange(mStart, mEnd);
|
mFrame->SetSelectionRange(mStart, mEnd);
|
||||||
|
mTextEditorState->HideSelectionIfBlurred();
|
||||||
}
|
}
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
@ -105,6 +108,7 @@ private:
|
||||||
nsWeakFrame mWeakFrame;
|
nsWeakFrame mWeakFrame;
|
||||||
PRInt32 mStart;
|
PRInt32 mStart;
|
||||||
PRInt32 mEnd;
|
PRInt32 mEnd;
|
||||||
|
nsTextEditorState* mTextEditorState;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*static*/
|
/*static*/
|
||||||
|
@ -1385,7 +1389,7 @@ nsTextEditorState::PrepareEditor(const nsAString *aValue)
|
||||||
|
|
||||||
// Restore our selection after being bound to a new frame
|
// Restore our selection after being bound to a new frame
|
||||||
if (mSelState) {
|
if (mSelState) {
|
||||||
nsContentUtils::AddScriptRunner(new RestoreSelectionState(mBoundFrame, mSelState->mStart, mSelState->mEnd));
|
nsContentUtils::AddScriptRunner(new RestoreSelectionState(this, mBoundFrame, mSelState->mStart, mSelState->mEnd));
|
||||||
mSelState = nsnull;
|
mSelState = nsnull;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2011,6 +2015,16 @@ nsTextEditorState::SetPlaceholderClass(PRBool aVisible,
|
||||||
classValue, aNotify);
|
classValue, aNotify);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nsTextEditorState::HideSelectionIfBlurred()
|
||||||
|
{
|
||||||
|
NS_ABORT_IF_FALSE(mSelCon, "Should have a selection controller if we have a frame!");
|
||||||
|
nsCOMPtr<nsIContent> content = do_QueryInterface(mTextCtrlElement);
|
||||||
|
if (!nsContentUtils::IsFocusedContent(content)) {
|
||||||
|
mSelCon->SetDisplaySelection(nsISelectionController::SELECTION_HIDDEN);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
NS_IMPL_ISUPPORTS1(nsAnonDivObserver, nsIMutationObserver)
|
NS_IMPL_ISUPPORTS1(nsAnonDivObserver, nsIMutationObserver)
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
@ -210,6 +210,8 @@ public:
|
||||||
|
|
||||||
void ClearValueCache() { mCachedValue.Truncate(); }
|
void ClearValueCache() { mCachedValue.Truncate(); }
|
||||||
|
|
||||||
|
void HideSelectionIfBlurred();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// not copy constructible
|
// not copy constructible
|
||||||
nsTextEditorState(const nsTextEditorState&);
|
nsTextEditorState(const nsTextEditorState&);
|
||||||
|
|
|
@ -2465,9 +2465,8 @@ HTMLContentSink::AddDocTypeDecl(const nsIParserNode& aNode)
|
||||||
nsAutoString voidString;
|
nsAutoString voidString;
|
||||||
voidString.SetIsVoid(PR_TRUE);
|
voidString.SetIsVoid(PR_TRUE);
|
||||||
rv = NS_NewDOMDocumentType(getter_AddRefs(docType),
|
rv = NS_NewDOMDocumentType(getter_AddRefs(docType),
|
||||||
mDocument->NodeInfoManager(), nsnull,
|
mDocument->NodeInfoManager(), nsnull, nameAtom,
|
||||||
nameAtom, nsnull, nsnull, publicId, systemId,
|
publicId, systemId, voidString);
|
||||||
voidString);
|
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
if (oldDocType) {
|
if (oldDocType) {
|
||||||
|
|
|
@ -3287,7 +3287,7 @@ nsHTMLDocument::EditingStateChanged()
|
||||||
}
|
}
|
||||||
|
|
||||||
PRBool makeWindowEditable = mEditingState == eOff;
|
PRBool makeWindowEditable = mEditingState == eOff;
|
||||||
PRBool updateState;
|
bool updateState = false;
|
||||||
PRBool spellRecheckAll = PR_FALSE;
|
PRBool spellRecheckAll = PR_FALSE;
|
||||||
nsCOMPtr<nsIEditor> editor;
|
nsCOMPtr<nsIEditor> editor;
|
||||||
|
|
||||||
|
@ -3356,7 +3356,7 @@ nsHTMLDocument::EditingStateChanged()
|
||||||
rv = editSession->DisableJSAndPlugins(window);
|
rv = editSession->DisableJSAndPlugins(window);
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
updateState = PR_TRUE;
|
updateState = true;
|
||||||
spellRecheckAll = oldState == eContentEditable;
|
spellRecheckAll = oldState == eContentEditable;
|
||||||
}
|
}
|
||||||
else if (oldState == eDesignMode) {
|
else if (oldState == eDesignMode) {
|
||||||
|
@ -3366,11 +3366,7 @@ nsHTMLDocument::EditingStateChanged()
|
||||||
rv = editSession->RestoreJSAndPlugins(window);
|
rv = editSession->RestoreJSAndPlugins(window);
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
updateState = PR_TRUE;
|
updateState = true;
|
||||||
}
|
|
||||||
else {
|
|
||||||
// contentEditable is being turned on (and designMode is off).
|
|
||||||
updateState = PR_FALSE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
rv = presShell->SetAgentStyleSheets(agentSheets);
|
rv = presShell->SetAgentStyleSheets(agentSheets);
|
||||||
|
|
|
@ -175,24 +175,24 @@ PRBool MulOverflow(PRInt64 a, PRInt64 b, PRInt64& aResult) {
|
||||||
return PR_TRUE;
|
return PR_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Converts from number of audio samples to milliseconds, given the specified
|
// Converts from number of audio samples to microseconds, given the specified
|
||||||
// audio rate.
|
// audio rate.
|
||||||
PRBool SamplesToMs(PRInt64 aSamples, PRUint32 aRate, PRInt64& aOutMs)
|
PRBool SamplesToUsecs(PRInt64 aSamples, PRUint32 aRate, PRInt64& aOutUsecs)
|
||||||
{
|
{
|
||||||
PRInt64 x;
|
PRInt64 x;
|
||||||
if (!MulOverflow(aSamples, 1000, x))
|
if (!MulOverflow(aSamples, USECS_PER_S, x))
|
||||||
return PR_FALSE;
|
return PR_FALSE;
|
||||||
aOutMs = x / aRate;
|
aOutUsecs = x / aRate;
|
||||||
return PR_TRUE;
|
return PR_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Converts from milliseconds to number of audio samples, given the specified
|
// Converts from microseconds to number of audio samples, given the specified
|
||||||
// audio rate.
|
// audio rate.
|
||||||
PRBool MsToSamples(PRInt64 aMs, PRUint32 aRate, PRInt64& aOutSamples)
|
PRBool UsecsToSamples(PRInt64 aUsecs, PRUint32 aRate, PRInt64& aOutSamples)
|
||||||
{
|
{
|
||||||
PRInt64 x;
|
PRInt64 x;
|
||||||
if (!MulOverflow(aMs, aRate, x))
|
if (!MulOverflow(aUsecs, aRate, x))
|
||||||
return PR_FALSE;
|
return PR_FALSE;
|
||||||
aOutSamples = x / 1000;
|
aOutSamples = x / USECS_PER_S;
|
||||||
return PR_TRUE;
|
return PR_TRUE;
|
||||||
}
|
}
|
||||||
|
|
|
@ -126,16 +126,22 @@ PRBool AddOverflow(PRInt64 a, PRInt64 b, PRInt64& aResult);
|
||||||
// in an integer overflow.
|
// in an integer overflow.
|
||||||
PRBool MulOverflow(PRInt64 a, PRInt64 b, PRInt64& aResult);
|
PRBool MulOverflow(PRInt64 a, PRInt64 b, PRInt64& aResult);
|
||||||
|
|
||||||
// Converts from number of audio samples (aSamples) to milliseconds, given
|
// Converts from number of audio samples (aSamples) to microseconds, given
|
||||||
// the specified audio rate (aRate). Stores result in aOutMs. Returns PR_TRUE
|
// the specified audio rate (aRate). Stores result in aOutUsecs. Returns PR_TRUE
|
||||||
// if the operation succeeded, or PR_FALSE if there was an integer overflow
|
// if the operation succeeded, or PR_FALSE if there was an integer overflow
|
||||||
// while calulating the conversion.
|
// while calulating the conversion.
|
||||||
PRBool SamplesToMs(PRInt64 aSamples, PRUint32 aRate, PRInt64& aOutMs);
|
PRBool SamplesToUsecs(PRInt64 aSamples, PRUint32 aRate, PRInt64& aOutUsecs);
|
||||||
|
|
||||||
// Converts from milliseconds (aMs) to number of audio samples, given the
|
// Converts from microseconds (aUsecs) to number of audio samples, given the
|
||||||
// specified audio rate (aRate). Stores the result in aOutSamples. Returns
|
// specified audio rate (aRate). Stores the result in aOutSamples. Returns
|
||||||
// PR_TRUE if the operation succeeded, or PR_FALSE if there was an integer
|
// PR_TRUE if the operation succeeded, or PR_FALSE if there was an integer
|
||||||
// overflow while calulating the conversion.
|
// overflow while calulating the conversion.
|
||||||
PRBool MsToSamples(PRInt64 aMs, PRUint32 aRate, PRInt64& aOutSamples);
|
PRBool UsecsToSamples(PRInt64 aUsecs, PRUint32 aRate, PRInt64& aOutSamples);
|
||||||
|
|
||||||
|
// Number of microseconds per second. 1e6.
|
||||||
|
#define USECS_PER_S 1000000
|
||||||
|
|
||||||
|
// Number of microseconds per millisecond.
|
||||||
|
#define USECS_PER_MS 1000
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -39,8 +39,8 @@
|
||||||
|
|
||||||
#include "nsTArray.h"
|
#include "nsTArray.h"
|
||||||
#include "nsAudioAvailableEventManager.h"
|
#include "nsAudioAvailableEventManager.h"
|
||||||
|
#include "VideoUtils.h"
|
||||||
|
|
||||||
#define MILLISECONDS_PER_SECOND 1000.0f
|
|
||||||
#define MAX_PENDING_EVENTS 100
|
#define MAX_PENDING_EVENTS 100
|
||||||
|
|
||||||
using namespace mozilla;
|
using namespace mozilla;
|
||||||
|
@ -107,7 +107,7 @@ void nsAudioAvailableEventManager::DispatchPendingEvents(PRUint64 aCurrentTime)
|
||||||
while (mPendingEvents.Length() > 0) {
|
while (mPendingEvents.Length() > 0) {
|
||||||
nsAudioAvailableEventRunner* e =
|
nsAudioAvailableEventRunner* e =
|
||||||
(nsAudioAvailableEventRunner*)mPendingEvents[0].get();
|
(nsAudioAvailableEventRunner*)mPendingEvents[0].get();
|
||||||
if (e->mTime * MILLISECONDS_PER_SECOND > aCurrentTime) {
|
if (e->mTime * USECS_PER_S > aCurrentTime) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
nsCOMPtr<nsIRunnable> event = mPendingEvents[0];
|
nsCOMPtr<nsIRunnable> event = mPendingEvents[0];
|
||||||
|
@ -228,7 +228,7 @@ void nsAudioAvailableEventManager::Drain(PRUint64 aEndTime)
|
||||||
(mSignalBufferLength - mSignalBufferPosition) * sizeof(float));
|
(mSignalBufferLength - mSignalBufferPosition) * sizeof(float));
|
||||||
|
|
||||||
// Force this last event to go now.
|
// Force this last event to go now.
|
||||||
float time = (aEndTime / MILLISECONDS_PER_SECOND) -
|
float time = (aEndTime / static_cast<float>(USECS_PER_S)) -
|
||||||
(mSignalBufferPosition / mSamplesPerSecond);
|
(mSignalBufferPosition / mSamplesPerSecond);
|
||||||
nsCOMPtr<nsIRunnable> lastEvent =
|
nsCOMPtr<nsIRunnable> lastEvent =
|
||||||
new nsAudioAvailableEventRunner(mDecoder, mSignalBuffer.forget(),
|
new nsAudioAvailableEventRunner(mDecoder, mSignalBuffer.forget(),
|
||||||
|
|
|
@ -51,6 +51,7 @@ using namespace mozilla::dom;
|
||||||
#include "nsAutoPtr.h"
|
#include "nsAutoPtr.h"
|
||||||
#include "nsAudioStream.h"
|
#include "nsAudioStream.h"
|
||||||
#include "nsAlgorithm.h"
|
#include "nsAlgorithm.h"
|
||||||
|
#include "VideoUtils.h"
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#include "sydneyaudio/sydney_audio.h"
|
#include "sydneyaudio/sydney_audio.h"
|
||||||
}
|
}
|
||||||
|
@ -74,7 +75,6 @@ PRLogModuleInfo* gAudioStreamLog = nsnull;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define FAKE_BUFFER_SIZE 176400
|
#define FAKE_BUFFER_SIZE 176400
|
||||||
#define MILLISECONDS_PER_SECOND 1000
|
|
||||||
|
|
||||||
class nsAudioStreamLocal : public nsAudioStream
|
class nsAudioStreamLocal : public nsAudioStream
|
||||||
{
|
{
|
||||||
|
@ -551,7 +551,7 @@ PRInt64 nsAudioStreamLocal::GetPosition()
|
||||||
{
|
{
|
||||||
PRInt64 sampleOffset = GetSampleOffset();
|
PRInt64 sampleOffset = GetSampleOffset();
|
||||||
if (sampleOffset >= 0) {
|
if (sampleOffset >= 0) {
|
||||||
return ((MILLISECONDS_PER_SECOND * sampleOffset) / mRate / mChannels);
|
return ((USECS_PER_S * sampleOffset) / mRate / mChannels);
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -718,7 +718,7 @@ PRInt64 nsAudioStreamRemote::GetPosition()
|
||||||
{
|
{
|
||||||
PRInt64 sampleOffset = GetSampleOffset();
|
PRInt64 sampleOffset = GetSampleOffset();
|
||||||
if (sampleOffset >= 0) {
|
if (sampleOffset >= 0) {
|
||||||
return ((MILLISECONDS_PER_SECOND * sampleOffset) / mRate / mChannels);
|
return ((USECS_PER_S * sampleOffset) / mRate / mChannels);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -734,7 +734,7 @@ nsAudioStreamRemote::GetSampleOffset()
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
PRInt64 time = mAudioChild->GetLastKnownSampleOffsetTime();
|
PRInt64 time = mAudioChild->GetLastKnownSampleOffsetTime();
|
||||||
PRInt64 result = offset + (mRate * mChannels * (PR_IntervalNow() - time) / MILLISECONDS_PER_SECOND);
|
PRInt64 result = offset + (mRate * mChannels * (PR_IntervalNow() - time) / USECS_PER_S);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
|
@ -106,7 +106,7 @@ public:
|
||||||
// Resume audio playback
|
// Resume audio playback
|
||||||
virtual void Resume() = 0;
|
virtual void Resume() = 0;
|
||||||
|
|
||||||
// Return the position in milliseconds of the sample being played by the
|
// Return the position in microseconds of the sample being played by the
|
||||||
// audio hardware.
|
// audio hardware.
|
||||||
virtual PRInt64 GetPosition() = 0;
|
virtual PRInt64 GetPosition() = 0;
|
||||||
|
|
||||||
|
|
|
@ -83,7 +83,7 @@ double nsBuiltinDecoder::GetDuration()
|
||||||
{
|
{
|
||||||
NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
|
NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
|
||||||
if (mDuration >= 0) {
|
if (mDuration >= 0) {
|
||||||
return static_cast<double>(mDuration) / 1000.0;
|
return static_cast<double>(mDuration) / static_cast<double>(USECS_PER_S);
|
||||||
}
|
}
|
||||||
return std::numeric_limits<double>::quiet_NaN();
|
return std::numeric_limits<double>::quiet_NaN();
|
||||||
}
|
}
|
||||||
|
@ -538,7 +538,7 @@ double nsBuiltinDecoder::ComputePlaybackRate(PRPackedBool* aReliable)
|
||||||
PRInt64 length = mStream ? mStream->GetLength() : -1;
|
PRInt64 length = mStream ? mStream->GetLength() : -1;
|
||||||
if (mDuration >= 0 && length >= 0) {
|
if (mDuration >= 0 && length >= 0) {
|
||||||
*aReliable = PR_TRUE;
|
*aReliable = PR_TRUE;
|
||||||
return double(length)*1000.0/mDuration;
|
return length * static_cast<double>(USECS_PER_S) / mDuration;
|
||||||
}
|
}
|
||||||
return mPlaybackStatistics.GetRateAtLastStop(aReliable);
|
return mPlaybackStatistics.GetRateAtLastStop(aReliable);
|
||||||
}
|
}
|
||||||
|
@ -814,15 +814,15 @@ void nsBuiltinDecoder::DurationChanged()
|
||||||
UpdatePlaybackRate();
|
UpdatePlaybackRate();
|
||||||
|
|
||||||
if (mElement && oldDuration != mDuration) {
|
if (mElement && oldDuration != mDuration) {
|
||||||
LOG(PR_LOG_DEBUG, ("%p duration changed to %lldms", this, mDuration));
|
LOG(PR_LOG_DEBUG, ("%p duration changed to %lld", this, mDuration));
|
||||||
mElement->DispatchEvent(NS_LITERAL_STRING("durationchange"));
|
mElement->DispatchEvent(NS_LITERAL_STRING("durationchange"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void nsBuiltinDecoder::SetDuration(PRInt64 aDuration)
|
void nsBuiltinDecoder::SetDuration(double aDuration)
|
||||||
{
|
{
|
||||||
NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
|
NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
|
||||||
mDuration = aDuration;
|
mDuration = static_cast<PRInt64>(NS_round(aDuration * static_cast<double>(USECS_PER_S)));
|
||||||
|
|
||||||
MonitorAutoEnter mon(mMonitor);
|
MonitorAutoEnter mon(mMonitor);
|
||||||
if (mDecoderStateMachine) {
|
if (mDecoderStateMachine) {
|
||||||
|
|
|
@ -250,13 +250,14 @@ public:
|
||||||
virtual void Shutdown() = 0;
|
virtual void Shutdown() = 0;
|
||||||
|
|
||||||
// Called from the main thread to get the duration. The decoder monitor
|
// Called from the main thread to get the duration. The decoder monitor
|
||||||
// must be obtained before calling this. It is in units of milliseconds.
|
// must be obtained before calling this. It is in units of microseconds.
|
||||||
virtual PRInt64 GetDuration() = 0;
|
virtual PRInt64 GetDuration() = 0;
|
||||||
|
|
||||||
// Called from the main thread to set the duration of the media resource
|
// Called from the main thread to set the duration of the media resource
|
||||||
// if it is able to be obtained via HTTP headers. Called from the
|
// if it is able to be obtained via HTTP headers. Called from the
|
||||||
// state machine thread to set the duration if it is obtained from the
|
// state machine thread to set the duration if it is obtained from the
|
||||||
// media metadata. The decoder monitor must be obtained before calling this.
|
// media metadata. The decoder monitor must be obtained before calling this.
|
||||||
|
// aDuration is in microseconds.
|
||||||
virtual void SetDuration(PRInt64 aDuration) = 0;
|
virtual void SetDuration(PRInt64 aDuration) = 0;
|
||||||
|
|
||||||
// Functions used by assertions to ensure we're calling things
|
// Functions used by assertions to ensure we're calling things
|
||||||
|
@ -387,10 +388,10 @@ class nsBuiltinDecoder : public nsMediaDecoder
|
||||||
// Call on the main thread only.
|
// Call on the main thread only.
|
||||||
virtual PRBool IsEnded() const;
|
virtual PRBool IsEnded() const;
|
||||||
|
|
||||||
// Set the duration of the media resource in units of milliseconds.
|
// Set the duration of the media resource in units of seconds.
|
||||||
// This is called via a channel listener if it can pick up the duration
|
// This is called via a channel listener if it can pick up the duration
|
||||||
// from a content header. Must be called from the main thread only.
|
// from a content header. Must be called from the main thread only.
|
||||||
virtual void SetDuration(PRInt64 aDuration);
|
virtual void SetDuration(double aDuration);
|
||||||
|
|
||||||
// Set a flag indicating whether seeking is supported
|
// Set a flag indicating whether seeking is supported
|
||||||
virtual void SetSeekable(PRBool aSeekable);
|
virtual void SetSeekable(PRBool aSeekable);
|
||||||
|
|
|
@ -179,8 +179,8 @@ public:
|
||||||
// chunk ends.
|
// chunk ends.
|
||||||
const PRInt64 mOffset;
|
const PRInt64 mOffset;
|
||||||
|
|
||||||
PRInt64 mTime; // Start time of samples in ms.
|
PRInt64 mTime; // Start time of samples in usecs.
|
||||||
const PRInt64 mDuration; // In ms.
|
const PRInt64 mDuration; // In usecs.
|
||||||
const PRUint32 mSamples;
|
const PRUint32 mSamples;
|
||||||
const PRUint32 mChannels;
|
const PRUint32 mChannels;
|
||||||
nsAutoArrayPtr<SoundDataValue> mAudioData;
|
nsAutoArrayPtr<SoundDataValue> mAudioData;
|
||||||
|
@ -241,10 +241,10 @@ public:
|
||||||
// Approximate byte offset of the end of the frame in the media.
|
// Approximate byte offset of the end of the frame in the media.
|
||||||
PRInt64 mOffset;
|
PRInt64 mOffset;
|
||||||
|
|
||||||
// Start time of frame in milliseconds.
|
// Start time of frame in microseconds.
|
||||||
PRInt64 mTime;
|
PRInt64 mTime;
|
||||||
|
|
||||||
// End time of frame in milliseconds;
|
// End time of frame in microseconds;
|
||||||
PRInt64 mEndTime;
|
PRInt64 mEndTime;
|
||||||
|
|
||||||
// Codec specific internal time code. For Ogg based codecs this is the
|
// Codec specific internal time code. For Ogg based codecs this is the
|
||||||
|
@ -387,7 +387,7 @@ template <class T> class MediaQueue : private nsDeque {
|
||||||
mEndOfStream = PR_TRUE;
|
mEndOfStream = PR_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the approximate number of milliseconds of samples in the queue.
|
// Returns the approximate number of microseconds of samples in the queue.
|
||||||
PRInt64 Duration() {
|
PRInt64 Duration() {
|
||||||
MonitorAutoEnter mon(mMonitor);
|
MonitorAutoEnter mon(mMonitor);
|
||||||
if (GetSize() < 2) {
|
if (GetSize() < 2) {
|
||||||
|
@ -457,9 +457,9 @@ public:
|
||||||
// This will not read past aEndOffset. Returns -1 on failure.
|
// This will not read past aEndOffset. Returns -1 on failure.
|
||||||
virtual PRInt64 FindEndTime(PRInt64 aEndOffset);
|
virtual PRInt64 FindEndTime(PRInt64 aEndOffset);
|
||||||
|
|
||||||
// Moves the decode head to aTime milliseconds. aStartTime and aEndTime
|
// Moves the decode head to aTime microseconds. aStartTime and aEndTime
|
||||||
// denote the start and end times of the media in ms, and aCurrentTime
|
// denote the start and end times of the media in usecs, and aCurrentTime
|
||||||
// is the current playback position in ms.
|
// is the current playback position in microseconds.
|
||||||
virtual nsresult Seek(PRInt64 aTime,
|
virtual nsresult Seek(PRInt64 aTime,
|
||||||
PRInt64 aStartTime,
|
PRInt64 aStartTime,
|
||||||
PRInt64 aEndTime,
|
PRInt64 aEndTime,
|
||||||
|
@ -485,7 +485,7 @@ public:
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
// Pumps the decode until we reach frames/samples required to play at
|
// Pumps the decode until we reach frames/samples required to play at
|
||||||
// time aTarget (ms).
|
// time aTarget (usecs).
|
||||||
nsresult DecodeToTarget(PRInt64 aTarget);
|
nsresult DecodeToTarget(PRInt64 aTarget);
|
||||||
|
|
||||||
// Reader decode function. Matches DecodeVideoFrame() and
|
// Reader decode function. Matches DecodeVideoFrame() and
|
||||||
|
|
|
@ -68,17 +68,17 @@ extern PRLogModuleInfo* gBuiltinDecoderLog;
|
||||||
#define BUFFERING_MIN_RATE 50000
|
#define BUFFERING_MIN_RATE 50000
|
||||||
#define BUFFERING_RATE(x) ((x)< BUFFERING_MIN_RATE ? BUFFERING_MIN_RATE : (x))
|
#define BUFFERING_RATE(x) ((x)< BUFFERING_MIN_RATE ? BUFFERING_MIN_RATE : (x))
|
||||||
|
|
||||||
// If audio queue has less than this many ms of decoded audio, we won't risk
|
// If audio queue has less than this many usecs of decoded audio, we won't risk
|
||||||
// trying to decode the video, we'll skip decoding video up to the next
|
// trying to decode the video, we'll skip decoding video up to the next
|
||||||
// keyframe. We may increase this value for an individual decoder if we
|
// keyframe. We may increase this value for an individual decoder if we
|
||||||
// encounter video frames which take a long time to decode.
|
// encounter video frames which take a long time to decode.
|
||||||
static const PRUint32 LOW_AUDIO_MS = 300;
|
static const PRUint32 LOW_AUDIO_USECS = 300000;
|
||||||
|
|
||||||
// If more than this many ms of decoded audio is queued, we'll hold off
|
// If more than this many usecs of decoded audio is queued, we'll hold off
|
||||||
// decoding more audio. If we increase the low audio threshold (see
|
// decoding more audio. If we increase the low audio threshold (see
|
||||||
// LOW_AUDIO_MS above) we'll also increase this value to ensure it's not
|
// LOW_AUDIO_USECS above) we'll also increase this value to ensure it's not
|
||||||
// less than the low audio threshold.
|
// less than the low audio threshold.
|
||||||
const PRInt64 AMPLE_AUDIO_MS = 1000;
|
const PRInt64 AMPLE_AUDIO_USECS = 1000000;
|
||||||
|
|
||||||
// Maximum number of bytes we'll allocate and write at once to the audio
|
// Maximum number of bytes we'll allocate and write at once to the audio
|
||||||
// hardware when the audio stream contains missing samples and we're
|
// hardware when the audio stream contains missing samples and we're
|
||||||
|
@ -98,9 +98,9 @@ static const PRUint32 LOW_VIDEO_FRAMES = 1;
|
||||||
static const PRUint32 AMPLE_VIDEO_FRAMES = 10;
|
static const PRUint32 AMPLE_VIDEO_FRAMES = 10;
|
||||||
|
|
||||||
// Arbitrary "frame duration" when playing only audio.
|
// Arbitrary "frame duration" when playing only audio.
|
||||||
static const int AUDIO_DURATION_MS = 40;
|
static const int AUDIO_DURATION_USECS = 40000;
|
||||||
|
|
||||||
// If we increase our "low audio threshold" (see LOW_AUDIO_MS above), we
|
// If we increase our "low audio threshold" (see LOW_AUDIO_USECS above), we
|
||||||
// use this as a factor in all our calculations. Increasing this will cause
|
// use this as a factor in all our calculations. Increasing this will cause
|
||||||
// us to be more likely to increase our low audio threshold, and to
|
// us to be more likely to increase our low audio threshold, and to
|
||||||
// increase it by more.
|
// increase it by more.
|
||||||
|
@ -110,16 +110,16 @@ static const int THRESHOLD_FACTOR = 2;
|
||||||
// ourselves to be running low on undecoded data. We determine how much
|
// ourselves to be running low on undecoded data. We determine how much
|
||||||
// undecoded data we have remaining using the reader's GetBuffered()
|
// undecoded data we have remaining using the reader's GetBuffered()
|
||||||
// implementation.
|
// implementation.
|
||||||
static const PRInt64 LOW_DATA_THRESHOLD_MS = 5000;
|
static const PRInt64 LOW_DATA_THRESHOLD_USECS = 5000000;
|
||||||
|
|
||||||
// LOW_DATA_THRESHOLD_MS needs to be greater than AMPLE_AUDIO_MS, otherwise
|
// LOW_DATA_THRESHOLD_USECS needs to be greater than AMPLE_AUDIO_USECS, otherwise
|
||||||
// the skip-to-keyframe logic can activate when we're running low on data.
|
// the skip-to-keyframe logic can activate when we're running low on data.
|
||||||
PR_STATIC_ASSERT(LOW_DATA_THRESHOLD_MS > AMPLE_AUDIO_MS);
|
PR_STATIC_ASSERT(LOW_DATA_THRESHOLD_USECS > AMPLE_AUDIO_USECS);
|
||||||
|
|
||||||
// Amount of excess ms of data to add in to the "should we buffer" calculation.
|
// Amount of excess usecs of data to add in to the "should we buffer" calculation.
|
||||||
static const PRUint32 EXHAUSTED_DATA_MARGIN_MS = 60;
|
static const PRUint32 EXHAUSTED_DATA_MARGIN_USECS = 60000;
|
||||||
|
|
||||||
// If we enter buffering within QUICK_BUFFER_THRESHOLD_MS seconds of starting
|
// If we enter buffering within QUICK_BUFFER_THRESHOLD_USECS seconds of starting
|
||||||
// decoding, we'll enter "quick buffering" mode, which exits a lot sooner than
|
// decoding, we'll enter "quick buffering" mode, which exits a lot sooner than
|
||||||
// normal buffering mode. This exists so that if the decode-ahead exhausts the
|
// normal buffering mode. This exists so that if the decode-ahead exhausts the
|
||||||
// downloaded data while decode/playback is just starting up (for example
|
// downloaded data while decode/playback is just starting up (for example
|
||||||
|
@ -128,24 +128,24 @@ static const PRUint32 EXHAUSTED_DATA_MARGIN_MS = 60;
|
||||||
// for buffering. We may actually be able to playback in this case, so exit
|
// for buffering. We may actually be able to playback in this case, so exit
|
||||||
// buffering early and try to play. If it turns out we can't play, we'll fall
|
// buffering early and try to play. If it turns out we can't play, we'll fall
|
||||||
// back to buffering normally.
|
// back to buffering normally.
|
||||||
static const PRUint32 QUICK_BUFFER_THRESHOLD_MS = 2000;
|
static const PRUint32 QUICK_BUFFER_THRESHOLD_USECS = 2000000;
|
||||||
|
|
||||||
// If we're quick buffering, we'll remain in buffering mode while we have less than
|
// If we're quick buffering, we'll remain in buffering mode while we have less than
|
||||||
// QUICK_BUFFERING_LOW_DATA_MS of decoded data available.
|
// QUICK_BUFFERING_LOW_DATA_USECS of decoded data available.
|
||||||
static const PRUint32 QUICK_BUFFERING_LOW_DATA_MS = 1000;
|
static const PRUint32 QUICK_BUFFERING_LOW_DATA_USECS = 1000000;
|
||||||
|
|
||||||
// If QUICK_BUFFERING_LOW_DATA_MS is > AMPLE_AUDIO_MS, we won't exit
|
// If QUICK_BUFFERING_LOW_DATA_USECS is > AMPLE_AUDIO_USECS, we won't exit
|
||||||
// quick buffering in a timely fashion, as the decode pauses when it
|
// quick buffering in a timely fashion, as the decode pauses when it
|
||||||
// reaches AMPLE_AUDIO_MS decoded data, and thus we'll never reach
|
// reaches AMPLE_AUDIO_USECS decoded data, and thus we'll never reach
|
||||||
// QUICK_BUFFERING_LOW_DATA_MS.
|
// QUICK_BUFFERING_LOW_DATA_USECS.
|
||||||
PR_STATIC_ASSERT(QUICK_BUFFERING_LOW_DATA_MS <= AMPLE_AUDIO_MS);
|
PR_STATIC_ASSERT(QUICK_BUFFERING_LOW_DATA_USECS <= AMPLE_AUDIO_USECS);
|
||||||
|
|
||||||
static TimeDuration MsToDuration(PRInt64 aMs) {
|
static TimeDuration UsecsToDuration(PRInt64 aUsecs) {
|
||||||
return TimeDuration::FromMilliseconds(static_cast<double>(aMs));
|
return TimeDuration::FromMilliseconds(static_cast<double>(aUsecs) / USECS_PER_MS);
|
||||||
}
|
}
|
||||||
|
|
||||||
static PRInt64 DurationToMs(TimeDuration aDuration) {
|
static PRInt64 DurationToUsecs(TimeDuration aDuration) {
|
||||||
return static_cast<PRInt64>(aDuration.ToSeconds() * 1000);
|
return static_cast<PRInt64>(aDuration.ToSeconds() * USECS_PER_S);
|
||||||
}
|
}
|
||||||
|
|
||||||
class nsAudioMetadataEventRunner : public nsRunnable
|
class nsAudioMetadataEventRunner : public nsRunnable
|
||||||
|
@ -212,7 +212,7 @@ PRBool nsBuiltinDecoderStateMachine::HasFutureAudio() const {
|
||||||
// we've completely decoded all audio (but not finished playing it yet
|
// we've completely decoded all audio (but not finished playing it yet
|
||||||
// as per 1).
|
// as per 1).
|
||||||
return !mAudioCompleted &&
|
return !mAudioCompleted &&
|
||||||
(AudioDecodedMs() > LOW_AUDIO_MS || mReader->mAudioQueue.IsFinished());
|
(AudioDecodedUsecs() > LOW_AUDIO_USECS || mReader->mAudioQueue.IsFinished());
|
||||||
}
|
}
|
||||||
|
|
||||||
PRBool nsBuiltinDecoderStateMachine::HaveNextFrameData() const {
|
PRBool nsBuiltinDecoderStateMachine::HaveNextFrameData() const {
|
||||||
|
@ -250,19 +250,19 @@ void nsBuiltinDecoderStateMachine::DecodeLoop()
|
||||||
// no longer be considered to be "pumping video".
|
// no longer be considered to be "pumping video".
|
||||||
const unsigned videoPumpThreshold = AMPLE_VIDEO_FRAMES / 2;
|
const unsigned videoPumpThreshold = AMPLE_VIDEO_FRAMES / 2;
|
||||||
|
|
||||||
// After the audio decode fills with more than audioPumpThresholdMs ms
|
// After the audio decode fills with more than audioPumpThreshold usecs
|
||||||
// of decoded audio, we'll start to check whether the audio or video decode
|
// of decoded audio, we'll start to check whether the audio or video decode
|
||||||
// is falling behind.
|
// is falling behind.
|
||||||
const unsigned audioPumpThresholdMs = LOW_AUDIO_MS * 2;
|
const unsigned audioPumpThreshold = LOW_AUDIO_USECS * 2;
|
||||||
|
|
||||||
// Our local low audio threshold. We may increase this if we're slow to
|
// Our local low audio threshold. We may increase this if we're slow to
|
||||||
// decode video frames, in order to reduce the chance of audio underruns.
|
// decode video frames, in order to reduce the chance of audio underruns.
|
||||||
PRInt64 lowAudioThreshold = LOW_AUDIO_MS;
|
PRInt64 lowAudioThreshold = LOW_AUDIO_USECS;
|
||||||
|
|
||||||
// Our local ample audio threshold. If we increase lowAudioThreshold, we'll
|
// Our local ample audio threshold. If we increase lowAudioThreshold, we'll
|
||||||
// also increase this too appropriately (we don't want lowAudioThreshold to
|
// also increase this too appropriately (we don't want lowAudioThreshold to
|
||||||
// be greater than ampleAudioThreshold, else we'd stop decoding!).
|
// be greater than ampleAudioThreshold, else we'd stop decoding!).
|
||||||
PRInt64 ampleAudioThreshold = AMPLE_AUDIO_MS;
|
PRInt64 ampleAudioThreshold = AMPLE_AUDIO_USECS;
|
||||||
|
|
||||||
MediaQueue<VideoData>& videoQueue = mReader->mVideoQueue;
|
MediaQueue<VideoData>& videoQueue = mReader->mVideoQueue;
|
||||||
MediaQueue<SoundData>& audioQueue = mReader->mAudioQueue;
|
MediaQueue<SoundData>& audioQueue = mReader->mAudioQueue;
|
||||||
|
@ -289,7 +289,7 @@ void nsBuiltinDecoderStateMachine::DecodeLoop()
|
||||||
// We don't want to consider skipping to the next keyframe if we've
|
// We don't want to consider skipping to the next keyframe if we've
|
||||||
// only just started up the decode loop, so wait until we've decoded
|
// only just started up the decode loop, so wait until we've decoded
|
||||||
// some audio data before enabling the keyframe skip logic on audio.
|
// some audio data before enabling the keyframe skip logic on audio.
|
||||||
if (audioPump && GetDecodedAudioDuration() >= audioPumpThresholdMs) {
|
if (audioPump && GetDecodedAudioDuration() >= audioPumpThreshold) {
|
||||||
audioPump = PR_FALSE;
|
audioPump = PR_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -328,11 +328,11 @@ void nsBuiltinDecoderStateMachine::DecodeLoop()
|
||||||
videoPlaying = mReader->DecodeVideoFrame(skipToNextKeyframe, currentTime);
|
videoPlaying = mReader->DecodeVideoFrame(skipToNextKeyframe, currentTime);
|
||||||
decodeTime = TimeStamp::Now() - start;
|
decodeTime = TimeStamp::Now() - start;
|
||||||
}
|
}
|
||||||
if (THRESHOLD_FACTOR * DurationToMs(decodeTime) > lowAudioThreshold &&
|
if (THRESHOLD_FACTOR * DurationToUsecs(decodeTime) > lowAudioThreshold &&
|
||||||
!HasLowUndecodedData())
|
!HasLowUndecodedData())
|
||||||
{
|
{
|
||||||
lowAudioThreshold =
|
lowAudioThreshold =
|
||||||
NS_MIN(THRESHOLD_FACTOR * DurationToMs(decodeTime), AMPLE_AUDIO_MS);
|
NS_MIN(THRESHOLD_FACTOR * DurationToUsecs(decodeTime), AMPLE_AUDIO_USECS);
|
||||||
ampleAudioThreshold = NS_MAX(THRESHOLD_FACTOR * lowAudioThreshold,
|
ampleAudioThreshold = NS_MAX(THRESHOLD_FACTOR * lowAudioThreshold,
|
||||||
ampleAudioThreshold);
|
ampleAudioThreshold);
|
||||||
LOG(PR_LOG_DEBUG,
|
LOG(PR_LOG_DEBUG,
|
||||||
|
@ -474,7 +474,7 @@ void nsBuiltinDecoderStateMachine::AudioLoop()
|
||||||
// Calculate the number of samples that have been pushed onto the audio
|
// Calculate the number of samples that have been pushed onto the audio
|
||||||
// hardware.
|
// hardware.
|
||||||
PRInt64 playedSamples = 0;
|
PRInt64 playedSamples = 0;
|
||||||
if (!MsToSamples(audioStartTime, rate, playedSamples)) {
|
if (!UsecsToSamples(audioStartTime, rate, playedSamples)) {
|
||||||
NS_WARNING("Int overflow converting playedSamples");
|
NS_WARNING("Int overflow converting playedSamples");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -486,7 +486,7 @@ void nsBuiltinDecoderStateMachine::AudioLoop()
|
||||||
// Calculate the timestamp of the next chunk of audio in numbers of
|
// Calculate the timestamp of the next chunk of audio in numbers of
|
||||||
// samples.
|
// samples.
|
||||||
PRInt64 sampleTime = 0;
|
PRInt64 sampleTime = 0;
|
||||||
if (!MsToSamples(s->mTime, rate, sampleTime)) {
|
if (!UsecsToSamples(s->mTime, rate, sampleTime)) {
|
||||||
NS_WARNING("Int overflow converting sampleTime");
|
NS_WARNING("Int overflow converting sampleTime");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -509,18 +509,18 @@ void nsBuiltinDecoderStateMachine::AudioLoop()
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
MonitorAutoEnter mon(mDecoder->GetMonitor());
|
MonitorAutoEnter mon(mDecoder->GetMonitor());
|
||||||
PRInt64 playedMs;
|
PRInt64 playedUsecs;
|
||||||
if (!SamplesToMs(audioDuration, rate, playedMs)) {
|
if (!SamplesToUsecs(audioDuration, rate, playedUsecs)) {
|
||||||
NS_WARNING("Int overflow calculating playedMs");
|
NS_WARNING("Int overflow calculating playedUsecs");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (!AddOverflow(audioStartTime, playedMs, mAudioEndTime)) {
|
if (!AddOverflow(audioStartTime, playedUsecs, mAudioEndTime)) {
|
||||||
NS_WARNING("Int overflow calculating audio end time");
|
NS_WARNING("Int overflow calculating audio end time");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
PRInt64 audioAhead = mAudioEndTime - GetMediaTime();
|
PRInt64 audioAhead = mAudioEndTime - GetMediaTime();
|
||||||
if (audioAhead > AMPLE_AUDIO_MS &&
|
if (audioAhead > AMPLE_AUDIO_USECS &&
|
||||||
audioDuration - samplesAtLastSleep > minWriteSamples)
|
audioDuration - samplesAtLastSleep > minWriteSamples)
|
||||||
{
|
{
|
||||||
samplesAtLastSleep = audioDuration;
|
samplesAtLastSleep = audioDuration;
|
||||||
|
@ -528,7 +528,7 @@ void nsBuiltinDecoderStateMachine::AudioLoop()
|
||||||
// significant amount ahead of the playback position. The decode
|
// significant amount ahead of the playback position. The decode
|
||||||
// thread will be going to sleep, so we won't get any new samples
|
// thread will be going to sleep, so we won't get any new samples
|
||||||
// anyway, so sleep until we need to push to the hardware again.
|
// anyway, so sleep until we need to push to the hardware again.
|
||||||
Wait(AMPLE_AUDIO_MS / 2);
|
Wait(AMPLE_AUDIO_USECS / 2);
|
||||||
// Kick the decode thread; since above we only do a NotifyAll when
|
// Kick the decode thread; since above we only do a NotifyAll when
|
||||||
// we pop an audio chunk of the queue, the decoder won't wake up if
|
// we pop an audio chunk of the queue, the decoder won't wake up if
|
||||||
// we've got no more decoded chunks to push to the hardware. We can
|
// we've got no more decoded chunks to push to the hardware. We can
|
||||||
|
@ -559,8 +559,8 @@ void nsBuiltinDecoderStateMachine::AudioLoop()
|
||||||
mState != DECODER_STATE_SEEKING &&
|
mState != DECODER_STATE_SEEKING &&
|
||||||
mState != DECODER_STATE_SHUTDOWN)
|
mState != DECODER_STATE_SHUTDOWN)
|
||||||
{
|
{
|
||||||
const PRInt64 DRAIN_BLOCK_MS = 100;
|
const PRInt64 DRAIN_BLOCK_USECS = 100000;
|
||||||
Wait(NS_MIN(mAudioEndTime - position, DRAIN_BLOCK_MS));
|
Wait(NS_MIN(mAudioEndTime - position, DRAIN_BLOCK_USECS));
|
||||||
oldPosition = position;
|
oldPosition = position;
|
||||||
position = GetMediaTime();
|
position = GetMediaTime();
|
||||||
}
|
}
|
||||||
|
@ -683,7 +683,7 @@ void nsBuiltinDecoderStateMachine::StopPlayback(eStopMode aMode)
|
||||||
// audio thread can block in the write, and we deadlock trying to acquire
|
// audio thread can block in the write, and we deadlock trying to acquire
|
||||||
// the audio monitor upon resume playback.
|
// the audio monitor upon resume playback.
|
||||||
if (IsPlaying()) {
|
if (IsPlaying()) {
|
||||||
mPlayDuration += TimeStamp::Now() - mPlayStartTime;
|
mPlayDuration += DurationToUsecs(TimeStamp::Now() - mPlayStartTime);
|
||||||
mPlayStartTime = TimeStamp();
|
mPlayStartTime = TimeStamp();
|
||||||
}
|
}
|
||||||
if (HasAudio()) {
|
if (HasAudio()) {
|
||||||
|
@ -799,7 +799,7 @@ double nsBuiltinDecoderStateMachine::GetCurrentTime() const
|
||||||
OnDecodeThread(),
|
OnDecodeThread(),
|
||||||
"Should be on main, decode, or state machine thread.");
|
"Should be on main, decode, or state machine thread.");
|
||||||
|
|
||||||
return static_cast<double>(mCurrentFrameTime) / 1000.0;
|
return static_cast<double>(mCurrentFrameTime) / static_cast<double>(USECS_PER_S);
|
||||||
}
|
}
|
||||||
|
|
||||||
PRInt64 nsBuiltinDecoderStateMachine::GetDuration()
|
PRInt64 nsBuiltinDecoderStateMachine::GetDuration()
|
||||||
|
@ -893,7 +893,7 @@ void nsBuiltinDecoderStateMachine::Seek(double aTime)
|
||||||
"We shouldn't already be seeking");
|
"We shouldn't already be seeking");
|
||||||
NS_ASSERTION(mState >= DECODER_STATE_DECODING,
|
NS_ASSERTION(mState >= DECODER_STATE_DECODING,
|
||||||
"We should have loaded metadata");
|
"We should have loaded metadata");
|
||||||
double t = aTime * 1000.0;
|
double t = aTime * static_cast<double>(USECS_PER_S);
|
||||||
if (t > PR_INT64_MAX) {
|
if (t > PR_INT64_MAX) {
|
||||||
// Prevent integer overflow.
|
// Prevent integer overflow.
|
||||||
return;
|
return;
|
||||||
|
@ -965,10 +965,10 @@ nsBuiltinDecoderStateMachine::StartDecodeThreads()
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
PRInt64 nsBuiltinDecoderStateMachine::AudioDecodedMs() const
|
PRInt64 nsBuiltinDecoderStateMachine::AudioDecodedUsecs() const
|
||||||
{
|
{
|
||||||
NS_ASSERTION(HasAudio(),
|
NS_ASSERTION(HasAudio(),
|
||||||
"Should only call AudioDecodedMs() when we have audio");
|
"Should only call AudioDecodedUsecs() when we have audio");
|
||||||
// The amount of audio we have decoded is the amount of audio data we've
|
// The amount of audio we have decoded is the amount of audio data we've
|
||||||
// already decoded and pushed to the hardware, plus the amount of audio
|
// already decoded and pushed to the hardware, plus the amount of audio
|
||||||
// data waiting to be pushed to the hardware.
|
// data waiting to be pushed to the hardware.
|
||||||
|
@ -976,7 +976,7 @@ PRInt64 nsBuiltinDecoderStateMachine::AudioDecodedMs() const
|
||||||
return pushed + mReader->mAudioQueue.Duration();
|
return pushed + mReader->mAudioQueue.Duration();
|
||||||
}
|
}
|
||||||
|
|
||||||
PRBool nsBuiltinDecoderStateMachine::HasLowDecodedData(PRInt64 aAudioMs) const
|
PRBool nsBuiltinDecoderStateMachine::HasLowDecodedData(PRInt64 aAudioUsecs) const
|
||||||
{
|
{
|
||||||
mDecoder->GetMonitor().AssertCurrentThreadIn();
|
mDecoder->GetMonitor().AssertCurrentThreadIn();
|
||||||
// We consider ourselves low on decoded data if we're low on audio,
|
// We consider ourselves low on decoded data if we're low on audio,
|
||||||
|
@ -985,7 +985,7 @@ PRBool nsBuiltinDecoderStateMachine::HasLowDecodedData(PRInt64 aAudioMs) const
|
||||||
// we've not decoded to the end of the video stream.
|
// we've not decoded to the end of the video stream.
|
||||||
return ((HasAudio() &&
|
return ((HasAudio() &&
|
||||||
!mReader->mAudioQueue.IsFinished() &&
|
!mReader->mAudioQueue.IsFinished() &&
|
||||||
AudioDecodedMs() < aAudioMs)
|
AudioDecodedUsecs() < aAudioUsecs)
|
||||||
||
|
||
|
||||||
(!HasAudio() &&
|
(!HasAudio() &&
|
||||||
HasVideo() &&
|
HasVideo() &&
|
||||||
|
@ -995,7 +995,7 @@ PRBool nsBuiltinDecoderStateMachine::HasLowDecodedData(PRInt64 aAudioMs) const
|
||||||
|
|
||||||
PRBool nsBuiltinDecoderStateMachine::HasLowUndecodedData() const
|
PRBool nsBuiltinDecoderStateMachine::HasLowUndecodedData() const
|
||||||
{
|
{
|
||||||
return GetUndecodedData() < LOW_DATA_THRESHOLD_MS;
|
return GetUndecodedData() < LOW_DATA_THRESHOLD_USECS;
|
||||||
}
|
}
|
||||||
|
|
||||||
PRInt64 nsBuiltinDecoderStateMachine::GetUndecodedData() const
|
PRInt64 nsBuiltinDecoderStateMachine::GetUndecodedData() const
|
||||||
|
@ -1084,7 +1084,7 @@ nsresult nsBuiltinDecoderStateMachine::Run()
|
||||||
!mSeekable || mEndTime != -1,
|
!mSeekable || mEndTime != -1,
|
||||||
"Active seekable media should have end time");
|
"Active seekable media should have end time");
|
||||||
NS_ASSERTION(!mSeekable || GetDuration() != -1, "Seekable media should have duration");
|
NS_ASSERTION(!mSeekable || GetDuration() != -1, "Seekable media should have duration");
|
||||||
LOG(PR_LOG_DEBUG, ("%p Media goes from %lldms to %lldms (duration %lldms) seekable=%d",
|
LOG(PR_LOG_DEBUG, ("%p Media goes from %lld to %lld (duration %lld) seekable=%d",
|
||||||
mDecoder, mStartTime, mEndTime, GetDuration(), mSeekable));
|
mDecoder, mStartTime, mEndTime, GetDuration(), mSeekable));
|
||||||
|
|
||||||
if (mState == DECODER_STATE_SHUTDOWN)
|
if (mState == DECODER_STATE_SHUTDOWN)
|
||||||
|
@ -1187,7 +1187,7 @@ nsresult nsBuiltinDecoderStateMachine::Run()
|
||||||
"Seek target should lie inside the first audio block after seek");
|
"Seek target should lie inside the first audio block after seek");
|
||||||
PRInt64 startTime = (audio && audio->mTime < seekTime) ? audio->mTime : seekTime;
|
PRInt64 startTime = (audio && audio->mTime < seekTime) ? audio->mTime : seekTime;
|
||||||
mAudioStartTime = startTime;
|
mAudioStartTime = startTime;
|
||||||
mPlayDuration = MsToDuration(startTime - mStartTime);
|
mPlayDuration = startTime - mStartTime;
|
||||||
if (HasVideo()) {
|
if (HasVideo()) {
|
||||||
nsAutoPtr<VideoData> video(mReader->mVideoQueue.PeekFront());
|
nsAutoPtr<VideoData> video(mReader->mVideoQueue.PeekFront());
|
||||||
if (video) {
|
if (video) {
|
||||||
|
@ -1220,12 +1220,12 @@ nsresult nsBuiltinDecoderStateMachine::Run()
|
||||||
|
|
||||||
nsCOMPtr<nsIRunnable> stopEvent;
|
nsCOMPtr<nsIRunnable> stopEvent;
|
||||||
if (GetMediaTime() == mEndTime) {
|
if (GetMediaTime() == mEndTime) {
|
||||||
LOG(PR_LOG_DEBUG, ("%p Changed state from SEEKING (to %lldms) to COMPLETED",
|
LOG(PR_LOG_DEBUG, ("%p Changed state from SEEKING (to %lld) to COMPLETED",
|
||||||
mDecoder, seekTime));
|
mDecoder, seekTime));
|
||||||
stopEvent = NS_NewRunnableMethod(mDecoder, &nsBuiltinDecoder::SeekingStoppedAtEnd);
|
stopEvent = NS_NewRunnableMethod(mDecoder, &nsBuiltinDecoder::SeekingStoppedAtEnd);
|
||||||
mState = DECODER_STATE_COMPLETED;
|
mState = DECODER_STATE_COMPLETED;
|
||||||
} else {
|
} else {
|
||||||
LOG(PR_LOG_DEBUG, ("%p Changed state from SEEKING (to %lldms) to DECODING",
|
LOG(PR_LOG_DEBUG, ("%p Changed state from SEEKING (to %lld) to DECODING",
|
||||||
mDecoder, seekTime));
|
mDecoder, seekTime));
|
||||||
stopEvent = NS_NewRunnableMethod(mDecoder, &nsBuiltinDecoder::SeekingStopped);
|
stopEvent = NS_NewRunnableMethod(mDecoder, &nsBuiltinDecoder::SeekingStopped);
|
||||||
StartDecoding();
|
StartDecoding();
|
||||||
|
@ -1261,18 +1261,18 @@ nsresult nsBuiltinDecoderStateMachine::Run()
|
||||||
PRBool isLiveStream = mDecoder->GetCurrentStream()->GetLength() == -1;
|
PRBool isLiveStream = mDecoder->GetCurrentStream()->GetLength() == -1;
|
||||||
if ((isLiveStream || !mDecoder->CanPlayThrough()) &&
|
if ((isLiveStream || !mDecoder->CanPlayThrough()) &&
|
||||||
elapsed < TimeDuration::FromSeconds(BUFFERING_WAIT) &&
|
elapsed < TimeDuration::FromSeconds(BUFFERING_WAIT) &&
|
||||||
(mQuickBuffering ? HasLowDecodedData(QUICK_BUFFERING_LOW_DATA_MS)
|
(mQuickBuffering ? HasLowDecodedData(QUICK_BUFFERING_LOW_DATA_USECS)
|
||||||
: (GetUndecodedData() < BUFFERING_WAIT * 1000)) &&
|
: (GetUndecodedData() < BUFFERING_WAIT * USECS_PER_S)) &&
|
||||||
!stream->IsDataCachedToEndOfStream(mDecoder->mDecoderPosition) &&
|
!stream->IsDataCachedToEndOfStream(mDecoder->mDecoderPosition) &&
|
||||||
!stream->IsSuspended())
|
!stream->IsSuspended())
|
||||||
{
|
{
|
||||||
LOG(PR_LOG_DEBUG,
|
LOG(PR_LOG_DEBUG,
|
||||||
("Buffering: %.3lfs/%ds, timeout in %.3lfs %s",
|
("Buffering: %.3lfs/%ds, timeout in %.3lfs %s",
|
||||||
GetUndecodedData() / 1000.0,
|
GetUndecodedData() / static_cast<double>(USECS_PER_S),
|
||||||
BUFFERING_WAIT,
|
BUFFERING_WAIT,
|
||||||
BUFFERING_WAIT - elapsed.ToSeconds(),
|
BUFFERING_WAIT - elapsed.ToSeconds(),
|
||||||
(mQuickBuffering ? "(quick exit)" : "")));
|
(mQuickBuffering ? "(quick exit)" : "")));
|
||||||
Wait(1000);
|
Wait(USECS_PER_S);
|
||||||
if (mState == DECODER_STATE_SHUTDOWN)
|
if (mState == DECODER_STATE_SHUTDOWN)
|
||||||
continue;
|
continue;
|
||||||
} else {
|
} else {
|
||||||
|
@ -1395,7 +1395,7 @@ void nsBuiltinDecoderStateMachine::AdvanceFrame()
|
||||||
// audio clock. Just wait and then return, to give the audio clock time
|
// audio clock. Just wait and then return, to give the audio clock time
|
||||||
// to tick. This should really wait for a specific signal from the audio
|
// to tick. This should really wait for a specific signal from the audio
|
||||||
// thread rather than polling after a sleep. See bug 568431 comment 4.
|
// thread rather than polling after a sleep. See bug 568431 comment 4.
|
||||||
Wait(AUDIO_DURATION_MS);
|
Wait(AUDIO_DURATION_USECS);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1404,18 +1404,18 @@ void nsBuiltinDecoderStateMachine::AdvanceFrame()
|
||||||
// audio, or don't have audio, use the system clock.
|
// audio, or don't have audio, use the system clock.
|
||||||
PRInt64 clock_time = -1;
|
PRInt64 clock_time = -1;
|
||||||
if (!IsPlaying()) {
|
if (!IsPlaying()) {
|
||||||
clock_time = DurationToMs(mPlayDuration) + mStartTime;
|
clock_time = mPlayDuration + mStartTime;
|
||||||
} else {
|
} else {
|
||||||
PRInt64 audio_time = GetAudioClock();
|
PRInt64 audio_time = GetAudioClock();
|
||||||
if (HasAudio() && !mAudioCompleted && audio_time != -1) {
|
if (HasAudio() && !mAudioCompleted && audio_time != -1) {
|
||||||
clock_time = audio_time;
|
clock_time = audio_time;
|
||||||
// Resync against the audio clock, while we're trusting the
|
// Resync against the audio clock, while we're trusting the
|
||||||
// audio clock. This ensures no "drift", particularly on Linux.
|
// audio clock. This ensures no "drift", particularly on Linux.
|
||||||
mPlayDuration = MsToDuration(clock_time - mStartTime);
|
mPlayDuration = clock_time - mStartTime;
|
||||||
mPlayStartTime = TimeStamp::Now();
|
mPlayStartTime = TimeStamp::Now();
|
||||||
} else {
|
} else {
|
||||||
// Sound is disabled on this system. Sync to the system clock.
|
// Sound is disabled on this system. Sync to the system clock.
|
||||||
clock_time = DurationToMs(TimeStamp::Now() - mPlayStartTime + mPlayDuration);
|
clock_time = DurationToUsecs(TimeStamp::Now() - mPlayStartTime) + mPlayDuration;
|
||||||
// Ensure the clock can never go backwards.
|
// Ensure the clock can never go backwards.
|
||||||
NS_ASSERTION(mCurrentFrameTime <= clock_time, "Clock should go forwards");
|
NS_ASSERTION(mCurrentFrameTime <= clock_time, "Clock should go forwards");
|
||||||
clock_time = NS_MAX(mCurrentFrameTime, clock_time) + mStartTime;
|
clock_time = NS_MAX(mCurrentFrameTime, clock_time) + mStartTime;
|
||||||
|
@ -1424,7 +1424,7 @@ void nsBuiltinDecoderStateMachine::AdvanceFrame()
|
||||||
|
|
||||||
// Skip frames up to the frame at the playback position, and figure out
|
// Skip frames up to the frame at the playback position, and figure out
|
||||||
// the time remaining until it's time to display the next frame.
|
// the time remaining until it's time to display the next frame.
|
||||||
PRInt64 remainingTime = AUDIO_DURATION_MS;
|
PRInt64 remainingTime = AUDIO_DURATION_USECS;
|
||||||
NS_ASSERTION(clock_time >= mStartTime, "Should have positive clock time.");
|
NS_ASSERTION(clock_time >= mStartTime, "Should have positive clock time.");
|
||||||
nsAutoPtr<VideoData> currentFrame;
|
nsAutoPtr<VideoData> currentFrame;
|
||||||
if (mReader->mVideoQueue.GetSize() > 0) {
|
if (mReader->mVideoQueue.GetSize() > 0) {
|
||||||
|
@ -1442,8 +1442,8 @@ void nsBuiltinDecoderStateMachine::AdvanceFrame()
|
||||||
// present the next frame.
|
// present the next frame.
|
||||||
if (frame && !currentFrame) {
|
if (frame && !currentFrame) {
|
||||||
PRInt64 now = IsPlaying()
|
PRInt64 now = IsPlaying()
|
||||||
? DurationToMs(TimeStamp::Now() - mPlayStartTime + mPlayDuration)
|
? (DurationToUsecs(TimeStamp::Now() - mPlayStartTime) + mPlayDuration)
|
||||||
: DurationToMs(mPlayDuration);
|
: mPlayDuration;
|
||||||
remainingTime = frame->mTime - mStartTime - now;
|
remainingTime = frame->mTime - mStartTime - now;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1453,7 +1453,7 @@ void nsBuiltinDecoderStateMachine::AdvanceFrame()
|
||||||
nsMediaStream* stream = mDecoder->GetCurrentStream();
|
nsMediaStream* stream = mDecoder->GetCurrentStream();
|
||||||
if (mState == DECODER_STATE_DECODING &&
|
if (mState == DECODER_STATE_DECODING &&
|
||||||
mDecoder->GetState() == nsBuiltinDecoder::PLAY_STATE_PLAYING &&
|
mDecoder->GetState() == nsBuiltinDecoder::PLAY_STATE_PLAYING &&
|
||||||
HasLowDecodedData(remainingTime + EXHAUSTED_DATA_MARGIN_MS) &&
|
HasLowDecodedData(remainingTime + EXHAUSTED_DATA_MARGIN_USECS) &&
|
||||||
!stream->IsDataCachedToEndOfStream(mDecoder->mDecoderPosition) &&
|
!stream->IsDataCachedToEndOfStream(mDecoder->mDecoderPosition) &&
|
||||||
!stream->IsSuspended() &&
|
!stream->IsSuspended() &&
|
||||||
(JustExitedQuickBuffering() || HasLowUndecodedData()))
|
(JustExitedQuickBuffering() || HasLowUndecodedData()))
|
||||||
|
@ -1474,8 +1474,8 @@ void nsBuiltinDecoderStateMachine::AdvanceFrame()
|
||||||
|
|
||||||
if (currentFrame) {
|
if (currentFrame) {
|
||||||
// Decode one frame and display it.
|
// Decode one frame and display it.
|
||||||
TimeStamp presTime = mPlayStartTime - mPlayDuration +
|
TimeStamp presTime = mPlayStartTime - UsecsToDuration(mPlayDuration) +
|
||||||
MsToDuration(currentFrame->mTime - mStartTime);
|
UsecsToDuration(currentFrame->mTime - mStartTime);
|
||||||
NS_ASSERTION(currentFrame->mTime >= mStartTime, "Should have positive frame time");
|
NS_ASSERTION(currentFrame->mTime >= mStartTime, "Should have positive frame time");
|
||||||
{
|
{
|
||||||
nsIntSize display = mInfo.mDisplay;
|
nsIntSize display = mInfo.mDisplay;
|
||||||
|
@ -1488,7 +1488,7 @@ void nsBuiltinDecoderStateMachine::AdvanceFrame()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mDecoder->GetFrameStatistics().NotifyPresentedFrame();
|
mDecoder->GetFrameStatistics().NotifyPresentedFrame();
|
||||||
PRInt64 now = DurationToMs(TimeStamp::Now() - mPlayStartTime + mPlayDuration);
|
PRInt64 now = DurationToUsecs(TimeStamp::Now() - mPlayStartTime) + mPlayDuration;
|
||||||
remainingTime = currentFrame->mEndTime - mStartTime - now;
|
remainingTime = currentFrame->mEndTime - mStartTime - now;
|
||||||
currentFrame = nsnull;
|
currentFrame = nsnull;
|
||||||
}
|
}
|
||||||
|
@ -1534,9 +1534,9 @@ void nsBuiltinDecoderStateMachine::AdvanceFrame()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void nsBuiltinDecoderStateMachine::Wait(PRInt64 aMs) {
|
void nsBuiltinDecoderStateMachine::Wait(PRInt64 aUsecs) {
|
||||||
mDecoder->GetMonitor().AssertCurrentThreadIn();
|
mDecoder->GetMonitor().AssertCurrentThreadIn();
|
||||||
TimeStamp end = TimeStamp::Now() + MsToDuration(aMs);
|
TimeStamp end = TimeStamp::Now() + UsecsToDuration(aUsecs);
|
||||||
TimeStamp now;
|
TimeStamp now;
|
||||||
while ((now = TimeStamp::Now()) < end &&
|
while ((now = TimeStamp::Now()) < end &&
|
||||||
mState != DECODER_STATE_SHUTDOWN &&
|
mState != DECODER_STATE_SHUTDOWN &&
|
||||||
|
@ -1546,8 +1546,6 @@ void nsBuiltinDecoderStateMachine::Wait(PRInt64 aMs) {
|
||||||
if (ms == 0 || ms > PR_UINT32_MAX) {
|
if (ms == 0 || ms > PR_UINT32_MAX) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
NS_ASSERTION(ms <= aMs && ms > 0,
|
|
||||||
"nsBuiltinDecoderStateMachine::Wait interval very wrong!");
|
|
||||||
mDecoder->GetMonitor().Wait(PR_MillisecondsToInterval(static_cast<PRUint32>(ms)));
|
mDecoder->GetMonitor().Wait(PR_MillisecondsToInterval(static_cast<PRUint32>(ms)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1579,7 +1577,7 @@ VideoData* nsBuiltinDecoderStateMachine::FindStartTime()
|
||||||
// first acutal audio sample we have, we'll inject silence during playback
|
// first acutal audio sample we have, we'll inject silence during playback
|
||||||
// to ensure the audio starts at the correct time.
|
// to ensure the audio starts at the correct time.
|
||||||
mAudioStartTime = mStartTime;
|
mAudioStartTime = mStartTime;
|
||||||
LOG(PR_LOG_DEBUG, ("%p Media start time is %lldms", mDecoder, mStartTime));
|
LOG(PR_LOG_DEBUG, ("%p Media start time is %lld", mDecoder, mStartTime));
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1604,7 +1602,7 @@ void nsBuiltinDecoderStateMachine::FindEndTime()
|
||||||
mEndTime = endTime;
|
mEndTime = endTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG(PR_LOG_DEBUG, ("%p Media end time is %lldms", mDecoder, mEndTime));
|
LOG(PR_LOG_DEBUG, ("%p Media end time is %lld", mDecoder, mEndTime));
|
||||||
}
|
}
|
||||||
|
|
||||||
void nsBuiltinDecoderStateMachine::UpdateReadyState() {
|
void nsBuiltinDecoderStateMachine::UpdateReadyState() {
|
||||||
|
@ -1658,7 +1656,7 @@ PRBool nsBuiltinDecoderStateMachine::JustExitedQuickBuffering()
|
||||||
{
|
{
|
||||||
return !mDecodeStartTime.IsNull() &&
|
return !mDecodeStartTime.IsNull() &&
|
||||||
mQuickBuffering &&
|
mQuickBuffering &&
|
||||||
(TimeStamp::Now() - mDecodeStartTime) < TimeDuration::FromSeconds(QUICK_BUFFER_THRESHOLD_MS);
|
(TimeStamp::Now() - mDecodeStartTime) < TimeDuration::FromSeconds(QUICK_BUFFER_THRESHOLD_USECS);
|
||||||
}
|
}
|
||||||
|
|
||||||
void nsBuiltinDecoderStateMachine::StartBuffering()
|
void nsBuiltinDecoderStateMachine::StartBuffering()
|
||||||
|
@ -1671,7 +1669,7 @@ void nsBuiltinDecoderStateMachine::StartBuffering()
|
||||||
// when the download speed is similar to the decode speed.
|
// when the download speed is similar to the decode speed.
|
||||||
mQuickBuffering =
|
mQuickBuffering =
|
||||||
!JustExitedQuickBuffering() &&
|
!JustExitedQuickBuffering() &&
|
||||||
decodeDuration < TimeDuration::FromMilliseconds(QUICK_BUFFER_THRESHOLD_MS);
|
decodeDuration < UsecsToDuration(QUICK_BUFFER_THRESHOLD_USECS);
|
||||||
mBufferingStart = TimeStamp::Now();
|
mBufferingStart = TimeStamp::Now();
|
||||||
|
|
||||||
// We need to tell the element that buffering has started.
|
// We need to tell the element that buffering has started.
|
||||||
|
|
|
@ -253,23 +253,23 @@ public:
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
// Returns PR_TRUE if we'v got less than aAudioMs ms of decoded and playable
|
// Returns PR_TRUE if we've got less than aAudioUsecs microseconds of decoded
|
||||||
// data. The decoder monitor must be held.
|
// and playable data. The decoder monitor must be held.
|
||||||
PRBool HasLowDecodedData(PRInt64 aAudioMs) const;
|
PRBool HasLowDecodedData(PRInt64 aAudioUsecs) const;
|
||||||
|
|
||||||
// Returns PR_TRUE if we're running low on data which is not yet decoded.
|
// Returns PR_TRUE if we're running low on data which is not yet decoded.
|
||||||
// The decoder monitor must be held.
|
// The decoder monitor must be held.
|
||||||
PRBool HasLowUndecodedData() const;
|
PRBool HasLowUndecodedData() const;
|
||||||
|
|
||||||
// Returns the number of milliseconds of undecoded data available for
|
// Returns the number of microseconds of undecoded data available for
|
||||||
// decoding. The decoder monitor must be held.
|
// decoding. The decoder monitor must be held.
|
||||||
PRInt64 GetUndecodedData() const;
|
PRInt64 GetUndecodedData() const;
|
||||||
|
|
||||||
// Returns the number of unplayed ms of audio we've got decoded and/or
|
// Returns the number of unplayed usecs of audio we've got decoded and/or
|
||||||
// pushed to the hardware waiting to play. This is how much audio we can
|
// pushed to the hardware waiting to play. This is how much audio we can
|
||||||
// play without having to run the audio decoder. The decoder monitor
|
// play without having to run the audio decoder. The decoder monitor
|
||||||
// must be held.
|
// must be held.
|
||||||
PRInt64 AudioDecodedMs() const;
|
PRInt64 AudioDecodedUsecs() const;
|
||||||
|
|
||||||
// Returns PR_TRUE when there's decoded audio waiting to play.
|
// Returns PR_TRUE when there's decoded audio waiting to play.
|
||||||
// The decoder monitor must be held.
|
// The decoder monitor must be held.
|
||||||
|
@ -278,13 +278,13 @@ protected:
|
||||||
// Returns PR_TRUE if we recently exited "quick buffering" mode.
|
// Returns PR_TRUE if we recently exited "quick buffering" mode.
|
||||||
PRBool JustExitedQuickBuffering();
|
PRBool JustExitedQuickBuffering();
|
||||||
|
|
||||||
// Waits on the decoder Monitor for aMs. If the decoder monitor is awoken
|
// Waits on the decoder Monitor for aUsecs microseconds. If the decoder
|
||||||
// by a Notify() call, we'll continue waiting, unless we've moved into
|
// monitor is awoken by a Notify() call, we'll continue waiting, unless
|
||||||
// shutdown state. This enables us to ensure that we wait for a specified
|
// we've moved into shutdown state. This enables us to ensure that we
|
||||||
// time, and that the myriad of Notify()s we do an the decoder monitor
|
// wait for a specified time, and that the myriad of Notify()s we do an
|
||||||
// don't cause the audio thread to be starved. The decoder monitor must
|
// the decoder monitor don't cause the audio thread to be starved. The
|
||||||
// be locked.
|
// decoder monitor must be locked.
|
||||||
void Wait(PRInt64 aMs);
|
void Wait(PRInt64 aUsecs);
|
||||||
|
|
||||||
// Dispatches an asynchronous event to update the media element's ready state.
|
// Dispatches an asynchronous event to update the media element's ready state.
|
||||||
void UpdateReadyState();
|
void UpdateReadyState();
|
||||||
|
@ -334,7 +334,8 @@ protected:
|
||||||
// hardware. This ensures that the playback position advances smoothly, and
|
// hardware. This ensures that the playback position advances smoothly, and
|
||||||
// guarantees that we don't try to allocate an impossibly large chunk of
|
// guarantees that we don't try to allocate an impossibly large chunk of
|
||||||
// memory in order to play back silence. Called on the audio thread.
|
// memory in order to play back silence. Called on the audio thread.
|
||||||
PRUint32 PlaySilence(PRUint32 aSamples, PRUint32 aChannels,
|
PRUint32 PlaySilence(PRUint32 aSamples,
|
||||||
|
PRUint32 aChannels,
|
||||||
PRUint64 aSampleOffset);
|
PRUint64 aSampleOffset);
|
||||||
|
|
||||||
// Pops an audio chunk from the front of the audio queue, and pushes its
|
// Pops an audio chunk from the front of the audio queue, and pushes its
|
||||||
|
@ -392,9 +393,9 @@ protected:
|
||||||
return mStartTime + mCurrentFrameTime;
|
return mStartTime + mCurrentFrameTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns an upper bound on the number of milliseconds of audio that is
|
// Returns an upper bound on the number of microseconds of audio that is
|
||||||
// decoded and playable. This is the sum of the number of ms of audio which
|
// decoded and playable. This is the sum of the number of usecs of audio which
|
||||||
// is decoded and in the reader's audio queue, and the ms of unplayed audio
|
// is decoded and in the reader's audio queue, and the usecs of unplayed audio
|
||||||
// which has been pushed to the audio hardware for playback. Note that after
|
// which has been pushed to the audio hardware for playback. Note that after
|
||||||
// calling this, the audio hardware may play some of the audio pushed to
|
// calling this, the audio hardware may play some of the audio pushed to
|
||||||
// hardware, so this can only be used as a upper bound. The decoder monitor
|
// hardware, so this can only be used as a upper bound. The decoder monitor
|
||||||
|
@ -430,25 +431,25 @@ protected:
|
||||||
// playback position is therefore |Now() - mPlayStartTime +
|
// playback position is therefore |Now() - mPlayStartTime +
|
||||||
// mPlayDuration|, which must be adjusted by mStartTime if used with media
|
// mPlayDuration|, which must be adjusted by mStartTime if used with media
|
||||||
// timestamps. Accessed only via the state machine thread.
|
// timestamps. Accessed only via the state machine thread.
|
||||||
TimeDuration mPlayDuration;
|
PRInt64 mPlayDuration;
|
||||||
|
|
||||||
// Time that buffering started. Used for buffering timeout and only
|
// Time that buffering started. Used for buffering timeout and only
|
||||||
// accessed on the state machine thread. This is null while we're not
|
// accessed on the state machine thread. This is null while we're not
|
||||||
// buffering.
|
// buffering.
|
||||||
TimeStamp mBufferingStart;
|
TimeStamp mBufferingStart;
|
||||||
|
|
||||||
// Start time of the media, in milliseconds. This is the presentation
|
// Start time of the media, in microseconds. This is the presentation
|
||||||
// time of the first sample decoded from the media, and is used to calculate
|
// time of the first sample decoded from the media, and is used to calculate
|
||||||
// duration and as a bounds for seeking. Accessed on state machine and
|
// duration and as a bounds for seeking. Accessed on state machine and
|
||||||
// main thread. Access controlled by decoder monitor.
|
// main thread. Access controlled by decoder monitor.
|
||||||
PRInt64 mStartTime;
|
PRInt64 mStartTime;
|
||||||
|
|
||||||
// Time of the last page in the media, in milliseconds. This is the
|
// Time of the last page in the media, in microseconds. This is the
|
||||||
// end time of the last sample in the media. Accessed on state
|
// end time of the last sample in the media. Accessed on state
|
||||||
// machine and main thread. Access controlled by decoder monitor.
|
// machine and main thread. Access controlled by decoder monitor.
|
||||||
PRInt64 mEndTime;
|
PRInt64 mEndTime;
|
||||||
|
|
||||||
// Position to seek to in milliseconds when the seek state transition occurs.
|
// Position to seek to in microseconds when the seek state transition occurs.
|
||||||
// The decoder monitor lock must be obtained before reading or writing
|
// The decoder monitor lock must be obtained before reading or writing
|
||||||
// this value. Accessed on main and state machine thread.
|
// this value. Accessed on main and state machine thread.
|
||||||
PRInt64 mSeekTime;
|
PRInt64 mSeekTime;
|
||||||
|
@ -463,24 +464,25 @@ protected:
|
||||||
// in the play state machine's destructor.
|
// in the play state machine's destructor.
|
||||||
nsAutoPtr<nsBuiltinDecoderReader> mReader;
|
nsAutoPtr<nsBuiltinDecoderReader> mReader;
|
||||||
|
|
||||||
// The time of the current frame in milliseconds. This is referenced from
|
// The time of the current frame in microseconds. This is referenced from
|
||||||
// 0 which is the initial playback position. Set by the state machine
|
// 0 which is the initial playback position. Set by the state machine
|
||||||
// thread, and read-only from the main thread to get the current
|
// thread, and read-only from the main thread to get the current
|
||||||
// time value. Synchronised via decoder monitor.
|
// time value. Synchronised via decoder monitor.
|
||||||
PRInt64 mCurrentFrameTime;
|
PRInt64 mCurrentFrameTime;
|
||||||
|
|
||||||
// The presentation time of the first audio sample that was played. We can
|
// The presentation time of the first audio sample that was played in
|
||||||
// add this to the audio stream position to determine the current audio time.
|
// microseconds. We can add this to the audio stream position to determine
|
||||||
// Accessed on audio and state machine thread. Synchronized by decoder monitor.
|
// the current audio time. Accessed on audio and state machine thread.
|
||||||
|
// Synchronized by decoder monitor.
|
||||||
PRInt64 mAudioStartTime;
|
PRInt64 mAudioStartTime;
|
||||||
|
|
||||||
// The end time of the last audio sample that's been pushed onto the audio
|
// The end time of the last audio sample that's been pushed onto the audio
|
||||||
// hardware. This will approximately be the end time of the audio stream,
|
// hardware in microseconds. This will approximately be the end time of the
|
||||||
// unless another sample is pushed to the hardware.
|
// audio stream, unless another sample is pushed to the hardware.
|
||||||
PRInt64 mAudioEndTime;
|
PRInt64 mAudioEndTime;
|
||||||
|
|
||||||
// The presentation end time of the last video frame which has been displayed.
|
// The presentation end time of the last video frame which has been displayed
|
||||||
// Accessed from the state machine thread.
|
// in microseconds. Accessed from the state machine thread.
|
||||||
PRInt64 mVideoFrameEndTime;
|
PRInt64 mVideoFrameEndTime;
|
||||||
|
|
||||||
// Volume of playback. 0.0 = muted. 1.0 = full volume. Read/Written
|
// Volume of playback. 0.0 = muted. 1.0 = full volume. Read/Written
|
||||||
|
|
|
@ -740,7 +740,7 @@ static PRInt32 GetMaxBlocks()
|
||||||
// to the pref are applied.
|
// to the pref are applied.
|
||||||
// Cache size is in KB
|
// Cache size is in KB
|
||||||
PRInt32 cacheSize = nsContentUtils::GetIntPref("media.cache_size", 500*1024);
|
PRInt32 cacheSize = nsContentUtils::GetIntPref("media.cache_size", 500*1024);
|
||||||
PRInt64 maxBlocks = PRInt64(cacheSize)*1024/nsMediaCache::BLOCK_SIZE;
|
PRInt64 maxBlocks = static_cast<PRInt64>(cacheSize)*1024/nsMediaCache::BLOCK_SIZE;
|
||||||
maxBlocks = PR_MAX(maxBlocks, 1);
|
maxBlocks = PR_MAX(maxBlocks, 1);
|
||||||
return PRInt32(PR_MIN(maxBlocks, PR_INT32_MAX));
|
return PRInt32(PR_MIN(maxBlocks, PR_INT32_MAX));
|
||||||
}
|
}
|
||||||
|
@ -1032,7 +1032,7 @@ nsMediaCache::PredictNextUse(TimeStamp aNow, PRInt32 aBlock)
|
||||||
case PLAYED_BLOCK:
|
case PLAYED_BLOCK:
|
||||||
// This block should be managed in LRU mode, and we should impose
|
// This block should be managed in LRU mode, and we should impose
|
||||||
// a "replay delay" to reflect the likelihood of replay happening
|
// a "replay delay" to reflect the likelihood of replay happening
|
||||||
NS_ASSERTION(PRInt64(bo->mStreamBlock)*BLOCK_SIZE <
|
NS_ASSERTION(static_cast<PRInt64>(bo->mStreamBlock)*BLOCK_SIZE <
|
||||||
bo->mStream->mStreamOffset,
|
bo->mStream->mStreamOffset,
|
||||||
"Played block after the current stream position?");
|
"Played block after the current stream position?");
|
||||||
prediction = aNow - bo->mLastUseTime +
|
prediction = aNow - bo->mLastUseTime +
|
||||||
|
@ -1040,7 +1040,7 @@ nsMediaCache::PredictNextUse(TimeStamp aNow, PRInt32 aBlock)
|
||||||
break;
|
break;
|
||||||
case READAHEAD_BLOCK: {
|
case READAHEAD_BLOCK: {
|
||||||
PRInt64 bytesAhead =
|
PRInt64 bytesAhead =
|
||||||
PRInt64(bo->mStreamBlock)*BLOCK_SIZE - bo->mStream->mStreamOffset;
|
static_cast<PRInt64>(bo->mStreamBlock)*BLOCK_SIZE - bo->mStream->mStreamOffset;
|
||||||
NS_ASSERTION(bytesAhead >= 0,
|
NS_ASSERTION(bytesAhead >= 0,
|
||||||
"Readahead block before the current stream position?");
|
"Readahead block before the current stream position?");
|
||||||
PRInt64 millisecondsAhead =
|
PRInt64 millisecondsAhead =
|
||||||
|
|
|
@ -282,10 +282,10 @@ public:
|
||||||
// Return the frame decode/paint related statistics.
|
// Return the frame decode/paint related statistics.
|
||||||
FrameStatistics& GetFrameStatistics() { return mFrameStats; }
|
FrameStatistics& GetFrameStatistics() { return mFrameStats; }
|
||||||
|
|
||||||
// Set the duration of the media resource in units of milliseconds.
|
// Set the duration of the media resource in units of seconds.
|
||||||
// This is called via a channel listener if it can pick up the duration
|
// This is called via a channel listener if it can pick up the duration
|
||||||
// from a content header. Must be called from the main thread only.
|
// from a content header. Must be called from the main thread only.
|
||||||
virtual void SetDuration(PRInt64 aDuration) = 0;
|
virtual void SetDuration(double aDuration) = 0;
|
||||||
|
|
||||||
// Set a flag indicating whether seeking is supported
|
// Set a flag indicating whether seeking is supported
|
||||||
virtual void SetSeekable(PRBool aSeekable) = 0;
|
virtual void SetSeekable(PRBool aSeekable) = 0;
|
||||||
|
|
|
@ -222,7 +222,7 @@ nsMediaChannelStream::OnStartRequest(nsIRequest* aRequest)
|
||||||
if (NS_SUCCEEDED(rv)) {
|
if (NS_SUCCEEDED(rv)) {
|
||||||
double duration = durationText.ToDouble(&ec);
|
double duration = durationText.ToDouble(&ec);
|
||||||
if (ec == NS_OK && duration >= 0) {
|
if (ec == NS_OK && duration >= 0) {
|
||||||
mDecoder->SetDuration(PRInt64(NS_round(duration*1000)));
|
mDecoder->SetDuration(duration);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1004,7 +1004,7 @@ nsresult nsMediaFileStream::Open(nsIStreamListener** aStreamListener)
|
||||||
*aStreamListener = nsnull;
|
*aStreamListener = nsnull;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult rv;
|
nsresult rv = NS_OK;
|
||||||
if (aStreamListener) {
|
if (aStreamListener) {
|
||||||
// The channel is already open. We need a synchronous stream that
|
// The channel is already open. We need a synchronous stream that
|
||||||
// implements nsISeekableStream, so we have to find the underlying
|
// implements nsISeekableStream, so we have to find the underlying
|
||||||
|
|
|
@ -107,7 +107,7 @@ public:
|
||||||
*aReliable = seconds >= 1.0;
|
*aReliable = seconds >= 1.0;
|
||||||
if (seconds <= 0.0)
|
if (seconds <= 0.0)
|
||||||
return 0.0;
|
return 0.0;
|
||||||
return double(mAccumulatedBytes)/seconds;
|
return static_cast<double>(mAccumulatedBytes)/seconds;
|
||||||
}
|
}
|
||||||
double GetRate(TimeStamp aNow, PRPackedBool* aReliable) {
|
double GetRate(TimeStamp aNow, PRPackedBool* aReliable) {
|
||||||
TimeDuration time = mAccumulatedTime;
|
TimeDuration time = mAccumulatedTime;
|
||||||
|
@ -118,7 +118,7 @@ public:
|
||||||
*aReliable = seconds >= 3.0;
|
*aReliable = seconds >= 3.0;
|
||||||
if (seconds <= 0.0)
|
if (seconds <= 0.0)
|
||||||
return 0.0;
|
return 0.0;
|
||||||
return double(mAccumulatedBytes)/seconds;
|
return static_cast<double>(mAccumulatedBytes)/seconds;
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
PRInt64 mAccumulatedBytes;
|
PRInt64 mAccumulatedBytes;
|
||||||
|
|
|
@ -126,7 +126,6 @@ nsTheoraState::nsTheoraState(ogg_page* aBosPage) :
|
||||||
nsOggCodecState(aBosPage),
|
nsOggCodecState(aBosPage),
|
||||||
mSetup(0),
|
mSetup(0),
|
||||||
mCtx(0),
|
mCtx(0),
|
||||||
mFrameDuration(0),
|
|
||||||
mPixelAspectRatio(0)
|
mPixelAspectRatio(0)
|
||||||
{
|
{
|
||||||
MOZ_COUNT_CTOR(nsTheoraState);
|
MOZ_COUNT_CTOR(nsTheoraState);
|
||||||
|
@ -146,22 +145,9 @@ PRBool nsTheoraState::Init() {
|
||||||
if (!mActive)
|
if (!mActive)
|
||||||
return PR_FALSE;
|
return PR_FALSE;
|
||||||
|
|
||||||
PRInt64 n = mInfo.fps_numerator;
|
PRInt64 n = mInfo.aspect_numerator;
|
||||||
PRInt64 d = mInfo.fps_denominator;
|
PRInt64 d = mInfo.aspect_denominator;
|
||||||
|
|
||||||
PRInt64 f;
|
|
||||||
if (!MulOverflow(1000, d, f)) {
|
|
||||||
return mActive = PR_FALSE;
|
|
||||||
}
|
|
||||||
f /= n;
|
|
||||||
if (f > PR_UINT32_MAX) {
|
|
||||||
return mActive = PR_FALSE;
|
|
||||||
}
|
|
||||||
mFrameDuration = static_cast<PRUint32>(f);
|
|
||||||
|
|
||||||
n = mInfo.aspect_numerator;
|
|
||||||
|
|
||||||
d = mInfo.aspect_denominator;
|
|
||||||
mPixelAspectRatio = (n == 0 || d == 0) ?
|
mPixelAspectRatio = (n == 0 || d == 0) ?
|
||||||
1.0f : static_cast<float>(n) / static_cast<float>(d);
|
1.0f : static_cast<float>(n) / static_cast<float>(d);
|
||||||
|
|
||||||
|
@ -244,7 +230,7 @@ PRInt64 nsTheoraState::Time(th_info* aInfo, PRInt64 aGranulepos)
|
||||||
PRInt64 frameno = iframe + pframe - TH_VERSION_CHECK(aInfo, 3, 2, 1);
|
PRInt64 frameno = iframe + pframe - TH_VERSION_CHECK(aInfo, 3, 2, 1);
|
||||||
if (!AddOverflow(frameno, 1, t))
|
if (!AddOverflow(frameno, 1, t))
|
||||||
return -1;
|
return -1;
|
||||||
if (!MulOverflow(t, 1000, t))
|
if (!MulOverflow(t, USECS_PER_S, t))
|
||||||
return -1;
|
return -1;
|
||||||
if (!MulOverflow(t, aInfo->fps_denominator, t))
|
if (!MulOverflow(t, aInfo->fps_denominator, t))
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -257,7 +243,7 @@ PRInt64 nsTheoraState::StartTime(PRInt64 granulepos) {
|
||||||
}
|
}
|
||||||
PRInt64 t = 0;
|
PRInt64 t = 0;
|
||||||
PRInt64 frameno = th_granule_frame(mCtx, granulepos);
|
PRInt64 frameno = th_granule_frame(mCtx, granulepos);
|
||||||
if (!MulOverflow(frameno, 1000, t))
|
if (!MulOverflow(frameno, USECS_PER_S, t))
|
||||||
return -1;
|
return -1;
|
||||||
if (!MulOverflow(t, mInfo.fps_denominator, t))
|
if (!MulOverflow(t, mInfo.fps_denominator, t))
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -267,25 +253,22 @@ PRInt64 nsTheoraState::StartTime(PRInt64 granulepos) {
|
||||||
PRInt64
|
PRInt64
|
||||||
nsTheoraState::MaxKeyframeOffset()
|
nsTheoraState::MaxKeyframeOffset()
|
||||||
{
|
{
|
||||||
// Determine the maximum time in milliseconds by which a key frame could
|
// Determine the maximum time in microseconds by which a key frame could
|
||||||
// offset for the theora bitstream. Theora granulepos encode time as:
|
// offset for the theora bitstream. Theora granulepos encode time as:
|
||||||
// ((key_frame_number << granule_shift) + frame_offset).
|
// ((key_frame_number << granule_shift) + frame_offset).
|
||||||
// Therefore the maximum possible time by which any frame could be offset
|
// Therefore the maximum possible time by which any frame could be offset
|
||||||
// from a keyframe is the duration of (1 << granule_shift) - 1) frames.
|
// from a keyframe is the duration of (1 << granule_shift) - 1) frames.
|
||||||
PRInt64 frameDuration;
|
PRInt64 frameDuration;
|
||||||
PRInt64 keyframeDiff;
|
|
||||||
|
|
||||||
PRInt64 shift = mInfo.keyframe_granule_shift;
|
|
||||||
|
|
||||||
// Max number of frames keyframe could possibly be offset.
|
// Max number of frames keyframe could possibly be offset.
|
||||||
keyframeDiff = (1 << shift) - 1;
|
PRInt64 keyframeDiff = (1 << mInfo.keyframe_granule_shift) - 1;
|
||||||
|
|
||||||
// Length of frame in ms.
|
// Length of frame in usecs.
|
||||||
PRInt64 d = 0; // d will be 0 if multiplication overflows.
|
PRInt64 d = 0; // d will be 0 if multiplication overflows.
|
||||||
MulOverflow(1000, mInfo.fps_denominator, d);
|
MulOverflow(USECS_PER_S, mInfo.fps_denominator, d);
|
||||||
frameDuration = d / mInfo.fps_numerator;
|
frameDuration = d / mInfo.fps_numerator;
|
||||||
|
|
||||||
// Total time in ms keyframe can be offset from any given frame.
|
// Total time in usecs keyframe can be offset from any given frame.
|
||||||
return frameDuration * keyframeDiff;
|
return frameDuration * keyframeDiff;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -390,7 +373,7 @@ PRInt64 nsVorbisState::Time(vorbis_info* aInfo, PRInt64 aGranulepos)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
PRInt64 t = 0;
|
PRInt64 t = 0;
|
||||||
MulOverflow(1000, aGranulepos, t);
|
MulOverflow(USECS_PER_S, aGranulepos, t);
|
||||||
return t / aInfo->rate;
|
return t / aInfo->rate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -522,7 +505,7 @@ PRBool nsSkeletonState::DecodeIndex(ogg_packet* aPacket)
|
||||||
// Extract the start time.
|
// Extract the start time.
|
||||||
n = LEInt64(p + INDEX_FIRST_NUMER_OFFSET);
|
n = LEInt64(p + INDEX_FIRST_NUMER_OFFSET);
|
||||||
PRInt64 t;
|
PRInt64 t;
|
||||||
if (!MulOverflow(n, 1000, t)) {
|
if (!MulOverflow(n, USECS_PER_S, t)) {
|
||||||
return (mActive = PR_FALSE);
|
return (mActive = PR_FALSE);
|
||||||
} else {
|
} else {
|
||||||
startTime = t / timeDenom;
|
startTime = t / timeDenom;
|
||||||
|
@ -530,7 +513,7 @@ PRBool nsSkeletonState::DecodeIndex(ogg_packet* aPacket)
|
||||||
|
|
||||||
// Extract the end time.
|
// Extract the end time.
|
||||||
n = LEInt64(p + INDEX_LAST_NUMER_OFFSET);
|
n = LEInt64(p + INDEX_LAST_NUMER_OFFSET);
|
||||||
if (!MulOverflow(n, 1000, t)) {
|
if (!MulOverflow(n, USECS_PER_S, t)) {
|
||||||
return (mActive = PR_FALSE);
|
return (mActive = PR_FALSE);
|
||||||
} else {
|
} else {
|
||||||
endTime = t / timeDenom;
|
endTime = t / timeDenom;
|
||||||
|
@ -590,11 +573,11 @@ PRBool nsSkeletonState::DecodeIndex(ogg_packet* aPacket)
|
||||||
{
|
{
|
||||||
return (mActive = PR_FALSE);
|
return (mActive = PR_FALSE);
|
||||||
}
|
}
|
||||||
PRInt64 timeMs = 0;
|
PRInt64 timeUsecs = 0;
|
||||||
if (!MulOverflow(time, 1000, timeMs))
|
if (!MulOverflow(time, USECS_PER_S, timeUsecs))
|
||||||
return mActive = PR_FALSE;
|
return mActive = PR_FALSE;
|
||||||
timeMs /= timeDenom;
|
timeUsecs /= timeDenom;
|
||||||
keyPoints->Add(offset, timeMs);
|
keyPoints->Add(offset, timeUsecs);
|
||||||
numKeyPointsRead++;
|
numKeyPointsRead++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -713,7 +696,7 @@ PRBool nsSkeletonState::DecodeHeader(ogg_packet* aPacket)
|
||||||
// presentation time exists in all versions.
|
// presentation time exists in all versions.
|
||||||
PRInt64 n = LEInt64(aPacket->packet + SKELETON_PRESENTATION_TIME_NUMERATOR_OFFSET);
|
PRInt64 n = LEInt64(aPacket->packet + SKELETON_PRESENTATION_TIME_NUMERATOR_OFFSET);
|
||||||
PRInt64 d = LEInt64(aPacket->packet + SKELETON_PRESENTATION_TIME_DENOMINATOR_OFFSET);
|
PRInt64 d = LEInt64(aPacket->packet + SKELETON_PRESENTATION_TIME_DENOMINATOR_OFFSET);
|
||||||
mPresentationTime = d == 0 ? 0 : (static_cast<float>(n) / static_cast<float>(d)) * 1000;
|
mPresentationTime = d == 0 ? 0 : (static_cast<float>(n) / static_cast<float>(d)) * USECS_PER_S;
|
||||||
|
|
||||||
mVersion = SKELETON_VERSION(verMajor, verMinor);
|
mVersion = SKELETON_VERSION(verMajor, verMinor);
|
||||||
if (mVersion < SKELETON_VERSION(4,0) ||
|
if (mVersion < SKELETON_VERSION(4,0) ||
|
||||||
|
|
|
@ -183,7 +183,7 @@ public:
|
||||||
virtual PRInt64 StartTime(PRInt64 granulepos);
|
virtual PRInt64 StartTime(PRInt64 granulepos);
|
||||||
virtual PRBool Init();
|
virtual PRBool Init();
|
||||||
|
|
||||||
// Returns the maximum number of milliseconds which a keyframe can be offset
|
// Returns the maximum number of microseconds which a keyframe can be offset
|
||||||
// from any given interframe.
|
// from any given interframe.
|
||||||
PRInt64 MaxKeyframeOffset();
|
PRInt64 MaxKeyframeOffset();
|
||||||
|
|
||||||
|
@ -195,9 +195,6 @@ public:
|
||||||
th_setup_info *mSetup;
|
th_setup_info *mSetup;
|
||||||
th_dec_ctx* mCtx;
|
th_dec_ctx* mCtx;
|
||||||
|
|
||||||
// Frame duration in ms.
|
|
||||||
PRUint32 mFrameDuration;
|
|
||||||
|
|
||||||
float mPixelAspectRatio;
|
float mPixelAspectRatio;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -233,7 +230,7 @@ public:
|
||||||
// Offset from start of segment/link-in-the-chain in bytes.
|
// Offset from start of segment/link-in-the-chain in bytes.
|
||||||
PRInt64 mOffset;
|
PRInt64 mOffset;
|
||||||
|
|
||||||
// Presentation time in ms.
|
// Presentation time in usecs.
|
||||||
PRInt64 mTime;
|
PRInt64 mTime;
|
||||||
|
|
||||||
PRBool IsNull() {
|
PRBool IsNull() {
|
||||||
|
@ -320,10 +317,10 @@ private:
|
||||||
return mKeyPoints.Length();
|
return mKeyPoints.Length();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Presentation time of the first sample in this stream in ms.
|
// Presentation time of the first sample in this stream in usecs.
|
||||||
const PRInt64 mStartTime;
|
const PRInt64 mStartTime;
|
||||||
|
|
||||||
// End time of the last sample in this stream in ms.
|
// End time of the last sample in this stream in usecs.
|
||||||
const PRInt64 mEndTime;
|
const PRInt64 mEndTime;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -68,15 +68,15 @@ extern PRLogModuleInfo* gBuiltinDecoderLog;
|
||||||
// position, we'll just decode forwards rather than performing a bisection
|
// position, we'll just decode forwards rather than performing a bisection
|
||||||
// search. If we have Theora video we use the maximum keyframe interval as
|
// search. If we have Theora video we use the maximum keyframe interval as
|
||||||
// this value, rather than SEEK_DECODE_MARGIN. This makes small seeks faster.
|
// this value, rather than SEEK_DECODE_MARGIN. This makes small seeks faster.
|
||||||
#define SEEK_DECODE_MARGIN 2000
|
#define SEEK_DECODE_MARGIN 2000000
|
||||||
|
|
||||||
// The number of milliseconds of "fuzz" we use in a bisection search over
|
// The number of microseconds of "fuzz" we use in a bisection search over
|
||||||
// HTTP. When we're seeking with fuzz, we'll stop the search if a bisection
|
// HTTP. When we're seeking with fuzz, we'll stop the search if a bisection
|
||||||
// lands between the seek target and SEEK_FUZZ_MS milliseconds before the
|
// lands between the seek target and SEEK_FUZZ_USECS microseconds before the
|
||||||
// seek target. This is becaue it's usually quicker to just keep downloading
|
// seek target. This is becaue it's usually quicker to just keep downloading
|
||||||
// from an exisiting connection than to do another bisection inside that
|
// from an exisiting connection than to do another bisection inside that
|
||||||
// small range, which would open a new HTTP connetion.
|
// small range, which would open a new HTTP connetion.
|
||||||
#define SEEK_FUZZ_MS 500
|
#define SEEK_FUZZ_USECS 500000
|
||||||
|
|
||||||
enum PageSyncResult {
|
enum PageSyncResult {
|
||||||
PAGE_SYNC_ERROR = 1,
|
PAGE_SYNC_ERROR = 1,
|
||||||
|
@ -390,8 +390,7 @@ nsresult nsOggReader::DecodeVorbis(nsTArray<nsAutoPtr<SoundData> >& aChunks,
|
||||||
}
|
}
|
||||||
|
|
||||||
PRInt64 duration = mVorbisState->Time((PRInt64)samples);
|
PRInt64 duration = mVorbisState->Time((PRInt64)samples);
|
||||||
PRInt64 startTime = (mVorbisGranulepos != -1) ?
|
PRInt64 startTime = mVorbisState->Time(mVorbisGranulepos);
|
||||||
mVorbisState->Time(mVorbisGranulepos) : -1;
|
|
||||||
SoundData* s = new SoundData(mPageOffset,
|
SoundData* s = new SoundData(mPageOffset,
|
||||||
startTime,
|
startTime,
|
||||||
duration,
|
duration,
|
||||||
|
@ -544,9 +543,8 @@ nsresult nsOggReader::DecodeTheora(nsTArray<nsAutoPtr<VideoData> >& aFrames,
|
||||||
if (ret != 0 && ret != TH_DUPFRAME) {
|
if (ret != 0 && ret != TH_DUPFRAME) {
|
||||||
return NS_ERROR_FAILURE;
|
return NS_ERROR_FAILURE;
|
||||||
}
|
}
|
||||||
PRInt64 time = (aPacket->granulepos != -1)
|
PRInt64 time = mTheoraState->StartTime(aPacket->granulepos);
|
||||||
? mTheoraState->StartTime(aPacket->granulepos) : -1;
|
PRInt64 endTime = mTheoraState->Time(aPacket->granulepos);
|
||||||
PRInt64 endTime = time != -1 ? time + mTheoraState->mFrameDuration : -1;
|
|
||||||
if (ret == TH_DUPFRAME) {
|
if (ret == TH_DUPFRAME) {
|
||||||
VideoData* v = VideoData::CreateDuplicate(mPageOffset,
|
VideoData* v = VideoData::CreateDuplicate(mPageOffset,
|
||||||
time,
|
time,
|
||||||
|
@ -704,7 +702,7 @@ PRBool nsOggReader::DecodeVideoFrame(PRBool &aKeyframeSkip,
|
||||||
"Granulepos calculation is incorrect!");
|
"Granulepos calculation is incorrect!");
|
||||||
|
|
||||||
frames[i]->mTime = mTheoraState->StartTime(granulepos);
|
frames[i]->mTime = mTheoraState->StartTime(granulepos);
|
||||||
frames[i]->mEndTime = frames[i]->mTime + mTheoraState->mFrameDuration;
|
frames[i]->mEndTime = mTheoraState->Time(granulepos);
|
||||||
NS_ASSERTION(frames[i]->mEndTime >= frames[i]->mTime, "Frame must start before it ends.");
|
NS_ASSERTION(frames[i]->mEndTime >= frames[i]->mTime, "Frame must start before it ends.");
|
||||||
frames[i]->mTimecode = granulepos;
|
frames[i]->mTimecode = granulepos;
|
||||||
}
|
}
|
||||||
|
@ -1257,7 +1255,7 @@ nsresult nsOggReader::SeekInBufferedRange(PRInt64 aTarget,
|
||||||
aStartTime,
|
aStartTime,
|
||||||
aEndTime,
|
aEndTime,
|
||||||
PR_FALSE);
|
PR_FALSE);
|
||||||
res = SeekBisection(keyframeTime, k, SEEK_FUZZ_MS);
|
res = SeekBisection(keyframeTime, k, SEEK_FUZZ_USECS);
|
||||||
NS_ASSERTION(mTheoraGranulepos == -1, "SeekBisection must reset Theora decode");
|
NS_ASSERTION(mTheoraGranulepos == -1, "SeekBisection must reset Theora decode");
|
||||||
NS_ASSERTION(mVorbisGranulepos == -1, "SeekBisection must reset Vorbis decode");
|
NS_ASSERTION(mVorbisGranulepos == -1, "SeekBisection must reset Vorbis decode");
|
||||||
}
|
}
|
||||||
|
@ -1283,7 +1281,7 @@ nsresult nsOggReader::SeekInUnbuffered(PRInt64 aTarget,
|
||||||
LOG(PR_LOG_DEBUG, ("%p Seeking in unbuffered data to %lldms using bisection search", mDecoder, aTarget));
|
LOG(PR_LOG_DEBUG, ("%p Seeking in unbuffered data to %lldms using bisection search", mDecoder, aTarget));
|
||||||
|
|
||||||
// If we've got an active Theora bitstream, determine the maximum possible
|
// If we've got an active Theora bitstream, determine the maximum possible
|
||||||
// time in ms which a keyframe could be before a given interframe. We
|
// time in usecs which a keyframe could be before a given interframe. We
|
||||||
// subtract this from our seek target, seek to the new target, and then
|
// subtract this from our seek target, seek to the new target, and then
|
||||||
// will decode forward to the original seek target. We should encounter a
|
// will decode forward to the original seek target. We should encounter a
|
||||||
// keyframe in that interval. This prevents us from needing to run two
|
// keyframe in that interval. This prevents us from needing to run two
|
||||||
|
@ -1302,7 +1300,7 @@ nsresult nsOggReader::SeekInUnbuffered(PRInt64 aTarget,
|
||||||
// Minimize the bisection search space using the known timestamps from the
|
// Minimize the bisection search space using the known timestamps from the
|
||||||
// buffered ranges.
|
// buffered ranges.
|
||||||
SeekRange k = SelectSeekRange(aRanges, seekTarget, aStartTime, aEndTime, PR_FALSE);
|
SeekRange k = SelectSeekRange(aRanges, seekTarget, aStartTime, aEndTime, PR_FALSE);
|
||||||
nsresult res = SeekBisection(seekTarget, k, SEEK_FUZZ_MS);
|
nsresult res = SeekBisection(seekTarget, k, SEEK_FUZZ_USECS);
|
||||||
NS_ASSERTION(mTheoraGranulepos == -1, "SeekBisection must reset Theora decode");
|
NS_ASSERTION(mTheoraGranulepos == -1, "SeekBisection must reset Theora decode");
|
||||||
NS_ASSERTION(mVorbisGranulepos == -1, "SeekBisection must reset Vorbis decode");
|
NS_ASSERTION(mVorbisGranulepos == -1, "SeekBisection must reset Vorbis decode");
|
||||||
return res;
|
return res;
|
||||||
|
@ -1786,9 +1784,8 @@ nsresult nsOggReader::GetBuffered(nsTimeRanges* aBuffered, PRInt64 aStartTime)
|
||||||
// find an end time.
|
// find an end time.
|
||||||
PRInt64 endTime = FindEndTime(startOffset, endOffset, PR_TRUE, &state);
|
PRInt64 endTime = FindEndTime(startOffset, endOffset, PR_TRUE, &state);
|
||||||
if (endTime != -1) {
|
if (endTime != -1) {
|
||||||
endTime -= aStartTime;
|
aBuffered->Add(startTime / static_cast<double>(USECS_PER_S),
|
||||||
aBuffered->Add(static_cast<double>(startTime) / 1000.0,
|
(endTime - aStartTime) / static_cast<double>(USECS_PER_S));
|
||||||
static_cast<double>(endTime) / 1000.0);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -104,8 +104,8 @@ private:
|
||||||
|
|
||||||
// Returns PR_TRUE if we should decode up to the seek target rather than
|
// Returns PR_TRUE if we should decode up to the seek target rather than
|
||||||
// seeking to the target using a bisection search or index-assisted seek.
|
// seeking to the target using a bisection search or index-assisted seek.
|
||||||
// We should do this if the seek target (aTarget, in ms), lies not too far
|
// We should do this if the seek target (aTarget, in usecs), lies not too far
|
||||||
// ahead of the current playback position (aCurrentTime, in ms).
|
// ahead of the current playback position (aCurrentTime, in usecs).
|
||||||
PRBool CanDecodeToTarget(PRInt64 aTarget,
|
PRBool CanDecodeToTarget(PRInt64 aTarget,
|
||||||
PRInt64 aCurrentTime);
|
PRInt64 aCurrentTime);
|
||||||
|
|
||||||
|
@ -152,10 +152,10 @@ private:
|
||||||
}
|
}
|
||||||
|
|
||||||
PRInt64 mOffsetStart, mOffsetEnd; // in bytes.
|
PRInt64 mOffsetStart, mOffsetEnd; // in bytes.
|
||||||
PRInt64 mTimeStart, mTimeEnd; // in ms.
|
PRInt64 mTimeStart, mTimeEnd; // in usecs.
|
||||||
};
|
};
|
||||||
|
|
||||||
// Seeks to aTarget ms in the buffered range aRange using bisection search,
|
// Seeks to aTarget usecs in the buffered range aRange using bisection search,
|
||||||
// or to the keyframe prior to aTarget if we have video. aStartTime must be
|
// or to the keyframe prior to aTarget if we have video. aStartTime must be
|
||||||
// the presentation time at the start of media, and aEndTime the time at
|
// the presentation time at the start of media, and aEndTime the time at
|
||||||
// end of media. aRanges must be the time/byte ranges buffered in the media
|
// end of media. aRanges must be the time/byte ranges buffered in the media
|
||||||
|
@ -166,7 +166,7 @@ private:
|
||||||
const nsTArray<SeekRange>& aRanges,
|
const nsTArray<SeekRange>& aRanges,
|
||||||
const SeekRange& aRange);
|
const SeekRange& aRange);
|
||||||
|
|
||||||
// Seeks to before aTarget ms in media using bisection search. If the media
|
// Seeks to before aTarget usecs in media using bisection search. If the media
|
||||||
// has video, this will seek to before the keyframe required to render the
|
// has video, this will seek to before the keyframe required to render the
|
||||||
// media at aTarget. Will use aRanges in order to narrow the bisection
|
// media at aTarget. Will use aRanges in order to narrow the bisection
|
||||||
// search space. aStartTime must be the presentation time at the start of
|
// search space. aStartTime must be the presentation time at the start of
|
||||||
|
@ -208,11 +208,11 @@ private:
|
||||||
PRBool ReadOggPacket(nsOggCodecState* aCodecState, ogg_packet* aPacket);
|
PRBool ReadOggPacket(nsOggCodecState* aCodecState, ogg_packet* aPacket);
|
||||||
|
|
||||||
// Performs a seek bisection to move the media stream's read cursor to the
|
// Performs a seek bisection to move the media stream's read cursor to the
|
||||||
// last ogg page boundary which has end time before aTarget ms on both the
|
// last ogg page boundary which has end time before aTarget usecs on both the
|
||||||
// Theora and Vorbis bitstreams. Limits its search to data inside aRange;
|
// Theora and Vorbis bitstreams. Limits its search to data inside aRange;
|
||||||
// i.e. it will only read inside of the aRange's start and end offsets.
|
// i.e. it will only read inside of the aRange's start and end offsets.
|
||||||
// aFuzz is the number of ms of leniency we'll allow; we'll terminate the
|
// aFuzz is the number of usecs of leniency we'll allow; we'll terminate the
|
||||||
// seek when we land in the range (aTime - aFuzz, aTime) ms.
|
// seek when we land in the range (aTime - aFuzz, aTime) usecs.
|
||||||
nsresult SeekBisection(PRInt64 aTarget,
|
nsresult SeekBisection(PRInt64 aTarget,
|
||||||
const SeekRange& aRange,
|
const SeekRange& aRange,
|
||||||
PRUint32 aFuzz);
|
PRUint32 aFuzz);
|
||||||
|
@ -228,7 +228,7 @@ private:
|
||||||
nsresult GetSeekRanges(nsTArray<SeekRange>& aRanges);
|
nsresult GetSeekRanges(nsTArray<SeekRange>& aRanges);
|
||||||
|
|
||||||
// Returns the range in which you should perform a seek bisection if
|
// Returns the range in which you should perform a seek bisection if
|
||||||
// you wish to seek to aTarget ms, given the known (buffered) byte ranges
|
// you wish to seek to aTarget usecs, given the known (buffered) byte ranges
|
||||||
// in aRanges. If aExact is PR_TRUE, we only return an exact copy of a
|
// in aRanges. If aExact is PR_TRUE, we only return an exact copy of a
|
||||||
// range in which aTarget lies, or a null range if aTarget isn't contained
|
// range in which aTarget lies, or a null range if aTarget isn't contained
|
||||||
// in any of the (buffered) ranges. Otherwise, when aExact is PR_FALSE,
|
// in any of the (buffered) ranges. Otherwise, when aExact is PR_FALSE,
|
||||||
|
|
|
@ -129,7 +129,7 @@ nsresult nsRawReader::ReadMetadata(nsVideoInfo* aInfo)
|
||||||
if (length != -1) {
|
if (length != -1) {
|
||||||
mozilla::MonitorAutoExit autoExitMonitor(mMonitor);
|
mozilla::MonitorAutoExit autoExitMonitor(mMonitor);
|
||||||
mozilla::MonitorAutoEnter autoMonitor(mDecoder->GetMonitor());
|
mozilla::MonitorAutoEnter autoMonitor(mDecoder->GetMonitor());
|
||||||
mDecoder->GetStateMachine()->SetDuration(1000 *
|
mDecoder->GetStateMachine()->SetDuration(USECS_PER_S *
|
||||||
(length - sizeof(nsRawVideoHeader)) /
|
(length - sizeof(nsRawVideoHeader)) /
|
||||||
(mFrameSize * mFrameRate));
|
(mFrameSize * mFrameRate));
|
||||||
}
|
}
|
||||||
|
@ -184,7 +184,7 @@ PRBool nsRawReader::DecodeVideoFrame(PRBool &aKeyframeSkip,
|
||||||
if (!mFrameSize)
|
if (!mFrameSize)
|
||||||
return PR_FALSE; // Metadata read failed. We should refuse to play.
|
return PR_FALSE; // Metadata read failed. We should refuse to play.
|
||||||
|
|
||||||
PRInt64 currentFrameTime = 1000 * mCurrentFrame / mFrameRate;
|
PRInt64 currentFrameTime = USECS_PER_S * mCurrentFrame / mFrameRate;
|
||||||
PRUint32 length = mFrameSize - sizeof(nsRawPacketHeader);
|
PRUint32 length = mFrameSize - sizeof(nsRawPacketHeader);
|
||||||
|
|
||||||
nsAutoArrayPtr<PRUint8> buffer(new PRUint8[length]);
|
nsAutoArrayPtr<PRUint8> buffer(new PRUint8[length]);
|
||||||
|
@ -212,7 +212,7 @@ PRBool nsRawReader::DecodeVideoFrame(PRBool &aKeyframeSkip,
|
||||||
break;
|
break;
|
||||||
|
|
||||||
mCurrentFrame++;
|
mCurrentFrame++;
|
||||||
currentFrameTime += 1000.0 / mFrameRate;
|
currentFrameTime += static_cast<double>(USECS_PER_S) / mFrameRate;
|
||||||
}
|
}
|
||||||
|
|
||||||
VideoData::YCbCrBuffer b;
|
VideoData::YCbCrBuffer b;
|
||||||
|
@ -237,7 +237,7 @@ PRBool nsRawReader::DecodeVideoFrame(PRBool &aKeyframeSkip,
|
||||||
mDecoder->GetImageContainer(),
|
mDecoder->GetImageContainer(),
|
||||||
-1,
|
-1,
|
||||||
currentFrameTime,
|
currentFrameTime,
|
||||||
currentFrameTime + (1000 / mFrameRate),
|
currentFrameTime + (USECS_PER_S / mFrameRate),
|
||||||
b,
|
b,
|
||||||
1, // In raw video every frame is a keyframe
|
1, // In raw video every frame is a keyframe
|
||||||
-1);
|
-1);
|
||||||
|
@ -247,7 +247,7 @@ PRBool nsRawReader::DecodeVideoFrame(PRBool &aKeyframeSkip,
|
||||||
mVideoQueue.Push(v);
|
mVideoQueue.Push(v);
|
||||||
mCurrentFrame++;
|
mCurrentFrame++;
|
||||||
decoded++;
|
decoded++;
|
||||||
currentFrameTime += 1000 / mFrameRate;
|
currentFrameTime += USECS_PER_S / mFrameRate;
|
||||||
|
|
||||||
return PR_TRUE;
|
return PR_TRUE;
|
||||||
}
|
}
|
||||||
|
@ -264,7 +264,7 @@ nsresult nsRawReader::Seek(PRInt64 aTime, PRInt64 aStartTime, PRInt64 aEndTime,
|
||||||
PRUint32 frame = mCurrentFrame;
|
PRUint32 frame = mCurrentFrame;
|
||||||
if (aTime >= UINT_MAX)
|
if (aTime >= UINT_MAX)
|
||||||
return NS_ERROR_FAILURE;
|
return NS_ERROR_FAILURE;
|
||||||
mCurrentFrame = aTime * mFrameRate / 1000;
|
mCurrentFrame = aTime * mFrameRate / USECS_PER_S;
|
||||||
|
|
||||||
PRUint32 offset;
|
PRUint32 offset;
|
||||||
if (!MulOverflow32(mCurrentFrame, mFrameSize, offset))
|
if (!MulOverflow32(mCurrentFrame, mFrameSize, offset))
|
||||||
|
|
|
@ -231,6 +231,7 @@ _TEST_FILES += \
|
||||||
r16000_u8_c1_list.wav \
|
r16000_u8_c1_list.wav \
|
||||||
wavedata_u8.wav \
|
wavedata_u8.wav \
|
||||||
wavedata_s16.wav \
|
wavedata_s16.wav \
|
||||||
|
audio.wav \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
||||||
# Other files
|
# Other files
|
||||||
|
|
Двоичный файл не отображается.
|
@ -214,6 +214,7 @@ var gErrorTests = [
|
||||||
// These are files that have nontrivial duration and are useful for seeking within.
|
// These are files that have nontrivial duration and are useful for seeking within.
|
||||||
var gSeekTests = [
|
var gSeekTests = [
|
||||||
{ name:"r11025_s16_c1.wav", type:"audio/x-wav", duration:1.0 },
|
{ name:"r11025_s16_c1.wav", type:"audio/x-wav", duration:1.0 },
|
||||||
|
{ name:"audio.wav", type:"audio/x-wav", duration:0.031247 },
|
||||||
{ name:"seek.ogv", type:"video/ogg", duration:3.966 },
|
{ name:"seek.ogv", type:"video/ogg", duration:3.966 },
|
||||||
{ name:"320x240.ogv", type:"video/ogg", duration:0.233 },
|
{ name:"320x240.ogv", type:"video/ogg", duration:0.233 },
|
||||||
{ name:"seek.webm", type:"video/webm", duration:3.966 },
|
{ name:"seek.webm", type:"video/webm", duration:3.966 },
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
function on_metadataloaded() {
|
function on_metadataloaded() {
|
||||||
var v = document.getElementById('v');
|
var v = document.getElementById('v');
|
||||||
var d = Math.round(v.duration*1000);
|
var d = Math.round(v.duration*1000);
|
||||||
ok(d == 3999, "Checking duration: " + d);
|
ok(d == 4000, "Checking duration: " + d);
|
||||||
SimpleTest.finish();
|
SimpleTest.finish();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -171,9 +171,8 @@ nsresult nsWaveReader::ReadMetadata(nsVideoInfo* aInfo)
|
||||||
MonitorAutoExit exitReaderMon(mMonitor);
|
MonitorAutoExit exitReaderMon(mMonitor);
|
||||||
MonitorAutoEnter decoderMon(mDecoder->GetMonitor());
|
MonitorAutoEnter decoderMon(mDecoder->GetMonitor());
|
||||||
|
|
||||||
float d = floorf(BytesToTime(GetDataLength() * 1000));
|
mDecoder->GetStateMachine()->SetDuration(
|
||||||
NS_ASSERTION(d <= PR_INT64_MAX, "Duration overflow");
|
static_cast<PRInt64>(BytesToTime(GetDataLength()) * USECS_PER_S));
|
||||||
mDecoder->GetStateMachine()->SetDuration(static_cast<PRInt64>(d));
|
|
||||||
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
@ -229,16 +228,18 @@ PRBool nsWaveReader::DecodeAudioData()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
float posTime = BytesToTime(pos);
|
double posTime = BytesToTime(pos);
|
||||||
float readSizeTime = BytesToTime(readSize);
|
double readSizeTime = BytesToTime(readSize);
|
||||||
NS_ASSERTION(posTime <= PR_INT64_MAX / 1000, "posTime overflow");
|
NS_ASSERTION(posTime <= PR_INT64_MAX / USECS_PER_S, "posTime overflow");
|
||||||
NS_ASSERTION(readSizeTime <= PR_INT64_MAX / 1000, "readSizeTime overflow");
|
NS_ASSERTION(readSizeTime <= PR_INT64_MAX / USECS_PER_S, "readSizeTime overflow");
|
||||||
NS_ASSERTION(samples < PR_INT32_MAX, "samples overflow");
|
NS_ASSERTION(samples < PR_INT32_MAX, "samples overflow");
|
||||||
|
|
||||||
mAudioQueue.Push(new SoundData(pos, static_cast<PRInt64>(posTime * 1000),
|
mAudioQueue.Push(new SoundData(pos,
|
||||||
static_cast<PRInt64>(readSizeTime * 1000),
|
static_cast<PRInt64>(posTime * USECS_PER_S),
|
||||||
|
static_cast<PRInt64>(readSizeTime * USECS_PER_S),
|
||||||
static_cast<PRInt32>(samples),
|
static_cast<PRInt32>(samples),
|
||||||
sampleBuffer.forget(), mChannels));
|
sampleBuffer.forget(),
|
||||||
|
mChannels));
|
||||||
|
|
||||||
return PR_TRUE;
|
return PR_TRUE;
|
||||||
}
|
}
|
||||||
|
@ -258,20 +259,24 @@ nsresult nsWaveReader::Seek(PRInt64 aTarget, PRInt64 aStartTime, PRInt64 aEndTim
|
||||||
MonitorAutoEnter mon(mMonitor);
|
MonitorAutoEnter mon(mMonitor);
|
||||||
NS_ASSERTION(mDecoder->OnStateMachineThread(),
|
NS_ASSERTION(mDecoder->OnStateMachineThread(),
|
||||||
"Should be on state machine thread.");
|
"Should be on state machine thread.");
|
||||||
LOG(PR_LOG_DEBUG, ("%p About to seek to %lldms", mDecoder, aTarget));
|
LOG(PR_LOG_DEBUG, ("%p About to seek to %lld", mDecoder, aTarget));
|
||||||
if (NS_FAILED(ResetDecode())) {
|
if (NS_FAILED(ResetDecode())) {
|
||||||
return NS_ERROR_FAILURE;
|
return NS_ERROR_FAILURE;
|
||||||
}
|
}
|
||||||
float d = BytesToTime(GetDataLength());
|
double d = BytesToTime(GetDataLength());
|
||||||
NS_ASSERTION(d < PR_INT64_MAX / 1000, "Duration overflow");
|
NS_ASSERTION(d < PR_INT64_MAX / USECS_PER_S, "Duration overflow");
|
||||||
PRInt64 duration = static_cast<PRInt64>(d) * 1000;
|
PRInt64 duration = static_cast<PRInt64>(d * USECS_PER_S);
|
||||||
PRInt64 seekTime = NS_MIN(aTarget, duration);
|
double seekTime = NS_MIN(aTarget, duration) / static_cast<double>(USECS_PER_S);
|
||||||
PRInt64 position = RoundDownToSample(static_cast<PRInt64>(TimeToBytes(seekTime) / 1000.f));
|
PRInt64 position = RoundDownToSample(static_cast<PRInt64>(TimeToBytes(seekTime)));
|
||||||
NS_ASSERTION(PR_INT64_MAX - mWavePCMOffset > position, "Integer overflow during wave seek");
|
NS_ASSERTION(PR_INT64_MAX - mWavePCMOffset > position, "Integer overflow during wave seek");
|
||||||
position += mWavePCMOffset;
|
position += mWavePCMOffset;
|
||||||
return mDecoder->GetCurrentStream()->Seek(nsISeekableStream::NS_SEEK_SET, position);
|
return mDecoder->GetCurrentStream()->Seek(nsISeekableStream::NS_SEEK_SET, position);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static double RoundToUsecs(double aSeconds) {
|
||||||
|
return floor(aSeconds * USECS_PER_S) / USECS_PER_S;
|
||||||
|
}
|
||||||
|
|
||||||
nsresult nsWaveReader::GetBuffered(nsTimeRanges* aBuffered, PRInt64 aStartTime)
|
nsresult nsWaveReader::GetBuffered(nsTimeRanges* aBuffered, PRInt64 aStartTime)
|
||||||
{
|
{
|
||||||
PRInt64 startOffset = mDecoder->GetCurrentStream()->GetNextCachedData(mWavePCMOffset);
|
PRInt64 startOffset = mDecoder->GetCurrentStream()->GetNextCachedData(mWavePCMOffset);
|
||||||
|
@ -281,8 +286,11 @@ nsresult nsWaveReader::GetBuffered(nsTimeRanges* aBuffered, PRInt64 aStartTime)
|
||||||
NS_ASSERTION(startOffset >= mWavePCMOffset, "Integer underflow in GetBuffered");
|
NS_ASSERTION(startOffset >= mWavePCMOffset, "Integer underflow in GetBuffered");
|
||||||
NS_ASSERTION(endOffset >= mWavePCMOffset, "Integer underflow in GetBuffered");
|
NS_ASSERTION(endOffset >= mWavePCMOffset, "Integer underflow in GetBuffered");
|
||||||
|
|
||||||
aBuffered->Add(floorf(BytesToTime(startOffset - mWavePCMOffset) * 1000.f) / 1000.0,
|
// We need to round the buffered ranges' times to microseconds so that they
|
||||||
floorf(BytesToTime(endOffset - mWavePCMOffset) * 1000.f) / 1000.0);
|
// have the same precision as the currentTime and duration attribute on
|
||||||
|
// the media element.
|
||||||
|
aBuffered->Add(RoundToUsecs(BytesToTime(startOffset - mWavePCMOffset)),
|
||||||
|
RoundToUsecs(BytesToTime(endOffset - mWavePCMOffset)));
|
||||||
startOffset = mDecoder->GetCurrentStream()->GetNextCachedData(endOffset);
|
startOffset = mDecoder->GetCurrentStream()->GetNextCachedData(endOffset);
|
||||||
}
|
}
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
|
@ -508,7 +516,7 @@ nsWaveReader::FindDataOffset()
|
||||||
return PR_TRUE;
|
return PR_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
float
|
double
|
||||||
nsWaveReader::BytesToTime(PRInt64 aBytes) const
|
nsWaveReader::BytesToTime(PRInt64 aBytes) const
|
||||||
{
|
{
|
||||||
NS_ABORT_IF_FALSE(aBytes >= 0, "Must be >= 0");
|
NS_ABORT_IF_FALSE(aBytes >= 0, "Must be >= 0");
|
||||||
|
@ -516,7 +524,7 @@ nsWaveReader::BytesToTime(PRInt64 aBytes) const
|
||||||
}
|
}
|
||||||
|
|
||||||
PRInt64
|
PRInt64
|
||||||
nsWaveReader::TimeToBytes(float aTime) const
|
nsWaveReader::TimeToBytes(double aTime) const
|
||||||
{
|
{
|
||||||
NS_ABORT_IF_FALSE(aTime >= 0.0f, "Must be >= 0");
|
NS_ABORT_IF_FALSE(aTime >= 0.0f, "Must be >= 0");
|
||||||
return RoundDownToSample(PRInt64(aTime * mSampleRate * mSampleSize));
|
return RoundDownToSample(PRInt64(aTime * mSampleRate * mSampleSize));
|
||||||
|
|
|
@ -76,13 +76,13 @@ private:
|
||||||
|
|
||||||
// Returns the number of seconds that aBytes represents based on the
|
// Returns the number of seconds that aBytes represents based on the
|
||||||
// current audio parameters. e.g. 176400 bytes is 1 second at 16-bit
|
// current audio parameters. e.g. 176400 bytes is 1 second at 16-bit
|
||||||
// stereo 44.1kHz. The time is rounded to the nearest millisecond.
|
// stereo 44.1kHz. The time is rounded to the nearest microsecond.
|
||||||
float BytesToTime(PRInt64 aBytes) const;
|
double BytesToTime(PRInt64 aBytes) const;
|
||||||
|
|
||||||
// Returns the number of bytes that aTime represents based on the current
|
// Returns the number of bytes that aTime represents based on the current
|
||||||
// audio parameters. e.g. 1 second is 176400 bytes at 16-bit stereo
|
// audio parameters. e.g. 1 second is 176400 bytes at 16-bit stereo
|
||||||
// 44.1kHz.
|
// 44.1kHz.
|
||||||
PRInt64 TimeToBytes(float aTime) const;
|
PRInt64 TimeToBytes(double aTime) const;
|
||||||
|
|
||||||
// Rounds aBytes down to the nearest complete sample. Assumes beginning
|
// Rounds aBytes down to the nearest complete sample. Assumes beginning
|
||||||
// of byte range is already sample aligned by caller.
|
// of byte range is already sample aligned by caller.
|
||||||
|
|
|
@ -44,7 +44,6 @@
|
||||||
using mozilla::MonitorAutoEnter;
|
using mozilla::MonitorAutoEnter;
|
||||||
|
|
||||||
static const double NS_PER_S = 1e9;
|
static const double NS_PER_S = 1e9;
|
||||||
static const double MS_PER_S = 1e3;
|
|
||||||
|
|
||||||
static PRUint32
|
static PRUint32
|
||||||
VIntLength(unsigned char aFirstByte, PRUint32* aMask)
|
VIntLength(unsigned char aFirstByte, PRUint32* aMask)
|
||||||
|
|
|
@ -65,14 +65,13 @@ extern PRLogModuleInfo* gBuiltinDecoderLog;
|
||||||
#define SEEK_LOG(type, msg)
|
#define SEEK_LOG(type, msg)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static const unsigned NS_PER_MS = 1000000;
|
static const unsigned NS_PER_USEC = 1000;
|
||||||
static const double NS_PER_S = 1e9;
|
static const double NS_PER_S = 1e9;
|
||||||
static const double MS_PER_S = 1e3;
|
|
||||||
|
|
||||||
// If a seek request is within SEEK_DECODE_MARGIN milliseconds of the
|
// If a seek request is within SEEK_DECODE_MARGIN microseconds of the
|
||||||
// current time, decode ahead from the current frame rather than performing
|
// current time, decode ahead from the current frame rather than performing
|
||||||
// a full seek.
|
// a full seek.
|
||||||
static const int SEEK_DECODE_MARGIN = 250;
|
static const int SEEK_DECODE_MARGIN = 250000;
|
||||||
|
|
||||||
NS_SPECIALIZE_TEMPLATE
|
NS_SPECIALIZE_TEMPLATE
|
||||||
class nsAutoRefTraits<NesteggPacketHolder> : public nsPointerRefTraits<NesteggPacketHolder>
|
class nsAutoRefTraits<NesteggPacketHolder> : public nsPointerRefTraits<NesteggPacketHolder>
|
||||||
|
@ -136,7 +135,7 @@ nsWebMReader::nsWebMReader(nsBuiltinDecoder* aDecoder)
|
||||||
mChannels(0),
|
mChannels(0),
|
||||||
mVideoTrack(0),
|
mVideoTrack(0),
|
||||||
mAudioTrack(0),
|
mAudioTrack(0),
|
||||||
mAudioStartMs(-1),
|
mAudioStartUsec(-1),
|
||||||
mAudioSamples(0),
|
mAudioSamples(0),
|
||||||
mHasVideo(PR_FALSE),
|
mHasVideo(PR_FALSE),
|
||||||
mHasAudio(PR_FALSE)
|
mHasAudio(PR_FALSE)
|
||||||
|
@ -184,7 +183,7 @@ nsresult nsWebMReader::Init(nsBuiltinDecoderReader* aCloneDonor)
|
||||||
nsresult nsWebMReader::ResetDecode()
|
nsresult nsWebMReader::ResetDecode()
|
||||||
{
|
{
|
||||||
mAudioSamples = 0;
|
mAudioSamples = 0;
|
||||||
mAudioStartMs = -1;
|
mAudioStartUsec = -1;
|
||||||
nsresult res = NS_OK;
|
nsresult res = NS_OK;
|
||||||
if (NS_FAILED(nsBuiltinDecoderReader::ResetDecode())) {
|
if (NS_FAILED(nsBuiltinDecoderReader::ResetDecode())) {
|
||||||
res = NS_ERROR_FAILURE;
|
res = NS_ERROR_FAILURE;
|
||||||
|
@ -229,7 +228,7 @@ nsresult nsWebMReader::ReadMetadata(nsVideoInfo* aInfo)
|
||||||
if (r == 0) {
|
if (r == 0) {
|
||||||
MonitorAutoExit exitReaderMon(mMonitor);
|
MonitorAutoExit exitReaderMon(mMonitor);
|
||||||
MonitorAutoEnter decoderMon(mDecoder->GetMonitor());
|
MonitorAutoEnter decoderMon(mDecoder->GetMonitor());
|
||||||
mDecoder->GetStateMachine()->SetDuration(duration / NS_PER_MS);
|
mDecoder->GetStateMachine()->SetDuration(duration / NS_PER_USEC);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int ntracks = 0;
|
unsigned int ntracks = 0;
|
||||||
|
@ -435,23 +434,23 @@ PRBool nsWebMReader::DecodeAudioPacket(nestegg_packet* aPacket, PRInt64 aOffset)
|
||||||
}
|
}
|
||||||
|
|
||||||
const PRUint32 rate = mVorbisDsp.vi->rate;
|
const PRUint32 rate = mVorbisDsp.vi->rate;
|
||||||
PRUint64 tstamp_ms = tstamp / NS_PER_MS;
|
PRUint64 tstamp_usecs = tstamp / NS_PER_USEC;
|
||||||
if (mAudioStartMs == -1) {
|
if (mAudioStartUsec == -1) {
|
||||||
// This is the first audio chunk. Assume the start time of our decode
|
// This is the first audio chunk. Assume the start time of our decode
|
||||||
// is the start of this chunk.
|
// is the start of this chunk.
|
||||||
mAudioStartMs = tstamp_ms;
|
mAudioStartUsec = tstamp_usecs;
|
||||||
}
|
}
|
||||||
// If there's a gap between the start of this sound chunk and the end of
|
// If there's a gap between the start of this sound chunk and the end of
|
||||||
// the previous sound chunk, we need to increment the packet count so that
|
// the previous sound chunk, we need to increment the packet count so that
|
||||||
// the vorbis decode doesn't use data from before the gap to help decode
|
// the vorbis decode doesn't use data from before the gap to help decode
|
||||||
// from after the gap.
|
// from after the gap.
|
||||||
PRInt64 tstamp_samples = 0;
|
PRInt64 tstamp_samples = 0;
|
||||||
if (!MsToSamples(tstamp_ms, rate, tstamp_samples)) {
|
if (!UsecsToSamples(tstamp_usecs, rate, tstamp_samples)) {
|
||||||
NS_WARNING("Int overflow converting WebM timestamp to samples");
|
NS_WARNING("Int overflow converting WebM timestamp to samples");
|
||||||
return PR_FALSE;
|
return PR_FALSE;
|
||||||
}
|
}
|
||||||
PRInt64 decoded_samples = 0;
|
PRInt64 decoded_samples = 0;
|
||||||
if (!MsToSamples(mAudioStartMs, rate, decoded_samples)) {
|
if (!UsecsToSamples(mAudioStartUsec, rate, decoded_samples)) {
|
||||||
NS_WARNING("Int overflow converting WebM start time to samples");
|
NS_WARNING("Int overflow converting WebM start time to samples");
|
||||||
return PR_FALSE;
|
return PR_FALSE;
|
||||||
}
|
}
|
||||||
|
@ -461,13 +460,13 @@ PRBool nsWebMReader::DecodeAudioPacket(nestegg_packet* aPacket, PRInt64 aOffset)
|
||||||
}
|
}
|
||||||
if (tstamp_samples > decoded_samples) {
|
if (tstamp_samples > decoded_samples) {
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
PRInt64 ms = 0;
|
PRInt64 usecs = 0;
|
||||||
LOG(PR_LOG_DEBUG, ("WebMReader detected gap of %lldms, %lld samples, in audio stream\n",
|
LOG(PR_LOG_DEBUG, ("WebMReader detected gap of %lld, %lld samples, in audio stream\n",
|
||||||
SamplesToMs(tstamp_samples - decoded_samples, rate, ms) ? ms: -1,
|
SamplesToUsecs(tstamp_samples - decoded_samples, rate, usecs) ? usecs: -1,
|
||||||
tstamp_samples - decoded_samples));
|
tstamp_samples - decoded_samples));
|
||||||
#endif
|
#endif
|
||||||
mPacketCount++;
|
mPacketCount++;
|
||||||
mAudioStartMs = tstamp_ms;
|
mAudioStartUsec = tstamp_usecs;
|
||||||
mAudioSamples = 0;
|
mAudioSamples = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -503,17 +502,17 @@ PRBool nsWebMReader::DecodeAudioPacket(nestegg_packet* aPacket, PRInt64 aOffset)
|
||||||
}
|
}
|
||||||
|
|
||||||
PRInt64 duration = 0;
|
PRInt64 duration = 0;
|
||||||
if (!SamplesToMs(samples, rate, duration)) {
|
if (!SamplesToUsecs(samples, rate, duration)) {
|
||||||
NS_WARNING("Int overflow converting WebM audio duration");
|
NS_WARNING("Int overflow converting WebM audio duration");
|
||||||
return PR_FALSE;
|
return PR_FALSE;
|
||||||
}
|
}
|
||||||
PRInt64 total_duration = 0;
|
PRInt64 total_duration = 0;
|
||||||
if (!SamplesToMs(total_samples, rate, total_duration)) {
|
if (!SamplesToUsecs(total_samples, rate, total_duration)) {
|
||||||
NS_WARNING("Int overflow converting WebM audio total_duration");
|
NS_WARNING("Int overflow converting WebM audio total_duration");
|
||||||
return PR_FALSE;
|
return PR_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
PRInt64 time = tstamp_ms + total_duration;
|
PRInt64 time = tstamp_usecs + total_duration;
|
||||||
total_samples += samples;
|
total_samples += samples;
|
||||||
SoundData* s = new SoundData(aOffset,
|
SoundData* s = new SoundData(aOffset,
|
||||||
time,
|
time,
|
||||||
|
@ -668,11 +667,11 @@ PRBool nsWebMReader::DecodeVideoFrame(PRBool &aKeyframeSkip,
|
||||||
if (endTime == -1) {
|
if (endTime == -1) {
|
||||||
return PR_FALSE;
|
return PR_FALSE;
|
||||||
}
|
}
|
||||||
next_tstamp = endTime * NS_PER_MS;
|
next_tstamp = endTime * NS_PER_USEC;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PRInt64 tstamp_ms = tstamp / NS_PER_MS;
|
PRInt64 tstamp_usecs = tstamp / NS_PER_USEC;
|
||||||
for (PRUint32 i = 0; i < count; ++i) {
|
for (PRUint32 i = 0; i < count; ++i) {
|
||||||
unsigned char* data;
|
unsigned char* data;
|
||||||
size_t length;
|
size_t length;
|
||||||
|
@ -685,7 +684,7 @@ PRBool nsWebMReader::DecodeVideoFrame(PRBool &aKeyframeSkip,
|
||||||
memset(&si, 0, sizeof(si));
|
memset(&si, 0, sizeof(si));
|
||||||
si.sz = sizeof(si);
|
si.sz = sizeof(si);
|
||||||
vpx_codec_peek_stream_info(&vpx_codec_vp8_dx_algo, data, length, &si);
|
vpx_codec_peek_stream_info(&vpx_codec_vp8_dx_algo, data, length, &si);
|
||||||
if (aKeyframeSkip && (!si.is_kf || tstamp_ms < aTimeThreshold)) {
|
if (aKeyframeSkip && (!si.is_kf || tstamp_usecs < aTimeThreshold)) {
|
||||||
// Skipping to next keyframe...
|
// Skipping to next keyframe...
|
||||||
parsed++; // Assume 1 frame per chunk.
|
parsed++; // Assume 1 frame per chunk.
|
||||||
continue;
|
continue;
|
||||||
|
@ -702,7 +701,7 @@ PRBool nsWebMReader::DecodeVideoFrame(PRBool &aKeyframeSkip,
|
||||||
// If the timestamp of the video frame is less than
|
// If the timestamp of the video frame is less than
|
||||||
// the time threshold required then it is not added
|
// the time threshold required then it is not added
|
||||||
// to the video queue and won't be displayed.
|
// to the video queue and won't be displayed.
|
||||||
if (tstamp_ms < aTimeThreshold) {
|
if (tstamp_usecs < aTimeThreshold) {
|
||||||
parsed++; // Assume 1 frame per chunk.
|
parsed++; // Assume 1 frame per chunk.
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -733,8 +732,8 @@ PRBool nsWebMReader::DecodeVideoFrame(PRBool &aKeyframeSkip,
|
||||||
VideoData *v = VideoData::Create(mInfo,
|
VideoData *v = VideoData::Create(mInfo,
|
||||||
mDecoder->GetImageContainer(),
|
mDecoder->GetImageContainer(),
|
||||||
holder->mOffset,
|
holder->mOffset,
|
||||||
tstamp_ms,
|
tstamp_usecs,
|
||||||
next_tstamp / NS_PER_MS,
|
next_tstamp / NS_PER_USEC,
|
||||||
b,
|
b,
|
||||||
si.is_kf,
|
si.is_kf,
|
||||||
-1);
|
-1);
|
||||||
|
@ -774,7 +773,7 @@ nsresult nsWebMReader::Seek(PRInt64 aTarget, PRInt64 aStartTime, PRInt64 aEndTim
|
||||||
return NS_ERROR_FAILURE;
|
return NS_ERROR_FAILURE;
|
||||||
}
|
}
|
||||||
PRUint32 trackToSeek = mHasVideo ? mVideoTrack : mAudioTrack;
|
PRUint32 trackToSeek = mHasVideo ? mVideoTrack : mAudioTrack;
|
||||||
int r = nestegg_track_seek(mContext, trackToSeek, aTarget * NS_PER_MS);
|
int r = nestegg_track_seek(mContext, trackToSeek, aTarget * NS_PER_USEC);
|
||||||
if (r != 0) {
|
if (r != 0) {
|
||||||
return NS_ERROR_FAILURE;
|
return NS_ERROR_FAILURE;
|
||||||
}
|
}
|
||||||
|
@ -786,7 +785,7 @@ nsresult nsWebMReader::GetBuffered(nsTimeRanges* aBuffered, PRInt64 aStartTime)
|
||||||
{
|
{
|
||||||
nsMediaStream* stream = mDecoder->GetCurrentStream();
|
nsMediaStream* stream = mDecoder->GetCurrentStream();
|
||||||
|
|
||||||
PRUint64 timecodeScale;
|
uint64_t timecodeScale;
|
||||||
if (!mContext || nestegg_tstamp_scale(mContext, &timecodeScale) == -1) {
|
if (!mContext || nestegg_tstamp_scale(mContext, &timecodeScale) == -1) {
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
@ -803,7 +802,7 @@ nsresult nsWebMReader::GetBuffered(nsTimeRanges* aBuffered, PRInt64 aStartTime)
|
||||||
nsresult res = stream->GetCachedRanges(ranges);
|
nsresult res = stream->GetCachedRanges(ranges);
|
||||||
NS_ENSURE_SUCCESS(res, res);
|
NS_ENSURE_SUCCESS(res, res);
|
||||||
|
|
||||||
PRInt64 startTimeOffsetNS = aStartTime * NS_PER_MS;
|
PRInt64 startTimeOffsetNS = aStartTime * NS_PER_USEC;
|
||||||
for (PRUint32 index = 0; index < ranges.Length(); index++) {
|
for (PRUint32 index = 0; index < ranges.Length(); index++) {
|
||||||
mBufferedState->CalculateBufferedForRange(aBuffered,
|
mBufferedState->CalculateBufferedForRange(aBuffered,
|
||||||
ranges[index].mStart,
|
ranges[index].mStart,
|
||||||
|
|
|
@ -192,8 +192,8 @@ private:
|
||||||
|
|
||||||
// Returns PR_TRUE if we should decode up to the seek target rather than
|
// Returns PR_TRUE if we should decode up to the seek target rather than
|
||||||
// seeking to the target using an index-assisted seek. We should do this
|
// seeking to the target using an index-assisted seek. We should do this
|
||||||
// if the seek target (aTarget, in ms), lies not too far ahead of the
|
// if the seek target (aTarget, in usecs), lies not too far ahead of the
|
||||||
// current playback position (aCurrentTime, in ms).
|
// current playback position (aCurrentTime, in usecs).
|
||||||
PRBool CanDecodeToTarget(PRInt64 aTarget, PRInt64 aCurrentTime);
|
PRBool CanDecodeToTarget(PRInt64 aTarget, PRInt64 aCurrentTime);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -221,8 +221,8 @@ private:
|
||||||
PRUint32 mVideoTrack;
|
PRUint32 mVideoTrack;
|
||||||
PRUint32 mAudioTrack;
|
PRUint32 mAudioTrack;
|
||||||
|
|
||||||
// Time in ms of the start of the first audio sample we've decoded.
|
// Time in microseconds of the start of the first audio sample we've decoded.
|
||||||
PRInt64 mAudioStartMs;
|
PRInt64 mAudioStartUsec;
|
||||||
|
|
||||||
// Number of samples we've decoded since decoding began at mAudioStartMs.
|
// Number of samples we've decoded since decoding began at mAudioStartMs.
|
||||||
PRUint64 mAudioSamples;
|
PRUint64 mAudioSamples;
|
||||||
|
|
|
@ -53,6 +53,12 @@ class SVGPreserveAspectRatio
|
||||||
friend class SVGAnimatedPreserveAspectRatio;
|
friend class SVGAnimatedPreserveAspectRatio;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
SVGPreserveAspectRatio()
|
||||||
|
: mAlign(0)
|
||||||
|
, mMeetOrSlice(0)
|
||||||
|
, mDefer(false)
|
||||||
|
{};
|
||||||
|
|
||||||
nsresult SetAlign(PRUint16 aAlign) {
|
nsresult SetAlign(PRUint16 aAlign) {
|
||||||
if (aAlign < nsIDOMSVGPreserveAspectRatio::SVG_PRESERVEASPECTRATIO_NONE ||
|
if (aAlign < nsIDOMSVGPreserveAspectRatio::SVG_PRESERVEASPECTRATIO_NONE ||
|
||||||
aAlign > nsIDOMSVGPreserveAspectRatio::SVG_PRESERVEASPECTRATIO_XMAXYMAX)
|
aAlign > nsIDOMSVGPreserveAspectRatio::SVG_PRESERVEASPECTRATIO_XMAXYMAX)
|
||||||
|
|
|
@ -337,8 +337,8 @@ nsSVGAngle::SetBaseValueString(const nsAString &aValueAsString,
|
||||||
nsSVGElement *aSVGElement,
|
nsSVGElement *aSVGElement,
|
||||||
PRBool aDoSetAttr)
|
PRBool aDoSetAttr)
|
||||||
{
|
{
|
||||||
float value;
|
float value = 0;
|
||||||
PRUint16 unitType;
|
PRUint16 unitType = 0;
|
||||||
|
|
||||||
nsresult rv = GetValueFromString(aValueAsString, &value, &unitType);
|
nsresult rv = GetValueFromString(aValueAsString, &value, &unitType);
|
||||||
if (NS_FAILED(rv)) {
|
if (NS_FAILED(rv)) {
|
||||||
|
|
|
@ -563,7 +563,7 @@ BoxBlur(const PRUint8 *aInput, PRUint8 *aOutput,
|
||||||
}
|
}
|
||||||
|
|
||||||
aOutput += aStrideMinor*aStartMinor;
|
aOutput += aStrideMinor*aStartMinor;
|
||||||
if (aStartMinor + boxSize <= aEndMinor) {
|
if (aStartMinor + PRInt32(boxSize) <= aEndMinor) {
|
||||||
const PRUint8 *lastInput = aInput + aStartMinor*aStrideMinor;
|
const PRUint8 *lastInput = aInput + aStartMinor*aStrideMinor;
|
||||||
const PRUint8 *nextInput = aInput + (aStartMinor + aRightLobe + 1)*aStrideMinor;
|
const PRUint8 *nextInput = aInput + (aStartMinor + aRightLobe + 1)*aStrideMinor;
|
||||||
#define OUTPUT(j) aOutput[j] = (sums[j]*scaledDivisor) >> 24;
|
#define OUTPUT(j) aOutput[j] = (sums[j]*scaledDivisor) >> 24;
|
||||||
|
@ -4876,7 +4876,8 @@ nsSVGFELightingElement::Filter(nsSVGFilterInstance *instance,
|
||||||
L[1] = sin(azimuth * radPerDeg) * cos(elevation * radPerDeg);
|
L[1] = sin(azimuth * radPerDeg) * cos(elevation * radPerDeg);
|
||||||
L[2] = sin(elevation * radPerDeg);
|
L[2] = sin(elevation * radPerDeg);
|
||||||
}
|
}
|
||||||
float lightPos[3], pointsAt[3], specularExponent, cosConeAngle;
|
float lightPos[3], pointsAt[3], specularExponent;
|
||||||
|
float cosConeAngle = 0;
|
||||||
if (pointLight) {
|
if (pointLight) {
|
||||||
static_cast<nsSVGFEPointLightElement*>
|
static_cast<nsSVGFEPointLightElement*>
|
||||||
(pointLight.get())->GetAnimatedNumberValues(lightPos,
|
(pointLight.get())->GetAnimatedNumberValues(lightPos,
|
||||||
|
@ -4903,8 +4904,6 @@ nsSVGFELightingElement::Filter(nsSVGFilterInstance *instance,
|
||||||
nsCOMPtr<nsIContent> spot = do_QueryInterface(spotLight);
|
nsCOMPtr<nsIContent> spot = do_QueryInterface(spotLight);
|
||||||
if (spot->HasAttr(kNameSpaceID_None, nsGkAtoms::limitingConeAngle)) {
|
if (spot->HasAttr(kNameSpaceID_None, nsGkAtoms::limitingConeAngle)) {
|
||||||
cosConeAngle = NS_MAX<double>(cos(limitingConeAngle * radPerDeg), 0.0);
|
cosConeAngle = NS_MAX<double>(cos(limitingConeAngle * radPerDeg), 0.0);
|
||||||
} else {
|
|
||||||
cosConeAngle = 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -115,7 +115,7 @@ nsSVGPolyElement::GetMarkPoints(nsTArray<nsSVGMark> *aMarks)
|
||||||
if (!points.Length())
|
if (!points.Length())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
float px = 0.0, py = 0.0, prevAngle;
|
float px = 0.0, py = 0.0, prevAngle = 0.0;
|
||||||
|
|
||||||
for (PRUint32 i = 0; i < points.Length(); ++i) {
|
for (PRUint32 i = 0; i < points.Length(); ++i) {
|
||||||
float x = points[i].mX;
|
float x = points[i].mX;
|
||||||
|
|
|
@ -1254,7 +1254,7 @@ nsXBLBinding::DoInitJSClass(JSContext *cx, JSObject *global, JSObject *obj,
|
||||||
{
|
{
|
||||||
// First ensure our JS class is initialized.
|
// First ensure our JS class is initialized.
|
||||||
jsval val;
|
jsval val;
|
||||||
JSObject* proto;
|
JSObject* proto = NULL;
|
||||||
|
|
||||||
nsCAutoString className(aClassName);
|
nsCAutoString className(aClassName);
|
||||||
JSObject* parent_proto = nsnull; // If we have an "obj" we can set this
|
JSObject* parent_proto = nsnull; // If we have an "obj" we can set this
|
||||||
|
|
|
@ -76,7 +76,7 @@ public:
|
||||||
|
|
||||||
virtual nsIScriptContext *GetContext();
|
virtual nsIScriptContext *GetContext();
|
||||||
virtual JSObject *GetGlobalJSObject();
|
virtual JSObject *GetGlobalJSObject();
|
||||||
virtual void OnFinalize(PRUint32 aLangID, void *aScriptGlobal);
|
virtual void OnFinalize(JSObject* aObject);
|
||||||
virtual void SetScriptsEnabled(PRBool aEnabled, PRBool aFireTimeouts);
|
virtual void SetScriptsEnabled(PRBool aEnabled, PRBool aFireTimeouts);
|
||||||
|
|
||||||
// nsIScriptObjectPrincipal methods
|
// nsIScriptObjectPrincipal methods
|
||||||
|
@ -167,7 +167,7 @@ nsXBLDocGlobalObject_finalize(JSContext *cx, JSObject *obj)
|
||||||
nsCOMPtr<nsIScriptGlobalObject> sgo(do_QueryInterface(nativeThis));
|
nsCOMPtr<nsIScriptGlobalObject> sgo(do_QueryInterface(nativeThis));
|
||||||
|
|
||||||
if (sgo)
|
if (sgo)
|
||||||
sgo->OnFinalize(nsIProgrammingLanguage::JAVASCRIPT, obj);
|
sgo->OnFinalize(obj);
|
||||||
|
|
||||||
// The addref was part of JSObject construction
|
// The addref was part of JSObject construction
|
||||||
NS_RELEASE(nativeThis);
|
NS_RELEASE(nativeThis);
|
||||||
|
@ -383,13 +383,10 @@ nsXBLDocGlobalObject::GetGlobalJSObject()
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
nsXBLDocGlobalObject::OnFinalize(PRUint32 aLangID, void *aObject)
|
nsXBLDocGlobalObject::OnFinalize(JSObject* aObject)
|
||||||
{
|
{
|
||||||
NS_ASSERTION(aLangID == nsIProgrammingLanguage::JAVASCRIPT,
|
|
||||||
"Only JS supported");
|
|
||||||
NS_ASSERTION(aObject == mJSObject, "Wrong object finalized!");
|
NS_ASSERTION(aObject == mJSObject, "Wrong object finalized!");
|
||||||
|
mJSObject = NULL;
|
||||||
mJSObject = nsnull;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
@ -1231,8 +1231,7 @@ nsXMLContentSink::HandleDoctypeDecl(const nsAString & aSubset,
|
||||||
// Create a new doctype node
|
// Create a new doctype node
|
||||||
nsCOMPtr<nsIDOMDocumentType> docType;
|
nsCOMPtr<nsIDOMDocumentType> docType;
|
||||||
rv = NS_NewDOMDocumentType(getter_AddRefs(docType), mNodeInfoManager, nsnull,
|
rv = NS_NewDOMDocumentType(getter_AddRefs(docType), mNodeInfoManager, nsnull,
|
||||||
name, nsnull, nsnull, aPublicId, aSystemId,
|
name, aPublicId, aSystemId, aSubset);
|
||||||
aSubset);
|
|
||||||
if (NS_FAILED(rv) || !docType) {
|
if (NS_FAILED(rv) || !docType) {
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
|
@ -329,7 +329,7 @@ txCoreFunctionCall::evaluate(txIEvalContext* aContext, txAExprResult** aResult)
|
||||||
rv = mParams[1]->evaluateToString(aContext, arg2);
|
rv = mParams[1]->evaluateToString(aContext, arg2);
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
PRBool result;
|
PRBool result = PR_FALSE;
|
||||||
if (arg2.IsEmpty()) {
|
if (arg2.IsEmpty()) {
|
||||||
result = PR_TRUE;
|
result = PR_TRUE;
|
||||||
}
|
}
|
||||||
|
|
|
@ -602,8 +602,8 @@ txExprParser::createLocationStep(txExprLexer& lexer, txIParseContext* aContext,
|
||||||
nodeTest =
|
nodeTest =
|
||||||
new txNameTest(prefix, lName, nspace,
|
new txNameTest(prefix, lName, nspace,
|
||||||
axisIdentifier == LocationStep::ATTRIBUTE_AXIS ?
|
axisIdentifier == LocationStep::ATTRIBUTE_AXIS ?
|
||||||
txXPathNodeType::ATTRIBUTE_NODE :
|
static_cast<PRUint16>(txXPathNodeType::ATTRIBUTE_NODE) :
|
||||||
txXPathNodeType::ELEMENT_NODE);
|
static_cast<PRUint16>(txXPathNodeType::ELEMENT_NODE));
|
||||||
NS_ENSURE_TRUE(nodeTest, NS_ERROR_OUT_OF_MEMORY);
|
NS_ENSURE_TRUE(nodeTest, NS_ERROR_OUT_OF_MEMORY);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
|
@ -269,7 +269,7 @@ TX_ResolveFunctionCallXPCOM(const nsCString &aContractID, PRInt32 aNamespaceID,
|
||||||
FunctionCall **aFunction)
|
FunctionCall **aFunction)
|
||||||
{
|
{
|
||||||
nsIID iid;
|
nsIID iid;
|
||||||
PRUint16 methodIndex;
|
PRUint16 methodIndex = 0;
|
||||||
nsCOMPtr<nsISupports> helper;
|
nsCOMPtr<nsISupports> helper;
|
||||||
|
|
||||||
nsresult rv = LookupFunction(aContractID.get(), aName, iid, methodIndex,
|
nsresult rv = LookupFunction(aContractID.get(), aName, iid, methodIndex,
|
||||||
|
|
|
@ -949,7 +949,7 @@ txMozillaXMLOutput::createResultDocument(const nsSubstring& aName, PRInt32 aNsID
|
||||||
voidString.SetIsVoid(PR_TRUE);
|
voidString.SetIsVoid(PR_TRUE);
|
||||||
rv = NS_NewDOMDocumentType(getter_AddRefs(documentType),
|
rv = NS_NewDOMDocumentType(getter_AddRefs(documentType),
|
||||||
mNodeInfoManager, nsnull,
|
mNodeInfoManager, nsnull,
|
||||||
doctypeName, nsnull, nsnull,
|
doctypeName,
|
||||||
mOutputFormat.mPublicId,
|
mOutputFormat.mPublicId,
|
||||||
mOutputFormat.mSystemId,
|
mOutputFormat.mSystemId,
|
||||||
voidString);
|
voidString);
|
||||||
|
|
|
@ -774,8 +774,8 @@ nsScriptEventHandlerOwnerTearoff::CompileEventHandler(
|
||||||
// XXX sXBL/XBL2 issue! Owner or current document?
|
// XXX sXBL/XBL2 issue! Owner or current document?
|
||||||
nsCOMPtr<nsIXULDocument> xuldoc = do_QueryInterface(mElement->GetOwnerDoc());
|
nsCOMPtr<nsIXULDocument> xuldoc = do_QueryInterface(mElement->GetOwnerDoc());
|
||||||
|
|
||||||
nsIScriptContext *context;
|
nsIScriptContext* context = NULL;
|
||||||
nsXULPrototypeElement *elem = mElement->mPrototype;
|
nsXULPrototypeElement* elem = mElement->mPrototype;
|
||||||
if (elem && xuldoc) {
|
if (elem && xuldoc) {
|
||||||
// It'll be shared among the instances of the prototype.
|
// It'll be shared among the instances of the prototype.
|
||||||
|
|
||||||
|
|
|
@ -81,7 +81,7 @@ public:
|
||||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||||
|
|
||||||
// nsIScriptGlobalObject methods
|
// nsIScriptGlobalObject methods
|
||||||
virtual void OnFinalize(PRUint32 aLangID, void *aGlobal);
|
virtual void OnFinalize(JSObject* aObject);
|
||||||
virtual void SetScriptsEnabled(PRBool aEnabled, PRBool aFireTimeouts);
|
virtual void SetScriptsEnabled(PRBool aEnabled, PRBool aFireTimeouts);
|
||||||
|
|
||||||
virtual void *GetScriptGlobal(PRUint32 lang);
|
virtual void *GetScriptGlobal(PRUint32 lang);
|
||||||
|
@ -124,7 +124,7 @@ nsXULPDGlobalObject_finalize(JSContext *cx, JSObject *obj)
|
||||||
nsCOMPtr<nsIScriptGlobalObject> sgo(do_QueryInterface(nativeThis));
|
nsCOMPtr<nsIScriptGlobalObject> sgo(do_QueryInterface(nativeThis));
|
||||||
|
|
||||||
if (sgo) {
|
if (sgo) {
|
||||||
sgo->OnFinalize(nsIProgrammingLanguage::JAVASCRIPT, obj);
|
sgo->OnFinalize(obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
// The addref was part of JSObject construction
|
// The addref was part of JSObject construction
|
||||||
|
@ -777,10 +777,8 @@ nsXULPDGlobalObject::ClearGlobalObjectOwner()
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
nsXULPDGlobalObject::OnFinalize(PRUint32 aLangID, void *aObject)
|
nsXULPDGlobalObject::OnFinalize(JSObject* aObject)
|
||||||
{
|
{
|
||||||
NS_ABORT_IF_FALSE(aLangID == nsIProgrammingLanguage::JAVASCRIPT,
|
|
||||||
"We don't support this language ID");
|
|
||||||
mJSObject = NULL;
|
mJSObject = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -207,8 +207,8 @@ nsTemplateCondition::CheckMatchStrings(const nsAString& aLeftString,
|
||||||
if (collation) {
|
if (collation) {
|
||||||
PRInt32 sortOrder;
|
PRInt32 sortOrder;
|
||||||
collation->CompareString((mIgnoreCase ?
|
collation->CompareString((mIgnoreCase ?
|
||||||
nsICollation::kCollationCaseInSensitive :
|
static_cast<PRInt32>(nsICollation::kCollationCaseInSensitive) :
|
||||||
nsICollation::kCollationCaseSensitive),
|
static_cast<PRInt32>(nsICollation::kCollationCaseSensitive)),
|
||||||
aLeftString,
|
aLeftString,
|
||||||
aRightString,
|
aRightString,
|
||||||
&sortOrder);
|
&sortOrder);
|
||||||
|
@ -230,8 +230,8 @@ nsTemplateCondition::CheckMatchStrings(const nsAString& aLeftString,
|
||||||
if (collation) {
|
if (collation) {
|
||||||
PRInt32 sortOrder;
|
PRInt32 sortOrder;
|
||||||
collation->CompareString((mIgnoreCase ?
|
collation->CompareString((mIgnoreCase ?
|
||||||
nsICollation::kCollationCaseInSensitive :
|
static_cast<PRInt32>(nsICollation::kCollationCaseInSensitive) :
|
||||||
nsICollation::kCollationCaseSensitive),
|
static_cast<PRInt32>(nsICollation::kCollationCaseSensitive)),
|
||||||
aLeftString,
|
aLeftString,
|
||||||
aRightString,
|
aRightString,
|
||||||
&sortOrder);
|
&sortOrder);
|
||||||
|
|
|
@ -1538,6 +1538,7 @@ static const nsConstructorFuncMapData kConstructorFuncMap[] =
|
||||||
{
|
{
|
||||||
NS_DEFINE_CONSTRUCTOR_FUNC_DATA(Worker, nsDOMWorker::NewWorker)
|
NS_DEFINE_CONSTRUCTOR_FUNC_DATA(Worker, nsDOMWorker::NewWorker)
|
||||||
NS_DEFINE_CONSTRUCTOR_FUNC_DATA(ChromeWorker, nsDOMWorker::NewChromeWorker)
|
NS_DEFINE_CONSTRUCTOR_FUNC_DATA(ChromeWorker, nsDOMWorker::NewChromeWorker)
|
||||||
|
NS_DEFINE_CONSTRUCTOR_FUNC_DATA(File, nsDOMFile::NewFile)
|
||||||
};
|
};
|
||||||
|
|
||||||
nsIXPConnect *nsDOMClassInfo::sXPConnect = nsnull;
|
nsIXPConnect *nsDOMClassInfo::sXPConnect = nsnull;
|
||||||
|
@ -3911,10 +3912,12 @@ nsDOMClassInfo::Init()
|
||||||
|
|
||||||
DOM_CLASSINFO_MAP_BEGIN(Blob, nsIDOMBlob)
|
DOM_CLASSINFO_MAP_BEGIN(Blob, nsIDOMBlob)
|
||||||
DOM_CLASSINFO_MAP_ENTRY(nsIDOMBlob)
|
DOM_CLASSINFO_MAP_ENTRY(nsIDOMBlob)
|
||||||
|
DOM_CLASSINFO_MAP_ENTRY(nsIDOMBlob_MOZILLA_2_0_BRANCH)
|
||||||
DOM_CLASSINFO_MAP_END
|
DOM_CLASSINFO_MAP_END
|
||||||
|
|
||||||
DOM_CLASSINFO_MAP_BEGIN(File, nsIDOMFile)
|
DOM_CLASSINFO_MAP_BEGIN(File, nsIDOMFile)
|
||||||
DOM_CLASSINFO_MAP_ENTRY(nsIDOMBlob)
|
DOM_CLASSINFO_MAP_ENTRY(nsIDOMBlob)
|
||||||
|
DOM_CLASSINFO_MAP_ENTRY(nsIDOMBlob_MOZILLA_2_0_BRANCH)
|
||||||
DOM_CLASSINFO_MAP_ENTRY(nsIDOMFile)
|
DOM_CLASSINFO_MAP_ENTRY(nsIDOMFile)
|
||||||
DOM_CLASSINFO_MAP_END
|
DOM_CLASSINFO_MAP_END
|
||||||
|
|
||||||
|
@ -7076,7 +7079,7 @@ nsWindowSH::Finalize(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
|
||||||
nsCOMPtr<nsIScriptGlobalObject> sgo(do_QueryWrappedNative(wrapper));
|
nsCOMPtr<nsIScriptGlobalObject> sgo(do_QueryWrappedNative(wrapper));
|
||||||
NS_ENSURE_TRUE(sgo, NS_ERROR_UNEXPECTED);
|
NS_ENSURE_TRUE(sgo, NS_ERROR_UNEXPECTED);
|
||||||
|
|
||||||
sgo->OnFinalize(nsIProgrammingLanguage::JAVASCRIPT, obj);
|
sgo->OnFinalize(obj);
|
||||||
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2760,13 +2760,10 @@ nsGlobalWindow::DispatchDOMEvent(nsEvent* aEvent,
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
nsGlobalWindow::OnFinalize(PRUint32 aLangID, void *aObject)
|
nsGlobalWindow::OnFinalize(JSObject* aObject)
|
||||||
{
|
{
|
||||||
NS_ASSERTION(aLangID == nsIProgrammingLanguage::JAVASCRIPT,
|
|
||||||
"We don't support this language ID");
|
|
||||||
|
|
||||||
if (aObject == mJSObject) {
|
if (aObject == mJSObject) {
|
||||||
mJSObject = nsnull;
|
mJSObject = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10713,12 +10710,6 @@ nsNavigator::GetProductSub(nsAString& aProductSub)
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
nsNavigator::GetSecurityPolicy(nsAString& aSecurityPolicy)
|
|
||||||
{
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsNavigator::GetMimeTypes(nsIDOMMimeTypeArray **aMimeTypes)
|
nsNavigator::GetMimeTypes(nsIDOMMimeTypeArray **aMimeTypes)
|
||||||
{
|
{
|
||||||
|
|
|
@ -320,7 +320,7 @@ public:
|
||||||
// for the context is created by the context's GetNativeGlobal() method.
|
// for the context is created by the context's GetNativeGlobal() method.
|
||||||
virtual nsresult SetScriptContext(PRUint32 lang, nsIScriptContext *aContext);
|
virtual nsresult SetScriptContext(PRUint32 lang, nsIScriptContext *aContext);
|
||||||
|
|
||||||
virtual void OnFinalize(PRUint32 aLangID, void *aScriptGlobal);
|
virtual void OnFinalize(JSObject* aObject);
|
||||||
virtual void SetScriptsEnabled(PRBool aEnabled, PRBool aFireTimeouts);
|
virtual void SetScriptsEnabled(PRBool aEnabled, PRBool aFireTimeouts);
|
||||||
|
|
||||||
// nsIScriptObjectPrincipal
|
// nsIScriptObjectPrincipal
|
||||||
|
|
|
@ -100,12 +100,12 @@ NS_HandleScriptError(nsIScriptGlobalObject *aScriptGlobal,
|
||||||
|
|
||||||
|
|
||||||
#define NS_ISCRIPTGLOBALOBJECT_IID \
|
#define NS_ISCRIPTGLOBALOBJECT_IID \
|
||||||
{ 0xe9f3f2c1, 0x2d94, 0x4722, \
|
{ 0x4eb16819, 0x4e81, 0x406e, \
|
||||||
{ 0xbb, 0xd4, 0x2b, 0xf6, 0xfd, 0xf4, 0x2f, 0x48 } }
|
{ 0x93, 0x05, 0x6f, 0x30, 0xfc, 0xd2, 0x62, 0x4a } }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The global object which keeps a script context for each supported script
|
* The global object which keeps a script context for each supported script
|
||||||
* language. This often used to store per-window global state.
|
* language. This often used to store per-window global state.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class nsIScriptGlobalObject : public nsISupports
|
class nsIScriptGlobalObject : public nsISupports
|
||||||
|
@ -156,8 +156,7 @@ public:
|
||||||
* After this call, the passed object is dead - which should generally be the
|
* After this call, the passed object is dead - which should generally be the
|
||||||
* same object the global is using for a global for that language.
|
* same object the global is using for a global for that language.
|
||||||
*/
|
*/
|
||||||
|
virtual void OnFinalize(JSObject* aObject) = 0;
|
||||||
virtual void OnFinalize(PRUint32 aLangID, void *aScriptGlobal) = 0;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called to enable/disable scripts.
|
* Called to enable/disable scripts.
|
||||||
|
|
|
@ -39,7 +39,7 @@
|
||||||
|
|
||||||
#include "domstubs.idl"
|
#include "domstubs.idl"
|
||||||
|
|
||||||
[scriptable, uuid(777bd8a1-38c1-4b12-ba8f-ff6c2eb8c56b)]
|
[scriptable, uuid(d7758ece-f088-4701-9ae4-1450192dca38)]
|
||||||
interface nsIDOMNavigator : nsISupports
|
interface nsIDOMNavigator : nsISupports
|
||||||
{
|
{
|
||||||
readonly attribute DOMString appCodeName;
|
readonly attribute DOMString appCodeName;
|
||||||
|
@ -54,7 +54,6 @@ interface nsIDOMNavigator : nsISupports
|
||||||
readonly attribute DOMString product;
|
readonly attribute DOMString product;
|
||||||
readonly attribute DOMString productSub;
|
readonly attribute DOMString productSub;
|
||||||
readonly attribute nsIDOMPluginArray plugins;
|
readonly attribute nsIDOMPluginArray plugins;
|
||||||
readonly attribute DOMString securityPolicy;
|
|
||||||
readonly attribute DOMString userAgent;
|
readonly attribute DOMString userAgent;
|
||||||
readonly attribute boolean cookieEnabled;
|
readonly attribute boolean cookieEnabled;
|
||||||
readonly attribute boolean onLine;
|
readonly attribute boolean onLine;
|
||||||
|
|
|
@ -49,12 +49,10 @@
|
||||||
* http://www.w3.org/TR/DOM-Level-2-Core/
|
* http://www.w3.org/TR/DOM-Level-2-Core/
|
||||||
*/
|
*/
|
||||||
|
|
||||||
[scriptable, uuid(5725a7de-2883-45a5-878e-30773cd82478)]
|
[scriptable, uuid(bfd028d4-fbbd-4d69-8899-dbee1778dde2)]
|
||||||
interface nsIDOMDocumentType : nsIDOMNode
|
interface nsIDOMDocumentType : nsIDOMNode
|
||||||
{
|
{
|
||||||
readonly attribute DOMString name;
|
readonly attribute DOMString name;
|
||||||
readonly attribute nsIDOMNamedNodeMap entities;
|
|
||||||
readonly attribute nsIDOMNamedNodeMap notations;
|
|
||||||
readonly attribute DOMString publicId;
|
readonly attribute DOMString publicId;
|
||||||
readonly attribute DOMString systemId;
|
readonly attribute DOMString systemId;
|
||||||
readonly attribute DOMString internalSubset;
|
readonly attribute DOMString internalSubset;
|
||||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче