This commit is contained in:
Ryan VanderMeulen 2014-02-12 08:39:43 -05:00
Родитель 679db71a9b e6001f74f4
Коммит ff776dff9f
301 изменённых файлов: 7662 добавлений и 5132 удалений

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

@ -0,0 +1,3 @@
function foo() { var a=1; var b=2; bar(a, b); }
function bar(c, d) { debugger; }
foo();

Просмотреть файл

@ -0,0 +1 @@
Content-Type: application/javascript

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше