Merge last PGO-green changeset of mozilla-inbound to mozilla-central a=merge

This commit is contained in:
Ed Morley 2012-04-17 17:47:09 -07:00
commit 0d5915835c
157 changed files with 10087 additions and 3959 deletions

View File

@ -38,11 +38,9 @@
*
* ***** END LICENSE BLOCK ***** */
#include "mozilla/Util.h"
#include "nsAccessible.h"
#include "nsAccessibleWrap.h"
#include "Accessible-inl.h"
#include "InterfaceInitFuncs.h"
#include "nsAccUtils.h"
#include "nsApplicationAccessibleWrap.h"
@ -60,6 +58,7 @@
#include "Relation.h"
#include "States.h"
#include "mozilla/Util.h"
#include "nsXPCOMStrings.h"
#include "nsComponentManagerUtils.h"

View File

@ -39,6 +39,7 @@
#include "InterfaceInitFuncs.h"
#include "Accessible-inl.h"
#include "nsMai.h"
#include "Role.h"

View File

@ -23,11 +23,6 @@ var EXPORTED_SYMBOLS = ['VisualPresenter',
function Presenter() {}
Presenter.prototype = {
/**
* The padding in pixels between the object and the highlight border.
*/
BORDER_PADDING: 2,
/**
* Attach function for presenter.
* @param {ChromeWindow} aWindow Chrome window the presenter could use.
@ -96,6 +91,11 @@ function VisualPresenter() {}
VisualPresenter.prototype = new Presenter();
/**
* The padding in pixels between the object and the highlight border.
*/
VisualPresenter.prototype.BORDER_PADDING = 2;
VisualPresenter.prototype.attach = function(aWindow) {
this.chromeWin = aWindow;
@ -251,7 +251,7 @@ AndroidPresenter.prototype.tabSelected = function(aObject) {
context.push(parent);
context.reverse();
this.pivotChanged(vcDoc.virtualCursor.position, context);
this.pivotChanged(vcDoc.virtualCursor.position || aObject, context);
};
AndroidPresenter.prototype.sendMessageToJava = function(aMessage) {

View File

@ -26,8 +26,8 @@
function doTest()
{
testKeyboardShortcut("input1", "");
testKeyboardShortcut("input2", MAC ? "⌃b" : "Alt+Shift+b");
testKeyboardShortcut("link", MAC ? "⌃l" : "Alt+Shift+l");
testKeyboardShortcut("input2", MAC ? "⌃%b" : "Alt+Shift+b");
testKeyboardShortcut("link", MAC ? "⌃%l" : "Alt+Shift+l");
SimpleTest.finish();
}

View File

@ -237,8 +237,7 @@ const kSansSerifFontFamily =
const kSerifFontFamily =
function(aFontFamily) { return aFontFamily != "serif"; }
const kCursiveFontFamily = WIN ? "Comic Sans MS" :
(LINUX ? "DejaVu Serif" : "MacFont");
const kCursiveFontFamily = LINUX ? "DejaVu Serif" : "Comic Sans MS";
/**
* Return used font from the given computed style.

View File

@ -210,7 +210,7 @@
aria-labelledby="l1 l2"
alt="Mozilla logo"
title="This is a logo"
src="moz.png"/>
src="../moz.png"/>
</markup>
<markup ref="html:img" ruleset="htmlimageemptyalt">
@ -221,7 +221,7 @@
aria-labelledby="l1 l2"
title="This is a logo"
alt=""
src="moz.png"/>
src="../moz.png"/>
</markup>
<markup ref="html:table/html:tr/html:td" ruleset="htmlelm"

View File

@ -40,6 +40,12 @@ probes/Makefile
extensions/Makefile
"
if [ "$MOZ_WEBAPP_RUNTIME" ]; then
add_makefiles "
webapprt/Makefile
"
fi
if [ ! "$LIBXUL_SDK" ]; then
if [ "$STLPORT_SOURCES" ]; then
add_makefiles "

View File

@ -349,6 +349,12 @@ pref("browser.download.manager.quitBehavior", 0);
pref("browser.download.manager.scanWhenDone", true);
pref("browser.download.manager.resumeOnWakeDelay", 10000);
// This allows disabling the Downloads Panel in favor of the old interface.
pref("browser.download.useToolkitUI", false);
// This controls retention behavior in the Downloads Panel only.
pref("browser.download.panel.removeFinishedDownloads", false);
// search engines URL
pref("browser.search.searchEnginesURL", "https://addons.mozilla.org/%LOCALE%/firefox/search-engines/");

View File

@ -1391,6 +1391,8 @@ function BrowserStartup() {
gPrivateBrowsingUI.init();
DownloadsButton.initializePlaceholder();
retrieveToolbarIconsizesFromTheme();
gDelayedStartupTimeoutId = setTimeout(delayedStartup, 0, isLoadingBlank, mustLoadSidebar);
@ -1640,6 +1642,11 @@ function delayedStartup(isLoadingBlank, mustLoadSidebar) {
#endif
}, 10000);
// The object handling the downloads indicator is also initialized here in the
// delayed startup function, but the actual indicator element is not loaded
// unless there are downloads to be displayed.
DownloadsButton.initializeIndicator();
#ifndef XP_MACOSX
updateEditUIVisibility();
let placesContext = document.getElementById("placesContext");
@ -3722,6 +3729,7 @@ function BrowserCustomizeToolbar()
PlacesToolbarHelper.customizeStart();
BookmarksMenuButton.customizeStart();
DownloadsButton.customizeStart();
TabsInTitlebar.allowedBy("customizing-toolbars", false);
@ -3788,6 +3796,7 @@ function BrowserToolboxCustomizeDone(aToolboxChanged) {
PlacesToolbarHelper.customizeDone();
BookmarksMenuButton.customizeDone();
DownloadsButton.customizeDone();
// The url bar splitter state is dependent on whether stop/reload
// and the location bar are combined, so we need this ordering

View File

@ -855,6 +855,9 @@
label="&printButton.label;" command="cmd_print"
tooltiptext="&printButton.tooltip;"/>
<!-- This is a placeholder for the Downloads Indicator. It is visible
only during the customization of the toolbar or in the palette, and
is replaced when customization is done. -->
<toolbarbutton id="downloads-button" class="toolbarbutton-1 chromeclass-toolbar-additional"
observes="Tools:Downloads"
ondrop="DownloadsButtonDNDObserver.onDrop(event)"

View File

@ -41,5 +41,7 @@
<script type="application/javascript" src="chrome://global/content/viewZoomOverlay.js"/>
<script type="application/javascript" src="chrome://browser/content/places/browserPlacesViews.js"/>
<script type="application/javascript" src="chrome://browser/content/browser.js"/>
<script type="application/javascript" src="chrome://browser/content/downloads/downloads.js"/>
<script type="application/javascript" src="chrome://browser/content/downloads/indicator.js"/>
<script type="application/javascript" src="chrome://global/content/inlineSpellCheckUI.js"/>
<script type="application/javascript" src="chrome://global/content/viewSourceUtils.js"/>

View File

@ -51,6 +51,10 @@ ifdef MOZ_SERVICES_SYNC
tier_app_dirs += services
endif
ifdef MOZ_WEBAPP_RUNTIME
tier_app_dirs += webapprt
endif
tier_app_dirs += browser
# Never add other tier_app_dirs after browser. They won't get packaged
# properly on mac.

View File

@ -24,8 +24,22 @@ category command-line-handler x-default @mozilla.org/browser/final-clh;1 applica
category command-line-validator b-browser @mozilla.org/browser/clh;1 application={ec8030f7-c20a-464f-9b0e-13a3a9e97384}
# nsBrowserGlue.js
# WebappRT doesn't need these instructions, and they don't necessarily work
# with it, but it does use a GRE directory that the GRE shares with Firefox,
# so in order to prevent the instructions from being processed for WebappRT,
# we need to restrict them to the applications that depend on them, i.e.:
#
# b2g: {3c2e2abc-06d4-11e1-ac3b-374f68613e61}
# browser: {ec8030f7-c20a-464f-9b0e-13a3a9e97384}
# mobile/android: {aa3c5121-dab2-40e2-81ca-7ea25febc110}
# mobile/xul: {a23983c0-fd0e-11dc-95ff-0800200c9a66}
#
# In theory we should do this for all these instructions, but in practice it is
# sufficient to do it for the app-startup one, and the file is simpler that way.
component {eab9012e-5f74-4cbc-b2b5-a590235513cc} nsBrowserGlue.js
contract @mozilla.org/browser/browserglue;1 {eab9012e-5f74-4cbc-b2b5-a590235513cc}
category app-startup nsBrowserGlue service,@mozilla.org/browser/browserglue;1
category app-startup nsBrowserGlue service,@mozilla.org/browser/browserglue;1 application={3c2e2abc-06d4-11e1-ac3b-374f68613e61} application={ec8030f7-c20a-464f-9b0e-13a3a9e97384} application={aa3c5121-dab2-40e2-81ca-7ea25febc110} application={a23983c0-fd0e-11dc-95ff-0800200c9a66}
component {d8903bf6-68d5-4e97-bcd1-e4d3012f721a} nsBrowserGlue.js
contract @mozilla.org/content-permission/prompt;1 {d8903bf6-68d5-4e97-bcd1-e4d3012f721a}

View File

@ -62,6 +62,7 @@ PARALLEL_DIRS = \
about \
certerror \
dirprovider \
downloads \
feeds \
places \
preferences \

View File

@ -36,12 +36,7 @@
/////////////////////////////////////////////////////////////////////////////
#define NS_BROWSERPROFILEMIGRATOR_CONTRACTID_PREFIX "@mozilla.org/profile/migrator;1?app=browser&type="
#ifdef XP_WIN
#define NS_WINIEPROFILEMIGRATOR_CID \
{ 0xbc15c73d, 0xc05b, 0x497b, { 0xa3, 0x73, 0x4b, 0xae, 0x6c, 0x17, 0x86, 0x31 } }
#define NS_WINIEHISTORYENUMERATOR_CID \
{ 0x93480624, 0x806e, 0x4756, { 0xb7, 0xcb, 0x0f, 0xb7, 0xdd, 0x74, 0x6a, 0x8f } }
@ -49,11 +44,6 @@
"@mozilla.org/profile/migrator/iehistoryenumerator;1"
#endif
#ifdef XP_MACOSX
#define NS_SAFARIPROFILEMIGRATOR_CID \
{ 0x29e3b139, 0xad19, 0x44f3, { 0xb2, 0xc2, 0xe9, 0xf1, 0x3b, 0xa2, 0xbb, 0xc6 } }
#endif
#define NS_SHELLSERVICE_CID \
{ 0x63c7b9f4, 0xcc8, 0x43f8, { 0xb6, 0x66, 0xa, 0x66, 0x16, 0x55, 0xcb, 0x73 } }

View File

@ -50,7 +50,6 @@
#endif
#if defined(XP_WIN) && !defined(__MINGW32__)
#include "nsIEProfileMigrator.h"
#include "nsIEHistoryEnumerator.h"
#endif
@ -76,7 +75,6 @@ NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsGNOMEShellService, Init)
#endif
#if defined(XP_WIN) && !defined(__MINGW32__)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsIEProfileMigrator)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsIEHistoryEnumerator)
#endif
@ -93,7 +91,6 @@ NS_DEFINE_NAMED_CID(NS_SHELLSERVICE_CID);
NS_DEFINE_NAMED_CID(NS_FEEDSNIFFER_CID);
NS_DEFINE_NAMED_CID(NS_BROWSER_ABOUT_REDIRECTOR_CID);
#if defined(XP_WIN) && !defined(__MINGW32__)
NS_DEFINE_NAMED_CID(NS_WINIEPROFILEMIGRATOR_CID);
NS_DEFINE_NAMED_CID(NS_WINIEHISTORYENUMERATOR_CID);
#elif defined(XP_MACOSX)
NS_DEFINE_NAMED_CID(NS_SHELLSERVICE_CID);
@ -110,7 +107,6 @@ static const mozilla::Module::CIDEntry kBrowserCIDs[] = {
{ &kNS_FEEDSNIFFER_CID, false, NULL, nsFeedSnifferConstructor },
{ &kNS_BROWSER_ABOUT_REDIRECTOR_CID, false, NULL, AboutRedirector::Create },
#if defined(XP_WIN) && !defined(__MINGW32__)
{ &kNS_WINIEPROFILEMIGRATOR_CID, false, NULL, nsIEProfileMigratorConstructor },
{ &kNS_WINIEHISTORYENUMERATOR_CID, false, NULL, nsIEHistoryEnumeratorConstructor },
#elif defined(XP_MACOSX)
{ &kNS_SHELLSERVICE_CID, false, NULL, nsMacShellServiceConstructor },
@ -144,7 +140,6 @@ static const mozilla::Module::ContractIDEntry kBrowserContracts[] = {
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "newtab", &kNS_BROWSER_ABOUT_REDIRECTOR_CID },
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "permissions", &kNS_BROWSER_ABOUT_REDIRECTOR_CID },
#if defined(XP_WIN) && !defined(__MINGW32__)
{ NS_BROWSERPROFILEMIGRATOR_CONTRACTID_PREFIX "ie", &kNS_WINIEPROFILEMIGRATOR_CID },
{ NS_IEHISTORYENUMERATOR_CONTRACTID, &kNS_WINIEHISTORYENUMERATOR_CID },
#elif defined(XP_MACOSX)
{ NS_SHELLSERVICE_CONTRACTID, &kNS_SHELLSERVICE_CID },

View File

@ -0,0 +1,18 @@
# 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/.
DEPTH = ../../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
DIRS = src
ifdef ENABLE_TESTS
DIRS += test
endif
include $(topsrcdir)/config/rules.mk

View File

@ -0,0 +1,60 @@
<?xml version="1.0"?>
# -*- Mode: HTML; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
# 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/.
<!DOCTYPE bindings SYSTEM "chrome://browser/locale/downloads/downloads.dtd">
<bindings id="downloadBindings"
xmlns="http://www.mozilla.org/xbl"
xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
xmlns:xbl="http://www.mozilla.org/xbl">
<binding id="download"
extends="chrome://global/content/bindings/richlistbox.xml#richlistitem">
<resources>
<stylesheet src="chrome://browser/skin/downloads/downloads.css"/>
</resources>
<content orient="horizontal">
<xul:hbox class="downloadInfo"
align="center"
flex="1"
onclick="DownloadsView.onDownloadClick(event);">
<xul:vbox pack="center">
<xul:image class="downloadTypeIcon"
validate="always"
xbl:inherits="src=image"/>
<xul:image class="downloadTypeIcon blockedIcon"/>
</xul:vbox>
<xul:vbox pack="center"
flex="1">
<xul:description class="downloadTarget"
crop="center"
xbl:inherits="value=target,tooltiptext=target"/>
<xul:progressmeter anonid="progressmeter"
class="downloadProgress"
min="0"
max="100"
xbl:inherits="mode=progressmode,value=progress"/>
<xul:description class="downloadDetails"
crop="end"
xbl:inherits="value=status,tooltiptext=statusTip"/>
</xul:vbox>
</xul:hbox>
<xul:hbox class="downloadButtonContainer"
align="center">
<xul:button class="downloadButton downloadCancel"
tooltiptext="&cmd.cancel.label;"
oncommand="DownloadsView.onDownloadCommand(event, 'downloadsCmd_cancel');"/>
<xul:button class="downloadButton downloadRetry"
tooltiptext="&cmd.retry.label;"
oncommand="DownloadsView.onDownloadCommand(event, 'downloadsCmd_retry');"/>
<xul:button class="downloadButton downloadShow"
tooltiptext="&cmd.show.label;"
oncommand="DownloadsView.onDownloadCommand(event, 'downloadsCmd_show');"/>
</xul:hbox>
</content>
</binding>
</bindings>

View File

@ -0,0 +1,90 @@
/* 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/. */
/*** Download items ***/
richlistitem[type="download"] {
-moz-binding: url('chrome://browser/content/downloads/download.xml#download');
}
richlistitem[type="download"]:not([selected]) button {
/* Only focus buttons in the selected item. */
-moz-user-focus: none;
}
/*** Visibility of controls inside download items ***/
.download-state:-moz-any( [state="6"], /* Blocked (parental) */
[state="8"], /* Blocked (dirty) */
[state="9"]) /* Blocked (policy) */
.downloadTypeIcon:not(.blockedIcon),
.download-state:not(:-moz-any([state="6"], /* Blocked (parental) */
[state="8"], /* Blocked (dirty) */
[state="9"]) /* Blocked (policy) */)
.downloadTypeIcon.blockedIcon,
.download-state:not(:-moz-any([state="-1"],/* Starting (initial) */
[state="5"], /* Starting (queued) */
[state="0"], /* Downloading */
[state="4"], /* Paused */
[state="7"]) /* Scanning */)
.downloadProgress,
.download-state:not( [state="0"] /* Downloading */)
.downloadPauseMenuItem,
.download-state:not( [state="4"] /* Paused */)
.downloadResumeMenuItem,
.download-state:not(:-moz-any([state="-1"],/* Starting (initial) */
[state="5"], /* Starting (queued) */
[state="0"], /* Downloading */
[state="4"]) /* Paused */)
.downloadCancel,
.download-state:not(:-moz-any([state="2"], /* Failed */
[state="4"]) /* Paused */)
.downloadCancelMenuItem,
.download-state:not(:-moz-any([state="1"], /* Finished */
[state="3"], /* Canceled */
[state="6"], /* Blocked (parental) */
[state="8"], /* Blocked (dirty) */
[state="9"]) /* Blocked (policy) */)
.downloadRemoveFromListMenuItem,
.download-state:not(:-moz-any([state="2"], /* Failed */
[state="3"]) /* Canceled */)
.downloadRetry,
.download-state:not( [state="1"] /* Finished */)
.downloadShow,
.download-state:not(:-moz-any([state="-1"],/* Starting (initial) */
[state="5"], /* Starting (queued) */
[state="0"], /* Downloading */
[state="4"]) /* Paused */)
.downloadShowMenuItem,
.download-state[state="7"] .downloadCommandsSeparator
{
display: none;
}
/*** Visibility of controls inside the downloads indicator ***/
#downloads-indicator:-moz-any([progress],
[counter],
[paused]) #downloads-indicator-icon,
#downloads-indicator:not(:-moz-any([progress],
[counter],
[paused]))
#downloads-indicator-progress-area
{
visibility: hidden;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,114 @@
<?xml version="1.0"?>
# -*- Mode: HTML; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
# 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/.
<?xml-stylesheet href="chrome://browser/content/downloads/downloads.css"?>
<?xml-stylesheet href="chrome://browser/skin/downloads/downloads.css"?>
<!DOCTYPE overlay SYSTEM "chrome://browser/locale/downloads/downloads.dtd">
<overlay xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
id="downloadsOverlay">
<commandset>
<command id="downloadsCmd_doDefault"
oncommand="goDoCommand('downloadsCmd_doDefault')"/>
<command id="downloadsCmd_pauseResume"
oncommand="goDoCommand('downloadsCmd_pauseResume')"/>
<command id="downloadsCmd_cancel"
oncommand="goDoCommand('downloadsCmd_cancel')"/>
<command id="downloadsCmd_open"
oncommand="goDoCommand('downloadsCmd_open')"/>
<command id="downloadsCmd_show"
oncommand="goDoCommand('downloadsCmd_show')"/>
<command id="downloadsCmd_retry"
oncommand="goDoCommand('downloadsCmd_retry')"/>
<command id="downloadsCmd_openReferrer"
oncommand="goDoCommand('downloadsCmd_openReferrer')"/>
<command id="downloadsCmd_copyLocation"
oncommand="goDoCommand('downloadsCmd_copyLocation')"/>
<command id="downloadsCmd_clearList"
oncommand="goDoCommand('downloadsCmd_clearList')"/>
</commandset>
<popupset>
<!-- The panel has level="top" to ensure that it is never hidden by the
taskbar on Windows. See bug 672365. For accessibility to screen
readers, we use a label on the panel instead of the anchor because the
panel can also be displayed without an anchor. -->
<panel id="downloadsPanel"
aria-label="&downloads.title;"
role="group"
type="arrow"
orient="vertical"
level="top"
onpopupshown="DownloadsPanel.onPopupShown(event);"
onpopuphidden="DownloadsPanel.onPopupHidden(event);">
<!-- The following popup menu should be a child of the panel element,
otherwise flickering may occur when the cursor is moved over the area
of a disabled menu item that overlaps the panel. See bug 492960. -->
<menupopup id="downloadsContextMenu"
class="download-state">
<menuitem command="downloadsCmd_pauseResume"
class="downloadPauseMenuItem"
label="&cmd.pause.label;"
accesskey="&cmd.pause.accesskey;"/>
<menuitem command="downloadsCmd_pauseResume"
class="downloadResumeMenuItem"
label="&cmd.resume.label;"
accesskey="&cmd.resume.accesskey;"/>
<menuitem command="downloadsCmd_cancel"
class="downloadCancelMenuItem"
label="&cmd.cancel.label;"
accesskey="&cmd.cancel.accesskey;"/>
<menuitem command="cmd_delete"
class="downloadRemoveFromListMenuItem"
label="&cmd.removeFromList.label;"
accesskey="&cmd.removeFromList.accesskey;"/>
<menuitem command="downloadsCmd_show"
class="downloadShowMenuItem"
#ifdef XP_MACOSX
label="&cmd.showMac.label;"
accesskey="&cmd.showMac.accesskey;"
#else
label="&cmd.show.label;"
accesskey="&cmd.show.accesskey;"
#endif
/>
<menuseparator class="downloadCommandsSeparator"/>
<menuitem command="downloadsCmd_openReferrer"
label="&cmd.goToDownloadPage.label;"
accesskey="&cmd.goToDownloadPage.accesskey;"/>
<menuitem command="downloadsCmd_copyLocation"
label="&cmd.copyDownloadLink.label;"
accesskey="&cmd.copyDownloadLink.accesskey;"/>
<menuseparator/>
<menuitem command="downloadsCmd_clearList"
label="&cmd.clearList.label;"
accesskey="&cmd.clearList.accesskey;"/>
</menupopup>
<richlistbox id="downloadsListBox"
class="plain"
flex="1"
context="downloadsContextMenu"
onkeypress="DownloadsView.onDownloadKeyPress(event);"
oncontextmenu="DownloadsView.onDownloadContextMenu(event);"
ondragstart="DownloadsView.onDownloadDragStart(event);"/>
<button id="downloadsHistory"
class="plain"
label="&downloadshistory.label;"
accesskey="&downloadshistory.accesskey;"
oncommand="DownloadsPanel.showDownloadsHistory();"/>
</panel>
</popupset>
</overlay>

View File

@ -0,0 +1,591 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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/. */
/**
* Handles the indicator that displays the progress of ongoing downloads, which
* is also used as the anchor for the downloads panel.
*
* This module includes the following constructors and global objects:
*
* DownloadsButton
* Main entry point for the downloads indicator. Depending on how the toolbars
* have been customized, this object determines if we should show a fully
* functional indicator, a placeholder used during customization and in the
* customization palette, or a neutral view as a temporary anchor for the
* downloads panel.
*
* DownloadsIndicatorView
* Builds and updates the actual downloads status widget, responding to changes
* in the global status data, or provides a neutral view if the indicator is
* removed from the toolbars and only used as a temporary anchor. In addition,
* handles the user interaction events raised by the widget.
*/
"use strict";
////////////////////////////////////////////////////////////////////////////////
//// DownloadsButton
/**
* Main entry point for the downloads indicator. Depending on how the toolbars
* have been customized, this object determines if we should show a fully
* functional indicator, a placeholder used during customization and in the
* customization palette, or a neutral view as a temporary anchor for the
* downloads panel.
*/
const DownloadsButton = {
/**
* Location of the indicator overlay.
*/
get kIndicatorOverlay()
"chrome://browser/content/downloads/indicatorOverlay.xul",
/**
* Returns a reference to the downloads button position placeholder, or null
* if not available because it has been removed from the toolbars.
*/
get _placeholder()
{
return document.getElementById("downloads-button");
},
/**
* This function is called synchronously at window initialization. It only
* sets the visibility of user interface elements to avoid flickering.
*
* NOTE: To keep startup time to a minimum, this function should not perform
* any expensive operations or input/output, and should not cause the
* Download Manager service to start.
*/
initializePlaceholder: function DB_initializePlaceholder()
{
// Exit now if the feature is disabled. To improve startup time, we don't
// load the DownloadsCommon module yet, but check the preference directly.
if (gPrefService.getBoolPref("browser.download.useToolkitUI")) {
return;
}
// We must hide the placeholder used for toolbar customization, unless it
// has been removed from the toolbars and is now located in the palette.
let placeholder = this._placeholder;
if (placeholder) {
placeholder.collapsed = true;
}
},
/**
* This function is called asynchronously just after window initialization.
*
* NOTE: This function should limit the input/output it performs to improve
* startup time, and in particular should not cause the Download Manager
* service to start.
*/
initializeIndicator: function DB_initializeIndicator()
{
this._update();
},
/**
* Indicates whether toolbar customization is in progress.
*/
_customizing: false,
/**
* This function is called when toolbar customization starts.
*
* During customization, we never show the actual download progress indication
* or the event notifications, but we show a neutral placeholder. The neutral
* placeholder is an ordinary button defined in the browser window that can be
* moved freely between the toolbars and the customization palette.
*/
customizeStart: function DB_customizeStart()
{
// Hide the indicator and prevent it to be displayed as a temporary anchor
// during customization, even if requested using the getAnchor method.
this._customizing = true;
this._anchorRequested = false;
let indicator = DownloadsIndicatorView.indicator;
if (indicator) {
indicator.collapsed = true;
}
let placeholder = this._placeholder;
if (placeholder) {
placeholder.collapsed = false;
}
},
/**
* This function is called when toolbar customization ends.
*/
customizeDone: function DB_customizeDone()
{
this._customizing = false;
this._update();
},
/**
* This function is called during initialization or when toolbar customization
* ends. It determines if we should enable or disable the object that keeps
* the indicator updated, and ensures that the placeholder is hidden unless it
* has been moved to the customization palette.
*
* NOTE: This function is also called on startup, thus it should limit the
* input/output it performs, and in particular should not cause the
* Download Manager service to start.
*/
_update: function DB_update() {
this._updatePositionInternal();
let placeholder = this._placeholder;
if (!DownloadsCommon.useToolkitUI) {
DownloadsIndicatorView.ensureInitialized();
if (placeholder) {
placeholder.collapsed = true;
}
} else {
DownloadsIndicatorView.ensureTerminated();
}
},
/**
* Determines the position where the indicator should appear, and moves its
* associated element to the new position. This does not happen if the
* indicator is currently being used as the anchor for the panel, to ensure
* that the panel doesn't flicker because we move the DOM element to which
* it's anchored.
*/
updatePosition: function DB_updatePosition()
{
if (!this._anchorRequested) {
this._updatePositionInternal();
}
},
/**
* Determines the position where the indicator should appear, and moves its
* associated element to the new position.
*
* @return Anchor element, or null if the indicator is not visible.
*/
_updatePositionInternal: function DB_updatePositionInternal()
{
let indicator = DownloadsIndicatorView.indicator;
if (!indicator) {
// Exit now if the indicator overlay isn't loaded yet.
return null;
}
let placeholder = this._placeholder;
// Firstly, determine if we should always hide the indicator.
if (!placeholder && !this._anchorRequested &&
!DownloadsIndicatorView.hasDownloads) {
indicator.collapsed = true;
return null;
}
indicator.collapsed = false;
indicator.open = this._anchorRequested;
// Determine if we should display the indicator in a known position.
if (placeholder) {
placeholder.parentNode.insertBefore(indicator, placeholder);
// Determine if the placeholder is located on a visible toolbar.
if (isElementVisible(placeholder.parentNode)) {
return DownloadsIndicatorView.indicatorAnchor;
}
}
// If not customized, the indicator is normally in the navigation bar.
// Always place it in the default position, unless we need an anchor.
if (!this._anchorRequested) {
this._navBar.appendChild(indicator);
return null;
}
// Show the indicator temporarily in the navigation bar, if visible.
if (isElementVisible(this._navBar)) {
this._navBar.appendChild(indicator);
return DownloadsIndicatorView.indicatorAnchor;
}
// Show the indicator temporarily in the tab bar, if visible.
if (!this._tabsToolbar.collapsed) {
this._tabsToolbar.appendChild(indicator);
return DownloadsIndicatorView.indicatorAnchor;
}
// The temporary anchor cannot be shown.
return null;
},
/**
* Indicates whether we should try and show the indicator temporarily as an
* anchor for the panel, even if the indicator would be hidden by default.
*/
_anchorRequested: false,
/**
* Ensures that there is an anchor available for the panel.
*
* @param aCallback
* Called when the anchor is available, passing the element where the
* panel should be anchored, or null if an anchor is not available (for
* example because both the tab bar and the navigation bar are hidden).
*/
getAnchor: function DB_getAnchor(aCallback)
{
// Do not allow anchoring the panel to the element while customizing.
if (this._customizing) {
aCallback(null);
return;
}
function DB_GA_callback() {
this._anchorRequested = true;
aCallback(this._updatePositionInternal());
}
DownloadsOverlayLoader.ensureOverlayLoaded(this.kIndicatorOverlay,
DB_GA_callback.bind(this));
},
/**
* Allows the temporary anchor to be hidden.
*/
releaseAnchor: function DB_releaseAnchor()
{
this._anchorRequested = false;
this._updatePositionInternal();
},
get _tabsToolbar()
{
delete this._tabsToolbar;
return this._tabsToolbar = document.getElementById("TabsToolbar");
},
get _navBar()
{
delete this._navBar;
return this._navBar = document.getElementById("nav-bar");
}
};
////////////////////////////////////////////////////////////////////////////////
//// DownloadsIndicatorView
/**
* Builds and updates the actual downloads status widget, responding to changes
* in the global status data, or provides a neutral view if the indicator is
* removed from the toolbars and only used as a temporary anchor. In addition,
* handles the user interaction events raised by the widget.
*/
const DownloadsIndicatorView = {
/**
* True when the view is connected with the underlying downloads data.
*/
_initialized: false,
/**
* True when the user interface elements required to display the indicator
* have finished loading in the browser window, and can be referenced.
*/
_operational: false,
/**
* Prepares the downloads indicator to be displayed.
*/
ensureInitialized: function DIV_ensureInitialized()
{
if (this._initialized) {
return;
}
this._initialized = true;
window.addEventListener("unload", this.onWindowUnload, false);
DownloadsCommon.indicatorData.addView(this);
},
/**
* Frees the internal resources related to the indicator.
*/
ensureTerminated: function DIV_ensureTerminated()
{
if (!this._initialized) {
return;
}
this._initialized = false;
window.removeEventListener("unload", this.onWindowUnload, false);
DownloadsCommon.indicatorData.removeView(this);
// Reset the view properties, so that a neutral indicator is displayed if we
// are visible only temporarily as an anchor.
this.counter = "";
this.percentComplete = 0;
this.paused = false;
this.attention = false;
},
/**
* Ensures that the user interface elements required to display the indicator
* are loaded, then invokes the given callback.
*/
_ensureOperational: function DIV_ensureOperational(aCallback)
{
if (this._operational) {
aCallback();
return;
}
function DIV_EO_callback() {
this._operational = true;
// If the view is initialized, we need to update the elements now that
// they are finally available in the document.
if (this._initialized) {
DownloadsCommon.indicatorData.refreshView(this);
}
aCallback();
}
DownloadsOverlayLoader.ensureOverlayLoaded(
DownloadsButton.kIndicatorOverlay,
DIV_EO_callback.bind(this));
},
//////////////////////////////////////////////////////////////////////////////
//// Direct control functions
/**
* Set while we are waiting for a notification to fade out.
*/
_notificationTimeout: null,
/**
* If the status indicator is visible in its assigned position, shows for a
* brief time a visual notification of a relevant event, like a new download.
*/
showEventNotification: function DIV_showEventNotification()
{
if (!this._initialized) {
return;
}
function DIV_SEN_callback() {
if (this._notificationTimeout) {
clearTimeout(this._notificationTimeout);
}
let indicator = this.indicator;
indicator.setAttribute("notification", "true");
this._notificationTimeout = setTimeout(
function () indicator.removeAttribute("notification"), 1000);
}
this._ensureOperational(DIV_SEN_callback.bind(this));
},
//////////////////////////////////////////////////////////////////////////////
//// Callback functions from DownloadsIndicatorData
/**
* Indicates whether the indicator should be shown because there are some
* downloads to be displayed.
*/
set hasDownloads(aValue)
{
if (this._hasDownloads != aValue) {
this._hasDownloads = aValue;
// If there is at least one download, ensure that the view elements are
// loaded before determining the position of the downloads button.
if (aValue) {
this._ensureOperational(function() DownloadsButton.updatePosition());
} else {
DownloadsButton.updatePosition();
}
}
return aValue;
},
get hasDownloads()
{
return this._hasDownloads;
},
_hasDownloads: false,
/**
* Status text displayed in the indicator. If this is set to an empty value,
* then the small downloads icon is displayed instead of the text.
*/
set counter(aValue)
{
if (!this._operational) {
return this._counter;
}
if (this._counter !== aValue) {
this._counter = aValue;
if (this._counter)
this.indicator.setAttribute("counter", "true");
else
this.indicator.removeAttribute("counter");
// We have to set the attribute instead of using the property because the
// XBL binding isn't applied if the element is invisible for any reason.
this._indicatorCounter.setAttribute("value", aValue);
}
return aValue;
},
_counter: null,
/**
* Progress indication to display, from 0 to 100, or -1 if unknown. The
* progress bar is hidden if the current progress is unknown and no status
* text is set in the "counter" property.
*/
set percentComplete(aValue)
{
if (!this._operational) {
return this._percentComplete;
}
if (this._percentComplete !== aValue) {
this._percentComplete = aValue;
if (this._percentComplete >= 0)
this.indicator.setAttribute("progress", "true");
else
this.indicator.removeAttribute("progress");
// We have to set the attribute instead of using the property because the
// XBL binding isn't applied if the element is invisible for any reason.
this._indicatorProgress.setAttribute("value", Math.max(aValue, 0));
}
return aValue;
},
_percentComplete: null,
/**
* Indicates whether the progress won't advance because of a paused state.
* Setting this property forces a paused progress bar to be displayed, even if
* the current progress information is unavailable.
*/
set paused(aValue)
{
if (!this._operational) {
return this._paused;
}
if (this._paused != aValue) {
this._paused = aValue;
if (this._paused) {
this.indicator.setAttribute("paused", "true")
} else {
this.indicator.removeAttribute("paused");
}
}
return aValue;
},
_paused: false,
/**
* Set when the indicator should draw user attention to itself.
*/
set attention(aValue)
{
if (!this._operational) {
return this._attention;
}
if (this._attention != aValue) {
this._attention = aValue;
if (aValue) {
this.indicator.setAttribute("attention", "true")
} else {
this.indicator.removeAttribute("attention");
}
}
return aValue;
},
_attention: false,
//////////////////////////////////////////////////////////////////////////////
//// User interface event functions
onWindowUnload: function DIV_onWindowUnload()
{
// This function is registered as an event listener, we can't use "this".
DownloadsIndicatorView.ensureTerminated();
},
onCommand: function DIV_onCommand(aEvent)
{
if (DownloadsCommon.useToolkitUI) {
// The panel won't suppress attention for us, we need to clear now.
DownloadsCommon.indicatorData.attention = false;
}
BrowserDownloadsUI();
aEvent.stopPropagation();
},
onDragOver: function DIV_onDragOver(aEvent)
{
browserDragAndDrop.dragOver(aEvent);
},
onDragExit: function () { },
onDrop: function DIV_onDrop(aEvent)
{
let name = {};
let url = browserDragAndDrop.drop(aEvent, name);
if (url) {
saveURL(url, name.value, null, true, true);
aEvent.preventDefault();
}
},
/**
* Returns a reference to the main indicator element, or null if the element
* is not present in the browser window yet.
*/
get indicator()
{
let indicator = document.getElementById("downloads-indicator");
if (!indicator) {
return null;
}
// Once the element is loaded, it will never be unloaded.
delete this.indicator;
return this.indicator = indicator;
},
get indicatorAnchor()
{
delete this.indicatorAnchor;
return this.indicatorAnchor =
document.getElementById("downloads-indicator-anchor");
},
get _indicatorCounter()
{
delete this._indicatorCounter;
return this._indicatorCounter =
document.getElementById("downloads-indicator-counter");
},
get _indicatorProgress()
{
delete this._indicatorProgress;
return this._indicatorProgress =
document.getElementById("downloads-indicator-progress");
}
};

View File

@ -0,0 +1,51 @@
<?xml version="1.0"?>
# -*- Mode: HTML; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
# 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/.
<?xml-stylesheet href="chrome://browser/content/downloads/downloads.css"?>
<?xml-stylesheet href="chrome://browser/skin/downloads/downloads.css"?>
<!DOCTYPE overlay SYSTEM "chrome://browser/locale/downloads/downloads.dtd">
<overlay xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
id="indicatorOverlay">
<popupset>
<!-- The downloads indicator is placed in its final toolbar location
programmatically, and can be shown temporarily even when its
placeholder is removed from the toolbars. Its initial location within
the document must not be a toolbar or the toolbar palette, otherwise the
toolbar handling code could remove it from the document. -->
<toolbarbutton id="downloads-indicator"
class="toolbarbutton-1 chromeclass-toolbar-additional"
tooltiptext="&indicator.tooltiptext;"
collapsed="true"
oncommand="DownloadsIndicatorView.onCommand(event);"
ondrop="DownloadsIndicatorView.onDrop(event);"
ondragover="DownloadsIndicatorView.onDragOver(event);"
ondragenter="DownloadsIndicatorView.onDragOver(event);"
ondragleave="DownloadsIndicatorView.onDragLeave(event);">
<!-- The panel's anchor area is smaller than the outer button, but must
always be visible and must not move or resize when the indicator
state changes, otherwise the panel could change its position or lose
its arrow unexpectedly. -->
<stack id="downloads-indicator-anchor"
class="toolbarbutton-icon">
<vbox id="downloads-indicator-progress-area"
pack="center">
<description id="downloads-indicator-counter"/>
<progressmeter id="downloads-indicator-progress"
class="plain"
min="0"
max="100"/>
</vbox>
<vbox id="downloads-indicator-icon"/>
<vbox id="downloads-indicator-notification"/>
</stack>
</toolbarbutton>
</popupset>
</overlay>

View File

@ -0,0 +1,7 @@
browser.jar:
* content/browser/downloads/download.xml (content/download.xml)
content/browser/downloads/downloads.css (content/downloads.css)
content/browser/downloads/downloads.js (content/downloads.js)
* content/browser/downloads/downloadsOverlay.xul (content/downloadsOverlay.xul)
content/browser/downloads/indicator.js (content/indicator.js)
* content/browser/downloads/indicatorOverlay.xul (content/indicatorOverlay.xul)

View File

@ -0,0 +1,4 @@
component {49507fe5-2cee-4824-b6a3-e999150ce9b8} DownloadsStartup.js
contract @mozilla.org/browser/downloadsstartup;1 {49507fe5-2cee-4824-b6a3-e999150ce9b8}
category app-startup DownloadsStartup service,@mozilla.org/browser/downloadsstartup;1
component {4d99321e-d156-455b-81f7-e7aa2308134f} DownloadsUI.js

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,242 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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/. */
/**
* This component listens to notifications for startup, shutdown and session
* restore, controlling which downloads should be loaded from the database.
*
* To avoid affecting startup performance, this component monitors the current
* session restore state, but defers the actual downloads data manipulation
* until the Download Manager service is loaded.
*/
"use strict";
////////////////////////////////////////////////////////////////////////////////
//// Globals
const Cc = Components.classes;
const Ci = Components.interfaces;
const Cu = Components.utils;
const Cr = Components.results;
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "DownloadsCommon",
"resource:///modules/DownloadsCommon.jsm");
XPCOMUtils.defineLazyServiceGetter(this, "gSessionStartup",
"@mozilla.org/browser/sessionstartup;1",
"nsISessionStartup");
XPCOMUtils.defineLazyServiceGetter(this, "gPrivateBrowsingService",
"@mozilla.org/privatebrowsing;1",
"nsIPrivateBrowsingService");
const kObservedTopics = [
"sessionstore-windows-restored",
"sessionstore-browser-state-restored",
"download-manager-initialized",
"download-manager-change-retention",
"private-browsing-transition-complete",
"browser-lastwindow-close-granted",
"quit-application",
"profile-change-teardown",
];
/**
* CID of our implementation of nsIDownloadManagerUI.
*/
const kDownloadsUICid = Components.ID("{4d99321e-d156-455b-81f7-e7aa2308134f}");
/**
* Contract ID of the service implementing nsIDownloadManagerUI.
*/
const kDownloadsUIContractId = "@mozilla.org/download-manager-ui;1";
////////////////////////////////////////////////////////////////////////////////
//// DownloadsStartup
function DownloadsStartup() { }
DownloadsStartup.prototype = {
classID: Components.ID("{49507fe5-2cee-4824-b6a3-e999150ce9b8}"),
_xpcom_factory: XPCOMUtils.generateSingletonFactory(DownloadsStartup),
//////////////////////////////////////////////////////////////////////////////
//// nsISupports
QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver,
Ci.nsISupportsWeakReference]),
//////////////////////////////////////////////////////////////////////////////
//// nsIObserver
observe: function DS_observe(aSubject, aTopic, aData)
{
switch (aTopic) {
case "app-startup":
kObservedTopics.forEach(
function (topic) Services.obs.addObserver(this, topic, true),
this);
// Override Toolkit's nsIDownloadManagerUI implementation with our own.
// This must be done at application startup and not in the manifest to
// ensure that our implementation overrides the original one.
Components.manager.QueryInterface(Ci.nsIComponentRegistrar)
.registerFactory(kDownloadsUICid, "",
kDownloadsUIContractId, null);
break;
case "sessionstore-windows-restored":
case "sessionstore-browser-state-restored":
// Unless there is no saved session, there is a chance that we are
// starting up after a restart or a crash. We should check the disk
// database to see if there are completed downloads to recover and show
// in the panel, in addition to in-progress downloads.
if (gSessionStartup.sessionType != Ci.nsISessionStartup.NO_SESSION) {
this._recoverAllDownloads = true;
}
this._ensureDataLoaded();
break;
case "download-manager-initialized":
// Don't initialize the JavaScript data and user interface layer if we
// are initializing the Download Manager service during shutdown.
if (this._shuttingDown) {
break;
}
// Start receiving events for active and new downloads before we return
// from this observer function. We can't defer the execution of this
// step, to ensure that we don't lose events raised in the meantime.
DownloadsCommon.data.initializeDataLink(
aSubject.QueryInterface(Ci.nsIDownloadManager));
this._downloadsServiceInitialized = true;
// Since this notification is generated during the getService call and
// we need to get the Download Manager service ourselves, we must post
// the handler on the event queue to be executed later.
Services.tm.mainThread.dispatch(this._ensureDataLoaded.bind(this),
Ci.nsIThread.DISPATCH_NORMAL);
break;
case "download-manager-change-retention":
// When the panel interface is enabled, we use a different preference to
// determine whether downloads should be removed from view as soon as
// they are finished. We do this to allow proper migration to the new
// feature when using the same profile on multiple versions of the
// product (bug 697678).
if (!DownloadsCommon.useToolkitUI) {
let removeFinishedDownloads = Services.prefs.getBoolPref(
"browser.download.panel.removeFinishedDownloads");
aSubject.QueryInterface(Ci.nsISupportsPRInt32)
.data = removeFinishedDownloads ? 0 : 2;
}
break;
case "private-browsing-transition-complete":
// Ensure that persistent data is reloaded only when the database
// connection is available again.
this._ensureDataLoaded();
break;
case "browser-lastwindow-close-granted":
// When using the panel interface, downloads that are already completed
// should be removed when the last full browser window is closed. This
// event is invoked only if the application is not shutting down yet.
// If the Download Manager service is not initialized, we don't want to
// initialize it just to clean up completed downloads, because they can
// be present only in case there was a browser crash or restart.
if (this._downloadsServiceInitialized &&
!DownloadsCommon.useToolkitUI) {
Services.downloads.cleanUp();
}
break;
case "quit-application":
// When the application is shutting down, we must free all resources in
// addition to cleaning up completed downloads. If the Download Manager
// service is not initialized, we don't want to initialize it just to
// clean up completed downloads, because they can be present only in
// case there was a browser crash or restart.
this._shuttingDown = true;
if (!this._downloadsServiceInitialized) {
break;
}
DownloadsCommon.data.terminateDataLink();
// When using the panel interface, downloads that are already completed
// should be removed when quitting the application.
if (!DownloadsCommon.useToolkitUI && aData != "restart") {
this._cleanupOnShutdown = true;
}
break;
case "profile-change-teardown":
// If we need to clean up, we must do it synchronously after all the
// "quit-application" listeners are invoked, so that the Download
// Manager service has a chance to pause or cancel in-progress downloads
// before we remove completed downloads from the list. Note that, since
// "quit-application" was invoked, we've already exited Private Browsing
// Mode, thus we are always working on the disk database.
if (this._cleanupOnShutdown) {
Services.downloads.cleanUp();
}
break;
}
},
//////////////////////////////////////////////////////////////////////////////
//// Private
/**
* Indicates whether we should load all downloads from the previous session,
* including completed items as well as active downloads.
*/
_recoverAllDownloads: false,
/**
* Indicates whether the Download Manager service has been initialized. This
* flag is required because we want to avoid accessing the service immediately
* at browser startup. The service will start when the user first requests a
* download, or some time after browser startup.
*/
_downloadsServiceInitialized: false,
/**
* True while we are processing the "quit-application" event, and later.
*/
_shuttingDown: false,
/**
* True during shutdown if we need to remove completed downloads.
*/
_cleanupOnShutdown: false,
/**
* Ensures that persistent download data is reloaded at the appropriate time.
*/
_ensureDataLoaded: function DS_ensureDataLoaded()
{
if (!this._downloadsServiceInitialized ||
gPrivateBrowsingService.privateBrowsingEnabled) {
return;
}
// If the previous session has been already restored, then we ensure that
// all the downloads are loaded. Otherwise, we only ensure that the active
// downloads from the previous session are loaded.
DownloadsCommon.data.ensurePersistentDataLoaded(!this._recoverAllDownloads);
}
};
////////////////////////////////////////////////////////////////////////////////
//// Module
const NSGetFactory = XPCOMUtils.generateNSGetFactory([DownloadsStartup]);

View File

@ -0,0 +1,125 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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/. */
/**
* This component implements the nsIDownloadManagerUI interface and opens the
* downloads panel in the most recent browser window when requested.
*
* If a specific preference is set, this component transparently forwards all
* calls to the original implementation in Toolkit, that shows the window UI.
*/
"use strict";
////////////////////////////////////////////////////////////////////////////////
//// Globals
const Cc = Components.classes;
const Ci = Components.interfaces;
const Cu = Components.utils;
const Cr = Components.results;
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "DownloadsCommon",
"resource:///modules/DownloadsCommon.jsm");
XPCOMUtils.defineLazyServiceGetter(this, "gBrowserGlue",
"@mozilla.org/browser/browserglue;1",
"nsIBrowserGlue");
////////////////////////////////////////////////////////////////////////////////
//// DownloadsUI
function DownloadsUI()
{
XPCOMUtils.defineLazyGetter(this, "_toolkitUI", function () {
// Create Toolkit's nsIDownloadManagerUI implementation.
return Components.classesByID["{7dfdf0d1-aff6-4a34-bad1-d0fe74601642}"]
.getService(Ci.nsIDownloadManagerUI);
});
}
DownloadsUI.prototype = {
classID: Components.ID("{4d99321e-d156-455b-81f7-e7aa2308134f}"),
_xpcom_factory: XPCOMUtils.generateSingletonFactory(DownloadsUI),
//////////////////////////////////////////////////////////////////////////////
//// nsISupports
QueryInterface: XPCOMUtils.generateQI([Ci.nsIDownloadManagerUI]),
//////////////////////////////////////////////////////////////////////////////
//// nsIDownloadManagerUI
show: function DUI_show(aWindowContext, aID, aReason)
{
if (DownloadsCommon.useToolkitUI) {
this._toolkitUI.show(aWindowContext, aID, aReason);
return;
}
if (!aReason) {
aReason = Ci.nsIDownloadManagerUI.REASON_USER_INTERACTED;
}
if (aReason == Ci.nsIDownloadManagerUI.REASON_NEW_DOWNLOAD) {
// New download notifications are already handled by the panel service.
// We don't handle them here because we don't want them to depend on the
// "browser.download.manager.showWhenStarting" and
// "browser.download.manager.focusWhenStarting" preferences.
return;
}
// Show the panel in the most recent browser window, if present.
let browserWin = gBrowserGlue.getMostRecentBrowserWindow();
if (browserWin) {
browserWin.focus();
browserWin.DownloadsPanel.showPanel();
return;
}
// If no browser window is visible and the user requested to show the
// current downloads, try and open a new window. We'll open the panel when
// delayed loading is finished.
Services.obs.addObserver(function DUIO_observe(aSubject, aTopic, aData) {
Services.obs.removeObserver(DUIO_observe, aTopic);
aSubject.DownloadsPanel.showPanel();
}, "browser-delayed-startup-finished", false);
// We must really build an empty arguments list for the new window.
let windowFirstArg = Cc["@mozilla.org/supports-string;1"]
.createInstance(Ci.nsISupportsString);
let windowArgs = Cc["@mozilla.org/supports-array;1"]
.createInstance(Ci.nsISupportsArray);
windowArgs.AppendElement(windowFirstArg);
Services.ww.openWindow(null, "chrome://browser/content/browser.xul",
null, "chrome,dialog=no,all", windowArgs);
},
get visible()
{
if (DownloadsCommon.useToolkitUI) {
return this._toolkitUI.visible;
}
let browserWin = gBrowserGlue.getMostRecentBrowserWindow();
return browserWin ? browserWin.DownloadsPanel.isPanelShowing : false;
},
getAttention: function DUI_getAttention()
{
if (DownloadsCommon.useToolkitUI) {
this._toolkitUI.getAttention();
}
}
};
////////////////////////////////////////////////////////////////////////////////
//// Module
const NSGetFactory = XPCOMUtils.generateNSGetFactory([DownloadsUI]);

View File

@ -0,0 +1,22 @@
# 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/.
DEPTH = ../../../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
EXTRA_COMPONENTS = \
BrowserDownloads.manifest \
DownloadsStartup.js \
DownloadsUI.js \
$(NULL)
EXTRA_JS_MODULES = \
DownloadsCommon.jsm \
$(NULL)
include $(topsrcdir)/config/rules.mk

View File

@ -0,0 +1,17 @@
# Any copyright is dedicated to the Public Domain.
# http://creativecommons.org/publicdomain/zero/1.0/
DEPTH = ../../../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
relativesrcdir = browser/components/downloads/test
include $(DEPTH)/config/autoconf.mk
XPCSHELL_TESTS = unit
DIRS = browser
include $(topsrcdir)/config/rules.mk

View File

@ -0,0 +1,20 @@
# Any copyright is dedicated to the Public Domain.
# http://creativecommons.org/publicdomain/zero/1.0/
DEPTH = ../../../../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
relativesrcdir = browser/components/downloads/test/browser
include $(DEPTH)/config/autoconf.mk
include $(topsrcdir)/config/rules.mk
_BROWSER_FILES = \
browser_basic_functionality.js \
head.js \
$(NULL)
libs:: $(_BROWSER_FILES)
$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/browser/$(relativesrcdir)

View File

@ -0,0 +1,53 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Make sure the downloads panel can display items in the right order and
* contains the expected data.
*/
function gen_test()
{
// Display one of each download state.
const DownloadData = [
{ endTime: 1180493839859239, state: nsIDM.DOWNLOAD_NOTSTARTED },
{ endTime: 1180493839859238, state: nsIDM.DOWNLOAD_DOWNLOADING },
{ endTime: 1180493839859237, state: nsIDM.DOWNLOAD_PAUSED },
{ endTime: 1180493839859236, state: nsIDM.DOWNLOAD_SCANNING },
{ endTime: 1180493839859235, state: nsIDM.DOWNLOAD_QUEUED },
{ endTime: 1180493839859234, state: nsIDM.DOWNLOAD_FINISHED },
{ endTime: 1180493839859233, state: nsIDM.DOWNLOAD_FAILED },
{ endTime: 1180493839859232, state: nsIDM.DOWNLOAD_CANCELED },
{ endTime: 1180493839859231, state: nsIDM.DOWNLOAD_BLOCKED_PARENTAL },
{ endTime: 1180493839859230, state: nsIDM.DOWNLOAD_DIRTY },
{ endTime: 1180493839859229, state: nsIDM.DOWNLOAD_BLOCKED_POLICY },
];
try {
// Ensure that state is reset in case previous tests didn't finish.
for (let yy in gen_resetState()) yield;
// Populate the downloads database with the data required by this test.
for (let yy in gen_addDownloadRows(DownloadData)) yield;
// Open the user interface and wait for data to be fully loaded.
for (let yy in gen_openPanel()) yield;
// Test item data and count. This also tests the ordering of the display.
let richlistbox = document.getElementById("downloadsListBox");
is(richlistbox.children.length, DownloadData.length,
"There is the correct number of richlistitems");
for (let i = 0; i < richlistbox.children.length; i++) {
let element = richlistbox.children[i];
let dataItem = new DownloadsViewItemController(element).dataItem;
is(dataItem.target, DownloadData[i].name, "Download names match up");
is(dataItem.state, DownloadData[i].state, "Download states match up");
is(dataItem.file, DownloadData[i].target, "Download targets match up");
is(dataItem.uri, DownloadData[i].source, "Download sources match up");
}
} finally {
// Clean up when the test finishes.
for (let yy in gen_resetState()) yield;
}
}

View File

@ -0,0 +1,229 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Provides infrastructure for automated download components tests.
*/
////////////////////////////////////////////////////////////////////////////////
//// Globals
XPCOMUtils.defineLazyModuleGetter(this, "FileUtils",
"resource://gre/modules/FileUtils.jsm");
const nsIDM = Ci.nsIDownloadManager;
let gTestTargetFile = FileUtils.getFile("TmpD", ["dm-ui-test.file"]);
gTestTargetFile.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, FileUtils.PERMS_FILE);
registerCleanupFunction(function () {
gTestTargetFile.remove(false);
});
/**
* This objects contains a property for each column in the downloads table.
*/
let gDownloadRowTemplate = {
name: "test-download.txt",
source: "http://www.example.com/test-download.txt",
target: NetUtil.newURI(gTestTargetFile).spec,
startTime: 1180493839859230,
endTime: 1180493839859234,
state: nsIDM.DOWNLOAD_FINISHED,
currBytes: 0,
maxBytes: -1,
preferredAction: 0,
autoResume: 0
};
////////////////////////////////////////////////////////////////////////////////
//// Infrastructure
// All test are run through the test runner.
function test()
{
testRunner.runTest(this.gen_test);
}
/**
* Runs a browser-chrome test defined through a generator function.
*
* This object is a singleton, initialized automatically when this script is
* included. Every browser-chrome test file includes a new copy of this object.
*/
var testRunner = {
_testIterator: null,
_lastEventResult: undefined,
_testRunning: false,
_eventRaised: false,
// --- Main test runner ---
/**
* Runs the test described by the provided generator function asynchronously.
*
* Calling yield in the generator will cause it to wait until continueTest is
* called. The parameter provided to continueTest will be the return value of
* the yield operator.
*
* @param aGenerator
* Test generator function. The function will be called with no
* arguments to retrieve its iterator.
*/
runTest: function TR_runTest(aGenerator) {
waitForExplicitFinish();
testRunner._testIterator = aGenerator();
testRunner.continueTest();
},
/**
* Continues the currently running test.
*
* @param aEventResult
* This will be the return value of the yield operator in the test.
*/
continueTest: function TR_continueTest(aEventResult) {
// Store the last event result, or set it to undefined.
testRunner._lastEventResult = aEventResult;
// Never reenter the main loop, but notify that the event has been raised.
if (testRunner._testRunning) {
testRunner._eventRaised = true;
return;
}
// Enter the main iteration loop.
testRunner._testRunning = true;
try {
do {
// Call the iterator, but don't leave the loop if the expected event is
// raised during the execution of the generator.
testRunner._eventRaised = false;
testRunner._testIterator.send(testRunner._lastEventResult);
} while (testRunner._eventRaised);
}
catch (e) {
// This block catches exceptions raised by the generator, including the
// normal StopIteration exception. Unexpected exceptions are reported as
// test failures.
if (!(e instanceof StopIteration))
ok(false, e);
// In any case, stop the tests in this file.
finish();
}
// Wait for the next event or finish.
testRunner._testRunning = false;
}
};
////////////////////////////////////////////////////////////////////////////////
//// Asynchronous generator-based support subroutines
//
// The following functions are all generators that can be used inside the main
// test generator to perform specific tasks asynchronously. To invoke these
// subroutines correctly, an iteration syntax should be used:
//
// for (let yy in gen_example("Parameter")) yield;
//
function gen_resetState()
{
let statement = Services.downloads.DBConnection.createAsyncStatement(
"DELETE FROM moz_downloads");
try {
statement.executeAsync({
handleResult: function(aResultSet) { },
handleError: function(aError)
{
Cu.reportError(aError);
},
handleCompletion: function(aReason)
{
testRunner.continueTest();
}
});
yield;
} finally {
statement.finalize();
}
// Ensure that the panel is closed and data is unloaded.
DownloadsCommon.data.clear();
DownloadsCommon.data._loadState = DownloadsCommon.data.kLoadNone;
// Wait for focus on the main window.
waitForFocus(testRunner.continueTest);
yield;
}
function gen_addDownloadRows(aDataRows)
{
let columnNames = Object.keys(gDownloadRowTemplate).join(", ");
let parameterNames = Object.keys(gDownloadRowTemplate)
.map(function(n) ":" + n)
.join(", ");
let statement = Services.downloads.DBConnection.createAsyncStatement(
"INSERT INTO moz_downloads (" + columnNames +
") VALUES(" + parameterNames + ")");
try {
// Execute the statement for each of the provided downloads in reverse.
for (let i = aDataRows.length - 1; i >= 0; i--) {
let dataRow = aDataRows[i];
// Populate insert parameters from the provided data.
for (let columnName in gDownloadRowTemplate) {
if (!(columnName in dataRow)) {
// Update the provided row object with data from the global template,
// for columns whose value is not provided explicitly.
dataRow[columnName] = gDownloadRowTemplate[columnName];
}
statement.params[columnName] = dataRow[columnName];
}
// Run the statement asynchronously and wait.
statement.executeAsync({
handleResult: function(aResultSet) { },
handleError: function(aError)
{
Cu.reportError(aError);
},
handleCompletion: function(aReason)
{
testRunner.continueTest();
}
});
yield;
// At each iteration, ensure that the end time in the global template is
// distinct, as this column is used to sort each download in its category.
gDownloadRowTemplate.endTime++;
}
} finally {
statement.finalize();
}
}
function gen_openPanel(aData)
{
// Hook to wait until the test data has been loaded.
let originalOnViewLoadCompleted = DownloadsPanel.onViewLoadCompleted;
DownloadsPanel.onViewLoadCompleted = function () {
DownloadsPanel.onViewLoadCompleted = originalOnViewLoadCompleted;
originalOnViewLoadCompleted.apply(this);
testRunner.continueTest();
};
// Start loading all the downloads from the database asynchronously.
DownloadsCommon.data.ensurePersistentDataLoaded(false);
// Wait for focus on the main window.
waitForFocus(testRunner.continueTest);
yield;
// Open the downloads panel, waiting until loading is completed.
DownloadsPanel.showPanel();
yield;
}

View File

@ -0,0 +1,18 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Provides infrastructure for automated download components tests.
*/
////////////////////////////////////////////////////////////////////////////////
//// Globals
const Cc = Components.classes;
const Ci = Components.interfaces;
const Cu = Components.utils;
const Cr = Components.results;
Cu.import("resource:///modules/DownloadsCommon.jsm");

View File

@ -0,0 +1,37 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Tests for the functions located directly in the "DownloadsCommon" object.
*/
function testFormatTimeLeft(aSeconds, aExpectedValue, aExpectedUnitString)
{
let expected = "";
if (aExpectedValue) {
// Format the expected result based on the current language.
expected = DownloadsCommon.strings[aExpectedUnitString](aExpectedValue);
}
do_check_eq(DownloadsCommon.formatTimeLeft(aSeconds), expected);
}
function run_test()
{
testFormatTimeLeft( 0, "", "");
testFormatTimeLeft( 1, "1", "shortTimeLeftSeconds");
testFormatTimeLeft( 29, "29", "shortTimeLeftSeconds");
testFormatTimeLeft( 30, "30", "shortTimeLeftSeconds");
testFormatTimeLeft( 31, "1", "shortTimeLeftMinutes");
testFormatTimeLeft( 60, "1", "shortTimeLeftMinutes");
testFormatTimeLeft( 89, "1", "shortTimeLeftMinutes");
testFormatTimeLeft( 90, "2", "shortTimeLeftMinutes");
testFormatTimeLeft( 91, "2", "shortTimeLeftMinutes");
testFormatTimeLeft( 3600, "1", "shortTimeLeftHours");
testFormatTimeLeft( 86400, "24", "shortTimeLeftHours");
testFormatTimeLeft( 169200, "47", "shortTimeLeftHours");
testFormatTimeLeft( 172800, "2", "shortTimeLeftDays");
testFormatTimeLeft(8553600, "99", "shortTimeLeftDays");
testFormatTimeLeft(8640000, "99", "shortTimeLeftDays");
}

View File

@ -0,0 +1,5 @@
[DEFAULT]
head = head.js
tail =
[test_DownloadsCommon.js]

View File

@ -1,3 +1,16 @@
# WebappRT doesn't need these instructions, and they don't necessarily work
# with it, but it does use a GRE directory that the GRE shares with Firefox,
# so in order to prevent the instructions from being processed for WebappRT,
# we need to restrict them to the applications that depend on them, i.e.:
#
# b2g: {3c2e2abc-06d4-11e1-ac3b-374f68613e61}
# browser: {ec8030f7-c20a-464f-9b0e-13a3a9e97384}
# mobile/android: {aa3c5121-dab2-40e2-81ca-7ea25febc110}
# mobile/xul: {a23983c0-fd0e-11dc-95ff-0800200c9a66}
#
# In theory we should do this for all these instructions, but in practice it is
# sufficient to do it for the app-startup one, and the file is simpler that way.
component {229fa115-9412-4d32-baf3-2fc407f76fb1} FeedConverter.js
contract @mozilla.org/streamconv;1?from=application/vnd.mozilla.maybe.feed&to=*/* {229fa115-9412-4d32-baf3-2fc407f76fb1}
contract @mozilla.org/streamconv;1?from=application/vnd.mozilla.maybe.video.feed&to=*/* {229fa115-9412-4d32-baf3-2fc407f76fb1}
@ -13,4 +26,4 @@ contract @mozilla.org/browser/feeds/result-writer;1 {49bb6593-3aff-4eb3-a068-271
category JavaScript-global-constructor BrowserFeedWriter @mozilla.org/browser/feeds/result-writer;1
component {792a7e82-06a0-437c-af63-b2d12e808acc} WebContentConverter.js
contract @mozilla.org/embeddor.implemented/web-content-handler-registrar;1 {792a7e82-06a0-437c-af63-b2d12e808acc}
category app-startup WebContentConverter service,@mozilla.org/embeddor.implemented/web-content-handler-registrar;1
category app-startup WebContentConverter service,@mozilla.org/embeddor.implemented/web-content-handler-registrar;1 application={3c2e2abc-06d4-11e1-ac3b-374f68613e61} application={ec8030f7-c20a-464f-9b0e-13a3a9e97384} application={aa3c5121-dab2-40e2-81ca-7ea25febc110} application={a23983c0-fd0e-11dc-95ff-0800200c9a66}

View File

@ -4,5 +4,7 @@ component {4cec1de4-1671-4fc3-a53e-6c539dc77a26} ChromeProfileMigrator.js
contract @mozilla.org/profile/migrator;1?app=browser&type=chrome {4cec1de4-1671-4fc3-a53e-6c539dc77a26}
component {91185366-ba97-4438-acba-48deaca63386} FirefoxProfileMigrator.js
contract @mozilla.org/profile/migrator;1?app=browser&type=firefox {91185366-ba97-4438-acba-48deaca63386}
component {3d2532e3-4932-4774-b7ba-968f5899d3a4} IEProfileMigrator.js
contract @mozilla.org/profile/migrator;1?app=browser&type=ie {3d2532e3-4932-4774-b7ba-968f5899d3a4}
component {4b609ecf-60b2-4655-9df4-dc149e474da1} SafariProfileMigrator.js
contract @mozilla.org/profile/migrator;1?app=browser&type=safari {4b609ecf-60b2-4655-9df4-dc149e474da1}

View File

@ -0,0 +1,678 @@
/* 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";
const Cc = Components.classes;
const Ci = Components.interfaces;
const Cu = Components.utils;
const Cr = Components.results;
const kMainKey = "Software\\Microsoft\\Internet Explorer\\Main";
const kRegMultiSz = 7;
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/NetUtil.jsm");
Cu.import("resource:///modules/MigrationUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "PlacesUtils",
"resource://gre/modules/PlacesUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "ctypes",
"resource://gre/modules/ctypes.jsm");
////////////////////////////////////////////////////////////////////////////////
//// Helpers.
let CtypesHelpers = {
_structs: {},
_functions: {},
_libs: {},
/**
* Must be invoked once before first use of any of the provided helpers.
*/
initialize: function CH_initialize() {
const WORD = ctypes.uint16_t;
const DWORD = ctypes.uint32_t;
const BOOL = ctypes.int;
this._structs.SYSTEMTIME = new ctypes.StructType('SYSTEMTIME', [
{wYear: WORD},
{wMonth: WORD},
{wDayOfWeek: WORD},
{wDay: WORD},
{wHour: WORD},
{wMinute: WORD},
{wSecond: WORD},
{wMilliseconds: WORD}
]);
this._structs.FILETIME = new ctypes.StructType('FILETIME', [
{dwLowDateTime: DWORD},
{dwHighDateTime: DWORD}
]);
try {
this._libs.kernel32 = ctypes.open("Kernel32");
this._functions.FileTimeToSystemTime =
this._libs.kernel32.declare("FileTimeToSystemTime",
ctypes.default_abi,
BOOL,
this._structs.FILETIME.ptr,
this._structs.SYSTEMTIME.ptr);
} catch (ex) {
this.finalize();
}
},
/**
* Must be invoked once after last use of any of the provided helpers.
*/
finalize: function CH_finalize() {
this._structs = {};
this._functions = {};
for each (let lib in this._libs) {
try {
lib.close();
} catch (ex) {}
}
this._libs = {};
},
/**
* Converts a FILETIME struct (2 DWORDS), to a SYSTEMTIME struct.
*
* @param aTimeHi
* Least significant DWORD.
* @param aTimeLo
* Most significant DWORD.
* @return a Date object representing the converted datetime.
*/
fileTimeToDate: function CH_fileTimeToDate(aTimeHi, aTimeLo) {
let fileTime = this._structs.FILETIME();
fileTime.dwLowDateTime = aTimeLo;
fileTime.dwHighDateTime = aTimeHi;
let systemTime = this._structs.SYSTEMTIME();
let result = this._functions.FileTimeToSystemTime(fileTime.address(),
systemTime.address());
if (result == 0)
throw new Error(ctypes.winLastError);
return new Date(systemTime.wYear,
systemTime.wMonth - 1,
systemTime.wDay,
systemTime.wHour,
systemTime.wMinute,
systemTime.wSecond,
systemTime.wMilliseconds);
}
};
/**
* Checks whether an host is an IP (v4 or v6) address.
*
* @param aHost
* The host to check.
* @return whether aHost is an IP address.
*/
function hostIsIPAddress(aHost) {
try {
Services.eTLD.getBaseDomainFromHost(aHost);
} catch (e if e.result == Cr.NS_ERROR_HOST_IS_IP_ADDRESS) {
return true;
} catch (e) {}
return false;
}
/**
* Safely reads a value from the registry.
*
* @param aRoot
* The root registry to use.
* @param aPath
* The registry path to the key.
* @param aKey
* The key name.
* @return The key value or undefined if it doesn't exist. If the key is
* a REG_MULTI_SZ, an array is returned.
*/
function readRegKey(aRoot, aPath, aKey) {
let registry = Cc["@mozilla.org/windows-registry-key;1"].
createInstance(Ci.nsIWindowsRegKey);
try {
registry.open(aRoot, aPath, Ci.nsIWindowsRegKey.ACCESS_READ);
if (registry.hasValue(aKey)) {
let type = registry.getValueType(aKey);
switch (type) {
case kRegMultiSz:
// nsIWindowsRegKey doesn't support REG_MULTI_SZ type out of the box.
let str = registry.readStringValue(aKey);
return [v for each (v in str.split("\0")) if (v)];
case Ci.nsIWindowsRegKey.TYPE_STRING:
return registry.readStringValue(aKey);
case Ci.nsIWindowsRegKey.TYPE_INT:
return registry.readIntValue(aKey);
default:
throw new Error("Unsupported registry value.");
}
}
} catch (ex) {
} finally {
registry.close();
}
return undefined;
};
////////////////////////////////////////////////////////////////////////////////
//// Resources
function Bookmarks() {
}
Bookmarks.prototype = {
type: MigrationUtils.resourceTypes.BOOKMARKS,
get exists() !!this._favoritesFolder,
__favoritesFolder: null,
get _favoritesFolder() {
if (!this.__favoritesFolder) {
let favoritesFolder = Services.dirsvc.get("Favs", Ci.nsIFile);
if (favoritesFolder.exists() && favoritesFolder.isReadable())
this.__favoritesFolder = favoritesFolder;
}
return this.__favoritesFolder;
},
__toolbarFolderName: null,
get _toolbarFolderName() {
if (!this.__toolbarFolderName) {
// Retrieve the name of IE's favorites subfolder that holds the bookmarks
// in the toolbar. This was previously stored in the registry and changed
// in IE7 to always be called "Links".
let folderName = readRegKey(Ci.nsIWindowsRegKey.ROOT_KEY_CURRENT_USER,
"Software\\Microsoft\\Internet Explorer\\Toolbar",
"LinksFolderName");
this.__toolbarFolderName = folderName || "Links";
}
return this.__toolbarFolderName;
},
migrate: function B_migrate(aCallback) {
PlacesUtils.bookmarks.runInBatchMode({
runBatched: (function migrateBatched() {
// Import to the bookmarks menu.
let destFolderId = PlacesUtils.bookmarksMenuFolderId;
if (!MigrationUtils.isStartupMigration) {
destFolderId =
MigrationUtils.createImportedBookmarksFolder("IE", destFolderId);
}
this._migrateFolder(this._favoritesFolder, destFolderId);
aCallback(true);
}).bind(this)
}, null);
},
_migrateFolder: function B__migrateFolder(aSourceFolder, aDestFolderId) {
// TODO (bug 741993): the favorites order is stored in the Registry, at
// HCU\Software\Microsoft\Windows\CurrentVersion\Explorer\MenuOrder\Favorites
// Until we support it, bookmarks are imported in alphabetical order.
let entries = aSourceFolder.directoryEntries;
while (entries.hasMoreElements()) {
let entry = entries.getNext().QueryInterface(Ci.nsIFile);
// Make sure that entry.path == entry.target to not follow .lnk folder
// shortcuts which could lead to infinite cycles.
if (entry.isDirectory() && entry.path == entry.target) {
let destFolderId;
if (entry.leafName == this._toolbarFolderName &&
entry.parent.equals(this._favoritesFolder)) {
// Import to the bookmarks toolbar.
destFolderId = PlacesUtils.toolbarFolderId;
if (!MigrationUtils.isStartupMigration) {
destFolderId =
MigrationUtils.createImportedBookmarksFolder("IE", destFolderId);
}
}
else {
// Import to a new folder.
destFolderId =
PlacesUtils.bookmarks.createFolder(aDestFolderId, entry.leafName,
PlacesUtils.bookmarks.DEFAULT_INDEX);
}
if (entry.isReadable()) {
// Recursively import the folder.
this._migrateFolder(entry, destFolderId);
}
}
else {
// Strip the .url extension, to both check this is a valid link file,
// and get the associated title.
let matches = entry.leafName.match(/(.+)\.url$/);
if (matches) {
let fileHandler = Cc["@mozilla.org/network/protocol;1?name=file"].
getService(Ci.nsIFileProtocolHandler);
let uri = fileHandler.readURLFile(entry);
let title = matches[1];
PlacesUtils.bookmarks.insertBookmark(aDestFolderId,
uri,
PlacesUtils.bookmarks.DEFAULT_INDEX,
title);
}
}
}
}
};
function History() {
}
History.prototype = {
type: MigrationUtils.resourceTypes.HISTORY,
get exists() true,
__typedURLs: null,
get _typedURLs() {
if (!this.__typedURLs) {
// The list of typed URLs is a sort of annotation stored in the registry.
// Currently, IE stores 25 entries and this value is not configurable,
// but we just keep reading up to the first non-existing entry to support
// possible future bumps of this limit.
this.__typedURLs = {};
let registry = Cc["@mozilla.org/windows-registry-key;1"].
createInstance(Ci.nsIWindowsRegKey);
try {
registry.open(Ci.nsIWindowsRegKey.ROOT_KEY_CURRENT_USER,
"Software\\Microsoft\\Internet Explorer\\TypedURLs",
Ci.nsIWindowsRegKey.ACCESS_READ);
for (let entry = 1; registry.hasValue("url" + entry); entry++) {
let url = registry.readStringValue("url" + entry);
this.__typedURLs[url] = true;
}
} catch (ex) {
} finally {
registry.close();
}
}
return this.__typedURLs;
},
migrate: function H_migrate(aCallback) {
let places = [];
let historyEnumerator = Cc["@mozilla.org/profile/migrator/iehistoryenumerator;1"].
createInstance(Ci.nsISimpleEnumerator);
while (historyEnumerator.hasMoreElements()) {
let entry = historyEnumerator.getNext().QueryInterface(Ci.nsIPropertyBag2);
let uri = entry.get("uri").QueryInterface(Ci.nsIURI);
// MSIE stores some types of URLs in its history that we don't handle,
// like HTMLHelp and others. Since we don't properly map handling for
// all of them we just avoid importing them.
if (["http", "https", "ftp", "file"].indexOf(uri.scheme) == -1) {
continue;
}
let title = entry.get("title");
// Embed visits have no title and don't need to be imported.
if (title.length == 0) {
continue;
}
// The typed urls are already fixed-up, so we can use them for comparison.
let transitionType = this._typedURLs[uri.spec] ?
Ci.nsINavHistoryService.TRANSITION_TYPED :
Ci.nsINavHistoryService.TRANSITION_LINK;
let lastVisitTime = entry.get("time");
places.push(
{ uri: uri,
title: title,
visits: [{ transitionType: transitionType,
visitDate: lastVisitTime }]
}
);
}
// Check whether there is any history to import.
if (places.length == 0) {
aCallback(true);
return;
}
PlacesUtils.asyncHistory.updatePlaces(places, {
_success: false,
handleResult: function() {
// Importing any entry is considered a successful import.
this._success = true;
},
handleError: function() {},
handleCompletion: function() {
aCallback(this._success);
}
});
}
};
function Cookies() {
}
Cookies.prototype = {
type: MigrationUtils.resourceTypes.COOKIES,
get exists() !!this._cookiesFolder,
__cookiesFolder: null,
get _cookiesFolder() {
// Cookies are stored in txt files, in a Cookies folder whose path varies
// across the different OS versions. CookD takes care of most of these
// cases, though, in Windows Vista/7, UAC makes a difference.
// If UAC is enabled, the most common destination is CookD/Low. Though,
// if the user runs the application in administrator mode or disables UAC,
// cookies are stored in the original CookD destination. Cause running the
// browser in administrator mode is unsafe and discouraged, we just care
// about the UAC state.
if (!this.__cookiesFolder) {
let cookiesFolder = Services.dirsvc.get("CookD", Ci.nsIFile);
if (cookiesFolder.exists() && cookiesFolder.isReadable()) {
// Check if UAC is enabled.
if (Services.appinfo.QueryInterface(Ci.nsIWinAppHelper).userCanElevate) {
cookiesFolder.append("Low");
}
this.__cookiesFolder = cookiesFolder;
}
}
return this.__cookiesFolder;
},
migrate: function C_migrate(aCallback) {
CtypesHelpers.initialize();
let cookiesGenerator = (function genCookie() {
let success = false;
let entries = this._cookiesFolder.directoryEntries;
while (entries.hasMoreElements()) {
let entry = entries.getNext().QueryInterface(Ci.nsIFile);
// Skip eventual bogus entries.
if (!entry.isFile() || !/\.txt$/.test(entry.leafName))
continue;
this._readCookieFile(entry, function(aSuccess) {
// Importing even a single cookie file is considered a success.
if (aSuccess)
success = true;
try {
cookiesGenerator.next();
} catch (ex) {}
});
yield;
}
CtypesHelpers.finalize();
aCallback(success);
}).apply(this);
cookiesGenerator.next();
},
_readCookieFile: function C__readCookieFile(aFile, aCallback) {
let fileReader = Cc["@mozilla.org/files/filereader;1"].
createInstance(Ci.nsIDOMFileReader);
fileReader.addEventListener("loadend", (function onLoadEnd() {
fileReader.removeEventListener("loadend", onLoadEnd, false);
if (fileReader.readyState != fileReader.DONE) {
Cu.reportError("Could not read cookie contents: " + fileReader.error);
aCallback(false);
return;
}
let success = true;
try {
this._parseCookieBuffer(fileReader.result);
} catch (ex) {
Components.utils.reportError("Unable to migrate cookie: " + ex);
success = false;
} finally {
aCallback(success);
}
}).bind(this), false);
fileReader.readAsText(File(aFile));
},
/**
* Parses a cookie file buffer and returns an array of the contained cookies.
*
* The cookie file format is a newline-separated-values with a "*" used as
* delimeter between multiple records.
* Each cookie has the following fields:
* - name
* - value
* - host/path
* - flags
* - Expiration time most significant integer
* - Expiration time least significant integer
* - Creation time most significant integer
* - Creation time least significant integer
* - Record delimiter "*"
*
* @note All the times are in FILETIME format.
*/
_parseCookieBuffer: function C__parseCookieBuffer(aTextBuffer) {
// Note the last record is an empty string.
let records = [r for each (r in aTextBuffer.split("*\n")) if (r)];
for (let record of records) {
let [name, value, hostpath, flags,
expireTimeLo, expireTimeHi] = record.split("\n");
// IE stores deleted cookies with a zero-length value, skip them.
if (value.length == 0)
continue;
let hostLen = hostpath.indexOf("/");
let host = hostpath.substr(0, hostLen);
// For a non-null domain, assume it's what Mozilla considers
// a domain cookie. See bug 222343.
if (host.length > 0) {
// Fist delete any possible extant matching host cookie.
Services.cookies.remove(host, name, path, false);
// Now make it a domain cookie.
if (host[0] != "." && !hostIsIPAddress(host))
host = "." + host;
}
let path = hostpath.substr(hostLen);
let expireTime = CtypesHelpers.fileTimeToDate(Number(expireTimeHi),
Number(expireTimeLo));
Services.cookies.add(host,
path,
name,
value,
Number(flags) & 0x1, // secure
false, // httpOnly
false, // session
expireTime);
}
}
};
function Settings() {
}
Settings.prototype = {
type: MigrationUtils.resourceTypes.SETTINGS,
get exists() true,
migrate: function S_migrate(aCallback) {
// Converts from yes/no to a boolean.
function yesNoToBoolean(v) v == "yes";
// Converts source format like "en-us,ar-kw;q=0.7,ar-om;q=0.3" into
// destination format like "en-us, ar-kw, ar-om".
// Final string is sorted by quality (q=) param.
function parseAcceptLanguageList(v) {
return v.match(/([a-z]{1,8}(-[a-z]{1,8})?)\s*(;\s*q\s*=\s*(1|0\.[0-9]+))?/gi)
.sort(function (a , b) {
let qA = parseFloat(a.split(";q=")[1]) || 1.0;
let qB = parseFloat(b.split(";q=")[1]) || 1.0;
return qA < qB ? 1 : qA == qB ? 0 : -1;
})
.map(function(a) a.split(";")[0]);
}
// For reference on some of the available IE Registry settings:
// * http://msdn.microsoft.com/en-us/library/cc980058%28v=prot.13%29.aspx
// * http://msdn.microsoft.com/en-us/library/cc980059%28v=prot.13%29.aspx
// Note that only settings exposed in our UI should be migrated.
this._set("Software\\Microsoft\\Internet Explorer\\International",
"AcceptLanguage",
"intl.accept_languages",
parseAcceptLanguageList);
// TODO (bug 745853): For now, only x-western font is translated.
this._set("Software\\Microsoft\\Internet Explorer\\International\\Scripts\\3",
"IEFixedFontName",
"font.name.monospace.x-western");
this._set(kMainKey,
"Use FormSuggest",
"browser.formfill.enable",
yesNoToBoolean);
this._set(kMainKey,
"FormSuggest Passwords",
"signon.rememberSignons",
yesNoToBoolean);
this._set(kMainKey,
"Anchor Underline",
"browser.underline_anchors",
yesNoToBoolean);
this._set(kMainKey,
"Display Inline Images",
"permissions.default.image",
function (v) yesNoToBoolean(v) ? 1 : 2);
this._set(kMainKey,
"Move System Caret",
"accessibility.browsewithcaret",
yesNoToBoolean);
this._set("Software\\Microsoft\\Internet Explorer\\Settings",
"Always Use My Colors",
"browser.display.use_document_colors",
function (v) !Boolean(v));
this._set("Software\\Microsoft\\Internet Explorer\\Settings",
"Always Use My Font Face",
"browser.display.use_document_fonts",
function (v) !Boolean(v));
this._set(kMainKey,
"SmoothScroll",
"general.smoothScroll",
Boolean);
this._set("Software\\Microsoft\\Internet Explorer\\TabbedBrowsing\\",
"WarnOnClose",
"browser.tabs.warnOnClose",
Boolean);
this._set("Software\\Microsoft\\Internet Explorer\\TabbedBrowsing\\",
"OpenInForeground",
"browser.tabs.loadInBackground",
function (v) !Boolean(v));
aCallback(true);
},
/**
* Reads a setting from the Registry and stores the converted result into
* the appropriate Firefox preference.
*
* @param aPath
* Registry path under HKCU.
* @param aKey
* Name of the key.
* @param aPref
* Firefox preference.
* @param [optional] aTransformFn
* Conversion function from the Registry format to the pref format.
*/
_set: function S__set(aPath, aKey, aPref, aTransformFn) {
let value = readRegKey(Ci.nsIWindowsRegKey.ROOT_KEY_CURRENT_USER,
aPath, aKey);
// Don't import settings that have never been flipped.
if (value === undefined)
return;
if (aTransformFn)
value = aTransformFn(value);
switch (typeof(value)) {
case "string":
Services.prefs.setCharPref(aPref, value);
break;
case "number":
Services.prefs.setIntPref(aPref, value);
break;
case "boolean":
Services.prefs.setBoolPref(aPref, value);
break;
default:
throw new Error("Unexpected value type: " + typeof(value));
}
}
};
////////////////////////////////////////////////////////////////////////////////
//// Migrator
function IEProfileMigrator()
{
}
IEProfileMigrator.prototype = Object.create(MigratorPrototype);
IEProfileMigrator.prototype.getResources = function IE_getResources() {
let resources = [
new Bookmarks()
, new History()
, new Cookies()
, new Settings()
];
return [r for each (r in resources) if (r.exists)];
};
Object.defineProperty(IEProfileMigrator.prototype, "sourceHomePageURL", {
get: function IE_get_sourceHomePageURL() {
let defaultStartPage = readRegKey(Ci.nsIWindowsRegKey.ROOT_KEY_LOCAL_MACHINE,
kMainKey, "Default_Page_URL");
let startPage = readRegKey(Ci.nsIWindowsRegKey.ROOT_KEY_CURRENT_USER,
kMainKey, "Start Page");
// If the user didn't customize the Start Page, he is still on the default
// page, that may be considered the equivalent of our about:home. There's
// no reason to retain it, since it is heavily targeted to IE.
let homepage = startPage != defaultStartPage ? startPage : "";
// IE7+ supports secondary home pages located in a REG_MULTI_SZ key. These
// are in addition to the Start Page, and no empty entries are possible,
// thus a Start Page is always defined if any of these exists, though it
// may be the default one.
let secondaryPages = readRegKey(Ci.nsIWindowsRegKey.ROOT_KEY_CURRENT_USER,
kMainKey, "Secondary Start Pages");
if (secondaryPages) {
if (homepage)
secondaryPages.unshift(homepage);
homepage = secondaryPages.join("|");
}
return homepage;
}
});
IEProfileMigrator.prototype.classDescription = "IE Profile Migrator";
IEProfileMigrator.prototype.contractID = "@mozilla.org/profile/migrator;1?app=browser&type=ie";
IEProfileMigrator.prototype.classID = Components.ID("{3d2532e3-4932-4774-b7ba-968f5899d3a4}");
const NSGetFactory = XPCOMUtils.generateNSGetFactory([IEProfileMigrator]);

View File

@ -55,12 +55,10 @@ EXTRA_PP_COMPONENTS = \
$(NULL)
ifeq ($(OS_ARCH)_$(GNU_CXX),WINNT_)
CPPSRCS += nsIEProfileMigrator.cpp \
nsBrowserProfileMigratorUtils.cpp \
nsIEHistoryEnumerator.cpp \
$(NULL)
CPPSRCS += nsIEHistoryEnumerator.cpp
EXTRA_PP_COMPONENTS += SafariProfileMigrator.js \
EXTRA_PP_COMPONENTS += IEProfileMigrator.js \
SafariProfileMigrator.js \
$(NULL)
endif

View File

@ -1,161 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is The Browser Profile Migrator.
*
* The Initial Developer of the Original Code is Ben Goodger.
* Portions created by the Initial Developer are Copyright (C) 2004
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Ben Goodger <ben@bengoodger.com>
* Asaf Romano <mozilla.mano@sent.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsBrowserProfileMigratorUtils.h"
#include "nsINavBookmarksService.h"
#include "nsBrowserCompsCID.h"
#include "nsToolkitCompsCID.h"
#include "nsIPlacesImportExportService.h"
#include "nsIFile.h"
#include "nsIProperties.h"
#include "nsIProfileMigrator.h"
#include "nsIURI.h"
#include "nsNetUtil.h"
#include "nsISupportsPrimitives.h"
#include "nsAppDirectoryServiceDefs.h"
#include "nsIRDFService.h"
#include "nsIStringBundle.h"
#include "nsXPCOMCID.h"
void SetUnicharPref(const char* aPref, const nsAString& aValue,
nsIPrefBranch* aPrefs)
{
nsCOMPtr<nsISupportsString> supportsString =
do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID);
if (supportsString) {
supportsString->SetData(aValue);
aPrefs->SetComplexValue(aPref, NS_GET_IID(nsISupportsString),
supportsString);
}
}
void SetProxyPref(const nsAString& aHostPort, const char* aPref,
const char* aPortPref, nsIPrefBranch* aPrefs)
{
nsCOMPtr<nsIURI> uri;
nsCAutoString host;
PRInt32 portValue;
// try parsing it as a URI first
if (NS_SUCCEEDED(NS_NewURI(getter_AddRefs(uri), aHostPort))
&& NS_SUCCEEDED(uri->GetHost(host))
&& !host.IsEmpty()
&& NS_SUCCEEDED(uri->GetPort(&portValue))) {
SetUnicharPref(aPref, NS_ConvertUTF8toUTF16(host), aPrefs);
aPrefs->SetIntPref(aPortPref, portValue);
}
else {
nsAutoString hostPort(aHostPort);
PRInt32 portDelimOffset = hostPort.RFindChar(':');
if (portDelimOffset > 0) {
SetUnicharPref(aPref, Substring(hostPort, 0, portDelimOffset), aPrefs);
nsAutoString port(Substring(hostPort, portDelimOffset + 1));
nsresult stringErr;
portValue = port.ToInteger(&stringErr);
if (NS_SUCCEEDED(stringErr))
aPrefs->SetIntPref(aPortPref, portValue);
}
else
SetUnicharPref(aPref, hostPort, aPrefs);
}
}
void ParseOverrideServers(const nsAString& aServers, nsIPrefBranch* aBranch)
{
// Windows (and Opera) formats its proxy override list in the form:
// server;server;server where server is a server name or ip address,
// or "<local>". Mozilla's format is server,server,server, and <local>
// must be translated to "localhost,127.0.0.1"
nsAutoString override(aServers);
PRInt32 left = 0, right = 0;
for (;;) {
right = override.FindChar(';', right);
const nsAString& host = Substring(override, left,
(right < 0 ? override.Length() : right) - left);
if (host.EqualsLiteral("<local>"))
override.Replace(left, 7, NS_LITERAL_STRING("localhost,127.0.0.1"));
if (right < 0)
break;
left = right + 1;
override.Replace(right, 1, NS_LITERAL_STRING(","));
}
SetUnicharPref("network.proxy.no_proxies_on", override, aBranch);
}
void GetMigrateDataFromArray(MigrationData* aDataArray, PRInt32 aDataArrayLength,
bool aReplace, nsIFile* aSourceProfile,
PRUint16* aResult)
{
nsCOMPtr<nsIFile> sourceFile;
bool exists;
MigrationData* cursor;
MigrationData* end = aDataArray + aDataArrayLength;
for (cursor = aDataArray; cursor < end && cursor->fileName; ++cursor) {
// When in replace mode, all items can be imported.
// When in non-replace mode, only items that do not require file replacement
// can be imported.
if (aReplace || !cursor->replaceOnly) {
aSourceProfile->Clone(getter_AddRefs(sourceFile));
sourceFile->Append(nsDependentString(cursor->fileName));
sourceFile->Exists(&exists);
if (exists)
*aResult |= cursor->sourceFlag;
}
NS_Free(cursor->fileName);
cursor->fileName = nsnull;
}
}
void
GetProfilePath(nsIProfileStartup* aStartup, nsCOMPtr<nsIFile>& aProfileDir)
{
if (aStartup) {
aStartup->GetDirectory(getter_AddRefs(aProfileDir));
}
else {
nsCOMPtr<nsIProperties> dirSvc
(do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID));
if (dirSvc) {
dirSvc->Get(NS_APP_USER_PROFILE_50_DIR, NS_GET_IID(nsIFile),
(void**) getter_AddRefs(aProfileDir));
}
}
}

View File

@ -1,103 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is The Browser Profile Migrator.
*
* The Initial Developer of the Original Code is Ben Goodger.
* Portions created by the Initial Developer are Copyright (C) 2004
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Ben Goodger <ben@bengoodger.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef browserprofilemigratorutils___h___
#define browserprofilemigratorutils___h___
#define MIGRATION_ITEMBEFOREMIGRATE "Migration:ItemBeforeMigrate"
#define MIGRATION_ITEMMIGRATEERROR "Migration:ItemError"
#define MIGRATION_ITEMAFTERMIGRATE "Migration:ItemAfterMigrate"
#define MIGRATION_STARTED "Migration:Started"
#define MIGRATION_ENDED "Migration:Ended"
#define NOTIFY_OBSERVERS(message, item) \
mObserverService->NotifyObservers(nsnull, message, item)
#define COPY_DATA(func, replace, itemIndex) \
if ((aItems & itemIndex || !aItems)) { \
nsAutoString index; \
index.AppendInt(itemIndex); \
NOTIFY_OBSERVERS(MIGRATION_ITEMBEFOREMIGRATE, index.get()); \
if (NS_FAILED(func(replace))) \
NOTIFY_OBSERVERS(MIGRATION_ITEMMIGRATEERROR, index.get()); \
NOTIFY_OBSERVERS(MIGRATION_ITEMAFTERMIGRATE, index.get()); \
}
#define NC_URI(property) \
NS_LITERAL_CSTRING("http://home.netscape.com/NC-rdf#"#property)
#define BATCH_ACTION_HISTORY 0
#define BATCH_ACTION_HISTORY_REPLACE 1
#define BATCH_ACTION_BOOKMARKS 2
#define BATCH_ACTION_BOOKMARKS_REPLACE 3
#include "nsIPrefBranch.h"
#include "nsIFile.h"
#include "nsStringAPI.h"
#include "nsCOMPtr.h"
class nsIProfileStartup;
void SetUnicharPref(const char* aPref, const nsAString& aValue,
nsIPrefBranch* aPrefs);
// Proxy utilities shared by the Opera and IE migrators
void ParseOverrideServers(const nsAString& aServers, nsIPrefBranch* aBranch);
void SetProxyPref(const nsAString& aHostPort, const char* aPref,
const char* aPortPref, nsIPrefBranch* aPrefs);
struct MigrationData {
PRUnichar* fileName;
PRUint32 sourceFlag;
bool replaceOnly;
};
class nsILocalFile;
void GetMigrateDataFromArray(MigrationData* aDataArray,
PRInt32 aDataArrayLength,
bool aReplace,
nsIFile* aSourceProfile,
PRUint16* aResult);
// get the base directory of the *target* profile
// this is already cloned, modify it to your heart's content
void GetProfilePath(nsIProfileStartup* aStartup, nsCOMPtr<nsIFile>& aProfileDir);
#endif

File diff suppressed because it is too large Load Diff

View File

@ -1,208 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 2002
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
/* Private header describing the class to migrate preferences from
Windows Trident to Gecko. This is a virtual class. */
#ifndef ieprofilemigrator___h___
#define ieprofilemigrator___h___
#include <time.h>
#include <windows.h>
#include <ole2.h>
#include "nsIBrowserProfileMigrator.h"
#include "nsIObserverService.h"
#include "nsTArray.h"
#include "nsINavHistoryService.h"
class nsIFile;
class nsICookieManager2;
class nsIRDFResource;
class nsINavBookmarksService;
class nsIPrefBranch;
struct SignonData {
PRUnichar* user;
PRUnichar* pass;
char* realm;
};
// VC11 doesn't ship with pstore.h, so we go ahead and define the stuff that
// we need from that file here.
class IEnumPStoreItems : public IUnknown {
public:
virtual HRESULT STDMETHODCALLTYPE Next(DWORD celt, LPWSTR* rgelt,
DWORD* pceltFetched) = 0;
virtual HRESULT STDMETHODCALLTYPE Skip(DWORD celt) = 0;
virtual HRESULT STDMETHODCALLTYPE Reset() = 0;
virtual HRESULT STDMETHODCALLTYPE Clone(IEnumPStoreItems** ppenum) = 0;
};
class IEnumPStoreTypes; // not used
struct PST_PROVIDERINFO; // not used
struct PST_TYPEINFO; // not used
struct PST_PROMPTINFO; // not used
struct PST_ACCESSRULESET; // not used
typedef DWORD PST_KEY;
typedef DWORD PST_ACCESSMODE;
class IPStore : public IUnknown {
public:
virtual HRESULT STDMETHODCALLTYPE GetInfo(PST_PROVIDERINFO** ppProperties) = 0;
virtual HRESULT STDMETHODCALLTYPE GetProvParam(DWORD dwParam, DWORD* pcbData,
BYTE** ppbData, DWORD dwFlags) = 0;
virtual HRESULT STDMETHODCALLTYPE SetProvParam(DWORD dwParam, DWORD cbData,
BYTE* pbData, DWORD dwFlags) = 0;
virtual HRESULT STDMETHODCALLTYPE CreateType(PST_KEY Key, const GUID* pType,
PST_TYPEINFO* pInfo, DWORD dwFlags) = 0;
virtual HRESULT STDMETHODCALLTYPE GetTypeInfo(PST_KEY Key, const GUID* pType,
PST_TYPEINFO** ppInfo, DWORD dwFlags) = 0;
virtual HRESULT STDMETHODCALLTYPE DeleteType(PST_KEY Key, const GUID* pType,
DWORD dwFlags) = 0;
virtual HRESULT STDMETHODCALLTYPE CreateSubtype(PST_KEY Key, const GUID* pType,
const GUID* pSubtype, PST_TYPEINFO* pInfo,
PST_ACCESSRULESET* pRules, DWORD dwFlags) = 0;
virtual HRESULT STDMETHODCALLTYPE GetSubtypeInfo(PST_KEY Key, const GUID* pType,
const GUID* pSubtype, PST_TYPEINFO** ppInfo,
DWORD dwFlags) = 0;
virtual HRESULT STDMETHODCALLTYPE DeleteSubtype(PST_KEY Key, const GUID* pType,
const GUID* pSubtype, DWORD dwFlags) = 0;
virtual HRESULT STDMETHODCALLTYPE ReadAccessRuleset(PST_KEY Key, const GUID* pType,
const GUID* pSubtype, PST_ACCESSRULESET** ppRules,
DWORD dwFlags) = 0;
virtual HRESULT STDMETHODCALLTYPE WriteAccessRuleset(PST_KEY Key, const GUID* pType,
const GUID* pSubtype, PST_ACCESSRULESET* pRules,
DWORD dwFlags) = 0;
virtual HRESULT STDMETHODCALLTYPE EnumTypes(PST_KEY Key, DWORD dwFlags, IEnumPStoreTypes** ppenum) = 0;
virtual HRESULT STDMETHODCALLTYPE EnumSubtypes(PST_KEY Key, const GUID* pType,
DWORD dwFlags, IEnumPStoreTypes** ppenum) = 0;
virtual HRESULT STDMETHODCALLTYPE DeleteItem(PST_KEY Key, const GUID* pItemType,
const GUID* pItemSubtype, LPCWSTR szItemName,
PST_PROMPTINFO* pPromptInfo, DWORD dwFlags) = 0;
virtual HRESULT STDMETHODCALLTYPE ReadItem(PST_KEY Key, const GUID* pItemType,
const GUID* pItemSubtype, LPCWSTR szItemName,
DWORD* pcbData, BYTE** ppbData,
PST_PROMPTINFO* pPromptInfo, DWORD dwFlags) = 0;
virtual HRESULT STDMETHODCALLTYPE WriteItem(PST_KEY Key, const GUID* pItemType,
const GUID* pItemSubtype, LPCWSTR szItemName,
DWORD cbData, BYTE* pbData,
PST_PROMPTINFO* pPromptInfo, DWORD dwFlags) = 0;
virtual HRESULT STDMETHODCALLTYPE OpenItem(PST_KEY Key, const GUID* pItemType,
const GUID* pItemSubtype, LPCWSTR szItemName,
PST_ACCESSMODE ModeFlags, PST_PROMPTINFO* pPromptInfo,
DWORD dwFlags) = 0;
virtual HRESULT STDMETHODCALLTYPE CloseItem(PST_KEY Key, const GUID* pItemType,
const GUID* pItemSubtype, LPCWSTR szItemName,
DWORD dwFlags) = 0;
virtual HRESULT STDMETHODCALLTYPE EnumItems(PST_KEY Key, const GUID* pItemType,
const GUID* pItemSubtype, DWORD dwFlags,
IEnumPStoreItems** ppenum) = 0;
};
class nsIEProfileMigrator : public nsIBrowserProfileMigrator,
public nsINavHistoryBatchCallback {
public:
NS_DECL_NSIBROWSERPROFILEMIGRATOR
NS_DECL_NSINAVHISTORYBATCHCALLBACK
NS_DECL_ISUPPORTS
nsIEProfileMigrator();
virtual ~nsIEProfileMigrator();
protected:
nsresult CopyPreferences(bool aReplace);
nsresult CopyStyleSheet(bool aReplace);
nsresult CopyCookies(bool aReplace);
nsresult CopyProxyPreferences(nsIPrefBranch* aPrefs);
nsresult CopySecurityPrefs(nsIPrefBranch* aPrefs);
/**
* Migrate history to Places.
* This will end up calling CopyHistoryBatched helper, that provides batch
* support. Batching allows for better performances and integrity.
*
* @param aReplace
* Indicates if we should replace current history or append to it.
*/
nsresult CopyHistory(bool aReplace);
nsresult CopyHistoryBatched(bool aReplace);
bool KeyIsURI(const nsAString& aKey, char** aRealm);
nsresult CopyPasswords(bool aReplace);
nsresult MigrateSiteAuthSignons(IPStore* aPStore);
nsresult GetSignonsListFromPStore(IPStore* aPStore, nsTArray<SignonData>* aSignonsFound);
nsresult ResolveAndMigrateSignons(IPStore* aPStore, nsTArray<SignonData>* aSignonsFound);
void EnumerateUsernames(const nsAString& aKey, PRUnichar* aData, unsigned long aCount, nsTArray<SignonData>* aSignonsFound);
void GetUserNameAndPass(unsigned char* data, unsigned long len, unsigned char** username, unsigned char** pass);
nsresult CopyFormData(bool aReplace);
nsresult AddDataToFormHistory(const nsAString& aKey, PRUnichar* data, unsigned long len);
/**
* Migrate bookmarks to Places.
* This will end up calling CopyFavoritesBatched helper, that provides batch
* support. Batching allows for better performances and integrity.
*
* @param aReplace
* Indicates if we should replace current bookmarks or append to them.
* When appending we will usually default to bookmarks menu.
*/
nsresult CopyFavorites(bool aReplace);
nsresult CopyFavoritesBatched(bool aReplace);
void ResolveShortcut(const nsString &aFileName, char** aOutURL);
nsresult ParseFavoritesFolder(nsIFile* aDirectory,
PRInt64 aParentFolder,
nsINavBookmarksService* aBookmarksService,
const nsAString& aPersonalToolbarFolderName,
bool aIsAtRootLevel);
nsresult CopySmartKeywords(nsINavBookmarksService* aBMS,
PRInt64 aParentFolder);
nsresult CopyCookiesFromBuffer(char *aBuffer, PRUint32 aBufferLength,
nsICookieManager2 *aCookieManager);
void DelimitField(char **aBuffer, const char *aBufferEnd, char **aField);
time_t FileTimeToTimeT(const char *aLowDateIntString,
const char *aHighDateIntString);
void GetUserStyleSheetFile(nsIFile **aUserFile);
bool TestForIE7();
private:
nsCOMPtr<nsIObserverService> mObserverService;
};
#endif

View File

@ -3,4 +3,4 @@ head = head_migration.js
tail =
[test_IE_bookmarks.js]
skip-if = os != "win"
skip-if = true

View File

@ -38,6 +38,10 @@
#
# ***** END LICENSE BLOCK *****
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "DownloadsCommon",
"resource:///modules/DownloadsCommon.jsm");
var gMainPane = {
_pane: null,
@ -55,12 +59,25 @@ var gMainPane = {
this.updateBrowserStartupLastSession();
this.startupPagePrefChanged();
this.setupDownloadsWindowOptions();
// Notify observers that the UI is now ready
Components.classes["@mozilla.org/observer-service;1"]
.getService(Components.interfaces.nsIObserverService)
.notifyObservers(window, "main-pane-loaded", null);
},
setupDownloadsWindowOptions: function ()
{
var showWhenDownloading = document.getElementById("showWhenDownloading");
var closeWhenDone = document.getElementById("closeWhenDone");
// These radio-buttons should not be visible if we have enabled the Downloads Panel.
let shouldHide = !DownloadsCommon.useToolkitUI;
showWhenDownloading.hidden = shouldHide;
closeWhenDone.hidden = shouldHide;
},
// HOME PAGE
/*

View File

@ -1,4 +1,17 @@
# WebappRT doesn't need these instructions, and they don't necessarily work
# with it, but it does use a GRE directory that the GRE shares with Firefox,
# so in order to prevent the instructions from being processed for WebappRT,
# we need to restrict them to the applications that depend on them, i.e.:
#
# b2g: {3c2e2abc-06d4-11e1-ac3b-374f68613e61}
# browser: {ec8030f7-c20a-464f-9b0e-13a3a9e97384}
# mobile/android: {aa3c5121-dab2-40e2-81ca-7ea25febc110}
# mobile/xul: {a23983c0-fd0e-11dc-95ff-0800200c9a66}
#
# In theory we should do this for all these instructions, but in practice it is
# sufficient to do it for the app-startup one, and the file is simpler that way.
component {c31f4883-839b-45f6-82ad-a6a9bc5ad599} nsPrivateBrowsingService.js
contract @mozilla.org/privatebrowsing;1 {c31f4883-839b-45f6-82ad-a6a9bc5ad599}
category command-line-handler m-privatebrowsing @mozilla.org/privatebrowsing;1
category app-startup nsPrivateBrowsingService service,@mozilla.org/privatebrowsing;1
category app-startup nsPrivateBrowsingService service,@mozilla.org/privatebrowsing;1 application={3c2e2abc-06d4-11e1-ac3b-374f68613e61} application={ec8030f7-c20a-464f-9b0e-13a3a9e97384} application={aa3c5121-dab2-40e2-81ca-7ea25febc110} application={a23983c0-fd0e-11dc-95ff-0800200c9a66}

View File

@ -1,5 +1,18 @@
# WebappRT doesn't need these instructions, and they don't necessarily work
# with it, but it does use a GRE directory that the GRE shares with Firefox,
# so in order to prevent the instructions from being processed for WebappRT,
# we need to restrict them to the applications that depend on them, i.e.:
#
# b2g: {3c2e2abc-06d4-11e1-ac3b-374f68613e61}
# browser: {ec8030f7-c20a-464f-9b0e-13a3a9e97384}
# mobile/android: {aa3c5121-dab2-40e2-81ca-7ea25febc110}
# mobile/xul: {a23983c0-fd0e-11dc-95ff-0800200c9a66}
#
# In theory we should do this for all these instructions, but in practice it is
# sufficient to do it for the app-startup one, and the file is simpler that way.
component {5280606b-2510-4fe0-97ef-9b5a22eafe6b} nsSessionStore.js
contract @mozilla.org/browser/sessionstore;1 {5280606b-2510-4fe0-97ef-9b5a22eafe6b}
component {ec7a6c20-e081-11da-8ad9-0800200c9a66} nsSessionStartup.js
contract @mozilla.org/browser/sessionstartup;1 {ec7a6c20-e081-11da-8ad9-0800200c9a66}
category app-startup nsSessionStartup service,@mozilla.org/browser/sessionstartup;1
category app-startup nsSessionStartup service,@mozilla.org/browser/sessionstartup;1 application={3c2e2abc-06d4-11e1-ac3b-374f68613e61} application={ec8030f7-c20a-464f-9b0e-13a3a9e97384} application={aa3c5121-dab2-40e2-81ca-7ea25febc110} application={a23983c0-fd0e-11dc-95ff-0800200c9a66}

View File

@ -30,8 +30,6 @@ let TestObserver = {
"sourceName is correct");
if (++errors == 2) {
is(lastWindowId, aSubject.outerWindowID,
"same window ID (" + lastWindowId + ") for both errors");
executeSoon(performTest);
}
else {

View File

@ -308,6 +308,9 @@
@BINPATH@/components/nsBrowserGlue.js
@BINPATH@/components/nsSetDefaultBrowser.manifest
@BINPATH@/components/nsSetDefaultBrowser.js
@BINPATH@/components/BrowserDownloads.manifest
@BINPATH@/components/DownloadsStartup.js
@BINPATH@/components/DownloadsUI.js
@BINPATH@/components/BrowserPlaces.manifest
@BINPATH@/components/BrowserPageThumbs.manifest
@BINPATH@/components/nsPrivateBrowsingService.manifest
@ -409,6 +412,7 @@
@BINPATH@/components/ChromeProfileMigrator.js
@BINPATH@/components/FirefoxProfileMigrator.js
#ifdef XP_WIN
@BINPATH@/components/IEProfileMigrator.js
@BINPATH@/components/SafariProfileMigrator.js
#endif
#ifdef XP_MACOSX
@ -499,6 +503,9 @@
#ifdef MOZ_SERVICES_SYNC
@BINPATH@/@PREF_DIR@/services-sync.js
#endif
#ifdef MOZ_WEBAPP_RUNTIME
@BINPATH@/@PREF_DIR@/webapprt@mozilla.org/prefs.js
#endif
@BINPATH@/greprefs.js
@BINPATH@/defaults/autoconfig/platform.js
@BINPATH@/defaults/autoconfig/prefcalls.js
@ -620,3 +627,14 @@ bin/components/@DLL_PREFIX@nkgnomevfs@DLL_SUFFIX@
@BINPATH@/*.xqs
@BINPATH@/components/*.xqs
#endif
#ifdef MOZ_WEBAPP_RUNTIME
; [Webapp Runtime]
@BINPATH@/webapprt-stub@BIN_SUFFIX@
@BINPATH@/chrome/webapprt@JAREXT@
@BINPATH@/chrome/webapprt.manifest
@BINPATH@/components/WebappRTComponents.manifest
@BINPATH@/components/WebappRTDirectoryProvider.js
@BINPATH@/components/WebappRTCommandLineHandler.js
@BINPATH@/webapprt.ini
#endif

View File

@ -0,0 +1,41 @@
<!-- 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/. -->
<!-- LOCALIZATION NOTE (indicator.tooltiptext):
Tooltip for the indicator that displays the progress of ongoing downloads.
-->
<!ENTITY indicator.tooltiptext "Downloads">
<!-- LOCALIZATION NOTE (downloads.title):
Used by screen readers to describe the Downloads Panel.
-->
<!ENTITY downloads.title "Downloads">
<!ENTITY cmd.pause.label "Pause">
<!ENTITY cmd.pause.accesskey "P">
<!ENTITY cmd.resume.label "Resume">
<!ENTITY cmd.resume.accesskey "R">
<!ENTITY cmd.cancel.label "Cancel">
<!ENTITY cmd.cancel.accesskey "C">
<!-- LOCALIZATION NOTE (cmd.show.label, cmd.show.accesskey, cmd.showMac.label,
cmd.showMac.accesskey):
The show and showMac commands are never shown together, thus they can share
the same access key (though the two access keys can also be different).
-->
<!ENTITY cmd.show.label "Open Containing Folder">
<!ENTITY cmd.show.accesskey "F">
<!ENTITY cmd.showMac.label "Show In Finder">
<!ENTITY cmd.showMac.accesskey "F">
<!ENTITY cmd.retry.label "Retry">
<!ENTITY cmd.goToDownloadPage.label "Go To Download Page">
<!ENTITY cmd.goToDownloadPage.accesskey "G">
<!ENTITY cmd.copyDownloadLink.label "Copy Download Link">
<!ENTITY cmd.copyDownloadLink.accesskey "L">
<!ENTITY cmd.removeFromList.label "Remove From List">
<!ENTITY cmd.removeFromList.accesskey "e">
<!ENTITY cmd.clearList.label "Clear List">
<!ENTITY cmd.clearList.accesskey "a">
<!ENTITY downloadshistory.label "Show All Downloads">
<!ENTITY downloadshistory.accesskey "S">

View File

@ -0,0 +1,72 @@
# 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/.
# LOCALIZATION NOTE (stateStarting):
# Indicates that the download is starting.
stateStarting=Starting…
# LOCALIZATION NOTE (stateScanning):
# Indicates that an external program is scanning the download for viruses.
stateScanning=Scanning for viruses…
# LOCALIZATION NOTE (stateFailed):
# Indicates that the download failed because of an error.
stateFailed=Failed
# LOCALIZATION NOTE (statePaused):
# Indicates that the download was paused by the user.
statePaused=Paused
# LOCALIZATION NOTE (stateCanceled):
# Indicates that the download was canceled by the user.
stateCanceled=Canceled
# LOCALIZATION NOTE (stateBlockedParentalControls):
# Indicates that the download was blocked by the Parental Controls feature of
# Windows. "Parental Controls" should be consistently named and capitalized
# with the display of this feature in Windows. The following article can
# provide a reference for the translation of "Parental Controls" in various
# languages:
# http://windows.microsoft.com/en-US/windows-vista/Set-up-Parental-Controls
stateBlockedParentalControls=Blocked by Parental Controls
# LOCALIZATION NOTE (stateBlockedPolicy):
# Indicates that the download was blocked on Windows because of the "Launching
# applications and unsafe files" setting of the "security zone" associated with
# the target site. "Security zone" should be consistently named and capitalized
# with the display of this feature in Windows. The following article can
# provide a reference for the translation of "security zone" in various
# languages:
# http://support.microsoft.com/kb/174360
stateBlockedPolicy=Blocked by your security zone policy
# LOCALIZATION NOTE (stateDirty):
# Indicates that the download was blocked after scanning.
stateDirty=Blocked: May contain a virus or spyware
# LOCALIZATION NOTE (sizeWithUnits):
# %1$S is replaced with the size number, and %2$S with the measurement unit.
sizeWithUnits=%1$S %2$S
sizeUnknown=Unknown size
# LOCALIZATION NOTE (shortTimeLeftSeconds, shortTimeLeftMinutes,
# shortTimeLeftHours, shortTimeLeftDays):
# These values are displayed in the downloads indicator in the main browser
# window, where space is available for three characters maximum. %1$S is
# replaced with the time left for the given measurement unit. Even for days,
# the value is never longer than two digits.
shortTimeLeftSeconds=%1$Ss
shortTimeLeftMinutes=%1$Sm
shortTimeLeftHours=%1$Sh
shortTimeLeftDays=%1$Sd
# LOCALIZATION NOTE (statusSeparator, statusSeparatorBeforeNumber):
# These strings define templates for the separation of different elements in the
# status line of a download item. As a separator, by default we use the Unicode
# character U+2014 'EM DASH' (long dash). Examples of status lines include
# "Canceled - 222.net", "1.1 MB - website2.com", or "Paused - 1.1 MB". Note
# that we use a wider space after the separator when it is followed by a number,
# just to avoid visually confusing it with with a minus sign with some fonts.
# If you use a different separator, this might not be necessary. However, there
# is usually no need to change the separator or the order of the substitutions,
# even for right-to-left languages, unless the defaults are not suitable.
statusSeparator=%1$S \u2014 %2$S
statusSeparatorBeforeNumber=%1$S \u2014 %2$S
fileExecutableSecurityWarning="%S" is an executable file. Executable files may contain viruses or other malicious code that could harm your computer. Use caution when opening this file. Are you sure you want to launch "%S"?
fileExecutableSecurityWarningTitle=Open Executable File?
fileExecutableSecurityWarningDontAsk=Don't ask me this again

View File

@ -7,9 +7,6 @@ sourceNameChrome=Google Chrome
sourceNameFirefox=Mozilla Firefox
importedBookmarksFolder=From %S
importedSearchURLsFolder=Keyword Searches (From %S)
importedSearchURLsTitle=Search on %S
importedSearchUrlDesc=Type "%S <search query>" in the Location Bar to perform a search on %S.
importedSafariReadingList=Reading List (From Safari)

View File

@ -0,0 +1,49 @@
<!-- 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/. -->
<!-- LOCALIZATION NOTE: These are localized strings for the webapp runtime,
- which loads a webapp in a separate process from Firefox. Webapps loaded
- in this way have very little application chrome, but the runtime does
- provide them with some default functionality, like the standard OS
- menus/menuitems. -->
<!ENTITY fileMenu.label "File">
<!ENTITY fileMenu.accesskey "F">
<!ENTITY quitApplicationCmdWin.label "Exit">
<!ENTITY quitApplicationCmdWin.accesskey "x">
<!ENTITY quitApplicationCmd.label "Quit">
<!ENTITY quitApplicationCmd.accesskey "Q">
<!-- On Mac, we create the Quit and Hide command labels dynamically,
- using properties in window.properties, in order to include the name
- of the webapp in the labels without creating a DTD file for it. -->
<!ENTITY quitApplicationCmdMac.key "Q">
<!ENTITY hideThisAppCmdMac.key "H">
<!ENTITY hideOtherAppsCmdMac.label "Hide Others">
<!ENTITY hideOtherAppsCmdMac.key "H">
<!ENTITY showAllAppsCmdMac.label "Show All">
<!ENTITY editMenu.label "Edit">
<!ENTITY editMenu.accesskey "E">
<!ENTITY undoCmd.label "Undo">
<!ENTITY undoCmd.key "Z">
<!ENTITY undoCmd.accesskey "U">
<!ENTITY redoCmd.label "Redo">
<!ENTITY redoCmd.key "Y">
<!ENTITY redoCmd.accesskey "R">
<!ENTITY cutCmd.label "Cut">
<!ENTITY cutCmd.key "X">
<!ENTITY cutCmd.accesskey "t">
<!ENTITY copyCmd.label "Copy">
<!ENTITY copyCmd.key "C">
<!ENTITY copyCmd.accesskey "C">
<!ENTITY pasteCmd.label "Paste">
<!ENTITY pasteCmd.key "V">
<!ENTITY pasteCmd.accesskey "P">
<!ENTITY deleteCmd.label "Delete">
<!ENTITY deleteCmd.key "D">
<!ENTITY deleteCmd.accesskey "D">
<!ENTITY selectAllCmd.label "Select All">
<!ENTITY selectAllCmd.key "A">
<!ENTITY selectAllCmd.accesskey "A">

View File

@ -0,0 +1,17 @@
# 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/.
# LOCALIZATION NOTE: These are localized strings for the webapp runtime,
# which loads a webapp in a separate process from Firefox. Webapps loaded
# in this way have very little application chrome, but the runtime does
# provide them with some default functionality, like the standard OS
# menus/menuitems.
# LOCALIZATION NOTE (quitApplicationCmdMac.label): %S will be replaced with
# the name of the webapp.
quitApplicationCmdMac.label=Quit %S
# LOCALIZATION NOTE (hideApplicationCmdMac.label): %S will be replaced with
# the name of the webapp.
hideApplicationCmdMac.label=Hide %S

View File

@ -50,6 +50,8 @@
locale/browser/tabbrowser.properties (%chrome/browser/tabbrowser.properties)
locale/browser/tabview.properties (%chrome/browser/tabview.properties)
locale/browser/taskbar.properties (%chrome/browser/taskbar.properties)
locale/browser/downloads/downloads.dtd (%chrome/browser/downloads/downloads.dtd)
locale/browser/downloads/downloads.properties (%chrome/browser/downloads/downloads.properties)
locale/browser/places/places.dtd (%chrome/browser/places/places.dtd)
locale/browser/places/places.properties (%chrome/browser/places/places.properties)
locale/browser/places/editBookmarkOverlay.dtd (%chrome/browser/places/editBookmarkOverlay.dtd)
@ -108,3 +110,6 @@
% locale testpilot @AB_CD@ %locale/feedback/
locale/feedback/main.dtd (%feedback/main.dtd)
locale/feedback/main.properties (%feedback/main.properties)
% locale webapprt @AB_CD@ %locale/webapprt/
locale/webapprt/webapp.dtd (%webapprt/webapp.dtd)
locale/webapprt/webapp.properties (%webapprt/webapp.properties)

View File

@ -48,6 +48,8 @@ browser/components/about/Makefile
browser/components/build/Makefile
browser/components/certerror/Makefile
browser/components/dirprovider/Makefile
browser/components/downloads/Makefile
browser/components/downloads/src/Makefile
browser/components/feeds/Makefile
browser/components/feeds/public/Makefile
browser/components/feeds/src/Makefile
@ -131,6 +133,8 @@ if [ "$ENABLE_TESTS" ]; then
browser/base/content/test/newtab/Makefile
browser/components/certerror/test/Makefile
browser/components/dirprovider/tests/Makefile
browser/components/downloads/test/Makefile
browser/components/downloads/test/browser/Makefile
browser/components/preferences/tests/Makefile
browser/components/search/test/Makefile
browser/components/sessionstore/test/Makefile

View File

@ -62,4 +62,8 @@ EXTRA_JS_MODULES += \
$(NULL)
endif
EXTRA_PP_JS_MODULES = \
WebappsInstaller.jsm \
$(NULL)
include $(topsrcdir)/config/rules.mk

View File

@ -0,0 +1,105 @@
/* 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/. */
/**
* This function receives a list of icon sizes
* and URLs and returns the url string for the biggest icon.
*
* @param aIcons An object where the keys are the icon sizes
* and the values are URL strings. E.g.:
* aIcons = {
* "16": "http://www.example.org/icon16.png",
* "32": "http://www.example.org/icon32.png"
* };
*
* @returns the URL string for the largest specified icon
*/
function getBiggestIconURL(aIcons) {
let iconSizes = Object.keys(aIcons);
if (iconSizes.length == 0) {
return "";
}
iconSizes.sort(function(a, b) a - b);
return aIcons[iconSizes.pop()];
}
/**
* This function retrieves the icon for an app as specified
* in the iconURI on the shell object.
* Upon completion it will call aShell.processIcon()
*
* @param aShell The shell that specifies the properties
* of the native app. Three properties from this
* shell will be used in this function:
* - iconURI
* - useTmpForIcon
* - processIcon()
*/
function getIconForApp(aShell, callback) {
let iconURI = aShell.iconURI;
let mimeService = Cc["@mozilla.org/mime;1"]
.getService(Ci.nsIMIMEService);
let mimeType;
try {
let tIndex = iconURI.path.indexOf(";");
if("data" == iconURI.scheme && tIndex != -1) {
mimeType = iconURI.path.substring(0, tIndex);
} else {
mimeType = mimeService.getTypeFromURI(iconURI);
}
} catch(e) {
throw("getIconFromURI - Failed to determine MIME type");
}
try {
let listener;
if(aShell.useTmpForIcon) {
let downloadObserver = {
onDownloadComplete: function(downloader, request, cx, aStatus, file) {
// pass downloader just to keep reference around
onIconDownloaded(aShell, mimeType, aStatus, file, callback, downloader);
}
};
tmpIcon = Services.dirsvc.get("TmpD", Ci.nsIFile);
tmpIcon.append("tmpicon." + mimeService.getPrimaryExtension(mimeType, ""));
tmpIcon.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0666);
listener = Cc["@mozilla.org/network/downloader;1"]
.createInstance(Ci.nsIDownloader);
listener.init(downloadObserver, tmpIcon);
} else {
let pipe = Cc["@mozilla.org/pipe;1"]
.createInstance(Ci.nsIPipe);
pipe.init(true, true, 0, 0xffffffff, null);
listener = Cc["@mozilla.org/network/simple-stream-listener;1"]
.createInstance(Ci.nsISimpleStreamListener);
listener.init(pipe.outputStream, {
onStartRequest: function() {},
onStopRequest: function(aRequest, aContext, aStatusCode) {
pipe.outputStream.close();
onIconDownloaded(aShell, mimeType, aStatusCode, pipe.inputStream, callback);
}
});
}
let channel = NetUtil.newChannel(iconURI);
let CertUtils = { };
Cu.import("resource://gre/modules/CertUtils.jsm", CertUtils);
// Pass true to avoid optional redirect-cert-checking behavior.
channel.notificationCallbacks = new CertUtils.BadCertHandler(true);
channel.asyncOpen(listener, null);
} catch(e) {
throw("getIconFromURI - Failure getting icon (" + e + ")");
}
}
function onIconDownloaded(aShell, aMimeType, aStatusCode, aIcon, aCallback) {
if (Components.isSuccessCode(aStatusCode)) {
aShell.processIcon(aMimeType, aIcon, aCallback);
}
}

View File

@ -0,0 +1,358 @@
/* 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/. */
let EXPORTED_SYMBOLS = ["WebappsInstaller"];
const Cc = Components.classes;
const Ci = Components.interfaces;
const Cu = Components.utils;
Cu.import("resource:///modules/Services.jsm");
Cu.import("resource:///modules/FileUtils.jsm");
Cu.import("resource:///modules/NetUtil.jsm");
let WebappsInstaller = {
/**
* Creates a native installation of the web app in the OS
*
* @param aData the manifest data provided by the web app
*
* @returns bool true on success, false if an error was thrown
*/
install: function(aData) {
#ifdef XP_MACOSX
let shell = new MacNativeApp(aData);
#else
return false;
#endif
try {
shell.install();
} catch (ex) {
Cu.reportError("Error installing app: " + ex);
return false;
}
return true;
}
}
/**
* This function implements the common constructor for both
* the Windows and Mac native app shells. It reads and parses
* the data from the app manifest and stores it in the NativeApp
* object. It's meant to be called as NativeApp.call(this, aData)
* from the platform-specific constructor.
*
* @param aData the data object provided by the web app with
* all the app settings and specifications.
*
*/
function NativeApp(aData) {
let app = this.app = aData.app;
let origin = Services.io.newURI(app.origin, null, null);
if (app.manifest.launch_path) {
this.launchURI = Services.io.newURI(origin.resolve(app.manifest.launch_path),
null, null);
} else {
this.launchURI = origin.clone();
}
let biggestIcon = getBiggestIconURL(app.manifest.icons);
try {
let iconURI = Services.io.newURI(biggestIcon, null, null);
if (iconURI.scheme == "data") {
this.iconURI = iconURI;
}
} catch (ex) {}
if (!this.iconURI) {
try {
this.iconURI = Services.io.newURI(origin.resolve(biggestIcon), null, null);
}
catch (ex) {}
}
this.appName = sanitize(app.manifest.name);
this.appNameAsFilename = stripStringForFilename(this.appName);
if(app.manifest.developer && app.manifest.developer.name) {
let devName = app.manifest.developer.name.substr(0, 128);
devName = sanitize(devName);
if (devName) {
this.developerName = devName;
}
}
let shortDesc = this.appName;
if (app.manifest.description) {
let firstLine = app.manifest.description.split("\n")[0];
shortDesc = firstLine.length <= 256
? firstLine
: firstLine.substr(0, 253) + "...";
}
this.shortDescription = sanitize(shortDesc);
this.manifest = app.manifest;
this.profileFolder = Services.dirsvc.get("ProfD", Ci.nsIFile);
}
#ifdef XP_MACOSX
function MacNativeApp(aData) {
NativeApp.call(this, aData);
this._init();
}
MacNativeApp.prototype = {
_init: function() {
this.appSupportDir = Services.dirsvc.get("ULibDir", Ci.nsILocalFile);
this.appSupportDir.append("Application Support");
let filenameRE = new RegExp("[<>:\"/\\\\|\\?\\*]", "gi");
this.appNameAsFilename = this.appNameAsFilename.replace(filenameRE, "");
if (this.appNameAsFilename == "") {
this.appNameAsFilename = "Webapp";
}
// The ${ProfileDir} format is as follows:
// host of the app origin + ";" +
// protocol + ";" +
// port (-1 for default port)
this.appProfileDir = this.appSupportDir.clone();
this.appProfileDir.append(this.launchURI.host + ";" +
this.launchURI.scheme + ";" +
this.launchURI.port);
this.installDir = Services.dirsvc.get("LocApp", Ci.nsILocalFile);
this.installDir.append(this.appNameAsFilename + ".app");
this.contentsDir = this.installDir.clone();
this.contentsDir.append("Contents");
this.macOSDir = this.contentsDir.clone();
this.macOSDir.append("MacOS");
this.resourcesDir = this.contentsDir.clone();
this.resourcesDir.append("Resources");
this.iconFile = this.resourcesDir.clone();
this.iconFile.append("appicon.icns");
this.processFolder = Services.dirsvc.get("CurProcD", Ci.nsIFile);
},
install: function() {
this._removeInstallation(true);
try {
this._createDirectoryStructure();
this._copyPrebuiltFiles();
this._createConfigFiles();
} catch (ex) {
this._removeInstallation(false);
throw(ex);
}
getIconForApp(this);
},
_removeInstallation: function(keepProfile) {
try {
if(this.installDir.exists()) {
this.installDir.followLinks = false;
this.installDir.remove(true);
}
} catch(ex) {
}
if (keepProfile)
return;
try {
if(this.appProfileDir.exists()) {
this.appProfileDir.followLinks = false;
this.appProfileDir.remove(true);
}
} catch(ex) {
}
},
_createDirectoryStructure: function() {
if (!this.appProfileDir.exists())
this.appProfileDir.create(Ci.nsIFile.DIRECTORY_TYPE, 0755);
this.installDir.create(Ci.nsIFile.DIRECTORY_TYPE, 0755);
this.contentsDir.create(Ci.nsIFile.DIRECTORY_TYPE, 0755);
this.macOSDir.create(Ci.nsIFile.DIRECTORY_TYPE, 0755);
this.resourcesDir.create(Ci.nsIFile.DIRECTORY_TYPE, 0755);
},
_copyPrebuiltFiles: function() {
let webapprt = this.processFolder.clone();
webapprt.append("webapprt-stub");
webapprt.copyTo(this.macOSDir, "webapprt");
},
_createConfigFiles: function() {
// ${ProfileDir}/config.json
let json = {
"app": {
"profile": this.profileFolder.path,
"origin": this.launchURI.prePath,
"installOrigin": "apps.mozillalabs.com",
"manifest": this.manifest
}
};
let configJson = this.appProfileDir.clone();
configJson.append("webapp.json");
writeToFile(configJson, JSON.stringify(json), function() {});
// ${InstallDir}/Contents/MacOS/webapp.ini
let applicationINI = this.macOSDir.clone().QueryInterface(Ci.nsILocalFile);
applicationINI.append("webapp.ini");
let factory = Cc["@mozilla.org/xpcom/ini-processor-factory;1"]
.getService(Ci.nsIINIParserFactory);
let writer = factory.createINIParser(applicationINI).QueryInterface(Ci.nsIINIParserWriter);
writer.setString("Webapp", "Name", this.appName);
writer.setString("Webapp", "Profile", this.appProfileDir.leafName);
writer.setString("Branding", "BrandFullName", this.appName);
writer.setString("Branding", "BrandShortName", this.appName);
writer.writeFile();
let infoPListContent = '<?xml version="1.0" encoding="UTF-8"?>\n\
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">\n\
<plist version="1.0">\n\
<dict>\n\
<key>CFBundleDevelopmentRegion</key>\n\
<string>English</string>\n\
<key>CFBundleDisplayName</key>\n\
<string>' + escapeXML(this.appName) + '</string>\n\
<key>CFBundleExecutable</key>\n\
<string>webapprt</string>\n\
<key>CFBundleIconFile</key>\n\
<string>appicon</string>\n\
<key>CFBundleIdentifier</key>\n\
<string>' + escapeXML(this.launchURI.prePath) + '</string>\n\
<key>CFBundleInfoDictionaryVersion</key>\n\
<string>6.0</string>\n\
<key>CFBundleName</key>\n\
<string>' + escapeXML(this.appName) + '</string>\n\
<key>CFBundlePackageType</key>\n\
<string>APPL</string>\n\
<key>CFBundleSignature</key>\n\
<string>MOZB</string>\n\
<key>CFBundleVersion</key>\n\
<string>0</string>\n\
#ifdef DEBUG
<key>FirefoxBinary</key>\n\
<string>org.mozilla.NightlyDebug</string>\n\
#endif
</dict>\n\
</plist>';
let infoPListFile = this.contentsDir.clone();
infoPListFile.append("Info.plist");
writeToFile(infoPListFile, infoPListContent, function() {});
},
/**
* This variable specifies if the icon retrieval process should
* use a temporary file in the system or a binary stream. This
* is accessed by a common function in WebappsIconHelpers.js and
* is different for each platform.
*/
useTmpForIcon: true,
/**
* Process the icon from the imageStream as retrieved from
* the URL by getIconForApp(). This will bundle the icon to the
* app package at Contents/Resources/appicon.icns.
*
* @param aMimeType the icon mimetype
* @param aImageStream the stream for the image data
* @param aCallback a callback function to be called
* after the process finishes
*/
processIcon: function(aMimeType, aIcon) {
try {
let process = Cc["@mozilla.org/process/util;1"]
.createInstance(Ci.nsIProcess);
let sipsFile = Cc["@mozilla.org/file/local;1"]
.createInstance(Ci.nsILocalFile);
sipsFile.initWithPath("/usr/bin/sips");
process.init(sipsFile);
process.run(true, ["-s",
"format", "icns",
aIcon.path,
"--out", this.iconFile.path,
"-z", "128", "128"],
9);
} catch(e) {
throw(e);
}
}
}
#endif
/* Helper Functions */
/**
* Async write a data string into a file
*
* @param aFile the nsIFile to write to
* @param aData a string with the data to be written
* @param aCallback a callback to be called after the process is finished
*/
function writeToFile(aFile, aData, aCallback) {
let ostream = FileUtils.openSafeFileOutputStream(aFile);
let converter = Cc["@mozilla.org/intl/scriptableunicodeconverter"]
.createInstance(Ci.nsIScriptableUnicodeConverter);
converter.charset = "UTF-8";
let istream = converter.convertToInputStream(aData);
NetUtil.asyncCopy(istream, ostream, function(x) aCallback(x));
}
/**
* Removes unprintable characters from a string.
*/
function sanitize(aStr) {
let unprintableRE = new RegExp("[\\x00-\\x1F\\x7F]" ,"gi");
return aStr.replace(unprintableRE, "");
}
/**
* Strips all non-word characters from the beginning and end of a string
*/
function stripStringForFilename(aPossiblyBadFilenameString) {
//strip everything from the front up to the first [0-9a-zA-Z]
let stripFrontRE = new RegExp("^\\W*","gi");
let stripBackRE = new RegExp("\\W*$","gi");
let stripped = aPossiblyBadFilenameString.replace(stripFrontRE, "");
stripped = stripped.replace(stripBackRE, "");
return stripped;
}
function escapeXML(aStr) {
return aStr.toString()
.replace(/&/g, "&amp;")
.replace(/"/g, "&quot;")
.replace(/'/g, "&apos;")
.replace(/</g, "&lt;")
.replace(/>/g, "&gt;");
}
/* More helpers for handling the app icon */
#include WebappsIconHelpers.js

View File

@ -11,6 +11,7 @@ let Cu = Components.utils;
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/Webapps.jsm");
Cu.import("resource://gre/modules/WebappsInstaller.jsm");
let webappsUI = {
init: function webappsUI_init() {
@ -108,8 +109,11 @@ let webappsUI = {
label: bundle.getString("webapps.install"),
accessKey: bundle.getString("webapps.install.accesskey"),
callback: function(notification) {
installDone = true;
DOMApplicationRegistry.confirmInstall(aData);
if (WebappsInstaller.install(aData)) {
DOMApplicationRegistry.confirmInstall(aData);
} else {
DOMApplicationRegistry.denyInstall(aData);
}
}
};

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

View File

@ -0,0 +1,279 @@
/* 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/. */
/*** Panel and outer controls ***/
#downloadsPanel > .panel-arrowcontainer > .panel-arrowcontent {
padding: 0;
}
#downloadsListBox {
width: 60ch;
background: transparent;
padding: 4px;
color: inherit;
}
#downloadsPanel:not([hasdownloads]) > #downloadsListBox {
display: none;
}
#downloadsHistory {
background: inherit;
color: -moz-nativehyperlinktext;
cursor: pointer;
}
#downloadsPanel[hasdownloads] > #downloadsHistory {
border-top: 1px solid ThreeDShadow;
background-image: -moz-linear-gradient(hsla(0,0%,0%,.15), hsla(0,0%,0%,.08) 6px);
}
#downloadsHistory > .button-box {
margin: 1em;
}
/*** List items ***/
richlistitem[type="download"] {
height: 6em;
margin: 0;
border-top: 1px solid hsla(0,0%,100%,.2);
border-bottom: 1px solid hsla(0,0%,0%,.15);
background: transparent;
padding: 0;
color: inherit;
}
richlistitem[type="download"]:first-child {
border-top: 1px solid transparent;
}
richlistitem[type="download"]:last-child {
border-bottom: 1px solid transparent;
}
#downloadsListBox:-moz-focusring > richlistitem[type="download"][selected] {
outline: 1px #999 dotted;
outline-offset: -1px;
-moz-outline-radius: 3px;
}
.downloadInfo {
padding: 8px;
-moz-padding-end: 0;
}
.downloadTypeIcon {
-moz-margin-end: 8px;
/* Prevent flickering when changing states. */
min-height: 32px;
min-width: 32px;
}
.blockedIcon {
list-style-image: url("chrome://global/skin/icons/Error.png");
}
.downloadTarget {
margin-bottom: 7px;
cursor: inherit;
}
.downloadDetails {
margin-top: 1px;
opacity: 0.6;
font-size: 90%;
cursor: inherit;
}
.downloadButton {
-moz-appearance: none;
min-width: 0;
min-height: 0;
margin: 6px;
border: none;
background: transparent;
padding: 5px;
list-style-image: url("chrome://browser/skin/downloads/buttons.png");
}
.downloadButton > .button-box {
padding: 0;
}
/*** Highlighted list items ***/
richlistitem[type="download"][state="1"] > .downloadInfo {
border-top: 1px solid transparent;
border-bottom: 1px solid transparent;
-moz-padding-end: 8px;
}
richlistitem[type="download"][state="1"] > .downloadInfo:hover {
border-radius: 3px;
border-top: 1px solid hsla(0,0%,100%,.3);
border-bottom: 1px solid hsla(0,0%,0%,.2);
background-color: Highlight;
background-image: -moz-linear-gradient(hsla(0,0%,100%,.1), hsla(0,0%,100%,0));
color: HighlightText;
cursor: pointer;
}
/*** Button icons ***/
.downloadButton.downloadCancel {
-moz-image-region: rect(0px, 14px, 14px, 0px);
}
.downloadButton.downloadCancel:hover {
-moz-image-region: rect(0px, 28px, 14px, 14px);
}
.downloadButton.downloadCancel:active {
-moz-image-region: rect(0px, 42px, 14px, 28px);
}
.downloadButton.downloadShow {
-moz-image-region: rect(14px, 14px, 28px, 0px);
}
.downloadButton.downloadShow:hover {
-moz-image-region: rect(14px, 28px, 28px, 14px);
}
.downloadButton.downloadShow:active {
-moz-image-region: rect(14px, 42px, 28px, 28px);
}
.downloadButton.downloadRetry {
-moz-image-region: rect(28px, 14px, 42px, 0px);
}
.downloadButton.downloadRetry:hover {
-moz-image-region: rect(28px, 28px, 42px, 14px);
}
.downloadButton.downloadRetry:active {
-moz-image-region: rect(28px, 42px, 42px, 28px);
}
/*** Status and progress indicator ***/
#downloads-indicator {
width: 35px;
}
#downloads-indicator-anchor {
min-width: 18px;
min-height: 18px;
/* Makes the outermost stack element positioned, so that its contents are
rendered over the main browser window in the Z order. This is required by
the animated event notification. */
position: relative;
}
/*** Main indicator icon ***/
#downloads-indicator-icon {
background: -moz-image-rect(url("chrome://browser/skin/Toolbar-small.png"),
0, 16, 16, 0) center no-repeat;
}
#downloads-indicator-icon:-moz-lwtheme-brighttext {
background: -moz-image-rect(url("chrome://browser/skin/Toolbar-inverted.png"),
0, 16, 16, 0) center no-repeat;
}
#downloads-indicator[attention] > #downloads-indicator-anchor > #downloads-indicator-icon {
background: -moz-image-rect(url("chrome://browser/skin/downloads/download-glow.png"),
16, 32, 32, 16) center no-repeat;
}
#downloads-indicator:not([counter]) > #downloads-indicator-anchor > #downloads-indicator-progress-area > #downloads-indicator-counter {
background: -moz-image-rect(url("chrome://browser/skin/Toolbar-small.png"),
0, 16, 16, 0) center no-repeat;
background-size: 12px;
}
#downloads-indicator:not([counter])[attention] > #downloads-indicator-anchor > #downloads-indicator-progress-area > #downloads-indicator-counter {
background-image: -moz-image-rect(url("chrome://browser/skin/downloads/download-glow.png"),
16, 32, 32, 16);
}
/*** Event notification ***/
#downloads-indicator-notification {
opacity: 0;
background: url("chrome://browser/skin/downloads/download-notification.png")
center no-repeat;
background-size: 16px;
}
@-moz-keyframes downloadsIndicatorNotificationRight {
from { opacity: 0; -moz-transform: translate(-128px, 128px) scale(8); }
20% { opacity: .85; -moz-animation-timing-function: ease-out; }
to { opacity: 0; -moz-transform: translate(0) scale(1); }
}
@-moz-keyframes downloadsIndicatorNotificationLeft {
from { opacity: 0; -moz-transform: translate(128px, 128px) scale(8); }
20% { opacity: .85; -moz-animation-timing-function: ease-out; }
to { opacity: 0; -moz-transform: translate(0) scale(1); }
}
#downloads-indicator[notification] > #downloads-indicator-anchor > #downloads-indicator-notification {
-moz-animation-name: downloadsIndicatorNotificationRight;
-moz-animation-duration: 1s;
}
#downloads-indicator[notification]:-moz-locale-dir(rtl) > #downloads-indicator-anchor > #downloads-indicator-notification {
-moz-animation-name: downloadsIndicatorNotificationLeft;
}
/*** Progress bar and text ***/
#downloads-indicator-counter {
height: 12px;
margin: 0;
color: hsl(0,0%,30%);
text-shadow: 0 1px 0 hsla(0,0%,100%,.5);
font-size: 10px;
line-height: 10px;
text-align: center;
}
#downloads-indicator-progress {
width: 24px;
height: 4px;
min-width: 0;
min-height: 0;
margin-top: 1px;
margin-bottom: 2px;
border-radius: 2px;
box-shadow: 0 1px 0 hsla(0,0%,100%,.4);
}
#downloads-indicator-progress > .progress-bar {
-moz-appearance: none;
min-width: 0;
min-height: 0;
background-image: -moz-linear-gradient(#41a0ff, #2090ff);
border: 1px solid;
border-color: hsla(0,0%,0%,.6) hsla(0,0%,0%,.2) hsla(0,0%,0%,.2);
border-radius: 2px 0 0 2px;
}
#downloads-indicator-progress > .progress-remainder {
-moz-appearance: none;
min-width: 0;
min-height: 0;
background-image: -moz-linear-gradient(#9a9a9a, #a1a1a1);
border: 1px solid;
border-color: hsla(0,0%,0%,.4) hsla(0,0%,0%,.3) hsla(0,0%,0%,.2);
-moz-border-start: none;
border-radius: 0 2px 2px 0;
}
#downloads-indicator[paused] > #downloads-indicator-anchor > #downloads-indicator-progress-area > #downloads-indicator-progress > .progress-bar {
background-image: -moz-linear-gradient(#a0a000, #909000);
}
#downloads-indicator[paused] > #downloads-indicator-anchor > #downloads-indicator-progress-area > #downloads-indicator-progress > .progress-remainder {
background-image: -moz-linear-gradient(#9a9a00, #a1a100);
}

View File

@ -35,6 +35,10 @@ browser.jar:
skin/classic/browser/Toolbar.png
skin/classic/browser/Toolbar-small.png
skin/classic/browser/urlbar-arrow.png
skin/classic/browser/downloads/buttons.png (downloads/buttons.png)
skin/classic/browser/downloads/download-glow.png (downloads/download-glow.png)
skin/classic/browser/downloads/download-notification.png (downloads/download-notification.png)
skin/classic/browser/downloads/downloads.css (downloads/downloads.css)
skin/classic/browser/feeds/feedIcon.png (feeds/feedIcon.png)
skin/classic/browser/feeds/feedIcon16.png (feeds/feedIcon16.png)
skin/classic/browser/feeds/videoFeedIcon.png (feeds/feedIcon.png)

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

View File

@ -0,0 +1,300 @@
/* 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/. */
/*** Panel and outer controls ***/
#downloadsPanel > .panel-arrowcontainer > .panel-arrowcontent {
padding: 0;
}
#downloadsListBox {
width: 60ch;
background: transparent;
padding: 4px;
color: inherit;
}
#downloadsPanel:not([hasdownloads]) > #downloadsListBox {
display: none;
}
#downloadsHistory {
background: inherit;
border-bottom-left-radius: 6px;
border-bottom-right-radius: 6px;
color: hsl(210,100%,75%);
cursor: pointer;
}
#downloadsPanel:not([hasdownloads]) > #downloadsHistory {
border-top-left-radius: 6px;
border-top-right-radius: 6px;
}
#downloadsPanel[hasdownloads] > #downloadsHistory {
border-top: 1px solid hsla(0,0%,100%,.1);
background-color: hsla(0,0%,7%,.3);
box-shadow: 0 1px 1px hsla(0,0%,0%,.25) inset;
}
#downloadsHistory > .button-box {
margin: 1em;
}
#downloadsHistory:-moz-focusring > .button-box {
border-top-left-radius: 6px;
border-top-right-radius: 6px;
}
#downloadsPanel:not([hasdownloads]) > #downloadsHistory:-moz-focusring > .button-box {
border-bottom-left-radius: 6px;
border-bottom-right-radius: 6px;
}
/*** List items ***/
richlistitem[type="download"] {
height: 7em;
margin: 0;
border-top: 1px solid hsla(0,0%,100%,.07);
border-bottom: 1px solid hsla(0,0%,0%,.2);
background: transparent;
padding: 0;
color: inherit;
}
richlistitem[type="download"]:first-child {
border-top: 1px solid transparent;
}
richlistitem[type="download"]:last-child {
border-bottom: 1px solid transparent;
}
#downloadsListBox:-moz-focusring > richlistitem[type="download"][selected] {
outline: 1px #999 dotted;
outline-offset: -1px;
-moz-outline-radius: 3px;
}
.downloadInfo {
color: white;
padding: 8px;
-moz-padding-end: 0;
}
.downloadTypeIcon {
-moz-margin-end: 8px;
/* Prevent flickering when changing states. */
min-height: 32px;
min-width: 32px;
}
.blockedIcon {
list-style-image: url("chrome://global/skin/icons/Error.png");
}
.downloadTarget {
margin-bottom: 6px;
cursor: inherit;
}
.downloadDetails {
opacity: 0.7;
font-size: 95%;
cursor: inherit;
}
.downloadButton {
-moz-appearance: none;
min-width: 0;
min-height: 0;
margin: 6px;
border: none;
background: transparent;
padding: 5px;
list-style-image: url("chrome://browser/skin/downloads/buttons.png");
}
.downloadButton > .button-box {
padding: 0;
}
/*** Highlighted list items ***/
richlistitem[type="download"][state="1"] .downloadInfo {
border-top: 1px solid transparent;
border-bottom: 1px solid transparent;
-moz-padding-end: 8px;
}
richlistitem[type="download"][state="1"] .downloadInfo:hover {
border-radius: 3px;
border-top: 1px solid hsla(0,0%,100%,.2);
border-bottom: 1px solid hsla(0,0%,0%,.4);
background-color: Highlight;
background-image: -moz-linear-gradient(hsl(210,100%,50%), hsl(210,96%,41%));
color: HighlightText;
cursor: pointer;
}
/*** Button icons ***/
.downloadButton.downloadCancel {
-moz-image-region: rect(0px, 14px, 14px, 0px);
}
.downloadButton.downloadCancel:hover {
-moz-image-region: rect(0px, 28px, 14px, 14px);
}
.downloadButton.downloadCancel:active {
-moz-image-region: rect(0px, 42px, 14px, 28px);
}
.downloadButton.downloadShow {
-moz-image-region: rect(14px, 14px, 28px, 0px);
}
.downloadButton.downloadShow:hover {
-moz-image-region: rect(14px, 28px, 28px, 14px);
}
.downloadButton.downloadShow:active {
-moz-image-region: rect(14px, 42px, 28px, 28px);
}
.downloadButton.downloadRetry {
-moz-image-region: rect(28px, 14px, 42px, 0px);
}
.downloadButton.downloadRetry:hover {
-moz-image-region: rect(28px, 28px, 42px, 14px);
}
.downloadButton.downloadRetry:active {
-moz-image-region: rect(28px, 42px, 42px, 28px);
}
/*** Status and progress indicator ***/
#downloads-indicator {
width: 35px;
}
#downloads-indicator-anchor {
min-width: 20px;
min-height: 20px;
/* Makes the outermost stack element positioned, so that its contents are
rendered over the main browser window in the Z order. This is required by
the animated event notification. */
position: relative;
}
/*** Main indicator icon ***/
#downloads-indicator-icon {
background: -moz-image-rect(url("chrome://browser/skin/Toolbar.png"),
0, 140, 20, 120) center no-repeat;
}
#downloads-indicator-icon:-moz-lwtheme-brighttext {
background: -moz-image-rect(url("chrome://browser/skin/Toolbar-inverted.png"),
0, 140, 20, 120) center no-repeat;
}
#downloads-indicator[attention]
#downloads-indicator-icon {
background: -moz-image-rect(url("chrome://browser/skin/downloads/download-glow.png"),
14, 34, 34, 14) center no-repeat;
}
#downloads-indicator:not([counter])
#downloads-indicator-counter {
background: -moz-image-rect(url("chrome://browser/skin/Toolbar.png"),
0, 140, 20, 120) center no-repeat;
background-size: 12px;
}
#downloads-indicator:not([counter])[attention]
#downloads-indicator-counter {
background-image: -moz-image-rect(url("chrome://browser/skin/downloads/download-glow.png"),
14, 34, 34, 14);
}
/*** Event notification ***/
#downloads-indicator-notification {
opacity: 0;
background: url("chrome://browser/skin/downloads/download-notification.png")
center no-repeat;
background-size: 16px;
}
@-moz-keyframes downloadsIndicatorNotificationRight {
from { opacity: 0; -moz-transform: translate(-128px, 128px) scale(8); }
20% { opacity: .85; -moz-animation-timing-function: ease-out; }
to { opacity: 0; -moz-transform: translate(0) scale(1); }
}
@-moz-keyframes downloadsIndicatorNotificationLeft {
from { opacity: 0; -moz-transform: translate(128px, 128px) scale(8); }
20% { opacity: .85; -moz-animation-timing-function: ease-out; }
to { opacity: 0; -moz-transform: translate(0) scale(1); }
}
#downloads-indicator[notification] > #downloads-indicator-anchor > #downloads-indicator-notification {
-moz-animation-name: downloadsIndicatorNotificationRight;
-moz-animation-duration: 1s;
}
#downloads-indicator[notification]:-moz-locale-dir(rtl) > #downloads-indicator-anchor > #downloads-indicator-notification {
-moz-animation-name: downloadsIndicatorNotificationLeft;
}
/*** Progress bar and text ***/
#downloads-indicator-counter {
height: 12px;
margin: 0;
color: hsl(0,0%,30%);
text-shadow: 0 1px 0 hsla(0,0%,100%,.5);
font-size: 10px;
line-height: 10px;
text-align: center;
}
#downloads-indicator-progress {
width: 24px;
height: 4px;
min-width: 0;
min-height: 0;
margin-top: 1px;
margin-bottom: 2px;
border-radius: 2px;
box-shadow: 0 1px 0 hsla(0,0%,100%,.4);
}
#downloads-indicator-progress > .progress-bar {
-moz-appearance: none;
min-width: 0;
min-height: 0;
background-image: -moz-linear-gradient(#41a0ff, #2090ff);
border: 1px solid;
border-color: hsla(0,0%,0%,.6) hsla(0,0%,0%,.2) hsla(0,0%,0%,.2);
border-radius: 2px 0 0 2px;
}
#downloads-indicator-progress > .progress-remainder {
-moz-appearance: none;
min-width: 0;
min-height: 0;
background-image: -moz-linear-gradient(#9a9a9a, #a1a1a1);
border: 1px solid;
border-color: hsla(0,0%,0%,.4) hsla(0,0%,0%,.3) hsla(0,0%,0%,.2);
-moz-border-start: none;
border-radius: 0 2px 2px 0;
}
#downloads-indicator[paused] > #downloads-indicator-anchor > #downloads-indicator-progress-area > #downloads-indicator-progress > .progress-bar {
background-image: -moz-linear-gradient(#a0a000, #909000);
}
#downloads-indicator[paused] > #downloads-indicator-anchor > #downloads-indicator-progress-area > #downloads-indicator-progress > .progress-remainder {
background-image: -moz-linear-gradient(#9a9a00, #a1a100);
}

View File

@ -45,6 +45,10 @@ browser.jar:
skin/classic/browser/urlbar-history-dropmarker.png
skin/classic/browser/urlbar-arrow.png
skin/classic/browser/urlbar-popup-blocked.png
skin/classic/browser/downloads/buttons.png (downloads/buttons.png)
skin/classic/browser/downloads/download-glow.png (downloads/download-glow.png)
skin/classic/browser/downloads/download-notification.png (downloads/download-notification.png)
skin/classic/browser/downloads/downloads.css (downloads/downloads.css)
skin/classic/browser/feeds/subscribe.css (feeds/subscribe.css)
skin/classic/browser/feeds/subscribe-ui.css (feeds/subscribe-ui.css)
skin/classic/browser/feeds/feedIcon.png (feeds/feedIcon.png)

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

View File

@ -0,0 +1,49 @@
%define WINSTRIPE_AERO
%include downloads.css
%undef WINSTRIPE_AERO
#downloadsPanel > .panel-arrowcontainer > .panel-arrowcontent > .panel-inner-arrowcontent {
padding: 0;
}
@media (-moz-windows-default-theme) {
#downloadsPanel[hasdownloads] > #downloadsHistory {
background-color: #f1f5fb;
}
richlistitem[type="download"] {
border: 1px solid transparent;
border-bottom: 1px solid hsl(213,40%,90%);
}
richlistitem[type="download"][state="1"] > .downloadInfo {
border: 1px solid transparent;
-moz-padding-end: 8px;
}
richlistitem[type="download"][state="1"] > .downloadInfo:hover {
border: 1px solid hsl(213,45%,65%);
box-shadow: 0 0 0 1px hsla(0,0%,100%,.5) inset,
0 1px 0 hsla(0,0%,100%,.3) inset;
background-image: -moz-linear-gradient(hsl(212,86%,92%), hsl(212,91%,86%));
color: black;
}
}
@media (-moz-windows-compositor) {
#toolbar-menubar #downloads-indicator-icon:not(:-moz-lwtheme),
#TabsToolbar[tabsontop=true] #downloads-indicator-icon:not(:-moz-lwtheme),
#navigator-toolbox[tabsontop=false] > #nav-bar #downloads-indicator-icon:not(:-moz-lwtheme),
#nav-bar + #customToolbars + #PersonalToolbar[collapsed=true] + #TabsToolbar[tabsontop=false]:last-child #downloads-indicator-icon:not(:-moz-lwtheme) {
list-style-image: url("chrome://browser/skin/Toolbar-inverted.png");
}
#toolbar-menubar #downloads-indicator-counter:not(:-moz-lwtheme),
#TabsToolbar[tabsontop=true] #downloads-indicator-counter:not(:-moz-lwtheme),
#navigator-toolbox[tabsontop=false] > #nav-bar #downloads-indicator-counter:not(:-moz-lwtheme),
#nav-bar + #customToolbars + #PersonalToolbar[collapsed=true] + #TabsToolbar[tabsontop=false]:last-child #downloads-indicator-counter:not(:-moz-lwtheme) {
color: white;
text-shadow: 0 0 1px rgba(0,0,0,.7),
0 1px 1.5px rgba(0,0,0,.5);
}
}

View File

@ -0,0 +1,310 @@
/* 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/. */
/*** Panel and outer controls ***/
%ifndef WINSTRIPE_AERO
#downloadsHistory,
#downloadsHistory:-moz-focusring > .button-box {
border-bottom-left-radius: 6px;
border-bottom-right-radius: 6px;
}
#downloadsPanel:not([hasdownloads]) > #downloadsHistory,
#downloadsPanel:not([hasdownloads]) > #downloadsHistory:-moz-focusring > .button-box {
border-top-left-radius: 6px;
border-top-right-radius: 6px;
}
#downloadsPanel > .panel-arrowcontainer > .panel-arrowcontent {
/* Avoid that the arrow overlaps the selection on first item */
padding-top: 5px;
}
%endif
#downloadsPanel > .panel-arrowcontainer > .panel-arrowcontent {
padding: 0;
}
#downloadsListBox {
width: 60ch;
background-color: transparent;
padding: 4px;
color: inherit;
}
#downloadsHistory {
background: inherit;
color: -moz-nativehyperlinktext;
cursor: pointer;
}
#downloadsHistory > .button-box {
margin: 1em;
}
@media (-moz-windows-default-theme) {
#downloadsPanel[hasdownloads] > #downloadsHistory {
background-color: hsla(216,45%,88%,.98);
box-shadow: 0px 1px 2px rgb(204,214,234) inset;
}
}
/*** List items ***/
richlistitem[type="download"] {
height: 7em;
margin: 0;
border-top: 1px solid hsla(0,0%,100%,.3);
border-bottom: 1px solid hsla(220,18%,51%,.25);
background: transparent;
padding: 0;
color: inherit;
}
richlistitem[type="download"]:first-child {
border-top: 1px solid transparent;
}
@media (-moz-windows-default-theme) {
richlistitem[type="download"]:last-child {
border-bottom: 1px solid transparent;
}
}
#downloadsListBox:-moz-focusring > richlistitem[type="download"][selected] {
outline: 1px #999 dotted;
outline-offset: -1px;
-moz-outline-radius: 3px;
}
.downloadInfo {
padding: 8px;
-moz-padding-end: 0;
}
.downloadTypeIcon {
-moz-margin-end: 8px;
/* Prevent flickering when changing states. */
min-height: 32px;
min-width: 32px;
}
.blockedIcon {
list-style-image: url("chrome://global/skin/icons/Error.png");
}
.downloadTarget {
margin-bottom: 6px;
cursor: inherit;
}
.downloadDetails {
opacity: 0.6;
font-size: 90%;
cursor: inherit;
}
.downloadButton {
-moz-appearance: none;
min-width: 0;
min-height: 0;
margin: 6px;
border: none;
background: transparent;
padding: 5px;
list-style-image: url("chrome://browser/skin/downloads/buttons.png");
}
.downloadButton > .button-box {
padding: 0;
}
/*** Highlighted list items ***/
%ifdef WINSTRIPE_AERO
@media not all and (-moz-windows-default-theme) {
%endif
richlistitem[type="download"][state="1"] > .downloadInfo {
border-top: 1px solid transparent;
border-bottom: 1px solid transparent;
-moz-padding-end: 8px;
}
%ifdef WINSTRIPE_AERO
}
%endif
richlistitem[type="download"][state="1"] > .downloadInfo:hover {
border-radius: 3px;
border-top: 1px solid hsla(0,0%,100%,.2);
border-bottom: 1px solid hsla(0,0%,0%,.2);
background-color: Highlight;
color: HighlightText;
cursor: pointer;
}
/*** Button icons ***/
.downloadButton.downloadCancel {
-moz-image-region: rect(0px, 14px, 14px, 0px);
}
.downloadButton.downloadCancel:hover {
-moz-image-region: rect(0px, 28px, 14px, 14px);
}
.downloadButton.downloadCancel:active {
-moz-image-region: rect(0px, 42px, 14px, 28px);
}
.downloadButton.downloadShow {
-moz-image-region: rect(14px, 14px, 28px, 0px);
}
.downloadButton.downloadShow:hover {
-moz-image-region: rect(14px, 28px, 28px, 14px);
}
.downloadButton.downloadShow:active {
-moz-image-region: rect(14px, 42px, 28px, 28px);
}
.downloadButton.downloadRetry {
-moz-image-region: rect(28px, 14px, 42px, 0px);
}
.downloadButton.downloadRetry:hover {
-moz-image-region: rect(28px, 28px, 42px, 14px);
}
.downloadButton.downloadRetry:active {
-moz-image-region: rect(28px, 42px, 42px, 28px);
}
/*** Status and progress indicator ***/
#downloads-indicator {
width: 35px;
}
#downloads-indicator-anchor {
min-width: 18px;
min-height: 18px;
/* Makes the outermost stack element positioned, so that its contents are
rendered over the main browser window in the Z order. This is required by
the animated event notification. */
position: relative;
}
/*** Main indicator icon ***/
#downloads-indicator-icon {
background: -moz-image-rect(url("chrome://browser/skin/Toolbar.png"),
0, 108, 18, 90) center no-repeat;
}
#downloads-indicator-icon:-moz-lwtheme-brighttext {
background: -moz-image-rect(url("chrome://browser/skin/Toolbar-inverted.png"),
0, 108, 18, 90) center no-repeat;
}
#downloads-indicator[attention] > #downloads-indicator-anchor > #downloads-indicator-icon {
background: -moz-image-rect(url("chrome://browser/skin/downloads/download-glow.png"),
15, 33, 33, 15) center no-repeat;
}
#downloads-indicator:not([counter]) > #downloads-indicator-anchor > #downloads-indicator-progress-area > #downloads-indicator-counter {
background: -moz-image-rect(url("chrome://browser/skin/Toolbar.png"),
0, 108, 18, 90) center no-repeat;
background-size: 12px;
}
#downloads-indicator:not([counter])[attention] > #downloads-indicator-anchor > #downloads-indicator-progress-area > #downloads-indicator-counter {
background-image: -moz-image-rect(url("chrome://browser/skin/downloads/download-glow.png"),
16, 32, 32, 16);
}
/*** Event notification ***/
#downloads-indicator-notification {
opacity: 0;
background: url("chrome://browser/skin/downloads/download-notification.png")
center no-repeat;
background-size: 16px;
}
@-moz-keyframes downloadsIndicatorNotificationRight {
from { opacity: 0; -moz-transform: translate(-128px, 128px) scale(8); }
20% { opacity: .85; -moz-animation-timing-function: ease-out; }
to { opacity: 0; -moz-transform: translate(0) scale(1); }
}
@-moz-keyframes downloadsIndicatorNotificationLeft {
from { opacity: 0; -moz-transform: translate(128px, 128px) scale(8); }
20% { opacity: .85; -moz-animation-timing-function: ease-out; }
to { opacity: 0; -moz-transform: translate(0) scale(1); }
}
#downloads-indicator[notification] > #downloads-indicator-anchor > #downloads-indicator-notification {
-moz-animation-name: downloadsIndicatorNotificationRight;
-moz-animation-duration: 1s;
}
#downloads-indicator[notification]:-moz-locale-dir(rtl) > #downloads-indicator-anchor > #downloads-indicator-notification {
-moz-animation-name: downloadsIndicatorNotificationLeft;
}
/*** Progress bar and text ***/
#downloads-indicator-counter {
height: 12px;
margin: 0;
color: hsl(0,0%,30%);
text-shadow: hsla(0,0%,100%,.5) 0 1px;
font-size: 10px;
line-height: 10px;
text-align: center;
}
#downloads-indicator-counter:-moz-lwtheme-brighttext {
color: white;
text-shadow: 0 0 1px rgba(0,0,0,.7),
0 1px 1.5px rgba(0,0,0,.5);
}
#downloads-indicator-progress {
width: 24px;
height: 4px;
min-width: 0;
min-height: 0;
margin-top: 1px;
margin-bottom: 2px;
border-radius: 2px;
box-shadow: 0 1px 0 hsla(0,0%,100%,.4);
}
#downloads-indicator-progress > .progress-bar {
-moz-appearance: none;
min-width: 0;
min-height: 0;
background-image: -moz-linear-gradient(#92DDA0, #6FC483 49%, #5EB272 51%, #80CE91);
border: 1px solid;
border-color: hsla(0,0%,0%,.6) hsla(0,0%,0%,.2) hsla(0,0%,0%,.2);
border-radius: 2px 0 0 2px;
}
#downloads-indicator-progress > .progress-remainder {
-moz-appearance: none;
min-width: 0;
min-height: 0;
background-image: -moz-linear-gradient(#9a9a9a, #a1a1a1);
border: 1px solid;
border-color: hsla(0,0%,0%,.4) hsla(0,0%,0%,.3) hsla(0,0%,0%,.2);
-moz-border-start: none;
border-radius: 0 2px 2px 0;
}
#downloads-indicator[paused] > #downloads-indicator-anchor > #downloads-indicator-progress-area > #downloads-indicator-progress > .progress-bar {
background-image: -moz-linear-gradient(#DDDD00, #C4C400 49%, #B2B200 51%, #CECE00);
}
#downloads-indicator[paused] > #downloads-indicator-anchor > #downloads-indicator-progress-area > #downloads-indicator-progress > .progress-remainder {
background-image: -moz-linear-gradient(#9a9a00, #a1a100);
}

View File

@ -50,6 +50,10 @@ browser.jar:
skin/classic/browser/urlbar-arrow.png
skin/classic/browser/urlbar-popup-blocked.png
skin/classic/browser/urlbar-history-dropmarker.png
skin/classic/browser/downloads/buttons.png (downloads/buttons.png)
skin/classic/browser/downloads/download-glow.png (downloads/download-glow.png)
skin/classic/browser/downloads/download-notification.png (downloads/download-notification.png)
* skin/classic/browser/downloads/downloads.css (downloads/downloads.css)
skin/classic/browser/feeds/feedIcon.png (feeds/feedIcon.png)
skin/classic/browser/feeds/feedIcon16.png (feeds/feedIcon16.png)
skin/classic/browser/feeds/audioFeedIcon.png (feeds/feedIcon.png)
@ -224,6 +228,10 @@ browser.jar:
skin/classic/aero/browser/urlbar-arrow.png
skin/classic/aero/browser/urlbar-popup-blocked.png
skin/classic/aero/browser/urlbar-history-dropmarker.png
skin/classic/aero/browser/downloads/buttons.png (downloads/buttons-aero.png)
skin/classic/aero/browser/downloads/download-glow.png (downloads/download-glow-aero.png)
skin/classic/aero/browser/downloads/download-notification.png (downloads/download-notification.png)
* skin/classic/aero/browser/downloads/downloads.css (downloads/downloads-aero.css)
skin/classic/aero/browser/feeds/feedIcon.png (feeds/feedIcon-aero.png)
skin/classic/aero/browser/feeds/feedIcon16.png (feeds/feedIcon16-aero.png)
skin/classic/aero/browser/feeds/audioFeedIcon.png (feeds/feedIcon-aero.png)

View File

@ -680,6 +680,8 @@ MOZ_THEME_FASTSTRIPE = @MOZ_THEME_FASTSTRIPE@
MOZ_SERVICES_SYNC = @MOZ_SERVICES_SYNC@
MOZ_WEBAPP_RUNTIME = @MOZ_WEBAPP_RUNTIME@
MOZ_OFFICIAL_BRANDING = @MOZ_OFFICIAL_BRANDING@
HAVE_CLOCK_MONOTONIC = @HAVE_CLOCK_MONOTONIC@

View File

@ -4497,6 +4497,7 @@ MOZ_BRANDING_DIRECTORY=
MOZ_OFFICIAL_BRANDING=
MOZ_FEEDS=1
MOZ_FLEXBOX=
MOZ_WEBAPP_RUNTIME=
MOZ_JSDEBUGGER=1
MOZ_AUTH_EXTENSION=1
MOZ_OGG=1
@ -4559,6 +4560,7 @@ MOZ_GRAPHITE=1
case "${target}" in
*darwin*)
ACCESSIBILITY=
MOZ_WEBAPP_RUNTIME=1
;;
*)
ACCESSIBILITY=1
@ -4569,6 +4571,7 @@ case "$target_os" in
mingw*)
NS_ENABLE_TSF=1
AC_DEFINE(NS_ENABLE_TSF)
MOZ_WEBAPP_RUNTIME=1
;;
esac
@ -6274,6 +6277,44 @@ if test -n "$MOZ_TREE_FREETYPE"; then
AC_SUBST(CAIRO_FT_CFLAGS)
fi
dnl ========================================================
dnl Web App Runtime
dnl ========================================================
MOZ_ARG_DISABLE_BOOL(webapp-runtime,
[ --disable-webapp-runtime Disable Web App Runtime],
MOZ_WEBAPP_RUNTIME=,
MOZ_WEBAPP_RUNTIME=1)
if test -n "$MOZ_WEBAPP_RUNTIME" -a "$OS_ARCH" = "WINNT"; then
# Disable Web App Runtime for Windows builds that use the new toolkit if the
# required major version and minimum minor version of Unicode NSIS isn't in
# the path.
REQ_NSIS_MAJOR_VER=2
MIN_NSIS_MINOR_VER=33
MOZ_PATH_PROGS(MAKENSISU, $MAKENSISU makensisu-2.46 makensisu makensis)
if test -z "$MAKENSISU" -o "$MAKENSISU" = ":"; then
AC_MSG_ERROR([To build the Web App Runtime you must have the latest MozillaBuild or Unicode NSIS with a major version of $REQ_NSIS_MAJOR_VER and a minimum minor version of $MIN_NSIS_MINOR_VER in your path. To build without the Web App Runtime reconfigure using --disable-webapp-runtime.])
fi
changequote(,)
MAKENSISU_VER=`"$MAKENSISU" -version 2>/dev/null | sed -e '/-Unicode/!s/.*//g' -e 's/^v\([0-9]\+\.[0-9]\+\)\-Unicode$/\1/g'`
changequote([,])
if test ! "$MAKENSISU_VER" = ""; then
MAKENSISU_MAJOR_VER=`echo $MAKENSISU_VER | $AWK -F\. '{ print $1 }'`
MAKENSISU_MINOR_VER=`echo $MAKENSISU_VER | $AWK -F\. '{ print $2 }'`
fi
AC_MSG_CHECKING([for Unicode NSIS with major version == $REQ_NSIS_MAJOR_VER and minor version >= $MIN_NSIS_MINOR_VER])
if test "$MAKENSISU_VER" = "" ||
test ! "$MAKENSISU_MAJOR_VER" = "$REQ_NSIS_MAJOR_VER" -o \
! "$MAKENSISU_MINOR_VER" -ge $MIN_NSIS_MINOR_VER; then
AC_MSG_RESULT([no])
AC_MSG_ERROR([To build the Web App Runtime you must have the latest MozillaBuild or Unicode NSIS with a major version of $REQ_NSIS_MAJOR_VER and a minimum minor version of $MIN_NSIS_MINOR_VER in your path. To build without the Web App Runtime reconfigure using --disable-webapp-runtime.])
fi
AC_MSG_RESULT([yes])
fi
AC_SUBST(MOZ_WEBAPP_RUNTIME)
if test "$MOZ_WEBAPP_RUNTIME"; then
AC_DEFINE(MOZ_WEBAPP_RUNTIME)
fi
dnl ========================================================
dnl Installer
dnl ========================================================

View File

@ -87,7 +87,7 @@ function CSPWarning(aMsg, aSource, aScriptSample, aLineNum) {
var consoleMsg = Components.classes["@mozilla.org/scripterror;1"]
.createInstance(Components.interfaces.nsIScriptError);
consoleMsg.init('CSP: ' + aMsg, aSource, aScriptSample, aLineNum, 0,
consoleMsg.init(textMessage, aSource, aScriptSample, aLineNum, 0,
Components.interfaces.nsIScriptError.warningFlag,
"Content Security Policy");
Components.classes["@mozilla.org/consoleservice;1"]
@ -100,7 +100,7 @@ function CSPError(aMsg) {
var consoleMsg = Components.classes["@mozilla.org/scripterror;1"]
.createInstance(Components.interfaces.nsIScriptError);
consoleMsg.init('CSP: ' + aMsg, null, null, 0, 0,
consoleMsg.init(textMessage, null, null, 0, 0,
Components.interfaces.nsIScriptError.errorFlag,
"Content Security Policy");
Components.classes["@mozilla.org/consoleservice;1"]
@ -213,7 +213,7 @@ CSPRep.ALLOW_DIRECTIVE = "allow";
* @param aStr
* string rep of a CSP
* @param self (optional)
* string or CSPSource representing the "self" source
* URI representing the "self" source
* @param docRequest (optional)
* request for the parent document which may need to be suspended
* while the policy-uri is asynchronously fetched
@ -231,8 +231,6 @@ CSPRep.fromString = function(aStr, self, docRequest, csp) {
var selfUri = null;
if (self instanceof Components.interfaces.nsIURI)
selfUri = self.clone();
else if (self)
selfUri = gIoService.newURI(self, null, null);
var dirs = aStr.split(";");
@ -452,8 +450,8 @@ CSPRep.prototype = {
var dirs = [];
if (this._allowEval || this._allowInlineScripts) {
dirs.push("options " + (this._allowEval ? "eval-script" : "")
+ (this._allowInlineScripts ? "inline-script" : ""));
dirs.push("options" + (this._allowEval ? " eval-script" : "")
+ (this._allowInlineScripts ? " inline-script" : ""));
}
for (var i in this._directives) {
if (this._directives[i]) {
@ -604,7 +602,7 @@ function CSPSourceList() {
* @param aStr
* string rep of a CSP Source List
* @param self (optional)
* string or CSPSource representing the "self" source
* URI or CSPSource representing the "self" source
* @param enforceSelfChecks (optional)
* if present, and "true", will check to be sure "self" has the
* appropriate values to inherit when they are omitted from the source.
@ -618,6 +616,12 @@ CSPSourceList.fromString = function(aStr, self, enforceSelfChecks) {
// <source-list> ::= <source>
// | <source-list>" "<source>
/* If self parameter is passed, convert to CSPSource,
unless it is already a CSPSource. */
if(self && !(self instanceof CSPSource)) {
self = CSPSource.create(self);
}
var slObj = new CSPSourceList();
if (aStr === "'none'")
return slObj;
@ -810,6 +814,15 @@ function CSPSource() {
* - nsURI
* - string
* - CSPSource (clone)
* @param aData
* string, nsURI, or CSPSource
* @param self (optional)
* if present, string, URI, or CSPSource representing the "self" resource
* @param enforceSelfChecks (optional)
* if present, and "true", will check to be sure "self" has the
* appropriate values to inherit when they are omitted from the source.
* @returns
* an instance of CSPSource
*/
CSPSource.create = function(aData, self, enforceSelfChecks) {
if (typeof aData === 'string')
@ -912,7 +925,7 @@ CSPSource.fromURI = function(aURI, self, enforceSelfChecks) {
* @param aStr
* string rep of a CSP Source
* @param self (optional)
* string or CSPSource representing the "self" source
* string, URI, or CSPSource representing the "self" source
* @param enforceSelfChecks (optional)
* if present, and "true", will check to be sure "self" has the
* appropriate values to inherit when they are omitted from aURI.

View File

@ -239,8 +239,10 @@ ContentSecurityPolicy.prototype = {
// If there is a policy-uri, fetch the policy, then re-call this function.
// (1) parse and create a CSPRep object
// Note that we pass the full URI since when it's parsed as 'self' to construct a
// CSPSource only the scheme, host, and port are kept.
var newpolicy = CSPRep.fromString(aPolicy,
selfURI.scheme + "://" + selfURI.hostPort,
selfURI,
this._docRequest,
this);

View File

@ -410,8 +410,9 @@ nsPlainTextSerializer::AppendElementEnd(Element* aElement,
mOutputString = nsnull;
if (id == nsGkAtoms::head) {
NS_ASSERTION(mHeadLevel != 0,
"mHeadLevel being decremented below 0");
--mHeadLevel;
NS_ASSERTION(mHeadLevel >= 0, "mHeadLevel < 0");
}
return rv;

View File

@ -62,6 +62,9 @@
#include "nsLayoutUtils.h"
#include "nsTextFrame.h"
#include "nsFontFaceList.h"
#include "mozilla/Telemetry.h"
using namespace mozilla;
nsresult NS_NewContentIterator(nsIContentIterator** aInstancePtrResult);
nsresult NS_NewContentSubtreeIterator(nsIContentIterator** aInstancePtrResult);
@ -243,6 +246,9 @@ nsRange::~nsRange()
{
NS_ASSERTION(!IsInSelection(), "deleting nsRange that is in use");
// Maybe we can remove Detach() -- bug 702948.
Telemetry::Accumulate(Telemetry::DOM_RANGE_DETACHED, mIsDetached);
// we want the side effects (releases and list removals)
DoSetRange(nsnull, 0, nsnull, 0, nsnull);
}

View File

@ -10,14 +10,20 @@ const POLICY_URI_RELATIVE = "/policy";
const DOCUMENT_URI = "http://localhost:" + POLICY_PORT + "/document";
const CSP_DOC_BODY = "CSP doc content";
const SD = CSPRep.SRC_DIRECTIVES;
const MAX_TESTS = 2;
var TESTS_COMPLETED = 0;
var cspr, cspr_static;
// this will get populated by run_tests()
var TESTS = [];
// helper to make URIs
function mkuri(foo) {
return Components.classes["@mozilla.org/network/io-service;1"]
.getService(Components.interfaces.nsIIOService)
.newURI(foo, null, null);
}
// helper to use .equals on stuff
function do_check_equivalent(foo, bar, stack) {
if (!stack)
if (!stack)
stack = Components.stack.caller;
var text = foo + ".equals(" + bar + ")";
@ -30,8 +36,10 @@ function do_check_equivalent(foo, bar, stack) {
do_throw(text, stack);
}
function listener() {
function listener(csp, cspr_static) {
this.buffer = "";
this._csp = csp;
this._cspr_static = cspr_static;
}
listener.prototype = {
@ -49,20 +57,30 @@ listener.prototype = {
// make sure that we have the full document content, guaranteeing that
// the document channel has been resumed, before we do the comparisons
if (this.buffer == CSP_DOC_BODY) {
// "policy-uri failed to load"
// need to re-grab cspr since it may have changed inside the document's
// nsIContentSecurityPolicy instance. The problem is, this cspr_str is a
// string and not a policy due to the way it's exposed from
// nsIContentSecurityPolicy, so we have to re-parse it.
let cspr_str = this._csp.policy;
let cspr = CSPRep.fromString(cspr_str, mkuri(DOCUMENT_URI));
// and in reparsing it, we lose the 'self' relationships, so need to also
// reparse the static one (or find a way to resolve 'self' in the parsed
// policy when doing comparisons).
let cspr_static_str = this._cspr_static.toString();
let cspr_static_reparse = CSPRep.fromString(cspr_static_str, mkuri(DOCUMENT_URI));
// not null, and one policy .equals the other one
do_check_neq(null, cspr);
do_check_true(cspr.equals(cspr_static_reparse));
// other directives inherit self
for (var i in SD) {
do_check_equivalent(cspr._directives[SD[i]],
cspr_static._directives[SD[i]]);
}
do_test_finished();
TESTS_COMPLETED++;
// final teardown
if (TESTS_COMPLETED == MAX_TESTS) {
httpserv.stop(function(){});
if (TESTS.length == 0) {
httpserv.stop(do_test_finished);
} else {
do_test_finished();
(TESTS.shift())();
}
}
}
@ -73,12 +91,11 @@ function run_test() {
httpserv.registerPathHandler("/document", csp_doc_response);
httpserv.registerPathHandler("/policy", csp_policy_response);
httpserv.start(POLICY_PORT);
TESTS = [ test_CSPRep_fromPolicyURI, test_CSPRep_fromRelativePolicyURI ];
var tests = [ test_CSPRep_fromPolicyURI, test_CSPRep_fromRelativePolicyURI];
for (var i = 0 ; i < tests.length ; i++) {
tests[i]();
do_test_pending();
}
// when this triggers the "onStopRequest" callback, it'll
// go to the next test.
(TESTS.shift())();
}
function makeChan(url) {
@ -101,27 +118,41 @@ function csp_policy_response(metadata, response) {
///////////////////// TEST POLICY_URI //////////////////////
function test_CSPRep_fromPolicyURI() {
var csp = Components.classes["@mozilla.org/contentsecuritypolicy;1"]
.createInstance[Components.interfaces.nsIContentSecurityPolicy];
do_test_pending();
let csp = Cc["@mozilla.org/contentsecuritypolicy;1"]
.createInstance(Ci.nsIContentSecurityPolicy);
// once the policy-uri is returned we will compare our static CSPRep with one
// we generated from the content we got back from the network to make sure
// they are equivalent
cspr_static = CSPRep.fromString(POLICY_FROM_URI, DOCUMENT_URI);
let cspr_static = CSPRep.fromString(POLICY_FROM_URI, mkuri(DOCUMENT_URI));
// simulates the request for the parent document
var docChan = makeChan(DOCUMENT_URI);
docChan.asyncOpen(new listener(), null);
cspr = CSPRep.fromString("policy-uri " + POLICY_URI, DOCUMENT_URI, docChan, csp);
docChan.asyncOpen(new listener(csp, cspr_static), null);
// the resulting policy here can be discarded, since it's going to be
// "allow *"; when the policy-uri fetching call-back happens, the *real*
// policy will be in csp.policy
CSPRep.fromString("policy-uri " + POLICY_URI,
mkuri(DOCUMENT_URI), docChan, csp);
}
function test_CSPRep_fromRelativePolicyURI() {
var csp = Components.classes["@mozilla.org/contentsecuritypolicy;1"]
.createInstance[Components.interfaces.nsIContentSecurityPolicy];
do_test_pending();
let csp = Cc["@mozilla.org/contentsecuritypolicy;1"]
.createInstance(Ci.nsIContentSecurityPolicy);
// once the policy-uri is returned we will compare our static CSPRep with one
// we generated from the content we got back from the network to make sure
// they are equivalent
cspr_static = CSPRep.fromString(POLICY_FROM_URI, DOCUMENT_URI);
let cspr_static = CSPRep.fromString(POLICY_FROM_URI, mkuri(DOCUMENT_URI));
// simulates the request for the parent document
var docChan = makeChan(DOCUMENT_URI);
docChan.asyncOpen(new listener(), null);
cspr = CSPRep.fromString("policy-uri " + POLICY_URI_RELATIVE, DOCUMENT_URI, docChan, csp);
docChan.asyncOpen(new listener(csp, cspr_static), null);
// the resulting policy here can be discarded, since it's going to be
// "allow *"; when the policy-uri fetching call-back happens, the *real*
// policy will be in csp.policy
CSPRep.fromString("policy-uri " + POLICY_URI_RELATIVE,
mkuri(DOCUMENT_URI), docChan, csp);
}

View File

@ -47,6 +47,14 @@ const POLICY_PORT = 9000;
const POLICY_URI = "http://localhost:" + POLICY_PORT + "/policy";
const POLICY_URI_RELATIVE = "/policy";
//converts string to nsIURI
function URI(uriString) {
var ioService = Components.classes["@mozilla.org/network/io-service;1"]
.getService(Components.interfaces.nsIIOService);
return ioService.newURI(uriString, null, null);
}
// helper to assert that an array has the given value somewhere.
function do_check_in_array(arr, val, stack) {
if (!stack)
@ -272,7 +280,7 @@ test(
function test_CSPSourceList_fromString_twohost() {
var str = "foo.bar:21 https://ras.bar";
var parsed = "http://foo.bar:21 https://ras.bar:443";
var sd = CSPSourceList.fromString(str, "http://self.com:80");
var sd = CSPSourceList.fromString(str, URI("http://self.com:80"));
//"two-host list should parse"
do_check_neq(null,sd);
//"two-host list should parse to two hosts"
@ -284,9 +292,9 @@ test(
test(
function test_CSPSourceList_permits() {
var nullSourceList = CSPSourceList.fromString("'none'");
var simpleSourceList = CSPSourceList.fromString("a.com", "http://self.com");
var simpleSourceList = CSPSourceList.fromString("a.com", URI("http://self.com"));
var doubleSourceList = CSPSourceList.fromString("https://foo.com http://bar.com:88",
"http://self.com:88");
URI("http://self.com:88"));
var allSourceList = CSPSourceList.fromString("*");
//'none' should permit none."
@ -362,7 +370,7 @@ test(
var SD = CSPRep.SRC_DIRECTIVES;
// check default policy "allow *"
cspr = CSPRep.fromString("allow *", "http://self.com:80");
cspr = CSPRep.fromString("allow *", URI("http://self.com:80"));
// "DEFAULT_SRC directive is missing when specified in fromString"
do_check_has_key(cspr._directives, SD.DEFAULT_SRC);
@ -384,7 +392,7 @@ test(
var SD = CSPRep.SRC_DIRECTIVES;
// apply policy of "default-src *" (e.g. "allow *")
cspr = CSPRep.fromString("default-src *", "http://self.com:80");
cspr = CSPRep.fromString("default-src *", URI("http://self.com:80"));
// "DEFAULT_SRC directive is missing when specified in fromString"
do_check_has_key(cspr._directives, SD.DEFAULT_SRC);
@ -399,8 +407,8 @@ test(
// check that |allow *| and |default-src *| are parsed equivalently and
// result in the same set of explicit policy directives
cspr = CSPRep.fromString("default-src *", "http://self.com:80");
cspr_allow = CSPRep.fromString("allow *", "http://self.com:80");
cspr = CSPRep.fromString("default-src *", URI("http://self.com:80"));
cspr_allow = CSPRep.fromString("allow *", URI("http://self.com:80"));
for (var d in SD) {
do_check_equivalent(cspr._directives[SD[d]],
@ -418,7 +426,7 @@ test(
// check one-directive policies
cspr = CSPRep.fromString("allow bar.com; script-src https://foo.com",
"http://self.com");
URI("http://self.com"));
for(var x in DEFAULTS) {
//DEFAULTS[x] + " does not use default rule."
@ -446,7 +454,7 @@ test(
var polstr = "allow allow.com; "
+ "script-src https://foo.com; "
+ "img-src bar.com:*";
cspr = CSPRep.fromString(polstr, "http://self.com");
cspr = CSPRep.fromString(polstr, URI("http://self.com"));
for(var x in DEFAULTS) {
do_check_true(cspr.permits("http://allow.com", DEFAULTS[x]));
@ -478,7 +486,7 @@ test(function test_CSPRep_fromString_withself() {
// check one-directive policies
cspr = CSPRep.fromString("allow 'self'; script-src 'self' https://*:*",
self);
URI(self));
//"img-src does not enforce default rule, 'self'.
do_check_false(cspr.permits("https://foo.com:400", SD.IMG_SRC));
//"img-src does not allow self
@ -498,7 +506,7 @@ test(function test_FrameAncestor_defaults() {
var SD = CSPRep.SRC_DIRECTIVES;
var self = "http://self.com:34";
cspr = CSPRep.fromString("allow 'none'", self);
cspr = CSPRep.fromString("allow 'none'", URI(self));
//"frame-ancestors should default to * not 'allow' value"
do_check_true(cspr.permits("https://foo.com:400", SD.FRAME_ANCESTORS));
@ -507,7 +515,7 @@ test(function test_FrameAncestor_defaults() {
do_check_true(cspr.permits("http://self.com", SD.FRAME_ANCESTORS));
do_check_true(cspr.permits("http://subd.self.com:34", SD.FRAME_ANCESTORS));
cspr = CSPRep.fromString("allow 'none'; frame-ancestors 'self'", self);
cspr = CSPRep.fromString("allow 'none'; frame-ancestors 'self'", URI(self));
//"frame-ancestors should only allow self"
do_check_true(cspr.permits("http://self.com:34", SD.FRAME_ANCESTORS));
@ -531,27 +539,27 @@ test(function test_CSP_ReportURI_parsing() {
var uri_valid_relative2_expanded = self + "/" + uri_valid_relative2;
var uri_invalid_relative = "javascript:alert(1)";
cspr = CSPRep.fromString("allow *; report-uri " + uri_valid_absolute, self);
cspr = CSPRep.fromString("allow *; report-uri " + uri_valid_absolute, URI(self));
parsedURIs = cspr.getReportURIs().split(/\s+/);
do_check_in_array(parsedURIs, uri_valid_absolute);
do_check_eq(parsedURIs.length, 1);
cspr = CSPRep.fromString("allow *; report-uri " + uri_invalid_host_absolute, self);
cspr = CSPRep.fromString("allow *; report-uri " + uri_invalid_host_absolute, URI(self));
parsedURIs = cspr.getReportURIs().split(/\s+/);
do_check_in_array(parsedURIs, "");
do_check_eq(parsedURIs.length, 1); // the empty string is in there.
cspr = CSPRep.fromString("allow *; report-uri " + uri_invalid_relative, self);
cspr = CSPRep.fromString("allow *; report-uri " + uri_invalid_relative, URI(self));
parsedURIs = cspr.getReportURIs().split(/\s+/);
do_check_in_array(parsedURIs, "");
do_check_eq(parsedURIs.length, 1);
cspr = CSPRep.fromString("allow *; report-uri " + uri_valid_relative, self);
cspr = CSPRep.fromString("allow *; report-uri " + uri_valid_relative, URI(self));
parsedURIs = cspr.getReportURIs().split(/\s+/);
do_check_in_array(parsedURIs, uri_valid_relative_expanded);
do_check_eq(parsedURIs.length, 1);
cspr = CSPRep.fromString("allow *; report-uri " + uri_valid_relative2, self);
cspr = CSPRep.fromString("allow *; report-uri " + uri_valid_relative2, URI(self));
parsedURIs = cspr.getReportURIs().split(/\s+/);
dump(parsedURIs.length);
do_check_in_array(parsedURIs, uri_valid_relative2_expanded);
@ -560,7 +568,7 @@ test(function test_CSP_ReportURI_parsing() {
// combination!
cspr = CSPRep.fromString("allow *; report-uri " +
uri_valid_relative2 + " " +
uri_valid_absolute, self);
uri_valid_absolute, URI(self));
parsedURIs = cspr.getReportURIs().split(/\s+/);
do_check_in_array(parsedURIs, uri_valid_relative2_expanded);
do_check_in_array(parsedURIs, uri_valid_absolute);
@ -569,7 +577,7 @@ test(function test_CSP_ReportURI_parsing() {
cspr = CSPRep.fromString("allow *; report-uri " +
uri_valid_relative2 + " " +
uri_invalid_host_absolute + " " +
uri_valid_absolute, self);
uri_valid_absolute, URI(self));
parsedURIs = cspr.getReportURIs().split(/\s+/);
do_check_in_array(parsedURIs, uri_valid_relative2_expanded);
do_check_in_array(parsedURIs, uri_valid_absolute);
@ -631,11 +639,11 @@ test(function test_CSPRep_fromPolicyURI_failswhenmixed() {
var my_uri_policy = "policy-uri " + POLICY_URI;
//print(" --- Ignore the following two errors if they print ---");
cspr = CSPRep.fromString("allow *; " + my_uri_policy, self);
cspr = CSPRep.fromString("allow *; " + my_uri_policy, URI(self));
//"Parsing should fail when 'policy-uri' is mixed with allow directive"
do_check_equivalent(cspr, closed_policy);
cspr = CSPRep.fromString("img-src 'self'; " + my_uri_policy, self);
cspr = CSPRep.fromString("img-src 'self'; " + my_uri_policy, URI(self));
//"Parsing should fail when 'policy-uri' is mixed with other directives"
do_check_equivalent(cspr, closed_policy);

View File

@ -58,49 +58,89 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=408231
["unlink", "true"],
["not-a-command", "false"]
];
var commandStateResults = [
["contentReadOnly", "exception"],
["copy", "exception"],
["createlink", "exception"],
["cut", "exception"],
["decreasefontsize", "exception"],
["delete", "exception"],
["fontname", "exception"],
["fontsize", "exception"],
["formatblock", "exception"],
["heading", "exception"],
["hilitecolor", "exception"],
["increasefontsize", "exception"],
["indent", "exception"],
["inserthorizontalrule", "exception"],
["inserthtml", "exception"],
["insertimage", "exception"],
var commandIndetermResults = [
["contentReadOnly", "false"],
["copy", "false"],
["createlink", "false"],
["cut", "false"],
["decreasefontsize", "false"],
["delete", "false"],
["fontname", "false"],
["fontsize", "false"],
["formatblock", "false"],
["heading", "false"],
["hilitecolor", "false"],
["increasefontsize", "false"],
["indent", "false"],
["inserthorizontalrule", "false"],
["inserthtml", "false"],
["insertimage", "false"],
["insertorderedlist", "false"],
["insertunorderedlist", "false"],
["insertparagraph", "exception"],
["insertparagraph", "false"],
["italic", "false"],
["justifycenter", "false"],
["justifyfull", "false"],
["justifyleft", "true"],
["justifyleft", "false"],
["justifyright", "false"],
["outdent", "exception"],
//["paste", "exception"],
["redo", "exception"],
["removeformat", "exception"],
["selectall", "exception"],
["outdent", "false"],
//["paste", "false"],
["redo", "false"],
["removeformat", "false"],
["selectall", "false"],
["strikethrough", "false"],
["styleWithCSS", "false"],
["subscript", "false"],
["superscript", "false"],
["underline", "false"],
["undo", "exception"],
["undo", "false"],
["unlink", "false"],
["not-a-command", "exception"]
["not-a-command", "NS_ERROR_NOT_IMPLEMENTED"]
];
var commandStateResults = [
["contentReadOnly", "false"],
["copy", "false"],
["createlink", "false"],
["cut", "false"],
["decreasefontsize", "false"],
["delete", "false"],
["fontname", "false"],
["fontsize", "false"],
["formatblock", "false"],
["heading", "false"],
["hilitecolor", "false"],
["increasefontsize", "false"],
["indent", "false"],
["inserthorizontalrule", "false"],
["inserthtml", "false"],
["insertimage", "false"],
["insertorderedlist", "false"],
["insertunorderedlist", "false"],
["insertparagraph", "false"],
["italic", "false"],
["justifycenter", "false"],
["justifyfull", "false"],
["justifyleft", "true"],
["justifyright", "false"],
["outdent", "false"],
//["paste", "false"],
["redo", "false"],
["removeformat", "false"],
["selectall", "false"],
["strikethrough", "false"],
["styleWithCSS", "false"],
["subscript", "false"],
["superscript", "false"],
["underline", "false"],
["undo", "false"],
["unlink", "false"],
["not-a-command", "NS_ERROR_NOT_IMPLEMENTED"]
];
var commandValueResults = [
["contentReadOnly", "exception"],
["contentReadOnly", ""],
["copy", ""],
["createlink", ""],
["cut", ""],
@ -136,7 +176,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=408231
["underline", ""],
["undo", ""],
["unlink", ""],
["not-a-command", "exception"],
["not-a-command", "NS_ERROR_NOT_IMPLEMENTED"],
];
@ -145,7 +185,17 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=408231
try {
result = '' + document.queryCommandEnabled( cmdName );
} catch( error ) {
result = 'exception';
result = 'name' in error ? error.name : 'exception';
}
return result;
}
function callQueryCommandIndeterm(cmdName) {
var result;
try {
result = '' + document.queryCommandIndeterm( cmdName );
} catch( error ) {
result = 'name' in error ? error.name : 'exception';
}
return result;
}
@ -155,7 +205,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=408231
try {
result = '' + document.queryCommandState( cmdName );
} catch( error ) {
result = 'exception';
result = 'name' in error ? error.name : 'exception';
}
return result;
}
@ -165,7 +215,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=408231
try {
result = '' + document.queryCommandValue( cmdName );
} catch( error ) {
result = 'exception';
result = 'name' in error ? error.name : 'exception';
}
return result;
}
@ -183,6 +233,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=408231
document.designMode='on';
window.getSelection().collapse(document.body, 0);
testQueryCommand(commandEnabledResults, callQueryCommandEnabled, "queryCommandEnabled");
testQueryCommand(commandIndetermResults, callQueryCommandIndeterm, "queryCommandIndeterm");
testQueryCommand(commandStateResults, callQueryCommandState, "queryCommandState");
testQueryCommand(commandValueResults, callQueryCommandValue, "queryCommandValue");
document.designMode='off';

View File

@ -2818,7 +2818,7 @@ static const struct MidasCommand gMidasCommandTable[] = {
{ "redo", "cmd_redo", "", true, false },
{ "indent", "cmd_indent", "", true, false },
{ "outdent", "cmd_outdent", "", true, false },
{ "backcolor", "cmd_backgroundColor", "", false, false },
{ "backcolor", "cmd_highlight", "", false, false },
{ "forecolor", "cmd_fontColor", "", false, false },
{ "hilitecolor", "cmd_highlight", "", false, false },
{ "fontname", "cmd_fontFace", "", false, false },
@ -2953,7 +2953,9 @@ ConvertToMidasInternalCommandInner(const nsAString & inCommandID,
}
}
return j != ArrayLength(gBlocks);
if (j == ArrayLength(gBlocks)) {
outParam.Truncate();
}
}
else {
CopyUTF16toUTF8(inParam, outParam);
@ -3101,6 +3103,11 @@ nsHTMLDocument::ExecCommand(const nsAString & commandID,
cmdToDispatch, paramStr, isBool, boolVal))
return NS_OK;
if (cmdToDispatch.EqualsLiteral("cmd_paragraphState") && paramStr.IsEmpty()) {
// Invalid value
return NS_OK;
}
if (!isBool && paramStr.IsEmpty()) {
rv = cmdMgr->DoCommand(cmdToDispatch.get(), nsnull, window);
} else {
@ -3179,10 +3186,8 @@ nsHTMLDocument::QueryCommandIndeterm(const nsAString & commandID,
if (!window)
return NS_ERROR_FAILURE;
nsCAutoString cmdToDispatch, paramToCheck;
bool dummy;
if (!ConvertToMidasInternalCommand(commandID, commandID,
cmdToDispatch, paramToCheck, dummy, dummy))
nsCAutoString cmdToDispatch;
if (!ConvertToMidasInternalCommand(commandID, cmdToDispatch))
return NS_ERROR_NOT_IMPLEMENTED;
nsresult rv;
@ -3194,10 +3199,11 @@ nsHTMLDocument::QueryCommandIndeterm(const nsAString & commandID,
if (NS_FAILED(rv))
return rv;
// if command does not have a state_mixed value, this call fails, so we fail too,
// which is what is expected
rv = cmdParams->GetBooleanValue("state_mixed", _retval);
return rv;
// If command does not have a state_mixed value, this call fails and sets
// *_retval to false. This is fine -- we want to return false in that case
// anyway (bug 738385), so we just return NS_OK regardless.
cmdParams->GetBooleanValue("state_mixed", _retval);
return NS_OK;
}
/* boolean queryCommandState(in DOMString commandID); */
@ -3258,14 +3264,14 @@ nsHTMLDocument::QueryCommandState(const nsAString & commandID, bool *_retval)
}
if (actualAlignmentType)
nsMemory::Free(actualAlignmentType);
}
else {
rv = cmdParams->GetBooleanValue("state_all", _retval);
if (NS_FAILED(rv))
*_retval = false;
return rv;
}
return rv;
// If command does not have a state_all value, this call fails and sets
// *_retval to false. This is fine -- we want to return false in that case
// anyway (bug 738385), so we just return NS_OK regardless.
cmdParams->GetBooleanValue("state_all", _retval);
return NS_OK;
}
/* boolean queryCommandSupported(in DOMString commandID); */
@ -3347,12 +3353,16 @@ nsHTMLDocument::QueryCommandValue(const nsAString & commandID,
if (NS_FAILED(rv))
return rv;
// If command does not have a state_attribute value, this call fails, and
// _retval will wind up being the empty string. This is fine -- we want to
// return "" in that case anyway (bug 738385), so we just return NS_OK
// regardless.
nsXPIDLCString cStringResult;
rv = cmdParams->GetCStringValue("state_attribute",
getter_Copies(cStringResult));
cmdParams->GetCStringValue("state_attribute",
getter_Copies(cStringResult));
CopyUTF8toUTF16(cStringResult, _retval);
return rv;
return NS_OK;
}
nsresult

View File

@ -12,6 +12,8 @@ Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/FileUtils.jsm");
const WEBAPP_RUNTIME = Services.appinfo.ID == "webapprt@mozilla.org";
XPCOMUtils.defineLazyGetter(this, "NetUtil", function() {
Cu.import("resource://gre/modules/NetUtil.jsm");
return NetUtil;
@ -24,7 +26,10 @@ XPCOMUtils.defineLazyGetter(this, "ppmm", function() {
#ifdef MOZ_WIDGET_GONK
const DIRECTORY_NAME = "webappsDir";
#else
const DIRECTORY_NAME = "ProfD";
// If we're executing in the context of the webapp runtime, the data files
// are in a different directory (currently the Firefox profile that installed
// the webapp); otherwise, they're in the current profile.
const DIRECTORY_NAME = WEBAPP_RUNTIME ? "WebappRegD" : "ProfD";
#endif
let DOMApplicationRegistry = {

View File

@ -143,9 +143,7 @@ AudioRunnable::Run()
if (!jenv)
return NS_ERROR_FAILURE;
if (jenv->PushLocalFrame(128)) {
return NS_ERROR_FAILURE;
}
mozilla::AndroidBridge::AutoLocalJNIFrame autoFrame(jenv);
jbyteArray bytearray = jenv->NewByteArray(mTrack->bufferSize);
if (!bytearray) {
@ -201,7 +199,6 @@ AudioRunnable::Run()
free(mTrack);
jenv->ReleaseByteArrayElements(bytearray, byte, 0);
jenv->PopLocalFrame(NULL);
return NS_OK;
}

View File

@ -914,8 +914,8 @@ nsHighlightColorStateCommand::SetState(nsIEditor *aEditor, nsString& newState)
// rv = RemoveOneProperty(htmlEditor, NS_LITERAL_STRING("font"), NS_LITERAL_STRING("bgcolor"));
rv = htmlEditor->RemoveInlineProperty(fontAtom, NS_LITERAL_STRING("bgcolor"));
} else {
rv = htmlEditor->SetCSSInlineProperty(fontAtom, NS_LITERAL_STRING("bgcolor"),
newState);
rv = htmlEditor->SetInlineProperty(fontAtom, NS_LITERAL_STRING("bgcolor"),
newState);
}
return rv;

View File

@ -52,7 +52,7 @@ interface nsIContentFilter;
NS_ERROR_GENERATE_SUCCESS(NS_ERROR_MODULE_EDITOR, 1)
%}
[scriptable, uuid(FF67AD39-ED58-4CD1-A1A3-DCD988390A97)]
[scriptable, uuid(833f30de-94c7-4630-a852-2300ef329d7b)]
interface nsIHTMLEditor : nsISupports
{
@ -118,9 +118,6 @@ interface nsIHTMLEditor : nsISupports
* Example: aProperty="font", aAttribute="color",
* aValue="0x00FFFF"
*/
void setCSSInlineProperty(in nsIAtom aProperty,
in AString aAttribute,
in AString aValue);
void setInlineProperty(in nsIAtom aProperty,
in AString aAttribute,
in AString aValue);

View File

@ -109,18 +109,6 @@ NS_IMETHODIMP nsHTMLEditor::RemoveAllDefaultProperties()
}
// Add the CSS style corresponding to the HTML inline style defined
// by aProperty aAttribute and aValue to the selection
NS_IMETHODIMP nsHTMLEditor::SetCSSInlineProperty(nsIAtom *aProperty,
const nsAString & aAttribute,
const nsAString & aValue)
{
if (IsCSSEnabled()) {
return SetInlineProperty(aProperty, aAttribute, aValue);
}
return NS_OK;
}
NS_IMETHODIMP nsHTMLEditor::SetInlineProperty(nsIAtom *aProperty,
const nsAString & aAttribute,
const nsAString & aValue)
@ -385,60 +373,58 @@ nsHTMLEditor::SetInlinePropertyOnNode( nsIDOMNode *aNode,
nsAutoString tag;
aProperty->ToString(tag);
ToLowerCase(tag);
if (IsCSSEnabled())
{
// we are in CSS mode
if (mHTMLCSSUtils->IsCSSEditableProperty(aNode, aProperty, aAttribute))
{
// the HTML style defined by aProperty/aAttribute has a CSS equivalence
// in this implementation for the node aNode
nsCOMPtr<nsIDOMNode> tmp = aNode;
if (IsTextNode(tmp))
{
// we are working on a text node and need to create a span container
// that will carry the styles
InsertContainerAbove( aNode,
address_of(tmp),
NS_LITERAL_STRING("span"),
nsnull,
nsnull);
}
nsCOMPtr<nsIDOMElement>element;
element = do_QueryInterface(tmp);
// first we have to remove occurences of the same style hint in the
// children of the aNode
res = RemoveStyleInside(tmp, aProperty, aAttribute, true);
NS_ENSURE_SUCCESS(res, res);
PRInt32 count;
// then we add the css styles corresponding to the HTML style request
res = mHTMLCSSUtils->SetCSSEquivalentToHTMLStyle(element, aProperty, aAttribute, aValue, &count, false);
NS_ENSURE_SUCCESS(res, res);
nsCOMPtr<nsIDOMNode> nextSibling, previousSibling;
GetNextHTMLSibling(tmp, address_of(nextSibling));
GetPriorHTMLSibling(tmp, address_of(previousSibling));
if (nextSibling || previousSibling)
{
nsCOMPtr<nsIDOMNode> mergeParent;
res = tmp->GetParentNode(getter_AddRefs(mergeParent));
NS_ENSURE_SUCCESS(res, res);
if (previousSibling &&
nsEditor::NodeIsType(previousSibling, nsEditProperty::span) &&
NodesSameType(tmp, previousSibling))
{
res = JoinNodes(previousSibling, tmp, mergeParent);
NS_ENSURE_SUCCESS(res, res);
}
if (nextSibling &&
nsEditor::NodeIsType(nextSibling, nsEditProperty::span) &&
NodesSameType(tmp, nextSibling))
{
res = JoinNodes(tmp, nextSibling, mergeParent);
}
}
return res;
bool useCSS = (IsCSSEnabled() &&
mHTMLCSSUtils->IsCSSEditableProperty(aNode, aProperty, aAttribute)) ||
// bgcolor is always done using CSS
aAttribute->EqualsLiteral("bgcolor");
if (useCSS) {
nsCOMPtr<nsIDOMNode> tmp = aNode;
if (IsTextNode(tmp))
{
// we are working on a text node and need to create a span container
// that will carry the styles
InsertContainerAbove(aNode,
address_of(tmp),
NS_LITERAL_STRING("span"),
nsnull,
nsnull);
}
nsCOMPtr<nsIDOMElement>element;
element = do_QueryInterface(tmp);
// first we have to remove occurences of the same style hint in the
// children of the aNode
res = RemoveStyleInside(tmp, aProperty, aAttribute, true);
NS_ENSURE_SUCCESS(res, res);
PRInt32 count;
// then we add the css styles corresponding to the HTML style request
res = mHTMLCSSUtils->SetCSSEquivalentToHTMLStyle(element, aProperty, aAttribute, aValue, &count, false);
NS_ENSURE_SUCCESS(res, res);
nsCOMPtr<nsIDOMNode> nextSibling, previousSibling;
GetNextHTMLSibling(tmp, address_of(nextSibling));
GetPriorHTMLSibling(tmp, address_of(previousSibling));
if (nextSibling || previousSibling)
{
nsCOMPtr<nsIDOMNode> mergeParent;
res = tmp->GetParentNode(getter_AddRefs(mergeParent));
NS_ENSURE_SUCCESS(res, res);
if (previousSibling &&
nsEditor::NodeIsType(previousSibling, nsEditProperty::span) &&
NodesSameType(tmp, previousSibling))
{
res = JoinNodes(previousSibling, tmp, mergeParent);
NS_ENSURE_SUCCESS(res, res);
}
if (nextSibling &&
nsEditor::NodeIsType(nextSibling, nsEditProperty::span) &&
NodesSameType(tmp, nextSibling))
{
res = JoinNodes(tmp, nextSibling, mergeParent);
}
}
return res;
}
// don't need to do anything if property already set on node

View File

@ -18,11 +18,8 @@ var knownFailures = {
'0-undefined' : true
},
'a' : {
'backcolor-0' : true,
'backcolor-1' : true,
'createbookmark-0' : true,
'fontsize-1' : true,
'hilitecolor-0' : true,
'subscript-1' : true,
'superscript-1' : true,
},
@ -35,16 +32,10 @@ var knownFailures = {
'unbookmark-0' : true,
},
'q': {
'backcolor-0' : true,
'backcolor-1' : true,
'backcolor-2' : true,
'fontsize-1' : true,
'fontsize-2' : true,
},
'c': {
'backcolor-0' : true,
'backcolor-1' : true,
'backcolor-2' : true,
'fontname-0' : true,
'fontname-2' : true,
'fontname-3' : true,

View File

@ -1893,26 +1893,18 @@ nsTextServicesDocument::DidJoinNodes(nsIDOMNode *aLeftNode,
// fflush(stdout);
//**** KDEBUG ****
// Make sure that both nodes are text nodes!
// Make sure that both nodes are text nodes -- otherwise we don't care.
result = aLeftNode->GetNodeType(&type);
NS_ENSURE_SUCCESS(result, false);
if (nsIDOMNode::TEXT_NODE != type)
{
NS_ERROR("JoinNode called with a non-text left node!");
return NS_ERROR_FAILURE;
if (nsIDOMNode::TEXT_NODE != type) {
return NS_OK;
}
result = aRightNode->GetNodeType(&type);
NS_ENSURE_SUCCESS(result, false);
if (nsIDOMNode::TEXT_NODE != type)
{
NS_ERROR("JoinNode called with a non-text right node!");
return NS_ERROR_FAILURE;
if (nsIDOMNode::TEXT_NODE != type) {
return NS_OK;
}
// Note: The editor merges the contents of the left node into the

View File

@ -231,23 +231,6 @@ CompositorParent::Composite()
#endif
}
// Go down shadow layer tree, setting properties to match their non-shadow
// counterparts.
static void
SetShadowProperties(Layer* aLayer)
{
// FIXME: Bug 717688 -- Do these updates in ShadowLayersParent::RecvUpdate.
ShadowLayer* shadow = aLayer->AsShadowLayer();
shadow->SetShadowTransform(aLayer->GetTransform());
shadow->SetShadowVisibleRegion(aLayer->GetVisibleRegion());
shadow->SetShadowClipRect(aLayer->GetClipRect());
for (Layer* child = aLayer->GetFirstChild();
child; child = child->GetNextSibling()) {
SetShadowProperties(child);
}
}
#ifdef MOZ_WIDGET_ANDROID
// Do a breadth-first search to find the first layer in the tree that is
// scrollable.
@ -256,21 +239,6 @@ CompositorParent::GetPrimaryScrollableLayer()
{
Layer* root = mLayerManager->GetRoot();
// FIXME: We're currently getting passed layers that are not part of our content, but
// we are drawing them anyway. This is causing severe rendering corruption to our background
// and checkerboarding. The real fix here is to assert that we don't have any useless layers
// and ensure that layout isn't giving us any. This is being tracked in bug 728284.
// For now just clip them to the empty rect so we don't draw them.
Layer* discardLayer = root->GetFirstChild();
while (discardLayer) {
if (!discardLayer->AsContainerLayer()) {
discardLayer->IntersectClipRect(nsIntRect());
SetShadowProperties(discardLayer);
}
discardLayer = discardLayer->GetNextSibling();
}
nsTArray<Layer*> queue;
queue.AppendElement(root);
while (queue.Length()) {
@ -296,6 +264,23 @@ CompositorParent::GetPrimaryScrollableLayer()
}
#endif
// Go down shadow layer tree, setting properties to match their non-shadow
// counterparts.
static void
SetShadowProperties(Layer* aLayer)
{
// FIXME: Bug 717688 -- Do these updates in ShadowLayersParent::RecvUpdate.
ShadowLayer* shadow = aLayer->AsShadowLayer();
shadow->SetShadowTransform(aLayer->GetTransform());
shadow->SetShadowVisibleRegion(aLayer->GetVisibleRegion());
shadow->SetShadowClipRect(aLayer->GetClipRect());
for (Layer* child = aLayer->GetFirstChild();
child; child = child->GetNextSibling()) {
SetShadowProperties(child);
}
}
void
CompositorParent::TransformShadowTree()
{

View File

@ -2786,12 +2786,13 @@ gfxGlyphExtents::GetTightGlyphExtentsAppUnits(gfxFont *aFont,
return false;
}
aFont->SetupCairoFont(aContext);
if (aFont->SetupCairoFont(aContext)) {
#ifdef DEBUG_TEXT_RUN_STORAGE_METRICS
++gGlyphExtentsSetupLazyTight;
++gGlyphExtentsSetupLazyTight;
#endif
aFont->SetupGlyphExtents(aContext, aGlyphID, true, this);
entry = mTightGlyphExtents.GetEntry(aGlyphID);
aFont->SetupGlyphExtents(aContext, aGlyphID, true, this);
entry = mTightGlyphExtents.GetEntry(aGlyphID);
}
if (!entry) {
NS_WARNING("Could not get glyph extents");
return false;
@ -5453,8 +5454,11 @@ gfxTextRun::FetchGlyphExtents(gfxContext *aRefContext)
PRUint32 glyphIndex = glyphData->GetSimpleGlyph();
if (!extents->IsGlyphKnown(glyphIndex)) {
if (!fontIsSetup) {
font->SetupCairoFont(aRefContext);
fontIsSetup = true;
if (!font->SetupCairoFont(aRefContext)) {
NS_WARNING("failed to set up font for glyph extents");
break;
}
fontIsSetup = true;
}
#ifdef DEBUG_TEXT_RUN_STORAGE_METRICS
++gGlyphExtentsSetupEagerSimple;
@ -5475,7 +5479,10 @@ gfxTextRun::FetchGlyphExtents(gfxContext *aRefContext)
PRUint32 glyphIndex = details->mGlyphID;
if (!extents->IsGlyphKnownWithTightExtents(glyphIndex)) {
if (!fontIsSetup) {
font->SetupCairoFont(aRefContext);
if (!font->SetupCairoFont(aRefContext)) {
NS_WARNING("failed to set up font for glyph extents");
break;
}
fontIsSetup = true;
}
#ifdef DEBUG_TEXT_RUN_STORAGE_METRICS

View File

@ -160,7 +160,9 @@ gfxGraphiteShaper::ShapeWord(gfxContext *aContext,
const PRUnichar *aText)
{
// some font back-ends require this in order to get proper hinted metrics
mFont->SetupCairoFont(aContext);
if (!mFont->SetupCairoFont(aContext)) {
return false;
}
mCallbackData.mContext = aContext;

Some files were not shown because too many files have changed in this diff Show More