mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Merge last PGO-green changeset of mozilla-inbound to mozilla-central
This commit is contained in:
commit
a5572ca7ff
@ -122,7 +122,7 @@
|
||||
<content>
|
||||
<xul:hbox align="end" pack="end" anonid="innerbox" class="chatbar-innerbox" mousethrough="always" flex="1">
|
||||
<xul:toolbarbutton anonid="nub" class="chatbar-button" type="menu" collapsed="true" mousethrough="never">
|
||||
<xul:menupopup anonid="nubMenu" oncommand="document.getBindingParent(this).swapChat(event)"/>
|
||||
<xul:menupopup anonid="nubMenu" oncommand="document.getBindingParent(this).showChat(event.target.chat)"/>
|
||||
</xul:toolbarbutton>
|
||||
<xul:spacer flex="1" anonid="spacer" class="chatbar-overflow-spacer"/>
|
||||
<children/>
|
||||
@ -130,6 +130,12 @@
|
||||
</content>
|
||||
|
||||
<implementation implements="nsIDOMEventListener">
|
||||
<constructor>
|
||||
// to avoid reflows we cache the values for various widths.
|
||||
this.cachedWidthOpen = 0;
|
||||
this.cachedWidthMinimized = 0;
|
||||
this.cachedWidthNub = 0;
|
||||
</constructor>
|
||||
|
||||
<field name="innerbox" readonly="true">
|
||||
document.getAnonymousElementByAttribute(this, "anonid", "innerbox");
|
||||
@ -143,22 +149,27 @@
|
||||
document.getAnonymousElementByAttribute(this, "anonid", "nub");
|
||||
</field>
|
||||
|
||||
<property name="emptyWidth">
|
||||
<getter>
|
||||
return document.getAnonymousElementByAttribute(this, "anonid", "spacer").boxObject.width;
|
||||
</getter>
|
||||
</property>
|
||||
|
||||
<property name="selectedChat">
|
||||
<getter><![CDATA[
|
||||
return this._selectedChat;
|
||||
]]></getter>
|
||||
<setter><![CDATA[
|
||||
if (this._selectedChat)
|
||||
this._selectedChat.removeAttribute("selected");
|
||||
this._selectedChat = val;
|
||||
// this is pretty horrible, but we:
|
||||
// * want to avoid doing touching 'selected' attribute when the
|
||||
// specified chat is already selected.
|
||||
// * remove 'activity' attribute on newly selected tab *even if*
|
||||
// newly selected is already selected.
|
||||
// * need to handle either current or new being null.
|
||||
if (this._selectedChat != val) {
|
||||
if (this._selectedChat) {
|
||||
this._selectedChat.removeAttribute("selected");
|
||||
}
|
||||
this._selectedChat = val;
|
||||
if (val) {
|
||||
this._selectedChat.setAttribute("selected", "true");
|
||||
}
|
||||
}
|
||||
if (val) {
|
||||
this._selectedChat.setAttribute("selected", "true");
|
||||
this._selectedChat.removeAttribute("activity");
|
||||
}
|
||||
]]></setter>
|
||||
@ -167,55 +178,48 @@
|
||||
<field name="menuitemMap">new WeakMap()</field>
|
||||
<field name="chatboxForURL">new Map();</field>
|
||||
|
||||
<property name="firstCollapsedChild">
|
||||
<property name="hasCollapsedChildren">
|
||||
<getter><![CDATA[
|
||||
return !!this.querySelector("[collapsed]");
|
||||
]]></getter>
|
||||
</property>
|
||||
|
||||
<property name="collapsedChildren">
|
||||
<getter><![CDATA[
|
||||
// A generator yielding all collapsed chatboxes, in the order in
|
||||
// which they should be restored.
|
||||
let child = this.lastChild;
|
||||
while (child && !child.collapsed) {
|
||||
while (child) {
|
||||
if (child.collapsed)
|
||||
yield child;
|
||||
child = child.previousSibling;
|
||||
}
|
||||
return child;
|
||||
]]></getter>
|
||||
</property>
|
||||
|
||||
<property name="firstVisibleChild">
|
||||
<property name="visibleChildren">
|
||||
<getter><![CDATA[
|
||||
// A generator yielding all non-collapsed chatboxes.
|
||||
let child = this.firstChild;
|
||||
while (child && child.collapsed) {
|
||||
while (child) {
|
||||
if (!child.collapsed)
|
||||
yield child;
|
||||
child = child.nextSibling;
|
||||
}
|
||||
return child;
|
||||
]]></getter>
|
||||
</property>
|
||||
|
||||
<property name="firstRemovableChild">
|
||||
<property name="collapsibleChildren">
|
||||
<getter><![CDATA[
|
||||
let child = this.firstChild;
|
||||
// find the first visible non-focused chatbox, always keep one visible if we
|
||||
// have enough width to do so.
|
||||
while (child &&
|
||||
(child.collapsed || child == this.selectedChat)) {
|
||||
child = child.nextSibling;
|
||||
}
|
||||
if (!child && this.selectedChat) {
|
||||
child = this.selectedChat;
|
||||
}
|
||||
return child;
|
||||
// A generator yielding all children which are able to be collapsed
|
||||
// in the order in which they should be collapsed.
|
||||
// (currently this is all visible ones other than the selected one.)
|
||||
for (let child of this.visibleChildren)
|
||||
if (child != this.selectedChat)
|
||||
yield child;
|
||||
]]></getter>
|
||||
</property>
|
||||
|
||||
<method name="resize">
|
||||
<body><![CDATA[
|
||||
let child = this.firstCollapsedChild;
|
||||
if (child && this.emptyWidth > child.viewWidth) {
|
||||
this.showChat(child);
|
||||
}
|
||||
if (!this.firstCollapsedChild) {
|
||||
window.removeEventListener("resize", this);
|
||||
this.menupopup.parentNode.collapsed = true;
|
||||
}
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
<method name="updateTitlebar">
|
||||
<parameter name="aChatbox"/>
|
||||
<body><![CDATA[
|
||||
@ -231,32 +235,46 @@
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
<method name="handleEvent">
|
||||
<parameter name="aEvent"/>
|
||||
<method name="calcTotalWidthOf">
|
||||
<parameter name="aElement"/>
|
||||
<body><![CDATA[
|
||||
if (aEvent.type == "resize") {
|
||||
this.resize();
|
||||
}
|
||||
let cs = document.defaultView.getComputedStyle(aElement);
|
||||
let margins = parseInt(cs.marginLeft) + parseInt(cs.marginRight);
|
||||
return aElement.getBoundingClientRect().width + margins;
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
<method name="swapChat">
|
||||
<parameter name="aEvent"/>
|
||||
<method name="getTotalChildWidth">
|
||||
<parameter name="aChatbox"/>
|
||||
<body><![CDATA[
|
||||
let menuitem = aEvent.target;
|
||||
let newChat = menuitem.chat;
|
||||
let oldChat = this.firstVisibleChild;
|
||||
if (oldChat)
|
||||
this.collapseChat(oldChat);
|
||||
if (newChat)
|
||||
this.showChat(newChat);
|
||||
// gets the width of a child, using/setting the cached value for
|
||||
// children of this type.
|
||||
// DOES NOT take collapsed into account - ie, this is the width
|
||||
// of a child assuming it is *not* collapsed. (collapsed chats
|
||||
// have a width of zero as they are not shown).
|
||||
if (aChatbox.minimized) {
|
||||
if (!this.cachedWidthMinimized) {
|
||||
if (aChatbox.collapsed)
|
||||
throw new Error("can't calculate size of collapsed chat!");
|
||||
this.cachedWidthMinimized = this.calcTotalWidthOf(aChatbox);
|
||||
}
|
||||
return this.cachedWidthMinimized;
|
||||
}
|
||||
if (!this.cachedWidthOpen) {
|
||||
if (aChatbox.collapsed)
|
||||
throw new Error("can't calculate size of collapsed chat!");
|
||||
this.cachedWidthOpen = this.calcTotalWidthOf(aChatbox);
|
||||
}
|
||||
return this.cachedWidthOpen;
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
<method name="collapseChat">
|
||||
<parameter name="aChatbox"/>
|
||||
<body><![CDATA[
|
||||
aChatbox.viewWidth = aChatbox.getBoundingClientRect().width;
|
||||
// we ensure that the cached width for a child of this type is
|
||||
// up-to-date so we can use it when resizing.
|
||||
this.getTotalChildWidth(aChatbox);
|
||||
aChatbox.collapsed = true;
|
||||
aChatbox.isActive = false;
|
||||
let menu = document.createElementNS("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul", "menuitem");
|
||||
@ -266,13 +284,31 @@
|
||||
menu.chat = aChatbox;
|
||||
this.menuitemMap.set(aChatbox, menu);
|
||||
this.menupopup.appendChild(menu);
|
||||
this.menupopup.parentNode.collapsed = false;
|
||||
this.nub.collapsed = false;
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
<method name="showChat">
|
||||
<parameter name="aChatbox"/>
|
||||
<body><![CDATA[
|
||||
if (aChatbox.minimized)
|
||||
aChatbox.minimized = false;
|
||||
if (this.selectedChat != aChatbox)
|
||||
this.selectedChat = aChatbox;
|
||||
if (!aChatbox.collapsed)
|
||||
return; // already showing - no more to do.
|
||||
this._showChat(aChatbox);
|
||||
// showing a collapsed chat might mean another needs to be collapsed
|
||||
// to make room...
|
||||
this.resize();
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
<method name="_showChat">
|
||||
<parameter name="aChatbox"/>
|
||||
<body><![CDATA[
|
||||
// the actual implementation - doesn't check for overflow, assumes
|
||||
// collapsed, etc.
|
||||
let menuitem = this.menuitemMap.get(aChatbox);
|
||||
this.menuitemMap.delete(aChatbox);
|
||||
this.menupopup.removeChild(menuitem);
|
||||
@ -282,13 +318,28 @@
|
||||
</method>
|
||||
|
||||
<method name="remove">
|
||||
<parameter name="aChatbox"/>
|
||||
<body><![CDATA[
|
||||
this._remove(aChatbox);
|
||||
// The removal of a chat may mean a collapsed one can spring up,
|
||||
// or that the popup should be hidden.
|
||||
this.resize();
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
<method name="_remove">
|
||||
<parameter name="aChatbox"/>
|
||||
<body><![CDATA[
|
||||
if (this.selectedChat == aChatbox) {
|
||||
this.selectedChat = aChatbox.previousSibling ? aChatbox.previousSibling : aChatbox.nextSibling
|
||||
}
|
||||
this.removeChild(aChatbox);
|
||||
this.resize();
|
||||
// child might have been collapsed.
|
||||
let menuitem = this.menuitemMap.get(aChatbox);
|
||||
if (menuitem) {
|
||||
this.menuitemMap.delete(aChatbox);
|
||||
this.menupopup.removeChild(menuitem);
|
||||
}
|
||||
this.chatboxForURL.delete(aChatbox.getAttribute('src'));
|
||||
]]></body>
|
||||
</method>
|
||||
@ -296,9 +347,10 @@
|
||||
<method name="removeAll">
|
||||
<body><![CDATA[
|
||||
while (this.firstChild) {
|
||||
this.removeChild(this.firstChild);
|
||||
this._remove(this.firstChild);
|
||||
}
|
||||
this.chatboxForURL = new Map();
|
||||
// and the nub/popup must also die.
|
||||
this.nub.collapsed = true;
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
@ -312,11 +364,7 @@
|
||||
if (cb) {
|
||||
cb = cb.get();
|
||||
if (cb.parentNode) {
|
||||
// ensure this chatbox is visible
|
||||
if (this.selectedChat != cb)
|
||||
this.selectedChat = cb;
|
||||
if (cb.collapsed)
|
||||
this.showChat(cb);
|
||||
this.showChat(cb);
|
||||
if (aCallback)
|
||||
aCallback(cb.iframe.contentWindow);
|
||||
return;
|
||||
@ -330,6 +378,75 @@
|
||||
this.insertBefore(cb, this.firstChild);
|
||||
cb.init(aProvider, aURL, aCallback);
|
||||
this.chatboxForURL.set(aURL, Cu.getWeakReference(cb));
|
||||
this.resize();
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
<method name="resize">
|
||||
<body><![CDATA[
|
||||
// Checks the current size against the collapsed state of children
|
||||
// and collapses or expands as necessary such that as many as possible
|
||||
// are shown.
|
||||
// So 2 basic strategies:
|
||||
// * Collapse/Expand one at a time until we can't collapse/expand any
|
||||
// more - but this is one reflow per change.
|
||||
// * Calculate the dimensions ourself and choose how many to collapse
|
||||
// or expand based on this, then do them all in one go. This is one
|
||||
// reflow regardless of how many we change.
|
||||
// So we go the more complicated but more efficient second option...
|
||||
let availWidth = this.getBoundingClientRect().width;
|
||||
let currentWidth = 0;
|
||||
if (!this.nub.collapsed) { // the nub is visible.
|
||||
if (!this.cachedWidthNub)
|
||||
this.cachedWidthNub = this.calcTotalWidthOf(this.nub);
|
||||
currentWidth += this.cachedWidthNub;
|
||||
}
|
||||
for (let child of this.visibleChildren) {
|
||||
currentWidth += this.getTotalChildWidth(child);
|
||||
}
|
||||
|
||||
if (currentWidth > availWidth) {
|
||||
// we need to collapse some.
|
||||
let toCollapse = [];
|
||||
for (let child of this.collapsibleChildren) {
|
||||
if (currentWidth <= availWidth)
|
||||
break;
|
||||
toCollapse.push(child);
|
||||
currentWidth -= this.getTotalChildWidth(child);
|
||||
}
|
||||
if (toCollapse.length) {
|
||||
for (let child of toCollapse)
|
||||
this.collapseChat(child);
|
||||
}
|
||||
} else if (currentWidth < availWidth) {
|
||||
// we *might* be able to expand some - see how many.
|
||||
// XXX - if this was clever, it could know when removing the nub
|
||||
// leaves enough space to show all collapsed
|
||||
let toShow = [];
|
||||
for (let child of this.collapsedChildren) {
|
||||
currentWidth += this.getTotalChildWidth(child);
|
||||
if (currentWidth > availWidth)
|
||||
break;
|
||||
toShow.push(child);
|
||||
}
|
||||
for (let child of toShow)
|
||||
this._showChat(child);
|
||||
|
||||
// If none remain collapsed remove the nub.
|
||||
if (!this.hasCollapsedChildren) {
|
||||
this.nub.collapsed = true;
|
||||
}
|
||||
}
|
||||
// else: achievement unlocked - we are pixel-perfect!
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
<method name="handleEvent">
|
||||
<parameter name="aEvent"/>
|
||||
<body><![CDATA[
|
||||
if (aEvent.type == "resize") {
|
||||
this.resize();
|
||||
}
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
@ -338,18 +455,11 @@
|
||||
<handler event="popupshown"><![CDATA[
|
||||
this.nub.removeAttribute("activity");
|
||||
]]></handler>
|
||||
<handler event="overflow"><![CDATA[
|
||||
// make sure we're not getting an overflow from content
|
||||
if (event.originalTarget != this.innerbox)
|
||||
return;
|
||||
|
||||
let hasHidden = this.firstCollapsedChild;
|
||||
let child = this.firstRemovableChild;
|
||||
if (child)
|
||||
this.collapseChat(child);
|
||||
if (!hasHidden) {
|
||||
window.addEventListener("resize", this);
|
||||
}
|
||||
<handler event="load"><![CDATA[
|
||||
window.addEventListener("resize", this);
|
||||
]]></handler>
|
||||
<handler event="unload"><![CDATA[
|
||||
window.removeEventListener("resize", this);
|
||||
]]></handler>
|
||||
</handlers>
|
||||
</binding>
|
||||
|
@ -12,10 +12,12 @@ function test() {
|
||||
workerURL: "https://example.com/browser/browser/base/content/test/social_worker.js",
|
||||
iconURL: "https://example.com/browser/browser/base/content/test/moz.png"
|
||||
};
|
||||
let oldwidth = window.outerWidth; // we futz with this, so we restore it
|
||||
runSocialTestWithProvider(manifest, function (finishcb) {
|
||||
runSocialTests(tests, undefined, undefined, function () {
|
||||
let chats = document.getElementById("pinnedchats");
|
||||
ok(chats.children.length == 0, "no chatty children left behind");
|
||||
window.resizeTo(oldwidth, window.outerHeight);
|
||||
finishcb();
|
||||
});
|
||||
});
|
||||
@ -109,8 +111,8 @@ var tests = {
|
||||
chats.selectedChat.close();
|
||||
}
|
||||
ok(!chats.selectedChat, "chats are all closed");
|
||||
port.close();
|
||||
ensureSocialUrlNotRemembered(chatUrl);
|
||||
port.close();
|
||||
next();
|
||||
break;
|
||||
}
|
||||
@ -138,6 +140,7 @@ var tests = {
|
||||
evt.initCustomEvent("socialTest-CloseSelf", true, true, {});
|
||||
doc.documentElement.dispatchEvent(evt);
|
||||
ok(!chat.parentNode, "chat is now closed");
|
||||
port.close();
|
||||
next();
|
||||
break;
|
||||
}
|
||||
@ -162,6 +165,7 @@ var tests = {
|
||||
let chats = document.getElementById("pinnedchats");
|
||||
chats.selectedChat.close();
|
||||
is(chats.selectedChat, null, "should only have been one chat open");
|
||||
port.close();
|
||||
next();
|
||||
} else {
|
||||
// first time we got the opened message, so re-request the same
|
||||
@ -173,6 +177,122 @@ var tests = {
|
||||
}
|
||||
port.postMessage({topic: "test-init", data: { id: 1 }});
|
||||
},
|
||||
|
||||
// check removeAll does the right thing
|
||||
testRemoveAll: function(next, mode) {
|
||||
let port = Social.provider.getWorkerPort();
|
||||
port.postMessage({topic: "test-init"});
|
||||
get3ChatsForCollapsing(mode || "normal", function() {
|
||||
let chatbar = window.SocialChatBar.chatbar;
|
||||
chatbar.removeAll();
|
||||
// should be no evidence of any chats left.
|
||||
is(chatbar.childNodes.length, 0, "should be no chats left");
|
||||
checkPopup();
|
||||
is(chatbar.selectedChat, null, "nothing should be selected");
|
||||
is(chatbar.chatboxForURL.size, 0, "chatboxForURL map should be empty");
|
||||
port.close();
|
||||
next();
|
||||
});
|
||||
},
|
||||
|
||||
testRemoveAllMinimized: function(next) {
|
||||
this.testRemoveAll(next, "minimized");
|
||||
},
|
||||
|
||||
// resize and collapse testing.
|
||||
testBrowserResize: function(next, mode) {
|
||||
let chats = document.getElementById("pinnedchats");
|
||||
let port = Social.provider.getWorkerPort();
|
||||
port.postMessage({topic: "test-init"});
|
||||
get3ChatsForCollapsing(mode || "normal", function(first, second, third) {
|
||||
let chatWidth = chats.getTotalChildWidth(first);
|
||||
ok(chatWidth, "have a chatwidth");
|
||||
let popupWidth = getPopupWidth();
|
||||
ok(popupWidth, "have a popupwidth");
|
||||
info("starting resize tests - each chat's width is " + chatWidth +
|
||||
" and the popup width is " + popupWidth);
|
||||
resizeAndCheckWidths(first, second, third, [
|
||||
[chatWidth-1, false, false, true, "to < 1 chat width - only last should be visible."],
|
||||
[chatWidth+1, false, false, true, "one pixel more then one fully exposed (not counting popup) - still only 1."],
|
||||
[chatWidth+popupWidth+1, false, false, true, "one pixel more than one fully exposed (including popup) - still only 1."],
|
||||
[chatWidth*2-1, false, false, true, "second not showing by 1 pixel (not counting popup) - only 1 exposed."],
|
||||
[chatWidth*2+popupWidth-1, false, false, true, "second not showing by 1 pixel (including popup) - only 1 exposed."],
|
||||
[chatWidth*2+popupWidth+1, false, true, true, "big enough to fit 2 - nub remains visible as first is still hidden"],
|
||||
[chatWidth*3+popupWidth-1, false, true, true, "one smaller than the size necessary to display all three - first still hidden"],
|
||||
[chatWidth*3+popupWidth+1, true, true, true, "big enough to fit all - all exposed (which removes the nub)"],
|
||||
[chatWidth*3, true, true, true, "now the nub is hidden we can resize back down to chatWidth*3 before overflow."],
|
||||
[chatWidth*3-1, false, true, true, "one pixel less and the first is again collapsed (and the nub re-appears)"],
|
||||
[chatWidth*2+popupWidth+1, false, true, true, "back down to just big enough to fit 2"],
|
||||
[chatWidth*2+popupWidth-1, false, false, true, "back down to just not enough to fit 2"],
|
||||
[chatWidth*3+popupWidth+1, true, true, true, "now a large jump to make all 3 visible (ie, affects 2)"],
|
||||
[chatWidth*1.5, false, false, true, "and a large jump back down to 1 visible (ie, affects 2)"],
|
||||
], function() {
|
||||
closeAllChats();
|
||||
port.close();
|
||||
next();
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
testBrowserResizeMinimized: function(next) {
|
||||
this.testBrowserResize(next, "minimized");
|
||||
},
|
||||
|
||||
testShowWhenCollapsed: function(next) {
|
||||
let port = Social.provider.getWorkerPort();
|
||||
port.postMessage({topic: "test-init"});
|
||||
get3ChatsForCollapsing("normal", function(first, second, third) {
|
||||
let chatbar = window.SocialChatBar.chatbar;
|
||||
chatbar.showChat(first);
|
||||
ok(!first.collapsed, "first should no longer be collapsed");
|
||||
ok(second.collapsed || third.collapsed, false, "one of the others should be collapsed");
|
||||
closeAllChats();
|
||||
port.close();
|
||||
next();
|
||||
});
|
||||
},
|
||||
|
||||
testActivity: function(next) {
|
||||
let port = Social.provider.getWorkerPort();
|
||||
port.postMessage({topic: "test-init"});
|
||||
get3ChatsForCollapsing("normal", function(first, second, third) {
|
||||
let chatbar = window.SocialChatBar.chatbar;
|
||||
is(chatbar.selectedChat, third, "third chat should be selected");
|
||||
ok(!chatbar.selectedChat.hasAttribute("activity"), "third chat should have no activity");
|
||||
// send an activity message to the second.
|
||||
ok(!second.hasAttribute("activity"), "second chat should have no activity");
|
||||
let iframe2 = second.iframe;
|
||||
let evt = iframe2.contentDocument.createEvent("CustomEvent");
|
||||
evt.initCustomEvent("socialChatActivity", true, true, {});
|
||||
iframe2.contentDocument.documentElement.dispatchEvent(evt);
|
||||
// second should have activity.
|
||||
ok(second.hasAttribute("activity"), "second chat should now have activity");
|
||||
// select the second - it should lose "activity"
|
||||
chatbar.selectedChat = second;
|
||||
ok(!second.hasAttribute("activity"), "second chat should no longer have activity");
|
||||
// Now try the first - it is collapsed, so the 'nub' also gets activity attr.
|
||||
ok(!first.hasAttribute("activity"), "first chat should have no activity");
|
||||
let iframe1 = first.iframe;
|
||||
let evt = iframe1.contentDocument.createEvent("CustomEvent");
|
||||
evt.initCustomEvent("socialChatActivity", true, true, {});
|
||||
iframe1.contentDocument.documentElement.dispatchEvent(evt);
|
||||
ok(first.hasAttribute("activity"), "first chat should now have activity");
|
||||
ok(chatbar.nub.hasAttribute("activity"), "nub should also have activity");
|
||||
// first is collapsed, so use openChat to get it.
|
||||
chatbar.openChat(Social.provider, first.getAttribute("src"));
|
||||
ok(!first.hasAttribute("activity"), "first chat should no longer have activity");
|
||||
// The nub should lose the activity flag here too
|
||||
todo(!chatbar.nub.hasAttribute("activity"), "Bug 806266 - nub should no longer have activity");
|
||||
// TODO: tests for bug 806266 should arrange to have 2 chats collapsed
|
||||
// then open them checking the nub is updated correctly.
|
||||
closeAllChats();
|
||||
port.close();
|
||||
next();
|
||||
});
|
||||
},
|
||||
|
||||
// XXX - note this must be the last test until we restore the login state
|
||||
// between tests...
|
||||
testCloseOnLogout: function(next) {
|
||||
const chatUrl = "https://example.com/browser/browser/base/content/test/social_chat.html";
|
||||
let port = Social.provider.getWorkerPort();
|
||||
@ -184,6 +304,7 @@ var tests = {
|
||||
case "got-chatbox-message":
|
||||
ok(true, "got a chat window opened");
|
||||
port.postMessage({topic: "test-logout"});
|
||||
port.close();
|
||||
waitForCondition(function() document.getElementById("pinnedchats").firstChild == null,
|
||||
next,
|
||||
"chat windows didn't close");
|
||||
@ -191,5 +312,163 @@ var tests = {
|
||||
}
|
||||
}
|
||||
port.postMessage({topic: "test-worker-chat", data: chatUrl});
|
||||
},
|
||||
}
|
||||
|
||||
// And lots of helpers for the resize tests.
|
||||
function get3ChatsForCollapsing(mode, cb) {
|
||||
// We make one chat, then measure its size. We then resize the browser to
|
||||
// ensure a second can be created fully visible but a third can not - then
|
||||
// create the other 2. first will will be collapsed, second fully visible
|
||||
// and the third also visible and the "selected" one.
|
||||
// To make our life easier we don't go via the worker and ports so we get
|
||||
// more control over creation *and* to make the code much simpler. We
|
||||
// assume the worker/port stuff is individually tested above.
|
||||
let chatbar = window.SocialChatBar.chatbar;
|
||||
let chatWidth = undefined;
|
||||
let num = 0;
|
||||
is(chatbar.childNodes.length, 0, "chatbar starting empty");
|
||||
is(chatbar.menupopup.childNodes.length, 0, "popup starting empty");
|
||||
|
||||
makeChat(mode, "first chat", function() {
|
||||
// got the first one.
|
||||
checkPopup();
|
||||
ok(chatbar.menupopup.parentNode.collapsed, "menu selection isn't visible");
|
||||
// we kinda cheat here and get the width of the first chat, assuming
|
||||
// that all future chats will have the same width when open.
|
||||
chatWidth = chatbar.calcTotalWidthOf(chatbar.selectedChat);
|
||||
let desired = chatWidth * 2.5;
|
||||
resizeWindowToChatAreaWidth(desired, function(sizedOk) {
|
||||
ok(sizedOk, "can't do any tests without this width");
|
||||
checkPopup();
|
||||
makeChat(mode, "second chat", function() {
|
||||
is(chatbar.childNodes.length, 2, "now have 2 chats");
|
||||
checkPopup();
|
||||
// and create the third.
|
||||
makeChat(mode, "third chat", function() {
|
||||
is(chatbar.childNodes.length, 3, "now have 3 chats");
|
||||
checkPopup();
|
||||
// XXX - this is a hacky implementation detail around the order of
|
||||
// the chats. Ideally things would be a little more sane wrt the
|
||||
// other in which the children were created.
|
||||
let second = chatbar.childNodes[2];
|
||||
let first = chatbar.childNodes[1];
|
||||
let third = chatbar.childNodes[0];
|
||||
ok(first.collapsed && !second.collapsed && !third.collapsed, "collapsed state as promised");
|
||||
is(chatbar.selectedChat, third, "third is selected as promised")
|
||||
info("have 3 chats for collapse testing - starting actual test...");
|
||||
cb(first, second, third);
|
||||
}, mode);
|
||||
}, mode);
|
||||
});
|
||||
}, mode);
|
||||
}
|
||||
|
||||
function makeChat(mode, uniqueid, cb) {
|
||||
const chatUrl = "https://example.com/browser/browser/base/content/test/social_chat.html";
|
||||
let provider = Social.provider;
|
||||
window.SocialChatBar.openChat(provider, chatUrl + "?id=" + uniqueid, function(chat) {
|
||||
// we can't callback immediately or we might close the chat during
|
||||
// this event which upsets the implementation - it is only 1/2 way through
|
||||
// handling the load event.
|
||||
chat.document.title = uniqueid;
|
||||
executeSoon(cb);
|
||||
}, mode);
|
||||
}
|
||||
|
||||
function checkPopup() {
|
||||
// popup only showing if any collapsed popup children.
|
||||
let chatbar = window.SocialChatBar.chatbar;
|
||||
let numCollapsed = 0;
|
||||
for (let chat of chatbar.childNodes) {
|
||||
if (chat.collapsed) {
|
||||
numCollapsed += 1;
|
||||
// and it have a menuitem weakmap
|
||||
is(chatbar.menuitemMap.get(chat).nodeName, "menuitem", "collapsed chat has a menu item");
|
||||
} else {
|
||||
ok(!chatbar.menuitemMap.has(chat), "open chat has no menu item");
|
||||
}
|
||||
}
|
||||
is(chatbar.menupopup.parentNode.collapsed, numCollapsed == 0, "popup matches child collapsed state");
|
||||
is(chatbar.menupopup.childNodes.length, numCollapsed, "popup has correct count of children");
|
||||
// todo - check each individual elt is what we expect?
|
||||
}
|
||||
|
||||
// Resize the main window so the chat area's boxObject is |desired| wide.
|
||||
// Does a callback passing |true| if the window is now big enough or false
|
||||
// if we couldn't resize large enough to satisfy the test requirement.
|
||||
function resizeWindowToChatAreaWidth(desired, cb) {
|
||||
let current = window.SocialChatBar.chatbar.getBoundingClientRect().width;
|
||||
let delta = desired - current;
|
||||
info("resizing window so chat area is " + desired + " wide, currently it is "
|
||||
+ current + ". Screen avail is " + window.screen.availWidth
|
||||
+ ", current outer width is " + window.outerWidth);
|
||||
|
||||
// WTF? Some test boxes will resize to fractional values - eg: we
|
||||
// request 660px but actually get 659.5!?
|
||||
let widthDeltaCloseEnough = function(d) {
|
||||
return Math.abs(d) <= 0.5;
|
||||
}
|
||||
|
||||
// attempting to resize by (0,0), unsurprisingly, doesn't cause a resize
|
||||
// event - so just callback saying all is well.
|
||||
if (widthDeltaCloseEnough(delta)) {
|
||||
cb(true);
|
||||
return;
|
||||
}
|
||||
// On lo-res screens we may already be maxed out but still smaller than the
|
||||
// requested size, so asking to resize up also will not cause a resize event.
|
||||
// So just callback now saying the test must be skipped.
|
||||
if (window.screen.availWidth - window.outerWidth < delta) {
|
||||
info("skipping this as screen available width is less than necessary");
|
||||
cb(false);
|
||||
return;
|
||||
}
|
||||
// Otherwise we request resize and expect a resize event
|
||||
window.addEventListener("resize", function resize_handler() {
|
||||
window.removeEventListener("resize", resize_handler);
|
||||
// we did resize - but did we get far enough to be able to continue?
|
||||
let newSize = window.SocialChatBar.chatbar.getBoundingClientRect().width;
|
||||
let sizedOk = widthDeltaCloseEnough(newSize - desired);
|
||||
if (!sizedOk) {
|
||||
// not an error...
|
||||
info("skipping this as we can't resize chat area to " + desired + " - got " + newSize);
|
||||
}
|
||||
cb(sizedOk);
|
||||
});
|
||||
window.resizeBy(delta, 0);
|
||||
}
|
||||
|
||||
function resizeAndCheckWidths(first, second, third, checks, cb) {
|
||||
if (checks.length == 0) {
|
||||
cb(); // nothing more to check!
|
||||
return;
|
||||
}
|
||||
let [width, firstVisible, secondVisible, thirdVisible, why] = checks.shift();
|
||||
info("Check: " + why);
|
||||
info("resizing window to " + width + ", expect visibility of " + firstVisible + "/" + secondVisible + "/" + thirdVisible);
|
||||
resizeWindowToChatAreaWidth(width, function(sizedOk) {
|
||||
checkPopup();
|
||||
if (sizedOk) {
|
||||
is(!first.collapsed, firstVisible, "first should be " + (firstVisible ? "visible" : "hidden"));
|
||||
is(!second.collapsed, secondVisible, "second should be " + (secondVisible ? "visible" : "hidden"));
|
||||
is(!third.collapsed, thirdVisible, "third should be " + (thirdVisible ? "visible" : "hidden"));
|
||||
}
|
||||
resizeAndCheckWidths(first, second, third, checks, cb);
|
||||
});
|
||||
}
|
||||
|
||||
function getPopupWidth() {
|
||||
let popup = window.SocialChatBar.chatbar.menupopup;
|
||||
ok(!popup.parentNode.collapsed, "asking for popup width when it is visible");
|
||||
let cs = document.defaultView.getComputedStyle(popup.parentNode);
|
||||
let margins = parseInt(cs.marginLeft) + parseInt(cs.marginRight);
|
||||
return popup.parentNode.getBoundingClientRect().width + margins;
|
||||
}
|
||||
|
||||
function closeAllChats() {
|
||||
let chatbar = window.SocialChatBar.chatbar;
|
||||
while (chatbar.selectedChat) {
|
||||
chatbar.selectedChat.close();
|
||||
}
|
||||
}
|
||||
|
@ -73,6 +73,8 @@ class RemoteAutomation(Automation):
|
||||
|
||||
if (status == 1 and self._devicemanager.processExist(proc.procName)):
|
||||
# Then we timed out, make sure Fennec is dead
|
||||
print "TEST-UNEXPECTED-FAIL | %s | application ran for longer than " \
|
||||
"allowed maximum time of %d seconds" % (self.lastTestSeen, int(maxTime))
|
||||
proc.kill()
|
||||
|
||||
return status
|
||||
|
@ -411,8 +411,7 @@ if test -n "$MOZ_METRO"; then
|
||||
AC_DEFINE(MOZ_METRO)
|
||||
# Target the Windows 8 Kit
|
||||
WINSDK_TARGETVER=602
|
||||
# Allow a higher api set
|
||||
WINVER=602
|
||||
WINVER=502
|
||||
# toolkit/library/makefile.in needs these, see nsDllMain.
|
||||
CRTDLLVERSION=110
|
||||
CRTEXPDLLVERSION=1-1-0
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include "nsDOMOfflineResourceList.h"
|
||||
#include "nsError.h"
|
||||
#include "nsIIdleService.h"
|
||||
#include "nsIPowerManagerService.h"
|
||||
|
||||
#ifdef XP_WIN
|
||||
#ifdef GetClassName
|
||||
@ -4588,6 +4589,17 @@ nsGlobalWindow::SetFullScreenInternal(bool aFullScreen, bool aRequireTrust)
|
||||
nsIDocument::ExitFullScreen(false);
|
||||
}
|
||||
|
||||
if (!mWakeLock && mFullScreen) {
|
||||
nsCOMPtr<nsIPowerManagerService> pmService =
|
||||
do_GetService(POWERMANAGERSERVICE_CONTRACTID);
|
||||
NS_ENSURE_TRUE(pmService, NS_OK);
|
||||
|
||||
pmService->NewWakeLock(NS_LITERAL_STRING("DOM_Fullscreen"), this, getter_AddRefs(mWakeLock));
|
||||
} else if (mWakeLock && !mFullScreen) {
|
||||
mWakeLock->Unlock();
|
||||
mWakeLock = NULL;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -65,6 +65,7 @@
|
||||
#include "nsWrapperCacheInlines.h"
|
||||
#include "nsIDOMApplicationRegistry.h"
|
||||
#include "nsIIdleObserver.h"
|
||||
#include "nsIDOMWakeLock.h"
|
||||
|
||||
// JS includes
|
||||
#include "jsapi.h"
|
||||
@ -636,6 +637,8 @@ protected:
|
||||
|
||||
nsCOMPtr <nsIIdleService> mIdleService;
|
||||
|
||||
nsCOMPtr <nsIDOMMozWakeLock> mWakeLock;
|
||||
|
||||
static bool sIdleObserversAPIFuzzTimeDisabled;
|
||||
|
||||
friend class HashchangeCallback;
|
||||
|
@ -174,7 +174,26 @@ static uint32_t sCleanupsSinceLastGC = UINT32_MAX;
|
||||
static bool sNeedsFullCC = false;
|
||||
static nsJSContext *sContextList = nullptr;
|
||||
|
||||
nsScriptNameSpaceManager *gNameSpaceManager;
|
||||
static nsScriptNameSpaceManager *gNameSpaceManager;
|
||||
static nsIMemoryReporter *gReporter;
|
||||
|
||||
NS_MEMORY_REPORTER_MALLOC_SIZEOF_FUN(ScriptNameSpaceManagerMallocSizeOf,
|
||||
"script-namespace-manager")
|
||||
|
||||
static int64_t
|
||||
GetScriptNameSpaceManagerSize()
|
||||
{
|
||||
MOZ_ASSERT(gNameSpaceManager);
|
||||
return gNameSpaceManager->SizeOfIncludingThis(
|
||||
ScriptNameSpaceManagerMallocSizeOf);
|
||||
}
|
||||
|
||||
NS_MEMORY_REPORTER_IMPLEMENT(ScriptNameSpaceManager,
|
||||
"explicit/script-namespace-manager",
|
||||
KIND_HEAP,
|
||||
nsIMemoryReporter::UNITS_BYTES,
|
||||
GetScriptNameSpaceManagerSize,
|
||||
"Memory used for the script namespace manager.")
|
||||
|
||||
static nsIJSRuntimeService *sRuntimeService;
|
||||
JSRuntime *nsJSRuntime::sRuntime;
|
||||
@ -3644,6 +3663,7 @@ nsJSRuntime::Startup()
|
||||
sDisableExplicitCompartmentGC = false;
|
||||
sNeedsFullCC = false;
|
||||
gNameSpaceManager = nullptr;
|
||||
gReporter = nullptr;
|
||||
sRuntimeService = nullptr;
|
||||
sRuntime = nullptr;
|
||||
sIsInitialized = false;
|
||||
@ -3986,6 +4006,9 @@ nsJSRuntime::GetNameSpaceManager()
|
||||
|
||||
nsresult rv = gNameSpaceManager->Init();
|
||||
NS_ENSURE_SUCCESS(rv, nullptr);
|
||||
|
||||
gReporter = new NS_MEMORY_REPORTER_NAME(ScriptNameSpaceManager);
|
||||
NS_RegisterMemoryReporter(gReporter);
|
||||
}
|
||||
|
||||
return gNameSpaceManager;
|
||||
@ -4002,6 +4025,10 @@ nsJSRuntime::Shutdown()
|
||||
nsJSContext::KillInterSliceGCTimer();
|
||||
|
||||
NS_IF_RELEASE(gNameSpaceManager);
|
||||
if (gReporter) {
|
||||
(void)::NS_UnregisterMemoryReporter(gReporter);
|
||||
gReporter = nullptr;
|
||||
}
|
||||
|
||||
if (!sContextCount) {
|
||||
// We're being shutdown, and there are no more contexts
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include "nsIComponentManager.h"
|
||||
#include "nsIComponentRegistrar.h"
|
||||
#include "nsICategoryManager.h"
|
||||
#include "nsIMemoryReporter.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsXPCOM.h"
|
||||
#include "nsISupportsPrimitives.h"
|
||||
@ -37,6 +38,13 @@ public:
|
||||
// Our hash table ops don't care about the order of these members
|
||||
nsString mKey;
|
||||
nsGlobalNameStruct mGlobalName;
|
||||
|
||||
size_t SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf) {
|
||||
// Measurement of the following members may be added later if DMD finds it
|
||||
// is worthwhile:
|
||||
// - mGlobalName
|
||||
return mKey.SizeOfExcludingThisMustBeUnshared(aMallocSizeOf);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@ -793,3 +801,22 @@ nsScriptNameSpaceManager::RegisterDefineDOMInterface(const nsAFlatString& aName,
|
||||
s->mPrefEnabled = aPrefEnabled;
|
||||
}
|
||||
}
|
||||
|
||||
static size_t
|
||||
SizeOfEntryExcludingThis(PLDHashEntryHdr *aHdr, nsMallocSizeOfFun aMallocSizeOf,
|
||||
void *aArg)
|
||||
{
|
||||
GlobalNameMapEntry* entry = static_cast<GlobalNameMapEntry*>(aHdr);
|
||||
return entry->SizeOfExcludingThis(aMallocSizeOf);
|
||||
}
|
||||
|
||||
size_t
|
||||
nsScriptNameSpaceManager::SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf)
|
||||
{
|
||||
size_t n = 0;
|
||||
n += PL_DHashTableSizeOfExcludingThis(&mGlobalNames,
|
||||
SizeOfEntryExcludingThis, aMallocSizeOf);
|
||||
n += PL_DHashTableSizeOfExcludingThis(&mNavigatorNames,
|
||||
SizeOfEntryExcludingThis, aMallocSizeOf);
|
||||
return n;
|
||||
}
|
||||
|
@ -143,6 +143,8 @@ public:
|
||||
mozilla::dom::DefineInterface aDefineDOMInterface,
|
||||
mozilla::dom::PrefEnabled aPrefEnabled);
|
||||
|
||||
size_t SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf);
|
||||
|
||||
private:
|
||||
// Adds a new entry to the hash and returns the nsGlobalNameStruct
|
||||
// that aKey will be mapped to. If mType in the returned
|
||||
|
@ -3473,9 +3473,13 @@ let RIL = {
|
||||
}
|
||||
|
||||
if (!updatedDataCall) {
|
||||
currentDataCall.state = GECKO_NETWORK_STATE_DISCONNECTED;
|
||||
currentDataCall.rilMessageType = "datacallstatechange";
|
||||
this.sendDOMMessage(currentDataCall);
|
||||
// If datacalls list is coming from REQUEST_SETUP_DATA_CALL response,
|
||||
// we do not change state for any currentDataCalls not in datacalls list.
|
||||
if (!newDataCallOptions) {
|
||||
currentDataCall.state = GECKO_NETWORK_STATE_DISCONNECTED;
|
||||
currentDataCall.rilMessageType = "datacallstatechange";
|
||||
this.sendDOMMessage(currentDataCall);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -32,6 +32,7 @@
|
||||
using namespace mozilla::hal;
|
||||
|
||||
#define LOGE(args...) __android_log_print(ANDROID_LOG_ERROR, "GonkSensor" , ## args)
|
||||
#define LOGW(args...) __android_log_print(ANDROID_LOG_WARN, "GonkSensor" , ## args)
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
@ -112,11 +113,6 @@ public:
|
||||
SensorRunnable(const sensors_event_t& data, const sensor_t* sensors, ssize_t size)
|
||||
{
|
||||
mSensorData.sensor() = HardwareSensorToHalSensor(data.type);
|
||||
if (mSensorData.sensor() == SENSOR_UNKNOWN) {
|
||||
// Emulator is broken and gives us events without types set
|
||||
if (data.sensor < size)
|
||||
mSensorData.sensor() = HardwareSensorToHalSensor(sensors[data.sensor].type);
|
||||
}
|
||||
mSensorData.accuracy() = HardwareStatusToHalAccuracy(SensorseventStatus(data));
|
||||
mSensorData.timestamp() = data.timestamp;
|
||||
if (mSensorData.sensor() == SENSOR_GYROSCOPE) {
|
||||
@ -185,6 +181,20 @@ PollSensors()
|
||||
if (buffer[i].type == SENSOR_TYPE_MAGNETIC_FIELD)
|
||||
continue;
|
||||
|
||||
if (buffer[i].sensor >= size) {
|
||||
LOGW("buffer type is hal sensor type SENSOR_UNKNOWN, and buffer sensor is not in a valid range");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (HardwareSensorToHalSensor(buffer[i].type) == SENSOR_UNKNOWN) {
|
||||
// Emulator is broken and gives us events without types set
|
||||
if (HardwareSensorToHalSensor(sensors[buffer[i].sensor].type) != SENSOR_UNKNOWN) {
|
||||
buffer[i].type = sensors[buffer[i].sensor].type;
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
NS_DispatchToMainThread(new SensorRunnable(buffer[i], sensors, size));
|
||||
}
|
||||
} while (true);
|
||||
|
@ -46,7 +46,7 @@ SPSProfiler::setProfilingStack(ProfileEntry *stack, uint32_t *size, uint32_t max
|
||||
{
|
||||
JS_ASSERT_IF(size_ && *size_ != 0, !enabled());
|
||||
if (!strings.initialized())
|
||||
strings.init(max);
|
||||
strings.init();
|
||||
stack_ = stack;
|
||||
size_ = size;
|
||||
max_ = max;
|
||||
|
@ -7805,6 +7805,7 @@ DoApplyRenderingChangeToTree(nsIFrame* aFrame,
|
||||
}
|
||||
if (aChange & nsChangeHint_UpdateTransformLayer) {
|
||||
aFrame->MarkLayersActive(nsChangeHint_UpdateTransformLayer);
|
||||
aFrame->AddStateBits(NS_FRAME_TRANSFORM_CHANGED);
|
||||
// If we're not already going to do an invalidating paint, see
|
||||
// if we can get away with only updating the transform on a
|
||||
// layer for this frame, and not scheduling an invalidating
|
||||
|
@ -6984,12 +6984,10 @@ nsIFrame::FinishAndStoreOverflow(nsOverflowAreas& aOverflowAreas,
|
||||
nsRect& o = aOverflowAreas.Overflow(otype);
|
||||
o = nsDisplayTransform::TransformRect(o, this, nsPoint(0, 0), &newBounds);
|
||||
}
|
||||
if (sizeChanged) {
|
||||
if (Preserves3DChildren()) {
|
||||
ComputePreserve3DChildrenOverflow(aOverflowAreas, newBounds);
|
||||
} else if (ChildrenHavePerspective()) {
|
||||
RecomputePerspectiveChildrenOverflow(this->GetStyleContext(), &newBounds);
|
||||
}
|
||||
if ((sizeChanged || HasAnyStateBits(NS_FRAME_TRANSFORM_CHANGED)) && Preserves3DChildren()) {
|
||||
ComputePreserve3DChildrenOverflow(aOverflowAreas, newBounds);
|
||||
} else if (sizeChanged && ChildrenHavePerspective()) {
|
||||
RecomputePerspectiveChildrenOverflow(this->GetStyleContext(), &newBounds);
|
||||
}
|
||||
} else {
|
||||
Properties().Delete(nsIFrame::PreTransformOverflowAreasProperty());
|
||||
@ -6998,6 +6996,7 @@ nsIFrame::FinishAndStoreOverflow(nsOverflowAreas& aOverflowAreas,
|
||||
RecomputePerspectiveChildrenOverflow(this->GetStyleContext(), &newBounds);
|
||||
}
|
||||
}
|
||||
RemoveStateBits(NS_FRAME_TRANSFORM_CHANGED);
|
||||
|
||||
|
||||
bool anyOverflowChanged;
|
||||
|
@ -252,6 +252,10 @@ typedef uint64_t nsFrameState;
|
||||
// This bit acts as a loop flag for recursive paint server drawing.
|
||||
#define NS_FRAME_DRAWING_AS_PAINTSERVER NS_FRAME_STATE_BIT(33)
|
||||
|
||||
// Marks the frame as having a changed transform between processing
|
||||
// nsChangeHint_UpdateTransformLayer and calling FinishAndStoreOverflow.
|
||||
#define NS_FRAME_TRANSFORM_CHANGED NS_FRAME_STATE_BIT(34)
|
||||
|
||||
// Frame is a display root and the retained layer tree needs to be updated
|
||||
// at the next paint via display list construction.
|
||||
// Only meaningful for display roots, so we don't really need a global state
|
||||
|
@ -119,15 +119,22 @@ GetFrameMetrics(Layer* aLayer)
|
||||
return container ? &container->GetFrameMetrics() : NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the layer-pixel offset of aContainerFrame's content rect top-left
|
||||
* from the nearest display item reference frame (which we assume will be inducing
|
||||
* a ContainerLayer).
|
||||
*/
|
||||
static nsIntPoint
|
||||
GetRootFrameOffset(nsIFrame* aContainerFrame, nsDisplayListBuilder* aBuilder)
|
||||
GetContentRectLayerOffset(nsIFrame* aContainerFrame, nsDisplayListBuilder* aBuilder)
|
||||
{
|
||||
nscoord auPerDevPixel = aContainerFrame->PresContext()->AppUnitsPerDevPixel();
|
||||
|
||||
// Offset to the content rect in case we have borders or padding
|
||||
nsPoint frameOffset =
|
||||
(aBuilder->ToReferenceFrame(aContainerFrame->GetParent()) +
|
||||
aContainerFrame->GetContentRect().TopLeft());
|
||||
// Note that aContainerFrame could be a reference frame itself, so
|
||||
// we need to be careful here to ensure that we call ToReferenceFrame
|
||||
// on aContainerFrame and not its parent.
|
||||
nsPoint frameOffset = aBuilder->ToReferenceFrame(aContainerFrame) +
|
||||
(aContainerFrame->GetContentRect().TopLeft() - aContainerFrame->GetPosition());
|
||||
|
||||
return frameOffset.ToNearestPixels(auPerDevPixel);
|
||||
}
|
||||
@ -278,10 +285,10 @@ TransformShadowTree(nsDisplayListBuilder* aBuilder, nsFrameLoader* aFrameLoader,
|
||||
|
||||
layerTransform = viewTransform;
|
||||
if (metrics->IsRootScrollable()) {
|
||||
// Apply the root frame translation *before* we do the rest of the transforms.
|
||||
nsIntPoint rootFrameOffset = GetRootFrameOffset(aFrame, aBuilder);
|
||||
// Apply the translation *before* we do the rest of the transforms.
|
||||
nsIntPoint offset = GetContentRectLayerOffset(aFrame, aBuilder);
|
||||
shadowTransform = shadowTransform *
|
||||
gfx3DMatrix::Translation(float(rootFrameOffset.x), float(rootFrameOffset.y), 0.0);
|
||||
gfx3DMatrix::Translation(float(offset.x), float(offset.y), 0.0);
|
||||
}
|
||||
}
|
||||
|
||||
@ -660,13 +667,13 @@ RenderFrameParent::BuildLayer(nsDisplayListBuilder* aBuilder,
|
||||
}
|
||||
static_cast<RefLayer*>(layer.get())->SetReferentId(id);
|
||||
layer->SetVisibleRegion(aVisibleRect);
|
||||
nsIntPoint rootFrameOffset = GetRootFrameOffset(aFrame, aBuilder);
|
||||
nsIntPoint offset = GetContentRectLayerOffset(aFrame, aBuilder);
|
||||
// We can only have an offset if we're a child of an inactive
|
||||
// container, but our display item is LAYER_ACTIVE_FORCE which
|
||||
// forces all layers above to be active.
|
||||
MOZ_ASSERT(aContainerParameters.mOffset == nsIntPoint());
|
||||
gfx3DMatrix m =
|
||||
gfx3DMatrix::Translation(rootFrameOffset.x, rootFrameOffset.y, 0.0);
|
||||
gfx3DMatrix::Translation(offset.x, offset.y, 0.0);
|
||||
// Remote content can't be repainted by us, so we multiply down
|
||||
// the resolution that our container expects onto our container.
|
||||
m.Scale(aContainerParameters.mXScale, aContainerParameters.mYScale, 1.0);
|
||||
@ -887,7 +894,7 @@ RenderFrameParent::BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
||||
ContainerLayer* container = GetRootLayer();
|
||||
if (aBuilder->IsForEventDelivery() && container) {
|
||||
ViewTransform offset =
|
||||
ViewTransform(GetRootFrameOffset(aFrame, aBuilder), 1, 1);
|
||||
ViewTransform(GetContentRectLayerOffset(aFrame, aBuilder), 1, 1);
|
||||
BuildListForLayer(container, mFrameLoader, offset,
|
||||
aBuilder, shadowTree, aFrame);
|
||||
} else {
|
||||
|
@ -6,6 +6,7 @@ import sys
|
||||
import os
|
||||
import time
|
||||
import tempfile
|
||||
import traceback
|
||||
|
||||
# We need to know our current directory so that we can serve our test files from it.
|
||||
SCRIPT_DIRECTORY = os.path.abspath(os.path.realpath(os.path.dirname(sys.argv[0])))
|
||||
@ -443,7 +444,8 @@ def main(args):
|
||||
dm.recordLogcat()
|
||||
reftest.runTests(manifest, options, cmdlineArgs)
|
||||
except:
|
||||
print "TEST-UNEXPECTED-FAIL | | exception while running reftests"
|
||||
print "Automation Error: Exception caught while running tests"
|
||||
traceback.print_exc()
|
||||
retVal = 1
|
||||
|
||||
reftest.stopWebServer(options)
|
||||
|
@ -547,7 +547,7 @@ def main(args=sys.argv[1:]):
|
||||
|
||||
retVal = reftest.runTests(manifest, options, cmdlineArgs)
|
||||
except:
|
||||
print "TEST-UNEXPECTED-FAIL | %s | Exception caught while running tests." % sys.exc_info()[1]
|
||||
print "Automation Error: Exception caught while running tests"
|
||||
traceback.print_exc()
|
||||
reftest.stopWebServer(options)
|
||||
try:
|
||||
|
@ -29,7 +29,6 @@ import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.drawable.BitmapDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.graphics.Path;
|
||||
import android.graphics.Paint;
|
||||
@ -553,10 +552,10 @@ public class AboutHomeContent extends ScrollView
|
||||
Favicons favicons = mActivity.getFavicons();
|
||||
favicons.loadFavicon(pageUrl, iconUrl, true,
|
||||
new Favicons.OnFaviconLoadedListener() {
|
||||
public void onFaviconLoaded(String url, Drawable favicon) {
|
||||
public void onFaviconLoaded(String url, Bitmap favicon) {
|
||||
if (favicon != null) {
|
||||
ImageView icon = (ImageView) row.findViewById(R.id.addon_icon);
|
||||
icon.setImageDrawable(favicon);
|
||||
icon.setImageBitmap(favicon);
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -590,7 +589,7 @@ public class AboutHomeContent extends ScrollView
|
||||
}
|
||||
|
||||
ContentResolver resolver = mActivity.getContentResolver();
|
||||
final BitmapDrawable favicon = BrowserDB.getFaviconForUrl(resolver, url);
|
||||
final Bitmap favicon = BrowserDB.getFaviconForUrl(resolver, url);
|
||||
lastTabUrlsList.add(url);
|
||||
|
||||
AboutHomeContent.this.post(new Runnable() {
|
||||
@ -599,7 +598,7 @@ public class AboutHomeContent extends ScrollView
|
||||
((TextView) container.findViewById(R.id.last_tab_title)).setText(tab.getSelectedTitle());
|
||||
((TextView) container.findViewById(R.id.last_tab_url)).setText(tab.getSelectedUrl());
|
||||
if (favicon != null) {
|
||||
((ImageView) container.findViewById(R.id.last_tab_favicon)).setImageDrawable(favicon);
|
||||
((ImageView) container.findViewById(R.id.last_tab_favicon)).setImageBitmap(favicon);
|
||||
}
|
||||
|
||||
container.setOnClickListener(new View.OnClickListener() {
|
||||
|
@ -582,7 +582,7 @@ abstract public class BrowserApp extends GeckoApp
|
||||
long id = getFavicons().loadFavicon(tab.getURL(), tab.getFaviconURL(), !tab.isPrivate(),
|
||||
new Favicons.OnFaviconLoadedListener() {
|
||||
|
||||
public void onFaviconLoaded(String pageUrl, Drawable favicon) {
|
||||
public void onFaviconLoaded(String pageUrl, Bitmap favicon) {
|
||||
// Leave favicon UI untouched if we failed to load the image
|
||||
// for some reason.
|
||||
if (favicon == null)
|
||||
|
@ -7,6 +7,7 @@ package org.mozilla.gecko;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.drawable.AnimationDrawable;
|
||||
import android.graphics.drawable.ColorDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
@ -678,12 +679,12 @@ public class BrowserToolbar implements ViewSwitcher.ViewFactory,
|
||||
mAwesomeBar.setContentDescription(title != null ? title : mTitle.getHint());
|
||||
}
|
||||
|
||||
public void setFavicon(Drawable image) {
|
||||
public void setFavicon(Bitmap image) {
|
||||
if (Tabs.getInstance().getSelectedTab().getState() == Tab.STATE_LOADING)
|
||||
return;
|
||||
|
||||
if (image != null)
|
||||
mFavicon.setImageDrawable(image);
|
||||
mFavicon.setImageBitmap(image);
|
||||
else
|
||||
mFavicon.setImageResource(R.drawable.favicon);
|
||||
}
|
||||
|
@ -21,6 +21,7 @@ import android.database.sqlite.SQLiteDatabase;
|
||||
import android.database.sqlite.SQLiteOpenHelper;
|
||||
import android.database.sqlite.SQLiteQueryBuilder;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.graphics.drawable.BitmapDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.net.http.AndroidHttpClient;
|
||||
@ -48,12 +49,12 @@ public class Favicons {
|
||||
|
||||
private Map<Long,LoadFaviconTask> mLoadTasks;
|
||||
private long mNextFaviconLoadId;
|
||||
private LruCache<String, Drawable> mFaviconsCache;
|
||||
private LruCache<String, Bitmap> mFaviconsCache;
|
||||
private static final String USER_AGENT = GeckoApp.mAppContext.getDefaultUAString();
|
||||
private AndroidHttpClient mHttpClient;
|
||||
|
||||
public interface OnFaviconLoadedListener {
|
||||
public void onFaviconLoaded(String url, Drawable favicon);
|
||||
public void onFaviconLoaded(String url, Bitmap favicon);
|
||||
}
|
||||
|
||||
private class DatabaseHelper extends SQLiteOpenHelper {
|
||||
@ -144,11 +145,10 @@ public class Favicons {
|
||||
mNextFaviconLoadId = 0;
|
||||
|
||||
// Create a favicon memory cache that have up to 1mb of size
|
||||
mFaviconsCache = new LruCache<String, Drawable>(1024 * 1024) {
|
||||
mFaviconsCache = new LruCache<String, Bitmap>(1024 * 1024) {
|
||||
@Override
|
||||
protected int sizeOf(String url, Drawable image) {
|
||||
Bitmap bitmap = ((BitmapDrawable) image).getBitmap();
|
||||
return bitmap.getRowBytes() * bitmap.getHeight();
|
||||
protected int sizeOf(String url, Bitmap image) {
|
||||
return image.getRowBytes() * image.getHeight();
|
||||
}
|
||||
};
|
||||
}
|
||||
@ -161,7 +161,7 @@ public class Favicons {
|
||||
return mHttpClient;
|
||||
}
|
||||
|
||||
private void dispatchResult(final String pageUrl, final Drawable image,
|
||||
private void dispatchResult(final String pageUrl, final Bitmap image,
|
||||
final OnFaviconLoadedListener listener) {
|
||||
if (pageUrl != null && image != null)
|
||||
putFaviconInMemCache(pageUrl, image);
|
||||
@ -189,7 +189,7 @@ public class Favicons {
|
||||
}
|
||||
|
||||
// Check if favicon is mem cached
|
||||
Drawable image = getFaviconFromMemCache(pageUrl);
|
||||
Bitmap image = getFaviconFromMemCache(pageUrl);
|
||||
if (image != null) {
|
||||
dispatchResult(pageUrl, image, listener);
|
||||
return -1;
|
||||
@ -205,11 +205,11 @@ public class Favicons {
|
||||
return taskId;
|
||||
}
|
||||
|
||||
public Drawable getFaviconFromMemCache(String pageUrl) {
|
||||
public Bitmap getFaviconFromMemCache(String pageUrl) {
|
||||
return mFaviconsCache.get(pageUrl);
|
||||
}
|
||||
|
||||
public void putFaviconInMemCache(String pageUrl, Drawable image) {
|
||||
public void putFaviconInMemCache(String pageUrl, Bitmap image) {
|
||||
mFaviconsCache.put(pageUrl, image);
|
||||
}
|
||||
|
||||
@ -254,7 +254,7 @@ public class Favicons {
|
||||
mHttpClient.close();
|
||||
}
|
||||
|
||||
private class LoadFaviconTask extends AsyncTask<Void, Void, BitmapDrawable> {
|
||||
private class LoadFaviconTask extends AsyncTask<Void, Void, Bitmap> {
|
||||
private long mId;
|
||||
private String mPageUrl;
|
||||
private String mFaviconUrl;
|
||||
@ -274,15 +274,13 @@ public class Favicons {
|
||||
}
|
||||
|
||||
// Runs in background thread
|
||||
private BitmapDrawable loadFaviconFromDb() {
|
||||
private Bitmap loadFaviconFromDb() {
|
||||
ContentResolver resolver = mContext.getContentResolver();
|
||||
BitmapDrawable favicon = BrowserDB.getFaviconForUrl(resolver, mPageUrl);
|
||||
|
||||
return favicon;
|
||||
return BrowserDB.getFaviconForUrl(resolver, mPageUrl);
|
||||
}
|
||||
|
||||
// Runs in background thread
|
||||
private void saveFaviconToDb(BitmapDrawable favicon) {
|
||||
private void saveFaviconToDb(Bitmap favicon) {
|
||||
if (!mPersist) {
|
||||
return;
|
||||
}
|
||||
@ -298,9 +296,10 @@ public class Favicons {
|
||||
}
|
||||
|
||||
// Runs in background thread
|
||||
private BitmapDrawable downloadFavicon(URL faviconUrl) {
|
||||
private Bitmap downloadFavicon(URL faviconUrl) {
|
||||
if (mFaviconUrl.startsWith("jar:jar:")) {
|
||||
return GeckoJarReader.getBitmapDrawable(mContext.getResources(), mFaviconUrl);
|
||||
BitmapDrawable d = GeckoJarReader.getBitmapDrawable(mContext.getResources(), mFaviconUrl);
|
||||
return d.getBitmap();
|
||||
}
|
||||
|
||||
URI uri;
|
||||
@ -318,13 +317,13 @@ public class Favicons {
|
||||
|
||||
// skia decoder sometimes returns null; workaround is to use BufferedHttpEntity
|
||||
// http://groups.google.com/group/android-developers/browse_thread/thread/171b8bf35dbbed96/c3ec5f45436ceec8?lnk=raot
|
||||
BitmapDrawable image = null;
|
||||
Bitmap image = null;
|
||||
try {
|
||||
HttpGet request = new HttpGet(faviconUrl.toURI());
|
||||
HttpEntity entity = getHttpClient().execute(request).getEntity();
|
||||
BufferedHttpEntity bufferedEntity = new BufferedHttpEntity(entity);
|
||||
InputStream contentStream = bufferedEntity.getContent();
|
||||
image = (BitmapDrawable) Drawable.createFromStream(contentStream, "src");
|
||||
image = BitmapFactory.decodeStream(contentStream);
|
||||
} catch (Exception e) {
|
||||
Log.e(LOGTAG, "Error reading favicon", e);
|
||||
}
|
||||
@ -333,8 +332,8 @@ public class Favicons {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected BitmapDrawable doInBackground(Void... unused) {
|
||||
BitmapDrawable image = null;
|
||||
protected Bitmap doInBackground(Void... unused) {
|
||||
Bitmap image = null;
|
||||
|
||||
if (isCancelled())
|
||||
return null;
|
||||
@ -382,7 +381,7 @@ public class Favicons {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(final BitmapDrawable image) {
|
||||
protected void onPostExecute(final Bitmap image) {
|
||||
mLoadTasks.remove(mId);
|
||||
dispatchResult(mPageUrl, image, mListener);
|
||||
}
|
||||
|
@ -46,7 +46,6 @@ import android.graphics.BitmapFactory;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.PointF;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.drawable.BitmapDrawable;
|
||||
import android.hardware.Sensor;
|
||||
import android.hardware.SensorEvent;
|
||||
import android.hardware.SensorEventListener;
|
||||
@ -2746,9 +2745,9 @@ abstract public class GeckoApp
|
||||
if (tab != null) {
|
||||
String url = tab.getURL();
|
||||
String title = tab.getDisplayTitle();
|
||||
BitmapDrawable favicon = (BitmapDrawable)(tab.getFavicon());
|
||||
Bitmap favicon = tab.getFavicon();
|
||||
if (url != null && title != null) {
|
||||
GeckoAppShell.createShortcut(title, url, url, favicon == null ? null : favicon.getBitmap(), "");
|
||||
GeckoAppShell.createShortcut(title, url, url, favicon == null ? null : favicon, "");
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
@ -41,7 +41,7 @@ public class Tab {
|
||||
private long mLastUsed;
|
||||
private String mUrl;
|
||||
private String mTitle;
|
||||
private Drawable mFavicon;
|
||||
private Bitmap mFavicon;
|
||||
private String mFaviconUrl;
|
||||
private int mFaviconSize;
|
||||
private JSONObject mIdentityData;
|
||||
@ -147,7 +147,7 @@ public class Tab {
|
||||
return mUrl;
|
||||
}
|
||||
|
||||
public Drawable getFavicon() {
|
||||
public Bitmap getFavicon() {
|
||||
return mFavicon;
|
||||
}
|
||||
|
||||
@ -325,7 +325,7 @@ public class Tab {
|
||||
return mFaviconLoadId;
|
||||
}
|
||||
|
||||
public void updateFavicon(Drawable favicon) {
|
||||
public void updateFavicon(Bitmap favicon) {
|
||||
mFavicon = favicon;
|
||||
}
|
||||
|
||||
|
@ -22,7 +22,6 @@ import android.content.Context;
|
||||
import android.database.Cursor;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.graphics.drawable.BitmapDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Handler;
|
||||
@ -54,6 +53,7 @@ import android.widget.TabHost.TabContentFactory;
|
||||
import android.widget.TextView;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@ -265,9 +265,19 @@ public class AllPagesTab extends AwesomeBarTab implements GeckoEventListener {
|
||||
if (keywordCol != -1)
|
||||
keyword = mCursor.getString(keywordCol);
|
||||
|
||||
return new ContextMenuSubject(id,
|
||||
mCursor.getString(mCursor.getColumnIndexOrThrow(URLColumns.URL)),
|
||||
mCursor.getBlob(mCursor.getColumnIndexOrThrow(URLColumns.FAVICON)),
|
||||
final String url = mCursor.getString(mCursor.getColumnIndexOrThrow(URLColumns.URL));
|
||||
|
||||
Favicons favicons = GeckoApp.mAppContext.getFavicons();
|
||||
Bitmap bitmap = favicons.getFaviconFromMemCache(url);
|
||||
byte[] favicon = null;
|
||||
|
||||
if (bitmap != null) {
|
||||
ByteArrayOutputStream stream = new ByteArrayOutputStream();
|
||||
bitmap.compress(Bitmap.CompressFormat.PNG, 100, stream);
|
||||
favicon = stream.toByteArray();
|
||||
}
|
||||
|
||||
return new ContextMenuSubject(id, url, favicon,
|
||||
mCursor.getString(mCursor.getColumnIndexOrThrow(URLColumns.TITLE)),
|
||||
keyword,
|
||||
mCursor.getInt(mCursor.getColumnIndexOrThrow(Combined.DISPLAY)));
|
||||
@ -770,8 +780,7 @@ public class AllPagesTab extends AwesomeBarTab implements GeckoEventListener {
|
||||
if (favicon == null)
|
||||
continue;
|
||||
|
||||
Drawable faviconDrawable = new BitmapDrawable(getResources(), favicon);
|
||||
favicons.putFaviconInMemCache(url, faviconDrawable);
|
||||
favicons.putFaviconInMemCache(url, favicon);
|
||||
} while (c.moveToNext());
|
||||
} finally {
|
||||
if (c != null)
|
||||
@ -801,7 +810,7 @@ public class AllPagesTab extends AwesomeBarTab implements GeckoEventListener {
|
||||
private void displayFavicon(AwesomeEntryViewHolder viewHolder) {
|
||||
final String url = viewHolder.urlView.getText().toString();
|
||||
Favicons favicons = GeckoApp.mAppContext.getFavicons();
|
||||
viewHolder.faviconView.setImageDrawable(favicons.getFaviconFromMemCache(url));
|
||||
viewHolder.faviconView.setImageBitmap(favicons.getFaviconFromMemCache(url));
|
||||
}
|
||||
|
||||
private void updateFavicons() {
|
||||
|
@ -10,6 +10,7 @@ import org.mozilla.gecko.db.BrowserContract.ExpirePriority;
|
||||
import android.content.ContentResolver;
|
||||
import android.database.ContentObserver;
|
||||
import android.database.Cursor;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.drawable.BitmapDrawable;
|
||||
|
||||
import java.util.List;
|
||||
@ -73,11 +74,11 @@ public class BrowserDB {
|
||||
|
||||
public void removeReadingListItemWithURL(ContentResolver cr, String uri);
|
||||
|
||||
public BitmapDrawable getFaviconForUrl(ContentResolver cr, String uri);
|
||||
public Bitmap getFaviconForUrl(ContentResolver cr, String uri);
|
||||
|
||||
public Cursor getFaviconsForUrls(ContentResolver cr, List<String> urls);
|
||||
|
||||
public void updateFaviconForUrl(ContentResolver cr, String uri, BitmapDrawable favicon);
|
||||
public void updateFaviconForUrl(ContentResolver cr, String uri, Bitmap favicon);
|
||||
|
||||
public void updateThumbnailForUrl(ContentResolver cr, String uri, BitmapDrawable thumbnail);
|
||||
|
||||
@ -190,7 +191,7 @@ public class BrowserDB {
|
||||
sDb.removeReadingListItemWithURL(cr, uri);
|
||||
}
|
||||
|
||||
public static BitmapDrawable getFaviconForUrl(ContentResolver cr, String uri) {
|
||||
public static Bitmap getFaviconForUrl(ContentResolver cr, String uri) {
|
||||
return sDb.getFaviconForUrl(cr, uri);
|
||||
}
|
||||
|
||||
@ -198,7 +199,7 @@ public class BrowserDB {
|
||||
return sDb.getFaviconsForUrls(cr, urls);
|
||||
}
|
||||
|
||||
public static void updateFaviconForUrl(ContentResolver cr, String uri, BitmapDrawable favicon) {
|
||||
public static void updateFaviconForUrl(ContentResolver cr, String uri, Bitmap favicon) {
|
||||
sDb.updateFaviconForUrl(cr, uri, favicon);
|
||||
}
|
||||
|
||||
|
@ -626,7 +626,7 @@ public class LocalBrowserDB implements BrowserDB.BrowserDBIface {
|
||||
new String[] { String.valueOf(id) });
|
||||
}
|
||||
|
||||
public BitmapDrawable getFaviconForUrl(ContentResolver cr, String uri) {
|
||||
public Bitmap getFaviconForUrl(ContentResolver cr, String uri) {
|
||||
Cursor c = cr.query(mImagesUriWithProfile,
|
||||
new String[] { Images.FAVICON },
|
||||
Images.URL + " = ?",
|
||||
@ -646,8 +646,7 @@ public class LocalBrowserDB implements BrowserDB.BrowserDBIface {
|
||||
if (b == null)
|
||||
return null;
|
||||
|
||||
Bitmap bitmap = BitmapFactory.decodeByteArray(b, 0, b.length);
|
||||
return new BitmapDrawable(bitmap);
|
||||
return BitmapFactory.decodeByteArray(b, 0, b.length);
|
||||
}
|
||||
|
||||
public Cursor getFaviconsForUrls(ContentResolver cr, List<String> urls) {
|
||||
@ -672,13 +671,9 @@ public class LocalBrowserDB implements BrowserDB.BrowserDBIface {
|
||||
}
|
||||
|
||||
public void updateFaviconForUrl(ContentResolver cr, String uri,
|
||||
BitmapDrawable favicon) {
|
||||
Bitmap bitmap = favicon.getBitmap();
|
||||
if (bitmap == null)
|
||||
return;
|
||||
|
||||
Bitmap favicon) {
|
||||
ByteArrayOutputStream stream = new ByteArrayOutputStream();
|
||||
bitmap.compress(Bitmap.CompressFormat.PNG, 100, stream);
|
||||
favicon.compress(Bitmap.CompressFormat.PNG, 100, stream);
|
||||
|
||||
ContentValues values = new ContentValues();
|
||||
values.put(Images.FAVICON, stream.toByteArray());
|
||||
|
@ -79,7 +79,7 @@ interface nsISAXXMLReader : nsIStreamListener {
|
||||
attribute nsISAXLexicalHandler lexicalHandler;
|
||||
|
||||
/**
|
||||
* Set the value of a feature flag. NOT CURRENTLY IMPLEMENTED.
|
||||
* Set the value of a feature flag.
|
||||
*
|
||||
* The feature name is any fully-qualified URI. It is possible
|
||||
* for an XMLReader to expose a feature value but to be unable to
|
||||
@ -93,11 +93,15 @@ interface nsISAXXMLReader : nsIStreamListener {
|
||||
*
|
||||
* @param name String flag for a parser feature.
|
||||
* @param value Turn the feature on/off.
|
||||
*
|
||||
* @note This is currently supported only for
|
||||
* http://xml.org/sax/features/namespace-prefixes . All other
|
||||
* features will result in a NOT_IMPLEMENTED exception.
|
||||
*/
|
||||
void setFeature(in AString name, in boolean value);
|
||||
|
||||
/**
|
||||
* Look up the value of a feature flag. NOT CURRENTLY IMPLEMENTED.
|
||||
* Look up the value of a feature flag.
|
||||
*
|
||||
* The feature name is any fully-qualified URI. It is
|
||||
* possible for an XMLReader to recognize a feature name but
|
||||
@ -110,6 +114,10 @@ interface nsISAXXMLReader : nsIStreamListener {
|
||||
* http://xml.org/sax/features/namespace-prefixes feature names.
|
||||
*
|
||||
* @param name String flag for a parser feature.
|
||||
*
|
||||
* @note This is currently supported only for
|
||||
* http://xml.org/sax/features/namespace-prefixes . All other
|
||||
* features will result in a NOT_IMPLEMENTED exception.
|
||||
*/
|
||||
boolean getFeature(in AString name);
|
||||
|
||||
|
@ -52,7 +52,9 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsSAXXMLReader)
|
||||
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsISAXXMLReader)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
nsSAXXMLReader::nsSAXXMLReader() : mIsAsyncParse(false)
|
||||
nsSAXXMLReader::nsSAXXMLReader() :
|
||||
mIsAsyncParse(false),
|
||||
mEnableNamespacePrefixes(false)
|
||||
{
|
||||
}
|
||||
|
||||
@ -101,7 +103,7 @@ nsSAXXMLReader::HandleStartElement(const PRUnichar *aName,
|
||||
// XXX don't have attr type information
|
||||
NS_NAMED_LITERAL_STRING(cdataType, "CDATA");
|
||||
// could support xmlns reporting, it's a standard SAX feature
|
||||
if (!uri.EqualsLiteral(XMLNS_URI)) {
|
||||
if (mEnableNamespacePrefixes || !uri.EqualsLiteral(XMLNS_URI)) {
|
||||
NS_ASSERTION(aAtts[1], "null passed to handler");
|
||||
atts->AddAttribute(uri, localName, qName, cdataType,
|
||||
nsDependentString(aAtts[1]));
|
||||
@ -397,12 +399,20 @@ nsSAXXMLReader::SetErrorHandler(nsISAXErrorHandler *aErrorHandler)
|
||||
NS_IMETHODIMP
|
||||
nsSAXXMLReader::SetFeature(const nsAString &aName, bool aValue)
|
||||
{
|
||||
if (aName.EqualsLiteral("http://xml.org/sax/features/namespace-prefixes")) {
|
||||
mEnableNamespacePrefixes = aValue;
|
||||
return NS_OK;
|
||||
}
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSAXXMLReader::GetFeature(const nsAString &aName, bool *aResult)
|
||||
{
|
||||
if (aName.EqualsLiteral("http://xml.org/sax/features/namespace-prefixes")) {
|
||||
*aResult = mEnableNamespacePrefixes;
|
||||
return NS_OK;
|
||||
}
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
|
@ -94,6 +94,9 @@ private:
|
||||
nsString &aQName);
|
||||
nsString mPublicId;
|
||||
nsString mSystemId;
|
||||
|
||||
// Feature flags
|
||||
bool mEnableNamespacePrefixes;
|
||||
};
|
||||
|
||||
#endif // nsSAXXMLReader_h__
|
||||
|
52
parser/xml/test/unit/test_namespace_support.js
Normal file
52
parser/xml/test/unit/test_namespace_support.js
Normal file
@ -0,0 +1,52 @@
|
||||
function noop() {}
|
||||
|
||||
function run_test() {
|
||||
var contentHandler = {
|
||||
attrs: null,
|
||||
reset: function() {
|
||||
this.attrs = [];
|
||||
},
|
||||
startDocument: noop,
|
||||
endDocument: noop,
|
||||
|
||||
startElement: function startElement(aNamespaceURI, aLocalName, aNodeName, aAttrs) {
|
||||
for (var i = 0; i < aAttrs.length; i++)
|
||||
this.attrs.push(aAttrs.getQName(i));
|
||||
},
|
||||
|
||||
endElement: noop,
|
||||
characters: noop,
|
||||
processingInstruction: noop,
|
||||
ignorableWhitespace: noop,
|
||||
startPrefixMapping: noop,
|
||||
endPrefixMapping: noop
|
||||
};
|
||||
|
||||
const nsISAXXMLReader = Components.interfaces.nsISAXXMLReader;
|
||||
const src = "<a:x xmlns:a='foo' y='bar'/>";
|
||||
const NS_PREFIX = "http://xml.org/sax/features/namespace-prefixes";
|
||||
|
||||
var saxReader = Components.classes["@mozilla.org/saxparser/xmlreader;1"]
|
||||
.createInstance(nsISAXXMLReader);
|
||||
do_check_false(saxReader.getFeature(NS_PREFIX));
|
||||
saxReader.contentHandler = contentHandler;
|
||||
contentHandler.reset();
|
||||
saxReader.parseFromString(src, "application/xml");
|
||||
do_check_eq(contentHandler.attrs.length, 1);
|
||||
do_check_eq(contentHandler.attrs[0], "y");
|
||||
|
||||
saxReader.setFeature(NS_PREFIX, true);
|
||||
do_check_true(saxReader.getFeature(NS_PREFIX));
|
||||
contentHandler.reset();
|
||||
saxReader.parseFromString(src, "application/xml");
|
||||
do_check_eq(contentHandler.attrs.length, 2);
|
||||
do_check_eq(contentHandler.attrs[0], "xmlns:a");
|
||||
do_check_eq(contentHandler.attrs[1], "y");
|
||||
|
||||
saxReader.setFeature(NS_PREFIX, false);
|
||||
do_check_false(saxReader.getFeature(NS_PREFIX));
|
||||
contentHandler.reset();
|
||||
saxReader.parseFromString(src, "application/xml");
|
||||
do_check_eq(contentHandler.attrs.length, 1);
|
||||
do_check_eq(contentHandler.attrs[0], "y");
|
||||
}
|
@ -3,3 +3,4 @@ head =
|
||||
tail =
|
||||
|
||||
[test_parser.js]
|
||||
[test_namespace_support.js]
|
||||
|
@ -1,5 +1,6 @@
|
||||
{
|
||||
"runtests": {
|
||||
"dom/base": "",
|
||||
"dom/tests/mochitest/dom-level0": "",
|
||||
"dom/tests/mochitest/dom-level1-core": "",
|
||||
"dom/tests/mochitest/dom-level2-core": "",
|
||||
|
@ -488,7 +488,7 @@ def main():
|
||||
mochitest.cleanup(None, options)
|
||||
retVal = mochitest.runTests(options)
|
||||
except:
|
||||
print "TEST-UNEXPECTED-FAIL | %s | Exception caught while running tests." % sys.exc_info()[1]
|
||||
print "Automation Error: Exception caught while running tests"
|
||||
traceback.print_exc()
|
||||
mochitest.stopWebServer(options)
|
||||
mochitest.stopWebSocketServer(options)
|
||||
|
@ -7,6 +7,7 @@ import os
|
||||
import time
|
||||
import tempfile
|
||||
import re
|
||||
import traceback
|
||||
|
||||
sys.path.insert(0, os.path.abspath(os.path.realpath(os.path.dirname(sys.argv[0]))))
|
||||
|
||||
@ -498,7 +499,8 @@ def main():
|
||||
retVal = mochitest.runTests(options)
|
||||
mochitest.addLogData()
|
||||
except:
|
||||
print "TEST-UNEXPECTED-FAIL | %s | Exception caught while running robocop tests." % sys.exc_info()[1]
|
||||
print "Automation Error: Exception caught while running tests"
|
||||
traceback.print_exc()
|
||||
mochitest.stopWebServer(options)
|
||||
mochitest.stopWebSocketServer(options)
|
||||
try:
|
||||
@ -521,7 +523,8 @@ def main():
|
||||
dm.recordLogcat()
|
||||
retVal = mochitest.runTests(options)
|
||||
except:
|
||||
print "TEST-UNEXPECTED-FAIL | %s | Exception caught while running tests." % sys.exc_info()[1]
|
||||
print "Automation Error: Exception caught while running tests"
|
||||
traceback.print_exc()
|
||||
mochitest.stopWebServer(options)
|
||||
mochitest.stopWebSocketServer(options)
|
||||
try:
|
||||
|
@ -154,7 +154,7 @@ def main():
|
||||
try:
|
||||
success = xpcsh.runTests(xpcshell='xpcshell', testdirs=args[0:], **options.__dict__)
|
||||
except:
|
||||
print "TEST-UNEXPECTED-FAIL | %s | Exception caught while running tests." % sys.exc_info()[1]
|
||||
print "Automation Error: Exception caught while running tests"
|
||||
traceback.print_exc()
|
||||
sys.exit(1)
|
||||
|
||||
|
@ -103,6 +103,9 @@ using mozilla::scache::StartupCache;
|
||||
#include "nsIWinAppHelper.h"
|
||||
#include <windows.h>
|
||||
#include "cairo/cairo-features.h"
|
||||
#ifdef MOZ_METRO
|
||||
#include <roapi.h>
|
||||
#endif
|
||||
|
||||
#ifndef PROCESS_DEP_ENABLE
|
||||
#define PROCESS_DEP_ENABLE 0x1
|
||||
@ -3958,13 +3961,149 @@ XREMain::XRE_main(int argc, char* argv[], const nsXREAppData* aAppData)
|
||||
return NS_FAILED(rv) ? 1 : 0;
|
||||
}
|
||||
|
||||
#if defined(MOZ_METRO) && defined(XP_WIN)
|
||||
extern bool XRE_MetroCoreApplicationRun();
|
||||
static XREMain* xreMainPtr;
|
||||
|
||||
// must be called by the thread we want as the main thread
|
||||
nsresult
|
||||
XRE_metroStartup()
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
bool exit = false;
|
||||
if (xreMainPtr->XRE_mainStartup(&exit) != 0 || exit)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
// Start the real application
|
||||
xreMainPtr->mScopedXPCom = new ScopedXPCOMStartup();
|
||||
if (!xreMainPtr->mScopedXPCom)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
rv = xreMainPtr->mScopedXPCom->Initialize();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = xreMainPtr->XRE_mainRun();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
XRE_metroShutdown()
|
||||
{
|
||||
delete xreMainPtr->mScopedXPCom;
|
||||
xreMainPtr->mScopedXPCom = nullptr;
|
||||
|
||||
#ifdef MOZ_INSTRUMENT_EVENT_LOOP
|
||||
mozilla::ShutdownEventTracing();
|
||||
#endif
|
||||
|
||||
// unlock the profile after ScopedXPCOMStartup object (xpcom)
|
||||
// has gone out of scope. see bug #386739 for more details
|
||||
xreMainPtr->mProfileLock->Unlock();
|
||||
gProfileLock = nullptr;
|
||||
|
||||
#ifdef MOZ_CRASHREPORTER
|
||||
if (xreMainPtr->mAppData->flags & NS_XRE_ENABLE_CRASH_REPORTER)
|
||||
CrashReporter::UnsetExceptionHandler();
|
||||
#endif
|
||||
|
||||
XRE_DeinitCommandLine();
|
||||
}
|
||||
|
||||
class WinRTInitWrapper
|
||||
{
|
||||
public:
|
||||
WinRTInitWrapper() {
|
||||
mResult = ::RoInitialize(RO_INIT_MULTITHREADED);
|
||||
}
|
||||
~WinRTInitWrapper() {
|
||||
if (SUCCEEDED(mResult)) {
|
||||
::RoUninitialize();
|
||||
}
|
||||
}
|
||||
HRESULT mResult;
|
||||
};
|
||||
|
||||
int
|
||||
XRE_mainMetro(int argc, char* argv[], const nsXREAppData* aAppData)
|
||||
{
|
||||
SAMPLER_INIT();
|
||||
SAMPLE_LABEL("Startup", "XRE_Main");
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
xreMainPtr = new XREMain();
|
||||
if (!xreMainPtr) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Inits Winrt and COM underneath it.
|
||||
WinRTInitWrapper wrap;
|
||||
|
||||
gArgc = argc;
|
||||
gArgv = argv;
|
||||
|
||||
NS_ENSURE_TRUE(aAppData, 2);
|
||||
|
||||
xreMainPtr->mAppData = new ScopedAppData(aAppData);
|
||||
if (!xreMainPtr->mAppData)
|
||||
return 1;
|
||||
// used throughout this file
|
||||
gAppData = xreMainPtr->mAppData;
|
||||
|
||||
ScopedLogging log;
|
||||
|
||||
// init
|
||||
bool exit = false;
|
||||
if (xreMainPtr->XRE_mainInit(aAppData, &exit) != 0 || exit)
|
||||
return 1;
|
||||
|
||||
// Located in widget, will call back into XRE_metroStartup and
|
||||
// XRE_metroShutdown above.
|
||||
if (!XRE_MetroCoreApplicationRun()) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// XRE_metroShutdown should have already been called on the worker
|
||||
// thread that called XRE_metroStartup.
|
||||
NS_ASSERTION(!xreMainPtr->mScopedXPCom,
|
||||
"XPCOM Shutdown hasn't occured, and we are exiting.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
void SetWindowsEnvironment(WindowsEnvironmentType aEnvID);
|
||||
#endif // MOZ_METRO || !defined(XP_WIN)
|
||||
|
||||
int
|
||||
XRE_main(int argc, char* argv[], const nsXREAppData* aAppData, uint32_t aFlags)
|
||||
{
|
||||
#if !defined(MOZ_METRO) || !defined(XP_WIN)
|
||||
XREMain main;
|
||||
int result = main.XRE_main(argc, argv, aAppData);
|
||||
mozilla::RecordShutdownEndTimeStamp();
|
||||
return result;
|
||||
#else
|
||||
if (aFlags == XRE_MAIN_FLAG_USE_METRO) {
|
||||
SetWindowsEnvironment(WindowsEnvironmentType_Metro);
|
||||
}
|
||||
|
||||
// Desktop
|
||||
if (XRE_GetWindowsEnvironment() == WindowsEnvironmentType_Desktop) {
|
||||
XREMain main;
|
||||
int result = main.XRE_main(argc, argv, aAppData);
|
||||
mozilla::RecordShutdownEndTimeStamp();
|
||||
return result;
|
||||
}
|
||||
|
||||
// Metro
|
||||
NS_ASSERTION(XRE_GetWindowsEnvironment() == WindowsEnvironmentType_Metro,
|
||||
"Unknown Windows environment");
|
||||
|
||||
int result = XRE_mainMetro(argc, argv, aAppData);
|
||||
mozilla::RecordShutdownEndTimeStamp();
|
||||
return result;
|
||||
#endif // MOZ_METRO || !defined(XP_WIN)
|
||||
}
|
||||
|
||||
nsresult
|
||||
|
Loading…
Reference in New Issue
Block a user