mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Merge m-c to b2g-inbound.
This commit is contained in:
commit
1618b717b1
@ -12,6 +12,7 @@
|
||||
#include "States.h"
|
||||
|
||||
#include "nsEventStateManager.h"
|
||||
#include "mozilla/Selection.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::a11y;
|
||||
@ -126,13 +127,22 @@ AccShowEvent::
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
AccTextSelChangeEvent::AccTextSelChangeEvent(HyperTextAccessible* aTarget,
|
||||
nsISelection* aSelection) :
|
||||
Selection* aSelection,
|
||||
int32_t aReason) :
|
||||
AccEvent(nsIAccessibleEvent::EVENT_TEXT_SELECTION_CHANGED, aTarget,
|
||||
eAutoDetect, eCoalesceTextSelChange),
|
||||
mSel(aSelection) {}
|
||||
mSel(aSelection), mReason(aReason) {}
|
||||
|
||||
AccTextSelChangeEvent::~AccTextSelChangeEvent() { }
|
||||
|
||||
bool
|
||||
AccTextSelChangeEvent::IsCaretMoveOnly() const
|
||||
{
|
||||
return mSel->GetRangeCount() == 1 && mSel->IsCollapsed() &&
|
||||
((mReason & (nsISelectionListener::COLLAPSETOSTART_REASON |
|
||||
nsISelectionListener::COLLAPSETOEND_REASON)) == 0);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// AccSelChangeEvent
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -10,9 +10,10 @@
|
||||
|
||||
#include "mozilla/a11y/Accessible.h"
|
||||
|
||||
class nsISelection;
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
class Selection;
|
||||
|
||||
namespace a11y {
|
||||
|
||||
class DocAccessible;
|
||||
@ -366,7 +367,8 @@ private:
|
||||
class AccTextSelChangeEvent : public AccEvent
|
||||
{
|
||||
public:
|
||||
AccTextSelChangeEvent(HyperTextAccessible* aTarget, nsISelection* aSelection);
|
||||
AccTextSelChangeEvent(HyperTextAccessible* aTarget, Selection* aSelection,
|
||||
int32_t aReason);
|
||||
virtual ~AccTextSelChangeEvent();
|
||||
|
||||
// AccEvent
|
||||
@ -376,8 +378,16 @@ public:
|
||||
return AccEvent::GetEventGroups() | (1U << eTextSelChangeEvent);
|
||||
}
|
||||
|
||||
// AccTextSelChangeEvent
|
||||
|
||||
/**
|
||||
* Return true if the text selection change wasn't caused by pure caret move.
|
||||
*/
|
||||
bool IsCaretMoveOnly() const;
|
||||
|
||||
private:
|
||||
nsCOMPtr<nsISelection> mSel;
|
||||
nsRefPtr<Selection> mSel;
|
||||
int32_t mReason;
|
||||
|
||||
friend class EventQueue;
|
||||
friend class SelectionManager;
|
||||
|
@ -582,7 +582,8 @@ logging::FocusDispatched(Accessible* aTarget)
|
||||
}
|
||||
|
||||
void
|
||||
logging::SelChange(nsISelection* aSelection, DocAccessible* aDocument)
|
||||
logging::SelChange(nsISelection* aSelection, DocAccessible* aDocument,
|
||||
int16_t aReason)
|
||||
{
|
||||
nsCOMPtr<nsISelectionPrivate> privSel(do_QueryInterface(aSelection));
|
||||
|
||||
@ -598,8 +599,10 @@ logging::SelChange(nsISelection* aSelection, DocAccessible* aDocument)
|
||||
strType = "unknown";
|
||||
|
||||
bool isIgnored = !aDocument || !aDocument->IsContentLoaded();
|
||||
printf("\nSelection changed, selection type: %s, notification %s\n",
|
||||
strType, (isIgnored ? "ignored" : "pending"));
|
||||
printf("\nSelection changed, selection type: %s, notification %s, reason: %d\n",
|
||||
strType, (isIgnored ? "ignored" : "pending"), aReason);
|
||||
|
||||
Stack();
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -118,7 +118,8 @@ void FocusDispatched(Accessible* aTarget);
|
||||
/**
|
||||
* Log the selection change.
|
||||
*/
|
||||
void SelChange(nsISelection* aSelection, DocAccessible* aDocument);
|
||||
void SelChange(nsISelection* aSelection, DocAccessible* aDocument,
|
||||
int16_t aReason);
|
||||
|
||||
/**
|
||||
* Log the message ('title: text' format) on new line. Print the start and end
|
||||
|
@ -14,13 +14,23 @@
|
||||
#include "nsIAccessibleTypes.h"
|
||||
#include "nsIDOMDocument.h"
|
||||
#include "nsIPresShell.h"
|
||||
#include "nsISelectionPrivate.h"
|
||||
#include "mozilla/Selection.h"
|
||||
#include "mozilla/dom/Element.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::a11y;
|
||||
|
||||
struct mozilla::a11y::SelData
|
||||
{
|
||||
SelData(Selection* aSel, int32_t aReason) :
|
||||
mSel(aSel), mReason(aReason) {}
|
||||
|
||||
nsRefPtr<Selection> mSel;
|
||||
int16_t mReason;
|
||||
|
||||
NS_INLINE_DECL_REFCOUNTING(SelData);
|
||||
};
|
||||
|
||||
void
|
||||
SelectionManager::ClearControlSelectionListener()
|
||||
{
|
||||
@ -110,17 +120,16 @@ SelectionManager::RemoveDocSelectionListener(nsIPresShell* aPresShell)
|
||||
void
|
||||
SelectionManager::ProcessTextSelChangeEvent(AccEvent* aEvent)
|
||||
{
|
||||
// Fire selection change event if it's not pure caret-move selection change,
|
||||
// i.e. the accessible has or had not collapsed selection.
|
||||
AccTextSelChangeEvent* event = downcast_accEvent(aEvent);
|
||||
Selection* sel = static_cast<Selection*>(event->mSel.get());
|
||||
|
||||
// Fire selection change event if it's not pure caret-move selection change.
|
||||
if (sel->GetRangeCount() != 1 || !sel->IsCollapsed())
|
||||
if (!event->IsCaretMoveOnly())
|
||||
nsEventShell::FireEvent(aEvent);
|
||||
|
||||
// Fire caret move event if there's a caret in the selection.
|
||||
nsINode* caretCntrNode =
|
||||
nsCoreUtils::GetDOMNodeFromDOMPoint(sel->GetFocusNode(),
|
||||
sel->FocusOffset());
|
||||
nsCoreUtils::GetDOMNodeFromDOMPoint(event->mSel->GetFocusNode(),
|
||||
event->mSel->FocusOffset());
|
||||
if (!caretCntrNode)
|
||||
return;
|
||||
|
||||
@ -150,7 +159,7 @@ SelectionManager::NotifySelectionChanged(nsIDOMDocument* aDOMDocument,
|
||||
|
||||
#ifdef A11Y_LOG
|
||||
if (logging::IsEnabled(logging::eSelection))
|
||||
logging::SelChange(aSelection, document);
|
||||
logging::SelChange(aSelection, document, aReason);
|
||||
#endif
|
||||
|
||||
// Don't fire events until document is loaded.
|
||||
@ -158,17 +167,19 @@ SelectionManager::NotifySelectionChanged(nsIDOMDocument* aDOMDocument,
|
||||
// Selection manager has longer lifetime than any document accessible,
|
||||
// so that we are guaranteed that the notification is processed before
|
||||
// the selection manager is destroyed.
|
||||
document->HandleNotification<SelectionManager, nsISelection>
|
||||
(this, &SelectionManager::ProcessSelectionChanged, aSelection);
|
||||
nsRefPtr<SelData> selData =
|
||||
new SelData(static_cast<Selection*>(aSelection), aReason);
|
||||
document->HandleNotification<SelectionManager, SelData>
|
||||
(this, &SelectionManager::ProcessSelectionChanged, selData);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
SelectionManager::ProcessSelectionChanged(nsISelection* aSelection)
|
||||
SelectionManager::ProcessSelectionChanged(SelData* aSelData)
|
||||
{
|
||||
Selection* selection = static_cast<Selection*>(aSelection);
|
||||
Selection* selection = aSelData->mSel;
|
||||
if (!selection->GetPresShell())
|
||||
return;
|
||||
|
||||
@ -176,11 +187,12 @@ SelectionManager::ProcessSelectionChanged(nsISelection* aSelection)
|
||||
nsINode* cntrNode = nullptr;
|
||||
if (range)
|
||||
cntrNode = range->GetCommonAncestor();
|
||||
|
||||
if (!cntrNode) {
|
||||
cntrNode = selection->GetFrameSelection()->GetAncestorLimiter();
|
||||
if (!cntrNode) {
|
||||
cntrNode = selection->GetPresShell()->GetDocument();
|
||||
NS_ASSERTION(selection->GetPresShell()->ConstFrameSelection() == selection->GetFrameSelection(),
|
||||
NS_ASSERTION(aSelData->mSel->GetPresShell()->ConstFrameSelection() == selection->GetFrameSelection(),
|
||||
"Wrong selection container was used!");
|
||||
}
|
||||
}
|
||||
@ -192,7 +204,8 @@ SelectionManager::ProcessSelectionChanged(nsISelection* aSelection)
|
||||
}
|
||||
|
||||
if (selection->GetType() == nsISelectionController::SELECTION_NORMAL) {
|
||||
nsRefPtr<AccEvent> event = new AccTextSelChangeEvent(text, aSelection);
|
||||
nsRefPtr<AccEvent> event =
|
||||
new AccTextSelChangeEvent(text, selection, aSelData->mReason);
|
||||
text->Document()->FireDelayedEvent(event);
|
||||
|
||||
} else if (selection->GetType() == nsISelectionController::SELECTION_SPELLCHECK) {
|
||||
|
@ -38,6 +38,8 @@ class AccEvent;
|
||||
* selection change events.
|
||||
*/
|
||||
|
||||
struct SelData;
|
||||
|
||||
class SelectionManager : public nsISelectionListener
|
||||
{
|
||||
public:
|
||||
@ -83,7 +85,7 @@ protected:
|
||||
/**
|
||||
* Process DOM selection change. Fire selection and caret move events.
|
||||
*/
|
||||
void ProcessSelectionChanged(nsISelection* aSelection);
|
||||
void ProcessSelectionChanged(SelData* aSelData);
|
||||
|
||||
private:
|
||||
// Currently focused control.
|
||||
|
@ -155,12 +155,18 @@ this.EventManager.prototype = {
|
||||
let event = aEvent.
|
||||
QueryInterface(Ci.nsIAccessibleVirtualCursorChangeEvent);
|
||||
let reason = event.reason;
|
||||
let oldAccessible = event.oldAccessible;
|
||||
|
||||
if (oldAccessible && oldAccessible.role == Roles.INTERNAL_FRAME) {
|
||||
let mm = Utils.getMessageManager(oldAccessible.DOMNode);
|
||||
mm.sendAsyncMessage('AccessFu:ClearCursor', {});
|
||||
}
|
||||
|
||||
if (this.editState.editing) {
|
||||
aEvent.accessibleDocument.takeFocus();
|
||||
}
|
||||
this.present(
|
||||
Presentation.pivotChanged(position, event.oldAccessible, reason,
|
||||
Presentation.pivotChanged(position, oldAccessible, reason,
|
||||
pivot.startOffset, pivot.endOffset));
|
||||
|
||||
break;
|
||||
@ -184,7 +190,7 @@ this.EventManager.prototype = {
|
||||
}
|
||||
case Events.SCROLLING_START:
|
||||
{
|
||||
let vc = Utils.getVirtualCursor(aEvent.accessibleDocument);
|
||||
let vc = Utils.getVirtualCursor(this.contentScope.content.document);
|
||||
vc.moveNext(TraversalRules.Simple, aEvent.accessible, true);
|
||||
break;
|
||||
}
|
||||
@ -275,7 +281,7 @@ this.EventManager.prototype = {
|
||||
let doc = aEvent.accessibleDocument;
|
||||
if (acc.role != Roles.DOCUMENT && doc.role != Roles.CHROME_WINDOW) {
|
||||
this.contentScope.content.clearTimeout(this._autoMove);
|
||||
let vc = Utils.getVirtualCursor(doc);
|
||||
let vc = Utils.getVirtualCursor(this.contentScope.content.document);
|
||||
vc.moveNext(TraversalRules.Simple, acc, true);
|
||||
}
|
||||
break;
|
||||
@ -283,7 +289,7 @@ this.EventManager.prototype = {
|
||||
case Events.DOCUMENT_LOAD_COMPLETE:
|
||||
{
|
||||
this._autoMove = this.contentScope.content.setTimeout(() => {
|
||||
Utils.getVirtualCursor(aEvent.accessibleDocument)
|
||||
Utils.getVirtualCursor(this.contentScope.content.document)
|
||||
.moveNext(TraversalRules.Simple, aEvent.accessible, true);
|
||||
}, 500);
|
||||
break;
|
||||
|
@ -27,6 +27,15 @@ Logger.debug('content-script.js');
|
||||
|
||||
let eventManager = null;
|
||||
|
||||
function clearCursor(aMessage) {
|
||||
try {
|
||||
Utils.getVirtualCursor(content.document).position = null;
|
||||
forwardToChild(aMessage);
|
||||
} catch (x) {
|
||||
Logger.logException(x);
|
||||
}
|
||||
}
|
||||
|
||||
function moveCursor(aMessage) {
|
||||
if (Logger.logLevel >= Logger.DEBUG) {
|
||||
Logger.debug(aMessage.name, JSON.stringify(aMessage.json, null, ' '));
|
||||
@ -144,7 +153,11 @@ function forwardToChild(aMessage, aListener, aVCPosition) {
|
||||
}
|
||||
|
||||
let mm = Utils.getMessageManager(acc.DOMNode);
|
||||
mm.addMessageListener(aMessage.name, aListener);
|
||||
|
||||
if (aListener) {
|
||||
mm.addMessageListener(aMessage.name, aListener);
|
||||
}
|
||||
|
||||
// XXX: This is a silly way to make a deep copy
|
||||
let newJSON = JSON.parse(JSON.stringify(aMessage.json));
|
||||
newJSON.origin = 'parent';
|
||||
@ -381,6 +394,7 @@ addMessageListener(
|
||||
addMessageListener('AccessFu:AdjustRange', adjustRange);
|
||||
addMessageListener('AccessFu:MoveCaret', moveCaret);
|
||||
addMessageListener('AccessFu:MoveByGranularity', moveByGranularity);
|
||||
addMessageListener('AccessFu:ClearCursor', clearCursor);
|
||||
|
||||
if (!eventManager) {
|
||||
eventManager = new EventManager(this);
|
||||
@ -401,6 +415,7 @@ addMessageListener(
|
||||
removeMessageListener('AccessFu:Scroll', scroll);
|
||||
removeMessageListener('AccessFu:MoveCaret', moveCaret);
|
||||
removeMessageListener('AccessFu:MoveByGranularity', moveByGranularity);
|
||||
removeMessageListener('AccessFu:ClearCursor', clearCursor);
|
||||
|
||||
eventManager.stop();
|
||||
});
|
||||
|
@ -16,7 +16,7 @@
|
||||
#include "nsIArray.h"
|
||||
#include "nsIDocument.h"
|
||||
#include "nsIDocShellTreeItem.h"
|
||||
#include "nsIXULRuntime.h"
|
||||
#include "nsXULAppAPI.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::a11y;
|
||||
@ -59,7 +59,7 @@ nsWinUtils::MaybeStartWindowEmulation()
|
||||
// with tabs.
|
||||
if (Compatibility::IsJAWS() || Compatibility::IsWE() ||
|
||||
Compatibility::IsDolphin() ||
|
||||
BrowserTabsRemote()) {
|
||||
XRE_GetProcessType() == GeckoProcessType_Content) {
|
||||
RegisterNativeWindow(kClassNameTabContent);
|
||||
sHWNDCache = new nsRefPtrHashtable<nsPtrHashKey<void>, DocAccessible>(4);
|
||||
return true;
|
||||
|
@ -1212,17 +1212,17 @@ function synthUpKey(aNodeOrID, aCheckerOrEventSeq, aArgs)
|
||||
/**
|
||||
* Left arrow key invoker.
|
||||
*/
|
||||
function synthLeftKey(aNodeOrID, aCheckerOrEventSeq)
|
||||
function synthLeftKey(aNodeOrID, aCheckerOrEventSeq, aArgs)
|
||||
{
|
||||
this.__proto__ = new synthKey(aNodeOrID, "VK_LEFT", null, aCheckerOrEventSeq);
|
||||
this.__proto__ = new synthKey(aNodeOrID, "VK_LEFT", aArgs, aCheckerOrEventSeq);
|
||||
}
|
||||
|
||||
/**
|
||||
* Right arrow key invoker.
|
||||
*/
|
||||
function synthRightKey(aNodeOrID, aCheckerOrEventSeq)
|
||||
function synthRightKey(aNodeOrID, aCheckerOrEventSeq, aArgs)
|
||||
{
|
||||
this.__proto__ = new synthKey(aNodeOrID, "VK_RIGHT", null, aCheckerOrEventSeq);
|
||||
this.__proto__ = new synthKey(aNodeOrID, "VK_RIGHT", aArgs, aCheckerOrEventSeq);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1764,7 +1764,12 @@ function textSelectionChecker(aID, aStartOffset, aEndOffset)
|
||||
|
||||
this.check = function textSelectionChecker_check(aEvent)
|
||||
{
|
||||
testTextGetSelection(aID, aStartOffset, aEndOffset, 0);
|
||||
if (aStartOffset == aEndOffset) {
|
||||
is(getAccessible(aID, [nsIAccessibleText]).caretOffset, aStartOffset,
|
||||
"Wrong collapsed selection!");
|
||||
} else {
|
||||
testTextGetSelection(aID, aStartOffset, aEndOffset, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -24,19 +24,30 @@
|
||||
// gA11yEventDumpID = "eventdump"; // debug stuff
|
||||
//gA11yEventDumpToConsole = true;
|
||||
|
||||
function getOnclickSeq(aID)
|
||||
{
|
||||
return [
|
||||
new caretMoveChecker(0, aID),
|
||||
new unexpectedInvokerChecker(EVENT_TEXT_SELECTION_CHANGED, aID)
|
||||
];
|
||||
}
|
||||
|
||||
function doTests()
|
||||
{
|
||||
// test caret move events and caret offsets
|
||||
gQueue = new eventQueue();
|
||||
|
||||
var onclickSeq = [
|
||||
new caretMoveChecker(0, "c1_p1"),
|
||||
new unexpectedInvokerChecker(EVENT_TEXT_SELECTION_CHANGED, "c1_p1")
|
||||
];
|
||||
gQueue.push(new synthClick("c1_p1", onclickSeq));
|
||||
gQueue.push(new synthClick("c1_p1", getOnclickSeq("c1_p1")));
|
||||
gQueue.push(new synthDownKey("c1", new textSelectionChecker("c1", 0, 1), { shiftKey: true }));
|
||||
gQueue.push(new synthDownKey("c1", new textSelectionChecker("c1", 0, 2), { shiftKey: true }));
|
||||
|
||||
gQueue.push(new synthClick("ta1", getOnclickSeq("ta1")));
|
||||
gQueue.push(new synthRightKey("ta1",
|
||||
new textSelectionChecker("ta1", 0, 1),
|
||||
{ shiftKey: true }));
|
||||
gQueue.push(new synthLeftKey("ta1",
|
||||
new textSelectionChecker("ta1", 0, 0)));
|
||||
|
||||
gQueue.invoke(); // Will call SimpleTest.finish();
|
||||
}
|
||||
|
||||
@ -52,6 +63,11 @@
|
||||
title="Text selection change event has a wrong target when selection is spanned through several objects">
|
||||
Bug 762934
|
||||
</a>
|
||||
<a target="_blank"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=956032"
|
||||
title="Text selection change event missed when selected text becomes unselected">
|
||||
Bug 956032
|
||||
</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none"></div>
|
||||
<pre id="test">
|
||||
@ -62,6 +78,8 @@
|
||||
<p id="c1_p2">paragraph</p>
|
||||
</div>
|
||||
|
||||
<textarea id="ta1">Hello world</textarea>
|
||||
|
||||
<div id="eventdump"></div>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -978,7 +978,16 @@ pref("dom.ipc.plugins.enabled.x86_64", true);
|
||||
pref("dom.ipc.plugins.enabled", true);
|
||||
#endif
|
||||
|
||||
#if defined(NIGHTLY_BUILD) && defined(XP_MACOSX)
|
||||
// In Nightly, browser.tabs.remote is enabled on platforms that
|
||||
// support OMTC. However, users won't actually get remote tabs unless
|
||||
// they enable browser.tabs.remote.autostart or they use the "New OOP
|
||||
// Window" menu option.
|
||||
pref("browser.tabs.remote", true);
|
||||
#else
|
||||
pref("browser.tabs.remote", false);
|
||||
#endif
|
||||
pref("browser.tabs.remote.autostart", false);
|
||||
|
||||
// This pref governs whether we attempt to work around problems caused by
|
||||
// plugins using OS calls to manipulate the cursor while running out-of-
|
||||
|
@ -27,6 +27,14 @@
|
||||
accesskey="&newPrivateWindow.accesskey;"
|
||||
command="Tools:PrivateBrowsing"
|
||||
key="key_privatebrowsing"/>
|
||||
<menuitem id="menu_newRemoteWindow"
|
||||
label="New OOP Window"
|
||||
hidden="true"
|
||||
command="Tools:RemoteWindow"/>
|
||||
<menuitem id="menu_newNonRemoteWindow"
|
||||
label="New In-process Window"
|
||||
hidden="true"
|
||||
command="Tools:NonRemoteWindow"/>
|
||||
<menuitem id="menu_openFile"
|
||||
label="&openFileCmd.label;"
|
||||
command="Browser:OpenFile"
|
||||
|
@ -20,7 +20,7 @@
|
||||
<command id="cmd_handleBackspace" oncommand="BrowserHandleBackspace();" />
|
||||
<command id="cmd_handleShiftBackspace" oncommand="BrowserHandleShiftBackspace();" />
|
||||
|
||||
<command id="cmd_newNavigatorTab" oncommand="BrowserOpenTab();"/>
|
||||
<command id="cmd_newNavigatorTab" oncommand="BrowserOpenNewTabOrWindow(event);"/>
|
||||
<command id="Browser:OpenFile" oncommand="BrowserOpenFileWindow();"/>
|
||||
<command id="Browser:SavePage" oncommand="saveDocument(window.content.document);"/>
|
||||
|
||||
@ -106,6 +106,10 @@
|
||||
oncommand="Cc['@mozilla.org/browser/browserglue;1'].getService(Ci.nsIBrowserGlue).sanitize(window);"/>
|
||||
<command id="Tools:PrivateBrowsing"
|
||||
oncommand="OpenBrowserWindow({private: true});"/>
|
||||
<command id="Tools:RemoteWindow"
|
||||
oncommand="OpenBrowserWindow({remote: true});"/>
|
||||
<command id="Tools:NonRemoteWindow"
|
||||
oncommand="OpenBrowserWindow({remote: false});"/>
|
||||
<command id="History:UndoCloseTab" oncommand="undoCloseTab();"/>
|
||||
<command id="History:UndoCloseWindow" oncommand="undoCloseWindow();"/>
|
||||
<command id="Social:SharePage" oncommand="SocialShare.sharePage();" disabled="true"/>
|
||||
|
@ -202,14 +202,9 @@ var ctrlTab = {
|
||||
list = list.filter(function (tab) !tab.closing);
|
||||
|
||||
if (this.recentlyUsedLimit != 0) {
|
||||
let recentlyUsedTabs = [];
|
||||
for (let tab of this._recentlyUsedTabs) {
|
||||
if (!tab.hidden && !tab.closing) {
|
||||
recentlyUsedTabs.push(tab);
|
||||
if (this.recentlyUsedLimit > 0 && recentlyUsedTabs.length >= this.recentlyUsedLimit)
|
||||
break;
|
||||
}
|
||||
}
|
||||
let recentlyUsedTabs = this._recentlyUsedTabs;
|
||||
if (this.recentlyUsedLimit > 0)
|
||||
recentlyUsedTabs = this._recentlyUsedTabs.slice(0, this.recentlyUsedLimit);
|
||||
for (let i = recentlyUsedTabs.length - 1; i >= 0; i--) {
|
||||
list.splice(list.indexOf(recentlyUsedTabs[i]), 1);
|
||||
list.unshift(recentlyUsedTabs[i]);
|
||||
|
@ -757,7 +757,11 @@ var gBrowserInit = {
|
||||
delayedStartupFinished: false,
|
||||
|
||||
onLoad: function() {
|
||||
gMultiProcessBrowser = Services.appinfo.browserTabsRemote;
|
||||
gMultiProcessBrowser =
|
||||
window.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIWebNavigation)
|
||||
.QueryInterface(Ci.nsILoadContext)
|
||||
.useRemoteTabs;
|
||||
|
||||
var mustLoadSidebar = false;
|
||||
|
||||
@ -1023,6 +1027,7 @@ var gBrowserInit = {
|
||||
IndexedDBPromptHelper.init();
|
||||
gFormSubmitObserver.init();
|
||||
SocialUI.init();
|
||||
gRemoteTabsUI.init();
|
||||
|
||||
// Initialize the full zoom setting.
|
||||
// We do this before the session restore service gets initialized so we can
|
||||
@ -3186,6 +3191,12 @@ function OpenBrowserWindow(options)
|
||||
extraFeatures = ",non-private";
|
||||
}
|
||||
|
||||
if (options && options.remote) {
|
||||
extraFeatures += ",remote";
|
||||
} else if (options && options.remote === false) {
|
||||
extraFeatures += ",non-remote";
|
||||
}
|
||||
|
||||
// if and only if the current window is a browser window and it has a document with a character
|
||||
// set, then extract the current charset menu setting from the current document and use it to
|
||||
// initialize the new browser window...
|
||||
@ -6866,6 +6877,28 @@ let gPrivateBrowsingUI = {
|
||||
}
|
||||
};
|
||||
|
||||
let gRemoteTabsUI = {
|
||||
init: function() {
|
||||
if (window.location.href != getBrowserURL()) {
|
||||
return;
|
||||
}
|
||||
|
||||
let remoteTabs = gPrefService.getBoolPref("browser.tabs.remote");
|
||||
let autostart = gPrefService.getBoolPref("browser.tabs.remote.autostart");
|
||||
|
||||
let newRemoteWindow = document.getElementById("menu_newRemoteWindow");
|
||||
let newNonRemoteWindow = document.getElementById("menu_newNonRemoteWindow");
|
||||
|
||||
if (!remoteTabs) {
|
||||
newRemoteWindow.hidden = true;
|
||||
newNonRemoteWindow.hidden = true;
|
||||
return;
|
||||
}
|
||||
|
||||
newRemoteWindow.hidden = autostart;
|
||||
newNonRemoteWindow.hidden = !autostart;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Switch to a tab that has a given URI, and focusses its browser window.
|
||||
@ -7203,3 +7236,11 @@ let BrowserChromeTest = {
|
||||
this._cb = cb;
|
||||
}
|
||||
};
|
||||
|
||||
function BrowserOpenNewTabOrWindow(event) {
|
||||
if (event.shiftKey) {
|
||||
OpenBrowserWindow();
|
||||
} else {
|
||||
BrowserOpenTab();
|
||||
}
|
||||
}
|
||||
|
@ -35,7 +35,7 @@ addMessageListener("Browser:HideSessionRestoreButton", function (message) {
|
||||
}
|
||||
});
|
||||
|
||||
if (Services.prefs.getBoolPref("browser.tabs.remote")) {
|
||||
if (Services.appinfo.processType == Services.appinfo.PROCESS_TYPE_CONTENT) {
|
||||
addEventListener("contextmenu", function (event) {
|
||||
sendAsyncMessage("contextmenu", {}, { event: event });
|
||||
}, false);
|
||||
|
@ -3054,7 +3054,11 @@
|
||||
"-moz-default-background-color" :
|
||||
Services.prefs.getCharPref("browser.display.background_color");
|
||||
|
||||
if (Services.appinfo.browserTabsRemote) {
|
||||
let remote = window.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIWebNavigation)
|
||||
.QueryInterface(Ci.nsILoadContext)
|
||||
.useRemoteTabs;
|
||||
if (remote) {
|
||||
messageManager.addMessageListener("DOMTitleChanged", this);
|
||||
messageManager.addMessageListener("contextmenu", this);
|
||||
}
|
||||
@ -3121,7 +3125,7 @@
|
||||
document.removeEventListener("keypress", this, false);
|
||||
window.removeEventListener("sizemodechange", this, false);
|
||||
|
||||
if (Services.appinfo.browserTabsRemote) {
|
||||
if (gMultiProcessBrowser) {
|
||||
messageManager.removeMessageListener("DOMTitleChanged", this);
|
||||
messageManager.removeMessageListener("contextmenu", this);
|
||||
}
|
||||
|
@ -729,21 +729,23 @@ function test22() {
|
||||
is(objLoadingContent.displayedType, Ci.nsIObjectLoadingContent.TYPE_PLUGIN, "Test 22, plugin should have started");
|
||||
ok(pluginNode.activated, "Test 22, plugin should be activated");
|
||||
|
||||
// Reload plugin
|
||||
var oldVal = pluginNode.getObjectValue();
|
||||
pluginNode.src = pluginNode.src;
|
||||
is(objLoadingContent.displayedType, Ci.nsIObjectLoadingContent.TYPE_PLUGIN, "Test 22, Plugin should have retained activated state");
|
||||
ok(pluginNode.activated, "Test 22, plugin should have remained activated");
|
||||
// Sanity, ensure that we actually reloaded the instance, since this behavior might change in the future.
|
||||
var pluginsDiffer;
|
||||
try {
|
||||
pluginNode.checkObjectValue(oldVal);
|
||||
} catch (e) {
|
||||
pluginsDiffer = true;
|
||||
}
|
||||
ok(pluginsDiffer, "Test 22, plugin should have reloaded");
|
||||
// Spin event loop for plugin to finish spawning
|
||||
executeSoon(function() {
|
||||
var oldVal = pluginNode.getObjectValue();
|
||||
pluginNode.src = pluginNode.src;
|
||||
is(objLoadingContent.displayedType, Ci.nsIObjectLoadingContent.TYPE_PLUGIN, "Test 22, Plugin should have retained activated state");
|
||||
ok(pluginNode.activated, "Test 22, plugin should have remained activated");
|
||||
// Sanity, ensure that we actually reloaded the instance, since this behavior might change in the future.
|
||||
var pluginsDiffer;
|
||||
try {
|
||||
pluginNode.checkObjectValue(oldVal);
|
||||
} catch (e) {
|
||||
pluginsDiffer = true;
|
||||
}
|
||||
ok(pluginsDiffer, "Test 22, plugin should have reloaded");
|
||||
|
||||
prepareTest(runAfterPluginBindingAttached(test23), gTestRoot + "plugin_test.html");
|
||||
prepareTest(runAfterPluginBindingAttached(test23), gTestRoot + "plugin_test.html");
|
||||
});
|
||||
}
|
||||
|
||||
// Tests that a click-to-play plugin resets its activated state when changing types
|
||||
|
@ -120,7 +120,6 @@
|
||||
oncommand="PlacesCommandHook.showPlacesOrganizer('UnfiledBookmarks'); PanelUI.hide();"/>
|
||||
<toolbarseparator/>
|
||||
<toolbaritem id="panelMenu_bookmarksMenu"
|
||||
flex="1"
|
||||
orient="vertical"
|
||||
smoothscroll="false"
|
||||
onclick="if (event.button == 1) BookmarkingUI.onPanelMenuViewCommand(event, this._placesView);"
|
||||
@ -145,7 +144,7 @@
|
||||
|
||||
<panelview id="PanelUI-helpView" flex="1" class="PanelUI-subView">
|
||||
<label value="&helpMenu.label;" class="panel-subview-header"/>
|
||||
<vbox id="PanelUI-helpItems"/>
|
||||
<vbox id="PanelUI-helpItems" class="panel-subview-body"/>
|
||||
</panelview>
|
||||
|
||||
<panelview id="PanelUI-developer" flex="1">
|
||||
|
@ -303,6 +303,7 @@ const PanelUI = {
|
||||
|
||||
let multiView = document.createElement("panelmultiview");
|
||||
tempPanel.appendChild(multiView);
|
||||
multiView.setAttribute("mainViewIsSubView", "true");
|
||||
multiView.setMainView(viewNode);
|
||||
viewNode.classList.add("cui-widget-panelview");
|
||||
CustomizableUI.addPanelCloseListeners(tempPanel);
|
||||
|
@ -66,6 +66,8 @@
|
||||
<property name="_mainViewId" onget="return this.getAttribute('mainViewId');" onset="this.setAttribute('mainViewId', val); return val;"/>
|
||||
<property name="_mainView" readonly="true"
|
||||
onget="return this._mainViewId ? document.getElementById(this._mainViewId) : null;"/>
|
||||
<property name="showingSubViewAsMainView" readonly="true"
|
||||
onget="return this.getAttribute('mainViewIsSubView') == 'true'"/>
|
||||
|
||||
<property name="ignoreMutations">
|
||||
<getter>
|
||||
@ -322,8 +324,13 @@
|
||||
<method name="_syncContainerWithMainView">
|
||||
<body><![CDATA[
|
||||
if (!this.ignoreMutations && !this.showingSubView && !this._transitioning) {
|
||||
this._viewContainer.style.height =
|
||||
this._mainView.scrollHeight + "px";
|
||||
let height;
|
||||
if (this.showingSubViewAsMainView) {
|
||||
height = this._heightOfSubview(this._mainView);
|
||||
} else {
|
||||
height = this._mainView.scrollHeight;
|
||||
}
|
||||
this._viewContainer.style.height = height + "px";
|
||||
}
|
||||
]]></body>
|
||||
</method>
|
||||
|
@ -3139,7 +3139,7 @@ function WidgetSingleWrapper(aWidget, aNode) {
|
||||
this.__defineGetter__("anchor", function() {
|
||||
let anchorId;
|
||||
// First check for an anchor for the area:
|
||||
let placement = CustomizableUIInternal.getPlacementOfWidget(aWidgetId);
|
||||
let placement = CustomizableUIInternal.getPlacementOfWidget(aWidget.id);
|
||||
if (placement) {
|
||||
anchorId = gAreas.get(placement.area).get("anchor");
|
||||
}
|
||||
|
@ -854,6 +854,7 @@ CustomizeMode.prototype = {
|
||||
this.persistCurrentSets(true);
|
||||
|
||||
this._updateResetButton();
|
||||
this._updateEmptyPaletteNotice();
|
||||
this._showPanelCustomizationPlaceholders();
|
||||
this.resetting = false;
|
||||
}.bind(this)).then(null, ERROR);
|
||||
@ -955,8 +956,10 @@ CustomizeMode.prototype = {
|
||||
|
||||
_onUIChange: function() {
|
||||
this._changed = true;
|
||||
this._updateResetButton();
|
||||
this._updateEmptyPaletteNotice();
|
||||
if (!this.resetting) {
|
||||
this._updateResetButton();
|
||||
this._updateEmptyPaletteNotice();
|
||||
}
|
||||
this.dispatchToolboxEvent("customizationchange");
|
||||
},
|
||||
|
||||
|
18
browser/config/mozconfigs/hazards
Normal file
18
browser/config/mozconfigs/hazards
Normal file
@ -0,0 +1,18 @@
|
||||
# This mozconfig is used when compiling the browser for the SM(Hf) rooting
|
||||
# hazard analysis build, see
|
||||
# https://wiki.mozilla.org/Javascript:SpiderMonkey:ExactStackRooting
|
||||
|
||||
. "$topsrcdir/build/unix/mozconfig.linux"
|
||||
|
||||
# The configuration options are chosen to compile the most code
|
||||
# (--enable-debug, --enable-tests) in the trickiest way possible
|
||||
# (--enable-optimize) to maximize the chance of seeing tricky static orderings.
|
||||
ac_add_options --enable-debug
|
||||
ac_add_options --enable-tests
|
||||
ac_add_options --enable-optimize
|
||||
|
||||
CFLAGS="$CFLAGS -Wno-attributes"
|
||||
CPPFLAGS="$CPPFLAGS -Wno-attributes"
|
||||
CXXFLAGS="$CXXFLAGS -Wno-attributes"
|
||||
|
||||
. "$topsrcdir/build/mozconfig.common.override"
|
@ -29,6 +29,9 @@ const EVENTS = {
|
||||
SOURCE_SHOWN: "Debugger:EditorSourceShown",
|
||||
SOURCE_ERROR_SHOWN: "Debugger:EditorSourceErrorShown",
|
||||
|
||||
// When the editor has shown a source and set the line / column position
|
||||
EDITOR_LOCATION_SET: "Debugger:EditorLocationSet",
|
||||
|
||||
// When scopes, variables, properties and watch expressions are fetched and
|
||||
// displayed in the variables view.
|
||||
FETCHED_SCOPES: "Debugger:FetchedScopes",
|
||||
@ -1300,7 +1303,7 @@ SourceScripts.prototype = {
|
||||
deferred.promise.pretty = wantPretty;
|
||||
this._cache.set(aSource.url, deferred.promise);
|
||||
|
||||
const afterToggle = ({ error, message, source: text }) => {
|
||||
const afterToggle = ({ error, message, source: text, contentType }) => {
|
||||
if (error) {
|
||||
// Revert the rejected promise from the cache, so that the original
|
||||
// source's text may be shown when the source is selected.
|
||||
@ -1308,7 +1311,7 @@ SourceScripts.prototype = {
|
||||
deferred.reject([aSource, message || error]);
|
||||
return;
|
||||
}
|
||||
deferred.resolve([aSource, text]);
|
||||
deferred.resolve([aSource, text, contentType]);
|
||||
};
|
||||
|
||||
if (wantPretty) {
|
||||
@ -1360,14 +1363,15 @@ SourceScripts.prototype = {
|
||||
}
|
||||
|
||||
// Get the source text from the active thread.
|
||||
this.activeThread.source(aSource).source(({ error, message, source: text }) => {
|
||||
this.activeThread.source(aSource)
|
||||
.source(({ error, message, source: text, contentType }) => {
|
||||
if (aOnTimeout) {
|
||||
window.clearTimeout(fetchTimeout);
|
||||
}
|
||||
if (error) {
|
||||
deferred.reject([aSource, message || error]);
|
||||
} else {
|
||||
deferred.resolve([aSource, text]);
|
||||
deferred.resolve([aSource, text, contentType]);
|
||||
}
|
||||
});
|
||||
|
||||
@ -1406,13 +1410,13 @@ SourceScripts.prototype = {
|
||||
}
|
||||
|
||||
/* Called if fetching a source finishes successfully. */
|
||||
function onFetch([aSource, aText]) {
|
||||
function onFetch([aSource, aText, aContentType]) {
|
||||
// If fetching the source has previously timed out, discard it this time.
|
||||
if (!pending.has(aSource.url)) {
|
||||
return;
|
||||
}
|
||||
pending.delete(aSource.url);
|
||||
fetched.push([aSource.url, aText]);
|
||||
fetched.push([aSource.url, aText, aContentType]);
|
||||
maybeFinish();
|
||||
}
|
||||
|
||||
|
@ -388,7 +388,8 @@ let DebuggerView = {
|
||||
this._setEditorText(L10N.getStr("loadingText"));
|
||||
this._editorSource = { url: aSource.url, promise: deferred.promise };
|
||||
|
||||
DebuggerController.SourceScripts.getText(aSource).then(([, aText]) => {
|
||||
DebuggerController.SourceScripts.getText(aSource)
|
||||
.then(([, aText, aContentType]) => {
|
||||
// Avoid setting an unexpected source. This may happen when switching
|
||||
// very fast between sources that haven't been fetched yet.
|
||||
if (this._editorSource.url != aSource.url) {
|
||||
@ -396,7 +397,7 @@ let DebuggerView = {
|
||||
}
|
||||
|
||||
this._setEditorText(aText);
|
||||
this._setEditorMode(aSource.url, aSource.contentType, aText);
|
||||
this._setEditorMode(aSource.url, aContentType, aText);
|
||||
|
||||
// Synchronize any other components with the currently displayed source.
|
||||
DebuggerView.Sources.selectedValue = aSource.url;
|
||||
@ -406,7 +407,7 @@ let DebuggerView = {
|
||||
|
||||
// Resolve and notify that a source file was shown.
|
||||
window.emit(EVENTS.SOURCE_SHOWN, aSource);
|
||||
deferred.resolve([aSource, aText]);
|
||||
deferred.resolve([aSource, aText, aContentType]);
|
||||
},
|
||||
([, aError]) => {
|
||||
let msg = L10N.getStr("errorLoadingText") + DevToolsUtils.safeErrorString(aError);
|
||||
@ -466,10 +467,14 @@ let DebuggerView = {
|
||||
|
||||
// Make sure the requested source client is shown in the editor, then
|
||||
// update the source editor's caret position and debug location.
|
||||
return this._setEditorSource(sourceForm, aFlags).then(() => {
|
||||
return this._setEditorSource(sourceForm, aFlags)
|
||||
.then(([,, aContentType]) => {
|
||||
// Record the contentType learned from fetching
|
||||
sourceForm.contentType = aContentType;
|
||||
// Line numbers in the source editor should start from 1. If invalid
|
||||
// or not specified, then don't do anything.
|
||||
if (aLine < 1) {
|
||||
window.emit(EVENTS.EDITOR_LOCATION_SET);
|
||||
return;
|
||||
}
|
||||
if (aFlags.charOffset) {
|
||||
@ -485,6 +490,7 @@ let DebuggerView = {
|
||||
if (!aFlags.noDebug) {
|
||||
this.editor.setDebugLocation(aLine - 1);
|
||||
}
|
||||
window.emit(EVENTS.EDITOR_LOCATION_SET);
|
||||
}).then(null, console.error);
|
||||
},
|
||||
|
||||
|
@ -28,6 +28,8 @@ support-files =
|
||||
code_ugly-5.js
|
||||
code_ugly-6.js
|
||||
code_ugly-7.js
|
||||
code_ugly-8
|
||||
code_ugly-8^headers^
|
||||
doc_auto-pretty-print-01.html
|
||||
doc_auto-pretty-print-02.html
|
||||
doc_binary_search.html
|
||||
@ -56,6 +58,7 @@ support-files =
|
||||
doc_pause-exceptions.html
|
||||
doc_pretty-print.html
|
||||
doc_pretty-print-2.html
|
||||
doc_pretty-print-3.html
|
||||
doc_random-javascript.html
|
||||
doc_recursion-stack.html
|
||||
doc_scope-variable.html
|
||||
@ -161,6 +164,7 @@ support-files =
|
||||
[browser_dbg_pretty-print-10.js]
|
||||
[browser_dbg_pretty-print-11.js]
|
||||
[browser_dbg_pretty-print-12.js]
|
||||
[browser_dbg_pretty-print-13.js]
|
||||
[browser_dbg_progress-listener-bug.js]
|
||||
[browser_dbg_reload-preferred-script-01.js]
|
||||
[browser_dbg_reload-preferred-script-02.js]
|
||||
|
@ -0,0 +1,87 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Make sure that clicking the pretty print button prettifies the source, even
|
||||
* when the source URL does not end in ".js", but the content type is
|
||||
* JavaScript.
|
||||
*/
|
||||
|
||||
const TAB_URL = EXAMPLE_URL + "doc_pretty-print-3.html";
|
||||
|
||||
let gTab, gDebuggee, gPanel, gDebugger;
|
||||
let gEditor, gSources;
|
||||
|
||||
function test() {
|
||||
initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => {
|
||||
gTab = aTab;
|
||||
gDebuggee = aDebuggee;
|
||||
gPanel = aPanel;
|
||||
gDebugger = gPanel.panelWin;
|
||||
gEditor = gDebugger.DebuggerView.editor;
|
||||
gSources = gDebugger.DebuggerView.Sources;
|
||||
|
||||
promise.all([waitForSourceShown(gPanel, "code_ugly-8"),
|
||||
waitForEditorLocationSet(gPanel)])
|
||||
.then(testSourceIsUgly)
|
||||
.then(() => {
|
||||
const finished = waitForSourceShown(gPanel, "code_ugly-8");
|
||||
clickPrettyPrintButton();
|
||||
testProgressBarShown();
|
||||
return finished;
|
||||
})
|
||||
.then(testSourceIsPretty)
|
||||
.then(testEditorShown)
|
||||
.then(testSourceIsStillPretty)
|
||||
.then(() => closeDebuggerAndFinish(gPanel))
|
||||
.then(null, aError => {
|
||||
ok(false, "Got an error: " + DevToolsUtils.safeErrorString(aError));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function testSourceIsUgly() {
|
||||
ok(!gEditor.getText().contains("\n "),
|
||||
"The source shouldn't be pretty printed yet.");
|
||||
}
|
||||
|
||||
function clickPrettyPrintButton() {
|
||||
gDebugger.document.getElementById("pretty-print").click();
|
||||
}
|
||||
|
||||
function testProgressBarShown() {
|
||||
const deck = gDebugger.document.getElementById("editor-deck");
|
||||
is(deck.selectedIndex, 2, "The progress bar should be shown");
|
||||
}
|
||||
|
||||
function testSourceIsPretty() {
|
||||
ok(gEditor.getText().contains("\n "),
|
||||
"The source should be pretty printed.")
|
||||
}
|
||||
|
||||
function testEditorShown() {
|
||||
const deck = gDebugger.document.getElementById("editor-deck");
|
||||
is(deck.selectedIndex, 0, "The editor should be shown");
|
||||
}
|
||||
|
||||
function testSourceIsStillPretty() {
|
||||
const deferred = promise.defer();
|
||||
|
||||
const { source } = gSources.selectedItem.attachment;
|
||||
gDebugger.DebuggerController.SourceScripts.getText(source).then(([, text]) => {
|
||||
ok(text.contains("\n "),
|
||||
"Subsequent calls to getText return the pretty printed source.");
|
||||
deferred.resolve();
|
||||
});
|
||||
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
registerCleanupFunction(function() {
|
||||
gTab = null;
|
||||
gDebuggee = null;
|
||||
gPanel = null;
|
||||
gDebugger = null;
|
||||
gEditor = null;
|
||||
gSources = null;
|
||||
});
|
3
browser/devtools/debugger/test/code_ugly-8
Normal file
3
browser/devtools/debugger/test/code_ugly-8
Normal file
@ -0,0 +1,3 @@
|
||||
function foo() { var a=1; var b=2; bar(a, b); }
|
||||
function bar(c, d) { debugger; }
|
||||
foo();
|
1
browser/devtools/debugger/test/code_ugly-8^headers^
Normal file
1
browser/devtools/debugger/test/code_ugly-8^headers^
Normal file
@ -0,0 +1 @@
|
||||
Content-Type: application/javascript
|
8
browser/devtools/debugger/test/doc_pretty-print-3.html
Normal file
8
browser/devtools/debugger/test/doc_pretty-print-3.html
Normal file
@ -0,0 +1,8 @@
|
||||
<!-- Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ -->
|
||||
<!DOCTYPE html>
|
||||
<head>
|
||||
<meta charset="utf-8"/>
|
||||
<title>Debugger Pretty Printing Test Page</title>
|
||||
</head>
|
||||
<script src="code_ugly-8"></script>
|
@ -236,6 +236,11 @@ function waitForSourceShown(aPanel, aUrl) {
|
||||
});
|
||||
}
|
||||
|
||||
function waitForEditorLocationSet(aPanel) {
|
||||
return waitForDebuggerEvents(aPanel,
|
||||
aPanel.panelWin.EVENTS.EDITOR_LOCATION_SET);
|
||||
}
|
||||
|
||||
function ensureSourceIs(aPanel, aUrl, aWaitFlag = false) {
|
||||
if (aPanel.panelWin.DebuggerView.Sources.selectedValue.contains(aUrl)) {
|
||||
ok(true, "Expected source is shown: " + aUrl);
|
||||
|
@ -205,7 +205,8 @@ StyleEditorUI.prototype = {
|
||||
// remember saved file locations
|
||||
for (let editor of this.editors) {
|
||||
if (editor.savedFile) {
|
||||
this.savedLocations[editor.styleSheet.href] = editor.savedFile;
|
||||
let identifier = this.getStyleSheetIdentifier(editor.styleSheet);
|
||||
this.savedLocations[identifier] = editor.savedFile;
|
||||
}
|
||||
}
|
||||
|
||||
@ -257,7 +258,8 @@ StyleEditorUI.prototype = {
|
||||
*/
|
||||
_addStyleSheetEditor: function(styleSheet, file, isNew) {
|
||||
// recall location of saved file for this sheet after page reload
|
||||
let savedFile = this.savedLocations[styleSheet.href];
|
||||
let identifier = this.getStyleSheetIdentifier(styleSheet);
|
||||
let savedFile = this.savedLocations[identifier];
|
||||
if (savedFile && !file) {
|
||||
file = savedFile;
|
||||
}
|
||||
@ -526,6 +528,18 @@ StyleEditorUI.prototype = {
|
||||
return deferred.promise;
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns an identifier for the given style sheet.
|
||||
*
|
||||
* @param {StyleSheet} aStyleSheet
|
||||
* The style sheet to be identified.
|
||||
*/
|
||||
getStyleSheetIdentifier: function (aStyleSheet) {
|
||||
// Identify inline style sheets by their host page URI and index at the page.
|
||||
return aStyleSheet.href ? aStyleSheet.href :
|
||||
"inline-" + aStyleSheet.styleSheetIndex + "-at-" + aStyleSheet.nodeHref;
|
||||
},
|
||||
|
||||
/**
|
||||
* selects a stylesheet and optionally moves the cursor to a selected line
|
||||
*
|
||||
|
@ -7,6 +7,8 @@ support-files =
|
||||
import.css
|
||||
import.html
|
||||
import2.css
|
||||
inline-1.html
|
||||
inline-2.html
|
||||
longload.html
|
||||
media-small.css
|
||||
media.html
|
||||
@ -37,6 +39,7 @@ support-files =
|
||||
[browser_styleeditor_import.js]
|
||||
[browser_styleeditor_import_rule.js]
|
||||
[browser_styleeditor_init.js]
|
||||
[browser_styleeditor_inline_friendly_names.js]
|
||||
[browser_styleeditor_loading.js]
|
||||
[browser_styleeditor_new.js]
|
||||
[browser_styleeditor_nostyle.js]
|
||||
|
@ -0,0 +1,150 @@
|
||||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
let gUI;
|
||||
|
||||
const FIRST_TEST_PAGE = TEST_BASE + "inline-1.html"
|
||||
const SECOND_TEST_PAGE = TEST_BASE + "inline-2.html"
|
||||
const SAVE_PATH = "test.css";
|
||||
|
||||
function test()
|
||||
{
|
||||
waitForExplicitFinish();
|
||||
|
||||
addTabAndOpenStyleEditor(function(panel) {
|
||||
gUI = panel.UI;
|
||||
|
||||
// First test that identifiers are correcly generated. If not other tests
|
||||
// are likely to fail.
|
||||
testIndentifierGeneration();
|
||||
|
||||
waitForEditors(2)
|
||||
.then(saveFirstInlineStyleSheet)
|
||||
.then(testFriendlyNamesAfterSave)
|
||||
.then(reloadPage)
|
||||
.then(testFriendlyNamesAfterSave)
|
||||
.then(navigateToAnotherPage)
|
||||
.then(testFriendlyNamesAfterNavigation)
|
||||
.then(finishTests);
|
||||
});
|
||||
|
||||
content.location = FIRST_TEST_PAGE;
|
||||
}
|
||||
|
||||
function testIndentifierGeneration() {
|
||||
let fakeStyleSheetFile = {
|
||||
"href": "http://example.com/test.css",
|
||||
"nodeHref": "http://example.com/",
|
||||
"styleSheetIndex": 1
|
||||
}
|
||||
|
||||
let fakeInlineStyleSheet = {
|
||||
"href": null,
|
||||
"nodeHref": "http://example.com/",
|
||||
"styleSheetIndex": 2
|
||||
}
|
||||
|
||||
is(gUI.getStyleSheetIdentifier(fakeStyleSheetFile), "http://example.com/test.css",
|
||||
"URI is the identifier of style sheet file.");
|
||||
|
||||
is(gUI.getStyleSheetIdentifier(fakeInlineStyleSheet), "inline-2-at-http://example.com/",
|
||||
"Inline style sheets are identified by their page and position at that page.");
|
||||
}
|
||||
|
||||
function saveFirstInlineStyleSheet() {
|
||||
let deferred = promise.defer();
|
||||
let editor = gUI.editors[0];
|
||||
|
||||
let destFile = FileUtils.getFile("ProfD", [SAVE_PATH]);
|
||||
|
||||
editor.saveToFile(destFile, function (file) {
|
||||
ok(file, "File was correctly saved.");
|
||||
deferred.resolve();
|
||||
});
|
||||
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
function testFriendlyNamesAfterSave() {
|
||||
let firstEditor = gUI.editors[0];
|
||||
let secondEditor = gUI.editors[1];
|
||||
|
||||
// The friendly name of first sheet should've been remembered, the second should
|
||||
// not be the same (bug 969900).
|
||||
is(firstEditor.friendlyName, SAVE_PATH,
|
||||
"Friendly name is correct for the saved inline style sheet.");
|
||||
isnot(secondEditor.friendlyName, SAVE_PATH,
|
||||
"Friendly name is for the second inline style sheet is not the same as first.");
|
||||
|
||||
return promise.resolve(null);
|
||||
}
|
||||
|
||||
function reloadPage() {
|
||||
info("Reloading page.");
|
||||
content.location.reload();
|
||||
return waitForEditors(2);
|
||||
}
|
||||
|
||||
function navigateToAnotherPage() {
|
||||
info("Navigating to another page.");
|
||||
let deferred = promise.defer();
|
||||
gBrowser.removeCurrentTab();
|
||||
|
||||
gUI = null;
|
||||
|
||||
addTabAndOpenStyleEditor(function(panel) {
|
||||
gUI = panel.UI;
|
||||
|
||||
waitForEditors(2).then(deferred.resolve);
|
||||
});
|
||||
|
||||
content.location = SECOND_TEST_PAGE;
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
function testFriendlyNamesAfterNavigation() {
|
||||
let firstEditor = gUI.editors[0];
|
||||
let secondEditor = gUI.editors[1];
|
||||
|
||||
// Inline style sheets shouldn't have the name of previously saved file as the
|
||||
// page is different.
|
||||
isnot(firstEditor.friendlyName, SAVE_PATH,
|
||||
"The first editor doesn't have the save path as a friendly name.");
|
||||
isnot(secondEditor.friendlyName, SAVE_PATH,
|
||||
"The second editor doesn't have the save path as a friendly name.");
|
||||
|
||||
return promise.resolve(null);
|
||||
}
|
||||
|
||||
function finishTests() {
|
||||
gUI = null;
|
||||
finish();
|
||||
}
|
||||
|
||||
/**
|
||||
* Waits for all editors to be added.
|
||||
*
|
||||
* @param {int} aNumberOfEditors
|
||||
* The number of editors to wait until proceeding.
|
||||
*
|
||||
* Returns a promise that's resolved once all editors are added.
|
||||
*/
|
||||
function waitForEditors(aNumberOfEditors) {
|
||||
let deferred = promise.defer();
|
||||
let count = 0;
|
||||
|
||||
info("Waiting for " + aNumberOfEditors + " editors to be added");
|
||||
gUI.on("editor-added", function editorAdded(event, editor) {
|
||||
if (++count == aNumberOfEditors) {
|
||||
info("All editors added. Resolving promise.");
|
||||
gUI.off("editor-added", editorAdded);
|
||||
gUI.editors[0].getSourceEditor().then(deferred.resolve);
|
||||
}
|
||||
else {
|
||||
info ("Editor " + count + " of " + aNumberOfEditors + " added.");
|
||||
}
|
||||
});
|
||||
|
||||
return deferred.promise;
|
||||
}
|
19
browser/devtools/styleeditor/test/inline-1.html
Normal file
19
browser/devtools/styleeditor/test/inline-1.html
Normal file
@ -0,0 +1,19 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Inline test page #1</title>
|
||||
<style type="text/css">
|
||||
.second {
|
||||
font-size:2em;
|
||||
}
|
||||
</style>
|
||||
<style type="text/css">
|
||||
.first {
|
||||
font-size:3em;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body class="first">
|
||||
Inline test page #1
|
||||
</body>
|
||||
</html>
|
19
browser/devtools/styleeditor/test/inline-2.html
Normal file
19
browser/devtools/styleeditor/test/inline-2.html
Normal file
@ -0,0 +1,19 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Inline test page #2</title>
|
||||
<style type="text/css">
|
||||
.second {
|
||||
font-size:2em;
|
||||
}
|
||||
</style>
|
||||
<style type="text/css">
|
||||
.first {
|
||||
font-size:3em;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body class="second">
|
||||
Inline test page #2
|
||||
</body>
|
||||
</html>
|
@ -1,59 +1,71 @@
|
||||
/* vim:set ts=2 sw=2 sts=2 et: */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*
|
||||
* Contributor(s):
|
||||
* Mihai Șucan <mihai.sucan@gmail.com>
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
function consoleOpened(HUD) {
|
||||
HUD.jsterm.clearOutput();
|
||||
// Test that the console output scrolls to JS eval results when there are many
|
||||
// messages displayed. See bug 601352.
|
||||
|
||||
let longMessage = "";
|
||||
for (let i = 0; i < 50; i++) {
|
||||
longMessage += "LongNonwrappingMessage";
|
||||
}
|
||||
function test() {
|
||||
Task.spawn(runner).then(finishTest);
|
||||
|
||||
for (let i = 0; i < 50; i++) {
|
||||
content.console.log("test message " + i);
|
||||
}
|
||||
function* runner() {
|
||||
let {tab} = yield loadTab("data:text/html;charset=utf-8,Web Console test for bug 601352");
|
||||
let hud = yield openConsole(tab);
|
||||
hud.jsterm.clearOutput();
|
||||
|
||||
content.console.log(longMessage);
|
||||
let longMessage = "";
|
||||
for (let i = 0; i < 50; i++) {
|
||||
longMessage += "LongNonwrappingMessage";
|
||||
}
|
||||
|
||||
for (let i = 0; i < 50; i++) {
|
||||
content.console.log("test message " + i);
|
||||
}
|
||||
for (let i = 0; i < 50; i++) {
|
||||
content.console.log("test1 message " + i);
|
||||
}
|
||||
|
||||
HUD.jsterm.execute("1+1", performTest);
|
||||
content.console.log(longMessage);
|
||||
|
||||
function performTest(node) {
|
||||
let scrollNode = HUD.outputNode.parentNode;
|
||||
for (let i = 0; i < 50; i++) {
|
||||
content.console.log("test2 message " + i);
|
||||
}
|
||||
|
||||
yield waitForMessages({
|
||||
webconsole: hud,
|
||||
messages: [{
|
||||
text: "test1 message 0",
|
||||
}, {
|
||||
text: "test1 message 49",
|
||||
}, {
|
||||
text: "LongNonwrappingMessage",
|
||||
}, {
|
||||
text: "test2 message 0",
|
||||
}, {
|
||||
text: "test2 message 49",
|
||||
}],
|
||||
});
|
||||
|
||||
let nodeDeferred = promise.defer();
|
||||
hud.jsterm.execute("1+1", (node) => { nodeDeferred.resolve(node); });
|
||||
let node = yield nodeDeferred.promise;
|
||||
|
||||
let scrollNode = hud.outputNode.parentNode;
|
||||
let rectNode = node.getBoundingClientRect();
|
||||
let rectOutput = scrollNode.getBoundingClientRect();
|
||||
console.debug("rectNode", rectNode, "rectOutput", rectOutput);
|
||||
console.log("scrollNode scrollHeight", scrollNode.scrollHeight, "scrollTop", scrollNode.scrollTop, "clientHeight", scrollNode.clientHeight);
|
||||
|
||||
isnot(scrollNode.scrollTop, 0, "scroll location is not at the top");
|
||||
|
||||
// Visible scroll viewport.
|
||||
let height = scrollNode.scrollHeight - scrollNode.scrollTop;
|
||||
// The bounding client rect .top/left coordinates are relative to the
|
||||
// console iframe.
|
||||
|
||||
// Top position of the last message node, relative to the outputNode.
|
||||
let top = rectNode.top + scrollNode.scrollTop;
|
||||
let bottom = top + node.clientHeight;
|
||||
info("output height " + height + " node top " + top + " node bottom " + bottom + " node height " + node.clientHeight);
|
||||
// Visible scroll viewport.
|
||||
let height = rectOutput.height;
|
||||
|
||||
// Top and bottom coordinates of the last message node, relative to the outputNode.
|
||||
let top = rectNode.top - rectOutput.top;
|
||||
let bottom = top + rectNode.height;
|
||||
info("node top " + top + " node bottom " + bottom + " node clientHeight " + node.clientHeight);
|
||||
|
||||
ok(top >= 0 && bottom <= height, "last message is visible");
|
||||
|
||||
finishTest();
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
function test() {
|
||||
addTab("data:text/html;charset=utf-8,Web Console test for bug 601352");
|
||||
browser.addEventListener("load", function tabLoad(aEvent) {
|
||||
browser.removeEventListener(aEvent.type, tabLoad, true);
|
||||
openConsole(null, consoleOpened);
|
||||
}, true);
|
||||
}
|
||||
|
||||
|
@ -196,7 +196,7 @@
|
||||
if (event.mozInputSource == Ci.nsIDOMMouseEvent.MOZ_SOURCE_TOUCH) {
|
||||
if (typeof SelectionHelperUI != 'undefined') {
|
||||
SelectionHelperUI.attachEditSession(ChromeSelectionHandler,
|
||||
event.clientX, event.clientY);
|
||||
event.clientX, event.clientY, this);
|
||||
} else {
|
||||
// If we don't have access to SelectionHelperUI then we are using this
|
||||
// binding for browser content (e.g. about:config)
|
||||
@ -295,7 +295,7 @@
|
||||
if (event.mozInputSource == Ci.nsIDOMMouseEvent.MOZ_SOURCE_TOUCH) {
|
||||
if (typeof SelectionHelperUI != 'undefined') {
|
||||
SelectionHelperUI.attachEditSession(ChromeSelectionHandler,
|
||||
event.clientX, event.clientY);
|
||||
event.clientX, event.clientY, this);
|
||||
} else {
|
||||
// If we don't have access to SelectionHelperUI then we are using this
|
||||
// binding for browser content (e.g. about:config)
|
||||
|
@ -292,6 +292,12 @@
|
||||
|
||||
if (aShouldDismiss)
|
||||
ContextUI.dismissTabs();
|
||||
|
||||
if (!InputSourceHelper.isPrecise && this.textLength) {
|
||||
let inputRectangle = this.inputField.getBoundingClientRect();
|
||||
SelectionHelperUI.attachEditSession(ChromeSelectionHandler,
|
||||
inputRectangle.left, inputRectangle.top, this);
|
||||
}
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
@ -448,6 +454,15 @@
|
||||
|
||||
<handler event="click" phase="capturing">
|
||||
<![CDATA[
|
||||
// workaround for bug 925457: taping browser chrome resets last tap
|
||||
// co-ordinates to 'undefined' so that we know not to shift the
|
||||
// browser when the keyboard is up in SelectionHandler's
|
||||
// _calcNewContentPosition().
|
||||
Browser.selectedTab.browser.messageManager.sendAsyncMessage(
|
||||
"Browser:ResetLastPos", {
|
||||
xPos: null,
|
||||
yPos: null
|
||||
});
|
||||
this.beginEditing(true);
|
||||
]]>
|
||||
</handler>
|
||||
|
@ -482,8 +482,7 @@ Desktop browser's sync prefs.
|
||||
autocompletepopup="urlbar-autocomplete"
|
||||
completeselectedindex="true"
|
||||
placeholder="&urlbar.emptytext;"
|
||||
tabscrolling="true"
|
||||
onclick="SelectionHelperUI.urlbarTextboxClick(this);"/>
|
||||
tabscrolling="true" />
|
||||
|
||||
<toolbarbutton id="go-button"
|
||||
class="urlbar-button"
|
||||
|
@ -33,7 +33,7 @@ var ChromeSelectionHandler = {
|
||||
_onSelectionAttach: function _onSelectionAttach(aJson) {
|
||||
this._domWinUtils = Util.getWindowUtils(window);
|
||||
this._contentWindow = window;
|
||||
this._targetElement = this._domWinUtils.elementFromPoint(aJson.xPos, aJson.yPos, true, false);
|
||||
this._targetElement = aJson.target;
|
||||
this._targetIsEditable = this._targetElement instanceof Components.interfaces.nsIDOMXULTextBoxElement;
|
||||
if (!this._targetIsEditable) {
|
||||
this._onFail("not an editable?", this._targetElement);
|
||||
|
@ -435,10 +435,12 @@ var SelectionHelperUI = {
|
||||
*
|
||||
* Attaches to existing selection and begins editing.
|
||||
*
|
||||
* @param aMsgTarget - Browser or chrome message target
|
||||
* @param aX, aY - Browser relative client coordinates.
|
||||
* @param aMsgTarget - Browser or chrome message target.
|
||||
* @param aX Tap browser relative client X coordinate.
|
||||
* @param aY Tap browser relative client Y coordinate.
|
||||
* @param aTarget Actual tap target (optional).
|
||||
*/
|
||||
attachEditSession: function attachEditSession(aMsgTarget, aX, aY) {
|
||||
attachEditSession: function attachEditSession(aMsgTarget, aX, aY, aTarget) {
|
||||
if (!aMsgTarget || this.isActive)
|
||||
return;
|
||||
this._init(aMsgTarget);
|
||||
@ -448,6 +450,7 @@ var SelectionHelperUI = {
|
||||
// back with information on the current selection. SelectionAttach
|
||||
// takes client coordinates.
|
||||
this._sendAsyncMessage("Browser:SelectionAttach", {
|
||||
target: aTarget,
|
||||
xPos: aX,
|
||||
yPos: aY
|
||||
});
|
||||
@ -464,11 +467,12 @@ var SelectionHelperUI = {
|
||||
* Once the user starts a drag, the caret marker is hidden, and
|
||||
* the start and end markers take over.
|
||||
*
|
||||
* @param aMsgTarget - Browser or chrome message target
|
||||
* @param aX, aY - Browser relative client coordinates of the tap
|
||||
* that initiated the session.
|
||||
* @param aMsgTarget - Browser or chrome message target.
|
||||
* @param aX Tap browser relative client X coordinate.
|
||||
* @param aY Tap browser relative client Y coordinate.
|
||||
* @param aTarget Actual tap target (optional).
|
||||
*/
|
||||
attachToCaret: function attachToCaret(aMsgTarget, aX, aY) {
|
||||
attachToCaret: function attachToCaret(aMsgTarget, aX, aY, aTarget) {
|
||||
if (!this.isActive) {
|
||||
this._init(aMsgTarget);
|
||||
this._setupDebugOptions();
|
||||
@ -476,9 +480,14 @@ var SelectionHelperUI = {
|
||||
this._hideMonocles();
|
||||
}
|
||||
|
||||
this._lastPoint = { xPos: aX, yPos: aY };
|
||||
this._lastCaretAttachment = {
|
||||
target: aTarget,
|
||||
xPos: aX,
|
||||
yPos: aY
|
||||
};
|
||||
|
||||
this._sendAsyncMessage("Browser:CaretAttach", {
|
||||
target: aTarget,
|
||||
xPos: aX,
|
||||
yPos: aY
|
||||
});
|
||||
@ -516,38 +525,14 @@ var SelectionHelperUI = {
|
||||
});
|
||||
},
|
||||
|
||||
/*
|
||||
* Event handler on the navbar text input. Called from navbar bindings
|
||||
* when focus is applied to the edit.
|
||||
*/
|
||||
urlbarTextboxClick: function(aEdit) {
|
||||
// workaround for bug 925457: taping browser chrome resets last tap
|
||||
// co-ordinates to 'undefined' so that we know not to shift the browser
|
||||
// when the keyboard is up in SelectionHandler's _calcNewContentPosition().
|
||||
Browser.selectedTab.browser.messageManager.sendAsyncMessage("Browser:ResetLastPos", {
|
||||
xPos: null,
|
||||
yPos: null
|
||||
});
|
||||
|
||||
if (InputSourceHelper.isPrecise || !aEdit.textLength) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Enable selection when there's text in the control
|
||||
let innerRect = aEdit.inputField.getBoundingClientRect();
|
||||
this.attachEditSession(ChromeSelectionHandler,
|
||||
innerRect.left,
|
||||
innerRect.top);
|
||||
},
|
||||
|
||||
/*
|
||||
* Click handler for chrome pages loaded into the browser (about:config).
|
||||
* Called from the text input bindings via the attach_edit_session_to_content
|
||||
* observer.
|
||||
*/
|
||||
chromeTextboxClick: function (aEvent) {
|
||||
this.attachEditSession(Browser.selectedTab.browser,
|
||||
aEvent.clientX, aEvent.clientY);
|
||||
this.attachEditSession(Browser.selectedTab.browser, aEvent.clientX,
|
||||
aEvent.clientY, aEvent.target);
|
||||
},
|
||||
|
||||
/*
|
||||
@ -875,12 +860,13 @@ var SelectionHelperUI = {
|
||||
|
||||
/*
|
||||
* Handles taps that move the current caret around in text edits,
|
||||
* clear active selection and focus when neccessary, or change
|
||||
* modes. Only active afer SelectionHandlerUI is initialized.
|
||||
* clear active selection and focus when necessary, or change
|
||||
* modes. Only active after SelectionHandlerUI is initialized.
|
||||
*/
|
||||
_onClick: function(aEvent) {
|
||||
if (this.layerMode == kChromeLayer && this._targetIsEditable) {
|
||||
this.attachToCaret(this._msgTarget, aEvent.clientX, aEvent.clientY);
|
||||
this.attachToCaret(this._msgTarget, aEvent.clientX, aEvent.clientY,
|
||||
aEvent.target);
|
||||
}
|
||||
},
|
||||
|
||||
@ -909,7 +895,8 @@ var SelectionHelperUI = {
|
||||
*/
|
||||
_onDeckOffsetChanged: function _onDeckOffsetChanged(aEvent) {
|
||||
// Update the monocle position and display
|
||||
this.attachToCaret(null, this._lastPoint.xPos, this._lastPoint.yPos);
|
||||
this.attachToCaret(null, this._lastCaretAttachment.xPos,
|
||||
this._lastCaretAttachment.yPos, this._lastCaretAttachment.target);
|
||||
},
|
||||
|
||||
/*
|
||||
|
@ -107,7 +107,8 @@ gTests.push({
|
||||
let autocompletePopup = document.getElementById("urlbar-autocomplete-scroll");
|
||||
yield waitForEvent(autocompletePopup, "transitionend");
|
||||
|
||||
SelectionHelperUI.attachEditSession(ChromeSelectionHandler, editCoords.x, editCoords.y);
|
||||
SelectionHelperUI.attachEditSession(ChromeSelectionHandler, editCoords.x,
|
||||
editCoords.y, edit);
|
||||
ok(SelectionHelperUI.isSelectionUIVisible, "selection enabled");
|
||||
|
||||
let selection = edit.QueryInterface(Components.interfaces.nsIDOMXULTextBoxElement)
|
||||
@ -136,7 +137,8 @@ gTests.push({
|
||||
edit.value = "wikipedia.org";
|
||||
edit.select();
|
||||
let editCoords = logicalCoordsForElement(edit);
|
||||
SelectionHelperUI.attachEditSession(ChromeSelectionHandler, editCoords.x, editCoords.y);
|
||||
SelectionHelperUI.attachEditSession(ChromeSelectionHandler, editCoords.x,
|
||||
editCoords.y, edit);
|
||||
edit.blur();
|
||||
ok(!SelectionHelperUI.isSelectionUIVisible, "selection no longer enabled");
|
||||
clearSelection(edit);
|
||||
@ -228,6 +230,26 @@ gTests.push({
|
||||
}
|
||||
});
|
||||
|
||||
gTests.push({
|
||||
desc: "Bug 957646 - Selection monocles sometimes don't display when tapping" +
|
||||
" text ion the nav bar.",
|
||||
run: function() {
|
||||
yield showNavBar();
|
||||
|
||||
let edit = document.getElementById("urlbar-edit");
|
||||
edit.value = "about:mozilla";
|
||||
|
||||
let editRectangle = edit.getBoundingClientRect();
|
||||
|
||||
// Tap outside the input but close enough for fluffing to take effect.
|
||||
sendTap(window, editRectangle.left + 50, editRectangle.top - 2);
|
||||
|
||||
yield waitForCondition(function () {
|
||||
return SelectionHelperUI.isSelectionUIVisible;
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
function test() {
|
||||
if (!isLandscapeMode()) {
|
||||
todo(false, "browser_selection_tests need landscape mode to run.");
|
||||
|
@ -26,3 +26,41 @@ gTests.push({
|
||||
ok(simpleMeasurements.UITelemetry["metro-ui"]["window-height"], "window-height measurement was captured");
|
||||
}
|
||||
});
|
||||
|
||||
gTests.push({
|
||||
desc: "Test tab count telemetry",
|
||||
run: function() {
|
||||
// Wait for Session Manager to be initialized.
|
||||
yield waitForCondition(() => window.__SSID);
|
||||
|
||||
Services.obs.notifyObservers(null, "reset-telemetry-vars", null);
|
||||
yield waitForCondition(function () {
|
||||
let simpleMeasurements = getTelemetryPayload().simpleMeasurements;
|
||||
return simpleMeasurements.UITelemetry["metro-tabs"]["currTabCount"] == 1;
|
||||
});
|
||||
|
||||
let simpleMeasurements = getTelemetryPayload().simpleMeasurements;
|
||||
is(simpleMeasurements.UITelemetry["metro-tabs"]["currTabCount"], 1);
|
||||
is(simpleMeasurements.UITelemetry["metro-tabs"]["maxTabCount"], 1);
|
||||
|
||||
let tab2 = Browser.addTab("about:mozilla");
|
||||
simpleMeasurements = getTelemetryPayload().simpleMeasurements;
|
||||
is(simpleMeasurements.UITelemetry["metro-tabs"]["currTabCount"], 2);
|
||||
is(simpleMeasurements.UITelemetry["metro-tabs"]["maxTabCount"], 2);
|
||||
|
||||
let tab3 = Browser.addTab("about:config");
|
||||
simpleMeasurements = getTelemetryPayload().simpleMeasurements;
|
||||
is(simpleMeasurements.UITelemetry["metro-tabs"]["currTabCount"], 3);
|
||||
is(simpleMeasurements.UITelemetry["metro-tabs"]["maxTabCount"], 3);
|
||||
|
||||
Browser.closeTab(tab2, { forceClose: true } );
|
||||
simpleMeasurements = getTelemetryPayload().simpleMeasurements;
|
||||
is(simpleMeasurements.UITelemetry["metro-tabs"]["currTabCount"], 2);
|
||||
is(simpleMeasurements.UITelemetry["metro-tabs"]["maxTabCount"], 3);
|
||||
|
||||
Browser.closeTab(tab3, { forceClose: true } );
|
||||
simpleMeasurements = getTelemetryPayload().simpleMeasurements;
|
||||
is(simpleMeasurements.UITelemetry["metro-tabs"]["currTabCount"], 1);
|
||||
is(simpleMeasurements.UITelemetry["metro-tabs"]["maxTabCount"], 3);
|
||||
}
|
||||
});
|
@ -24,6 +24,9 @@ XPCOMUtils.defineLazyGetter(this, "NetUtil", function() {
|
||||
return NetUtil;
|
||||
});
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "UITelemetry",
|
||||
"resource://gre/modules/UITelemetry.jsm");
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Session Store
|
||||
// -----------------------------------------------------------------------
|
||||
@ -52,6 +55,9 @@ SessionStore.prototype = {
|
||||
_maxTabsUndo: 1,
|
||||
_shouldRestore: false,
|
||||
|
||||
// Tab telemetry variables
|
||||
_maxTabsOpen: 1,
|
||||
|
||||
init: function ss_init() {
|
||||
// Get file references
|
||||
this._sessionFile = Services.dirsvc.get("ProfD", Ci.nsILocalFile);
|
||||
@ -63,6 +69,13 @@ SessionStore.prototype = {
|
||||
|
||||
this._loadState = STATE_STOPPED;
|
||||
|
||||
try {
|
||||
UITelemetry.addSimpleMeasureFunction("metro-tabs",
|
||||
this._getTabStats.bind(this));
|
||||
} catch (ex) {
|
||||
// swallow exception that occurs if metro-tabs measure is already set up
|
||||
}
|
||||
|
||||
try {
|
||||
let shutdownWasUnclean = false;
|
||||
|
||||
@ -184,6 +197,13 @@ SessionStore.prototype = {
|
||||
})
|
||||
},
|
||||
|
||||
_getTabStats: function() {
|
||||
return {
|
||||
currTabCount: this._currTabCount,
|
||||
maxTabCount: this._maxTabsOpen
|
||||
};
|
||||
},
|
||||
|
||||
observe: function ss_observe(aSubject, aTopic, aData) {
|
||||
let self = this;
|
||||
let observerService = Services.obs;
|
||||
@ -197,6 +217,7 @@ SessionStore.prototype = {
|
||||
observerService.addObserver(this, "quit-application-requested", true);
|
||||
observerService.addObserver(this, "quit-application-granted", true);
|
||||
observerService.addObserver(this, "quit-application", true);
|
||||
observerService.addObserver(this, "reset-telemetry-vars", true);
|
||||
break;
|
||||
case "final-ui-startup":
|
||||
observerService.removeObserver(this, "final-ui-startup");
|
||||
@ -264,6 +285,7 @@ SessionStore.prototype = {
|
||||
observerService.removeObserver(this, "quit-application-requested");
|
||||
observerService.removeObserver(this, "quit-application-granted");
|
||||
observerService.removeObserver(this, "quit-application");
|
||||
observerService.removeObserver(this, "reset-telemetry-vars");
|
||||
|
||||
// If a save has been queued, kill the timer and save state now
|
||||
if (this._saveTimer) {
|
||||
@ -295,13 +317,24 @@ SessionStore.prototype = {
|
||||
this._saveTimer = null;
|
||||
this.saveState();
|
||||
break;
|
||||
case "reset-telemetry-vars":
|
||||
// Used in mochitests only.
|
||||
this._maxTabsOpen = 1;
|
||||
}
|
||||
},
|
||||
|
||||
updateTabTelemetryVars: function(window) {
|
||||
this._currTabCount = window.Browser.tabs.length;
|
||||
if (this._currTabCount > this._maxTabsOpen) {
|
||||
this._maxTabsOpen = this._currTabCount;
|
||||
}
|
||||
},
|
||||
|
||||
handleEvent: function ss_handleEvent(aEvent) {
|
||||
let window = aEvent.currentTarget.ownerDocument.defaultView;
|
||||
switch (aEvent.type) {
|
||||
case "TabOpen":
|
||||
this.updateTabTelemetryVars(window);
|
||||
case "TabClose": {
|
||||
let browser = aEvent.originalTarget.linkedBrowser;
|
||||
if (aEvent.type == "TabOpen") {
|
||||
@ -313,6 +346,9 @@ SessionStore.prototype = {
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "TabRemove":
|
||||
this.updateTabTelemetryVars(window);
|
||||
break;
|
||||
case "TabSelect": {
|
||||
let browser = aEvent.originalTarget.linkedBrowser;
|
||||
this.onTabSelect(window, browser);
|
||||
@ -361,6 +397,7 @@ SessionStore.prototype = {
|
||||
let tabContainer = aWindow.document.getElementById("tabs");
|
||||
tabContainer.addEventListener("TabOpen", this, true);
|
||||
tabContainer.addEventListener("TabClose", this, true);
|
||||
tabContainer.addEventListener("TabRemove", this, true);
|
||||
tabContainer.addEventListener("TabSelect", this, true);
|
||||
},
|
||||
|
||||
@ -372,6 +409,7 @@ SessionStore.prototype = {
|
||||
let tabContainer = aWindow.document.getElementById("tabs");
|
||||
tabContainer.removeEventListener("TabOpen", this, true);
|
||||
tabContainer.removeEventListener("TabClose", this, true);
|
||||
tabContainer.removeEventListener("TabRemove", this, true);
|
||||
tabContainer.removeEventListener("TabSelect", this, true);
|
||||
|
||||
if (this._loadState == STATE_RUNNING) {
|
||||
|
@ -640,10 +640,12 @@ tabmodalprompt:not([promptType="promptUserAndPass"]) .infoContainer {
|
||||
|
||||
.meta {
|
||||
background-color: @panel_light_color@;
|
||||
/* bug 969354
|
||||
background-image: url("chrome://browser/skin/images/firefox-watermark.png");
|
||||
background-repeat: no-repeat;
|
||||
background-position: center center;
|
||||
background-attachment: fixed;
|
||||
*/
|
||||
}
|
||||
|
||||
/* needs to observe the viewstate */
|
||||
|
@ -560,6 +560,11 @@ menuitem:not([type]):not(.menuitem-tooltip):not(.menuitem-iconic-tooltip) {
|
||||
-moz-appearance: none;
|
||||
}
|
||||
|
||||
:-moz-any(#TabsToolbar, #nav-bar) .toolbarbutton-1[open="true"],
|
||||
:-moz-any(#TabsToolbar, #nav-bar) .toolbarbutton-1:hover:active {
|
||||
padding: 3px;
|
||||
}
|
||||
|
||||
:-moz-any(#TabsToolbar, #nav-bar) .toolbarbutton-1 > .toolbarbutton-menubutton-button > .toolbarbutton-icon,
|
||||
:-moz-any(#TabsToolbar, #nav-bar) .toolbarbutton-1 > .toolbarbutton-menubutton-dropmarker > .dropmarker-icon,
|
||||
:-moz-any(#TabsToolbar, #nav-bar) .toolbarbutton-1 > .toolbarbutton-icon {
|
||||
|
@ -41,7 +41,8 @@ body {
|
||||
}
|
||||
|
||||
.property-name {
|
||||
width: 50%;
|
||||
/* -12px is so the expander triangle isn't pushed up above the property */
|
||||
width: calc(100% - 12px);
|
||||
overflow-x: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
@ -49,8 +50,7 @@ body {
|
||||
}
|
||||
|
||||
.property-value {
|
||||
width: 50%;
|
||||
max-width: 100%;
|
||||
width: 100%;
|
||||
overflow-x: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
@ -75,7 +75,8 @@ body {
|
||||
width: 200px;
|
||||
}
|
||||
.property-value {
|
||||
width: auto;
|
||||
/* -212px is accounting for the 200px property-name and the 12px triangle */
|
||||
width: calc(100% - 212px);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -22,6 +22,8 @@
|
||||
#downloads-button[cui-areatype="toolbar"] > #downloads-indicator-anchor > #downloads-indicator-icon {
|
||||
background: -moz-image-rect(url("chrome://browser/skin/Toolbar.png"),
|
||||
0, 198, 18, 180) center no-repeat;
|
||||
min-width: 18px;
|
||||
min-height: 18px;
|
||||
}
|
||||
|
||||
#downloads-button[cui-areatype="toolbar"][attention] > #downloads-indicator-anchor > #downloads-indicator-icon {
|
||||
|
@ -2573,24 +2573,13 @@ toolbarbutton.chevron > .toolbarbutton-menu-dropmarker {
|
||||
url(chrome://browser/skin/tabbrowser/tab-background-start@2x.png);
|
||||
}
|
||||
|
||||
.tabbrowser-tab:hover > .tab-stack > .tab-background:not([selected=true]),
|
||||
.tabs-newtab-button:hover {
|
||||
background-image: url(chrome://browser/skin/tabbrowser/tab-background-start@2x.png),
|
||||
url(chrome://browser/skin/tabbrowser/tab-background-middle@2x.png),
|
||||
url(chrome://browser/skin/tabbrowser/tab-background-end@2x.png);
|
||||
}
|
||||
|
||||
.tabbrowser-tab:hover > .tab-stack > .tab-background > .tab-background-middle:not([selected=true]) {
|
||||
background-image: url(chrome://browser/skin/tabbrowser/tab-background-middle@2x.png);
|
||||
}
|
||||
|
||||
.tabbrowser-tab:hover > .tab-stack > .tab-background > .tab-background-start:not([selected=true]) {
|
||||
background-image: url(chrome://browser/skin/tabbrowser/tab-background-start@2x.png);
|
||||
}
|
||||
|
||||
.tabbrowser-tab:hover > .tab-stack > .tab-background > .tab-background-end:not([selected=true]) {
|
||||
background-image: url(chrome://browser/skin/tabbrowser/tab-background-end@2x.png);
|
||||
}
|
||||
|
||||
.tab-background-middle[selected=true] {
|
||||
background-image: url(chrome://browser/skin/tabbrowser/tab-active-middle@2x.png),
|
||||
@fgTabTexture@,
|
||||
@ -4125,6 +4114,10 @@ window > chatbox {
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
|
||||
#main-window:not([tabsintitlebar]):-moz-lwtheme > #titlebar {
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
#main-window[tabsintitlebar]:-moz-lwtheme > #titlebar > #titlebar-content {
|
||||
margin-top: 11px;
|
||||
margin-bottom: 11px;
|
||||
|
@ -59,7 +59,8 @@ body {
|
||||
}
|
||||
|
||||
.property-name {
|
||||
width: 50%;
|
||||
/* -12px is so the expander triangle isn't pushed up above the property */
|
||||
width: calc(100% - 12px);
|
||||
overflow-x: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
@ -67,8 +68,7 @@ body {
|
||||
}
|
||||
|
||||
.property-value {
|
||||
width: 50%;
|
||||
max-width: 100%;
|
||||
width: 100%;
|
||||
overflow-x: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
@ -93,7 +93,8 @@ body {
|
||||
width: 200px;
|
||||
}
|
||||
.property-value {
|
||||
width: auto;
|
||||
/* -212px is accounting for the 200px property-name and the 12px triangle */
|
||||
width: calc(100% - 212px);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -494,15 +494,15 @@ box.requests-menu-status {
|
||||
|
||||
/* Footer */
|
||||
|
||||
#requests-menu-footer {
|
||||
border-top: solid 1px hsla(210,5%,5%,.3);
|
||||
}
|
||||
|
||||
.theme-dark #requests-menu-footer {
|
||||
border-top: 1px solid @table_itemDarkStartBorder@;
|
||||
box-shadow: 0 1px 0 @table_itemDarkEndBorder@ inset;
|
||||
background: url(background-noise-toolbar.png), #343c45; /* Toolbars */
|
||||
}
|
||||
|
||||
.theme-light #requests-menu-footer {
|
||||
border-top: 1px solid @table_itemLightStartBorder@;
|
||||
box-shadow: 0 1px 0 @table_itemLightEndBorder@ inset;
|
||||
background: url(background-noise-toolbar.png), #f0f1f2; /* Toolbars */
|
||||
}
|
||||
|
||||
@ -530,14 +530,14 @@ box.requests-menu-status {
|
||||
|
||||
.theme-dark .requests-menu-footer-spacer:not(:first-child),
|
||||
.theme-dark .requests-menu-footer-button:not(:first-child) {
|
||||
-moz-border-start: 1px solid @table_itemDarkStartBorder@;
|
||||
box-shadow: -1px 0 0 @table_itemDarkEndBorder@;
|
||||
-moz-border-start: 1px solid @table_itemDarkEndBorder@;
|
||||
box-shadow: -1px 0 0 @table_itemDarkStartBorder@;
|
||||
}
|
||||
|
||||
.theme-light .requests-menu-footer-spacer:not(:first-child),
|
||||
.theme-light .requests-menu-footer-button:not(:first-child) {
|
||||
-moz-border-start: 1px solid @table_itemLightStartBorder@;
|
||||
box-shadow: -1px 0 0 @table_itemLightEndBorder@;
|
||||
-moz-border-start: 1px solid @table_itemLightEndBorder@;
|
||||
box-shadow: -1px 0 0 @table_itemLightStartBorder@;
|
||||
}
|
||||
|
||||
.requests-menu-footer-button {
|
||||
@ -546,18 +546,25 @@ box.requests-menu-status {
|
||||
}
|
||||
|
||||
.requests-menu-footer-button:hover {
|
||||
background: rgba(0,0,0,0.20);
|
||||
background: rgba(0,0,0,0.10);
|
||||
}
|
||||
|
||||
.requests-menu-footer-button:hover:active {
|
||||
background: rgba(0,0,0,0.35);
|
||||
.theme-dark .requests-menu-footer-button:hover:active {
|
||||
background-color: rgba(29,79,115,0.4); /* Select Highlight Blue at 40% opacity */
|
||||
}
|
||||
|
||||
.requests-menu-footer-button:not(:active)[checked] {
|
||||
background-color: rgba(0,0,0,0.25);
|
||||
background-image: radial-gradient(farthest-side at center top, hsla(200,100%,70%,.7), hsla(200,100%,70%,0.3));
|
||||
background-size: 100% 1px;
|
||||
background-repeat: no-repeat;
|
||||
.theme-light .requests-menu-footer-button:hover:active {
|
||||
background-color: rgba(76,158,217,0.4); /* Select Highlight Blue at 40% opacity */
|
||||
}
|
||||
|
||||
.theme-dark .requests-menu-footer-button:not(:active)[checked] {
|
||||
background-color: rgba(29,79,115,1); /* Select Highlight Blue */
|
||||
color: rgba(245,247,250,1); /* Light foreground text */
|
||||
}
|
||||
|
||||
.theme-light .requests-menu-footer-button:not(:active)[checked] {
|
||||
background-color: rgba(76,158,217,1); /* Select Highlight Blue */
|
||||
color: rgba(245,247,250,1); /* Light foreground text */
|
||||
}
|
||||
|
||||
.requests-menu-footer-label {
|
||||
|
@ -393,6 +393,10 @@
|
||||
background-image: linear-gradient(transparent, transparent), @smallSeparatorDark@;
|
||||
}
|
||||
|
||||
.theme-dark .devtools-sidebar-tabs > tabs > tab:hover {
|
||||
background-image: linear-gradient(hsla(206,37%,4%,.2), hsla(206,37%,4%,.2)), @smallSeparatorDark@;
|
||||
}
|
||||
|
||||
.theme-dark .devtools-sidebar-tabs > tabs > tab:hover:active {
|
||||
background-image: linear-gradient(hsla(206,37%,4%,.4), hsla(206,37%,4%,.4)), @smallSeparatorDark@;
|
||||
}
|
||||
|
@ -224,6 +224,7 @@
|
||||
/* End selected tab */
|
||||
|
||||
/* new tab button border and gradient on hover */
|
||||
.tabbrowser-tab:hover > .tab-stack > .tab-background:not([selected=true]),
|
||||
.tabs-newtab-button:hover {
|
||||
background-image: url(chrome://browser/skin/tabbrowser/tab-background-start.png),
|
||||
url(chrome://browser/skin/tabbrowser/tab-background-middle.png),
|
||||
@ -233,27 +234,6 @@
|
||||
background-size: @tabCurveWidth@ 100%, calc(100% - (2 * @tabCurveWidth@)) 100%, @tabCurveWidth@ 100%;
|
||||
}
|
||||
|
||||
/* normal tab border and gradient on hover */
|
||||
.tabbrowser-tab:hover > .tab-stack > .tab-background > .tab-background-middle:not([selected=true]) {
|
||||
background-image: url(chrome://browser/skin/tabbrowser/tab-background-middle.png);
|
||||
background-repeat: repeat-x;
|
||||
background-size: auto 100%;
|
||||
}
|
||||
|
||||
.tabbrowser-tab:hover > .tab-stack > .tab-background > .tab-background-start:not([selected=true]),
|
||||
.tabbrowser-tab:hover > .tab-stack > .tab-background > .tab-background-end:not([selected=true]) {
|
||||
background-repeat: no-repeat;
|
||||
background-size: 100% 100%;
|
||||
}
|
||||
|
||||
.tabbrowser-tab:hover > .tab-stack > .tab-background > .tab-background-start:not([selected=true]) {
|
||||
background-image: url(chrome://browser/skin/tabbrowser/tab-background-start.png);
|
||||
}
|
||||
|
||||
.tabbrowser-tab:hover > .tab-stack > .tab-background > .tab-background-end:not([selected=true]) {
|
||||
background-image: url(chrome://browser/skin/tabbrowser/tab-background-end.png);
|
||||
}
|
||||
|
||||
/* Tab pointer-events */
|
||||
.tabbrowser-tab {
|
||||
pointer-events: none;
|
||||
|
@ -59,7 +59,8 @@ body {
|
||||
}
|
||||
|
||||
.property-name {
|
||||
width: 50%;
|
||||
/* -12px is so the expander triangle isn't pushed up above the property */
|
||||
width: calc(100% - 12px);
|
||||
overflow-x: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
@ -67,8 +68,7 @@ body {
|
||||
}
|
||||
|
||||
.property-value {
|
||||
width: 50%;
|
||||
max-width: 100%;
|
||||
width: 100%;
|
||||
overflow-x: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
@ -93,7 +93,8 @@ body {
|
||||
width: 200px;
|
||||
}
|
||||
.property-value {
|
||||
width: auto;
|
||||
/* -212px is accounting for the 200px property-name and the 12px triangle */
|
||||
width: calc(100% - 212px);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -140,11 +140,9 @@ class B2GRemoteAutomation(Automation):
|
||||
output.
|
||||
"""
|
||||
timeout = timeout or 120
|
||||
responseDueBy = time.time() + timeout
|
||||
while True:
|
||||
currentlog = proc.stdout
|
||||
currentlog = proc.getStdoutLines(timeout)
|
||||
if currentlog:
|
||||
responseDueBy = time.time() + timeout
|
||||
print currentlog
|
||||
# Match the test filepath from the last TEST-START line found in the new
|
||||
# log content. These lines are in the form:
|
||||
@ -155,11 +153,10 @@ class B2GRemoteAutomation(Automation):
|
||||
if hasattr(self, 'logFinish') and self.logFinish in currentlog:
|
||||
return 0
|
||||
else:
|
||||
if time.time() > responseDueBy:
|
||||
self.log.info("TEST-UNEXPECTED-FAIL | %s | application timed "
|
||||
"out after %d seconds with no output",
|
||||
self.lastTestSeen, int(timeout))
|
||||
return 1
|
||||
self.log.info("TEST-UNEXPECTED-FAIL | %s | application timed "
|
||||
"out after %d seconds with no output",
|
||||
self.lastTestSeen, int(timeout))
|
||||
return 1
|
||||
|
||||
def getDeviceStatus(self, serial=None):
|
||||
# Get the current status of the device. If we know the device
|
||||
@ -329,16 +326,22 @@ class B2GRemoteAutomation(Automation):
|
||||
# a dummy value to make the automation happy
|
||||
return 0
|
||||
|
||||
@property
|
||||
def stdout(self):
|
||||
def getStdoutLines(self, timeout):
|
||||
# Return any lines in the queue used by the
|
||||
# b2g process handler.
|
||||
lines = []
|
||||
# get all of the lines that are currently available
|
||||
while True:
|
||||
try:
|
||||
lines.append(self.queue.get_nowait())
|
||||
except Queue.Empty:
|
||||
break
|
||||
|
||||
# wait 'timeout' for any additional lines
|
||||
try:
|
||||
lines.append(self.queue.get(True, timeout))
|
||||
except Queue.Empty:
|
||||
pass
|
||||
return '\n'.join(lines)
|
||||
|
||||
def wait(self, timeout=None):
|
||||
|
@ -12,10 +12,10 @@ public interface Driver {
|
||||
* Find the first Element using the given method.
|
||||
*
|
||||
* @param activity The activity the element belongs to
|
||||
* @param name The name of the element
|
||||
* @param id The resource id of the element
|
||||
* @return The first matching element on the current context, or null if not found.
|
||||
*/
|
||||
Element findElement(Activity activity, String name);
|
||||
Element findElement(Activity activity, int id);
|
||||
|
||||
/**
|
||||
* Sets up scroll handling so that data is received from the extension.
|
||||
|
@ -16,16 +16,13 @@ import java.io.FileReader;
|
||||
import java.io.FileWriter;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.io.PrintWriter;
|
||||
import java.nio.IntBuffer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.opengl.GLSurfaceView;
|
||||
import android.view.View;
|
||||
import android.util.Log;
|
||||
|
||||
@ -36,8 +33,6 @@ import com.jayway.android.robotium.solo.Solo;
|
||||
public class FennecNativeDriver implements Driver {
|
||||
private static final int FRAME_TIME_THRESHOLD = 25; // allow 25ms per frame (40fps)
|
||||
|
||||
// Map of IDs to element names.
|
||||
private HashMap mLocators = null;
|
||||
private Activity mActivity;
|
||||
private Solo mSolo;
|
||||
private String mRootPath;
|
||||
@ -67,9 +62,6 @@ public class FennecNativeDriver implements Driver {
|
||||
mActivity = activity;
|
||||
mSolo = robocop;
|
||||
mRootPath = rootPath;
|
||||
|
||||
// Set up table of fennec_ids.
|
||||
mLocators = convertTextToTable(getFile(mRootPath + "/fennec_ids.txt"));
|
||||
}
|
||||
|
||||
//Information on the location of the Gecko Frame.
|
||||
@ -80,7 +72,7 @@ public class FennecNativeDriver implements Driver {
|
||||
private int mGeckoWidth = 1024;
|
||||
|
||||
private void getGeckoInfo() {
|
||||
View geckoLayout = mActivity.findViewById(Integer.decode((String)mLocators.get("gecko_layout")));
|
||||
View geckoLayout = mActivity.findViewById(R.id.gecko_layout);
|
||||
if (geckoLayout != null) {
|
||||
int[] pos = new int[2];
|
||||
geckoLayout.getLocationOnScreen(pos);
|
||||
@ -122,21 +114,12 @@ public class FennecNativeDriver implements Driver {
|
||||
return mGeckoWidth;
|
||||
}
|
||||
|
||||
/** Find the named element in the list of known Fennec views.
|
||||
/** Find the element with given id.
|
||||
*
|
||||
* @return An Element representing the view, or null if the view is not found.
|
||||
*/
|
||||
public Element findElement(Activity activity, String name) {
|
||||
if (name == null) {
|
||||
FennecNativeDriver.log(FennecNativeDriver.LogLevel.ERROR,
|
||||
"Can not findElements when passed a null");
|
||||
return null;
|
||||
}
|
||||
if (mLocators.containsKey(name)) {
|
||||
return new FennecNativeElement(Integer.decode((String)mLocators.get(name)), activity, mSolo);
|
||||
}
|
||||
FennecNativeDriver.log(FennecNativeDriver.LogLevel.ERROR,
|
||||
"findElement: Element '"+name+"' does not exist in the list");
|
||||
return null;
|
||||
public Element findElement(Activity activity, int id) {
|
||||
return new FennecNativeElement(id, activity);
|
||||
}
|
||||
|
||||
public void startFrameRecording() {
|
||||
|
@ -7,26 +7,17 @@ package org.mozilla.gecko;
|
||||
import android.app.Activity;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.Button;
|
||||
import android.widget.EditText;
|
||||
import android.widget.ListView;
|
||||
import android.widget.TextView;
|
||||
import android.widget.TextSwitcher;
|
||||
import android.app.Instrumentation;
|
||||
import com.jayway.android.robotium.solo.Solo;
|
||||
import java.util.List;
|
||||
import android.widget.TextView;
|
||||
|
||||
public class FennecNativeElement implements Element {
|
||||
private final Activity mActivity;
|
||||
private Integer mId;
|
||||
private Solo mSolo;
|
||||
// max time to wait for thread synchronization
|
||||
private static final int MAX_WAIT_MS = 60000;
|
||||
|
||||
public FennecNativeElement(Integer id, Activity activity, Solo solo) {
|
||||
public FennecNativeElement(Integer id, Activity activity) {
|
||||
mId = id;
|
||||
mActivity = activity;
|
||||
mSolo = solo;
|
||||
}
|
||||
|
||||
public Integer getId() {
|
||||
|
@ -83,9 +83,17 @@ ifdef JAVA_JAR_TARGETS #{
|
||||
# Arg 3: List of extra jars to link against. We do not use VPATH so
|
||||
# jars must be relative to $(CURDIR).
|
||||
# Arg 4: Additional JAVAC_FLAGS.
|
||||
|
||||
# Note: Proguard fails when stale .class files corresponding to
|
||||
# removed inner classes are present in the object directory. These
|
||||
# stale class files get packaged into the .jar file, which then gets
|
||||
# processed by Proguard. To work around this, we always delete any
|
||||
# existing jarfile-classes directory and start fresh.
|
||||
|
||||
define java_jar_template
|
||||
$(1): $(2) $(3)
|
||||
$$(REPORT_BUILD)
|
||||
@$$(RM) -rf $(1:.jar=)-classes
|
||||
@$$(NSINSTALL) -D $(1:.jar=)-classes
|
||||
@$$(if $$(filter-out .,$$(@D)),$$(NSINSTALL) -D $$(@D))
|
||||
$$(JAVAC) $$(JAVAC_FLAGS)\
|
||||
|
@ -29,7 +29,6 @@
|
||||
#include "nsIDOMClassInfo.h"
|
||||
#include "nsIDOMFile.h"
|
||||
#include "xpcpublic.h"
|
||||
#include "mozilla/Debug.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "mozilla/dom/StructuredCloneUtils.h"
|
||||
#include "JavaScriptChild.h"
|
||||
@ -38,6 +37,9 @@
|
||||
#include "nsPrintfCString.h"
|
||||
#include <algorithm>
|
||||
|
||||
#ifdef ANDROID
|
||||
#include <android/log.h>
|
||||
#endif
|
||||
#ifdef XP_WIN
|
||||
#include <windows.h>
|
||||
# if defined(SendMessage)
|
||||
@ -721,7 +723,16 @@ nsFrameMessageManager::GetChildAt(uint32_t aIndex,
|
||||
NS_IMETHODIMP
|
||||
nsFrameMessageManager::Dump(const nsAString& aStr)
|
||||
{
|
||||
PrintToDebugger(aStr, stdout);
|
||||
#ifdef ANDROID
|
||||
__android_log_print(ANDROID_LOG_INFO, "Gecko", "%s", NS_ConvertUTF16toUTF8(aStr).get());
|
||||
#endif
|
||||
#ifdef XP_WIN
|
||||
if (IsDebuggerPresent()) {
|
||||
OutputDebugStringW(PromiseFlatString(aStr).get());
|
||||
}
|
||||
#endif
|
||||
fputs(NS_ConvertUTF16toUTF8(aStr).get(), stdout);
|
||||
fflush(stdout);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -2622,7 +2622,7 @@ nsObjectLoadingContent::ScriptRequestPluginInstance(JSContext* aCx,
|
||||
NS_NOTREACHED("failed to dispatch PluginScripted event");
|
||||
}
|
||||
mScriptRequested = true;
|
||||
} else if (mType == eType_Plugin && !mInstanceOwner &&
|
||||
} else if (callerIsContentJS && mType == eType_Plugin && !mInstanceOwner &&
|
||||
nsContentUtils::IsSafeToRunScript() &&
|
||||
InActiveDocument(thisContent)) {
|
||||
// If we're configured as a plugin in an active document and it's safe to
|
||||
@ -3434,7 +3434,8 @@ nsObjectLoadingContent::DoNewResolve(JSContext* aCx, JS::Handle<JSObject*> aObje
|
||||
JS::Handle<jsid> aId,
|
||||
JS::MutableHandle<JSPropertyDescriptor> aDesc)
|
||||
{
|
||||
// We don't resolve anything; we just try to make sure we're instantiated
|
||||
// We don't resolve anything; we just try to make sure we're instantiated.
|
||||
// This purposefully does not fire for chrome/xray resolves, see bug 967694
|
||||
|
||||
nsRefPtr<nsNPAPIPluginInstance> pi;
|
||||
nsresult rv = ScriptRequestPluginInstance(aCx, getter_AddRefs(pi));
|
||||
@ -3450,8 +3451,8 @@ nsObjectLoadingContent::GetOwnPropertyNames(JSContext* aCx,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
// Just like DoNewResolve, just make sure we're instantiated. That will do
|
||||
// the work our Enumerate hook needs to do, and we don't want to return these
|
||||
// property names from Xrays anyway.
|
||||
// the work our Enumerate hook needs to do. This purposefully does not fire
|
||||
// for xray resolves, see bug 967694
|
||||
nsRefPtr<nsNPAPIPluginInstance> pi;
|
||||
aRv = ScriptRequestPluginInstance(aCx, getter_AddRefs(pi));
|
||||
}
|
||||
|
@ -367,6 +367,7 @@ public:
|
||||
void GetShaderInfoLog(WebGLShader *shader, nsACString& retval);
|
||||
void GetShaderInfoLog(WebGLShader *shader, nsAString& retval);
|
||||
void GetShaderSource(WebGLShader *shader, nsAString& retval);
|
||||
void GetShaderTranslatedSource(WebGLShader *shader, nsAString& retval);
|
||||
JS::Value GetTexParameter(GLenum target, GLenum pname);
|
||||
JS::Value GetTexParameter(JSContext * /* unused */, GLenum target,
|
||||
GLenum pname) {
|
||||
@ -906,6 +907,7 @@ protected:
|
||||
WEBGL_compressed_texture_pvrtc,
|
||||
WEBGL_compressed_texture_s3tc,
|
||||
WEBGL_debug_renderer_info,
|
||||
WEBGL_debug_shaders,
|
||||
WEBGL_depth_texture,
|
||||
WEBGL_lose_context,
|
||||
WEBGL_draw_buffers,
|
||||
|
@ -29,6 +29,7 @@ static const char *sExtensionNames[] = {
|
||||
"WEBGL_compressed_texture_pvrtc",
|
||||
"WEBGL_compressed_texture_s3tc",
|
||||
"WEBGL_debug_renderer_info",
|
||||
"WEBGL_debug_shaders",
|
||||
"WEBGL_depth_texture",
|
||||
"WEBGL_lose_context",
|
||||
"WEBGL_draw_buffers",
|
||||
@ -53,13 +54,23 @@ WebGLContext::IsExtensionEnabled(WebGLExtensionID ext) const {
|
||||
|
||||
bool WebGLContext::IsExtensionSupported(JSContext *cx, WebGLExtensionID ext) const
|
||||
{
|
||||
bool allowPrivilegedExts = false;
|
||||
|
||||
// Chrome contexts need access to debug information even when
|
||||
// webgl.disable-extensions is set. This is used in the graphics
|
||||
// section of about:support.
|
||||
if (xpc::AccessCheck::isChrome(js::GetContextCompartment(cx))) {
|
||||
if (xpc::AccessCheck::isChrome(js::GetContextCompartment(cx)))
|
||||
allowPrivilegedExts = true;
|
||||
|
||||
if (Preferences::GetBool("webgl.enable-privileged-extensions", false))
|
||||
allowPrivilegedExts = true;
|
||||
|
||||
if (allowPrivilegedExts) {
|
||||
switch (ext) {
|
||||
case WEBGL_debug_renderer_info:
|
||||
return true;
|
||||
case WEBGL_debug_shaders:
|
||||
return true;
|
||||
default:
|
||||
// For warnings-as-errors.
|
||||
break;
|
||||
@ -163,7 +174,7 @@ WebGLContext::GetExtension(JSContext *cx, const nsAString& aName, ErrorResult& r
|
||||
for (size_t i = 0; i < size_t(WebGLExtensionID_max); i++)
|
||||
{
|
||||
WebGLExtensionID extension = WebGLExtensionID(i);
|
||||
|
||||
|
||||
if (CompareWebGLExtensionName(name, GetExtensionString(extension))) {
|
||||
ext = extension;
|
||||
break;
|
||||
@ -251,6 +262,9 @@ WebGLContext::EnableExtension(WebGLExtensionID ext)
|
||||
case WEBGL_debug_renderer_info:
|
||||
obj = new WebGLExtensionDebugRendererInfo(this);
|
||||
break;
|
||||
case WEBGL_debug_shaders:
|
||||
obj = new WebGLExtensionDebugShaders(this);
|
||||
break;
|
||||
case WEBGL_depth_texture:
|
||||
obj = new WebGLExtensionDepthTexture(this);
|
||||
break;
|
||||
|
@ -3299,13 +3299,17 @@ WebGLContext::CompileShader(WebGLShader *shader)
|
||||
nsDependentCString(mapped_name)));
|
||||
}
|
||||
|
||||
size_t len = 0;
|
||||
ShGetInfo(compiler, SH_OBJECT_CODE_LENGTH, &len);
|
||||
size_t lenWithNull = 0;
|
||||
ShGetInfo(compiler, SH_OBJECT_CODE_LENGTH, &lenWithNull);
|
||||
MOZ_ASSERT(lenWithNull >= 1);
|
||||
size_t len = lenWithNull - 1;
|
||||
|
||||
nsAutoCString translatedSrc;
|
||||
translatedSrc.SetLength(len);
|
||||
translatedSrc.SetLength(len); // Allocates len+1, for the null-term.
|
||||
ShGetObjectCode(compiler, translatedSrc.BeginWriting());
|
||||
|
||||
CopyASCIItoUTF16(translatedSrc, shader->mTranslatedSource);
|
||||
|
||||
const char *ts = translatedSrc.get();
|
||||
|
||||
#ifdef WEBGL2_BYPASS_ANGLE
|
||||
@ -3324,6 +3328,8 @@ WebGLContext::CompileShader(WebGLShader *shader)
|
||||
// that's really bad, as that means we can't be 100% conformant. We should work towards always
|
||||
// using ANGLE identifier mapping.
|
||||
gl->fShaderSource(shadername, 1, &s, nullptr);
|
||||
|
||||
CopyASCIItoUTF16(s, shader->mTranslatedSource);
|
||||
}
|
||||
|
||||
shader->SetTranslationSuccess();
|
||||
@ -3617,8 +3623,7 @@ WebGLContext::GetShaderPrecisionFormat(GLenum shadertype, GLenum precisiontype)
|
||||
void
|
||||
WebGLContext::GetShaderSource(WebGLShader *shader, nsAString& retval)
|
||||
{
|
||||
if (IsContextLost())
|
||||
{
|
||||
if (IsContextLost()) {
|
||||
retval.SetIsVoid(true);
|
||||
return;
|
||||
}
|
||||
@ -3651,6 +3656,20 @@ WebGLContext::ShaderSource(WebGLShader *shader, const nsAString& source)
|
||||
shader->SetNeedsTranslation();
|
||||
}
|
||||
|
||||
void
|
||||
WebGLContext::GetShaderTranslatedSource(WebGLShader *shader, nsAString& retval)
|
||||
{
|
||||
if (IsContextLost()) {
|
||||
retval.SetIsVoid(true);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!ValidateObject("getShaderTranslatedSource: shader", shader))
|
||||
return;
|
||||
|
||||
retval.Assign(shader->TranslatedSource());
|
||||
}
|
||||
|
||||
GLenum WebGLContext::CheckedTexImage2D(GLenum target,
|
||||
GLint level,
|
||||
GLenum internalFormat,
|
||||
|
36
content/canvas/src/WebGLExtensionDebugShaders.cpp
Normal file
36
content/canvas/src/WebGLExtensionDebugShaders.cpp
Normal file
@ -0,0 +1,36 @@
|
||||
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "WebGLContext.h"
|
||||
#include "WebGLExtensions.h"
|
||||
#include "mozilla/dom/WebGLRenderingContextBinding.h"
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
WebGLExtensionDebugShaders::WebGLExtensionDebugShaders(WebGLContext* context)
|
||||
: WebGLExtensionBase(context)
|
||||
{
|
||||
}
|
||||
|
||||
WebGLExtensionDebugShaders::~WebGLExtensionDebugShaders()
|
||||
{
|
||||
}
|
||||
|
||||
/* If no source has been defined, compileShader() has not been called,
|
||||
* or the translation has failed for shader, an empty string is
|
||||
* returned; otherwise, return the translated source.
|
||||
*/
|
||||
void
|
||||
WebGLExtensionDebugShaders::GetTranslatedShaderSource(WebGLShader* shader,
|
||||
nsAString& retval)
|
||||
{
|
||||
mContext->GetShaderTranslatedSource(shader, retval);
|
||||
|
||||
if (retval.IsVoid()) {
|
||||
CopyASCIItoUTF16("", retval);
|
||||
}
|
||||
}
|
||||
|
||||
IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionDebugShaders)
|
@ -76,6 +76,18 @@ public:
|
||||
DECL_WEBGL_EXTENSION_GOOP
|
||||
};
|
||||
|
||||
class WebGLExtensionDebugShaders
|
||||
: public WebGLExtensionBase
|
||||
{
|
||||
public:
|
||||
WebGLExtensionDebugShaders(WebGLContext*);
|
||||
virtual ~WebGLExtensionDebugShaders();
|
||||
|
||||
void GetTranslatedShaderSource(WebGLShader* shader, nsAString& retval);
|
||||
|
||||
DECL_WEBGL_EXTENSION_GOOP
|
||||
};
|
||||
|
||||
class WebGLExtensionDepthTexture
|
||||
: public WebGLExtensionBase
|
||||
{
|
||||
|
@ -72,6 +72,8 @@ public:
|
||||
|
||||
const nsCString& TranslationLog() const { return mTranslationLog; }
|
||||
|
||||
const nsString& TranslatedSource() const { return mTranslatedSource; }
|
||||
|
||||
WebGLContext *GetParentObject() const {
|
||||
return Context();
|
||||
}
|
||||
@ -87,6 +89,7 @@ protected:
|
||||
GLuint mGLName;
|
||||
GLenum mType;
|
||||
nsString mSource;
|
||||
nsString mTranslatedSource;
|
||||
nsCString mTranslationLog; // The translation log should contain only ASCII characters
|
||||
bool mNeedsTranslation;
|
||||
nsTArray<WebGLMappedIdentifier> mAttributes;
|
||||
|
@ -48,6 +48,7 @@ if CONFIG['MOZ_WEBGL']:
|
||||
'WebGLExtensionCompressedTexturePVRTC.cpp',
|
||||
'WebGLExtensionCompressedTextureS3TC.cpp',
|
||||
'WebGLExtensionDebugRendererInfo.cpp',
|
||||
'WebGLExtensionDebugShaders.cpp',
|
||||
'WebGLExtensionDepthTexture.cpp',
|
||||
'WebGLExtensionDrawBuffers.cpp',
|
||||
'WebGLExtensionElementIndexUint.cpp',
|
||||
|
@ -75,9 +75,9 @@ function runTestEnabled() {
|
||||
|
||||
// if no source has been defined or compileShader() has not been called,
|
||||
// getTranslatedShaderSource() should return an empty string.
|
||||
shouldBeNull("ext.getTranslatedShaderSource(shader)");
|
||||
shouldBe("ext.getTranslatedShaderSource(shader)", '""');
|
||||
gl.shaderSource(shader, source);
|
||||
shouldBeNull("ext.getTranslatedShaderSource(shader)");
|
||||
shouldBe("ext.getTranslatedShaderSource(shader)", '""');
|
||||
gl.compileShader(shader);
|
||||
shouldBeTrue("gl.getShaderParameter(shader, gl.COMPILE_STATUS)");
|
||||
var translatedSource = ext.getTranslatedShaderSource(shader);
|
||||
|
@ -5,6 +5,7 @@ support-files =
|
||||
|
||||
[test_highp_fs.html]
|
||||
[test_no_arr_points.html]
|
||||
[test_privileged_exts.html]
|
||||
[test_webgl_available.html]
|
||||
[test_webgl_conformance.html]
|
||||
[test_webgl_request_context.html]
|
||||
|
@ -0,0 +1,33 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>WebGL test: Check for privileged ext access.</title>
|
||||
<script src="/MochiKit/MochiKit.js"></script>
|
||||
<script src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" href="/tests/SimpleTest/test.css">
|
||||
<script src="webgl-util.js"></script>
|
||||
<script src="driver-info.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<canvas id="c"></canvas>
|
||||
<script>
|
||||
|
||||
function TestExt(gl, name) {
|
||||
var ext = gl.getExtension(name);
|
||||
ok(!ext, 'Should not have access to \'' + name + '\'.');
|
||||
}
|
||||
|
||||
(function() {
|
||||
var gl = WebGLUtil.getWebGL('c');
|
||||
if (!gl) {
|
||||
todo(gl, 'Get GL working here first.');
|
||||
return;
|
||||
}
|
||||
|
||||
// Privileged extensions:
|
||||
TestExt(gl, 'WEBGL_debug_renderer_info');
|
||||
})();
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -416,15 +416,23 @@ const int16_t irc_composite_c_r0195_p090[][256] =
|
||||
{/* IRC_Composite_C_R0195_T000_P090.wav */
|
||||
{-1,1,-1,1,-1,1,-1,2,-2,2,-3,3,-3,4,-5,5,-7,8,-10,14,-25,-385,-133,-356,-344,-390,-312,-438,-400,-852,-107,-995,-245,-186,1358,-771,1473,28,-1710,-3762,-3025,4119,8200,5927,-785,1558,2250,1837,2098,631,-318,150,-77,1215,-23,792,865,600,981,659,366,950,511,766,502,516,589,299,331,571,105,609,462,485,538,594,470,640,393,432,325,604,259,355,336,454,33,263,182,-24,-124,121,-231,-50,-93,49,-230,-101,25,-196,-123,-21,-160,-161,-132,-136,-155,-268,-121,-146,-311,-112,-328,-201,-220,-280,-214,-304,-233,-227,-250,-242,-334,-256,-283,-393,-267,-285,-332,-331,-224,-295,-279,-171,-151,-361,-199,-239,-227,-317,-168,-211,-370,-182,-150,-343,-204,-192,-224,-319,-203,-137,-357,-146,-223,-237,-276,-162,-201,-262,-186,-209,-147,-267,-46,-252,-162,-146,-182,-199,-143,-218,-204,-108,-250,-163,-90,-241,-137,-125,-122,-272,-111,-188,-211,-160,-160,-164,-201,-231,-114,-175,-180,-212,-172,-181,-129,-130,-77,-150,-114,-39,12,-122,-9,-11,-46,-21,-4,7,-73,-20,-50,-21,-80,-102,2,-103,-66,-67,-8,-41,-119,-26,29,-208,3,-108,-34,-228,114,-196,-84,-28,1,-109,-92,77,-169,-27,48,-12,-79,3,-100,-44,-53,13,-103,-90,-14,-91,-23,-64,-21,-116}};
|
||||
|
||||
struct Elevation
|
||||
{
|
||||
/**
|
||||
* An array of |count| impulse responses of 256 samples for the left ear.
|
||||
* The impulse responses in each elevation are at equally spaced azimuths
|
||||
* for a full 360 degree revolution, ordered clockwise from in front the
|
||||
* listener.
|
||||
*/
|
||||
const int16_t (*azimuths)[256];
|
||||
int count;
|
||||
};
|
||||
|
||||
/**
|
||||
* irc_composite_c_r0195 is an array with each element containing data for one
|
||||
* elevation. For each elevation, |azimuths| is an array of |count| impulse
|
||||
* responses of 256 samples for the left ear. The impulse responses in each
|
||||
* elevation are at equally spaced azimuths for a full 360 degree revolution,
|
||||
* ordered clockwise from in front the listener.
|
||||
* elevation.
|
||||
*/
|
||||
const struct { const int16_t (*azimuths)[256]; int count; }
|
||||
irc_composite_c_r0195[] =
|
||||
const Elevation irc_composite_c_r0195[] =
|
||||
{{irc_composite_c_r0195_p315, MOZ_ARRAY_LENGTH(irc_composite_c_r0195_p315)},
|
||||
{irc_composite_c_r0195_p330, MOZ_ARRAY_LENGTH(irc_composite_c_r0195_p330)},
|
||||
{irc_composite_c_r0195_p345, MOZ_ARRAY_LENGTH(irc_composite_c_r0195_p345)},
|
||||
|
@ -6,7 +6,6 @@
|
||||
#include "mozilla/dom/SVGFEOffsetElement.h"
|
||||
#include "mozilla/dom/SVGFEOffsetElementBinding.h"
|
||||
#include "nsSVGFilterInstance.h"
|
||||
#include "gfxContext.h"
|
||||
|
||||
NS_IMPL_NS_NEW_NAMESPACED_SVG_ELEMENT(FEOffset)
|
||||
|
||||
@ -60,15 +59,6 @@ SVGFEOffsetElement::Dy()
|
||||
return mNumberAttributes[DY].ToDOMAnimatedNumber(this);
|
||||
}
|
||||
|
||||
nsIntPoint
|
||||
SVGFEOffsetElement::GetOffset(const nsSVGFilterInstance& aInstance)
|
||||
{
|
||||
return nsIntPoint(int32_t(aInstance.GetPrimitiveNumber(
|
||||
SVGContentUtils::X, &mNumberAttributes[DX])),
|
||||
int32_t(aInstance.GetPrimitiveNumber(
|
||||
SVGContentUtils::Y, &mNumberAttributes[DY])));
|
||||
}
|
||||
|
||||
FilterPrimitiveDescription
|
||||
SVGFEOffsetElement::GetPrimitiveDescription(nsSVGFilterInstance* aInstance,
|
||||
const IntRect& aFilterSubregion,
|
||||
@ -76,8 +66,11 @@ SVGFEOffsetElement::GetPrimitiveDescription(nsSVGFilterInstance* aInstance,
|
||||
nsTArray<RefPtr<SourceSurface>>& aInputImages)
|
||||
{
|
||||
FilterPrimitiveDescription descr(FilterPrimitiveDescription::eOffset);
|
||||
nsIntPoint offset = GetOffset(*aInstance);
|
||||
descr.Attributes().Set(eOffsetOffset, IntPoint(offset.x, offset.y));
|
||||
IntPoint offset(int32_t(aInstance->GetPrimitiveNumber(
|
||||
SVGContentUtils::X, &mNumberAttributes[DX])),
|
||||
int32_t(aInstance->GetPrimitiveNumber(
|
||||
SVGContentUtils::Y, &mNumberAttributes[DY])));
|
||||
descr.Attributes().Set(eOffsetOffset, offset);
|
||||
return descr;
|
||||
}
|
||||
|
||||
|
@ -49,8 +49,6 @@ public:
|
||||
already_AddRefed<SVGAnimatedNumber> Dy();
|
||||
|
||||
protected:
|
||||
nsIntPoint GetOffset(const nsSVGFilterInstance& aInstance);
|
||||
|
||||
virtual NumberAttributesInfo GetNumberInfo() MOZ_OVERRIDE;
|
||||
virtual StringAttributesInfo GetStringInfo() MOZ_OVERRIDE;
|
||||
|
||||
|
@ -160,7 +160,7 @@ SVGFilterElement::Invalidate()
|
||||
nsTObserverArray<nsIMutationObserver*>::ForwardIterator iter(*observers);
|
||||
while (iter.HasMore()) {
|
||||
nsCOMPtr<nsIMutationObserver> obs(iter.GetNext());
|
||||
nsCOMPtr<nsISVGFilterProperty> filter = do_QueryInterface(obs);
|
||||
nsCOMPtr<nsISVGFilterReference> filter = do_QueryInterface(obs);
|
||||
if (filter)
|
||||
filter->Invalidate();
|
||||
}
|
||||
|
@ -89,6 +89,26 @@ LoadContext::SetPrivateBrowsing(bool aUsePrivateBrowsing)
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
LoadContext::GetUseRemoteTabs(bool* aUseRemoteTabs)
|
||||
{
|
||||
MOZ_ASSERT(mIsNotNull);
|
||||
|
||||
NS_ENSURE_ARG_POINTER(aUseRemoteTabs);
|
||||
|
||||
*aUseRemoteTabs = mUseRemoteTabs;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
LoadContext::SetRemoteTabs(bool aUseRemoteTabs)
|
||||
{
|
||||
MOZ_ASSERT(mIsNotNull);
|
||||
|
||||
// We shouldn't need this on parent...
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
LoadContext::GetIsInBrowserElement(bool* aIsInBrowserElement)
|
||||
{
|
||||
|
@ -48,6 +48,7 @@ public:
|
||||
, mAppId(aAppId)
|
||||
, mIsContent(aToCopy.mIsContent)
|
||||
, mUsePrivateBrowsing(aToCopy.mUsePrivateBrowsing)
|
||||
, mUseRemoteTabs(aToCopy.mUseRemoteTabs)
|
||||
, mIsInBrowserElement(aInBrowser)
|
||||
#ifdef DEBUG
|
||||
, mIsNotNull(aToCopy.mIsNotNull)
|
||||
@ -58,11 +59,13 @@ public:
|
||||
uint32_t aAppId,
|
||||
bool aIsContent,
|
||||
bool aUsePrivateBrowsing,
|
||||
bool aUseRemoteTabs,
|
||||
bool aIsInBrowserElement)
|
||||
: mTopFrameElement(do_GetWeakReference(aTopFrameElement))
|
||||
, mAppId(aAppId)
|
||||
, mIsContent(aIsContent)
|
||||
, mUsePrivateBrowsing(aUsePrivateBrowsing)
|
||||
, mUseRemoteTabs(aUseRemoteTabs)
|
||||
, mIsInBrowserElement(aIsInBrowserElement)
|
||||
#ifdef DEBUG
|
||||
, mIsNotNull(true)
|
||||
@ -75,6 +78,7 @@ public:
|
||||
, mAppId(aAppId)
|
||||
, mIsContent(false)
|
||||
, mUsePrivateBrowsing(false)
|
||||
, mUseRemoteTabs(false)
|
||||
, mIsInBrowserElement(false)
|
||||
#ifdef DEBUG
|
||||
, mIsNotNull(true)
|
||||
@ -86,6 +90,7 @@ private:
|
||||
uint32_t mAppId;
|
||||
bool mIsContent;
|
||||
bool mUsePrivateBrowsing;
|
||||
bool mUseRemoteTabs;
|
||||
bool mIsInBrowserElement;
|
||||
#ifdef DEBUG
|
||||
bool mIsNotNull;
|
||||
|
@ -59,6 +59,7 @@ SerializedLoadContext::Init(nsILoadContext* aLoadContext)
|
||||
mIsPrivateBitValid = true;
|
||||
aLoadContext->GetIsContent(&mIsContent);
|
||||
aLoadContext->GetUsePrivateBrowsing(&mUsePrivateBrowsing);
|
||||
aLoadContext->GetUseRemoteTabs(&mUseRemoteTabs);
|
||||
aLoadContext->GetAppId(&mAppId);
|
||||
aLoadContext->GetIsInBrowserElement(&mIsInBrowserElement);
|
||||
} else {
|
||||
@ -68,6 +69,7 @@ SerializedLoadContext::Init(nsILoadContext* aLoadContext)
|
||||
// we won't be GetInterfaced to nsILoadContext
|
||||
mIsContent = true;
|
||||
mUsePrivateBrowsing = false;
|
||||
mUseRemoteTabs = false;
|
||||
mAppId = 0;
|
||||
mIsInBrowserElement = false;
|
||||
}
|
||||
|
@ -54,6 +54,7 @@ public:
|
||||
bool mIsPrivateBitValid;
|
||||
bool mIsContent;
|
||||
bool mUsePrivateBrowsing;
|
||||
bool mUseRemoteTabs;
|
||||
bool mIsInBrowserElement;
|
||||
uint32_t mAppId;
|
||||
};
|
||||
@ -70,6 +71,7 @@ struct ParamTraits<SerializedLoadContext>
|
||||
WriteParam(aMsg, aParam.mIsContent);
|
||||
WriteParam(aMsg, aParam.mIsPrivateBitValid);
|
||||
WriteParam(aMsg, aParam.mUsePrivateBrowsing);
|
||||
WriteParam(aMsg, aParam.mUseRemoteTabs);
|
||||
WriteParam(aMsg, aParam.mAppId);
|
||||
WriteParam(aMsg, aParam.mIsInBrowserElement);
|
||||
}
|
||||
@ -80,6 +82,7 @@ struct ParamTraits<SerializedLoadContext>
|
||||
!ReadParam(aMsg, aIter, &aResult->mIsContent) ||
|
||||
!ReadParam(aMsg, aIter, &aResult->mIsPrivateBitValid) ||
|
||||
!ReadParam(aMsg, aIter, &aResult->mUsePrivateBrowsing) ||
|
||||
!ReadParam(aMsg, aIter, &aResult->mUseRemoteTabs) ||
|
||||
!ReadParam(aMsg, aIter, &aResult->mAppId) ||
|
||||
!ReadParam(aMsg, aIter, &aResult->mIsInBrowserElement)) {
|
||||
return false;
|
||||
|
@ -829,6 +829,7 @@ nsDocShell::nsDocShell():
|
||||
mIsAppTab(false),
|
||||
mUseGlobalHistory(false),
|
||||
mInPrivateBrowsing(false),
|
||||
mUseRemoteTabs(false),
|
||||
mDeviceSizeIsPageSize(false),
|
||||
mCanExecuteScripts(false),
|
||||
mFiredUnloadEvent(false),
|
||||
@ -2245,6 +2246,29 @@ nsDocShell::SetPrivateBrowsing(bool aUsePrivateBrowsing)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDocShell::GetUseRemoteTabs(bool* aUseRemoteTabs)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aUseRemoteTabs);
|
||||
|
||||
*aUseRemoteTabs = mUseRemoteTabs;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDocShell::SetRemoteTabs(bool aUseRemoteTabs)
|
||||
{
|
||||
#ifdef MOZ_CRASHREPORTER
|
||||
if (aUseRemoteTabs) {
|
||||
CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("DOMIPCEnabled"),
|
||||
NS_LITERAL_CSTRING("1"));
|
||||
}
|
||||
#endif
|
||||
|
||||
mUseRemoteTabs = aUseRemoteTabs;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDocShell::SetAffectPrivateSessionLifetime(bool aAffectLifetime)
|
||||
{
|
||||
|
@ -213,6 +213,8 @@ public:
|
||||
NS_IMETHOD GetUsePrivateBrowsing(bool*);
|
||||
NS_IMETHOD SetUsePrivateBrowsing(bool);
|
||||
NS_IMETHOD SetPrivateBrowsing(bool);
|
||||
NS_IMETHOD GetUseRemoteTabs(bool*);
|
||||
NS_IMETHOD SetRemoteTabs(bool);
|
||||
|
||||
// Restores a cached presentation from history (mLSHE).
|
||||
// This method swaps out the content viewer and simulates loads for
|
||||
@ -830,6 +832,7 @@ protected:
|
||||
bool mIsAppTab;
|
||||
bool mUseGlobalHistory;
|
||||
bool mInPrivateBrowsing;
|
||||
bool mUseRemoteTabs;
|
||||
bool mDeviceSizeIsPageSize;
|
||||
|
||||
// Because scriptability depends on the mAllowJavascript values of our
|
||||
|
@ -14,7 +14,7 @@ interface nsIDOMElement;
|
||||
* can be queried for various information about where the load is
|
||||
* happening.
|
||||
*/
|
||||
[scriptable, uuid(d0029474-0cc4-42fd-bb21-d9ff22f5293c)]
|
||||
[scriptable, uuid(852ed1f0-8ec0-11e3-baa8-0800200c9a66)]
|
||||
interface nsILoadContext : nsISupports
|
||||
{
|
||||
/**
|
||||
@ -66,6 +66,11 @@ interface nsILoadContext : nsISupports
|
||||
*/
|
||||
attribute boolean usePrivateBrowsing;
|
||||
|
||||
/**
|
||||
* Attribute that determines if remote (out-of-process) tabs should be used.
|
||||
*/
|
||||
readonly attribute boolean useRemoteTabs;
|
||||
|
||||
%{C++
|
||||
/**
|
||||
* De-XPCOMed getter to make call-sites cleaner.
|
||||
@ -75,6 +80,12 @@ interface nsILoadContext : nsISupports
|
||||
GetUsePrivateBrowsing(&usingPB);
|
||||
return usingPB;
|
||||
}
|
||||
|
||||
bool UseRemoteTabs() {
|
||||
bool usingRT;
|
||||
GetUseRemoteTabs(&usingRT);
|
||||
return usingRT;
|
||||
}
|
||||
%}
|
||||
|
||||
/**
|
||||
@ -82,6 +93,11 @@ interface nsILoadContext : nsISupports
|
||||
*/
|
||||
[noscript] void SetPrivateBrowsing(in boolean aInPrivateBrowsing);
|
||||
|
||||
/**
|
||||
* Set the remote tabs state of the load context, meant to be used internally.
|
||||
*/
|
||||
[noscript] void SetRemoteTabs(in boolean aUseRemoteTabs);
|
||||
|
||||
/**
|
||||
* Returns true iff the load is occurring inside a browser element.
|
||||
*/
|
||||
|
@ -232,6 +232,10 @@ class nsIScriptTimeoutHandler;
|
||||
#endif // check
|
||||
#include "AccessCheck.h"
|
||||
|
||||
#ifdef ANDROID
|
||||
#include <android/log.h>
|
||||
#endif
|
||||
|
||||
#ifdef PR_LOGGING
|
||||
static PRLogModuleInfo* gDOMLeakPRLog;
|
||||
#endif
|
||||
@ -5809,7 +5813,31 @@ nsGlobalWindow::Dump(const nsAString& aStr)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
PrintToDebugger(aStr, gDumpFile ? gDumpFile : stdout);
|
||||
char *cstr = ToNewUTF8String(aStr);
|
||||
|
||||
#if defined(XP_MACOSX)
|
||||
// have to convert \r to \n so that printing to the console works
|
||||
char *c = cstr, *cEnd = cstr + strlen(cstr);
|
||||
while (c < cEnd) {
|
||||
if (*c == '\r')
|
||||
*c = '\n';
|
||||
c++;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (cstr) {
|
||||
#ifdef XP_WIN
|
||||
PrintToDebugger(cstr);
|
||||
#endif
|
||||
#ifdef ANDROID
|
||||
__android_log_write(ANDROID_LOG_INFO, "GeckoDump", cstr);
|
||||
#endif
|
||||
FILE *fp = gDumpFile ? gDumpFile : stdout;
|
||||
fputs(cstr, fp);
|
||||
fflush(fp);
|
||||
nsMemory::Free(cstr);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -1370,6 +1370,11 @@ DOMInterfaces = {
|
||||
'headerFile': 'WebGLExtensions.h'
|
||||
},
|
||||
|
||||
'WebGLExtensionDebugShaders': {
|
||||
'nativeType': 'mozilla::WebGLExtensionDebugShaders',
|
||||
'headerFile': 'WebGLExtensions.h'
|
||||
},
|
||||
|
||||
'WebGLExtensionElementIndexUint': {
|
||||
'nativeType': 'mozilla::WebGLExtensionElementIndexUint',
|
||||
'headerFile': 'WebGLExtensions.h'
|
||||
|
@ -696,6 +696,8 @@ TabChild::Init()
|
||||
MOZ_ASSERT(loadContext);
|
||||
loadContext->SetPrivateBrowsing(
|
||||
mChromeFlags & nsIWebBrowserChrome::CHROME_PRIVATE_WINDOW);
|
||||
loadContext->SetRemoteTabs(
|
||||
mChromeFlags & nsIWebBrowserChrome::CHROME_REMOTE_WINDOW);
|
||||
|
||||
nsCOMPtr<nsIWebProgress> webProgress = do_GetInterface(docShell);
|
||||
NS_ENSURE_TRUE(webProgress, NS_ERROR_FAILURE);
|
||||
|
@ -1919,6 +1919,7 @@ TabParent::GetLoadContext()
|
||||
OwnOrContainingAppId(),
|
||||
true /* aIsContent */,
|
||||
mChromeFlags & nsIWebBrowserChrome::CHROME_PRIVATE_WINDOW,
|
||||
mChromeFlags & nsIWebBrowserChrome::CHROME_REMOTE_WINDOW,
|
||||
IsBrowserElement());
|
||||
mLoadContext = loadContext;
|
||||
}
|
||||
|
@ -32,6 +32,7 @@ support-files =
|
||||
[test_bug813906.html]
|
||||
[test_bug854082.html]
|
||||
[test_bug863792.html]
|
||||
[test_bug967694.html]
|
||||
[test_cocoa_focus.html]
|
||||
skip-if = toolkit != "cocoa"
|
||||
support-files = cocoa_focus.html
|
||||
|
78
dom/plugins/test/mochitest/test_bug967694.html
Normal file
78
dom/plugins/test/mochitest/test_bug967694.html
Normal file
@ -0,0 +1,78 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test for Bug 967694</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="utils.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
|
||||
<meta http-equiv="content-type" content="text/html; charset=utf-8">
|
||||
</head>
|
||||
<body>
|
||||
<script type="application/javascript">
|
||||
|
||||
// Touching a plugin from chrome scope should not spawn it, bug should
|
||||
// synchronously spawn it from content scope
|
||||
|
||||
setTestPluginEnabledState(SpecialPowers.Ci.nsIPluginTag.STATE_ENABLED);
|
||||
|
||||
var plugin;
|
||||
var spPlugin;
|
||||
|
||||
function recreatePlugin() {
|
||||
if (plugin) {
|
||||
document.body.removeChild(plugin);
|
||||
}
|
||||
plugin = document.createElement("embed");
|
||||
plugin.type = "application/x-test";
|
||||
|
||||
document.body.appendChild(plugin);
|
||||
// Plugin should now be queued for async spawning.
|
||||
spPlugin = SpecialPowers.wrap(plugin);
|
||||
|
||||
is(spPlugin.displayedType, spPlugin.TYPE_PLUGIN, "Should be configured as plugin");
|
||||
ok(!spPlugin.hasRunningPlugin, "Should not be spawned yet");
|
||||
}
|
||||
|
||||
recreatePlugin();
|
||||
|
||||
// Try various JS operations with chrome context
|
||||
var thrown = false;
|
||||
// Get and set non-existent Property
|
||||
var hi = spPlugin._testShouldntExist;
|
||||
spPlugin._testShouldntExist = 5;
|
||||
// Call some test-plugin function
|
||||
try {
|
||||
var val = spPlugin.getObjectValue();
|
||||
} catch (e) {
|
||||
thrown = true;
|
||||
}
|
||||
|
||||
ok(thrown, "Function call should have thrown");
|
||||
ok(!spPlugin.hasRunningPlugin, "Plugin should not have spawned");
|
||||
|
||||
// Try property access from content
|
||||
var hi = plugin._testShouldntExistContent;
|
||||
ok(spPlugin.hasRunningPlugin, "Should've caused plugin to spawn");
|
||||
|
||||
// Property set
|
||||
recreatePlugin();
|
||||
plugin._testShouldntExistContent = 5;
|
||||
ok(spPlugin.hasRunningPlugin, "Should've caused plugin to spawn");
|
||||
|
||||
// Call test plugin function. Should succeed.
|
||||
recreatePlugin();
|
||||
thrown = false;
|
||||
try {
|
||||
var value = plugin.getObjectValue();
|
||||
} catch (e) {
|
||||
thrown = true;
|
||||
}
|
||||
|
||||
ok(!thrown, "Call should have succeeded");
|
||||
ok(spPlugin.hasRunningPlugin, "Call should have synchronously spawned plugin");
|
||||
ok(plugin.checkObjectValue(value), "Plugin should recognize self");
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -21,12 +21,17 @@
|
||||
const FLAG_CLEAR_ALL = pluginHostIface.FLAG_CLEAR_ALL;
|
||||
const FLAG_CLEAR_CACHE = pluginHostIface.FLAG_CLEAR_CACHE;
|
||||
|
||||
// Make sure clearing by timerange is supported.
|
||||
var p = document.getElementById("plugin1");
|
||||
p.setSitesWithDataCapabilities(true);
|
||||
|
||||
ok(PluginUtils.withTestPlugin(runTest), "Test plugin found");
|
||||
SimpleTest.finish();
|
||||
// Since we're running with chrome permissions, accessing the plugin wont
|
||||
// synchronously spawn it -- wait for the async spawning to finish.
|
||||
SimpleTest.executeSoon(function() {
|
||||
// Make sure clearing by timerange is supported.
|
||||
p.setSitesWithDataCapabilities(true);
|
||||
|
||||
ok(PluginUtils.withTestPlugin(runTest), "Test plugin found");
|
||||
SimpleTest.finish();
|
||||
});
|
||||
|
||||
function stored(needles) {
|
||||
var something = pluginHost.siteHasData(this.pluginTag, null);
|
||||
|
@ -161,14 +161,15 @@ namespace {
|
||||
class StorageNotifierRunnable : public nsRunnable
|
||||
{
|
||||
public:
|
||||
StorageNotifierRunnable(nsISupports* aSubject)
|
||||
: mSubject(aSubject)
|
||||
StorageNotifierRunnable(nsISupports* aSubject, const char16_t* aType)
|
||||
: mSubject(aSubject), mType(aType)
|
||||
{ }
|
||||
|
||||
NS_DECL_NSIRUNNABLE
|
||||
|
||||
private:
|
||||
nsCOMPtr<nsISupports> mSubject;
|
||||
const char16_t* mType;
|
||||
};
|
||||
|
||||
NS_IMETHODIMP
|
||||
@ -177,7 +178,7 @@ StorageNotifierRunnable::Run()
|
||||
nsCOMPtr<nsIObserverService> observerService =
|
||||
mozilla::services::GetObserverService();
|
||||
if (observerService) {
|
||||
observerService->NotifyObservers(mSubject, "dom-storage2-changed", nullptr);
|
||||
observerService->NotifyObservers(mSubject, "dom-storage2-changed", mType);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
@ -207,7 +208,11 @@ DOMStorage::BroadcastChangeNotification(const nsSubstring& aKey,
|
||||
return;
|
||||
}
|
||||
|
||||
nsRefPtr<StorageNotifierRunnable> r = new StorageNotifierRunnable(event);
|
||||
nsRefPtr<StorageNotifierRunnable> r =
|
||||
new StorageNotifierRunnable(event,
|
||||
GetType() == LocalStorage
|
||||
? MOZ_UTF16("localStorage")
|
||||
: MOZ_UTF16("sessionStorage"));
|
||||
NS_DispatchToMainThread(r);
|
||||
}
|
||||
|
||||
|
@ -13,9 +13,13 @@
|
||||
#include "unistd.h"
|
||||
#include "dirent.h"
|
||||
#include "sys/stat.h"
|
||||
#if !defined(ANDROID)
|
||||
#if defined(ANDROID)
|
||||
#include <sys/vfs.h>
|
||||
#define statvfs statfs
|
||||
#else
|
||||
#include "sys/statvfs.h"
|
||||
#include <spawn.h>
|
||||
#endif // !defined(ANDROID)
|
||||
#endif // defined(ANDROID)
|
||||
#endif // defined(XP_UNIX)
|
||||
|
||||
#if defined(XP_LINUX)
|
||||
@ -526,6 +530,9 @@ static const dom::ConstantSpec gLibcProperties[] =
|
||||
// The size of |time_t|.
|
||||
{ "OSFILE_SIZEOF_TIME_T", INT_TO_JSVAL(sizeof (time_t)) },
|
||||
|
||||
// The size of |fsblkcnt_t|.
|
||||
{ "OSFILE_SIZEOF_FSBLKCNT_T", INT_TO_JSVAL(sizeof (fsblkcnt_t)) },
|
||||
|
||||
#if !defined(ANDROID)
|
||||
// The size of |posix_spawn_file_actions_t|.
|
||||
{ "OSFILE_SIZEOF_POSIX_SPAWN_FILE_ACTIONS_T", INT_TO_JSVAL(sizeof (posix_spawn_file_actions_t)) },
|
||||
@ -585,6 +592,13 @@ static const dom::ConstantSpec gLibcProperties[] =
|
||||
{ "OSFILE_OFFSETOF_STAT_ST_BIRTHTIME", INT_TO_JSVAL(offsetof (struct stat, st_birthtime)) },
|
||||
#endif // defined(_DARWIN_FEATURE_64_BIT_INODE)
|
||||
|
||||
// Defining |statvfs|
|
||||
|
||||
{ "OSFILE_SIZEOF_STATVFS", INT_TO_JSVAL(sizeof (struct statvfs)) },
|
||||
|
||||
{ "OSFILE_OFFSETOF_STATVFS_F_BSIZE", INT_TO_JSVAL(offsetof (struct statvfs, f_bsize)) },
|
||||
{ "OSFILE_OFFSETOF_STATVFS_F_BAVAIL", INT_TO_JSVAL(offsetof (struct statvfs, f_bavail)) },
|
||||
|
||||
#endif // defined(XP_UNIX)
|
||||
|
||||
|
||||
|
@ -12,5 +12,6 @@ support-files =
|
||||
|
||||
[test_storageLocalStorageEventCheckNoPropagation.html]
|
||||
[test_storageLocalStorageEventCheckPropagation.html]
|
||||
[test_storageNotifications.html]
|
||||
[test_storageSessionStorageEventCheckNoPropagation.html]
|
||||
[test_storageSessionStorageEventCheckPropagation.html]
|
||||
|
127
dom/tests/mochitest/storageevent/test_storageNotifications.html
Normal file
127
dom/tests/mochitest/storageevent/test_storageNotifications.html
Normal file
@ -0,0 +1,127 @@
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<title>sessionStorage basic test</title>
|
||||
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
|
||||
<script type="application/javascript;version=1.7">
|
||||
|
||||
var expectedTypes = [
|
||||
"localStorage",
|
||||
"localStorage",
|
||||
"sessionStorage",
|
||||
"localStorage",
|
||||
"sessionStorage",
|
||||
"sessionStorage",
|
||||
"localStorage",
|
||||
"sessionStorage",
|
||||
"localStorage",
|
||||
"sessionStorage",
|
||||
"localStorage",
|
||||
"sessionStorage",
|
||||
"sessionStorage",
|
||||
"localStorage",
|
||||
"sessionStorage",
|
||||
"localStorage",
|
||||
];
|
||||
|
||||
var tests = Tests();
|
||||
function setup() {
|
||||
sessionStorage.clear();
|
||||
SimpleTest.executeSoon(function() {
|
||||
tests.next();
|
||||
});
|
||||
}
|
||||
|
||||
function Tests()
|
||||
{
|
||||
// Initially check the both storages are empty
|
||||
is(sessionStorage.length, 0, "Session storage is empty [1]");
|
||||
is(localStorage.length, 0, "Local storage is empty [1]");
|
||||
|
||||
var onStorageChanged = {
|
||||
observe: function(subject, topic, type) {
|
||||
if (topic == "dom-storage2-changed") {
|
||||
ok(expectedTypes.length > 0, "Not more then expected events encountered");
|
||||
is(type, expectedTypes.shift(), "Expected type of the storage notificaiton");
|
||||
tests.next();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Listen for dom-storage2-changed notification
|
||||
SpecialPowers.Services.obs.addObserver(onStorageChanged,
|
||||
"dom-storage2-changed", false);
|
||||
|
||||
// add an empty-value key
|
||||
localStorage.setItem("empty", "");
|
||||
yield undefined;
|
||||
|
||||
localStorage.setItem("empty", "value-1");
|
||||
yield undefined;
|
||||
|
||||
sessionStorage.setItem("empty", "");
|
||||
yield undefined;
|
||||
|
||||
localStorage.removeItem("empty");
|
||||
yield undefined;
|
||||
|
||||
sessionStorage.setItem("empty", "value-1");
|
||||
yield undefined;
|
||||
|
||||
sessionStorage.removeItem("empty");
|
||||
yield undefined;
|
||||
|
||||
localStorage.setItem("key1", "value-1");
|
||||
yield undefined;
|
||||
|
||||
sessionStorage.setItem("key2", "value-2");
|
||||
yield undefined;
|
||||
|
||||
localStorage.setItem("key1", "value-1-2");
|
||||
yield undefined;
|
||||
|
||||
sessionStorage.setItem("key2", "value-2-2");
|
||||
yield undefined;
|
||||
|
||||
localStorage.setItem("key3", "value-3");
|
||||
yield undefined;
|
||||
|
||||
sessionStorage.setItem("key4", "value-4");
|
||||
yield undefined;
|
||||
|
||||
sessionStorage.removeItem("key4");
|
||||
yield undefined;
|
||||
|
||||
localStorage.setItem("key4", "value-4");
|
||||
yield undefined;
|
||||
|
||||
sessionStorage.clear();
|
||||
yield undefined;
|
||||
|
||||
localStorage.clear();
|
||||
yield undefined;
|
||||
|
||||
SimpleTest.executeSoon(function () {
|
||||
SpecialPowers.Services.obs.removeObserver(onStorageChanged,
|
||||
"dom-storage2-changed", false);
|
||||
is(expectedTypes.length, 0, "received the correct number of events");
|
||||
|
||||
sessionStorage.clear();
|
||||
localStorage.clear();
|
||||
tests = null;
|
||||
SimpleTest.finish();
|
||||
});
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
</script>
|
||||
|
||||
</head>
|
||||
|
||||
<body onload="setup();">
|
||||
|
||||
</body>
|
||||
</html>
|
@ -805,6 +805,12 @@ interface WebGLExtensionDebugRendererInfo
|
||||
const GLenum UNMASKED_RENDERER_WEBGL = 0x9246;
|
||||
};
|
||||
|
||||
[NoInterfaceObject]
|
||||
interface WebGLExtensionDebugShaders
|
||||
{
|
||||
DOMString getTranslatedShaderSource(WebGLShader? shader);
|
||||
};
|
||||
|
||||
[NoInterfaceObject]
|
||||
interface WebGLExtensionDepthTexture
|
||||
{
|
||||
|
@ -7,11 +7,14 @@
|
||||
#include "WorkerScope.h"
|
||||
|
||||
#include "jsapi.h"
|
||||
#include "mozilla/Debug.h"
|
||||
#include "mozilla/dom/FunctionBinding.h"
|
||||
#include "mozilla/dom/DedicatedWorkerGlobalScopeBinding.h"
|
||||
#include "mozilla/dom/SharedWorkerGlobalScopeBinding.h"
|
||||
|
||||
#ifdef ANDROID
|
||||
#include <android/log.h>
|
||||
#endif
|
||||
|
||||
#include "Console.h"
|
||||
#include "Location.h"
|
||||
#include "Navigator.h"
|
||||
@ -258,8 +261,13 @@ WorkerGlobalScope::Dump(const Optional<nsAString>& aString) const
|
||||
return;
|
||||
}
|
||||
|
||||
PrintToDebugger(aString.Value(), stdout, kPrintToStream
|
||||
| kPrintInfoLog);
|
||||
NS_ConvertUTF16toUTF8 str(aString.Value());
|
||||
|
||||
#ifdef ANDROID
|
||||
__android_log_print(ANDROID_LOG_INFO, "Gecko", "%s", str.get());
|
||||
#endif
|
||||
fputs(str.get(), stdout);
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
DedicatedWorkerGlobalScope::DedicatedWorkerGlobalScope(WorkerPrivate* aWorkerPrivate)
|
||||
|
@ -80,6 +80,9 @@ interface nsIWebBrowserChrome : nsISupports
|
||||
// Whether this was opened by nsGlobalWindow::ShowModalDialog.
|
||||
const unsigned long CHROME_MODAL_CONTENT_WINDOW = 0x00080000;
|
||||
|
||||
// Whether this window should use remote (out-of-process) tabs.
|
||||
const unsigned long CHROME_REMOTE_WINDOW = 0x00100000;
|
||||
|
||||
// Prevents new window animations on Mac OS X Lion. Ignored on other
|
||||
// platforms.
|
||||
const unsigned long CHROME_MAC_SUPPRESS_ANIMATION = 0x01000000;
|
||||
|
@ -17,7 +17,7 @@ NS_NewControllerCommandTable(nsIControllerCommandTable** aResult);
|
||||
|
||||
|
||||
nsControllerCommandTable::nsControllerCommandTable()
|
||||
: mCommandsTable(NUM_COMMANDS_BOUNDS, false)
|
||||
: mCommandsTable(NUM_COMMANDS_BOUNDS)
|
||||
, mMutable(true)
|
||||
{
|
||||
}
|
||||
@ -40,15 +40,9 @@ NS_IMETHODIMP
|
||||
nsControllerCommandTable::RegisterCommand(const char * aCommandName, nsIControllerCommand *aCommand)
|
||||
{
|
||||
NS_ENSURE_TRUE(mMutable, NS_ERROR_FAILURE);
|
||||
|
||||
nsCStringKey commandKey(aCommandName);
|
||||
|
||||
if (mCommandsTable.Put(&commandKey, aCommand))
|
||||
{
|
||||
#if DEBUG
|
||||
NS_WARNING("Replacing existing command -- ");
|
||||
#endif
|
||||
}
|
||||
|
||||
mCommandsTable.Put(nsDependentCString(aCommandName), aCommand);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -58,10 +52,14 @@ nsControllerCommandTable::UnregisterCommand(const char * aCommandName, nsIContro
|
||||
{
|
||||
NS_ENSURE_TRUE(mMutable, NS_ERROR_FAILURE);
|
||||
|
||||
nsCStringKey commandKey(aCommandName);
|
||||
nsDependentCString commandKey(aCommandName);
|
||||
|
||||
bool wasRemoved = mCommandsTable.Remove(&commandKey);
|
||||
return wasRemoved ? NS_OK : NS_ERROR_FAILURE;
|
||||
if (!mCommandsTable.Get(commandKey, nullptr)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
mCommandsTable.Remove(commandKey);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
@ -69,15 +67,14 @@ NS_IMETHODIMP
|
||||
nsControllerCommandTable::FindCommandHandler(const char * aCommandName, nsIControllerCommand **outCommand)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(outCommand);
|
||||
|
||||
|
||||
*outCommand = nullptr;
|
||||
|
||||
nsCStringKey commandKey(aCommandName);
|
||||
nsISupports* foundCommand = mCommandsTable.Get(&commandKey);
|
||||
|
||||
nsCOMPtr<nsIControllerCommand> foundCommand;
|
||||
mCommandsTable.Get(nsDependentCString(aCommandName), getter_AddRefs(foundCommand));
|
||||
if (!foundCommand) return NS_ERROR_FAILURE;
|
||||
|
||||
// no need to addref since the .Get does it for us
|
||||
*outCommand = reinterpret_cast<nsIControllerCommand*>(foundCommand);
|
||||
|
||||
foundCommand.forget(outCommand);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -90,18 +87,18 @@ nsControllerCommandTable::IsCommandEnabled(const char * aCommandName, nsISupport
|
||||
NS_ENSURE_ARG_POINTER(aResult);
|
||||
|
||||
*aResult = false;
|
||||
|
||||
// find the command
|
||||
|
||||
// find the command
|
||||
nsCOMPtr<nsIControllerCommand> commandHandler;
|
||||
FindCommandHandler(aCommandName, getter_AddRefs(commandHandler));
|
||||
if (!commandHandler)
|
||||
FindCommandHandler(aCommandName, getter_AddRefs(commandHandler));
|
||||
if (!commandHandler)
|
||||
{
|
||||
#if DEBUG
|
||||
NS_WARNING("Controller command table asked about a command that it does not handle -- ");
|
||||
#endif
|
||||
return NS_OK; // we don't handle this command
|
||||
}
|
||||
|
||||
|
||||
return commandHandler->IsCommandEnabled(aCommandName, aCommandRefCon, aResult);
|
||||
}
|
||||
|
||||
@ -109,9 +106,9 @@ nsControllerCommandTable::IsCommandEnabled(const char * aCommandName, nsISupport
|
||||
NS_IMETHODIMP
|
||||
nsControllerCommandTable::UpdateCommandState(const char * aCommandName, nsISupports *aCommandRefCon)
|
||||
{
|
||||
// find the command
|
||||
// find the command
|
||||
nsCOMPtr<nsIControllerCommand> commandHandler;
|
||||
FindCommandHandler(aCommandName, getter_AddRefs(commandHandler));
|
||||
FindCommandHandler(aCommandName, getter_AddRefs(commandHandler));
|
||||
if (!commandHandler)
|
||||
{
|
||||
#if DEBUG
|
||||
@ -119,7 +116,7 @@ nsControllerCommandTable::UpdateCommandState(const char * aCommandName, nsISuppo
|
||||
#endif
|
||||
return NS_OK; // we don't handle this command
|
||||
}
|
||||
|
||||
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
@ -131,8 +128,8 @@ nsControllerCommandTable::SupportsCommand(const char * aCommandName, nsISupports
|
||||
// XXX: need to check the readonly and disabled states
|
||||
|
||||
*aResult = false;
|
||||
|
||||
// find the command
|
||||
|
||||
// find the command
|
||||
nsCOMPtr<nsIControllerCommand> commandHandler;
|
||||
FindCommandHandler(aCommandName, getter_AddRefs(commandHandler));
|
||||
|
||||
@ -144,7 +141,7 @@ nsControllerCommandTable::SupportsCommand(const char * aCommandName, nsISupports
|
||||
NS_IMETHODIMP
|
||||
nsControllerCommandTable::DoCommand(const char * aCommandName, nsISupports *aCommandRefCon)
|
||||
{
|
||||
// find the command
|
||||
// find the command
|
||||
nsCOMPtr<nsIControllerCommand> commandHandler;
|
||||
FindCommandHandler(aCommandName, getter_AddRefs(commandHandler));
|
||||
if (!commandHandler)
|
||||
@ -154,14 +151,14 @@ nsControllerCommandTable::DoCommand(const char * aCommandName, nsISupports *aCom
|
||||
#endif
|
||||
return NS_OK; // we don't handle this command
|
||||
}
|
||||
|
||||
|
||||
return commandHandler->DoCommand(aCommandName, aCommandRefCon);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsControllerCommandTable::DoCommandParams(const char *aCommandName, nsICommandParams *aParams, nsISupports *aCommandRefCon)
|
||||
{
|
||||
// find the command
|
||||
// find the command
|
||||
nsCOMPtr<nsIControllerCommand> commandHandler;
|
||||
FindCommandHandler(aCommandName, getter_AddRefs(commandHandler));
|
||||
if (!commandHandler)
|
||||
@ -178,7 +175,7 @@ nsControllerCommandTable::DoCommandParams(const char *aCommandName, nsICommandPa
|
||||
NS_IMETHODIMP
|
||||
nsControllerCommandTable::GetCommandState(const char *aCommandName, nsICommandParams *aParams, nsISupports *aCommandRefCon)
|
||||
{
|
||||
// find the command
|
||||
// find the command
|
||||
nsCOMPtr<nsIControllerCommand> commandHandler;
|
||||
FindCommandHandler(aCommandName, getter_AddRefs(commandHandler));
|
||||
if (!commandHandler)
|
||||
@ -207,6 +204,3 @@ NS_NewControllerCommandTable(nsIControllerCommandTable** aResult)
|
||||
*aResult = newCommandTable;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user