зеркало из https://github.com/mozilla/gecko-dev.git
Merge mozilla-central to mozilla-inbound
This commit is contained in:
Коммит
eea585ebbc
|
@ -12,7 +12,7 @@
|
|||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="6586d2b8b43c6997be5cf5895bbdf3dd20490725"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="e314d089d988f0eb1bef2404858c60b734dc4130"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9b6626eddbc85873eaa2a9174a9bd5101e5c05f"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="eda08beb3ba9a159843c70ffde0f9660ec351eb9"/>
|
||||
|
@ -96,6 +96,6 @@
|
|||
<project name="platform/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" revision="d2685281e2e54ca14d1df304867aa82c37b27162"/>
|
||||
<project name="platform/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" revision="627f9b20fc518937b93747a7ff1ed4f5ed46e06f"/>
|
||||
<project name="platform/prebuilts/tools" path="prebuilts/tools" revision="a3daa50e9b5db558696951ae724f913e4e5c7489"/>
|
||||
<project name="platform_prebuilts_qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="83dbccadb19d0d3c07828c2bb0e5c2be12c0f980"/>
|
||||
<project name="platform_prebuilts_qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="11663426672fcc46e2a0f29239afa736b90635ba"/>
|
||||
<project name="android-sdk" path="sdk" remote="b2g" revision="5701d3cb45c2e848cc57003cda2e1141288ecae4"/>
|
||||
</manifest>
|
||||
|
|
|
@ -6,12 +6,12 @@
|
|||
<remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
|
||||
<remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
|
||||
<!-- B2G specific things. -->
|
||||
<project name="platform_build" path="build" remote="b2g" revision="fce1a137746dbd354bca1918f02f96d51c40bad2">
|
||||
<project name="platform_build" path="build" remote="b2g" revision="317f25e0a4cb3e8e86e2b76c37a14081372f0307">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="6586d2b8b43c6997be5cf5895bbdf3dd20490725"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="e314d089d988f0eb1bef2404858c60b734dc4130"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9b6626eddbc85873eaa2a9174a9bd5101e5c05f"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="96d2d00165f4561fbde62d1062706eab74b3a01f"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="a887bfabaed83c4588b40c845535c0388c8da0f3"/>
|
||||
|
@ -106,7 +106,7 @@
|
|||
<project name="platform/ndk" path="ndk" revision="7666b97bbaf1d645cdd6b4430a367b7a2bb53369"/>
|
||||
<project name="platform/prebuilts/misc" path="prebuilts/misc" revision="f6ab40b3257abc07741188fd173ac392575cc8d2"/>
|
||||
<project name="platform/prebuilts/ndk" path="prebuilts/ndk" revision="e52099755d0bd3a579130eefe8e58066cc6c0cb6"/>
|
||||
<project name="platform/prebuilts/qemu-kernel" path="prebuilts/qemu-kernel" revision="42011ad6bfec9978f9a297cf4a754af67b7c478a"/>
|
||||
<project name="platform_prebuilts_qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="11663426672fcc46e2a0f29239afa736b90635ba"/>
|
||||
<project name="platform/prebuilts/sdk" path="prebuilts/sdk" revision="842e33e43a55ea44833b9e23e4d180fa17c843af"/>
|
||||
<project name="platform/prebuilts/tools" path="prebuilts/tools" revision="5db24726f0f42124304195a6bdea129039eeeaeb"/>
|
||||
<project name="platform/system/bluetooth" path="system/bluetooth" revision="930ae098543881f47eac054677726ee4b998b2f8"/>
|
||||
|
@ -119,10 +119,12 @@
|
|||
<default remote="caf" revision="refs/tags/android-4.3_r2.1" sync-j="4"/>
|
||||
<!-- Emulator specific things -->
|
||||
<project name="device/generic/armv7-a-neon" path="device/generic/armv7-a-neon" revision="3a9a17613cc685aa232432566ad6cc607eab4ec1"/>
|
||||
<project name="device_generic_goldfish" path="device/generic/goldfish" remote="b2g" revision="9e1ff573f5669a9e0756e199cb4237ab18546388"/>
|
||||
<project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="87e1478ffc36b0b446119ae0a1ea7a02e1baea5e"/>
|
||||
<project name="device_generic_goldfish" path="device/generic/goldfish" remote="b2g" revision="09485b73629856b21b2ed6073e327ab0e69a1189"/>
|
||||
<project name="platform/external/libnfc-nci" path="external/libnfc-nci" revision="7d33aaf740bbf6c7c6e9c34a92b371eda311b66b"/>
|
||||
<project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="8f7c9ac889ae2c778197b4a4c0529d60530f480b"/>
|
||||
<project name="platform/external/wpa_supplicant_8" path="external/wpa_supplicant_8" revision="0e56e450367cd802241b27164a2979188242b95f"/>
|
||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="2838a77ce4b8c09fa6a46fe25410bb3a4474cbd4"/>
|
||||
<project name="platform_system_nfcd" path="system/nfcd" remote="b2g" revision="f995ccdb7c023b7edd8064c9d06fbea8f7108c45"/>
|
||||
<project name="platform/development" path="development" revision="1f18cfe031ce23b7fb838fe3d4379dd802b49e71"/>
|
||||
<project name="android-sdk" path="sdk" remote="b2g" revision="8b1365af38c9a653df97349ee53a3f5d64fd590a"/>
|
||||
</manifest>
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="6586d2b8b43c6997be5cf5895bbdf3dd20490725"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="e314d089d988f0eb1bef2404858c60b734dc4130"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9b6626eddbc85873eaa2a9174a9bd5101e5c05f"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="eda08beb3ba9a159843c70ffde0f9660ec351eb9"/>
|
||||
|
@ -96,6 +96,6 @@
|
|||
<project name="platform/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" revision="d2685281e2e54ca14d1df304867aa82c37b27162"/>
|
||||
<project name="platform/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" revision="627f9b20fc518937b93747a7ff1ed4f5ed46e06f"/>
|
||||
<project name="platform/prebuilts/tools" path="prebuilts/tools" revision="a3daa50e9b5db558696951ae724f913e4e5c7489"/>
|
||||
<project name="platform_prebuilts_qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="83dbccadb19d0d3c07828c2bb0e5c2be12c0f980"/>
|
||||
<project name="platform_prebuilts_qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="11663426672fcc46e2a0f29239afa736b90635ba"/>
|
||||
<project name="android-sdk" path="sdk" remote="b2g" revision="5701d3cb45c2e848cc57003cda2e1141288ecae4"/>
|
||||
</manifest>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
{
|
||||
"revision": "1150c11d1e6f0f78df3552dfca8c53d5ed5c173d",
|
||||
"revision": "34769c5ab47b95fe97fa0fe65e7e3a34f47b3f90",
|
||||
"repo_path": "/integration/gaia-central"
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="6586d2b8b43c6997be5cf5895bbdf3dd20490725"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="e314d089d988f0eb1bef2404858c60b734dc4130"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9b6626eddbc85873eaa2a9174a9bd5101e5c05f"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="84f2f2fce22605e17d511ff1767e54770067b5b5"/>
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="6586d2b8b43c6997be5cf5895bbdf3dd20490725"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="e314d089d988f0eb1bef2404858c60b734dc4130"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9b6626eddbc85873eaa2a9174a9bd5101e5c05f"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="84f2f2fce22605e17d511ff1767e54770067b5b5"/>
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="6586d2b8b43c6997be5cf5895bbdf3dd20490725"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="e314d089d988f0eb1bef2404858c60b734dc4130"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9b6626eddbc85873eaa2a9174a9bd5101e5c05f"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="84f2f2fce22605e17d511ff1767e54770067b5b5"/>
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="6586d2b8b43c6997be5cf5895bbdf3dd20490725"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="e314d089d988f0eb1bef2404858c60b734dc4130"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9b6626eddbc85873eaa2a9174a9bd5101e5c05f"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="84f2f2fce22605e17d511ff1767e54770067b5b5"/>
|
||||
|
|
|
@ -6,12 +6,12 @@
|
|||
<remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
|
||||
<remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
|
||||
<!-- B2G specific things. -->
|
||||
<project name="platform_build" path="build" remote="b2g" revision="fce1a137746dbd354bca1918f02f96d51c40bad2">
|
||||
<project name="platform_build" path="build" remote="b2g" revision="317f25e0a4cb3e8e86e2b76c37a14081372f0307">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="6586d2b8b43c6997be5cf5895bbdf3dd20490725"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="e314d089d988f0eb1bef2404858c60b734dc4130"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9b6626eddbc85873eaa2a9174a9bd5101e5c05f"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="96d2d00165f4561fbde62d1062706eab74b3a01f"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="a887bfabaed83c4588b40c845535c0388c8da0f3"/>
|
||||
|
@ -106,7 +106,7 @@
|
|||
<project name="platform/ndk" path="ndk" revision="7666b97bbaf1d645cdd6b4430a367b7a2bb53369"/>
|
||||
<project name="platform/prebuilts/misc" path="prebuilts/misc" revision="f6ab40b3257abc07741188fd173ac392575cc8d2"/>
|
||||
<project name="platform/prebuilts/ndk" path="prebuilts/ndk" revision="e52099755d0bd3a579130eefe8e58066cc6c0cb6"/>
|
||||
<project name="platform/prebuilts/qemu-kernel" path="prebuilts/qemu-kernel" revision="42011ad6bfec9978f9a297cf4a754af67b7c478a"/>
|
||||
<project name="platform_prebuilts_qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="11663426672fcc46e2a0f29239afa736b90635ba"/>
|
||||
<project name="platform/prebuilts/sdk" path="prebuilts/sdk" revision="842e33e43a55ea44833b9e23e4d180fa17c843af"/>
|
||||
<project name="platform/prebuilts/tools" path="prebuilts/tools" revision="5db24726f0f42124304195a6bdea129039eeeaeb"/>
|
||||
<project name="platform/system/bluetooth" path="system/bluetooth" revision="930ae098543881f47eac054677726ee4b998b2f8"/>
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="6586d2b8b43c6997be5cf5895bbdf3dd20490725"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="e314d089d988f0eb1bef2404858c60b734dc4130"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9b6626eddbc85873eaa2a9174a9bd5101e5c05f"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="84f2f2fce22605e17d511ff1767e54770067b5b5"/>
|
||||
|
|
|
@ -271,7 +271,8 @@ var gPluginHandler = {
|
|||
if (eventType == "PluginRemoved") {
|
||||
let doc = event.target;
|
||||
let browser = gBrowser.getBrowserForDocument(doc.defaultView.top.document);
|
||||
this._setPluginNotificationIcon(browser);
|
||||
if (browser)
|
||||
this._setPluginNotificationIcon(browser);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -301,6 +302,8 @@ var gPluginHandler = {
|
|||
|
||||
let shouldShowNotification = false;
|
||||
let browser = gBrowser.getBrowserForDocument(doc.defaultView.top.document);
|
||||
if (!browser)
|
||||
return;
|
||||
|
||||
switch (eventType) {
|
||||
case "PluginCrashed":
|
||||
|
|
|
@ -832,12 +832,11 @@
|
|||
|
||||
<toolbaritem id="PanelUI-button"
|
||||
class="chromeclass-toolbar-additional"
|
||||
removable="false"
|
||||
title="&appmenu.title;">
|
||||
removable="false">
|
||||
<toolbarbutton id="PanelUI-menu-button"
|
||||
class="toolbarbutton-1"
|
||||
label="&brandShortName;"
|
||||
tooltiptext="&appmenu.title;"/>
|
||||
tooltiptext="&appmenu.tooltip;"/>
|
||||
</toolbaritem>
|
||||
|
||||
<hbox id="window-controls" hidden="true" pack="end" skipintoolbarset="true"
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<hbox id="customization-container" flex="1" hidden="true">
|
||||
<vbox flex="1" id="customization-palette-container">
|
||||
<label id="customization-header">
|
||||
&customizeMode.menuAndToolbars.header;
|
||||
&customizeMode.menuAndToolbars.header2;
|
||||
</label>
|
||||
<hbox id="customization-empty" hidden="true">
|
||||
<label>&customizeMode.menuAndToolbars.empty;</label>
|
||||
|
|
|
@ -1411,10 +1411,13 @@ CustomizeMode.prototype = {
|
|||
|
||||
_setGridDragActive: function(aDragOverNode, aDraggedItem, aValue) {
|
||||
let targetArea = this._getCustomizableParent(aDragOverNode);
|
||||
let draggedWrapper = this.document.getElementById("wrapper-" + aDraggedItem.id);
|
||||
let originArea = this._getCustomizableParent(draggedWrapper);
|
||||
let positionManager = DragPositionManager.getManagerForArea(targetArea);
|
||||
let draggedSize = this._getDragItemSize(aDragOverNode, aDraggedItem);
|
||||
let isWide = aDraggedItem.classList.contains(CustomizableUI.WIDE_PANEL_CLASS);
|
||||
positionManager.insertPlaceholder(targetArea, aDragOverNode, isWide, draggedSize);
|
||||
positionManager.insertPlaceholder(targetArea, aDragOverNode, isWide, draggedSize,
|
||||
originArea == targetArea);
|
||||
},
|
||||
|
||||
_getDragItemSize: function(aDragOverNode, aDraggedItem) {
|
||||
|
|
|
@ -126,7 +126,7 @@ AreaPositionManager.prototype = {
|
|||
* they would have if we had inserted something before aBefore. We use CSS
|
||||
* transforms for this, which are CSS transitioned.
|
||||
*/
|
||||
insertPlaceholder: function(aContainer, aBefore, aWide, aSize) {
|
||||
insertPlaceholder: function(aContainer, aBefore, aWide, aSize, aIsFromThisArea) {
|
||||
let isShifted = false;
|
||||
let shiftDown = aWide;
|
||||
for (let child of aContainer.children) {
|
||||
|
@ -157,7 +157,7 @@ AreaPositionManager.prototype = {
|
|||
if (this.__moveDown) {
|
||||
shiftDown = true;
|
||||
}
|
||||
if (!this._lastPlaceholderInsertion) {
|
||||
if (aIsFromThisArea && !this._lastPlaceholderInsertion) {
|
||||
child.setAttribute("notransition", "true");
|
||||
}
|
||||
// Determine the CSS transform based on the next node:
|
||||
|
@ -167,7 +167,8 @@ AreaPositionManager.prototype = {
|
|||
child.style.transform = "";
|
||||
}
|
||||
}
|
||||
if (aContainer.lastChild && !this._lastPlaceholderInsertion) {
|
||||
if (aContainer.lastChild && aIsFromThisArea &&
|
||||
!this._lastPlaceholderInsertion) {
|
||||
// Flush layout:
|
||||
aContainer.lastChild.getBoundingClientRect();
|
||||
// then remove all the [notransition]
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
inside the private browsing mode -->
|
||||
<!ENTITY mainWindow.titlePrivateBrowsingSuffix "(Private Browsing)">
|
||||
|
||||
<!ENTITY appmenu.title "Customize and Control &brandFullName;">
|
||||
<!ENTITY appmenu.tooltip "Open menu">
|
||||
<!ENTITY navbarOverflow.label "More tools…">
|
||||
|
||||
<!-- Tab context menu -->
|
||||
|
@ -674,7 +674,7 @@ just addresses the organization to follow, e.g. "This site is run by " -->
|
|||
|
||||
<!ENTITY customizeMode.tabTitle "Customize &brandShortName;">
|
||||
<!ENTITY customizeMode.menuAndToolbars.label "Menu and toolbars">
|
||||
<!ENTITY customizeMode.menuAndToolbars.header "More Tools to Add to the Menu and Toolbar">
|
||||
<!ENTITY customizeMode.menuAndToolbars.header2 "Additional Tools and Features">
|
||||
<!ENTITY customizeMode.menuAndToolbars.empty "Want more tools?">
|
||||
<!ENTITY customizeMode.menuAndToolbars.emptyLink "Choose from thousands of add-ons">
|
||||
<!ENTITY customizeMode.restoreDefaults "Restore Defaults">
|
||||
|
|
|
@ -123,6 +123,9 @@ var Appbar = {
|
|||
onMenuButton: function(aEvent) {
|
||||
let typesArray = [];
|
||||
|
||||
if (BrowserUI.isPrivateBrowsingEnabled) {
|
||||
typesArray.push("private-browsing");
|
||||
}
|
||||
if (!BrowserUI.isStartTabVisible) {
|
||||
typesArray.push("find-in-page");
|
||||
if (ContextCommands.getPageSource())
|
||||
|
|
|
@ -86,6 +86,8 @@ var BrowserUI = {
|
|||
Services.prefs.addObserver(debugServerStateChanged, this, false);
|
||||
Services.prefs.addObserver(debugServerPortChanged, this, false);
|
||||
Services.prefs.addObserver("app.crashreporter.autosubmit", this, false);
|
||||
Services.prefs.addObserver("metro.private_browsing.enabled", this, false);
|
||||
this.updatePrivateBrowsingUI();
|
||||
|
||||
Services.obs.addObserver(this, "handle-xul-text-link", false);
|
||||
|
||||
|
@ -188,6 +190,12 @@ var BrowserUI = {
|
|||
messageManager.removeMessageListener("Content:StateChange", this);
|
||||
|
||||
messageManager.removeMessageListener("Browser:MozApplicationManifest", OfflineApps);
|
||||
|
||||
Services.prefs.removeObserver(debugServerStateChanged, this);
|
||||
Services.prefs.removeObserver(debugServerPortChanged, this);
|
||||
Services.prefs.removeObserver("app.crashreporter.autosubmit", this);
|
||||
Services.prefs.removeObserver("metro.private_browsing.enabled", this);
|
||||
|
||||
Services.obs.removeObserver(this, "handle-xul-text-link");
|
||||
|
||||
PanelUI.uninit();
|
||||
|
@ -411,9 +419,26 @@ var BrowserUI = {
|
|||
* Open a new tab in the foreground in response to a user action.
|
||||
* See Browser.addTab for more documentation.
|
||||
*/
|
||||
addAndShowTab: function (aURI, aOwner) {
|
||||
addAndShowTab: function (aURI, aOwner, aParams) {
|
||||
ContextUI.peekTabs(kForegroundTabAnimationDelay);
|
||||
return Browser.addTab(aURI || kStartURI, true, aOwner);
|
||||
return Browser.addTab(aURI || kStartURI, true, aOwner, aParams);
|
||||
},
|
||||
|
||||
addAndShowPrivateTab: function (aURI, aOwner) {
|
||||
return this.addAndShowTab(aURI, aOwner, { private: true });
|
||||
},
|
||||
|
||||
get isPrivateBrowsingEnabled() {
|
||||
return Services.prefs.getBoolPref("metro.private_browsing.enabled");
|
||||
},
|
||||
|
||||
updatePrivateBrowsingUI: function () {
|
||||
let command = document.getElementById("cmd_newPrivateTab");
|
||||
if (this.isPrivateBrowsingEnabled) {
|
||||
command.removeAttribute("disabled");
|
||||
} else {
|
||||
command.setAttribute("disabled", "true");
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -609,8 +634,9 @@ var BrowserUI = {
|
|||
BrowserUI.submitLastCrashReportOrShowPrompt;
|
||||
#endif
|
||||
break;
|
||||
|
||||
|
||||
case "metro.private_browsing.enabled":
|
||||
this.updatePrivateBrowsingUI();
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -848,29 +874,33 @@ var BrowserUI = {
|
|||
referrerURI = Services.io.newURI(json.referrer, null, null);
|
||||
this.goToURI(json.uri);
|
||||
break;
|
||||
case "Content:StateChange":
|
||||
let currBrowser = Browser.selectedBrowser;
|
||||
if (this.shouldCaptureThumbnails(currBrowser)) {
|
||||
PageThumbs.captureAndStore(currBrowser);
|
||||
let currPage = currBrowser.currentURI.spec;
|
||||
case "Content:StateChange": {
|
||||
let tab = Browser.selectedTab;
|
||||
if (this.shouldCaptureThumbnails(tab)) {
|
||||
PageThumbs.captureAndStore(tab.browser);
|
||||
let currPage = tab.browser.currentURI.spec;
|
||||
Services.obs.notifyObservers(null, "Metro:RefreshTopsiteThumbnail", currPage);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return {};
|
||||
},
|
||||
|
||||
// Private Browsing is not supported on metro at this time, when it is added
|
||||
// this function must be updated to skip capturing those pages
|
||||
shouldCaptureThumbnails: function shouldCaptureThumbnails(aBrowser) {
|
||||
shouldCaptureThumbnails: function shouldCaptureThumbnails(aTab) {
|
||||
// Capture only if it's the currently selected tab.
|
||||
if (aBrowser != Browser.selectedBrowser) {
|
||||
if (aTab != Browser.selectedTab) {
|
||||
return false;
|
||||
}
|
||||
// Skip private tabs
|
||||
if (aTab.isPrivate) {
|
||||
return false;
|
||||
}
|
||||
// FIXME Bug 720575 - Don't capture thumbnails for SVG or XML documents as
|
||||
// that currently regresses Talos SVG tests.
|
||||
let doc = aBrowser.contentDocument;
|
||||
let browser = aTab.browser;
|
||||
let doc = browser.contentDocument;
|
||||
if (doc instanceof SVGDocument || doc instanceof XMLDocument) {
|
||||
return false;
|
||||
}
|
||||
|
@ -883,17 +913,17 @@ var BrowserUI = {
|
|||
return false;
|
||||
}
|
||||
// There's no point in taking screenshot of loading pages.
|
||||
if (aBrowser.docShell.busyFlags != Ci.nsIDocShell.BUSY_FLAGS_NONE) {
|
||||
if (browser.docShell.busyFlags != Ci.nsIDocShell.BUSY_FLAGS_NONE) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Don't take screenshots of about: pages.
|
||||
if (aBrowser.currentURI.schemeIs("about")) {
|
||||
if (browser.currentURI.schemeIs("about")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// No valid document channel. We shouldn't take a screenshot.
|
||||
let channel = aBrowser.docShell.currentDocumentChannel;
|
||||
let channel = browser.docShell.currentDocumentChannel;
|
||||
if (!channel) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -476,6 +476,7 @@ var Browser = {
|
|||
* is closed, we will return to a parent or "sibling" tab if possible.
|
||||
* @param aParams Object (optional) with optional properties:
|
||||
* index: Number specifying where in the tab list to insert the new tab.
|
||||
* private: If true, the new tab should be have Private Browsing active.
|
||||
* flags, postData, charset, referrerURI: See loadURIWithFlags.
|
||||
*/
|
||||
addTab: function browser_addTab(aURI, aBringFront, aOwner, aParams) {
|
||||
|
@ -1255,6 +1256,13 @@ function Tab(aURI, aParams, aOwner) {
|
|||
this._eventDeferred = null;
|
||||
this._updateThumbnailTimeout = null;
|
||||
|
||||
this._private = false;
|
||||
if ("private" in aParams) {
|
||||
this._private = aParams.private;
|
||||
} else if (aOwner) {
|
||||
this._private = aOwner.private;
|
||||
}
|
||||
|
||||
this.owner = aOwner || null;
|
||||
|
||||
// Set to 0 since new tabs that have not been viewed yet are good tabs to
|
||||
|
@ -1282,6 +1290,10 @@ Tab.prototype = {
|
|||
return this._chromeTab;
|
||||
},
|
||||
|
||||
get isPrivate() {
|
||||
return this._private;
|
||||
},
|
||||
|
||||
get pageShowPromise() {
|
||||
return this._eventDeferred ? this._eventDeferred.promise : null;
|
||||
},
|
||||
|
@ -1307,6 +1319,10 @@ Tab.prototype = {
|
|||
this._eventDeferred = Promise.defer();
|
||||
|
||||
this._chromeTab = Elements.tabList.addTab(aParams.index);
|
||||
if (this.isPrivate) {
|
||||
this._chromeTab.setAttribute("private", "true");
|
||||
}
|
||||
|
||||
this._id = Browser.createTabId();
|
||||
let browser = this._createBrowser(aURI, null);
|
||||
|
||||
|
@ -1461,6 +1477,11 @@ Tab.prototype = {
|
|||
// let the content area manager know about this browser.
|
||||
ContentAreaObserver.onBrowserCreated(browser);
|
||||
|
||||
if (this.isPrivate) {
|
||||
let ctx = browser.docShell.QueryInterface(Ci.nsILoadContext);
|
||||
ctx.usePrivateBrowsing = true;
|
||||
}
|
||||
|
||||
// stop about:blank from loading
|
||||
browser.stop();
|
||||
|
||||
|
@ -1485,7 +1506,9 @@ Tab.prototype = {
|
|||
},
|
||||
|
||||
updateThumbnail: function updateThumbnail() {
|
||||
PageThumbs.captureToCanvas(this.browser.contentWindow, this._chromeTab.thumbnailCanvas);
|
||||
if (!this.isPrivate) {
|
||||
PageThumbs.captureToCanvas(this.browser.contentWindow, this._chromeTab.thumbnailCanvas);
|
||||
}
|
||||
},
|
||||
|
||||
updateFavicon: function updateFavicon() {
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
<?xml-stylesheet href="chrome://browser/skin/platform.css" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://browser/skin/browser.css" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://browser/content/browser.css" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://browser/content/bindings.css" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://browser/skin/cssthrobber.css" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://browser/skin/tiles.css" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://branding/content/metro-about.css" type="text/css"?>
|
||||
|
@ -85,6 +85,7 @@
|
|||
#ifdef MOZ_SERVICES_SYNC
|
||||
<command id="cmd_remoteTabs" oncommand="CommandUpdater.doCommand(this.id);"/>
|
||||
#endif
|
||||
<command id="cmd_newPrivateTab" oncommand="BrowserUI.addAndShowPrivateTab();"/>
|
||||
|
||||
<!-- misc -->
|
||||
<command id="cmd_close" oncommand="CommandUpdater.doCommand(this.id);"/>
|
||||
|
@ -162,6 +163,7 @@ Desktop browser's sync prefs.
|
|||
<key id="key_closeTab" key="&closeTab.key;" modifiers="accel" command="cmd_closeTab"/>
|
||||
<key id="key_closeTab2" keycode="VK_F4" modifiers="accel" command="cmd_closeTab"/>
|
||||
<key id="key_undoCloseTab" key="&newTab.key;" modifiers="accel,shift" command="cmd_undoCloseTab"/>
|
||||
<key id="key_newPrivateTab" key="&newPrivateTab.key;" modifiers="accel,shift" command="cmd_newPrivateTab"/>
|
||||
|
||||
<!-- tab selection -->
|
||||
<key id="key_nextTab" oncommand="BrowserUI.selectNextTab();" keycode="VK_TAB" modifiers="accel"/>
|
||||
|
@ -400,28 +402,34 @@ Desktop browser's sync prefs.
|
|||
<spacer flex="1"/>
|
||||
</hbox>
|
||||
<hbox id="checkingForUpdates" align="center">
|
||||
<image class="update-throbber"/><label>&update.checkingForUpdates;</label>
|
||||
<image class="update-throbber"/>
|
||||
<description flex="1">&update.checkingForUpdates;</description>
|
||||
</hbox>
|
||||
<hbox id="checkingAddonCompat" align="center">
|
||||
<image class="update-throbber"/><label>&update.checkingAddonCompat;</label>
|
||||
<image class="update-throbber"/>
|
||||
<description flex="1">&update.checkingAddonCompat;</description>
|
||||
</hbox>
|
||||
<hbox id="downloading" align="center">
|
||||
<image class="update-throbber"/><label>&update.downloading.start;</label><label id="downloadStatus"/><label>&update.downloading.end;</label>
|
||||
<image class="update-throbber"/>
|
||||
<description flex="1">
|
||||
&update.downloading.start;<html:span id="downloadStatus"></html:span>&update.downloading.end;
|
||||
</description>
|
||||
</hbox>
|
||||
<hbox id="applying" align="center">
|
||||
<image class="update-throbber"/><label>&update.applying;</label>
|
||||
<image class="update-throbber"/>
|
||||
<description flex="1">&update.applying;</description>
|
||||
</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>
|
||||
<label linewrap="true">&update.adminDisabled;</label>
|
||||
</hbox>
|
||||
<hbox id="noUpdatesFound" align="center">
|
||||
<label>&update.noUpdatesFound;</label>
|
||||
<label linewrap="true">&update.noUpdatesFound;</label>
|
||||
</hbox>
|
||||
<hbox id="otherInstanceHandlingUpdates" align="center">
|
||||
<label>&update.otherInstanceHandlingUpdates;</label>
|
||||
<label linewrap="true">&update.otherInstanceHandlingUpdates;</label>
|
||||
</hbox>
|
||||
<hbox id="manualUpdate" align="center">
|
||||
<label>&update.manual.start;</label><label id="manualLink" linewrap="true" class="text-link"/><label>&update.manual.end;</label>
|
||||
|
@ -807,6 +815,9 @@ Desktop browser's sync prefs.
|
|||
</richlistitem>
|
||||
|
||||
<!-- standard buttons -->
|
||||
<richlistitem id="context-newprivatetab" type="private-browsing" onclick="BrowserUI.addAndShowPrivateTab()">
|
||||
<label value="&newPrivateTab.label;"/>
|
||||
</richlistitem>
|
||||
<richlistitem id="context-findinpage" type="find-in-page" onclick="ContextCommands.findInPage();">
|
||||
<label value="&appbarFindInPage2.label;"/>
|
||||
</richlistitem>
|
||||
|
|
|
@ -506,7 +506,7 @@ appUpdater.prototype =
|
|||
*/
|
||||
setupDownloadingUI: function() {
|
||||
this.downloadStatus = document.getElementById("downloadStatus");
|
||||
this.downloadStatus.value =
|
||||
this.downloadStatus.textContent =
|
||||
DownloadUtils.getTransferTotal(0, this.update.selectedPatch.size);
|
||||
this.selectPanel("downloading");
|
||||
this.aus.addDownloadListener(this);
|
||||
|
@ -598,7 +598,7 @@ appUpdater.prototype =
|
|||
* See nsIProgressEventSink.idl
|
||||
*/
|
||||
onProgress: function(aRequest, aContext, aProgress, aProgressMax) {
|
||||
this.downloadStatus.value =
|
||||
this.downloadStatus.textContent =
|
||||
DownloadUtils.getTransferTotal(aProgress, aProgressMax);
|
||||
},
|
||||
|
||||
|
|
|
@ -26,8 +26,7 @@
|
|||
<meta name="viewport" content="width=device-width; user-scalable=false;" />
|
||||
<title>&crashprompt.title;</title>
|
||||
<link rel="stylesheet" href="chrome://browser/skin/platform.css" type="text/css" media="all" />
|
||||
<link rel="stylesheet" href="chrome://browser/skin/browser.css" type="text/css" media="all" />
|
||||
<link rel="stylesheet" href="chrome://browser/content/browser.css" type="text/css" media="all" />
|
||||
<link rel="stylesheet" href="chrome://browser/content/bindings.css" type="text/css" media="all" />
|
||||
<link rel="stylesheet" href="chrome://browser/skin/crashprompt.css" type="text/css" media="all" />
|
||||
<!--TODO: Do we need a favicon?-->
|
||||
|
||||
|
|
|
@ -5,9 +5,9 @@
|
|||
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
|
||||
|
||||
<?xml-stylesheet href="chrome://browser/skin/platform.css" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://browser/skin/browser.css" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://browser/content/browser.css" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://browser/content/bindings.css" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://browser/skin/tiles.css" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://browser/skin/start.css" type="text/css"?>
|
||||
|
||||
<!DOCTYPE window [
|
||||
<!ENTITY % globalDTD SYSTEM "chrome://global/locale/global.dtd">
|
||||
|
|
|
@ -75,7 +75,7 @@ chrome.jar:
|
|||
content/appbar.js (content/appbar.js)
|
||||
content/shell.xul (content/jsshell/shell.xul)
|
||||
content/shell.html (content/jsshell/shell.html)
|
||||
content/browser.css (content/browser.css)
|
||||
content/bindings.css (content/bindings.css)
|
||||
content/cursor.css (content/cursor.css)
|
||||
content/sanitize.js (content/sanitize.js)
|
||||
content/sanitizeUI.js (content/sanitizeUI.js)
|
||||
|
|
|
@ -0,0 +1,111 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
let gStartView = null;
|
||||
|
||||
function test() {
|
||||
requestLongerTimeout(2);
|
||||
runTests();
|
||||
}
|
||||
|
||||
function setup() {
|
||||
PanelUI.hide();
|
||||
|
||||
if (!BrowserUI.isStartTabVisible) {
|
||||
let tab = yield addTab("about:start");
|
||||
gStartView = tab.browser.contentWindow.BookmarksStartView._view;
|
||||
|
||||
yield waitForCondition(() => BrowserUI.isStartTabVisible);
|
||||
|
||||
yield hideContextUI();
|
||||
}
|
||||
|
||||
BookmarksTestHelper.setup();
|
||||
HistoryTestHelper.setup();
|
||||
}
|
||||
|
||||
function tearDown() {
|
||||
PanelUI.hide();
|
||||
BookmarksTestHelper.restore();
|
||||
HistoryTestHelper.restore();
|
||||
}
|
||||
|
||||
gTests.push({
|
||||
desc: "touch scroll",
|
||||
run: function run() {
|
||||
yield addTab(chromeRoot + "res/scroll_test.html");
|
||||
yield hideContextUI();
|
||||
yield hideNavBar();
|
||||
|
||||
let stopwatch = new StopWatch();
|
||||
let win = Browser.selectedTab.browser.contentWindow;
|
||||
let domUtils = win.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils);
|
||||
|
||||
var touchdrag = new TouchDragAndHold();
|
||||
touchdrag.useNativeEvents = true;
|
||||
touchdrag.stepTimeout = 5;
|
||||
touchdrag.numSteps = 20;
|
||||
|
||||
stopwatch.start();
|
||||
let recordingHandle = domUtils.startFrameTimeRecording();
|
||||
for (let count = 0; count < 3; count++) {
|
||||
yield touchdrag.start(win, 100, (win.innerHeight - 50), 100, 50);
|
||||
touchdrag.end();
|
||||
yield touchdrag.start(win, 100, 50, 100, (win.innerHeight - 50));
|
||||
touchdrag.end();
|
||||
}
|
||||
let intervals = domUtils.stopFrameTimeRecording(recordingHandle);
|
||||
let msec = stopwatch.stop();
|
||||
|
||||
|
||||
PerfTest.declareTest("14C693E5-3ED3-4A5D-93BC-A31F130A8CDE",
|
||||
"touch scroll text", "graphics", "apzc",
|
||||
"Measures performance of apzc scrolling for a large page of text using FTR.");
|
||||
PerfTest.declareFrameRateResult(intervals.length, msec, "fps");
|
||||
}
|
||||
});
|
||||
|
||||
gTests.push({
|
||||
desc: "touch scroll start",
|
||||
setUp: setup,
|
||||
tearDown: tearDown,
|
||||
run: function run() {
|
||||
let stopwatch = new StopWatch();
|
||||
let win = Browser.selectedTab.browser.contentWindow;
|
||||
let domUtils = win.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils);
|
||||
|
||||
var touchdrag = new TouchDragAndHold();
|
||||
touchdrag.useNativeEvents = true;
|
||||
touchdrag.stepTimeout = 5;
|
||||
touchdrag.numSteps = 20;
|
||||
|
||||
stopwatch.start();
|
||||
let recordingHandle = domUtils.startFrameTimeRecording();
|
||||
for (let count = 0; count < 3; count++) {
|
||||
yield touchdrag.start(win, (win.innerWidth - 50), (win.innerHeight - 50), 50, (win.innerHeight - 50));
|
||||
touchdrag.end();
|
||||
yield touchdrag.start(win, 50, (win.innerHeight - 50), (win.innerWidth - 50), (win.innerHeight - 50));
|
||||
touchdrag.end();
|
||||
}
|
||||
let intervals = domUtils.stopFrameTimeRecording(recordingHandle);
|
||||
let msec = stopwatch.stop();
|
||||
|
||||
PerfTest.declareTest("24C693E5-3ED3-4A5D-93BC-A31F130A8CDE",
|
||||
"touch scroll about:start", "graphics", "apzc",
|
||||
"Measures performance of apzc scrolling for about:start using FTR.");
|
||||
PerfTest.declareFrameRateResult(intervals.length, msec, "fps");
|
||||
|
||||
let results = PerfTest.computeHighLowBands(intervals, .1);
|
||||
PerfTest.declareTest("2E60F8B5-8925-4628-988E-E4C0BC6B34C7",
|
||||
"about:start jank", "graphics", "apzc",
|
||||
"Displays the low, high, and average FTR frame intervals for about:start.");
|
||||
info("results.low:" + results.low);
|
||||
PerfTest.declareNumericalResults([
|
||||
{ value: results.low, desc: "low" },
|
||||
{ value: results.high, desc: "high" },
|
||||
{ value: results.ave, desc: "average" }
|
||||
]);
|
||||
}
|
||||
});
|
|
@ -12,19 +12,17 @@ gTests.push({
|
|||
run: function run() {
|
||||
yield addTab("about:mozilla");
|
||||
yield hideContextUI();
|
||||
yield waitForMs(5000);
|
||||
yield hideNavBar();
|
||||
yield waitForMs(3000);
|
||||
|
||||
let shiftDataSet = new Array();
|
||||
let paintDataSet = new Array();
|
||||
let stopwatch = new StopWatch();
|
||||
|
||||
var paintCount = 0;
|
||||
function onPaint() {
|
||||
paintCount++;
|
||||
}
|
||||
let win = Browser.selectedTab.browser.contentWindow;
|
||||
let domUtils = win.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils);
|
||||
|
||||
for (let idx = 0; idx < 10; idx++) {
|
||||
window.addEventListener("MozAfterPaint", onPaint, true);
|
||||
let recordingHandle = domUtils.startFrameTimeRecording();
|
||||
stopwatch.start();
|
||||
let promise = waitForEvent(window, "MozDeckOffsetChanged");
|
||||
ContentAreaObserver.shiftBrowserDeck(300);
|
||||
|
@ -34,22 +32,21 @@ gTests.push({
|
|||
yield promise;
|
||||
stopwatch.stop();
|
||||
yield waitForMs(500);
|
||||
window.removeEventListener("MozAfterPaint", onPaint, true);
|
||||
let intervals = domUtils.stopFrameTimeRecording(recordingHandle);
|
||||
shiftDataSet.push(stopwatch.time());
|
||||
paintDataSet.push(paintCount);
|
||||
paintCount = 0;
|
||||
paintDataSet.push(intervals.length);
|
||||
}
|
||||
|
||||
PerfTest.declareTest("ecb5fbec-0b3d-490f-8d4a-13fa8963e54a",
|
||||
"shift browser deck", "browser", "ux",
|
||||
"Triggers multiple SKB deck shifting operations using an offset " +
|
||||
"value of 300px. Measures total time in milliseconds for a up/down " +
|
||||
"shift operation plus the total number of paints. Strips outliers.");
|
||||
"shift operation plus the total number of frames. Strips outliers.");
|
||||
let shiftAverage = PerfTest.computeAverage(shiftDataSet, { stripOutliers: true });
|
||||
let paintAverage = PerfTest.computeAverage(paintDataSet, { stripOutliers: true });
|
||||
PerfTest.declareNumericalResults([
|
||||
{ value: shiftAverage, desc: "msec" },
|
||||
{ value: paintAverage, desc: "paint count" },
|
||||
{ value: paintAverage, desc: "frame count" },
|
||||
]);
|
||||
}
|
||||
});
|
||||
|
|
|
@ -11,24 +11,24 @@ gTests.push({
|
|||
desc: "rotating divs",
|
||||
run: function run() {
|
||||
yield addTab(chromeRoot + "res/divs_test.html", true);
|
||||
|
||||
yield hideContextUI();
|
||||
yield hideNavBar();
|
||||
|
||||
let stopwatch = new StopWatch();
|
||||
|
||||
let win = Browser.selectedTab.browser.contentWindow;
|
||||
let domUtils = win.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils);
|
||||
yield waitForEvent(win, "teststarted", 5000);
|
||||
// the test runs for five seconds
|
||||
let recordingHandle = domUtils.startFrameTimeRecording();
|
||||
stopwatch.start();
|
||||
let event = yield waitForEvent(win, "testfinished", 10000);
|
||||
let intervals = domUtils.stopFrameTimeRecording(recordingHandle);
|
||||
let msec = stopwatch.stop();
|
||||
|
||||
PerfTest.declareTest("B924F3FA-4CB5-4453-B131-53E3611E0765",
|
||||
"rotating divs w/text", "graphics", "content",
|
||||
"Measures animation frames for rotating translucent divs on top of a background of text.");
|
||||
|
||||
|
||||
stopwatch.start();
|
||||
// the test runs for ten seconds
|
||||
let event = yield waitForEvent(win, "testfinished", 20000);
|
||||
let msec = stopwatch.stop();
|
||||
|
||||
PerfTest.declareNumericalResult((event.detail.frames / msec) * 1000.0, "fps");
|
||||
PerfTest.declareFrameRateResult(intervals.length, msec, "fps");
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -18,81 +18,27 @@ gTests.push({
|
|||
run: function run() {
|
||||
yield addTab(chromeRoot + "res/scroll_test.html");
|
||||
yield hideContextUI();
|
||||
yield hideNavBar();
|
||||
|
||||
let stopwatch = new StopWatch();
|
||||
|
||||
let win = Browser.selectedTab.browser.contentWindow;
|
||||
|
||||
PerfTest.declareTest("79235F74-037C-4F6B-AE47-FDCCC13458C3",
|
||||
"scrollBy scroll", "graphics", "content",
|
||||
"Measures performance of single line scrolls using scrollBy for a large page of text.");
|
||||
|
||||
let mozpaints = 0;
|
||||
function onPaint() {
|
||||
mozpaints++;
|
||||
}
|
||||
win.addEventListener("MozAfterPaint", onPaint, true);
|
||||
|
||||
let domUtils = win.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils);
|
||||
let deferExit = Promise.defer();
|
||||
let recordingHandle = domUtils.startFrameTimeRecording();
|
||||
|
||||
function step() {
|
||||
if (stopwatch.time() < 10000) {
|
||||
if (stopwatch.time() < 5000) {
|
||||
win.scrollBy(0, 2);
|
||||
// XXX slaves won't paint without this
|
||||
win.mozRequestAnimationFrame(step);
|
||||
return;
|
||||
}
|
||||
win.removeEventListener("MozAfterPaint", onPaint, true);
|
||||
|
||||
let intervals = domUtils.stopFrameTimeRecording(recordingHandle);
|
||||
let msec = stopwatch.stop();
|
||||
PerfTest.declareFrameRateResult(mozpaints, msec, "fps");
|
||||
deferExit.resolve();
|
||||
}
|
||||
|
||||
stopwatch.start();
|
||||
win.mozRequestAnimationFrame(step);
|
||||
yield deferExit.promise;
|
||||
}
|
||||
});
|
||||
|
||||
gTests.push({
|
||||
desc: "scoll touch",
|
||||
run: function run() {
|
||||
yield addTab(chromeRoot + "res/scroll_test.html");
|
||||
yield hideContextUI();
|
||||
|
||||
let stopwatch = new StopWatch();
|
||||
|
||||
let win = Browser.selectedTab.browser.contentWindow;
|
||||
|
||||
PerfTest.declareTest("14C693E5-3ED3-4A5D-93BC-A31F130A8CDE",
|
||||
"touch scroll", "graphics", "content",
|
||||
"Measures performance of single line scrolls using touch input for a large page of text.");
|
||||
|
||||
let y = win.innerHeight - 10;
|
||||
EventUtils.synthesizeTouchAtPoint(100, y, { type: "touchstart" }, win);
|
||||
EventUtils.synthesizeTouchAtPoint(100, y, { type: "touchmove" }, win);
|
||||
y -= tapRadius() + 5;
|
||||
EventUtils.synthesizeTouchAtPoint(100, y, { type: "touchmove" }, win);
|
||||
|
||||
let mozpaints = 0;
|
||||
function onPaint() {
|
||||
mozpaints++;
|
||||
}
|
||||
win.addEventListener("MozAfterPaint", onPaint, true);
|
||||
|
||||
let deferExit = Promise.defer();
|
||||
|
||||
function step() {
|
||||
if (stopwatch.time() < 10000) {
|
||||
y -= 2;
|
||||
EventUtils.synthesizeTouchAtPoint(100, y, { type: "touchmove" }, win);
|
||||
win.mozRequestAnimationFrame(step);
|
||||
return;
|
||||
}
|
||||
win.removeEventListener("MozAfterPaint", onPaint, true);
|
||||
let msec = stopwatch.stop();
|
||||
EventUtils.synthesizeTouchAtPoint(100, y, { type: "touchend" }, win);
|
||||
PerfTest.declareFrameRateResult(mozpaints, msec, "fps");
|
||||
PerfTest.declareTest("79235F74-037C-4F6B-AE47-FDCCC13458C3",
|
||||
"scrollBy scroll", "graphics", "content",
|
||||
"Measures performance of single line scrolls for a large page of text using FTR.");
|
||||
PerfTest.declareFrameRateResult(intervals.length, msec, "fps");
|
||||
deferExit.resolve();
|
||||
}
|
||||
|
||||
|
@ -106,17 +52,22 @@ gTests.push({
|
|||
desc: "canvas perf test",
|
||||
run: function run() {
|
||||
yield addTab(chromeRoot + "res/ripples.html");
|
||||
let win = Browser.selectedTab.browser.contentWindow;
|
||||
yield hideContextUI();
|
||||
yield hideNavBar();
|
||||
|
||||
let win = Browser.selectedTab.browser.contentWindow;
|
||||
let domUtils = win.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils);
|
||||
let recordingHandle = domUtils.startFrameTimeRecording();
|
||||
PerfTest.declareTest("6A455F96-2B2C-4B3C-B387-1AF2F1747CCF",
|
||||
"ripples", "graphics", "canvas",
|
||||
"Measures animation frames during a computationally " +
|
||||
"heavy graphics demo using canvas.");
|
||||
"heavy graphics demo using canvas using FTR.");
|
||||
let stopwatch = new StopWatch(true);
|
||||
let event = yield waitForEvent(win, "test", 20000);
|
||||
// test page runs for 5 seconds
|
||||
let event = yield waitForEvent(win, "test", 10000);
|
||||
let intervals = domUtils.stopFrameTimeRecording(recordingHandle);
|
||||
let msec = stopwatch.stop();
|
||||
PerfTest.declareFrameRateResult(event.detail.frames, msec, "fps");
|
||||
|
||||
PerfTest.declareFrameRateResult(intervals.length, msec, "fps");
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -125,27 +76,24 @@ gTests.push({
|
|||
run: function run() {
|
||||
yield addTab(chromeRoot + "res/tidevideo.html");
|
||||
let win = Browser.selectedTab.browser.contentWindow;
|
||||
let domUtils = win.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils);
|
||||
let video = win.document.getElementById("videoelement");
|
||||
video.pause();
|
||||
yield hideContextUI();
|
||||
yield hideNavBar();
|
||||
yield waitForMs(1000);
|
||||
PerfTest.declareTest("7F55F9C4-0ECF-4A13-9A9C-A38D46922C0B",
|
||||
"video playback (moz paints)", "graphics", "video",
|
||||
"Measures MozAfterPaints per second during five seconds of playback of an mp4.");
|
||||
"Measures frames per second during five seconds of playback of an mp4.");
|
||||
|
||||
var paintCount = 0;
|
||||
function onPaint() {
|
||||
paintCount++;
|
||||
}
|
||||
let recordingHandle = domUtils.startFrameTimeRecording();
|
||||
let stopwatch = new StopWatch(true);
|
||||
window.addEventListener("MozAfterPaint", onPaint, true);
|
||||
video.play();
|
||||
yield waitForMs(5000);
|
||||
video.pause();
|
||||
window.removeEventListener("MozAfterPaint", onPaint, true);
|
||||
let intervals = domUtils.stopFrameTimeRecording(recordingHandle);
|
||||
let msec = stopwatch.stop();
|
||||
|
||||
PerfTest.declareNumericalResult((paintCount / msec) * 1000.0, "pps");
|
||||
PerfTest.declareFrameRateResult(intervals.length, msec, "fps");
|
||||
|
||||
PerfTest.declareTest("E132D333-4642-4597-B1F0-1E74B625DBD7",
|
||||
"video playback (moz stats)", "graphics", "video",
|
||||
|
@ -158,4 +106,3 @@ gTests.push({
|
|||
PerfTest.declareNumericalResults(results);
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -179,6 +179,29 @@ var PerfTest = {
|
|||
return total / count;
|
||||
},
|
||||
|
||||
computeHighLowBands: function computeHighLow(aArray, aPercentage) {
|
||||
let bandCount = Math.ceil(aArray.length * aPercentage);
|
||||
let lowGroup = 0, highGroup = 0;
|
||||
let idx;
|
||||
|
||||
function compareNumbers(a, b) {
|
||||
return a - b;
|
||||
}
|
||||
aArray.sort(compareNumbers);
|
||||
for (idx = 0; idx < bandCount; idx++) {
|
||||
lowGroup += aArray[idx];
|
||||
}
|
||||
let top = aArray.length - 1;
|
||||
for (idx = top; idx > (top - bandCount); idx--) {
|
||||
highGroup += aArray[idx];
|
||||
}
|
||||
return {
|
||||
low: lowGroup / bandCount,
|
||||
high: highGroup / bandCount,
|
||||
ave: this.computeAverage(aArray, {})
|
||||
};
|
||||
},
|
||||
|
||||
/******************************************************
|
||||
* Internal
|
||||
*/
|
||||
|
|
|
@ -11,6 +11,7 @@ support-files =
|
|||
res/divs_test.html
|
||||
res/fx.png
|
||||
|
||||
[browser_apzc.js]
|
||||
[browser_miscgfx_01.js]
|
||||
[browser_tabs_01.js]
|
||||
[browser_deck_01.js]
|
||||
|
|
|
@ -70,12 +70,15 @@ var frames = 0;
|
|||
|
||||
function go() {
|
||||
var now = new Date();
|
||||
var evt = document.createEvent("CustomEvent");
|
||||
evt.initCustomEvent("teststarted", true, false, {});
|
||||
window.dispatchEvent(evt);
|
||||
function step(timestamp) {
|
||||
render();
|
||||
frames++;
|
||||
var time = new Date();
|
||||
var diff = time.getTime() - now.getTime();
|
||||
if (diff < 10000) {
|
||||
if (diff < 5000) {
|
||||
window.mozRequestAnimationFrame(step);
|
||||
} else {
|
||||
var evt = document.createEvent("CustomEvent");
|
||||
|
|
|
@ -231,7 +231,7 @@ function run() {
|
|||
ripples.run(progress);
|
||||
var time = new Date();
|
||||
var diff = time.getTime() - now.getTime();
|
||||
if (diff < 10000) { // ten seconds
|
||||
if (diff < 5000) { // five seconds
|
||||
window.mozRequestAnimationFrame(step);
|
||||
} else {
|
||||
var evt = document.createEvent("CustomEvent");
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
function test() {
|
||||
runTests();
|
||||
}
|
||||
|
||||
gTests.push({
|
||||
desc: "Private tab sanity check",
|
||||
run: function() {
|
||||
let tab = Browser.addTab("about:mozilla");
|
||||
is(tab.isPrivate, false, "Tabs are not private by default");
|
||||
is(tab.chromeTab.hasAttribute("private"), false,
|
||||
"non-private tab has no private attribute");
|
||||
Browser.closeTab(tab, { forceClose: true });
|
||||
|
||||
tab = Browser.addTab("about:mozilla", false, null, { private: true });
|
||||
is(tab.isPrivate, true, "Create a private tab");
|
||||
is(tab.chromeTab.getAttribute("private"), "true",
|
||||
"private tab has private attribute");
|
||||
Browser.closeTab(tab, { forceClose: true });
|
||||
}
|
||||
});
|
|
@ -6,10 +6,10 @@
|
|||
|
||||
<?xml-stylesheet href="chrome://browser/skin/platform.css" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://browser/skin/browser.css" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://browser/content/browser.css" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://browser/content/bindings.css" type="text/css"?>
|
||||
|
||||
<!DOCTYPE window []>
|
||||
|
||||
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
<circularprogressindicator id="progress-indicator" oncommand=""/>
|
||||
</window>
|
||||
</window>
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
<?xml-stylesheet href="chrome://browser/skin/platform.css" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://browser/skin/browser.css" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://browser/content/browser.css" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://browser/content/bindings.css" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://browser/skin/tiles.css" type="text/css"?>
|
||||
<!DOCTYPE window []>
|
||||
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
|
|
|
@ -213,11 +213,22 @@ function hideContextUI()
|
|||
|
||||
function showNavBar()
|
||||
{
|
||||
let promise = waitForEvent(Elements.navbar, "transitionend");
|
||||
if (!ContextUI.navbarVisible) {
|
||||
let promise = waitForEvent(Elements.navbar, "transitionend");
|
||||
ContextUI.displayNavbar();
|
||||
return promise;
|
||||
}
|
||||
return Promise.resolve(null);
|
||||
}
|
||||
|
||||
function hideNavBar()
|
||||
{
|
||||
if (ContextUI.navbarVisible) {
|
||||
let promise = waitForEvent(Elements.navbar, "transitionend");
|
||||
ContextUI.dismissNavbar();
|
||||
return promise;
|
||||
}
|
||||
return Promise.resolve(null);
|
||||
}
|
||||
|
||||
function fireAppBarDisplayEvent()
|
||||
|
@ -827,6 +838,14 @@ TouchDragAndHold.prototype = {
|
|||
this._native = aValue;
|
||||
},
|
||||
|
||||
set stepTimeout(aValue) {
|
||||
this._timeoutStep = aValue;
|
||||
},
|
||||
|
||||
set numSteps(aValue) {
|
||||
this._numSteps = aValue;
|
||||
},
|
||||
|
||||
set nativePointerId(aValue) {
|
||||
this._pointerId = aValue;
|
||||
},
|
||||
|
|
|
@ -53,6 +53,7 @@ support-files =
|
|||
[browser_mouse_events.js]
|
||||
[browser_onscreen_keyboard.js]
|
||||
[browser_prefs_ui.js]
|
||||
[browser_private_browsing.js]
|
||||
[browser_prompt.js]
|
||||
[browser_remotetabs.js]
|
||||
[browser_snappedState.js]
|
||||
|
|
|
@ -553,15 +553,17 @@ SessionStore.prototype = {
|
|||
},
|
||||
|
||||
_getTabData: function(aWindow) {
|
||||
return aWindow.Browser.tabs.map(tab => {
|
||||
let browser = tab.browser;
|
||||
if (browser.__SS_data) {
|
||||
let tabData = browser.__SS_data;
|
||||
if (browser.__SS_extdata)
|
||||
tabData.extData = browser.__SS_extdata;
|
||||
return tabData;
|
||||
}
|
||||
});
|
||||
return aWindow.Browser.tabs
|
||||
.filter(tab => !tab.isPrivate)
|
||||
.map(tab => {
|
||||
let browser = tab.browser;
|
||||
if (browser.__SS_data) {
|
||||
let tabData = browser.__SS_data;
|
||||
if (browser.__SS_extdata)
|
||||
tabData.extData = browser.__SS_extdata;
|
||||
return tabData;
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
_collectWindowData: function ss__collectWindowData(aWindow) {
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
<!ENTITY back.label "Back">
|
||||
<!ENTITY forward.label "Forward">
|
||||
<!ENTITY newtab.label "New Tab">
|
||||
<!ENTITY newPrivateTab.label "New Private Tab">
|
||||
<!ENTITY closetab.label "Close Tab">
|
||||
|
||||
<!ENTITY autocompleteResultsHeader.label "Your Results">
|
||||
|
@ -103,6 +104,8 @@
|
|||
<!ENTITY newTab.key "t">
|
||||
<!ENTITY newTab2.key "n">
|
||||
<!ENTITY closeTab.key "w">
|
||||
<!-- Private browsing (control+shift+key) -->
|
||||
<!ENTITY newPrivateTab.key "p">
|
||||
|
||||
<!-- DEVELOPER SHORTCUTS (control+shift+key) -->
|
||||
<!ENTITY jsConsole.key "j">
|
||||
|
|
|
@ -33,10 +33,12 @@ pref("metro.debug.selection.displayRanges", false);
|
|||
pref("metro.debug.selection.dumpRanges", false);
|
||||
pref("metro.debug.selection.dumpEvents", false);
|
||||
|
||||
// Private browsing is disabled by default until implementation and testing are complete
|
||||
pref("metro.private_browsing.enabled", false);
|
||||
|
||||
// Enable tab-modal prompts
|
||||
pref("prompts.tab_modal.enabled", true);
|
||||
|
||||
|
||||
// Enable off main thread compositing
|
||||
pref("layers.offmainthreadcomposition.enabled", true);
|
||||
pref("layers.async-pan-zoom.enabled", true);
|
||||
|
|
|
@ -163,6 +163,12 @@ documenttab[closing] > .documenttab-container {
|
|||
background-image: none!important;
|
||||
}
|
||||
|
||||
/* TODO: Decide how and where to display private tabs.
|
||||
* For now, display them in the main tab strip but hide the thumbnail. */
|
||||
documenttab[private] .documenttab-thumbnail {
|
||||
background-color: purple;
|
||||
}
|
||||
|
||||
.documenttab-title {
|
||||
margin: @metro_spacing_normal@ @metro_spacing_snormal@;
|
||||
margin-top: 0;
|
||||
|
@ -220,43 +226,11 @@ documenttab[selected] .documenttab-selection {
|
|||
padding-bottom: @toolbar_height@;
|
||||
}
|
||||
|
||||
#startui-page {
|
||||
overflow-x: scroll;
|
||||
overflow-y: hidden;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
#startui-page[viewstate="snapped"],
|
||||
#startui-page[viewstate="portrait"] {
|
||||
overflow-x: hidden;
|
||||
overflow-y: scroll;
|
||||
}
|
||||
|
||||
#startui-body {
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
#start-container {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
#urlbar-autocomplete[viewstate="snapped"],
|
||||
#urlbar-autocomplete[viewstate="portrait"]{
|
||||
-moz-box-orient: vertical;
|
||||
}
|
||||
|
||||
#start-container[viewstate="snapped"],
|
||||
#start-container[viewstate="portrait"] {
|
||||
width: 100%;
|
||||
max-width: 100%; /* ensure page doesn't expand, messing up @media rules */
|
||||
height: auto;
|
||||
}
|
||||
|
||||
#start-container[viewstate="snapped"] .meta-section:not([expanded]) > richgrid {
|
||||
visibility: collapse;
|
||||
}
|
||||
|
||||
#autocomplete-overlay {
|
||||
display: none;
|
||||
background-color: black;
|
||||
|
|
|
@ -23,6 +23,7 @@ chrome.jar:
|
|||
skin/touchcontrols.css (touchcontrols.css)
|
||||
* skin/netError.css (netError.css)
|
||||
skin/firstrun.css (firstrun.css)
|
||||
* skin/start.css (start.css)
|
||||
% override chrome://global/skin/about.css chrome://browser/skin/about.css
|
||||
% override chrome://global/skin/media/videocontrols.css chrome://browser/skin/touchcontrols.css
|
||||
% override chrome://global/skin/netError.css chrome://browser/skin/netError.css
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
%filter substitution
|
||||
%include defines.inc
|
||||
|
||||
/* Start UI ----------------------------------------------------------------- */
|
||||
|
||||
#startui-page {
|
||||
overflow-x: scroll;
|
||||
overflow-y: hidden;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
#startui-page[viewstate="snapped"],
|
||||
#startui-page[viewstate="portrait"] {
|
||||
overflow-x: hidden;
|
||||
overflow-y: scroll;
|
||||
}
|
||||
|
||||
#startui-body {
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
#start-container {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
#start-container[viewstate="snapped"],
|
||||
#start-container[viewstate="portrait"] {
|
||||
width: 100%;
|
||||
max-width: 100%; /* ensure page doesn't expand, messing up @media rules */
|
||||
height: auto;
|
||||
}
|
||||
|
||||
#start-container[viewstate="snapped"] .meta-section:not([expanded]) > richgrid {
|
||||
visibility: collapse;
|
||||
}
|
|
@ -50,6 +50,10 @@
|
|||
|
||||
#customization-panel-container {
|
||||
padding: 15px 25px 25px;
|
||||
background-image: linear-gradient(to bottom, #3e86ce, #3878ba);
|
||||
}
|
||||
|
||||
#main-window[customize-entered] #customization-panel-container {
|
||||
background-image: url("chrome://browser/skin/customizableui/customizeMode-separatorHorizontal.png"),
|
||||
url("chrome://browser/skin/customizableui/customizeMode-separatorVertical.png"),
|
||||
url("chrome://browser/skin/customizableui/customizeMode-gridTexture.png"),
|
||||
|
@ -75,6 +79,7 @@ toolbarpaletteitem[place="panel"] {
|
|||
transition: transform .3s ease-in-out;
|
||||
}
|
||||
|
||||
toolbarpaletteitem[notransition].panel-customization-placeholder,
|
||||
toolbarpaletteitem[notransition][place="palette"],
|
||||
toolbarpaletteitem[notransition][place="panel"] {
|
||||
transition: none;
|
||||
|
|
|
@ -6,8 +6,8 @@
|
|||
|
||||
%define menuPanelWidth 22.35em
|
||||
%define exitSubviewGutterWidth 38px
|
||||
%define buttonStateHover :not(:-moz-any([disabled],[open],[checked="true"],[_moz-menuactive="true"],:active)):hover
|
||||
%define buttonStateActive :not([disabled]):-moz-any([open],[checked="true"],[_moz-menuactive="true"],:hover:active)
|
||||
%define buttonStateHover :not(:-moz-any([disabled],[checked="true"],[open],:active)):hover
|
||||
%define buttonStateActive :not([disabled]):-moz-any([open],[checked="true"],:hover:active)
|
||||
|
||||
%include ../browser.inc
|
||||
|
||||
|
@ -510,7 +510,9 @@ toolbarpaletteitem[place="palette"] > #search-container {
|
|||
of 3px. */
|
||||
min-width: calc(@menuPanelWidth@ / 3 - 2px);
|
||||
max-width: calc(@menuPanelWidth@ / 3 - 2px);
|
||||
height: auto;
|
||||
/* We'd prefer to use height: auto here but it leads to layout bugs in the panel. Cope:
|
||||
1.2em for line height + 2 * .5em padding + margin on the label (2 * 2px) */
|
||||
height: calc(2.2em + 4px);
|
||||
max-height: none;
|
||||
-moz-box-orient: horizontal;
|
||||
}
|
||||
|
|
|
@ -294,7 +294,7 @@ case "$target" in
|
|||
# The build tools got moved around to different directories in
|
||||
# SDK Tools r22. Try to locate them.
|
||||
android_build_tools=""
|
||||
for suffix in android-4.3 19.0.0 18.1.0 18.0.1 18.0.0 17.0.0 android-4.2.2; do
|
||||
for suffix in android-4.4 android-4.3 android-4.2.2 19.0.0 18.1.0 18.0.1 18.0.0 17.0.0; do
|
||||
tools_directory="$android_sdk_root/build-tools/$suffix"
|
||||
if test -d "$tools_directory" ; then
|
||||
android_build_tools="$tools_directory"
|
||||
|
|
|
@ -354,7 +354,7 @@ PreallocatedProcessManagerImpl::OnNuwaReady()
|
|||
{
|
||||
NS_ASSERTION(!mIsNuwaReady, "Multiple Nuwa processes created!");
|
||||
ProcessPriorityManager::SetProcessPriority(mPreallocatedAppProcess,
|
||||
hal::PROCESS_PRIORITY_FOREGROUND);
|
||||
hal::PROCESS_PRIORITY_MASTER);
|
||||
mIsNuwaReady = true;
|
||||
if (Preferences::GetBool("dom.ipc.processPriorityManager.testMode")) {
|
||||
AutoJSContext cx;
|
||||
|
|
|
@ -300,7 +300,7 @@
|
|||
android:authorities="@ANDROID_PACKAGE_NAME@.db.tabs"
|
||||
android:permission="@ANDROID_PACKAGE_NAME@.permissions.BROWSER_PROVIDER"/>
|
||||
|
||||
<provider android:name="org.mozilla.gecko.db.HomeListsProvider"
|
||||
<provider android:name="org.mozilla.gecko.db.HomeProvider"
|
||||
android:authorities="@ANDROID_PACKAGE_NAME@.db.homelists"
|
||||
android:permission="@ANDROID_PACKAGE_NAME@.permissions.BROWSER_PROVIDER"/>
|
||||
|
||||
|
|
|
@ -24,8 +24,8 @@ public class BrowserContract {
|
|||
public static final String TABS_AUTHORITY = AppConstants.ANDROID_PACKAGE_NAME + ".db.tabs";
|
||||
public static final Uri TABS_AUTHORITY_URI = Uri.parse("content://" + TABS_AUTHORITY);
|
||||
|
||||
public static final String HOME_LISTS_AUTHORITY = AppConstants.ANDROID_PACKAGE_NAME + ".db.homelists";
|
||||
public static final Uri HOME_LISTS_AUTHORITY_URI = Uri.parse("content://" + HOME_LISTS_AUTHORITY);
|
||||
public static final String HOME_AUTHORITY = AppConstants.ANDROID_PACKAGE_NAME + ".db.home";
|
||||
public static final Uri HOME_AUTHORITY_URI = Uri.parse("content://" + HOME_AUTHORITY);
|
||||
|
||||
public static final String PARAM_PROFILE = "profile";
|
||||
public static final String PARAM_PROFILE_PATH = "profilePath";
|
||||
|
@ -288,16 +288,21 @@ public class BrowserContract {
|
|||
public static final String LAST_MODIFIED = "last_modified";
|
||||
}
|
||||
|
||||
// Data storage for custom lists on about:home
|
||||
// Data storage for dynamic panels on about:home
|
||||
@RobocopTarget
|
||||
public static final class HomeListItems implements CommonColumns, URLColumns {
|
||||
private HomeListItems() {}
|
||||
public static final Uri CONTENT_FAKE_URI = Uri.withAppendedPath(HOME_LISTS_AUTHORITY_URI, "items/fake");
|
||||
public static final Uri CONTENT_URI = Uri.withAppendedPath(HOME_LISTS_AUTHORITY_URI, "items");
|
||||
public static final class HomeItems implements CommonColumns {
|
||||
private HomeItems() {}
|
||||
public static final Uri CONTENT_FAKE_URI = Uri.withAppendedPath(HOME_AUTHORITY_URI, "items/fake");
|
||||
public static final Uri CONTENT_URI = Uri.withAppendedPath(HOME_AUTHORITY_URI, "items");
|
||||
|
||||
public static final String CONTENT_TYPE = "vnd.android.cursor.dir/homelistitem";
|
||||
public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/homelistitem";
|
||||
public static final String CONTENT_TYPE = "vnd.android.cursor.dir/homeitem";
|
||||
public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/homeitem";
|
||||
|
||||
public static final String PROVIDER_ID = "provider_id";
|
||||
public static final String DATASET_ID = "dataset_id";
|
||||
public static final String URL = "url";
|
||||
public static final String TITLE = "title";
|
||||
public static final String DESCRIPTION = "description";
|
||||
public static final String IMAGE_URL = "image_url";
|
||||
public static final String CREATED = "created";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
package org.mozilla.gecko.db;
|
||||
|
||||
import org.mozilla.gecko.R;
|
||||
import org.mozilla.gecko.db.BrowserContract.HomeListItems;
|
||||
import org.mozilla.gecko.db.BrowserContract.HomeItems;
|
||||
import org.mozilla.gecko.db.PerProfileDatabases.DatabaseHelperFactory;
|
||||
import org.mozilla.gecko.sqlite.SQLiteBridge;
|
||||
|
||||
|
@ -27,8 +27,8 @@ import android.util.Log;
|
|||
import java.io.InputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
public class HomeListsProvider extends SQLiteBridgeContentProvider {
|
||||
private static final String LOGTAG = "GeckoHomeListsProvider";
|
||||
public class HomeProvider extends SQLiteBridgeContentProvider {
|
||||
private static final String LOGTAG = "GeckoHomeProvider";
|
||||
|
||||
// This should be kept in sync with the db version in mobile/android/modules/HomeProvider.jsm
|
||||
private static int DB_VERSION = 1;
|
||||
|
@ -44,12 +44,12 @@ public class HomeListsProvider extends SQLiteBridgeContentProvider {
|
|||
static final UriMatcher URI_MATCHER = new UriMatcher(UriMatcher.NO_MATCH);
|
||||
|
||||
static {
|
||||
URI_MATCHER.addURI(BrowserContract.HOME_LISTS_AUTHORITY, "items/fake", ITEMS_FAKE);
|
||||
URI_MATCHER.addURI(BrowserContract.HOME_LISTS_AUTHORITY, "items", ITEMS);
|
||||
URI_MATCHER.addURI(BrowserContract.HOME_LISTS_AUTHORITY, "items/#", ITEMS_ID);
|
||||
URI_MATCHER.addURI(BrowserContract.HOME_AUTHORITY, "items/fake", ITEMS_FAKE);
|
||||
URI_MATCHER.addURI(BrowserContract.HOME_AUTHORITY, "items", ITEMS);
|
||||
URI_MATCHER.addURI(BrowserContract.HOME_AUTHORITY, "items/#", ITEMS_ID);
|
||||
}
|
||||
|
||||
public HomeListsProvider() {
|
||||
public HomeProvider() {
|
||||
super(LOGTAG);
|
||||
}
|
||||
|
||||
|
@ -59,10 +59,10 @@ public class HomeListsProvider extends SQLiteBridgeContentProvider {
|
|||
|
||||
switch (match) {
|
||||
case ITEMS_FAKE: {
|
||||
return HomeListItems.CONTENT_TYPE;
|
||||
return HomeItems.CONTENT_TYPE;
|
||||
}
|
||||
case ITEMS: {
|
||||
return HomeListItems.CONTENT_TYPE;
|
||||
return HomeItems.CONTENT_TYPE;
|
||||
}
|
||||
default: {
|
||||
throw new UnsupportedOperationException("Unknown type " + uri);
|
||||
|
@ -91,18 +91,19 @@ public class HomeListsProvider extends SQLiteBridgeContentProvider {
|
|||
try {
|
||||
items = new JSONArray(getRawFakeItems());
|
||||
} catch (IOException e) {
|
||||
Log.e(LOGTAG, "Error getting fake list items", e);
|
||||
Log.e(LOGTAG, "Error getting fake home items", e);
|
||||
return null;
|
||||
} catch (JSONException e) {
|
||||
Log.e(LOGTAG, "Error parsing fake-list-items.json", e);
|
||||
Log.e(LOGTAG, "Error parsing fake_home_items.json", e);
|
||||
return null;
|
||||
}
|
||||
|
||||
final String[] itemsColumns = new String[] {
|
||||
HomeListItems._ID,
|
||||
HomeListItems.PROVIDER_ID,
|
||||
HomeListItems.URL,
|
||||
HomeListItems.TITLE
|
||||
HomeItems._ID,
|
||||
HomeItems.DATASET_ID,
|
||||
HomeItems.URL,
|
||||
HomeItems.TITLE,
|
||||
HomeItems.DESCRIPTION
|
||||
};
|
||||
|
||||
final MatrixCursor c = new MatrixCursor(itemsColumns);
|
||||
|
@ -111,19 +112,20 @@ public class HomeListsProvider extends SQLiteBridgeContentProvider {
|
|||
final JSONObject item = items.getJSONObject(i);
|
||||
c.addRow(new Object[] {
|
||||
item.getInt("id"),
|
||||
item.getString("provider_id"),
|
||||
item.getString("dataset_id"),
|
||||
item.getString("url"),
|
||||
item.getString("title")
|
||||
item.getString("title"),
|
||||
item.getString("description")
|
||||
});
|
||||
} catch (JSONException e) {
|
||||
Log.e(LOGTAG, "Error creating cursor row for fake list item", e);
|
||||
Log.e(LOGTAG, "Error creating cursor row for fake home item", e);
|
||||
}
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
private String getRawFakeItems() throws IOException {
|
||||
final InputStream inputStream = getContext().getResources().openRawResource(R.raw.fake_list_items);
|
||||
final InputStream inputStream = getContext().getResources().openRawResource(R.raw.fake_home_items);
|
||||
final byte[] buffer = new byte[1024];
|
||||
StringBuilder s = new StringBuilder();
|
||||
int count;
|
|
@ -7,9 +7,10 @@ package org.mozilla.gecko.home;
|
|||
|
||||
import org.mozilla.gecko.R;
|
||||
import org.mozilla.gecko.db.BrowserContract;
|
||||
import org.mozilla.gecko.db.BrowserContract.HomeListItems;
|
||||
import org.mozilla.gecko.db.BrowserContract.HomeItems;
|
||||
import org.mozilla.gecko.home.HomePager.OnUrlOpenListener;
|
||||
import org.mozilla.gecko.home.HomeConfig.PanelConfig;
|
||||
import org.mozilla.gecko.home.PanelLayout.DatasetHandler;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.ContentResolver;
|
||||
|
@ -18,6 +19,7 @@ import android.content.res.Configuration;
|
|||
import android.database.Cursor;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.LoaderManager;
|
||||
import android.support.v4.app.LoaderManager.LoaderCallbacks;
|
||||
import android.support.v4.content.Loader;
|
||||
import android.support.v4.widget.CursorAdapter;
|
||||
|
@ -30,24 +32,38 @@ import android.widget.ListView;
|
|||
import java.util.EnumSet;
|
||||
|
||||
/**
|
||||
* Fragment that displays dynamic content specified by a PanelConfig.
|
||||
* Fragment that displays dynamic content specified by a {@code PanelConfig}.
|
||||
* The {@code DynamicPanel} UI is built based on the given {@code LayoutType}
|
||||
* and its associated list of {@code ViewConfig}.
|
||||
*
|
||||
* {@code DynamicPanel} manages all necessary Loaders to load panel datasets
|
||||
* from their respective content providers. Each panel dataset has its own
|
||||
* associated Loader. This is enforced by defining the Loader IDs based on
|
||||
* their associated dataset IDs.
|
||||
*
|
||||
* The {@code PanelLayout} can make load and reset requests on datasets via
|
||||
* the provided {@code DatasetHandler}. This way it doesn't need to know the
|
||||
* details of how datasets are loaded and reset. Each time a dataset is
|
||||
* requested, {@code DynamicPanel} restarts a Loader with the respective ID (see
|
||||
* {@code PanelDatasetHandler}).
|
||||
*
|
||||
* See {@code PanelLayout} for more details on how {@code DynamicPanel}
|
||||
* receives dataset requests and delivers them back to the {@code PanelLayout}.
|
||||
*/
|
||||
public class DynamicPanel extends HomeFragment {
|
||||
private static final String LOGTAG = "GeckoDynamicPanel";
|
||||
|
||||
// Cursor loader ID for the lists
|
||||
private static final int LOADER_ID_LIST = 0;
|
||||
// Dataset ID to be used by the loader
|
||||
private static final String DATASET_ID = "dataset_id";
|
||||
|
||||
// The panel layout associated with this panel
|
||||
private PanelLayout mLayout;
|
||||
|
||||
// The configuration associated with this panel
|
||||
private PanelConfig mPanelConfig;
|
||||
|
||||
// XXX: Right now DynamicPanel is hard-coded to show a single ListView,
|
||||
// but it should dynamically build views from mPanelConfig (bug 959777).
|
||||
private HomeListAdapter mAdapter;
|
||||
private ListView mList;
|
||||
|
||||
// Callbacks used for the list loader
|
||||
private CursorLoaderCallbacks mCursorLoaderCallbacks;
|
||||
// Callbacks used for the loader
|
||||
private PanelLoaderCallbacks mLoaderCallbacks;
|
||||
|
||||
// On URL open listener
|
||||
private OnUrlOpenListener mUrlOpenListener;
|
||||
|
@ -87,22 +103,30 @@ public class DynamicPanel extends HomeFragment {
|
|||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
// XXX: Dynamically build views from mPanelConfig (bug 959777).
|
||||
mList = new HomeListView(getActivity());
|
||||
return mList;
|
||||
switch(mPanelConfig.getLayoutType()) {
|
||||
case FRAME:
|
||||
final PanelDatasetHandler datasetHandler = new PanelDatasetHandler();
|
||||
mLayout = new FramePanelLayout(getActivity(), mPanelConfig, datasetHandler);
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new IllegalStateException("Unrecognized layout type in DynamicPanel");
|
||||
}
|
||||
|
||||
Log.d(LOGTAG, "Created layout of type: " + mPanelConfig.getLayoutType());
|
||||
|
||||
return mLayout;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewCreated(View view, Bundle savedInstanceState) {
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
|
||||
registerForContextMenu(mList);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
super.onDestroyView();
|
||||
mList = null;
|
||||
mLayout = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -122,29 +146,73 @@ public class DynamicPanel extends HomeFragment {
|
|||
public void onActivityCreated(Bundle savedInstanceState) {
|
||||
super.onActivityCreated(savedInstanceState);
|
||||
|
||||
// XXX: Dynamically set adapters from mPanelConfig (bug 959777).
|
||||
mAdapter = new HomeListAdapter(getActivity(), null);
|
||||
mList.setAdapter(mAdapter);
|
||||
|
||||
// Create callbacks before the initial loader is started.
|
||||
mCursorLoaderCallbacks = new CursorLoaderCallbacks();
|
||||
mLoaderCallbacks = new PanelLoaderCallbacks();
|
||||
loadIfVisible();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void load() {
|
||||
getLoaderManager().initLoader(LOADER_ID_LIST, null, mCursorLoaderCallbacks);
|
||||
Log.d(LOGTAG, "Loading layout");
|
||||
mLayout.load();
|
||||
}
|
||||
|
||||
private static int generateLoaderId(String datasetId) {
|
||||
return datasetId.hashCode();
|
||||
}
|
||||
|
||||
/**
|
||||
* Cursor loader for the lists.
|
||||
* Used by the PanelLayout to make load and reset requests to
|
||||
* the holding fragment.
|
||||
*/
|
||||
private static class HomeListLoader extends SimpleCursorLoader {
|
||||
private String mProviderId;
|
||||
private class PanelDatasetHandler implements DatasetHandler {
|
||||
@Override
|
||||
public void requestDataset(String datasetId) {
|
||||
Log.d(LOGTAG, "Requesting dataset: " + datasetId);
|
||||
|
||||
public HomeListLoader(Context context, String providerId) {
|
||||
// Ignore dataset requests while the fragment is not
|
||||
// allowed to load its content.
|
||||
if (!getCanLoadHint()) {
|
||||
return;
|
||||
}
|
||||
|
||||
final Bundle bundle = new Bundle();
|
||||
bundle.putString(DATASET_ID, datasetId);
|
||||
|
||||
// Ensure one loader per dataset
|
||||
final int loaderId = generateLoaderId(datasetId);
|
||||
getLoaderManager().restartLoader(loaderId, bundle, mLoaderCallbacks);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resetDataset(String datasetId) {
|
||||
Log.d(LOGTAG, "Resetting dataset: " + datasetId);
|
||||
|
||||
final LoaderManager lm = getLoaderManager();
|
||||
final int loaderId = generateLoaderId(datasetId);
|
||||
|
||||
// Release any resources associated with the dataset if
|
||||
// it's currently loaded in memory.
|
||||
final Loader<?> datasetLoader = lm.getLoader(loaderId);
|
||||
if (datasetLoader != null) {
|
||||
datasetLoader.reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Cursor loader for the panel datasets.
|
||||
*/
|
||||
private static class PanelDatasetLoader extends SimpleCursorLoader {
|
||||
private final String mDatasetId;
|
||||
|
||||
public PanelDatasetLoader(Context context, String datasetId) {
|
||||
super(context);
|
||||
mProviderId = providerId;
|
||||
mDatasetId = datasetId;
|
||||
}
|
||||
|
||||
public String getDatasetId() {
|
||||
return mDatasetId;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -152,55 +220,45 @@ public class DynamicPanel extends HomeFragment {
|
|||
final ContentResolver cr = getContext().getContentResolver();
|
||||
|
||||
// XXX: Use the test URI for static fake data
|
||||
final Uri fakeItemsUri = HomeListItems.CONTENT_FAKE_URI.buildUpon().
|
||||
final Uri fakeItemsUri = HomeItems.CONTENT_FAKE_URI.buildUpon().
|
||||
appendQueryParameter(BrowserContract.PARAM_PROFILE, "default").build();
|
||||
|
||||
final String selection = HomeListItems.PROVIDER_ID + " = ?";
|
||||
final String[] selectionArgs = new String[] { mProviderId };
|
||||
final String selection = HomeItems.DATASET_ID + " = ?";
|
||||
final String[] selectionArgs = new String[] { mDatasetId };
|
||||
|
||||
Log.i(LOGTAG, "Loading fake data for list provider: " + mProviderId);
|
||||
Log.i(LOGTAG, "Loading fake data for list provider: " + mDatasetId);
|
||||
|
||||
return cr.query(fakeItemsUri, null, selection, selectionArgs, null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Cursor adapter for the list.
|
||||
*/
|
||||
private class HomeListAdapter extends CursorAdapter {
|
||||
public HomeListAdapter(Context context, Cursor cursor) {
|
||||
super(context, cursor, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bindView(View view, Context context, Cursor cursor) {
|
||||
final TwoLinePageRow row = (TwoLinePageRow) view;
|
||||
row.updateFromCursor(cursor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public View newView(Context context, Cursor cursor, ViewGroup parent) {
|
||||
return LayoutInflater.from(parent.getContext()).inflate(R.layout.bookmark_item_row, parent, false);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* LoaderCallbacks implementation that interacts with the LoaderManager.
|
||||
*/
|
||||
private class CursorLoaderCallbacks implements LoaderCallbacks<Cursor> {
|
||||
private class PanelLoaderCallbacks implements LoaderCallbacks<Cursor> {
|
||||
@Override
|
||||
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
|
||||
return new HomeListLoader(getActivity(), mPanelConfig.getId());
|
||||
final String datasetId = args.getString(DATASET_ID);
|
||||
|
||||
Log.d(LOGTAG, "Creating loader for dataset: " + datasetId);
|
||||
return new PanelDatasetLoader(getActivity(), datasetId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoadFinished(Loader<Cursor> loader, Cursor c) {
|
||||
mAdapter.swapCursor(c);
|
||||
public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
|
||||
final PanelDatasetLoader datasetLoader = (PanelDatasetLoader) loader;
|
||||
|
||||
Log.d(LOGTAG, "Finished loader for dataset: " + datasetLoader.getDatasetId());
|
||||
mLayout.deliverDataset(datasetLoader.getDatasetId(), cursor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoaderReset(Loader<Cursor> loader) {
|
||||
mAdapter.swapCursor(null);
|
||||
final PanelDatasetLoader datasetLoader = (PanelDatasetLoader) loader;
|
||||
Log.d(LOGTAG, "Resetting loader for dataset: " + datasetLoader.getDatasetId());
|
||||
if (mLayout != null) {
|
||||
mLayout.releaseDataset(datasetLoader.getDatasetId());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
package org.mozilla.gecko.home;
|
||||
|
||||
import org.mozilla.gecko.home.HomeConfig.PanelConfig;
|
||||
import org.mozilla.gecko.home.HomeConfig.ViewConfig;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
|
||||
class FramePanelLayout extends PanelLayout {
|
||||
private static final String LOGTAG = "GeckoFramePanelLayout";
|
||||
|
||||
private final View mChildView;
|
||||
private final ViewConfig mChildConfig;
|
||||
|
||||
public FramePanelLayout(Context context, PanelConfig panelConfig, DatasetHandler datasetHandler) {
|
||||
super(context, panelConfig, datasetHandler);
|
||||
|
||||
// This layout can only hold one view so we simply
|
||||
// take the first defined view from PanelConfig.
|
||||
mChildConfig = panelConfig.getViewAt(0);
|
||||
if (mChildConfig == null) {
|
||||
throw new IllegalStateException("FramePanelLayout requires a view in PanelConfig");
|
||||
}
|
||||
|
||||
mChildView = createPanelView(mChildConfig);
|
||||
addView(mChildView);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void load() {
|
||||
Log.d(LOGTAG, "Loading");
|
||||
|
||||
if (mChildView instanceof DatasetBacked) {
|
||||
Log.d(LOGTAG, "Requesting child dataset: " + mChildConfig.getDatasetId());
|
||||
requestDataset(mChildConfig.getDatasetId());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,227 @@
|
|||
/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
package org.mozilla.gecko.home;
|
||||
|
||||
import org.mozilla.gecko.home.HomeConfig.PanelConfig;
|
||||
import org.mozilla.gecko.home.HomeConfig.ViewConfig;
|
||||
|
||||
import android.content.Context;
|
||||
import android.database.Cursor;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.widget.FrameLayout;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* {@code PanelLayout} is the base class for custom layouts to be
|
||||
* used in {@code DynamicPanel}. It provides the basic framework
|
||||
* that enables custom layouts to request and reset datasets and
|
||||
* create panel views. Furthermore, it automates most of the process
|
||||
* of binding panel views with their respective datasets.
|
||||
*
|
||||
* {@code PanelLayout} abstracts the implemention details of how
|
||||
* datasets are actually loaded through the {@DatasetHandler} interface.
|
||||
* {@code DatasetHandler} provides two operations: request and reset.
|
||||
* The results of the dataset requests done via the {@code DatasetHandler}
|
||||
* are delivered to the {@code PanelLayout} with the {@code deliverDataset()}
|
||||
* method.
|
||||
*
|
||||
* Subclasses of {@code PanelLayout} should simply use the utilities
|
||||
* provided by {@code PanelLayout}. Namely:
|
||||
*
|
||||
* {@code requestDataset()} - To fetch datasets and auto-bind them to
|
||||
* the existing panel views backed by them.
|
||||
*
|
||||
* {@code resetDataset()} - To release any resources associated with a
|
||||
* previously loaded dataset.
|
||||
*
|
||||
* {@code createPanelView()} - To create a panel view for a ViewConfig
|
||||
* associated with the panel.
|
||||
*
|
||||
* {@code disposePanelView()} - To dispose any dataset references associated
|
||||
* with the given view.
|
||||
*
|
||||
* {@code PanelLayout} subclasses should always use {@code createPanelView()}
|
||||
* to create the views dynamically created based on {@code ViewConfig}. This
|
||||
* allows {@code PanelLayout} to auto-bind datasets with panel views.
|
||||
* {@code PanelLayout} subclasses are free to have any type of views to arrange
|
||||
* the panel views in different ways.
|
||||
*/
|
||||
abstract class PanelLayout extends FrameLayout {
|
||||
private static final String LOGTAG = "GeckoPanelLayout";
|
||||
|
||||
private final List<ViewEntry> mViewEntries;
|
||||
private final DatasetHandler mDatasetHandler;
|
||||
|
||||
/**
|
||||
* To be used by panel views to express that they are
|
||||
* backed by datasets.
|
||||
*/
|
||||
public interface DatasetBacked {
|
||||
public void setDataset(Cursor cursor);
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines the contract with the component that is responsible
|
||||
* for handling datasets requests.
|
||||
*/
|
||||
public interface DatasetHandler {
|
||||
/**
|
||||
* Requests a dataset to be fetched and auto-bound to the
|
||||
* panel views backed by it.
|
||||
*/
|
||||
public void requestDataset(String datasetId);
|
||||
|
||||
/**
|
||||
* Releases any resources associated with a previously loaded
|
||||
* dataset. It will do nothing if the dataset with the given ID
|
||||
* hasn't been loaded before.
|
||||
*/
|
||||
public void resetDataset(String datasetId);
|
||||
}
|
||||
|
||||
public PanelLayout(Context context, PanelConfig panelConfig, DatasetHandler datasetHandler) {
|
||||
super(context);
|
||||
mViewEntries = new ArrayList<ViewEntry>();
|
||||
mDatasetHandler = datasetHandler;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delivers the dataset as a {@code Cursor} to be bound to the
|
||||
* panel views backed by it. This is used by the {@code DatasetHandler}
|
||||
* in response to a dataset request.
|
||||
*/
|
||||
public final void deliverDataset(String datasetId, Cursor cursor) {
|
||||
Log.d(LOGTAG, "Delivering dataset: " + datasetId);
|
||||
updateViewsWithDataset(datasetId, cursor);
|
||||
}
|
||||
|
||||
/**
|
||||
* Releases any references to the given dataset from all
|
||||
* existing panel views.
|
||||
*/
|
||||
public final void releaseDataset(String datasetId) {
|
||||
Log.d(LOGTAG, "Resetting dataset: " + datasetId);
|
||||
updateViewsWithDataset(datasetId, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Requests a dataset to be loaded and bound to any existing
|
||||
* panel view backed by it.
|
||||
*/
|
||||
protected final void requestDataset(String datasetId) {
|
||||
Log.d(LOGTAG, "Requesting dataset: " + datasetId);
|
||||
mDatasetHandler.requestDataset(datasetId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Releases any resources associated with a previously
|
||||
* loaded dataset e.g. close any associated {@code Cursor}.
|
||||
*/
|
||||
protected final void resetDataset(String datasetId) {
|
||||
mDatasetHandler.resetDataset(datasetId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Factory method to create instance of panels from a given
|
||||
* {@code ViewConfig}. All panel views defined in {@code PanelConfig}
|
||||
* should be created using this method so that {@PanelLayout} can
|
||||
* keep track of panel views and their associated datasets.
|
||||
*/
|
||||
protected final View createPanelView(ViewConfig viewConfig) {
|
||||
final View view;
|
||||
|
||||
Log.d(LOGTAG, "Creating panel view: " + viewConfig.getType());
|
||||
|
||||
switch(viewConfig.getType()) {
|
||||
case LIST:
|
||||
view = new PanelListView(getContext(), viewConfig);
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new IllegalStateException("Unrecognized view type in " + getClass().getSimpleName());
|
||||
}
|
||||
|
||||
final ViewEntry entry = new ViewEntry(view, viewConfig);
|
||||
mViewEntries.add(entry);
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
/**
|
||||
* Dispose any dataset references associated with the
|
||||
* given view.
|
||||
*/
|
||||
protected final void disposePanelView(View view) {
|
||||
Log.d(LOGTAG, "Disposing panel view");
|
||||
|
||||
final int count = mViewEntries.size();
|
||||
for (int i = 0; i < count; i++) {
|
||||
final View entryView = mViewEntries.get(i).getView();
|
||||
if (view == entryView) {
|
||||
// Release any Cursor references from the view
|
||||
// if it's backed by a dataset.
|
||||
maybeSetDataset(entryView, null);
|
||||
|
||||
// Remove the view entry from the list
|
||||
mViewEntries.remove(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void updateViewsWithDataset(String datasetId, Cursor cursor) {
|
||||
final int count = mViewEntries.size();
|
||||
for (int i = 0; i < count; i++) {
|
||||
final ViewEntry entry = mViewEntries.get(i);
|
||||
|
||||
// Update any views associated with the given dataset ID
|
||||
if (TextUtils.equals(entry.getDatasetId(), datasetId)) {
|
||||
final View view = entry.getView();
|
||||
maybeSetDataset(view, cursor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void maybeSetDataset(View view, Cursor cursor) {
|
||||
if (view instanceof DatasetBacked) {
|
||||
final DatasetBacked dsb = (DatasetBacked) view;
|
||||
dsb.setDataset(cursor);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Must be implemented by {@code PanelLayout} subclasses to define
|
||||
* what happens then the layout is first loaded. Should set initial
|
||||
* UI state and request any necessary datasets.
|
||||
*/
|
||||
public abstract void load();
|
||||
|
||||
/**
|
||||
* Represents a 'live' instance of a panel view associated with
|
||||
* the {@code PanelLayout}.
|
||||
*/
|
||||
private static class ViewEntry {
|
||||
private final View mView;
|
||||
private final ViewConfig mViewConfig;
|
||||
|
||||
public ViewEntry(View view, ViewConfig viewConfig) {
|
||||
mView = view;
|
||||
mViewConfig = viewConfig;
|
||||
}
|
||||
|
||||
public View getView() {
|
||||
return mView;
|
||||
}
|
||||
|
||||
public String getDatasetId() {
|
||||
return mViewConfig.getDatasetId();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,60 @@
|
|||
/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
package org.mozilla.gecko.home;
|
||||
|
||||
import android.util.Log;
|
||||
import org.mozilla.gecko.favicons.Favicons;
|
||||
import org.mozilla.gecko.R;
|
||||
import org.mozilla.gecko.Tab;
|
||||
import org.mozilla.gecko.Tabs;
|
||||
import org.mozilla.gecko.db.BrowserContract.Combined;
|
||||
import org.mozilla.gecko.db.BrowserDB.URLColumns;
|
||||
import org.mozilla.gecko.favicons.OnFaviconLoadedListener;
|
||||
import org.mozilla.gecko.util.ThreadUtils;
|
||||
import org.mozilla.gecko.widget.FaviconView;
|
||||
|
||||
import android.content.Context;
|
||||
import android.database.Cursor;
|
||||
import android.graphics.Bitmap;
|
||||
import android.text.TextUtils;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
|
||||
public class PanelListRow extends TwoLineRow {
|
||||
|
||||
public PanelListRow(Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
public PanelListRow(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
|
||||
// XXX: Never show icon for now. We have to figure out
|
||||
// how the images will be passed through the cursor.
|
||||
final View iconView = findViewById(R.id.icon);
|
||||
iconView.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateFromCursor(Cursor cursor) {
|
||||
if (cursor == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// XXX: This will have to be updated once we come up with the
|
||||
// final schema for Panel datasets (see bug 942288).
|
||||
|
||||
int titleIndex = cursor.getColumnIndexOrThrow(URLColumns.TITLE);
|
||||
final String title = cursor.getString(titleIndex);
|
||||
setPrimaryText(title);
|
||||
|
||||
int urlIndex = cursor.getColumnIndexOrThrow(URLColumns.URL);
|
||||
final String url = cursor.getString(urlIndex);
|
||||
setSecondaryText(url);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
package org.mozilla.gecko.home;
|
||||
|
||||
import org.mozilla.gecko.R;
|
||||
import org.mozilla.gecko.home.HomeConfig.ViewConfig;
|
||||
import org.mozilla.gecko.home.PanelLayout.DatasetBacked;
|
||||
|
||||
import android.content.Context;
|
||||
import android.database.Cursor;
|
||||
import android.support.v4.widget.CursorAdapter;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
public class PanelListView extends HomeListView
|
||||
implements DatasetBacked {
|
||||
|
||||
private static final String LOGTAG = "GeckoPanelListView";
|
||||
|
||||
private final PanelListAdapter mAdapter;
|
||||
private final ViewConfig mViewConfig;
|
||||
|
||||
public PanelListView(Context context, ViewConfig viewConfig) {
|
||||
super(context);
|
||||
mViewConfig = viewConfig;
|
||||
mAdapter = new PanelListAdapter(context);
|
||||
setAdapter(mAdapter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDataset(Cursor cursor) {
|
||||
Log.d(LOGTAG, "Setting dataset: " + mViewConfig.getDatasetId());
|
||||
mAdapter.swapCursor(cursor);
|
||||
}
|
||||
|
||||
private class PanelListAdapter extends CursorAdapter {
|
||||
public PanelListAdapter(Context context) {
|
||||
super(context, null, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bindView(View view, Context context, Cursor cursor) {
|
||||
final PanelListRow row = (PanelListRow) view;
|
||||
row.updateFromCursor(cursor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public View newView(Context context, Cursor cursor, ViewGroup parent) {
|
||||
return LayoutInflater.from(parent.getContext()).inflate(R.layout.panel_list_row, parent, false);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -21,23 +21,14 @@ import android.database.Cursor;
|
|||
import android.graphics.Bitmap;
|
||||
import android.text.TextUtils;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.Gravity;
|
||||
import android.view.LayoutInflater;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
|
||||
public class TwoLinePageRow extends LinearLayout
|
||||
public class TwoLinePageRow extends TwoLineRow
|
||||
implements Tabs.OnTabsChangedListener {
|
||||
private static final int NO_ICON = 0;
|
||||
|
||||
private final TextView mTitle;
|
||||
private final TextView mUrl;
|
||||
private final FaviconView mFavicon;
|
||||
|
||||
private int mUrlIconId;
|
||||
private int mBookmarkIconId;
|
||||
private boolean mShowIcons;
|
||||
private int mLoadFaviconJobId = Favicons.NOT_LOADING;
|
||||
|
||||
|
@ -79,16 +70,9 @@ public class TwoLinePageRow extends LinearLayout
|
|||
public TwoLinePageRow(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
|
||||
setGravity(Gravity.CENTER_VERTICAL);
|
||||
|
||||
mUrlIconId = NO_ICON;
|
||||
mBookmarkIconId = NO_ICON;
|
||||
mShowIcons = true;
|
||||
|
||||
LayoutInflater.from(context).inflate(R.layout.two_line_page_row, this);
|
||||
mTitle = (TextView) findViewById(R.id.title);
|
||||
mUrl = (TextView) findViewById(R.id.url);
|
||||
mFavicon = (FaviconView) findViewById(R.id.favicon);
|
||||
mFavicon = (FaviconView) findViewById(R.id.icon);
|
||||
mFaviconListener = new UpdateViewFaviconLoadedListener(mFavicon);
|
||||
}
|
||||
|
||||
|
@ -120,36 +104,6 @@ public class TwoLinePageRow extends LinearLayout
|
|||
}
|
||||
}
|
||||
|
||||
private void setTitle(String title) {
|
||||
mTitle.setText(title);
|
||||
}
|
||||
|
||||
private void setUrl(String url) {
|
||||
mUrl.setText(url);
|
||||
}
|
||||
|
||||
private void setUrl(int stringId) {
|
||||
mUrl.setText(stringId);
|
||||
}
|
||||
|
||||
private void setUrlIcon(int urlIconId) {
|
||||
if (mUrlIconId == urlIconId) {
|
||||
return;
|
||||
}
|
||||
|
||||
mUrlIconId = urlIconId;
|
||||
mUrl.setCompoundDrawablesWithIntrinsicBounds(mUrlIconId, 0, mBookmarkIconId, 0);
|
||||
}
|
||||
|
||||
private void setBookmarkIcon(int bookmarkIconId) {
|
||||
if (mBookmarkIconId == bookmarkIconId) {
|
||||
return;
|
||||
}
|
||||
|
||||
mBookmarkIconId = bookmarkIconId;
|
||||
mUrl.setCompoundDrawablesWithIntrinsicBounds(mUrlIconId, 0, mBookmarkIconId, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores the page URL, so that we can use it to replace "Switch to tab" if the open
|
||||
* tab changes or is closed.
|
||||
|
@ -168,11 +122,11 @@ public class TwoLinePageRow extends LinearLayout
|
|||
boolean isPrivate = Tabs.getInstance().getSelectedTab().isPrivate();
|
||||
int tabId = Tabs.getInstance().getTabIdForUrl(mPageUrl, isPrivate);
|
||||
if (!mShowIcons || tabId < 0) {
|
||||
setUrl(mPageUrl);
|
||||
setUrlIcon(NO_ICON);
|
||||
setSecondaryText(mPageUrl);
|
||||
setSecondaryIcon(NO_ICON);
|
||||
} else {
|
||||
setUrl(R.string.switch_to_tab);
|
||||
setUrlIcon(R.drawable.ic_url_bar_tab);
|
||||
setSecondaryText(R.string.switch_to_tab);
|
||||
setSecondaryIcon(R.drawable.ic_url_bar_tab);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -180,6 +134,7 @@ public class TwoLinePageRow extends LinearLayout
|
|||
mShowIcons = showIcons;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateFromCursor(Cursor cursor) {
|
||||
if (cursor == null) {
|
||||
return;
|
||||
|
@ -207,20 +162,20 @@ public class TwoLinePageRow extends LinearLayout
|
|||
// The bookmark id will be 0 (null in database) when the url
|
||||
// is not a bookmark.
|
||||
if (bookmarkId == 0) {
|
||||
setBookmarkIcon(NO_ICON);
|
||||
setPrimaryIcon(NO_ICON);
|
||||
} else if (display == Combined.DISPLAY_READER) {
|
||||
setBookmarkIcon(R.drawable.ic_url_bar_reader);
|
||||
setPrimaryIcon(R.drawable.ic_url_bar_reader);
|
||||
} else {
|
||||
setBookmarkIcon(R.drawable.ic_url_bar_star);
|
||||
setPrimaryIcon(R.drawable.ic_url_bar_star);
|
||||
}
|
||||
} else {
|
||||
setBookmarkIcon(NO_ICON);
|
||||
setPrimaryIcon(NO_ICON);
|
||||
}
|
||||
}
|
||||
|
||||
// Use the URL instead of an empty title for consistency with the normal URL
|
||||
// bar view - this is the equivalent of getDisplayTitle() in Tab.java
|
||||
setTitle(TextUtils.isEmpty(title) ? url : title);
|
||||
setPrimaryText(TextUtils.isEmpty(title) ? url : title);
|
||||
|
||||
// No point updating the below things if URL has not changed. Prevents evil Favicon flicker.
|
||||
if (url.equals(mPageUrl)) {
|
||||
|
|
|
@ -0,0 +1,77 @@
|
|||
/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
package org.mozilla.gecko.home;
|
||||
|
||||
import org.mozilla.gecko.R;
|
||||
|
||||
import android.content.Context;
|
||||
import android.database.Cursor;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.Gravity;
|
||||
import android.view.LayoutInflater;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
|
||||
public abstract class TwoLineRow extends LinearLayout {
|
||||
protected static final int NO_ICON = 0;
|
||||
|
||||
private final TextView mPrimaryText;
|
||||
private int mPrimaryIconId;
|
||||
|
||||
private final TextView mSecondaryText;
|
||||
private int mSecondaryIconId;
|
||||
|
||||
public TwoLineRow(Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
public TwoLineRow(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
|
||||
setGravity(Gravity.CENTER_VERTICAL);
|
||||
|
||||
mSecondaryIconId = NO_ICON;
|
||||
mPrimaryIconId = NO_ICON;
|
||||
|
||||
LayoutInflater.from(context).inflate(R.layout.two_line_row, this);
|
||||
mPrimaryText = (TextView) findViewById(R.id.primary_text);
|
||||
mSecondaryText = (TextView) findViewById(R.id.secondary_text);
|
||||
}
|
||||
|
||||
protected void setPrimaryText(String text) {
|
||||
mPrimaryText.setText(text);
|
||||
}
|
||||
|
||||
protected void setSecondaryText(String text) {
|
||||
mSecondaryText.setText(text);
|
||||
}
|
||||
|
||||
protected void setSecondaryText(int stringId) {
|
||||
mSecondaryText.setText(stringId);
|
||||
}
|
||||
|
||||
protected void setPrimaryIcon(int iconId) {
|
||||
if (mPrimaryIconId == iconId) {
|
||||
return;
|
||||
}
|
||||
|
||||
mPrimaryIconId = iconId;
|
||||
mSecondaryText.setCompoundDrawablesWithIntrinsicBounds(mSecondaryIconId, 0, mPrimaryIconId, 0);
|
||||
}
|
||||
|
||||
protected void setSecondaryIcon(int iconId) {
|
||||
if (mSecondaryIconId == iconId) {
|
||||
return;
|
||||
}
|
||||
|
||||
mSecondaryIconId = iconId;
|
||||
mSecondaryText.setCompoundDrawablesWithIntrinsicBounds(mSecondaryIconId, 0, mPrimaryIconId, 0);
|
||||
}
|
||||
|
||||
public abstract void updateFromCursor(Cursor cursor);
|
||||
}
|
|
@ -115,7 +115,7 @@ gbjar.sources += [
|
|||
'db/BrowserProvider.java',
|
||||
'db/DBUtils.java',
|
||||
'db/FormHistoryProvider.java',
|
||||
'db/HomeListsProvider.java',
|
||||
'db/HomeProvider.java',
|
||||
'db/LocalBrowserDB.java',
|
||||
'db/PasswordsProvider.java',
|
||||
'db/PerProfileDatabases.java',
|
||||
|
@ -215,6 +215,7 @@ gbjar.sources += [
|
|||
'home/BrowserSearch.java',
|
||||
'home/DynamicPanel.java',
|
||||
'home/FadedTextView.java',
|
||||
'home/FramePanelLayout.java',
|
||||
'home/HistoryPanel.java',
|
||||
'home/HomeAdapter.java',
|
||||
'home/HomeBanner.java',
|
||||
|
@ -228,6 +229,9 @@ gbjar.sources += [
|
|||
'home/LastTabsPanel.java',
|
||||
'home/MostRecentPanel.java',
|
||||
'home/MultiTypeCursorAdapter.java',
|
||||
'home/PanelLayout.java',
|
||||
'home/PanelListRow.java',
|
||||
'home/PanelListView.java',
|
||||
'home/PanelManager.java',
|
||||
'home/PinSiteDialog.java',
|
||||
'home/ReadingListPanel.java',
|
||||
|
@ -242,6 +246,7 @@ gbjar.sources += [
|
|||
'home/TopSitesPanel.java',
|
||||
'home/TopSitesThumbnailView.java',
|
||||
'home/TwoLinePageRow.java',
|
||||
'home/TwoLineRow.java',
|
||||
'InputMethods.java',
|
||||
'JavaAddonManager.java',
|
||||
'LightweightTheme.java',
|
||||
|
|
|
@ -20,17 +20,13 @@ public class PanelsPreference extends CustomListPreference {
|
|||
private static final int INDEX_SHOW_BUTTON = 1;
|
||||
private static final int INDEX_REMOVE_BUTTON = 2;
|
||||
|
||||
private final String LABEL_HIDE;
|
||||
private final String LABEL_SHOW;
|
||||
private String LABEL_HIDE;
|
||||
private String LABEL_SHOW;
|
||||
|
||||
protected boolean mIsHidden = false;
|
||||
|
||||
public PanelsPreference(Context context, CustomListCategory parentCategory) {
|
||||
super(context, parentCategory);
|
||||
|
||||
Resources res = getContext().getResources();
|
||||
LABEL_HIDE = res.getString(R.string.pref_panels_hide);
|
||||
LABEL_SHOW = res.getString(R.string.pref_panels_show);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -56,6 +52,9 @@ public class PanelsPreference extends CustomListPreference {
|
|||
@Override
|
||||
protected String[] getDialogStrings() {
|
||||
Resources res = getContext().getResources();
|
||||
LABEL_HIDE = res.getString(R.string.pref_panels_hide);
|
||||
LABEL_SHOW = res.getString(R.string.pref_panels_show);
|
||||
|
||||
// XXX: Don't provide the "Remove" string for now, because we only support built-in
|
||||
// panels, which can only be disabled.
|
||||
return new String[] { LABEL_SET_AS_DEFAULT,
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- This Source Code Form is subject to the terms of the Mozilla Public
|
||||
- License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
|
||||
|
||||
<org.mozilla.gecko.home.PanelListRow xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="@dimen/page_row_height"
|
||||
android:paddingLeft="10dip"
|
||||
android:minHeight="@dimen/page_row_height"/>
|
|
@ -6,7 +6,7 @@
|
|||
<merge xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:gecko="http://schemas.android.com/apk/res-auto">
|
||||
|
||||
<org.mozilla.gecko.widget.FaviconView android:id="@+id/favicon"
|
||||
<org.mozilla.gecko.widget.FaviconView android:id="@+id/icon"
|
||||
android:layout_width="@dimen/favicon_bg"
|
||||
android:layout_height="@dimen/favicon_bg"
|
||||
android:layout_marginLeft="10dip"
|
||||
|
@ -18,14 +18,14 @@
|
|||
android:orientation="vertical">
|
||||
|
||||
<org.mozilla.gecko.home.FadedTextView
|
||||
android:id="@+id/title"
|
||||
style="@style/Widget.TwoLinePageRow.Title"
|
||||
android:id="@+id/primary_text"
|
||||
style="@style/Widget.TwoLineRow.PrimaryText"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
gecko:fadeWidth="30dp"/>
|
||||
|
||||
<TextView android:id="@+id/url"
|
||||
style="@style/Widget.TwoLinePageRow.Url"
|
||||
<TextView android:id="@+id/secondary_text"
|
||||
style="@style/Widget.TwoLineRow.SecondaryText"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:drawablePadding="5dp"
|
|
@ -0,0 +1,13 @@
|
|||
[{
|
||||
"id": 1,
|
||||
"dataset_id": "fake-dataset",
|
||||
"url": "http://example.com/first",
|
||||
"title": "First Example",
|
||||
"description": "This is an example"
|
||||
}, {
|
||||
"id": 2,
|
||||
"dataset_id": "fake-dataset",
|
||||
"url": "http://example.com/second",
|
||||
"title": "Second Example",
|
||||
"description": "This is a second example"
|
||||
}]
|
|
@ -1,11 +0,0 @@
|
|||
[{
|
||||
"id": 1,
|
||||
"provider_id": "fake-provider",
|
||||
"url": "http://example.com",
|
||||
"title": "Example"
|
||||
}, {
|
||||
"id": 2,
|
||||
"provider_id": "fake-provider",
|
||||
"url": "http://mozilla.org",
|
||||
"title": "Mozilla"
|
||||
}]
|
|
@ -9,13 +9,13 @@
|
|||
<item name="android:orientation">vertical</item>
|
||||
</style>
|
||||
|
||||
<style name="Widget.BookmarkFolderView" parent="Widget.TwoLinePageRow.Title">
|
||||
<style name="Widget.BookmarkFolderView" parent="Widget.TwoLineRow.PrimaryText">
|
||||
<item name="android:paddingLeft">60dip</item>
|
||||
<item name="android:drawablePadding">10dip</item>
|
||||
<item name="android:drawableLeft">@drawable/bookmark_folder</item>
|
||||
</style>
|
||||
|
||||
<style name="Widget.BookmarkItemView" parent="Widget.TwoLinePageRow">
|
||||
<style name="Widget.BookmarkItemView" parent="Widget.TwoLineRow">
|
||||
<item name="android:paddingLeft">50dp</item>
|
||||
<item name="android:paddingRight">50dp</item>
|
||||
</style>
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
<item name="android:fontFamily">sans-serif-light</item>
|
||||
</style>
|
||||
|
||||
<style name="TextAppearance.Widget.TwoLinePageRow.Title" parent="TextAppearance.Medium">
|
||||
<style name="TextAppearance.Widget.TwoLineRow.PrimaryText" parent="TextAppearance.Medium">
|
||||
<item name="android:fontFamily">sans-serif-light</item>
|
||||
</style>
|
||||
|
||||
|
|
|
@ -109,22 +109,22 @@
|
|||
<item name="android:ellipsize">middle</item>
|
||||
</style>
|
||||
|
||||
<style name="Widget.TwoLinePageRow" />
|
||||
<style name="Widget.TwoLineRow" />
|
||||
|
||||
<style name="Widget.TwoLinePageRow.Title">
|
||||
<item name="android:textAppearance">@style/TextAppearance.Widget.TwoLinePageRow.Title</item>
|
||||
<style name="Widget.TwoLineRow.PrimaryText">
|
||||
<item name="android:textAppearance">@style/TextAppearance.Widget.TwoLineRow.PrimaryText</item>
|
||||
<item name="android:singleLine">true</item>
|
||||
<item name="android:ellipsize">none</item>
|
||||
</style>
|
||||
|
||||
<style name="Widget.TwoLinePageRow.Url">
|
||||
<item name="android:textAppearance">@style/TextAppearance.Widget.TwoLinePageRow.Url</item>
|
||||
<style name="Widget.TwoLineRow.SecondaryText">
|
||||
<item name="android:textAppearance">@style/TextAppearance.Widget.TwoLineRow.SecondaryText</item>
|
||||
<item name="android:includeFontPadding">false</item>
|
||||
<item name="android:singleLine">true</item>
|
||||
<item name="android:ellipsize">middle</item>
|
||||
</style>
|
||||
|
||||
<style name="Widget.BookmarkFolderView" parent="Widget.TwoLinePageRow.Title">
|
||||
<style name="Widget.BookmarkFolderView" parent="Widget.TwoLineRow.PrimaryText">
|
||||
<item name="android:paddingLeft">10dip</item>
|
||||
<item name="android:drawablePadding">10dip</item>
|
||||
<item name="android:drawableLeft">@drawable/bookmark_folder</item>
|
||||
|
@ -143,7 +143,7 @@
|
|||
<item name="android:orientation">vertical</item>
|
||||
</style>
|
||||
|
||||
<style name="Widget.BookmarkItemView" parent="Widget.TwoLinePageRow"/>
|
||||
<style name="Widget.BookmarkItemView" parent="Widget.TwoLineRow"/>
|
||||
|
||||
<style name="Widget.BookmarksListView" parent="Widget.HomeListView"/>
|
||||
|
||||
|
@ -317,11 +317,11 @@
|
|||
<item name="android:textSize">14sp</item>
|
||||
</style>
|
||||
|
||||
<style name="TextAppearance.Widget.TwoLinePageRow" />
|
||||
<style name="TextAppearance.Widget.TwoLineRow" />
|
||||
|
||||
<style name="TextAppearance.Widget.TwoLinePageRow.Title" parent="TextAppearance.Medium"/>
|
||||
<style name="TextAppearance.Widget.TwoLineRow.PrimaryText" parent="TextAppearance.Medium"/>
|
||||
|
||||
<style name="TextAppearance.Widget.TwoLinePageRow.Url" parent="TextAppearance.Micro">
|
||||
<style name="TextAppearance.Widget.TwoLineRow.SecondaryText" parent="TextAppearance.Micro">
|
||||
<item name="android:textColor">?android:attr/textColorSecondary</item>
|
||||
</style>
|
||||
|
||||
|
|
|
@ -38,7 +38,7 @@ skip-if = processor == "x86"
|
|||
[testInputUrlBar]
|
||||
[testJarReader]
|
||||
[testLinkContextMenu]
|
||||
[testHomeListsProvider]
|
||||
# [testHomeListsProvider] # see bug 952310
|
||||
[testHomeProvider]
|
||||
[testLoad]
|
||||
[testMailToContextMenu]
|
||||
|
|
|
@ -448,8 +448,7 @@ var SelectionHandler = {
|
|||
icon: "drawable://ab_paste",
|
||||
action: function(aElement) {
|
||||
ClipboardHelper.paste(aElement);
|
||||
SelectionHandler._positionHandles();
|
||||
SelectionHandler._updateMenu();
|
||||
SelectionHandler._closeSelection();
|
||||
},
|
||||
order: 2,
|
||||
selector: ClipboardHelper.pasteContext,
|
||||
|
|
|
@ -27,13 +27,15 @@ const SQL = {
|
|||
"id INTEGER PRIMARY KEY AUTOINCREMENT, " +
|
||||
"dataset_id TEXT NOT NULL, " +
|
||||
"url TEXT," +
|
||||
"primary_text TEXT," +
|
||||
"secondary_text TEXT" +
|
||||
"title TEXT," +
|
||||
"description TEXT," +
|
||||
"image_url TEXT," +
|
||||
"created INTEGER" +
|
||||
")",
|
||||
|
||||
insertItem:
|
||||
"INSERT INTO items (dataset_id, url) " +
|
||||
"VALUES (:dataset_id, :url)",
|
||||
"INSERT INTO items (dataset_id, url, title, description, image_url, created) " +
|
||||
"VALUES (:dataset_id, :url, :title, :description, :image_url, :created)",
|
||||
|
||||
deleteFromDataset:
|
||||
"DELETE FROM items WHERE dataset_id = :dataset_id"
|
||||
|
@ -82,7 +84,11 @@ HomeStorage.prototype = {
|
|||
// XXX: Directly pass item as params? More validation for item? Batch insert?
|
||||
let params = {
|
||||
dataset_id: this.datasetId,
|
||||
url: item.url
|
||||
url: item.url,
|
||||
title: item.title,
|
||||
description: item.description,
|
||||
image_url: item.image_url,
|
||||
created: Date.now()
|
||||
};
|
||||
yield db.executeCached(SQL.insertItem, params);
|
||||
}
|
||||
|
|
|
@ -27,7 +27,6 @@ body {
|
|||
}
|
||||
|
||||
#banner {
|
||||
margin: 0 -10px;
|
||||
min-height: 150px;
|
||||
background-color: #bdc7ce;
|
||||
}
|
||||
|
@ -79,7 +78,7 @@ body {
|
|||
}
|
||||
|
||||
#aboutLinks {
|
||||
margin: 0 -10px 15px -10px;
|
||||
margin: 0 0 15px 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче