Merge cedar into mozilla-central

This commit is contained in:
Ehsan Akhgari 2011-04-08 11:05:22 -07:00
commit ac600720a8
29 changed files with 603 additions and 85 deletions

View File

@ -3,7 +3,7 @@
-moz-padding-end: 0;
padding-bottom: 10px;
-moz-padding-start: 0;
width: 600px;
width: 620px;
}
#clientBox {
@ -58,10 +58,6 @@
-moz-padding-start: 0;
}
#updateBox {
margin-bottom: 10px;
}
#updateButton,
#updateDeck > hbox > label {
-moz-margin-start: 0;
@ -99,3 +95,36 @@
color: #999999;
margin-top: 10px;
}
#currentChannel {
margin: 0;
padding: 0;
font-weight: bold;
}
#channelSelector {
margin-top: 10px;
}
#channelMenulist {
margin: 0;
}
.channel-description {
margin: 10px 0;
text-align: center;
}
#detailsBox,
#channelSelector,
.channel-description {
-moz-transition: opacity 250ms;
}
#contentDeck:not([selectedIndex="0"]) > #detailsBox,
#contentDeck:not([selectedIndex="1"]) > #channelSelector,
#channelDescriptionDeck:not([selectedIndex="0"]) > #releaseDescription,
#channelDescriptionDeck:not([selectedIndex="1"]) > #betaDescription,
#channelDescriptionDeck:not([selectedIndex="2"]) > #auroraDescription {
opacity: 0;
}

View File

@ -88,6 +88,8 @@ function init(aEvent)
gAppUpdater = new appUpdater();
#endif
gChannelSelector.init();
#ifdef XP_MACOSX
// it may not be sized at this point, and we need its width to calculate its position
window.sizeToContent();
@ -572,3 +574,68 @@ appUpdater.prototype =
}
};
#endif
var gChannelSelector = {
validChannels: { release: 1, beta: 1, aurora: 1 },
init: function() {
try {
this.channelValue = Services.prefs.getCharPref("app.update.desiredChannel");
} catch (e) {
let defaults = Services.prefs.getDefaultBranch("");
this.channelValue = defaults.getCharPref("app.update.channel");
}
// Only show channel selector UI on valid update channels.
if (this.channelValue in this.validChannels) {
document.getElementById("currentChannelText").hidden = false;
this.setChannelLabel(this.channelValue);
this.setChannelMenuitem(this.channelValue);
}
},
selectChannel: function(aSelectedItem) {
document.getElementById("channelDescriptionDeck").selectedPanel =
document.getElementById(aSelectedItem.value + "Description");
},
cancel: function() {
this.setChannelMenuitem(this.channelValue);
this.hide();
},
apply: function() {
this.channelValue = document.getElementById("channelMenulist").selectedItem.value;
this.setChannelLabel(this.channelValue);
// Change app update channel.
Services.prefs.setCharPref("app.update.desiredChannel", this.channelValue);
// App updater will look at app.update.desiredChannel for new channel value
// and will clear it when the update is complete.
gAppUpdater.isChecking = true;
gAppUpdater.checker.checkForUpdates(gAppUpdater.updateCheckListener, true);
this.hide();
},
show: function() {
document.getElementById("contentDeck").selectedPanel =
document.getElementById("channelSelector");
},
hide: function() {
document.getElementById("contentDeck").selectedPanel =
document.getElementById("detailsBox");
},
setChannelLabel: function(aValue) {
let channelLabel = document.getElementById("currentChannel");
channelLabel.value = document.getElementById(aValue + "Menuitem").label;
},
setChannelMenuitem: function(aValue) {
document.getElementById("channelMenulist").selectedItem =
document.getElementById(aValue + "Menuitem");
}
}

View File

@ -77,44 +77,81 @@
#expand <label id="version" value="__MOZ_APP_VERSION__"/>
<label id="distribution" class="text-blurb"/>
<label id="distributionId" class="text-blurb"/>
<vbox id="updateBox">
<!-- Make sure the selectedIndex attribute is always set so that the CSS
selectors for transitions work -->
<deck id="contentDeck" selectedIndex="0">
<vbox id="detailsBox">
<vbox id="updateBox">
#ifdef MOZ_UPDATER
<deck id="updateDeck" orient="vertical">
<hbox id="updateButtonBox" align="center">
<button id="updateButton" align="start"
oncommand="gAppUpdater.buttonOnCommand();"/>
<spacer flex="1"/>
</hbox>
<hbox id="checkingForUpdates" align="center">
<image class="update-throbber"/><label>&update.checkingForUpdates;</label>
</hbox>
<hbox id="checkingAddonCompat" align="center">
<image class="update-throbber"/><label>&update.checkingAddonCompat;</label>
</hbox>
<hbox id="downloading" align="center">
<image class="update-throbber"/><label>&update.downloading.start;</label><label id="downloadStatus"/><label>&update.downloading.end;</label>
</hbox>
<hbox id="downloadFailed" align="center">
<label>&update.failed.start;</label><label id="failedLink" class="text-link">&update.failed.linkText;</label><label>&update.failed.end;</label>
</hbox>
<hbox id="adminDisabled" align="center">
<label>&update.adminDisabled;</label>
</hbox>
<hbox id="noUpdatesFound" align="center">
<label>&update.noUpdatesFound;</label>
</hbox>
<hbox id="manualUpdate" align="center">
<label>&update.manual.start;</label><label id="manualLink" class="text-link"/><label>&update.manual.end;</label>
</hbox>
</deck>
<deck id="updateDeck" orient="vertical">
<hbox id="updateButtonBox" align="center">
<button id="updateButton" align="start"
oncommand="gAppUpdater.buttonOnCommand();"/>
<spacer flex="1"/>
</hbox>
<hbox id="checkingForUpdates" align="center">
<image class="update-throbber"/><label>&update.checkingForUpdates;</label>
</hbox>
<hbox id="checkingAddonCompat" align="center">
<image class="update-throbber"/><label>&update.checkingAddonCompat;</label>
</hbox>
<hbox id="downloading" align="center">
<image class="update-throbber"/><label>&update.downloading.start;</label><label id="downloadStatus"/><label>&update.downloading.end;</label>
</hbox>
<hbox id="downloadFailed" align="center">
<label>&update.failed.start;</label><label id="failedLink" class="text-link">&update.failed.linkText;</label><label>&update.failed.end;</label>
</hbox>
<hbox id="adminDisabled" align="center">
<label>&update.adminDisabled;</label>
</hbox>
<hbox id="noUpdatesFound" align="center">
<label>&update.noUpdatesFound;</label>
</hbox>
<hbox id="manualUpdate" align="center">
<label>&update.manual.start;</label><label id="manualLink" class="text-link"/><label>&update.manual.end;</label>
</hbox>
</deck>
#endif
</vbox>
<description class="text-blurb">
&community.start2;<label class="text-link" href="http://www.mozilla.org/">&community.mozillaLink;</label>&community.middle2;<label class="text-link" href="about:credits">&community.creditsLink;</label>&community.end2;
</description>
<description class="text-blurb">
&contribute.start;<label class="text-link" href="http://www.mozilla.org/contribute/">&contribute.getInvolvedLink;</label>&contribute.end;
</description>
</vbox>
<description class="text-blurb" id="currentChannelText" hidden="true">
&channel.description.start;<label id="currentChannel"/>&channel.description.end;<label id="channelChangeLink" class="text-link" onclick="gChannelSelector.show();">&channel.change;</label>
</description>
<description class="text-blurb">
&community.start2;<label class="text-link" href="http://www.mozilla.org/">&community.mozillaLink;</label>&community.middle2;<label class="text-link" href="about:credits">&community.creditsLink;</label>&community.end2;
</description>
<description class="text-blurb">
&contribute.start;<label class="text-link" href="http://www.mozilla.org/contribute/">&contribute.getInvolvedLink;</label>&contribute.end;
</description>
</vbox>
<vbox id="channelSelector">
<hbox pack="center" align="center">
<label>&channel.selector.start;</label>
<menulist id="channelMenulist" onselect="gChannelSelector.selectChannel(this.selectedItem);">
<menupopup>
<menuitem id="releaseMenuitem" label="Release" value="release"/>
<menuitem id="betaMenuitem" label="Beta" value="beta"/>
<menuseparator/>
<menuitem id="auroraMenuitem" label="Aurora" value="aurora"/>
</menupopup>
</menulist>
<label>&channel.selector.end;</label>
</hbox>
<deck id="channelDescriptionDeck" selectedIndex="0">
<description id="releaseDescription" class="channel-description">&channel.release.description;</description>
<description id="betaDescription" class="channel-description">&channel.beta.description;</description>
<description id="auroraDescription" class="channel-description">&channel.aurora.description;</description>
</deck>
<hbox id="channelSelectorButtons" pack="center">
<button oncommand="gChannelSelector.apply();" label="&channel.selector.applyButton;"/>
<button oncommand="gChannelSelector.cancel();" label="&channel.selector.cancelButton;"/>
</hbox>
</vbox>
</deck>
</vbox>
</hbox>
<vbox id="bottomBox">

View File

@ -54,3 +54,27 @@
example: Downloading update 111 KB of 13 MB -->
<!ENTITY update.downloading.start "Downloading update — ">
<!ENTITY update.downloading.end "">
<!-- LOCALIZATION NOTE (channel.description.start,channel.description.end): channel.description.start and
channel.description.end create one sentence, with the current channel label inserted in between.
example: You are currently on the _Stable_ update channel. -->
<!ENTITY channel.description.start "You are currently on the ">
<!ENTITY channel.description.end " update channel. ">
<!ENTITY channel.change "Change">
<!ENTITY channel.release.description "Enjoy the tried and tested final release being used by hundreds of millions around the world. Stay in control of your online experience with super speed, easy customization and the latest Web technologies.">
<!ENTITY channel.beta.description "Experience cutting edge features with more stability. Provide feedback to help refine and polish what will be in the final release.">
<!ENTITY channel.aurora.description "Experience the newest innovations in an unstable environment that's not for the faint of heart. Provide feedback on features and performance to help determine what makes the final release.">
<!-- LOCALIZATION NOTE (channel.selector.start,channel.selector.end): channel.selector.start and
channel.selector.end create one sentence, with a channel selection menulist instered in between.
This is all in one line, so try to make the localized text short.
example: Switch to the [Stable] update channel. -->
<!ENTITY channel.selector.start "Switch to the">
<!ENTITY channel.selector.end "update channel.">
<!-- LOCALIZATION NOTE (channel.selector.applyButton): This button applies the user's choice to switch
to a new update channel and starts the application update process. -->
<!ENTITY channel.selector.applyButton "Apply and Update">
<!ENTITY channel.selector.cancelButton "Cancel">

View File

@ -59,6 +59,8 @@ import android.widget.*;
import android.hardware.*;
import android.location.*;
import android.webkit.MimeTypeMap;
import android.media.MediaScannerConnection;
import android.media.MediaScannerConnection.MediaScannerConnectionClient;
import android.util.*;
import android.net.Uri;
@ -119,6 +121,31 @@ public class GeckoAppShell
}
}
private static class GeckoMediaScannerClient implements MediaScannerConnectionClient {
private String mFile = "";
private String mMimeType = "";
private MediaScannerConnection mScanner = null;
public GeckoMediaScannerClient(Context aContext, String aFile, String aMimeType) {
mFile = aFile;
mMimeType = aMimeType;
mScanner = new MediaScannerConnection(aContext, this);
if (mScanner != null)
mScanner.connect();
}
public void onMediaScannerConnected() {
mScanner.scanFile(mFile, mMimeType);
}
public void onScanCompleted(String path, Uri uri) {
if(path.equals(mFile)) {
mScanner.disconnect();
mScanner = null;
}
}
}
// Get a Handler for the main java thread
public static Handler getMainHandler() {
return GeckoApp.mAppContext.mMainHandler;
@ -1065,4 +1092,9 @@ public class GeckoAppShell
} catch (InterruptedException ie) {}
}
}
public static void scanMedia(String aFile, String aMimeType) {
Context context = GeckoApp.surfaceView.getContext();
GeckoMediaScannerClient client = new GeckoMediaScannerClient(context, aFile, aMimeType);
}
}

View File

@ -172,9 +172,6 @@ gfxSurfaceDrawable::Draw(gfxContext* aContext,
PreparePatternForUntiledDrawing(pattern, deviceSpaceToImageSpace,
surfaceType, currentTarget, filter);
}
#ifdef MOZ_GFX_OPTIMIZE_MOBILE
pattern->SetFilter(gfxPattern::FILTER_FAST);
#endif
pattern->SetMatrix(gfxMatrix(aTransform).Multiply(mTransform));
aContext->NewPath();
aContext->SetPattern(pattern);

View File

@ -3030,11 +3030,7 @@ nsLayoutUtils::GetClosestLayer(nsIFrame* aFrame)
GraphicsFilter
nsLayoutUtils::GetGraphicsFilterForFrame(nsIFrame* aForFrame)
{
#ifdef MOZ_GFX_OPTIMIZE_MOBILE
GraphicsFilter defaultFilter = gfxPattern::FILTER_NEAREST;
#else
GraphicsFilter defaultFilter = gfxPattern::FILTER_GOOD;
#endif
#ifdef MOZ_SVG
nsIFrame *frame = nsCSSRendering::IsCanvasFrame(aForFrame) ?
nsCSSRendering::FindBackgroundStyleFrame(aForFrame) : aForFrame;

View File

@ -873,7 +873,7 @@ public:
return (aCoord.GetUnit() == eStyleUnit_Coord &&
aCoord.GetCoordValue() == 0) ||
(aCoord.GetUnit() == eStyleUnit_Percent &&
aCoord.GetPercentValue() == 0.0) ||
aCoord.GetPercentValue() == 0.0f) ||
(aCoord.IsCalcUnit() &&
// clamp negative calc() to 0
nsRuleNode::ComputeCoordPercentCalc(aCoord, nscoord_MAX) <= 0 &&
@ -885,7 +885,7 @@ public:
return (aCoord.GetUnit() == eStyleUnit_Coord &&
aCoord.GetCoordValue() == 0) ||
(aCoord.GetUnit() == eStyleUnit_Percent &&
aCoord.GetPercentValue() == 0.0) ||
aCoord.GetPercentValue() == 0.0f) ||
(aCoord.IsCalcUnit() &&
nsRuleNode::ComputeCoordPercentCalc(aCoord, nscoord_MAX) == 0 &&
nsRuleNode::ComputeCoordPercentCalc(aCoord, 0) == 0);

View File

@ -4,10 +4,39 @@ var AppMenu = {
return this.panel = document.getElementById("appmenu");
},
shouldShow: function appmenu_shouldShow(aElement) {
return !aElement.hidden;
},
overflowMenu : [],
show: function show() {
if (BrowserUI.activePanel || BrowserUI.isPanelVisible())
return;
this.panel.setAttribute("count", this.panel.childNodes.length);
let shown = 0;
let lastShown = null;
this.overflowMenu = [];
let childrenCount = this.panel.childElementCount;
for (let i = 0; i < childrenCount; i++) {
if (this.shouldShow(this.panel.children[i])) {
if (shown == 6 && this.overflowMenu.length == 0) {
// if we are trying to show more than 6 elements fall back to showing a more button
lastShown.removeAttribute("show");
this.overflowMenu.push(lastShown);
this.panel.appendChild(this.createMoreButton());
}
if (this.overflowMenu.length > 0) {
this.overflowMenu.push(this.panel.children[i]);
} else {
lastShown = this.panel.children[i];
lastShown.setAttribute("show", shown);
shown++;
}
}
}
this.panel.setAttribute("count", shown);
this.panel.hidden = false;
addEventListener("keypress", this, true);
@ -18,6 +47,14 @@ var AppMenu = {
hide: function hide() {
this.panel.hidden = true;
let moreButton = document.getElementById("appmenu-more-button");
if (moreButton)
moreButton.parentNode.removeChild(moreButton);
for (let i = 0; i < this.panel.childElementCount; i++) {
if (this.panel.children[i].hasAttribute("show"))
this.panel.children[i].removeAttribute("show");
}
removeEventListener("keypress", this, true);
@ -31,5 +68,36 @@ var AppMenu = {
handleEvent: function handleEvent(aEvent) {
this.hide();
},
showAsList: function showAsList() {
// allow menu to hide to remove the more button before we show the menulist
setTimeout((function() {
this.menu.menupopup.children = this.overflowMenu;
MenuListHelperUI.show(this.menu);
}).bind(this), 0)
},
menu : {
id: "appmenu-menulist",
dispatchEvent: function(aEvent) {
let menuitem = AppMenu.overflowMenu[this.selectedIndex];
if (menuitem)
menuitem.click();
},
menupopup: {
hasAttribute: function(aAttr) { return false; }
},
selectedIndex: -1
},
createMoreButton: function() {
let button = document.createElement("toolbarbutton");
button.setAttribute("id", "appmenu-more-button");
button.setAttribute("class", "appmenu-button");
button.setAttribute("label", Strings.browser.GetStringFromName("appMenu.more"));
button.setAttribute("show", 6);
button.setAttribute("oncommand", "AppMenu.showAsList();");
return button;
}
};

View File

@ -674,21 +674,17 @@
</hbox>
<hbox id="appmenu" bottom="0" hidden="true" align="stretch" oncommand="AppMenu.hide();">
<toolbarbutton class="appmenu-button"
<toolbarbutton class="appmenu-site-button appmenu-button"
label="&appMenu.siteOptions;"
image="chrome://browser/skin/images/appmenu-site-hdpi.png"
oncommand="getIdentityHandler().show(); event.stopPropagation();"/>
<toolbarbutton class="appmenu-button"
<toolbarbutton class="appmenu-preferences-button appmenu-button"
label="&prefsHeader.label;"
image="chrome://browser/skin/images/appmenu-preferences-hdpi.png"
oncommand="BrowserUI.showPanel('prefs-container');"/>
<toolbarbutton class="appmenu-button"
<toolbarbutton class="appmenu-addons-button appmenu-button"
label="&addonsHeader.label;"
image="chrome://browser/skin/images/appmenu-addons-hdpi.png"
oncommand="BrowserUI.showPanel('addons-container');"/>
<toolbarbutton class="appmenu-button"
<toolbarbutton class="appmenu-downloads-button appmenu-button"
label="&downloadsHeader.label;"
image="chrome://browser/skin/images/appmenu-downloads-hdpi.png"
oncommand="BrowserUI.showPanel('downloads-container');"/>
</hbox>
</stack>

View File

@ -353,3 +353,10 @@ input > .anonymous-div:after {
margin: 16px;
}
/*
* Enforce nearest scaling for video in order not to lose too much performance
* after fixing bug 598736 ("Use higher-quality imageinterpolation on mobile")
*/
video {
image-rendering: -moz-crisp-edges;
}

View File

@ -546,6 +546,7 @@ var ExtensionsView = {
appendSearchResults: function(aAddons, aShowRating, aShowCount) {
let urlproperties = [ "iconURL", "homepageURL" ];
let foundItem = false;
let appendedAddons = 0;
for (let i = 0; i < aAddons.length; i++) {
let addon = aAddons[i];
@ -563,6 +564,7 @@ var ExtensionsView = {
continue;
}
appendedAddons++;
// Convert the numeric type to a string
let types = {"2":"extension", "4":"theme", "8":"locale"};
addon.type = types[addon.type];
@ -584,6 +586,7 @@ var ExtensionsView = {
if (aShowCount < 0)
item.hidden = true;
}
return appendedAddons;
},
showMoreSearchResults: function showMoreSearchResults() {
@ -652,15 +655,16 @@ var ExtensionsView = {
// We only show extra browse add-ons if the recommended count is small. Otherwise, the user
// can see more by pressing the "Show More" button
this.appendSearchResults(aRecommendedAddons, false, aRecommendedAddons.length);
this.appendSearchResults(aBrowseAddons, true, (aRecommendedAddons.length >= kAddonPageSize ? 0 : kAddonPageSize));
let minOverflow = (aRecommendedAddons.length >= kAddonPageSize ? 0 : kAddonPageSize);
let numAdded = this.appendSearchResults(aBrowseAddons, true, minOverflow);
let totalAddons = aRecommendedAddons.length + aBrowseAddons.length;
let totalAddons = aRecommendedAddons.length + numAdded;
let showmore = document.createElement("richlistitem");
showmore.setAttribute("typeName", "showmore");
showmore.setAttribute("pagelabel", strings.GetStringFromName("addonsBrowseAll.seeMore"));
showmore.setAttribute("onpagecommand", "ExtensionsView.showMoreSearchResults();");
showmore.setAttribute("hidepage", totalAddons > kAddonPageSize ? "false" : "true");
showmore.setAttribute("hidepage", numAdded > minOverflow ? "false" : "true");
showmore.setAttribute("sitelabel", strings.GetStringFromName("addonsBrowseAll.browseSite"));
showmore.setAttribute("onsitecommand", "ExtensionsView.showMoreResults('" + browseURL + "');");
this.addItem(showmore, "repo");

View File

@ -54,6 +54,7 @@ _BROWSER_FILES = \
remote_formsZoom.js \
remote_vkb.js \
browser_addons.js \
browser_appmenu.js \
browser_autocomplete.html \
browser_autocomplete.js \
browser_autocompletesearch.js\

View File

@ -0,0 +1,123 @@
let gTests = [];
let gCurrentTest = null;
let Panels = [AllPagesList, HistoryList, BookmarkList];
function test() {
waitForExplicitFinish();
setTimeout(runNextTest, 200);
}
//------------------------------------------------------------------------------
// Iterating tests by shifting test out one by one as runNextTest is called.
function runNextTest() {
// Run the next test until all tests completed
if (gTests.length > 0) {
gCurrentTest = gTests.shift();
info(gCurrentTest.desc);
gCurrentTest.run();
} else {
// Close the awesome panel just in case
BrowserUI.activePanel = null;
finish();
}
}
gTests.push({
// This test will keep adding buttons and checking the result until there are a
// total of 9 buttons, then it will (one at a time) hide 3 items and check the
// result again.
desc: "Test for showing the application menu",
newButtons: [],
hidden: 0,
run: function() {
addEventListener("PopupChanged", gCurrentTest.popupOpened, false)
CommandUpdater.doCommand("cmd_menu");
},
addButton: function() {
info("Adding a new button\n");
let menu = document.getElementById("appmenu");
let newButton = menu.children[0].cloneNode(true);
menu.appendChild(newButton);
gCurrentTest.newButtons.push(newButton);
},
popupOpened: function() {
removeEventListener("PopupChanged", gCurrentTest.popupOpened, false);
let menu = document.getElementById("appmenu");
ok(!document.getElementById("appmenu").hidden, "App menu is shown");
let more = document.getElementById("appmenu-more-button");
if (menu.children.length > 6) {
ok(!!more, "More button is shown");
addEventListener("PopupChanged", gCurrentTest.moreShown, false);
more.click();
} else {
ok(!more, "More button is hidden");
addEventListener("PopupChanged", gCurrentTest.popupClosed, false);
EventUtils.synthesizeKey("VK_ESCAPE", {}, window);
}
},
popupClosed: function() {
removeEventListener("PopupChanged", gCurrentTest.popupClosed, false);
let menu = document.getElementById("appmenu");
ok(document.getElementById("appmenu").hidden, "Esc hides menus");
if (menu.children.length < 9) {
gCurrentTest.addButton();
gCurrentTest.run();
} else {
menu.children[gCurrentTest.hidden].hidden = true;
gCurrentTest.hidden++;
addEventListener("PopupChanged", gCurrentTest.menuitemHidden, false)
CommandUpdater.doCommand("cmd_menu");
}
},
moreShown: function(aEvent) {
// AppMenu hiding
if (!aEvent.detail)
return;
let menu = document.getElementById("appmenu");
ok(document.getElementById("appmenu").hidden, "Clicking more button hides menu");
removeEventListener("PopupChanged", gCurrentTest.moreShown, false);
let listbox = document.getElementById("menulist-popup").lastChild;
is(listbox.childNodes.length, (menu.childNodes.length - 5), "Menu popup only shows overflow children");
addEventListener("PopupChanged", gCurrentTest.popupClosed, false);
EventUtils.synthesizeKey("VK_ESCAPE", {}, window);
},
menuitemHidden: function() {
removeEventListener("PopupChanged", gCurrentTest.menuitemHidden, false);
let menu = document.getElementById("appmenu");
ok(!document.getElementById("appmenu").hidden, "App menu is shown");
let more = document.getElementById("appmenu-more-button");
if (menu.children.length - gCurrentTest.hidden > 6) {
ok(more, "More button is shown");
addEventListener("PopupChanged", gCurrentTest.popupClosed, false);
} else {
ok(!more, "More button is hidden");
addEventListener("PopupChanged", gCurrentTest.popupClosedAgain, false);
}
EventUtils.synthesizeKey("VK_ESCAPE", {}, window);
},
popupClosedAgain: function() {
removeEventListener("PopupChanged", gCurrentTest.popupClosedAgain, false)
let menu = document.getElementById("appmenu");
while (gCurrentTest.hidden > -1) {
gCurrentTest.hidden--;
menu.children[gCurrentTest.hidden] = false;
}
gCurrentTest.newButtons.forEach(function(aButton) {
menu.removeChild(aButton);
})
runNextTest();
}
});

View File

@ -223,3 +223,6 @@ browser.menu.showCharacterEncoding=false
# LOCALIZATION NOTE (intl.charsetmenu.browser.static): Set to a series of comma separated
# values for charsets that the user can select from in the Character Encoding menu.
intl.charsetmenu.browser.static=iso-8859-1,utf-8,x-gbk,big5,iso-2022-jp,shift_jis,euc-jp
#Application Menu
appMenu.more=More

View File

@ -1327,7 +1327,7 @@ pageaction:not([image]) > hbox >.pageaction-image {
border-width: @border_width_large@ @border_width_large@ 0 @border_width_large@;
}
.appmenu-button {
#appmenu > .appmenu-button {
-moz-box-flex: 1;
-moz-box-orient: vertical;
border-style: solid;
@ -1335,9 +1335,14 @@ pageaction:not([image]) > hbox >.pageaction-image {
border-width: 0 @border_width_tiny@ @border_width_tiny@ 0;
height: @appmenu_button_height@;
width: 0;
display: none;
}
.appmenu-button:hover:active {
#appmenu > .appmenu-button[show] {
display: inline-block;
}
#appmenu > .appmenu-button:hover:active {
background-image: url("chrome://browser/skin/images/appmenu-active-hdpi.png");
background-size: 100% 100%;
}
@ -1352,6 +1357,31 @@ pageaction:not([image]) > hbox >.pageaction-image {
margin-bottom: @margin_small@ !important;
}
richlistitem.appmenu-site-button > image,
.appmenu-site-button {
list-style-image: url("chrome://browser/skin/images/appmenu-site-hdpi.png");
}
richlistitem.appmenu-addons-button > image,
.appmenu-addons-button {
list-style-image: url("chrome://browser/skin/images/appmenu-addons-hdpi.png");
}
richlistitem.appmenu-preferences-button > image,
.appmenu-preferences-button {
list-style-image: url("chrome://browser/skin/images/appmenu-preferences-hdpi.png");
}
richlistitem.appmenu-downloads-button > image,
.appmenu-downloads-button {
list-style-image: url("chrome://browser/skin/images/appmenu-downloads-hdpi.png");
}
#appmenu-more-button {
list-style-image: url("chrome://browser/skin/images/appmenu-site-hdpi.png");
display: none;
}
@media (@orientation@: portrait) {
#appmenu:not([hidden])[count="4"],
#appmenu:not([hidden])[count="5"],
@ -1364,10 +1394,10 @@ pageaction:not([image]) > hbox >.pageaction-image {
#appmenu[count="5"] > .appmenu-button {
width: 50%;
}
#appmenu[count="5"] > .appmenu-button:nth-child(3),
#appmenu[count="5"] > .appmenu-button:nth-child(4),
#appmenu[count="5"] > .appmenu-button:nth-child(5),
#appmenu[count="5"] > .appmenu-button[show="2"],
#appmenu[count="5"] > .appmenu-button[show="3"],
#appmenu[count="5"] > .appmenu-button[show="4"],
#appmenu[count="6"] > .appmenu-button {
width: 33.33%;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

View File

@ -20,6 +20,7 @@ chrome.jar:
skin/images/appmenu-addons-hdpi.png (images/appmenu-addons-hdpi.png)
skin/images/appmenu-active-hdpi.png (images/appmenu-active-hdpi.png)
skin/images/appmenu-downloads-hdpi.png (images/appmenu-downloads-hdpi.png)
skin/images/appmenu-more-hdpi.png (images/appmenu-more-hdpi.png)
skin/images/appmenu-preferences-hdpi.png (images/appmenu-preferences-hdpi.png)
skin/images/appmenu-site-hdpi.png (images/appmenu-site-hdpi.png)
skin/images/aboutBackground.jpg (images/aboutBackground.jpg)

View File

@ -1978,8 +1978,10 @@ HUD_SERVICE.prototype =
{
// Pipe the message to createMessageNode().
let hud = HUDService.hudReferences[aHUDId];
let mappedArguments = Array.map(aArguments, hud.jsterm.formatResult,
hud.jsterm);
function formatResult(x) {
return (typeof(x) == "string") ? x : hud.jsterm.formatResult(x);
}
let mappedArguments = Array.map(aArguments, formatResult);
let joinedArguments = Array.join(mappedArguments, " ");
let node = ConsoleUtils.createMessageNode(hud.outputNode.ownerDocument,
CATEGORY_WEBDEV,

View File

@ -17,7 +17,7 @@ let dateNow = Date.now();
let inputValues = [
// [showsPropertyPanel?, input value, expected output format,
// print() output, optional console API test]
// print() output, console output, optional console API test]
// 0
[false, "'hello \\nfrom \\rthe \\\"string world!'",
@ -59,17 +59,20 @@ let inputValues = [
// 11
[false, "document.getElementById", "function getElementById() {[native code]}",
"function getElementById() {\n [native code]\n}",
"function getElementById() {[native code]}",
"document.wrappedJSObject.getElementById"],
// 12
[false, "function() { return 42; }", "function () {return 42;}",
"function () {\n return 42;\n}"],
"function () {\n return 42;\n}",
"(function () {return 42;})"],
// 13
[false, "new Date(" + dateNow + ")", (new Date(dateNow)).toString()],
// 14
[true, "document.body", "[object HTMLBodyElement", "[object HTMLBodyElement",
"[object HTMLBodyElement",
"document.wrappedJSObject.body"],
// 15
@ -77,11 +80,13 @@ let inputValues = [
// 16
[true, "[1,2,3,'a','b','c','4','5']", '[1, 2, 3, "a", "b", "c", "4", "5"]',
'1,2,3,a,b,c,4,5'],
'1,2,3,a,b,c,4,5',
'[1, 2, 3, "a", "b", "c", "4", "5"]'],
// 17
[true, "({a:'b', c:'d', e:1, f:'2'})", '({a:"b", c:"d", e:1, f:"2"})',
"[object Object"],
"[object Object",
'({a:"b", c:"d", e:1, f:"2"})'],
];
let eventHandlers = [];
@ -116,7 +121,10 @@ function testNext() {
let printOutput = inputValues[cpos].length >= 4 ?
inputValues[cpos][3] : expectedOutput;
let consoleTest = inputValues[cpos][4] || inputValue;
let consoleOutput = inputValues[cpos].length >= 5 ?
inputValues[cpos][4] : printOutput;
let consoleTest = inputValues[cpos][5] || inputValue;
HUD.jsterm.clearOutput();
@ -129,7 +137,7 @@ function testNext() {
querySelector(".hud-log:last-child");
ok(outputItem,
"found the window.console output line for inputValues[" + cpos + "]");
ok(outputItem.textContent.indexOf(expectedOutput) > -1,
ok(outputItem.textContent.indexOf(consoleOutput) > -1,
"console API output is correct for inputValues[" + cpos + "]");
HUD.jsterm.clearOutput();

View File

@ -102,7 +102,7 @@ function testConsoleLoggingAPI(aMethod) {
console[aMethod]("foo", "bar");
let node = outputNode.querySelector(".hud-msg-node");
ok(/"foo" "bar"/.test(node.textContent),
ok(/foo bar/.test(node.textContent),
"Emitted both console arguments");
}

View File

@ -69,7 +69,7 @@ function testOutputOrder() {
/console\.log\('foo', 'bar'\);/.test(nodes[0].textContent);
let outputSecond =
/"foo" "bar"/.test(nodes[1].textContent);
/foo bar/.test(nodes[1].textContent);
ok(executedStringFirst && outputSecond, "executed string comes first");

View File

@ -80,6 +80,10 @@
#include <CoreFoundation/CoreFoundation.h>
#endif
#ifdef ANDROID
#include "AndroidBridge.h"
#endif
#define DOWNLOAD_MANAGER_BUNDLE "chrome://mozapps/locale/downloads/downloads.properties"
#define DOWNLOAD_MANAGER_ALERT_ICON "chrome://mozapps/skin/downloads/downloadIcon.png"
#define PREF_BDM_SHOWALERTONCOMPLETE "browser.download.manager.showAlertOnComplete"
@ -2239,7 +2243,7 @@ nsDownload::SetState(DownloadState aState)
}
}
#if (defined(XP_WIN) && !defined(WINCE)) || defined(XP_MACOSX)
#if (defined(XP_WIN) && !defined(WINCE)) || defined(XP_MACOSX) || defined(ANDROID)
nsCOMPtr<nsIFileURL> fileURL = do_QueryInterface(mTarget);
nsCOMPtr<nsIFile> file;
nsAutoString path;
@ -2272,6 +2276,16 @@ nsDownload::SetState(DownloadState aState)
::CFNotificationCenterPostNotification(center, CFSTR("com.apple.DownloadFileFinished"),
observedObject, NULL, TRUE);
::CFRelease(observedObject);
#endif
#ifdef ANDROID
nsCOMPtr<nsIMIMEInfo> mimeInfo;
nsCAutoString contentType;
GetMIMEInfo(getter_AddRefs(mimeInfo));
if (mimeInfo)
mimeInfo->GetMIMEType(contentType);
mozilla::AndroidBridge::Bridge()->ScanMedia(path, contentType);
#endif
}

View File

@ -51,6 +51,7 @@ var gIoService = Components.classes["@mozilla.org/network/io-service;1"]
function createInstallTrigger(window) {
let chromeObject = {
window: window,
url: window.document.documentURIObject,
__exposedProps__: {
SKIN: "r",
@ -76,7 +77,7 @@ function createInstallTrigger(window) {
*/
enabled: function() {
return sendSyncMessage(MSG_INSTALL_ENABLED, {
mimetype: "application/x-xpinstall", referer: this.window.location.href
mimetype: "application/x-xpinstall", referer: this.url.spec
})[0];
},
@ -97,7 +98,7 @@ function createInstallTrigger(window) {
var params = {
installerId: this.installerId,
mimetype: "application/x-xpinstall",
referer: this.window.location.href,
referer: this.url.spec,
uris: [],
hashes: [],
names: [],
@ -163,8 +164,7 @@ function createInstallTrigger(window) {
* @return A resolved, absolute nsURI object.
*/
resolveURL: function(aUrl) {
return gIoService.newURI(aUrl, null,
this.window.document.documentURIObject);
return gIoService.newURI(aUrl, null, this.url);
},
/**
@ -175,7 +175,7 @@ function createInstallTrigger(window) {
checkLoadURIFromScript: function(aUri) {
var secman = Cc["@mozilla.org/scriptsecuritymanager;1"].
getService(Ci.nsIScriptSecurityManager);
var principal = this.window.content.document.nodePrincipal;
var principal = this.window.document.nodePrincipal;
try {
secman.checkLoadURIWithPrincipal(principal, aUri,
Ci.nsIScriptSecurityManager.DISALLOW_INHERIT_PRINCIPAL);
@ -242,7 +242,7 @@ InstallTriggerManager.prototype = {
// alive for as long as the tab is alive).
delete window.wrappedJSObject.InstallTrigger;
var installTrigger = createInstallTrigger(window.wrappedJSObject);
var installTrigger = createInstallTrigger(window);
window.wrappedJSObject.InstallTrigger = installTrigger;
return installTrigger;
});

View File

@ -97,6 +97,7 @@ _BROWSER_FILES = head.js \
browser_badargs2.js \
browser_bug611242.js \
browser_bug638292.js \
browser_bug645699.js \
unsigned.xpi \
signed.xpi \
signed2.xpi \
@ -121,6 +122,7 @@ _BROWSER_FILES = head.js \
hashRedirect.sjs \
bug540558.html \
bug638292.html \
bug645699.html \
redirect.sjs \
$(NULL)

View File

@ -0,0 +1,36 @@
// ----------------------------------------------------------------------------
// Tests installing an unsigned add-on through an InstallTrigger call in web
// content. This should be blocked by the whitelist check.
// This verifies bug 645699
function test() {
Harness.installConfirmCallback = confirm_install;
Harness.installBlockedCallback = allow_blocked;
Harness.installsCompletedCallback = finish_test;
Harness.setup();
var pm = Services.perms;
pm.add(makeURI("http://example.org/"), "install", pm.ALLOW_ACTION);
gBrowser.selectedTab = gBrowser.addTab();
gBrowser.loadURI(TESTROOT + "bug645699.html");
}
function allow_blocked(installInfo) {
is(installInfo.originatingWindow, gBrowser.contentWindow, "Install should have been triggered by the right window");
is(installInfo.originatingURI.spec, gBrowser.currentURI.spec, "Install should have been triggered by the right uri");
return false;
}
function confirm_install(window) {
ok(false, "Should not see the install dialog");
return false;
}
function finish_test(count) {
is(count, 0, "0 Add-ons should have been successfully installed");
Services.perms.remove("addons.mozilla.org", "install");
gBrowser.removeCurrentTab();
Harness.finish();
}
// ----------------------------------------------------------------------------

View File

@ -0,0 +1,24 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<title>InstallTrigger tests</title>
<script type="text/javascript">
function startInstall() {
var whiteUrl = "https://example.org/";
Object.defineProperty(window, "location", { value : { href : whiteUrl } });
Object.defineProperty(document, "documentURIObject", { spec : { href : whiteUrl } });
InstallTrigger.install({
"Unsigned XPI": "http://example.com/browser/toolkit/mozapps/extensions/test/xpinstall/unsigned.xpi"
});
}
</script>
</head>
<body onload="startInstall()">
<p>InstallTrigger tests</p>
</body>
</html>

View File

@ -134,6 +134,7 @@ AndroidBridge::Init(JNIEnv *jEnv,
jIsNetworkLinkUp = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "isNetworkLinkUp", "()Z");
jIsNetworkLinkKnown = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "isNetworkLinkKnown", "()Z");
jSetSelectedLocale = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "setSelectedLocale", "(Ljava/lang/String;)V");
jScanMedia = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "scanMedia", "(Ljava/lang/String;Ljava/lang/String;)V");
jEGLContextClass = (jclass) jEnv->NewGlobalRef(jEnv->FindClass("javax/microedition/khronos/egl/EGLContext"));
jEGL10Class = (jclass) jEnv->NewGlobalRef(jEnv->FindClass("javax/microedition/khronos/egl/EGL10"));
@ -784,3 +785,16 @@ jclass GetGeckoAppShellClass()
{
return mozilla::AndroidBridge::GetGeckoAppShellClass();
}
void
AndroidBridge::ScanMedia(const nsAString& aFile, const nsACString& aMimeType)
{
jstring jstrFile = mJNIEnv->NewString(nsPromiseFlatString(aFile).get(), aFile.Length());
nsString mimeType2;
CopyUTF8toUTF16(aMimeType, mimeType2);
jstring jstrMimeTypes = mJNIEnv->NewString(nsPromiseFlatString(mimeType2).get(), mimeType2.Length());
mJNIEnv->CallStaticVoidMethod(mGeckoAppShellClass, jScanMedia, jstrFile, jstrMimeTypes);
}

View File

@ -224,6 +224,8 @@ public:
void SetKeepScreenOn(bool on);
void ScanMedia(const nsAString& aFile, const nsACString& aMimeType);
protected:
static AndroidBridge *sBridge;
@ -278,6 +280,7 @@ protected:
jmethodID jIsNetworkLinkUp;
jmethodID jIsNetworkLinkKnown;
jmethodID jSetSelectedLocale;
jmethodID jScanMedia;
// stuff we need for CallEglCreateWindowSurface
jclass jEGLSurfaceImplClass;