Merge last green changeset from mozilla-inbound to mozilla-central

This commit is contained in:
Marco Bonardo 2011-11-28 14:10:59 +01:00
commit 3cb7574cf1
152 changed files with 2211 additions and 3372 deletions

View File

@ -44,7 +44,8 @@
#include "nsMai.h"
#include "prlink.h"
#include "prenv.h"
#include "nsIPrefBranch.h"
#include "mozilla/Preferences.h"
#include "nsIGConfService.h"
#include "nsIServiceManager.h"
#include "nsAutoPtr.h"
#include "nsAccessibilityService.h"
@ -53,6 +54,8 @@
#include <gtk/gtk.h>
#include <atk/atk.h>
using namespace mozilla;
typedef GType (* AtkGetTypeType) (void);
GType g_atk_hyperlink_impl_type = G_TYPE_INVALID;
static bool sATKChecked = false;
@ -61,10 +64,12 @@ static const char sATKLibName[] = "libatk-1.0.so.0";
static const char sATKHyperlinkImplGetTypeSymbol[] =
"atk_hyperlink_impl_get_type";
static const char sAccEnv [] = "GNOME_ACCESSIBILITY";
static const char sSysPrefService [] =
"@mozilla.org/system-preference-service;1";
static const char sUseSystemPrefsKey[] =
"config.use_system_prefs";
static const char sAccessibilityKey [] =
"config.use_system_prefs.accessibility";
static const char sGconfAccessibilityKey[] =
"/desktop/gnome/interface/accessibility";
/* gail function pointer */
static guint (* gail_add_global_event_listener) (GSignalEmissionHook listener,
@ -625,11 +630,17 @@ nsApplicationAccessibleWrap::Init()
isGnomeATEnabled = !!atoi(envValue);
} else {
//check gconf-2 setting
nsresult rv;
nsCOMPtr<nsIPrefBranch> sysPrefService =
do_GetService(sSysPrefService, &rv);
if (NS_SUCCEEDED(rv) && sysPrefService) {
sysPrefService->GetBoolPref(sAccessibilityKey, &isGnomeATEnabled);
if (Preferences::GetBool(sUseSystemPrefsKey, false)) {
nsresult rv;
nsCOMPtr<nsIGConfService> gconf =
do_GetService(NS_GCONFSERVICE_CONTRACTID, &rv);
if (NS_SUCCEEDED(rv) && gconf) {
gconf->GetBool(NS_LITERAL_CSTRING(sGconfAccessibilityKey),
&isGnomeATEnabled);
}
} else {
isGnomeATEnabled =
Preferences::GetBool(sAccessibilityKey, false);
}
}

View File

@ -88,6 +88,17 @@
padding: 2px 4px;
}
/* Because of -moz-box-align: center above, separators will be invisible unless
we set their min-height. See bug 583510 for more information. */
toolbarseparator {
min-height: 22px;
}
/* We need more height when toolbar buttons show both icon and text. */
toolbar[mode="full"] toolbarseparator {
min-height: 36px;
}
#nav-bar {
padding-bottom: 4px !important;
}

View File

@ -2,12 +2,6 @@
/* Sidebars */
.sidebar-placesTree {
background-color: transparent !important;
-moz-appearance: none !important;
border: none !important;
}
#bookmarksPanel,
#history-panel,
#sidebar-search-container {

View File

@ -36,13 +36,14 @@ dnl the terms of any one of the MPL, the GPL or the LGPL.
dnl
dnl ***** END LICENSE BLOCK *****
dnl MOZ_CHECK_HEADER(HEADER-FILE, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]])
dnl MOZ_CHECK_HEADER(HEADER-FILE, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND [, INCLUDES]]])
AC_DEFUN([MOZ_CHECK_HEADER],
[ dnl Do the transliteration at runtime so arg 1 can be a shell variable.
ac_safe=`echo "$1" | sed 'y%./+-%__p_%'`
AC_MSG_CHECKING([for $1])
AC_CACHE_VAL(ac_cv_header_$ac_safe,
[ AC_TRY_COMPILE([#include <$1>], ,
[ AC_TRY_COMPILE([$4
#include <$1>], ,
eval "ac_cv_header_$ac_safe=yes",
eval "ac_cv_header_$ac_safe=no") ])
if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
@ -54,12 +55,12 @@ AC_DEFUN([MOZ_CHECK_HEADER],
fi
])
dnl MOZ_CHECK_HEADERS(HEADER-FILE... [, ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]])
dnl MOZ_CHECK_HEADERS(HEADER-FILE... [, ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND [, INCLUDES]]])
AC_DEFUN([MOZ_CHECK_HEADERS],
[ for ac_hdr in $1
do
MOZ_CHECK_HEADER($ac_hdr,
[ ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'`
AC_DEFINE_UNQUOTED($ac_tr_hdr) $2], $3)
AC_DEFINE_UNQUOTED($ac_tr_hdr) $2], $3, [$4])
done
])

View File

@ -5935,12 +5935,11 @@ if test "$MOZ_XTF"; then
fi
dnl ========================================================
dnl Pref extensions (autoconfig and system-pref)
dnl Pref extensions (autoconfig)
dnl ========================================================
MOZ_ARG_DISABLE_BOOL(pref-extensions,
[ --disable-pref-extensions
Disable pref extensions such as autoconfig and
system-pref],
Disable pref extensions such as autoconfig],
MOZ_PREF_EXTENSIONS=,
MOZ_PREF_EXTENSIONS=1 )
@ -8761,8 +8760,8 @@ if test "$USE_FC_FREETYPE"; then
if test "$COMPILE_ENVIRONMENT"; then
_SAVE_CPPFLAGS="$CPPFLAGS"
CPPFLAGS="$CPPFLAGS $FT2_CFLAGS $XCFLAGS"
AC_CHECK_HEADERS(fontconfig/fcfreetype.h, ,
[AC_MSG_ERROR(Can't find header fontconfig/fcfreetype.h.)])
MOZ_CHECK_HEADERS([fontconfig/fcfreetype.h], ,
[AC_MSG_ERROR(Can't find header fontconfig/fcfreetype.h.)], [#include <fontconfig/fontconfig.h>])
CPPFLAGS="$_SAVE_CPPFLAGS"
else
AC_DEFINE(HAVE_FONTCONFIG_FCFREETYPE_H)

View File

@ -1290,11 +1290,6 @@ public:
static void TraceWrapper(nsWrapperCache* aCache, TraceCallback aCallback,
void *aClosure);
/**
* Convert nsIContent::IME_STATUS_* to nsIWidget::IME_STATUS_*
*/
static PRUint32 GetWidgetStatusFromIMEStatus(PRUint32 aState);
/*
* Notify when the first XUL menu is opened and when the all XUL menus are
* closed. At opening, aInstalling should be TRUE, otherwise, it should be

View File

@ -63,8 +63,11 @@ class nsIDOMCSSStyleDeclaration;
namespace mozilla {
namespace css {
class StyleRule;
}
}
} // namespace css
namespace widget {
struct IMEState;
} // namespace widget
} // namespace mozilla
enum nsLinkState {
eLinkState_Unknown = 0,
@ -75,8 +78,8 @@ enum nsLinkState {
// IID for the nsIContent interface
#define NS_ICONTENT_IID \
{ 0x3128b3a0, 0xb609, 0x44e3, \
{ 0xad, 0x91, 0xdc, 0xf1, 0x4a, 0x3f, 0xf6, 0xa0 } }
{ 0xed40a3e5, 0xd7ed, 0x473e, \
{ 0x85, 0xe3, 0x82, 0xc3, 0xf0, 0x41, 0xdb, 0x52 } }
/**
* A node of content in a document's content model. This interface
@ -84,6 +87,8 @@ enum nsLinkState {
*/
class nsIContent : public nsINode {
public:
typedef mozilla::widget::IMEState IMEState;
#ifdef MOZILLA_INTERNAL_API
// If you're using the external API, the only thing you can know about
// nsIContent is that it exists with an IID
@ -604,40 +609,18 @@ public:
* Get desired IME state for the content.
*
* @return The desired IME status for the content.
* This is a combination of IME_STATUS_* flags,
* controlling what happens to IME when the content takes focus.
* If this is IME_STATUS_NONE, IME remains in its current state.
* IME_STATUS_ENABLE and IME_STATUS_DISABLE must not be set
* together; likewise IME_STATUS_OPEN and IME_STATUS_CLOSE must
* not be set together.
* If you return IME_STATUS_DISABLE, you should not set the
* OPEN or CLOSE flag; that way, when IME is next enabled,
* the previous OPEN/CLOSE state will be restored (unless the newly
* focused content specifies the OPEN/CLOSE state by setting the OPEN
* or CLOSE flag with the ENABLE flag).
* IME_STATUS_PASSWORD should be returned only from password editor,
* this value has a special meaning. It is used as alternative of
* IME_STATUS_DISABLED.
* IME_STATUS_PLUGIN should be returned only when plug-in has focus.
* When a plug-in is focused content, we should send native events
* directly. Because we don't process some native events, but they may
* be needed by the plug-in.
* This is a combination of an IME enabled value and
* an IME open value of widget::IMEState.
* If you return DISABLED, you should not set the OPEN and CLOSE
* value.
* PASSWORD should be returned only from password editor, this value
* has a special meaning. It is used as alternative of DISABLED.
* PLUGIN should be returned only when plug-in has focus. When a
* plug-in is focused content, we should send native events directly.
* Because we don't process some native events, but they may be needed
* by the plug-in.
*/
enum {
IME_STATUS_NONE = 0x0000,
IME_STATUS_ENABLE = 0x0001,
IME_STATUS_DISABLE = 0x0002,
IME_STATUS_PASSWORD = 0x0004,
IME_STATUS_PLUGIN = 0x0008,
IME_STATUS_OPEN = 0x0010,
IME_STATUS_CLOSE = 0x0020
};
enum {
IME_STATUS_MASK_ENABLED = IME_STATUS_ENABLE | IME_STATUS_DISABLE |
IME_STATUS_PASSWORD | IME_STATUS_PLUGIN,
IME_STATUS_MASK_OPENED = IME_STATUS_OPEN | IME_STATUS_CLOSE
};
virtual PRUint32 GetDesiredIMEState();
virtual IMEState GetDesiredIMEState();
/**
* Gets content node with the binding (or native code, possibly on the

View File

@ -212,6 +212,7 @@ static NS_DEFINE_CID(kXTFServiceCID, NS_XTFSERVICE_CID);
using namespace mozilla::dom;
using namespace mozilla::layers;
using namespace mozilla::widget;
using namespace mozilla;
const char kLoadAsData[] = "loadAsData";
@ -4026,25 +4027,6 @@ nsContentUtils::DropJSObjects(void* aScriptObjectHolder)
return rv;
}
/* static */
PRUint32
nsContentUtils::GetWidgetStatusFromIMEStatus(PRUint32 aState)
{
switch (aState & nsIContent::IME_STATUS_MASK_ENABLED) {
case nsIContent::IME_STATUS_DISABLE:
return nsIWidget::IME_STATUS_DISABLED;
case nsIContent::IME_STATUS_ENABLE:
return nsIWidget::IME_STATUS_ENABLED;
case nsIContent::IME_STATUS_PASSWORD:
return nsIWidget::IME_STATUS_PASSWORD;
case nsIContent::IME_STATUS_PLUGIN:
return nsIWidget::IME_STATUS_PLUGIN;
default:
NS_ERROR("The given state doesn't have valid enable state");
return nsIWidget::IME_STATUS_ENABLED;
}
}
/* static */
void
nsContentUtils::NotifyInstalledMenuKeyboardListener(bool aInstalling)

View File

@ -109,6 +109,7 @@
#include "nsIDOMEventListener.h"
#include "nsIWebNavigation.h"
#include "nsIBaseWindow.h"
#include "nsIWidget.h"
#include "jsapi.h"
@ -1363,11 +1364,11 @@ nsIContent::GetFlattenedTreeParent() const
return parent;
}
PRUint32
nsIContent::IMEState
nsIContent::GetDesiredIMEState()
{
if (!IsEditableInternal()) {
return IME_STATUS_DISABLE;
return IMEState(IMEState::DISABLED);
}
// NOTE: The content for independent editors (e.g., input[type=text],
// textarea) must override this method, so, we don't need to worry about
@ -1380,26 +1381,23 @@ nsIContent::GetDesiredIMEState()
}
nsIDocument* doc = GetCurrentDoc();
if (!doc) {
return IME_STATUS_DISABLE;
return IMEState(IMEState::DISABLED);
}
nsIPresShell* ps = doc->GetShell();
if (!ps) {
return IME_STATUS_DISABLE;
return IMEState(IMEState::DISABLED);
}
nsPresContext* pc = ps->GetPresContext();
if (!pc) {
return IME_STATUS_DISABLE;
return IMEState(IMEState::DISABLED);
}
nsIEditor* editor = GetHTMLEditor(pc);
nsCOMPtr<nsIEditorIMESupport> imeEditor = do_QueryInterface(editor);
if (!imeEditor) {
return IME_STATUS_DISABLE;
return IMEState(IMEState::DISABLED);
}
// Use "enable" for the default value because IME is disabled unexpectedly,
// it makes serious a11y problem.
PRUint32 state = IME_STATUS_ENABLE;
nsresult rv = imeEditor->GetPreferredIMEState(&state);
NS_ENSURE_SUCCESS(rv, IME_STATUS_ENABLE);
IMEState state;
imeEditor->GetPreferredIMEState(&state);
return state;
}

View File

@ -40,7 +40,6 @@
#include "nsIMEStateManager.h"
#include "nsCOMPtr.h"
#include "nsIWidget.h"
#include "nsIViewManager.h"
#include "nsIPresShell.h"
#include "nsISupports.h"
@ -51,6 +50,8 @@
#include "nsIDocument.h"
#include "nsPresContext.h"
#include "nsIDOMWindow.h"
#include "nsIDOMMouseEvent.h"
#include "nsIDOMNSEvent.h"
#include "nsContentUtils.h"
#include "nsINode.h"
#include "nsIFrame.h"
@ -68,6 +69,8 @@
#include "nsIForm.h"
#include "nsHTMLFormElement.h"
using namespace mozilla::widget;
/******************************************************************/
/* nsIMEStateManager */
/******************************************************************/
@ -87,8 +90,10 @@ nsIMEStateManager::OnDestroyPresContext(nsPresContext* aPresContext)
return NS_OK;
nsCOMPtr<nsIWidget> widget = GetWidget(sPresContext);
if (widget) {
PRUint32 newState = GetNewIMEState(sPresContext, nsnull);
SetIMEState(newState, nsnull, widget, IMEContext::FOCUS_REMOVED);
IMEState newState = GetNewIMEState(sPresContext, nsnull);
InputContextAction action(InputContextAction::CAUSE_UNKNOWN,
InputContextAction::LOST_FOCUS);
SetIMEState(newState, nsnull, widget, action);
}
sContent = nsnull;
sPresContext = nsnull;
@ -112,8 +117,10 @@ nsIMEStateManager::OnRemoveContent(nsPresContext* aPresContext,
nsresult rv = widget->CancelIMEComposition();
if (NS_FAILED(rv))
widget->ResetInputState();
PRUint32 newState = GetNewIMEState(sPresContext, nsnull);
SetIMEState(newState, nsnull, widget, IMEContext::FOCUS_REMOVED);
IMEState newState = GetNewIMEState(sPresContext, nsnull);
InputContextAction action(InputContextAction::CAUSE_UNKNOWN,
InputContextAction::LOST_FOCUS);
SetIMEState(newState, nsnull, widget, action);
}
sContent = nsnull;
@ -125,7 +132,16 @@ nsIMEStateManager::OnRemoveContent(nsPresContext* aPresContext,
nsresult
nsIMEStateManager::OnChangeFocus(nsPresContext* aPresContext,
nsIContent* aContent,
PRUint32 aReason)
InputContextAction::Cause aCause)
{
InputContextAction action(aCause);
return OnChangeFocusInternal(aPresContext, aContent, action);
}
nsresult
nsIMEStateManager::OnChangeFocusInternal(nsPresContext* aPresContext,
nsIContent* aContent,
InputContextAction aAction)
{
NS_ENSURE_ARG_POINTER(aPresContext);
@ -157,25 +173,22 @@ nsIMEStateManager::OnChangeFocus(nsPresContext* aPresContext,
}
}
PRUint32 newState = GetNewIMEState(aPresContext, aContent);
IMEState newState = GetNewIMEState(aPresContext, aContent);
if (aPresContext == sPresContext && aContent == sContent) {
// actual focus isn't changing, but if IME enabled state is changing,
// we should do it.
PRUint32 newEnabledState = newState & nsIContent::IME_STATUS_MASK_ENABLED;
if (newEnabledState == 0) {
// the enabled state isn't changing, we should do nothing.
return NS_OK;
}
IMEContext context;
if (!widget || NS_FAILED(widget->GetInputMode(context))) {
// this platform doesn't support IME controlling
return NS_OK;
}
if (context.mStatus ==
nsContentUtils::GetWidgetStatusFromIMEStatus(newEnabledState)) {
InputContext context = widget->GetInputContext();
if (context.mIMEState.mEnabled == newState.mEnabled) {
// the enabled state isn't changing.
return NS_OK;
}
aAction.mFocusChange = InputContextAction::FOCUS_NOT_CHANGED;
} else if (aAction.mFocusChange == InputContextAction::FOCUS_NOT_CHANGED) {
// If aContent isn't null or aContent is null but editable, somebody gets
// focus.
bool gotFocus = aContent || (newState.mEnabled == IMEState::ENABLED);
aAction.mFocusChange =
gotFocus ? InputContextAction::GOT_FOCUS : InputContextAction::LOST_FOCUS;
}
// Current IME transaction should commit
@ -189,10 +202,8 @@ nsIMEStateManager::OnChangeFocus(nsPresContext* aPresContext,
oldWidget->ResetInputState();
}
if (newState != nsIContent::IME_STATUS_NONE) {
// Update IME state for new focus widget
SetIMEState(newState, aContent, widget, aReason);
}
// Update IME state for new focus widget
SetIMEState(newState, aContent, widget, aAction);
sPresContext = aPresContext;
sContent = aContent;
@ -205,19 +216,60 @@ nsIMEStateManager::OnInstalledMenuKeyboardListener(bool aInstalling)
{
sInstalledMenuKeyboardListener = aInstalling;
PRUint32 reason = aInstalling ? IMEContext::FOCUS_MOVED_TO_MENU
: IMEContext::FOCUS_MOVED_FROM_MENU;
OnChangeFocus(sPresContext, sContent, reason);
InputContextAction action(InputContextAction::CAUSE_UNKNOWN,
aInstalling ? InputContextAction::MENU_GOT_PSEUDO_FOCUS :
InputContextAction::MENU_LOST_PSEUDO_FOCUS);
OnChangeFocusInternal(sPresContext, sContent, action);
}
void
nsIMEStateManager::UpdateIMEState(PRUint32 aNewIMEState, nsIContent* aContent)
nsIMEStateManager::OnClickInEditor(nsPresContext* aPresContext,
nsIContent* aContent,
nsIDOMMouseEvent* aMouseEvent)
{
if (sPresContext != aPresContext || sContent != aContent) {
return;
}
nsCOMPtr<nsIWidget> widget = GetWidget(aPresContext);
NS_ENSURE_TRUE(widget, );
bool isTrusted;
nsCOMPtr<nsIDOMNSEvent> NSEvent = do_QueryInterface(aMouseEvent);
nsresult rv = NSEvent->GetIsTrusted(&isTrusted);
NS_ENSURE_SUCCESS(rv, );
if (!isTrusted) {
return; // ignore untrusted event.
}
PRUint16 button;
rv = aMouseEvent->GetButton(&button);
NS_ENSURE_SUCCESS(rv, );
if (button != 0) {
return; // not a left click event.
}
PRInt32 clickCount;
rv = aMouseEvent->GetDetail(&clickCount);
NS_ENSURE_SUCCESS(rv, );
if (clickCount != 1) {
return; // should notify only first click event.
}
InputContextAction action(InputContextAction::CAUSE_MOUSE,
InputContextAction::FOCUS_NOT_CHANGED);
IMEState newState = GetNewIMEState(aPresContext, aContent);
SetIMEState(newState, aContent, widget, action);
}
void
nsIMEStateManager::UpdateIMEState(const IMEState &aNewIMEState,
nsIContent* aContent)
{
if (!sPresContext) {
NS_WARNING("ISM doesn't know which editor has focus");
return;
}
NS_PRECONDITION(aNewIMEState != 0, "aNewIMEState doesn't specify new state.");
nsCOMPtr<nsIWidget> widget = GetWidget(sPresContext);
if (!widget) {
NS_WARNING("focused widget is not found");
@ -225,43 +277,41 @@ nsIMEStateManager::UpdateIMEState(PRUint32 aNewIMEState, nsIContent* aContent)
}
// Don't update IME state when enabled state isn't actually changed.
IMEContext context;
nsresult rv = widget->GetInputMode(context);
if (NS_FAILED(rv)) {
return; // This platform doesn't support controling the IME state.
}
PRUint32 newEnabledState = aNewIMEState & nsIContent::IME_STATUS_MASK_ENABLED;
if (context.mStatus ==
nsContentUtils::GetWidgetStatusFromIMEStatus(newEnabledState)) {
InputContext context = widget->GetInputContext();
if (context.mIMEState.mEnabled == aNewIMEState.mEnabled) {
return;
}
// commit current composition
widget->ResetInputState();
SetIMEState(aNewIMEState, aContent, widget, IMEContext::EDITOR_STATE_MODIFIED);
InputContextAction action(InputContextAction::CAUSE_UNKNOWN,
InputContextAction::FOCUS_NOT_CHANGED);
SetIMEState(aNewIMEState, aContent, widget, action);
}
PRUint32
IMEState
nsIMEStateManager::GetNewIMEState(nsPresContext* aPresContext,
nsIContent* aContent)
{
// On Printing or Print Preview, we don't need IME.
if (aPresContext->Type() == nsPresContext::eContext_PrintPreview ||
aPresContext->Type() == nsPresContext::eContext_Print) {
return nsIContent::IME_STATUS_DISABLE;
return IMEState(IMEState::DISABLED);
}
if (sInstalledMenuKeyboardListener)
return nsIContent::IME_STATUS_DISABLE;
if (sInstalledMenuKeyboardListener) {
return IMEState(IMEState::DISABLED);
}
if (!aContent) {
// Even if there are no focused content, the focused document might be
// editable, such case is design mode.
nsIDocument* doc = aPresContext->Document();
if (doc && doc->HasFlag(NODE_IS_EDITABLE))
return nsIContent::IME_STATUS_ENABLE;
return nsIContent::IME_STATUS_DISABLE;
if (doc && doc->HasFlag(NODE_IS_EDITABLE)) {
return IMEState(IMEState::ENABLED);
}
return IMEState(IMEState::DISABLED);
}
return aContent->GetDesiredIMEState();
@ -290,65 +340,62 @@ private:
};
void
nsIMEStateManager::SetIMEState(PRUint32 aState,
nsIMEStateManager::SetIMEState(const IMEState &aState,
nsIContent* aContent,
nsIWidget* aWidget,
PRUint32 aReason)
InputContextAction aAction)
{
if (aState & nsIContent::IME_STATUS_MASK_ENABLED) {
if (!aWidget)
return;
NS_ENSURE_TRUE(aWidget, );
PRUint32 state = nsContentUtils::GetWidgetStatusFromIMEStatus(aState);
IMEContext context;
context.mStatus = state;
if (aContent && aContent->GetNameSpaceID() == kNameSpaceID_XHTML &&
(aContent->Tag() == nsGkAtoms::input ||
aContent->Tag() == nsGkAtoms::textarea)) {
aContent->GetAttr(kNameSpaceID_None, nsGkAtoms::type,
context.mHTMLInputType);
aContent->GetAttr(kNameSpaceID_None, nsGkAtoms::moz_action_hint,
context.mActionHint);
InputContext oldContext = aWidget->GetInputContext();
// if we don't have an action hint and return won't submit the form use "next"
if (context.mActionHint.IsEmpty() && aContent->Tag() == nsGkAtoms::input) {
bool willSubmit = false;
nsCOMPtr<nsIFormControl> control(do_QueryInterface(aContent));
mozilla::dom::Element* formElement = control->GetFormElement();
nsCOMPtr<nsIForm> form;
if (control) {
// is this a form and does it have a default submit element?
if ((form = do_QueryInterface(formElement)) && form->GetDefaultSubmitElement()) {
willSubmit = true;
// is this an html form and does it only have a single text input element?
} else if (formElement && formElement->Tag() == nsGkAtoms::form && formElement->IsHTML() &&
static_cast<nsHTMLFormElement*>(formElement)->HasSingleTextControl()) {
willSubmit = true;
}
InputContext context;
context.mIMEState = aState;
if (aContent && aContent->GetNameSpaceID() == kNameSpaceID_XHTML &&
(aContent->Tag() == nsGkAtoms::input ||
aContent->Tag() == nsGkAtoms::textarea)) {
aContent->GetAttr(kNameSpaceID_None, nsGkAtoms::type,
context.mHTMLInputType);
aContent->GetAttr(kNameSpaceID_None, nsGkAtoms::moz_action_hint,
context.mActionHint);
// if we don't have an action hint and return won't submit the form use "next"
if (context.mActionHint.IsEmpty() && aContent->Tag() == nsGkAtoms::input) {
bool willSubmit = false;
nsCOMPtr<nsIFormControl> control(do_QueryInterface(aContent));
mozilla::dom::Element* formElement = control->GetFormElement();
nsCOMPtr<nsIForm> form;
if (control) {
// is this a form and does it have a default submit element?
if ((form = do_QueryInterface(formElement)) && form->GetDefaultSubmitElement()) {
willSubmit = true;
// is this an html form and does it only have a single text input element?
} else if (formElement && formElement->Tag() == nsGkAtoms::form && formElement->IsHTML() &&
static_cast<nsHTMLFormElement*>(formElement)->HasSingleTextControl()) {
willSubmit = true;
}
context.mActionHint.Assign(willSubmit ? control->GetType() == NS_FORM_INPUT_SEARCH
? NS_LITERAL_STRING("search")
: NS_LITERAL_STRING("go")
: formElement
? NS_LITERAL_STRING("next")
: EmptyString());
}
context.mActionHint.Assign(willSubmit ? control->GetType() == NS_FORM_INPUT_SEARCH
? NS_LITERAL_STRING("search")
: NS_LITERAL_STRING("go")
: formElement
? NS_LITERAL_STRING("next")
: EmptyString());
}
if (XRE_GetProcessType() == GeckoProcessType_Content) {
context.mReason = aReason | IMEContext::FOCUS_FROM_CONTENT_PROCESS;
} else {
context.mReason = aReason;
}
aWidget->SetInputMode(context);
nsContentUtils::AddScriptRunner(new IMEEnabledStateChangedEvent(state));
}
if (aState & nsIContent::IME_STATUS_MASK_OPENED) {
bool open = !!(aState & nsIContent::IME_STATUS_OPEN);
aWidget->SetIMEOpenState(open);
// XXX I think that we should use nsContentUtils::IsCallerChrome() instead
// of the process type.
if (aAction.mCause == InputContextAction::CAUSE_UNKNOWN &&
XRE_GetProcessType() != GeckoProcessType_Content) {
aAction.mCause = InputContextAction::CAUSE_UNKNOWN_CHROME;
}
aWidget->SetInputContext(context, aAction);
if (oldContext.mIMEState.mEnabled != context.mIMEState.mEnabled) {
nsContentUtils::AddScriptRunner(
new IMEEnabledStateChangedEvent(context.mIMEState.mEnabled));
}
}

View File

@ -40,11 +40,12 @@
#define nsIMEStateManager_h__
#include "nscore.h"
#include "nsIWidget.h"
class nsIContent;
class nsIDOMMouseEvent;
class nsPIDOMWindow;
class nsPresContext;
class nsIWidget;
class nsTextStateManager;
class nsISelection;
@ -54,13 +55,23 @@ class nsISelection;
class nsIMEStateManager
{
protected:
typedef mozilla::widget::IMEState IMEState;
typedef mozilla::widget::InputContext InputContext;
typedef mozilla::widget::InputContextAction InputContextAction;
public:
static nsresult OnDestroyPresContext(nsPresContext* aPresContext);
static nsresult OnRemoveContent(nsPresContext* aPresContext,
nsIContent* aContent);
/**
* OnChangeFocus() should be called when focused content is changed or
* IME enabled state is changed. If focus isn't actually changed and IME
* enabled state isn't changed, this will do nothing.
*/
static nsresult OnChangeFocus(nsPresContext* aPresContext,
nsIContent* aContent,
PRUint32 aReason);
InputContextAction::Cause aCause);
static void OnInstalledMenuKeyboardListener(bool aInstalling);
// These two methods manage focus and selection/text observers.
@ -85,14 +96,27 @@ public:
// isn't changed by the new state, this method does nothing.
// Note that this method changes the IME state of the active element in the
// widget. So, the caller must have focus.
// aNewIMEState must have an enabled state of nsIContent::IME_STATUS_*.
// And optionally, it can have an open state of nsIContent::IME_STATUS_*.
static void UpdateIMEState(PRUint32 aNewIMEState, nsIContent* aContent);
static void UpdateIMEState(const IMEState &aNewIMEState,
nsIContent* aContent);
// This method is called when user clicked in an editor.
// aContent must be:
// If the editor is for <input> or <textarea>, the element.
// If the editor is for contenteditable, the active editinghost.
// If the editor is for designMode, NULL.
static void OnClickInEditor(nsPresContext* aPresContext,
nsIContent* aContent,
nsIDOMMouseEvent* aMouseEvent);
protected:
static void SetIMEState(PRUint32 aState, nsIContent* aContent,
nsIWidget* aWidget, PRUint32 aReason);
static PRUint32 GetNewIMEState(nsPresContext* aPresContext,
static nsresult OnChangeFocusInternal(nsPresContext* aPresContext,
nsIContent* aContent,
InputContextAction aAction);
static void SetIMEState(const IMEState &aState,
nsIContent* aContent,
nsIWidget* aWidget,
InputContextAction aAction);
static IMEState GetNewIMEState(nsPresContext* aPresContext,
nsIContent* aContent);
static nsIWidget* GetWidget(nsPresContext* aPresContext);

View File

@ -71,6 +71,7 @@
#include "nsIScrollableFrame.h"
#include "nsIView.h"
#include "nsIViewManager.h"
#include "nsIWidget.h"
#include "nsRange.h"
#include "nsIPresShell.h"
#include "nsPresContext.h"
@ -2652,7 +2653,7 @@ nsGenericHTMLFormElement::GetForm(nsIDOMHTMLFormElement** aForm)
return NS_OK;
}
PRUint32
nsIContent::IMEState
nsGenericHTMLFormElement::GetDesiredIMEState()
{
nsCOMPtr<nsIEditor> editor = nsnull;
@ -2662,7 +2663,7 @@ nsGenericHTMLFormElement::GetDesiredIMEState()
nsCOMPtr<nsIEditorIMESupport> imeEditor = do_QueryInterface(editor);
if (!imeEditor)
return nsGenericHTMLElement::GetDesiredIMEState();
PRUint32 state;
IMEState state;
rv = imeEditor->GetPreferredIMEState(&state);
if (NS_FAILED(rv))
return nsGenericHTMLElement::GetDesiredIMEState();

View File

@ -884,7 +884,7 @@ public:
bool aCompileEventHandlers);
virtual void UnbindFromTree(bool aDeep = true,
bool aNullParent = true);
virtual PRUint32 GetDesiredIMEState();
virtual IMEState GetDesiredIMEState();
virtual nsEventStates IntrinsicState() const;
virtual nsresult PreHandleEvent(nsEventChainPreVisitor& aVisitor);

View File

@ -52,6 +52,7 @@
#include "nsIObjectFrame.h"
#include "nsNPAPIPluginInstance.h"
#include "nsIConstraintValidation.h"
#include "nsIWidget.h"
using namespace mozilla;
using namespace mozilla::dom;
@ -116,7 +117,7 @@ public:
bool aNotify);
virtual bool IsHTMLFocusable(bool aWithMouse, bool *aIsFocusable, PRInt32 *aTabIndex);
virtual PRUint32 GetDesiredIMEState();
virtual IMEState GetDesiredIMEState();
// Overriden nsIFormControl methods
NS_IMETHOD_(PRUint32) GetType() const
@ -376,11 +377,11 @@ nsHTMLObjectElement::IsHTMLFocusable(bool aWithMouse,
return false;
}
PRUint32
nsIContent::IMEState
nsHTMLObjectElement::GetDesiredIMEState()
{
if (Type() == eType_Plugin) {
return nsIContent::IME_STATUS_PLUGIN;
return IMEState(IMEState::PLUGIN);
}
return nsGenericHTMLFormElement::GetDesiredIMEState();

View File

@ -50,6 +50,7 @@
#include "nsIDOMGetSVGDocument.h"
#include "nsIDOMSVGDocument.h"
#include "nsIScriptError.h"
#include "nsIWidget.h"
using namespace mozilla;
using namespace mozilla::dom;
@ -119,7 +120,7 @@ public:
bool aNotify);
virtual bool IsHTMLFocusable(bool aWithMouse, bool *aIsFocusable, PRInt32 *aTabIndex);
virtual PRUint32 GetDesiredIMEState();
virtual IMEState GetDesiredIMEState();
virtual void DoneAddingChildren(bool aHaveNotified);
virtual bool IsDoneAddingChildren();
@ -365,11 +366,11 @@ nsHTMLSharedObjectElement::IsHTMLFocusable(bool aWithMouse,
return nsGenericHTMLElement::IsHTMLFocusable(aWithMouse, aIsFocusable, aTabIndex);
}
PRUint32
nsIContent::IMEState
nsHTMLSharedObjectElement::GetDesiredIMEState()
{
if (Type() == eType_Plugin) {
return nsIContent::IME_STATUS_PLUGIN;
return IMEState(IMEState::PLUGIN);
}
return nsGenericHTMLElement::GetDesiredIMEState();

View File

@ -334,6 +334,11 @@ nsSMILTimeValueSpec::RegisterEventListener(Element* aTarget)
if (!aTarget)
return;
// Don't listen for accessKey events if script is disabled. (see bug 704482)
if (mParams.mType == nsSMILTimeValueSpecParams::ACCESSKEY &&
!aTarget->GetOwnerDocument()->IsScriptEnabled())
return;
if (!mEventListener) {
mEventListener = new EventListener(this);
}

View File

@ -86,6 +86,7 @@
using namespace mozilla::dom;
using namespace mozilla::layers;
using namespace mozilla::widget;
static bool IsUniversalXPConnectCapable()
{
@ -1039,13 +1040,16 @@ nsDOMWindowUtils::GetIMEIsOpen(bool *aState)
return NS_ERROR_FAILURE;
// Open state should not be available when IME is not enabled.
IMEContext context;
nsresult rv = widget->GetInputMode(context);
NS_ENSURE_SUCCESS(rv, rv);
if (context.mStatus != nsIWidget::IME_STATUS_ENABLED)
InputContext context = widget->GetInputContext();
if (context.mIMEState.mEnabled != IMEState::ENABLED) {
return NS_ERROR_NOT_AVAILABLE;
}
return widget->GetIMEOpenState(aState);
if (context.mIMEState.mOpen == IMEState::OPEN_STATE_NOT_SUPPORTED) {
return NS_ERROR_NOT_IMPLEMENTED;
}
*aState = (context.mIMEState.mOpen == IMEState::OPEN);
return NS_OK;
}
NS_IMETHODIMP
@ -1057,11 +1061,8 @@ nsDOMWindowUtils::GetIMEStatus(PRUint32 *aState)
if (!widget)
return NS_ERROR_FAILURE;
IMEContext context;
nsresult rv = widget->GetInputMode(context);
NS_ENSURE_SUCCESS(rv, rv);
*aState = context.mStatus;
InputContext context = widget->GetInputContext();
*aState = static_cast<PRUint32>(context.mIMEState.mEnabled);
return NS_OK;
}
@ -1075,10 +1076,7 @@ nsDOMWindowUtils::GetFocusedInputType(char** aType)
return NS_ERROR_FAILURE;
}
IMEContext context;
nsresult rv = widget->GetInputMode(context);
NS_ENSURE_SUCCESS(rv, rv);
InputContext context = widget->GetInputContext();
*aType = ToNewCString(context.mHTMLInputType);
return NS_OK;
}

View File

@ -72,7 +72,6 @@
#include "nsIMEStateManager.h"
#include "nsIWebNavigation.h"
#include "nsCaret.h"
#include "nsIWidget.h"
#include "nsIBaseWindow.h"
#include "nsIViewManager.h"
#include "nsFrameSelection.h"
@ -96,6 +95,7 @@
using namespace mozilla;
using namespace mozilla::dom;
using namespace mozilla::widget;
//#define DEBUG_FOCUS 1
//#define DEBUG_FOCUS_NAVIGATION 1
@ -337,19 +337,15 @@ nsFocusManager::GetRedirectedFocus(nsIContent* aContent)
}
// static
PRUint32
nsFocusManager::GetFocusMoveReason(PRUint32 aFlags)
InputContextAction::Cause
nsFocusManager::GetFocusMoveActionCause(PRUint32 aFlags)
{
PRUint32 reason = IMEContext::FOCUS_MOVED_UNKNOWN;
if (aFlags & nsIFocusManager::FLAG_BYMOUSE) {
reason = IMEContext::FOCUS_MOVED_BY_MOUSE;
return InputContextAction::CAUSE_MOUSE;
} else if (aFlags & nsIFocusManager::FLAG_BYKEY) {
reason = IMEContext::FOCUS_MOVED_BY_KEY;
} else if (aFlags & nsIFocusManager::FLAG_BYMOVEFOCUS) {
reason = IMEContext::FOCUS_MOVED_BY_MOVEFOCUS;
return InputContextAction::CAUSE_KEY;
}
return reason;
return InputContextAction::CAUSE_UNKNOWN;
}
NS_IMETHODIMP
@ -964,7 +960,8 @@ nsFocusManager::WindowHidden(nsIDOMWindow* aWindow)
nsIMEStateManager::OnTextStateBlur(nsnull, nsnull);
if (presShell) {
nsIMEStateManager::OnChangeFocus(presShell->GetPresContext(), nsnull, IMEContext::FOCUS_REMOVED);
nsIMEStateManager::OnChangeFocus(presShell->GetPresContext(), nsnull,
GetFocusMoveActionCause(0));
SetCaretVisible(presShell, false, nsnull);
}
@ -1523,8 +1520,10 @@ nsFocusManager::Blur(nsPIDOMWindow* aWindowToClear,
// This has to happen before the focus is cleared below, otherwise, the IME
// compositionend event won't get fired at the element being blurred.
nsIMEStateManager::OnTextStateBlur(nsnull, nsnull);
if (mActiveWindow)
nsIMEStateManager::OnChangeFocus(presShell->GetPresContext(), nsnull, IMEContext::FOCUS_REMOVED);
if (mActiveWindow) {
nsIMEStateManager::OnChangeFocus(presShell->GetPresContext(), nsnull,
GetFocusMoveActionCause(0));
}
// now adjust the actual focus, by clearing the fields in the focus manager
// and in the window.
@ -1786,8 +1785,8 @@ nsFocusManager::Focus(nsPIDOMWindow* aWindow,
}
}
PRUint32 reason = GetFocusMoveReason(aFlags);
nsIMEStateManager::OnChangeFocus(presContext, aContent, reason);
nsIMEStateManager::OnChangeFocus(presContext, aContent,
GetFocusMoveActionCause(aFlags));
// as long as this focus wasn't because a window was raised, update the
// commands
@ -1803,7 +1802,8 @@ nsFocusManager::Focus(nsPIDOMWindow* aWindow,
nsIMEStateManager::OnTextStateFocus(presContext, aContent);
} else {
nsIMEStateManager::OnTextStateBlur(presContext, nsnull);
nsIMEStateManager::OnChangeFocus(presContext, nsnull, IMEContext::FOCUS_REMOVED);
nsIMEStateManager::OnChangeFocus(presContext, nsnull,
GetFocusMoveActionCause(aFlags));
if (!aWindowRaised) {
aWindow->UpdateCommands(NS_LITERAL_STRING("focus"));
}
@ -1826,7 +1826,8 @@ nsFocusManager::Focus(nsPIDOMWindow* aWindow,
nsPresContext* presContext = presShell->GetPresContext();
nsIMEStateManager::OnTextStateBlur(presContext, nsnull);
nsIMEStateManager::OnChangeFocus(presContext, nsnull, IMEContext::FOCUS_REMOVED);
nsIMEStateManager::OnChangeFocus(presContext, nsnull,
GetFocusMoveActionCause(aFlags));
if (!aWindowRaised)
aWindow->UpdateCommands(NS_LITERAL_STRING("focus"));

View File

@ -41,6 +41,7 @@
#include "nsWeakReference.h"
#include "nsIObserver.h"
#include "nsIContent.h"
#include "nsIWidget.h"
#define FOCUSMETHOD_MASK 0xF000
#define FOCUSMETHODANDRING_MASK 0xF0F000
@ -67,6 +68,8 @@ class nsFocusManager : public nsIFocusManager,
public nsIObserver,
public nsSupportsWeakReference
{
typedef mozilla::widget::InputContextAction InputContextAction;
public:
NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsFocusManager, nsIFocusManager)
@ -131,11 +134,9 @@ public:
static nsIContent* GetRedirectedFocus(nsIContent* aContent);
/**
* Returns a flag indicating the source and/or reason of the focus change.
* This is used to indicate to the IME code if the focus come from a user
* input or a script for example.
* Returns an InputContextAction cause for aFlags.
*/
static PRUint32 GetFocusMoveReason(PRUint32 aFlags);
static InputContextAction::Cause GetFocusMoveActionCause(PRUint32 aFlags);
static bool sMouseFocusesFormControl;

View File

@ -172,13 +172,14 @@ parent:
*/
sync EndIMEComposition(bool cancel) returns (nsString composition);
sync GetIMEEnabled() returns (PRUint32 value);
sync GetInputContext() returns (PRInt32 IMEEnabled, PRInt32 IMEOpen);
SetInputMode(PRUint32 value, nsString type, nsString actionHint, PRUint32 reason);
sync GetIMEOpenState() returns (bool value);
SetIMEOpenState(bool value);
SetInputContext(PRInt32 IMEEnabled,
PRInt32 IMEOpen,
nsString type,
nsString actionHint,
PRInt32 cause,
PRInt32 focusChange);
/**
* Gets the DPI of the screen corresponding to this browser.

View File

@ -74,6 +74,7 @@
using namespace mozilla::dom;
using namespace mozilla::ipc;
using namespace mozilla::layout;
using namespace mozilla::widget;
// The flags passed by the webProgress notifications are 16 bits shifted
// from the ones registered by webProgressListeners.
@ -563,66 +564,60 @@ TabParent::RecvEndIMEComposition(const bool& aCancel,
}
bool
TabParent::RecvGetIMEEnabled(PRUint32* aValue)
TabParent::RecvGetInputContext(PRInt32* aIMEEnabled,
PRInt32* aIMEOpen)
{
nsCOMPtr<nsIWidget> widget = GetWidget();
if (!widget) {
*aValue = nsIWidget::IME_STATUS_DISABLED;
*aIMEEnabled = IMEState::DISABLED;
*aIMEOpen = IMEState::OPEN_STATE_NOT_SUPPORTED;
return true;
}
IMEContext context;
widget->GetInputMode(context);
*aValue = context.mStatus;
InputContext context = widget->GetInputContext();
*aIMEEnabled = static_cast<PRInt32>(context.mIMEState.mEnabled);
*aIMEOpen = static_cast<PRInt32>(context.mIMEState.mOpen);
return true;
}
bool
TabParent::RecvSetInputMode(const PRUint32& aValue, const nsString& aType, const nsString& aAction, const PRUint32& aReason)
TabParent::RecvSetInputContext(const PRInt32& aIMEEnabled,
const PRInt32& aIMEOpen,
const nsString& aType,
const nsString& aActionHint,
const PRInt32& aCause,
const PRInt32& aFocusChange)
{
// mIMETabParent (which is actually static) tracks which if any TabParent has IMEFocus
// When the input mode is set to anything but IME_STATUS_NONE, mIMETabParent should be set to this
mIMETabParent = aValue & nsIContent::IME_STATUS_MASK_ENABLED ? this : nsnull;
// When the input mode is set to anything but IMEState::DISABLED,
// mIMETabParent should be set to this
mIMETabParent =
aIMEEnabled != static_cast<PRInt32>(IMEState::DISABLED) ? this : nsnull;
nsCOMPtr<nsIWidget> widget = GetWidget();
if (!widget || !AllowContentIME())
return true;
IMEContext context;
context.mStatus = aValue;
InputContext context;
context.mIMEState.mEnabled = static_cast<IMEState::Enabled>(aIMEEnabled);
context.mIMEState.mOpen = static_cast<IMEState::Open>(aIMEOpen);
context.mHTMLInputType.Assign(aType);
context.mActionHint.Assign(aAction);
context.mReason = aReason;
widget->SetInputMode(context);
context.mActionHint.Assign(aActionHint);
InputContextAction action(
static_cast<InputContextAction::Cause>(aCause),
static_cast<InputContextAction::FocusChange>(aFocusChange));
widget->SetInputContext(context, action);
nsCOMPtr<nsIObserverService> observerService = mozilla::services::GetObserverService();
if (!observerService)
return true;
nsAutoString state;
state.AppendInt(aValue);
state.AppendInt(aIMEEnabled);
observerService->NotifyObservers(nsnull, "ime-enabled-state-changed", state.get());
return true;
}
bool
TabParent::RecvGetIMEOpenState(bool* aValue)
{
nsCOMPtr<nsIWidget> widget = GetWidget();
if (widget)
widget->GetIMEOpenState(aValue);
return true;
}
bool
TabParent::RecvSetIMEOpenState(const bool& aValue)
{
nsCOMPtr<nsIWidget> widget = GetWidget();
if (widget && AllowContentIME())
widget->SetIMEOpenState(aValue);
return true;
}
bool
TabParent::RecvGetDPI(float* aValue)
{

View File

@ -103,10 +103,14 @@ public:
virtual bool RecvNotifyIMETextHint(const nsString& aText);
virtual bool RecvEndIMEComposition(const bool& aCancel,
nsString* aComposition);
virtual bool RecvGetIMEEnabled(PRUint32* aValue);
virtual bool RecvSetInputMode(const PRUint32& aValue, const nsString& aType, const nsString& aAction, const PRUint32& aReason);
virtual bool RecvGetIMEOpenState(bool* aValue);
virtual bool RecvSetIMEOpenState(const bool& aValue);
virtual bool RecvGetInputContext(PRInt32* aIMEEnabled,
PRInt32* aIMEOpen);
virtual bool RecvSetInputContext(const PRInt32& aIMEEnabled,
const PRInt32& aIMEOpen,
const nsString& aType,
const nsString& aActionHint,
const PRInt32& aCause,
const PRInt32& aFocusChange);
virtual bool RecvSetCursor(const PRUint32& aValue);
virtual bool RecvSetBackgroundColor(const nscolor& aValue);
virtual bool RecvGetDPI(float* aValue);

View File

@ -39,7 +39,17 @@
#include "nsISupports.idl"
#include "domstubs.idl"
[scriptable, uuid(a64744c5-d3ff-46ba-b9b1-57f79ff7d97d)]
%{C++
namespace mozilla {
namespace widget {
struct IMEState;
} // namespace widget
} // namespace mozilla
%}
native IMEState(mozilla::widget::IMEState);
[scriptable, uuid(0ba7f490-afb8-46dd-87fc-bc6137fbc899)]
interface nsIEditorIMESupport : nsISupports
{
@ -53,7 +63,7 @@ interface nsIEditorIMESupport : nsISupports
* Get preferred IME status of current widget.
*/
[noscript] void getPreferredIMEState(out unsigned long aState);
[noscript] IMEState getPreferredIMEState();
/**
* whether this editor has active IME transaction

View File

@ -133,6 +133,7 @@ static bool gNoisy = false;
#endif
using namespace mozilla;
using namespace mozilla::widget;
// Defined in nsEditorRegistration.cpp
extern nsIParserService *sParserService;
@ -492,9 +493,7 @@ nsEditor::SetFlags(PRUint32 aFlags)
// if we're focused and the flag change causes IME state change.
nsCOMPtr<nsIContent> focusedContent = GetFocusedContent();
if (focusedContent) {
// Use "enable" for the default value because if IME is disabled
// unexpectedly, it makes serious a11y problem.
PRUint32 newState = nsIContent::IME_STATUS_ENABLE;
IMEState newState;
nsresult rv = GetPreferredIMEState(&newState);
if (NS_SUCCEEDED(rv)) {
// NOTE: When the enabled state isn't going to be modified, this method
@ -2050,13 +2049,14 @@ nsEditor::ForceCompositionEnd()
}
NS_IMETHODIMP
nsEditor::GetPreferredIMEState(PRUint32 *aState)
nsEditor::GetPreferredIMEState(IMEState *aState)
{
NS_ENSURE_ARG_POINTER(aState);
*aState = nsIContent::IME_STATUS_ENABLE;
aState->mEnabled = IMEState::ENABLED;
aState->mOpen = IMEState::DONT_CHANGE_OPEN_STATE;
if (IsReadonly() || IsDisabled()) {
*aState = nsIContent::IME_STATUS_DISABLE;
aState->mEnabled = IMEState::DISABLED;
return NS_OK;
}
@ -2069,17 +2069,17 @@ nsEditor::GetPreferredIMEState(PRUint32 *aState)
switch (frame->GetStyleUIReset()->mIMEMode) {
case NS_STYLE_IME_MODE_AUTO:
if (IsPasswordEditor())
*aState = nsIContent::IME_STATUS_PASSWORD;
aState->mEnabled = IMEState::PASSWORD;
break;
case NS_STYLE_IME_MODE_DISABLED:
// we should use password state for |ime-mode: disabled;|.
*aState = nsIContent::IME_STATUS_PASSWORD;
aState->mEnabled = IMEState::PASSWORD;
break;
case NS_STYLE_IME_MODE_ACTIVE:
*aState |= nsIContent::IME_STATUS_OPEN;
aState->mOpen = IMEState::OPEN;
break;
case NS_STYLE_IME_MODE_INACTIVE:
*aState |= nsIContent::IME_STATUS_CLOSE;
aState->mOpen = IMEState::CLOSED;
break;
}

View File

@ -90,6 +90,12 @@ class nsCSSStyleSheet;
class nsKeyEvent;
class nsIDOMNSEvent;
namespace mozilla {
namespace widget {
struct IMEState;
} // namespace widget
} // namespace mozilla
#define kMOZEditorBogusNodeAttrAtom nsEditProperty::mozEditorBogusNode
#define kMOZEditorBogusNodeValue NS_LITERAL_STRING("TRUE")

View File

@ -55,6 +55,7 @@
#include "nsIEditorMailSupport.h"
#include "nsFocusManager.h"
#include "nsEventListenerManager.h"
#include "nsIMEStateManager.h"
#include "mozilla/Preferences.h"
// Drag & Drop, Clipboard
@ -203,13 +204,16 @@ nsEditorEventListener::InstallToEditor()
NS_EVENT_FLAG_CAPTURE);
elmP->AddEventListenerByType(this,
NS_LITERAL_STRING("text"),
NS_EVENT_FLAG_BUBBLE);
NS_EVENT_FLAG_BUBBLE |
NS_EVENT_FLAG_SYSTEM_EVENT);
elmP->AddEventListenerByType(this,
NS_LITERAL_STRING("compositionstart"),
NS_EVENT_FLAG_BUBBLE);
NS_EVENT_FLAG_BUBBLE |
NS_EVENT_FLAG_SYSTEM_EVENT);
elmP->AddEventListenerByType(this,
NS_LITERAL_STRING("compositionend"),
NS_EVENT_FLAG_BUBBLE);
NS_EVENT_FLAG_BUBBLE |
NS_EVENT_FLAG_SYSTEM_EVENT);
return NS_OK;
}
@ -289,13 +293,16 @@ nsEditorEventListener::UninstallFromEditor()
NS_EVENT_FLAG_CAPTURE);
elmP->RemoveEventListenerByType(this,
NS_LITERAL_STRING("text"),
NS_EVENT_FLAG_BUBBLE);
NS_EVENT_FLAG_BUBBLE |
NS_EVENT_FLAG_SYSTEM_EVENT);
elmP->RemoveEventListenerByType(this,
NS_LITERAL_STRING("compositionstart"),
NS_EVENT_FLAG_BUBBLE);
NS_EVENT_FLAG_BUBBLE |
NS_EVENT_FLAG_SYSTEM_EVENT);
elmP->RemoveEventListenerByType(this,
NS_LITERAL_STRING("compositionend"),
NS_EVENT_FLAG_BUBBLE);
NS_EVENT_FLAG_BUBBLE |
NS_EVENT_FLAG_SYSTEM_EVENT);
}
already_AddRefed<nsIPresShell>
@ -527,6 +534,21 @@ nsEditorEventListener::MouseClick(nsIDOMEvent* aMouseEvent)
return NS_OK;
}
// Notifies clicking on editor to IMEStateManager even when the event was
// consumed.
nsCOMPtr<nsIContent> focusedContent = mEditor->GetFocusedContent();
if (focusedContent) {
nsIDocument* currentDoc = focusedContent->GetCurrentDoc();
nsCOMPtr<nsIPresShell> presShell = GetPresShell();
nsPresContext* presContext =
presShell ? presShell->GetPresContext() : nsnull;
if (presContext && currentDoc) {
nsIMEStateManager::OnClickInEditor(presContext,
currentDoc->HasFlag(NODE_IS_EDITABLE) ? nsnull : focusedContent,
mouseEvent);
}
}
nsCOMPtr<nsIDOMNSEvent> nsevent = do_QueryInterface(aMouseEvent);
NS_ASSERTION(nsevent, "nsevent must not be NULL here");
bool preventDefault;

View File

@ -96,12 +96,14 @@
#include "nsEditorUtils.h"
#include "nsWSRunObject.h"
#include "nsGkAtoms.h"
#include "nsIWidget.h"
#include "nsIFrame.h"
#include "nsIParserService.h"
#include "mozilla/dom/Element.h"
using namespace mozilla;
using namespace mozilla::widget;
// Some utilities to handle annoying overloading of "A" tag for link and named anchor
static char hrefText[] = "href";
@ -6042,14 +6044,14 @@ nsHTMLEditor::IsAcceptableInputEvent(nsIDOMEvent* aEvent)
}
NS_IMETHODIMP
nsHTMLEditor::GetPreferredIMEState(PRUint32 *aState)
nsHTMLEditor::GetPreferredIMEState(IMEState *aState)
{
if (IsReadonly() || IsDisabled()) {
*aState = nsIContent::IME_STATUS_DISABLE;
return NS_OK;
}
// HTML editor don't prefer the CSS ime-mode because IE didn't do so too.
*aState = nsIContent::IME_STATUS_ENABLE;
aState->mOpen = IMEState::DONT_CHANGE_OPEN_STATE;
if (IsReadonly() || IsDisabled()) {
aState->mEnabled = IMEState::DISABLED;
} else {
aState->mEnabled = IMEState::ENABLED;
}
return NS_OK;
}

View File

@ -84,6 +84,12 @@ class nsIRangeUtils;
class nsILinkHandler;
struct PropItem;
namespace mozilla {
namespace widget {
struct IMEState;
} // namespace widget
} // namespace mozilla
/**
* The HTML editor implementation.<br>
* Use to edit HTML document represented as a DOM tree.
@ -161,7 +167,7 @@ public:
NS_DECL_NSIMUTATIONOBSERVER_CONTENTREMOVED
/* ------------ nsIEditorIMESupport overrides ------------ */
NS_IMETHOD GetPreferredIMEState(PRUint32 *aState);
NS_IMETHOD GetPreferredIMEState(mozilla::widget::IMEState *aState);
/* ------------ nsIHTMLEditor methods -------------- */

View File

@ -90,6 +90,7 @@ _TEST_FILES = \
test_bug674861.html \
test_bug676401.html \
test_bug677752.html \
test_bug697842.html \
test_CF_HTML_clipboard.html \
test_contenteditable_focus.html \
test_htmleditor_keyevent_handling.html \

View File

@ -0,0 +1,125 @@
<!DOCTYPE>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=697842
-->
<head>
<title>Test for Bug 697842</title>
<script type="application/javascript" src="/MochiKit/packed.js"></script>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
<link rel="stylesheet" type="text/css"
href="chrome://mochikit/content/tests/SimpleTest/test.css" />
</head>
<body>
<div id="display">
<p id="editor" contenteditable style="min-height: 1.5em;"></p>
</div>
<div id="content" style="display: none">
</div>
<pre id="test">
</pre>
<script class="testbody" type="application/javascript">
/** Test for Bug 697842 **/
SimpleTest.waitForExplicitFinish();
SimpleTest.waitForFocus(runTests);
function runTests()
{
var editor = document.getElementById("editor");
editor.focus();
SimpleTest.executeSoon(function() {
var composingString = "";
function handler(aEvent) {
if (aEvent.type != "text") {
is(aEvent.data, composingString, "mismatch composition string");
}
aEvent.stopPropagation();
aEvent.preventDefault();
}
editor.addEventListener("compositionstart", handler, true);
editor.addEventListener("compositionend", handler, true);
editor.addEventListener("compositionupdate", handler, true);
editor.addEventListener("text", handler, true);
// start composition
synthesizeComposition({ type: "compositionstart" });
// input first character
composingString = "\u306B";
synthesizeComposition({ type: "compositionupdate", data: composingString });
synthesizeText(
{ "composition":
{ "string": composingString,
"clauses":
[
{ "length": 1, "attr": COMPOSITION_ATTR_RAWINPUT }
]
},
"caret": { "start": 1, "length": 0 }
});
// input second character
composingString = "\u306B\u3085";
synthesizeComposition({ type: "compositionupdate", data: composingString });
synthesizeText(
{ "composition":
{ "string": composingString,
"clauses":
[
{ "length": 2, "attr": COMPOSITION_ATTR_RAWINPUT }
]
},
"caret": { "start": 2, "length": 0 }
});
// convert them
synthesizeText(
{ "composition":
{ "string": composingString,
"clauses":
[
{ "length": 2,
"attr": COMPOSITION_ATTR_SELECTEDCONVERTEDTEXT }
]
},
"caret": { "start": 2, "length": 0 }
});
// commit
synthesizeText(
{ "composition":
{ "string": composingString,
"clauses":
[
{ "length": 0, "attr": 0 }
]
},
"caret": { "start": 2, "length": 0 }
});
synthesizeComposition({ type: "compositionend", data: composingString });
is(editor.innerHTML, composingString,
"editor has unexpected result");
editor.removeEventListener("compositionstart", handler, true);
editor.removeEventListener("compositionend", handler, true);
editor.removeEventListener("compositionupdate", handler, true);
editor.removeEventListener("text", handler, true);
SimpleTest.finish();
});
}
</script>
</body>
</html>

View File

@ -148,9 +148,9 @@ public class GeckoEvent {
if (s.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
mType = ACCELERATION_EVENT;
mX = s.values[0] / SensorManager.GRAVITY_EARTH;
mY = s.values[1] / SensorManager.GRAVITY_EARTH;
mZ = s.values[2] / SensorManager.GRAVITY_EARTH;
mX = s.values[0];
mY = s.values[1];
mZ = s.values[2];
}
else {
mType = ORIENTATION_EVENT;

View File

@ -45,8 +45,4 @@ include $(DEPTH)/config/autoconf.mk
DIRS = autoconfig
ifdef MOZ_ENABLE_GTK2
DIRS += system-pref/src
endif
include $(topsrcdir)/config/rules.mk

View File

@ -42,10 +42,3 @@ add_makefiles "
extensions/pref/autoconfig/public/Makefile
extensions/pref/autoconfig/src/Makefile
"
if [ "$MOZ_ENABLE_GTK2" ]; then
add_makefiles "
extensions/pref/system-pref/src/Makefile
extensions/pref/system-pref/src/gconf/Makefile
"
fi

View File

@ -1,75 +0,0 @@
# ***** 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
# Sun Microsystems, Inc.
# Portions created by the Initial Developer are Copyright (C) 2003
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
# Bolian Yin <bolian.yin@sun.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 *****
DEPTH = ../../../../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
MODULE = system-pref
LIBRARY_NAME = system-pref
LIBXUL_LIBRARY = 1
CPPSRCS = \
nsSystemPrefService.cpp \
nsSystemPrefFactory.cpp \
$(NULL)
SHARED_LIBRARY_LIBS = ../libsystem-pref_s.a
EXPORT_LIBRARY = 1
IS_COMPONENT = 1
MODULE_NAME = nsSystemPrefModule
EXPORTS = \
nsSystemPrefService.h \
$(NULL)
include $(topsrcdir)/config/rules.mk
CFLAGS += $(MOZ_GTK2_CFLAGS)
CXXFLAGS += $(MOZ_GTK2_CFLAGS)
LOCAL_INCLUDES = -I$(srcdir)/..
export::
$(INSTALL) $(srcdir)/../nsSystemPrefFactory.cpp .
GARBAGE += nsSystemPrefFactory.cpp

View File

@ -1,19 +0,0 @@
/* This file is included as the content of an array
*
* the first column is the mozilla pref name, the second column is the
* the related gconf pref name.
*
*************************************************************************/
{"network.proxy.http", "/system/http_proxy/host"},
{"network.proxy.http_port", "/system/http_proxy/port"},
{"network.proxy.ftp", "/system/proxy/ftp_host"},
{"network.proxy.ftp_port", "/system/proxy/ftp_port"},
{"network.proxy.ssl", "/system/proxy/secure_host"},
{"network.proxy.ssl_port", "/system/proxy/secure_port"},
{"network.proxy.socks", "/system/proxy/socks_host"},
{"network.proxy.socks_port", "/system/proxy/socks_port"},
{"network.proxy.no_proxies_on", "/system/http_proxy/ignore_hosts"},
{"network.proxy.autoconfig_url", "/system/proxy/autoconfig_url"},
{"network.proxy.type", "/system/proxy/mode"},
{"config.use_system_prefs.accessibility", "/desktop/gnome/interface/accessibility"},

View File

@ -1,915 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* vim:expandtab:shiftwidth=4:tabstop=4:
*/
/* ***** BEGIN LICENSE BLOCK *****
* Version: NPL 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 Sun Microsystems, Inc.
* Portions created by Sun Microsystems are Copyright (C) 2003 Sun
* Microsystems, Inc. All Rights Reserved.
*
* Original Author: Bolian Yin (bolian.yin@sun.com)
*
* 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 NPL, 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 NPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include <glib.h>
#include <glib-object.h>
#include "plstr.h"
#include "nsCOMPtr.h"
#include "nsIPrefBranch.h"
#include "nsIPrefService.h"
#include "nsIServiceManager.h"
#include "nsIObserver.h"
#include "nsWeakReference.h"
#include "nsString.h"
#include "nsSystemPrefLog.h"
#include "nsSystemPrefService.h"
/*************************************************************************
* The strange thing here is that we load the gconf library manually and
* search the function pointers we need. If that process fails, no gconf
* support is available in mozilla. The aim is to make mozilla independent
* on gconf, in both compile time and run time.
************************************************************************/
//gconf types
extern "C" {
typedef enum {
GCONF_VALUE_INVALID,
GCONF_VALUE_STRING,
GCONF_VALUE_INT,
GCONF_VALUE_FLOAT,
GCONF_VALUE_BOOL,
GCONF_VALUE_SCHEMA,
GCONF_VALUE_LIST,
GCONF_VALUE_PAIR
}GConfValueType;
typedef struct {
GConfValueType type;
}GConfValue;
typedef void * (*GConfClientGetDefaultType) (void);
typedef bool (*GConfClientGetBoolType) (void *client, const gchar *key,
GError **err);
typedef gchar* (*GConfClientGetStringType) (void *client, const gchar *key,
GError **err);
typedef PRInt32 (*GConfClientGetIntType) (void *client, const gchar *key,
GError **err);
typedef GSList* (*GConfClientGetListType) (void *client, const gchar *key,
GConfValueType list_type,
GError **err);
typedef void (*GConfClientNotifyFuncType) (void* client, guint cnxn_id,
void *entry,
gpointer user_data);
typedef guint (*GConfClientNotifyAddType) (void* client,
const gchar* namespace_section,
GConfClientNotifyFuncType func,
gpointer user_data,
GFreeFunc destroy_notify,
GError** err);
typedef void (*GConfClientNotifyRemoveType) (void *client,
guint cnxn);
typedef void (*GConfClientAddDirType) (void *client,
const gchar *dir,
guint8 preload,
GError **err);
typedef void (*GConfClientRemoveDirType) (void *client,
const gchar *dir,
GError **err);
typedef const char* (*GConfEntryGetKeyType) (const void *entry);
typedef GConfValue* (*GConfEntryGetValueType) (const void *entry);
typedef const char* (*GConfValueGetStringType) (const GConfValue *value);
typedef PRInt32 (*GConfValueGetIntType) (const GConfValue *value);
typedef bool (*GConfValueGetBoolType) (const GConfValue *value);
static void gconf_key_listener (void* client, guint cnxn_id,
void *entry, gpointer user_data);
}
struct GConfCallbackData
{
GConfProxy *proxy;
void * userData;
PRUint32 atom;
PRUint32 notifyId;
};
//////////////////////////////////////////////////////////////////////
// GConPrxoy is a thin wrapper for easy use of gconf funcs. It loads the
// gconf library and initializes the func pointers for later use.
//////////////////////////////////////////////////////////////////////
class GConfProxy
{
public:
GConfProxy(nsSystemPrefService* aSysPrefService);
~GConfProxy();
bool Init();
nsresult GetBoolPref(const char *aMozKey, bool *retval);
nsresult GetCharPref(const char *aMozKey, char **retval);
nsresult GetIntPref(const char *aMozKey, PRInt32 *retval);
nsresult NotifyAdd (PRUint32 aAtom, void *aUserData);
nsresult NotifyRemove (PRUint32 aAtom, const void *aUserData);
nsresult GetAtomForMozKey(const char *aMozKey, PRUint32 *aAtom) {
return GetAtom(aMozKey, 0, aAtom);
}
const char *GetMozKey(PRUint32 aAtom) {
return GetKey(aAtom, 0);
}
void OnNotify(void *aClient, void * aEntry, PRUint32 aNotifyId,
GConfCallbackData *aData);
private:
void *mGConfClient;
PRLibrary *mGConfLib;
bool mInitialized;
nsSystemPrefService *mSysPrefService;
//listeners
nsAutoVoidArray *mObservers;
void InitFuncPtrs();
//gconf public func ptrs
//gconf client funcs
GConfClientGetDefaultType GConfClientGetDefault;
GConfClientGetBoolType GConfClientGetBool;
GConfClientGetStringType GConfClientGetString;
GConfClientGetIntType GConfClientGetInt;
GConfClientGetListType GConfClientGetList;
GConfClientNotifyAddType GConfClientNotifyAdd;
GConfClientNotifyRemoveType GConfClientNotifyRemove;
GConfClientAddDirType GConfClientAddDir;
GConfClientRemoveDirType GConfClientRemoveDir;
//gconf entry funcs
GConfEntryGetValueType GConfEntryGetValue;
GConfEntryGetKeyType GConfEntryGetKey;
//gconf value funcs
GConfValueGetBoolType GConfValueGetBool;
GConfValueGetStringType GConfValueGetString;
GConfValueGetIntType GConfValueGetInt;
//pref name translating stuff
nsresult GetAtom(const char *aKey, PRUint8 aNameType, PRUint32 *aAtom);
nsresult GetAtomForGConfKey(const char *aGConfKey, PRUint32 *aAtom) \
{return GetAtom(aGConfKey, 1, aAtom);}
const char *GetKey(PRUint32 aAtom, PRUint8 aNameType);
const char *GetGConfKey(PRUint32 aAtom) \
{return GetKey(aAtom, 1); }
inline const char *MozKey2GConfKey(const char *aMozKey);
//const strings
static const char sPrefGConfKey[];
static const char sDefaultLibName1[];
static const char sDefaultLibName2[];
};
struct SysPrefCallbackData {
nsISupports *observer;
bool bIsWeakRef;
PRUint32 prefAtom;
};
bool
sysPrefDeleteObserver(void *aElement, void *aData) {
SysPrefCallbackData *pElement =
static_cast<SysPrefCallbackData *>(aElement);
NS_RELEASE(pElement->observer);
nsMemory::Free(pElement);
return true;
}
NS_IMPL_ISUPPORTS2(nsSystemPrefService, nsIPrefBranch, nsIPrefBranch2)
/* public */
nsSystemPrefService::nsSystemPrefService()
:mInitialized(false),
mGConf(nsnull),
mObservers(nsnull)
{
}
nsSystemPrefService::~nsSystemPrefService()
{
mInitialized = false;
delete mGConf;
if (mObservers) {
(void)mObservers->EnumerateForwards(sysPrefDeleteObserver, nsnull);
delete mObservers;
}
}
nsresult
nsSystemPrefService::Init()
{
if (!gSysPrefLog) {
gSysPrefLog = PR_NewLogModule("Syspref");
if (!gSysPrefLog) return NS_ERROR_OUT_OF_MEMORY;
}
SYSPREF_LOG(("Init SystemPref Service\n"));
if (mInitialized)
return NS_ERROR_FAILURE;
if (!mGConf) {
mGConf = new GConfProxy(this);
if (!mGConf->Init()) {
delete mGConf;
mGConf = nsnull;
return NS_ERROR_FAILURE;
}
}
mInitialized = true;
return NS_OK;
}
/* readonly attribute string root; */
NS_IMETHODIMP nsSystemPrefService::GetRoot(char * *aRoot)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
/* long getPrefType (in string aPrefName); */
NS_IMETHODIMP nsSystemPrefService::GetPrefType(const char *aPrefName, PRInt32 *_retval)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
/* boolean getBoolPref (in string aPrefName); */
NS_IMETHODIMP nsSystemPrefService::GetBoolPref(const char *aPrefName, bool *_retval)
{
return mInitialized ?
mGConf->GetBoolPref(aPrefName, _retval) : NS_ERROR_FAILURE;
}
/* void setBoolPref (in string aPrefName, in long aValue); */
NS_IMETHODIMP nsSystemPrefService::SetBoolPref(const char *aPrefName, bool aValue)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
/* string getCharPref (in string aPrefName); */
NS_IMETHODIMP nsSystemPrefService::GetCharPref(const char *aPrefName, char **_retval)
{
return mInitialized ?
mGConf->GetCharPref(aPrefName, _retval) : NS_ERROR_FAILURE;
}
/* void setCharPref (in string aPrefName, in string aValue); */
NS_IMETHODIMP nsSystemPrefService::SetCharPref(const char *aPrefName, const char *aValue)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
/* long getIntPref (in string aPrefName); */
NS_IMETHODIMP nsSystemPrefService::GetIntPref(const char *aPrefName, PRInt32 *_retval)
{
return mInitialized ?
mGConf->GetIntPref(aPrefName, _retval) : NS_ERROR_FAILURE;
}
/* void setIntPref (in string aPrefName, in long aValue); */
NS_IMETHODIMP nsSystemPrefService::SetIntPref(const char *aPrefName, PRInt32 aValue)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
/* void getComplexValue (in string aPrefName, in nsIIDRef aType, [iid_is (aType), retval] out nsQIResult aValue); */
NS_IMETHODIMP nsSystemPrefService::GetComplexValue(const char *aPrefName, const nsIID & aType, void * *aValue)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
/* void setComplexValue (in string aPrefName, in nsIIDRef aType, in nsISupports aValue); */
NS_IMETHODIMP nsSystemPrefService::SetComplexValue(const char *aPrefName, const nsIID & aType, nsISupports *aValue)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
/* void clearUserPref (in string aPrefName); */
NS_IMETHODIMP nsSystemPrefService::ClearUserPref(const char *aPrefName)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
/* void lockPref (in string aPrefName); */
NS_IMETHODIMP nsSystemPrefService::LockPref(const char *aPrefName)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
/* boolean prefHasUserValue (in string aPrefName); */
NS_IMETHODIMP nsSystemPrefService::PrefHasUserValue(const char *aPrefName, bool *_retval)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
/* boolean prefIsLocked (in string aPrefName); */
NS_IMETHODIMP nsSystemPrefService::PrefIsLocked(const char *aPrefName, bool *_retval)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
/* void unlockPref (in string aPrefName); */
NS_IMETHODIMP nsSystemPrefService::UnlockPref(const char *aPrefName)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
/* void deleteBranch (in string aStartingAt); */
NS_IMETHODIMP nsSystemPrefService::DeleteBranch(const char *aStartingAt)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
/* void getChildList (in string aStartingAt, [optional] out unsigned long aCount, [array, size_is (aCount), retval] out string aChildArray); */
NS_IMETHODIMP nsSystemPrefService::GetChildList(const char *aStartingAt, PRUint32 *aCount, char ***aChildArray)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
/* void resetBranch (in string aStartingAt); */
NS_IMETHODIMP nsSystemPrefService::ResetBranch(const char *aStartingAt)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
/* void addObserver (in string aDomain, in nsIObserver aObserver, in boolean aHoldWeak); */
NS_IMETHODIMP nsSystemPrefService::AddObserver(const char *aDomain, nsIObserver *aObserver, bool aHoldWeak)
{
nsresult rv;
NS_ENSURE_ARG_POINTER(aDomain);
NS_ENSURE_ARG_POINTER(aObserver);
NS_ENSURE_TRUE(mInitialized, NS_ERROR_FAILURE);
PRUint32 prefAtom;
// make sure the pref name is supported
rv = mGConf->GetAtomForMozKey(aDomain, &prefAtom);
NS_ENSURE_SUCCESS(rv, rv);
if (!mObservers) {
mObservers = new nsAutoVoidArray();
if (mObservers == nsnull)
return NS_ERROR_OUT_OF_MEMORY;
}
SysPrefCallbackData *pCallbackData = (SysPrefCallbackData *)
nsMemory::Alloc(sizeof(SysPrefCallbackData));
if (pCallbackData == nsnull)
return NS_ERROR_OUT_OF_MEMORY;
pCallbackData->bIsWeakRef = aHoldWeak;
pCallbackData->prefAtom = prefAtom;
// hold a weak reference to the observer if so requested
nsCOMPtr<nsISupports> observerRef;
if (aHoldWeak) {
nsCOMPtr<nsISupportsWeakReference> weakRefFactory =
do_QueryInterface(aObserver);
if (!weakRefFactory) {
// the caller didn't give us a object that supports weak reference.
// ... tell them
nsMemory::Free(pCallbackData);
return NS_ERROR_INVALID_ARG;
}
nsCOMPtr<nsIWeakReference> tmp = do_GetWeakReference(weakRefFactory);
observerRef = tmp;
} else {
observerRef = aObserver;
}
rv = mGConf->NotifyAdd(prefAtom, pCallbackData);
if (NS_FAILED(rv)) {
nsMemory::Free(pCallbackData);
return rv;
}
pCallbackData->observer = observerRef;
NS_ADDREF(pCallbackData->observer);
mObservers->AppendElement(pCallbackData);
return NS_OK;
}
/* void removeObserver (in string aDomain, in nsIObserver aObserver); */
NS_IMETHODIMP nsSystemPrefService::RemoveObserver(const char *aDomain, nsIObserver *aObserver)
{
nsresult rv;
NS_ENSURE_ARG_POINTER(aDomain);
NS_ENSURE_ARG_POINTER(aObserver);
NS_ENSURE_TRUE(mInitialized, NS_ERROR_FAILURE);
if (!mObservers)
return NS_OK;
PRUint32 prefAtom;
// make sure the pref name is supported
rv = mGConf->GetAtomForMozKey(aDomain, &prefAtom);
NS_ENSURE_SUCCESS(rv, rv);
// need to find the index of observer, so we can remove it
PRIntn count = mObservers->Count();
if (count <= 0)
return NS_OK;
PRIntn i;
SysPrefCallbackData *pCallbackData;
for (i = 0; i < count; ++i) {
pCallbackData = (SysPrefCallbackData *)mObservers->ElementAt(i);
if (pCallbackData) {
nsCOMPtr<nsISupports> observerRef;
if (pCallbackData->bIsWeakRef) {
nsCOMPtr<nsISupportsWeakReference> weakRefFactory =
do_QueryInterface(aObserver);
if (weakRefFactory) {
nsCOMPtr<nsIWeakReference> tmp =
do_GetWeakReference(aObserver);
observerRef = tmp;
}
}
if (!observerRef)
observerRef = aObserver;
if (pCallbackData->observer == observerRef &&
pCallbackData->prefAtom == prefAtom) {
rv = mGConf->NotifyRemove(prefAtom, pCallbackData);
if (NS_SUCCEEDED(rv)) {
mObservers->RemoveElementAt(i);
NS_RELEASE(pCallbackData->observer);
nsMemory::Free(pCallbackData);
}
return rv;
}
}
}
return NS_OK;
}
void
nsSystemPrefService::OnPrefChange(PRUint32 aPrefAtom, void *aData)
{
if (!mInitialized)
return;
SysPrefCallbackData *pData = (SysPrefCallbackData *)aData;
if (pData->prefAtom != aPrefAtom)
return;
nsCOMPtr<nsIObserver> observer;
if (pData->bIsWeakRef) {
nsCOMPtr<nsIWeakReference> weakRef =
do_QueryInterface(pData->observer);
if(weakRef)
observer = do_QueryReferent(weakRef);
if (!observer) {
// this weak referenced observer went away, remove it from the list
nsresult rv = mGConf->NotifyRemove(aPrefAtom, pData);
if (NS_SUCCEEDED(rv)) {
mObservers->RemoveElement(pData);
NS_RELEASE(pData->observer);
nsMemory::Free(pData);
}
return;
}
}
else
observer = do_QueryInterface(pData->observer);
if (observer)
observer->Observe(static_cast<nsIPrefBranch *>(this),
NS_SYSTEMPREF_PREFCHANGE_TOPIC_ID,
NS_ConvertUTF8toUTF16(mGConf->GetMozKey(aPrefAtom)).
get());
}
/*************************************************************
* GConfProxy
*
************************************************************/
struct GConfFuncListType {
const char *FuncName;
PRFuncPtr FuncPtr;
};
struct PrefNamePair {
const char *mozPrefName;
const char *gconfPrefName;
};
const char
GConfProxy::sPrefGConfKey[] = "accessibility.unix.gconf2.shared-library";
const char GConfProxy::sDefaultLibName1[] = "libgconf-2.so.4";
const char GConfProxy::sDefaultLibName2[] = "libgconf-2.so";
#define GCONF_FUNCS_POINTER_BEGIN \
static GConfFuncListType sGConfFuncList[] = {
#define GCONF_FUNCS_POINTER_ADD(func_name) \
{func_name, nsnull},
#define GCONF_FUNCS_POINTER_END \
{nsnull, nsnull}, };
GCONF_FUNCS_POINTER_BEGIN
GCONF_FUNCS_POINTER_ADD("gconf_client_get_default") // 0
GCONF_FUNCS_POINTER_ADD("gconf_client_get_bool") // 1
GCONF_FUNCS_POINTER_ADD("gconf_client_get_string") //2
GCONF_FUNCS_POINTER_ADD("gconf_client_get_int") //3
GCONF_FUNCS_POINTER_ADD("gconf_client_notify_add") //4
GCONF_FUNCS_POINTER_ADD("gconf_client_notify_remove") //5
GCONF_FUNCS_POINTER_ADD("gconf_client_add_dir") //6
GCONF_FUNCS_POINTER_ADD("gconf_client_remove_dir") //7
GCONF_FUNCS_POINTER_ADD("gconf_entry_get_value") //8
GCONF_FUNCS_POINTER_ADD("gconf_entry_get_key") //9
GCONF_FUNCS_POINTER_ADD("gconf_value_get_bool") //10
GCONF_FUNCS_POINTER_ADD("gconf_value_get_string") //11
GCONF_FUNCS_POINTER_ADD("gconf_value_get_int") //12
GCONF_FUNCS_POINTER_ADD("gconf_client_get_list") //13
GCONF_FUNCS_POINTER_END
/////////////////////////////////////////////////////////////////////////////
// the list is the mapping table, between mozilla prefs and gconf prefs
// It is expected to include all the pref pairs that are related in mozilla
// and gconf.
//
// Note: the prefs listed here are not neccessarily be read from gconf, they
// are the prefs that could be read from gconf. Mozilla has another
// list (see sSysPrefList in nsSystemPref.cpp) that decide which prefs
// are really read.
//////////////////////////////////////////////////////////////////////////////
static const PrefNamePair sPrefNameMapping[] = {
#include "gconf_pref_list.inc"
{nsnull, nsnull},
};
bool
gconfDeleteObserver(void *aElement, void *aData) {
nsMemory::Free(aElement);
return true;
}
GConfProxy::GConfProxy(nsSystemPrefService *aSysPrefService):
mGConfClient(nsnull),
mGConfLib(nsnull),
mInitialized(false),
mSysPrefService(aSysPrefService),
mObservers(nsnull)
{
}
GConfProxy::~GConfProxy()
{
if (mGConfClient)
g_object_unref(G_OBJECT(mGConfClient));
if (mObservers) {
(void)mObservers->EnumerateForwards(gconfDeleteObserver, nsnull);
delete mObservers;
}
// bug 379666: can't unload GConf-2 since it registers atexit handlers
//PR_UnloadLibrary(mGConfLib);
}
bool
GConfProxy::Init()
{
SYSPREF_LOG(("GConfProxy:: Init GConfProxy\n"));
if (!mSysPrefService)
return false;
if (mInitialized)
return true;
nsCOMPtr<nsIPrefBranch> pref = do_GetService(NS_PREFSERVICE_CONTRACTID);
if (!pref)
return false;
nsXPIDLCString gconfLibName;
nsresult rv;
//check if gconf-2 library is given in prefs
rv = pref->GetCharPref(sPrefGConfKey, getter_Copies(gconfLibName));
if (NS_SUCCEEDED(rv)) {
//use the library name in the preference
SYSPREF_LOG(("GConf library in prefs is %s\n", gconfLibName.get()));
mGConfLib = PR_LoadLibrary(gconfLibName.get());
}
else {
SYSPREF_LOG(("GConf library not specified in prefs, try the default: "
"%s and %s\n", sDefaultLibName1, sDefaultLibName2));
mGConfLib = PR_LoadLibrary(sDefaultLibName1);
if (!mGConfLib)
mGConfLib = PR_LoadLibrary(sDefaultLibName2);
}
if (!mGConfLib) {
SYSPREF_LOG(("Fail to load GConf library\n"));
return false;
}
//check every func we need in the gconf library
GConfFuncListType *funcList;
PRFuncPtr func;
for (funcList = sGConfFuncList; funcList->FuncName; ++funcList) {
func = PR_FindFunctionSymbol(mGConfLib, funcList->FuncName);
if (!func) {
SYSPREF_LOG(("Check GConf Func Error: %s", funcList->FuncName));
goto init_failed_unload;
}
funcList->FuncPtr = func;
}
InitFuncPtrs();
mGConfClient = GConfClientGetDefault();
// Don't unload past this point, since GConf's initialization of ORBit
// causes atexit handlers to be registered.
if (!mGConfClient) {
SYSPREF_LOG(("Fail to Get default gconf client\n"));
goto init_failed;
}
mInitialized = true;
return true;
init_failed_unload:
PR_UnloadLibrary(mGConfLib);
init_failed:
mGConfLib = nsnull;
return false;
}
nsresult
GConfProxy::GetBoolPref(const char *aMozKey, bool *retval)
{
NS_ENSURE_TRUE(mInitialized, NS_ERROR_FAILURE);
*retval = GConfClientGetBool(mGConfClient, MozKey2GConfKey(aMozKey), NULL);
return NS_OK;
}
nsresult
GConfProxy::GetCharPref(const char *aMozKey, char **retval)
{
NS_ENSURE_TRUE(mInitialized, NS_ERROR_FAILURE);
const gchar *gconfkey = MozKey2GConfKey(aMozKey);
if (!strcmp (aMozKey, "network.proxy.no_proxies_on")) {
GSList *s;
nsCString noproxy;
GSList *gslist = GConfClientGetList(mGConfClient, gconfkey,
GCONF_VALUE_STRING, NULL);
for (s = gslist; s; s = g_slist_next(s)) {
noproxy += (char *)s->data;
noproxy += ", ";
g_free ((char *)s->data);
}
g_slist_free (gslist);
*retval = PL_strdup(noproxy.get());
} else {
gchar *str = GConfClientGetString(mGConfClient, gconfkey, NULL);
if (str) {
*retval = PL_strdup(str);
g_free (str);
}
}
return NS_OK;
}
nsresult
GConfProxy::GetIntPref(const char *aMozKey, PRInt32 *retval)
{
NS_ENSURE_TRUE(mInitialized, NS_ERROR_FAILURE);
if (strcmp (aMozKey, "network.proxy.type") == 0) {
gchar *str;
str = GConfClientGetString(mGConfClient,
MozKey2GConfKey (aMozKey), NULL);
if (str) {
if (strcmp (str, "manual") == 0)
*retval = 1;
else if (strcmp (str, "auto") == 0)
*retval = 2;
else
*retval = 0;
g_free (str);
} else
*retval = 0;
} else {
*retval = GConfClientGetInt(mGConfClient,
MozKey2GConfKey(aMozKey), NULL);
}
return NS_OK;
}
nsresult
GConfProxy::NotifyAdd (PRUint32 aAtom, void *aUserData)
{
NS_ENSURE_TRUE(mInitialized, NS_ERROR_FAILURE);
const char *gconfKey = GetGConfKey(aAtom);
if (!gconfKey)
return NS_ERROR_FAILURE;
if (!mObservers) {
mObservers = new nsAutoVoidArray();
if (mObservers == nsnull)
return NS_ERROR_OUT_OF_MEMORY;
}
GConfCallbackData *pData = (GConfCallbackData *)
nsMemory::Alloc(sizeof(GConfCallbackData));
NS_ENSURE_TRUE(pData, NS_ERROR_OUT_OF_MEMORY);
pData->proxy = this;
pData->userData = aUserData;
pData->atom = aAtom;
mObservers->AppendElement(pData);
GConfClientAddDir(mGConfClient, gconfKey,
0, // GCONF_CLIENT_PRELOAD_NONE, don't preload anything
NULL);
pData->notifyId = GConfClientNotifyAdd(mGConfClient, gconfKey,
gconf_key_listener, pData,
NULL, NULL);
return NS_OK;
}
nsresult
GConfProxy::NotifyRemove (PRUint32 aAtom, const void *aUserData)
{
NS_ENSURE_TRUE(mInitialized, NS_ERROR_FAILURE);
PRIntn count = mObservers->Count();
if (count <= 0)
return NS_OK;
PRIntn i;
GConfCallbackData *pData;
for (i = 0; i < count; ++i) {
pData = (GConfCallbackData *)mObservers->ElementAt(i);
if (pData && pData->atom == aAtom && pData->userData == aUserData) {
GConfClientNotifyRemove(mGConfClient, pData->notifyId);
GConfClientRemoveDir(mGConfClient,
GetGConfKey(pData->atom), NULL);
mObservers->RemoveElementAt(i);
nsMemory::Free(pData);
break;
}
}
return NS_OK;
}
void
GConfProxy::InitFuncPtrs()
{
//gconf client funcs
GConfClientGetDefault =
(GConfClientGetDefaultType) sGConfFuncList[0].FuncPtr;
GConfClientGetBool =
(GConfClientGetBoolType) sGConfFuncList[1].FuncPtr;
GConfClientGetString =
(GConfClientGetStringType) sGConfFuncList[2].FuncPtr;
GConfClientGetInt =
(GConfClientGetIntType) sGConfFuncList[3].FuncPtr;
GConfClientNotifyAdd =
(GConfClientNotifyAddType) sGConfFuncList[4].FuncPtr;
GConfClientNotifyRemove =
(GConfClientNotifyRemoveType) sGConfFuncList[5].FuncPtr;
GConfClientAddDir =
(GConfClientAddDirType) sGConfFuncList[6].FuncPtr;
GConfClientRemoveDir =
(GConfClientRemoveDirType) sGConfFuncList[7].FuncPtr;
//gconf entry funcs
GConfEntryGetValue = (GConfEntryGetValueType) sGConfFuncList[8].FuncPtr;
GConfEntryGetKey = (GConfEntryGetKeyType) sGConfFuncList[9].FuncPtr;
//gconf value funcs
GConfValueGetBool = (GConfValueGetBoolType) sGConfFuncList[10].FuncPtr;
GConfValueGetString = (GConfValueGetStringType) sGConfFuncList[11].FuncPtr;
GConfValueGetInt = (GConfValueGetIntType) sGConfFuncList[12].FuncPtr;
//gconf client list func
GConfClientGetList =
(GConfClientGetListType) sGConfFuncList[13].FuncPtr;
}
void
GConfProxy::OnNotify(void *aClient, void * aEntry, PRUint32 aNotifyId,
GConfCallbackData *aData)
{
if (!mInitialized || !aEntry || (mGConfClient != aClient) || !aData)
return;
if (GConfEntryGetValue(aEntry) == NULL)
return;
PRUint32 prefAtom;
nsresult rv = GetAtomForGConfKey(GConfEntryGetKey(aEntry), &prefAtom);
if (NS_FAILED(rv))
return;
mSysPrefService->OnPrefChange(prefAtom, aData->userData);
}
nsresult
GConfProxy::GetAtom(const char *aKey, PRUint8 aNameType, PRUint32 *aAtom)
{
if (!aKey)
return NS_ERROR_FAILURE;
PRUint32 prefSize = sizeof(sPrefNameMapping) / sizeof(sPrefNameMapping[0]);
for (PRUint32 index = 0; index < prefSize; ++index) {
if (!strcmp((aNameType == 0) ? sPrefNameMapping[index].mozPrefName :
sPrefNameMapping[index].gconfPrefName, aKey)) {
*aAtom = index;
return NS_OK;
}
}
return NS_ERROR_FAILURE;
}
const char *
GConfProxy::GetKey(PRUint32 aAtom, PRUint8 aNameType)
{
PRUint32 mapSize = sizeof(sPrefNameMapping) / sizeof(sPrefNameMapping[0]);
if (aAtom >= 0 && aAtom < mapSize)
return (aNameType == 0) ? sPrefNameMapping[aAtom].mozPrefName :
sPrefNameMapping[aAtom].gconfPrefName;
return NULL;
}
inline const char *
GConfProxy::MozKey2GConfKey(const char *aMozKey)
{
PRUint32 atom;
nsresult rv = GetAtomForMozKey(aMozKey, &atom);
if (NS_SUCCEEDED(rv))
return GetGConfKey(atom);
return NULL;
}
/* static */
void gconf_key_listener (void* client, guint cnxn_id,
void *entry, gpointer user_data)
{
SYSPREF_LOG(("...SYSPREF_LOG...key listener get called \n"));
if (!user_data)
return;
GConfCallbackData *pData = reinterpret_cast<GConfCallbackData *>
(user_data);
pData->proxy->OnNotify(client, entry, cnxn_id, pData);
}

View File

@ -1,93 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* vim:expandtab:shiftwidth=4:tabstop=4:
*/
/* ***** BEGIN LICENSE BLOCK *****
* Version: NPL 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 Sun Microsystems, Inc.
* Portions created by Sun Microsystems are Copyright (C) 2003 Sun
* Microsystems, Inc. All Rights Reserved.
*
* Original Author: Bolian Yin (bolian.yin@sun.com)
*
* 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 NPL, 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 NPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef __SYSTEM_PREF_SERVICE_H__
#define __SYSTEM_PREF_SERVICE_H__
#include "prlink.h"
#include "nsVoidArray.h"
#include "nsWeakPtr.h"
#include "nsIPrefBranch.h"
#include "nsIPrefBranch2.h"
class GConfProxy;
////////////////////////////////////////////////////////////////////////////
// nsSystemPrefService provide a interface for read system prefs. It is
// platform related. This directory (system-pref/gconf) impls it for gconf
// on the gconf platform.
////////////////////////////////////////////////////////////////////////////
class nsSystemPrefService : public nsIPrefBranch2
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIPREFBRANCH
NS_DECL_NSIPREFBRANCH2
nsSystemPrefService();
virtual ~nsSystemPrefService();
nsresult Init();
void OnPrefChange(PRUint32 aPrefAtom, void *aData);
private:
bool mInitialized;
GConfProxy *mGConf;
//listeners
nsAutoVoidArray *mObservers;
};
#define NS_SYSTEMPREF_SERVICE_CID \
{ /* {94f1de09-d0e5-4ca8-94c2-98b049316b7f} */ \
0x94f1de09, \
0xd0e5, \
0x4ca8, \
{ 0x94, 0xc2, 0x98, 0xb0, 0x49, 0x31, 0x6b, 0x7f } \
}
#define NS_SYSTEMPREF_SERVICE_CONTRACTID "@mozilla.org/system-preference-service;1"
#define NS_SYSTEMPREF_SERVICE_CLASSNAME "System Preferences Service"
#define NS_SYSTEMPREF_PREFCHANGE_TOPIC_ID "nsSystemPrefService:pref-changed"
#endif /* __SYSTEM_PREF_SERVICE_H__ */

View File

@ -1,474 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* vim:expandtab:shiftwidth=4:tabstop=4:
*/
/* ***** BEGIN LICENSE BLOCK *****
* Version: NPL 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 Sun Microsystems, Inc.
* Portions created by Sun Microsystems are Copyright (C) 2003 Sun
* Microsystems, Inc. All Rights Reserved.
*
* Original Author: Bolian Yin (bolian.yin@sun.com)
*
* 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 NPL, 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 NPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsSystemPref.h"
#include "nsIObserverService.h"
#include "nsSystemPrefLog.h"
#include "nsSystemPrefService.h"
#include "nsString.h"
const char sSysPrefString[] = "config.use_system_prefs";
union MozPrefValue {
char * stringVal;
PRInt32 intVal;
bool boolVal;
};
struct SysPrefItem {
const char *prefName; // mozilla pref string name
MozPrefValue defaultValue; // store the mozilla default value
bool isLocked; // store the mozilla lock status
SysPrefItem() {
prefName = nsnull;
defaultValue.intVal = 0;
defaultValue.stringVal = nsnull;
defaultValue.boolVal = false;
isLocked = false;
}
void SetPrefName(const char *aPrefName) {
prefName = aPrefName;
}
};
// all prefs that mozilla need to read from host system if they are available
static const char *sSysPrefList[] = {
"network.proxy.http",
"network.proxy.http_port",
"network.proxy.ftp",
"network.proxy.ftp_port",
"network.proxy.ssl",
"network.proxy.ssl_port",
"network.proxy.socks",
"network.proxy.socks_port",
"network.proxy.no_proxies_on",
"network.proxy.autoconfig_url",
"network.proxy.type",
"config.use_system_prefs.accessibility",
};
PRLogModuleInfo *gSysPrefLog = NULL;
NS_IMPL_ISUPPORTS2(nsSystemPref, nsIObserver, nsISupportsWeakReference)
nsSystemPref::nsSystemPref():
mSysPrefService(nsnull),
mEnabled(false),
mSysPrefs(nsnull)
{
}
nsSystemPref::~nsSystemPref()
{
mSysPrefService = nsnull;
mEnabled = false;
delete [] mSysPrefs;
}
///////////////////////////////////////////////////////////////////////////////
// nsSystemPref::Init
// Setup log and listen on NS_PREFSERVICE_READ_TOPIC_ID from pref service
///////////////////////////////////////////////////////////////////////////////
nsresult
nsSystemPref::Init(void)
{
nsresult rv;
if (!gSysPrefLog) {
gSysPrefLog = PR_NewLogModule("Syspref");
if (!gSysPrefLog)
return NS_ERROR_OUT_OF_MEMORY;
}
nsCOMPtr<nsIObserverService> observerService =
do_GetService("@mozilla.org/observer-service;1", &rv);
if (observerService) {
rv = observerService->AddObserver(this, NS_PREFSERVICE_READ_TOPIC_ID,
false);
rv = observerService->AddObserver(this, "profile-before-change",
false);
SYSPREF_LOG(("Add Observer for %s\n", NS_PREFSERVICE_READ_TOPIC_ID));
}
return(rv);
}
///////////////////////////////////////////////////////////////////////////////
// nsSystemPref::Observe
// Observe notifications from mozilla pref system and system prefs (if enabled)
///////////////////////////////////////////////////////////////////////////////
NS_IMETHODIMP
nsSystemPref::Observe(nsISupports *aSubject,
const char *aTopic,
const PRUnichar *aData)
{
nsresult rv = NS_OK;
if (!aTopic)
return NS_OK;
// if we are notified by pref service
// check the system pref settings
if (!nsCRT::strcmp(aTopic, NS_PREFSERVICE_READ_TOPIC_ID)) {
SYSPREF_LOG(("Observed: %s\n", aTopic));
nsCOMPtr<nsIPrefBranch2> prefBranch =
do_GetService(NS_PREFSERVICE_CONTRACTID, &rv);
if (NS_FAILED(rv))
return rv;
rv = prefBranch->GetBoolPref(sSysPrefString, &mEnabled);
if (NS_FAILED(rv)) {
SYSPREF_LOG(("...FAil to Get %s\n", sSysPrefString));
return rv;
}
// if there is no system pref service, assume nothing happen to us
mSysPrefService = do_GetService(NS_SYSTEMPREF_SERVICE_CONTRACTID, &rv);
if (NS_FAILED(rv) || !mSysPrefService) {
SYSPREF_LOG(("...No System Pref Service\n"));
return NS_OK;
}
// listen on its changes
rv = prefBranch->AddObserver(sSysPrefString, this, true);
if (NS_FAILED(rv)) {
SYSPREF_LOG(("...FAil to add observer for %s\n", sSysPrefString));
return rv;
}
if (!mEnabled) {
SYSPREF_LOG(("%s is disabled\n", sSysPrefString));
return NS_OK;
}
SYSPREF_LOG(("%s is enabled\n", sSysPrefString));
rv = UseSystemPrefs();
}
// sSysPrefString value was changed, update ...
else if (!nsCRT::strcmp(aTopic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID) &&
NS_ConvertUTF8toUTF16(sSysPrefString).Equals(aData)) {
SYSPREF_LOG(("++++++ Notify: topic=%s data=%s\n",
aTopic, NS_ConvertUTF16toUTF8(aData).get()));
nsCOMPtr<nsIPrefBranch> prefBranch =
do_GetService(NS_PREFSERVICE_CONTRACTID, &rv);
if (NS_FAILED(rv))
return rv;
bool enabled = mEnabled;
rv = prefBranch->GetBoolPref(sSysPrefString, &mEnabled);
if (enabled != mEnabled) {
if (mEnabled)
//read prefs from system
rv = UseSystemPrefs();
else
//roll back to mozilla prefs
rv = UseMozillaPrefs();
}
}
// if the system pref notify us that some pref has been changed by user
// outside mozilla. We need to read it again.
else if (!nsCRT::strcmp(aTopic, NS_SYSTEMPREF_PREFCHANGE_TOPIC_ID) &&
aData) {
NS_ASSERTION(mEnabled, "Should not listen when disabled");
SYSPREF_LOG(("====== System Pref Notify topic=%s data=%s\n",
aTopic, (char*)aData));
rv = ReadSystemPref(NS_LossyConvertUTF16toASCII(aData).get());
return NS_OK;
} else if (!nsCRT::strcmp(aTopic,"profile-before-change")) {
//roll back to mozilla prefs
if (mEnabled)
UseMozillaPrefs();
mEnabled = false;
mSysPrefService = nsnull;
delete [] mSysPrefs;
mSysPrefs = nsnull;
} else
SYSPREF_LOG(("Not needed topic Received %s\n", aTopic));
return rv;
}
/* private */
////////////////////////////////////////////////////////////////
// nsSystemPref::UseSystemPrefs
// Read all the prefs in the table from system, listen for their
// changes in system pref service.
////////////////////////////////////////////////////////////////
nsresult
nsSystemPref::UseSystemPrefs()
{
SYSPREF_LOG(("\n====Now Use system prefs==\n"));
nsresult rv = NS_OK;
if (!mSysPrefService) {
return NS_ERROR_FAILURE;
}
PRIntn sysPrefCount= sizeof(sSysPrefList) / sizeof(sSysPrefList[0]);
if (!mSysPrefs) {
mSysPrefs = new SysPrefItem[sysPrefCount];
if (!mSysPrefs)
return NS_ERROR_OUT_OF_MEMORY;
for (PRIntn index = 0; index < sysPrefCount; ++index)
mSysPrefs[index].SetPrefName(sSysPrefList[index]);
}
for (PRIntn index = 0; index < sysPrefCount; ++index) {
// save mozilla prefs
SaveMozDefaultPref(mSysPrefs[index].prefName,
&mSysPrefs[index].defaultValue,
&mSysPrefs[index].isLocked);
// get the system prefs
ReadSystemPref(mSysPrefs[index].prefName);
SYSPREF_LOG(("Add Listener on %s\n", mSysPrefs[index].prefName));
mSysPrefService->AddObserver(mSysPrefs[index].prefName,
this, true);
}
return rv;
}
//////////////////////////////////////////////////////////////////////
// nsSystemPref::ReadSystemPref
// Read a pref value from system pref service, and lock it in mozilla.
//////////////////////////////////////////////////////////////////////
nsresult
nsSystemPref::ReadSystemPref(const char *aPrefName)
{
if (!mSysPrefService)
return NS_ERROR_FAILURE;
nsresult rv;
nsCOMPtr<nsIPrefBranch> prefBranch
(do_GetService(NS_PREFSERVICE_CONTRACTID, &rv));
if (NS_FAILED(rv))
return rv;
SYSPREF_LOG(("about to read aPrefName %s\n", aPrefName));
prefBranch->UnlockPref(aPrefName);
PRInt32 prefType = nsIPrefBranch::PREF_INVALID;
nsXPIDLCString strValue;
PRInt32 intValue = 0;
bool boolValue = false;
rv = prefBranch->GetPrefType(aPrefName, &prefType);
if (NS_FAILED(rv))
return rv;
switch (prefType) {
case nsIPrefBranch::PREF_STRING:
mSysPrefService->GetCharPref(aPrefName, getter_Copies(strValue));
SYSPREF_LOG(("system value is %s\n", strValue.get()));
prefBranch->SetCharPref(aPrefName, strValue.get());
break;
case nsIPrefBranch::PREF_INT:
mSysPrefService->GetIntPref(aPrefName, &intValue);
SYSPREF_LOG(("system value is %d\n", intValue));
prefBranch->SetIntPref(aPrefName, intValue);
break;
case nsIPrefBranch::PREF_BOOL:
mSysPrefService->GetBoolPref(aPrefName, &boolValue);
SYSPREF_LOG(("system value is %s\n", boolValue ? "TRUE" : "FALSE"));
prefBranch->SetBoolPref(aPrefName, boolValue);
break;
default:
SYSPREF_LOG(("Fail to system value for it\n"));
return NS_ERROR_FAILURE;
}
prefBranch->LockPref(aPrefName);
return NS_OK;
}
//////////////////////////////////////////////////////////////////////
// nsSystemPref::UseMozillaPrefs
// Restore mozilla default prefs, remove system pref listeners
/////////////////////////////////////////////////////////////////////
nsresult
nsSystemPref::UseMozillaPrefs()
{
nsresult rv = NS_OK;
SYSPREF_LOG(("\n====Now rollback to Mozilla prefs==\n"));
// if we did not use system prefs, do nothing
if (!mSysPrefService)
return NS_OK;
PRIntn sysPrefCount= sizeof(sSysPrefList) / sizeof(sSysPrefList[0]);
for (PRIntn index = 0; index < sysPrefCount; ++index) {
// restore mozilla default value and free string memory if needed
RestoreMozDefaultPref(mSysPrefs[index].prefName,
&mSysPrefs[index].defaultValue,
mSysPrefs[index].isLocked);
SYSPREF_LOG(("stop listening on %s\n", mSysPrefs[index].prefName));
mSysPrefService->RemoveObserver(mSysPrefs[index].prefName,
this);
}
return rv;
}
////////////////////////////////////////////////////////////////////////////
// nsSystemPref::RestoreMozDefaultPref
// Save the saved mozilla default value.
// It is also responsible for allocate the string memory when needed, because
// this method know what type of value is stored.
/////////////////////////////////////////////////////////////////////////////
nsresult
nsSystemPref::SaveMozDefaultPref(const char *aPrefName,
MozPrefValue *aPrefValue,
bool *aLocked)
{
NS_ENSURE_ARG_POINTER(aPrefName);
NS_ENSURE_ARG_POINTER(aPrefValue);
NS_ENSURE_ARG_POINTER(aLocked);
nsresult rv;
nsCOMPtr<nsIPrefBranch> prefBranch =
do_GetService(NS_PREFSERVICE_CONTRACTID, &rv);
if (NS_FAILED(rv))
return rv;
SYSPREF_LOG(("Save Mozilla value for %s\n", aPrefName));
PRInt32 prefType = nsIPrefBranch::PREF_INVALID;
nsXPIDLCString strValue;
rv = prefBranch->GetPrefType(aPrefName, &prefType);
if (NS_FAILED(rv))
return rv;
switch (prefType) {
case nsIPrefBranch::PREF_STRING:
prefBranch->GetCharPref(aPrefName,
getter_Copies(strValue));
SYSPREF_LOG(("Mozilla value is %s", strValue.get()));
if (aPrefValue->stringVal)
PL_strfree(aPrefValue->stringVal);
aPrefValue->stringVal = PL_strdup(strValue.get());
break;
case nsIPrefBranch::PREF_INT:
prefBranch->GetIntPref(aPrefName, &aPrefValue->intVal);
SYSPREF_LOG(("Mozilla value is %d\n", aPrefValue->intVal));
break;
case nsIPrefBranch::PREF_BOOL:
prefBranch->GetBoolPref(aPrefName, &aPrefValue->boolVal);
SYSPREF_LOG(("Mozilla value is %s\n",
aPrefValue->boolVal ? "TRUE" : "FALSE"));
break;
default:
SYSPREF_LOG(("Fail to Read Mozilla value for it\n"));
return NS_ERROR_FAILURE;
}
rv = prefBranch->PrefIsLocked(aPrefName, aLocked);
SYSPREF_LOG((" (%s).\n", aLocked ? "Locked" : "NOT Locked"));
return rv;
}
////////////////////////////////////////////////////////////////////////////
// nsSystemPref::RestoreMozDefaultPref
// Restore the saved mozilla default value to pref service.
// It is also responsible for free the string memory when needed, because
// this method know what type of value is stored.
/////////////////////////////////////////////////////////////////////////////
nsresult
nsSystemPref::RestoreMozDefaultPref(const char *aPrefName,
MozPrefValue *aPrefValue,
bool aLocked)
{
NS_ENSURE_ARG_POINTER(aPrefName);
nsresult rv;
nsCOMPtr<nsIPrefBranch> prefBranch =
do_GetService(NS_PREFSERVICE_CONTRACTID, &rv);
if (NS_FAILED(rv))
return rv;
SYSPREF_LOG(("Restore Mozilla value for %s\n", aPrefName));
PRInt32 prefType = nsIPrefBranch::PREF_INVALID;
rv = prefBranch->GetPrefType(aPrefName, &prefType);
if (NS_FAILED(rv))
return rv;
// unlock, if it is locked
prefBranch->UnlockPref(aPrefName);
switch (prefType) {
case nsIPrefBranch::PREF_STRING:
prefBranch->SetCharPref(aPrefName,
aPrefValue->stringVal);
SYSPREF_LOG(("Mozilla value is %s\n", aPrefValue->stringVal));
PL_strfree(aPrefValue->stringVal);
aPrefValue->stringVal = nsnull;
break;
case nsIPrefBranch::PREF_INT:
prefBranch->SetIntPref(aPrefName, aPrefValue->intVal);
SYSPREF_LOG(("Mozilla value is %d\n", aPrefValue->intVal));
break;
case nsIPrefBranch::PREF_BOOL:
prefBranch->SetBoolPref(aPrefName, aPrefValue->boolVal);
SYSPREF_LOG(("Mozilla value is %s\n",
aPrefValue->boolVal ? "TRUE" : "FALSE"));
break;
default:
SYSPREF_LOG(("Fail to Restore Mozilla value for it\n"));
return NS_ERROR_FAILURE;
}
// restore its old lock status
if (aLocked)
prefBranch->LockPref(aPrefName);
return NS_OK;
}

View File

@ -1,116 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* vim:expandtab:shiftwidth=4:tabstop=4:
*/
/* ***** BEGIN LICENSE BLOCK *****
* Version: NPL 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 Sun Microsystems, Inc.
* Portions created by Sun Microsystems are Copyright (C) 2003 Sun
* Microsystems, Inc. All Rights Reserved.
*
* Original Author: Bolian Yin (bolian.yin@sun.com)
*
* 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 NPL, 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 NPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef __SYSTEM_PREF_H__
#define __SYSTEM_PREF_H__
#include "nsCOMPtr.h"
#include "nsXPCOM.h"
#include "nsCRT.h"
#include "nsIAppStartupNotifier.h"
#include "nsICategoryManager.h"
#include "nsIServiceManager.h"
#include "nsWeakReference.h"
#include "nsIPrefService.h"
#include "nsIPrefBranch2.h"
#include <nsIObserver.h>
union MozPrefValue;
struct SysPrefItem;
//////////////////////////////////////////////////////////////////////////
//
// nsSystemPref, as an extension of mozilla pref service, reads some mozilla
// prefs from host system when the feature is enabled ("config.system-pref").
//
// nsSystemPref listens on NS_PREFSERVICE_READ_TOPIC_ID. When notified,
// nsSystemPref will start the nsSystemPrefService (platform specific) to
// read all the interested prefs (listed in sSysPrefList table) from system
// and lock these prefs from user's modification.
//
// This feature will make mozilla integrated better into host platforms. If
// users want to change the prefs read from system, the system provided pref
// editor (i.e. gconf-editor in gnome) should be used.
//////////////////////////////////////////////////////////////////////////
class nsSystemPref : public nsIObserver,
public nsSupportsWeakReference
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIOBSERVER
nsSystemPref();
virtual ~nsSystemPref();
nsresult Init(void);
private:
// funcs used to load system prefs and save mozilla default prefs
nsresult UseSystemPrefs();
nsresult ReadSystemPref(const char *aPrefName);
nsresult SaveMozDefaultPref(const char *aPrefName,
MozPrefValue *aPrefVal,
bool *aLocked);
// funcs used to load mozilla default prefs
nsresult UseMozillaPrefs();
nsresult RestoreMozDefaultPref(const char *aPrefName,
MozPrefValue *aPrefVal,
bool aLocked);
nsCOMPtr<nsIPrefBranch2> mSysPrefService;
bool mEnabled; // system pref is enabled or not
SysPrefItem *mSysPrefs;
};
#define NS_SYSTEMPREF_CID \
{ /* {549abb24-7c9d-4aba-915e-7ce0b716b32f} */ \
0x549abb24, \
0x7c9d, \
0x4aba, \
{ 0x91, 0x5e, 0x7c, 0xe0, 0xb7, 0x16, 0xb3, 0x2f } \
}
#define NS_SYSTEMPREF_CONTRACTID "@mozilla.org/system-preferences;1"
#define NS_SYSTEMPREF_CLASSNAME "System Preferences"
#endif /* __SYSTEM_PREF_H__ */

View File

@ -1,77 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* vim:expandtab:shiftwidth=4:tabstop=4:
*/
/* ***** BEGIN LICENSE BLOCK *****
* Version: NPL 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 Sun Microsystems, Inc.
* Portions created by Sun Microsystems are Copyright (C) 2003 Sun
* Microsystems, Inc. All Rights Reserved.
*
* Original Author: Bolian Yin (bolian.yin@sun.com)
*
* 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 NPL, 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 NPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsICategoryManager.h"
#include "mozilla/ModuleUtils.h"
#include "nsSystemPref.h"
#include "nsSystemPrefService.h"
NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsSystemPref, Init)
NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsSystemPrefService, Init)
NS_DEFINE_NAMED_CID(NS_SYSTEMPREF_CID);
NS_DEFINE_NAMED_CID(NS_SYSTEMPREF_SERVICE_CID);
static const mozilla::Module::CIDEntry kSysPrefCIDs[] = {
{ &kNS_SYSTEMPREF_CID, false, NULL, nsSystemPrefConstructor },
{ &kNS_SYSTEMPREF_SERVICE_CID, false, NULL, nsSystemPrefServiceConstructor },
{ NULL }
};
static const mozilla::Module::ContractIDEntry kSysPrefContracts[] = {
{ NS_SYSTEMPREF_CONTRACTID, &kNS_SYSTEMPREF_CID },
{ NS_SYSTEMPREF_SERVICE_CONTRACTID, &kNS_SYSTEMPREF_SERVICE_CID },
{ NULL }
};
static const mozilla::Module::CategoryEntry kSysPrefCategories[] = {
{ APPSTARTUP_CATEGORY, "SystemPref Module", NS_SYSTEMPREF_CONTRACTID },
{ NULL }
};
static const mozilla::Module kSysPrefModule = {
mozilla::Module::kVersion,
kSysPrefCIDs,
kSysPrefContracts,
kSysPrefCategories
};
NSMODULE_DEFN(nsSystemPrefModule) = &kSysPrefModule;

View File

@ -1,45 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* vim:expandtab:shiftwidth=4:tabstop=4:
*/
/* ***** BEGIN LICENSE BLOCK *****
* Version: NPL 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 Sun Microsystems, Inc.
* Portions created by Sun Microsystems are Copyright (C) 2003 Sun
* Microsystems, Inc. All Rights Reserved.
*
* Original Author: Bolian Yin (bolian.yin@sun.com)
*
* 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 NPL, 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 NPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "prlog.h"
extern PRLogModuleInfo *gSysPrefLog;
#define SYSPREF_LOG(args) PR_LOG(gSysPrefLog, PR_LOG_DEBUG, args)

View File

@ -95,14 +95,18 @@ NS_IMPL_CYCLE_COLLECTION_3(mozHunspell,
mEncoder,
mDecoder)
// Memory reporting stuff
// Memory reporting stuff.
static PRInt64 gHunspellAllocatedSize = 0;
void HunspellReportMemoryAllocation(void* ptr) {
gHunspellAllocatedSize += moz_malloc_usable_size(ptr);
// |computedSize| is zero because we don't know what it is.
gHunspellAllocatedSize +=
mozilla::MemoryReporterMallocSizeOfForCounterInc(ptr, 0);
}
void HunspellReportMemoryDeallocation(void* ptr) {
gHunspellAllocatedSize -= moz_malloc_usable_size(ptr);
// |computedSize| is zero because we don't know what it is.
gHunspellAllocatedSize -=
mozilla::MemoryReporterMallocSizeOfForCounterDec(ptr, 0);
}
static PRInt64 HunspellGetCurrentAllocatedSize() {
return gHunspellAllocatedSize;

View File

@ -47,6 +47,7 @@
#include "nsReadableUtils.h"
#include "nsExpirationTracker.h"
#include "nsILanguageAtomService.h"
#include "nsIMemoryReporter.h"
#include "gfxFont.h"
#include "gfxPlatform.h"
@ -1182,8 +1183,8 @@ gfxFont::Draw(gfxTextRun *aTextRun, PRUint32 aStart, PRUint32 aEnd,
// synthetic-bold strikes are each offset one device pixel in run direction
// (these values are only needed if IsSyntheticBold() is true)
double synBoldOnePixelOffset;
PRInt32 strikes;
double synBoldOnePixelOffset = 0;
PRInt32 strikes = 0;
if (IsSyntheticBold()) {
double xscale = CalcXScale(aContext);
synBoldOnePixelOffset = direction * xscale;
@ -4480,21 +4481,15 @@ gfxTextRun::ClusterIterator::ClusterAdvance(PropertyProvider *aProvider) const
return mTextRun->GetAdvanceWidth(mCurrentChar, ClusterLength(), aProvider);
}
PRUint64
gfxTextRun::ComputeSize()
size_t
gfxTextRun::SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf)
{
PRUint64 total = moz_malloc_usable_size(this);
if (total == 0) {
total = sizeof(gfxTextRun);
}
PRUint64 glyphDataSize = moz_malloc_usable_size(mCharacterGlyphs);
if (glyphDataSize == 0) {
// calculate how much gfxTextRun::AllocateStorage would have allocated
glyphDataSize = sizeof(CompressedGlyph) *
GlyphStorageAllocCount(mCharacterCount, mFlags);
}
total += glyphDataSize;
// The second arg is how much gfxTextRun::AllocateStorage would have
// allocated.
size_t total =
aMallocSizeOf(mCharacterGlyphs,
sizeof(CompressedGlyph) *
GlyphStorageAllocCount(mCharacterCount, mFlags));
if (mDetailedGlyphs) {
total += mDetailedGlyphs->SizeOf();
@ -4505,6 +4500,13 @@ gfxTextRun::ComputeSize()
return total;
}
size_t
gfxTextRun::SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf)
{
return aMallocSizeOf(this, sizeof(gfxTextRun)) +
SizeOfExcludingThis(aMallocSizeOf);
}
#ifdef DEBUG
void

View File

@ -2048,16 +2048,20 @@ public:
// return storage used by this run, for memory reporter;
// nsTransformedTextRun needs to override this as it holds additional data
virtual PRUint64 ComputeSize();
virtual NS_MUST_OVERRIDE size_t
SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf);
virtual NS_MUST_OVERRIDE size_t
SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf);
void AccountForSize(PRUint64* aTotal) {
// Get the size, if it hasn't already been gotten, marking as it goes.
size_t MaybeSizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) {
if (mFlags & gfxTextRunFactory::TEXT_RUN_SIZE_ACCOUNTED) {
return;
return 0;
}
mFlags |= gfxTextRunFactory::TEXT_RUN_SIZE_ACCOUNTED;
*aTotal += ComputeSize();
return SizeOfIncludingThis(aMallocSizeOf);
}
void ClearSizeAccounted() {
void ResetSizeOfAccountingFlags() {
mFlags &= ~gfxTextRunFactory::TEXT_RUN_SIZE_ACCOUNTED;
}

View File

@ -42,7 +42,7 @@
#include "prtypes.h"
#include "prlog.h"
#include "nsTArray.h"
#include "nsString.h"
#include "nsStringGlue.h"
#include "nsIObserver.h"
#include "gfxTypes.h"

View File

@ -135,7 +135,8 @@ public:
#endif
}
void ComputeStorage(PRUint64 *aTotal);
size_t MaybeSizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf);
void ResetSizeOfAccountingFlags();
#ifdef DEBUG
PRUint32 mGeneration;
@ -219,10 +220,10 @@ protected:
PRUint32 aEnd, PRUint32 aHash);
void Uninit();
static PLDHashOperator AccountForStorage(CacheHashEntry *aEntry,
void *aUserData);
static PLDHashOperator ClearSizeAccounted(CacheHashEntry *aEntry,
void *aUserData);
static PLDHashOperator MaybeSizeOfEntry(CacheHashEntry *aEntry,
void *aUserData);
static PLDHashOperator ResetSizeOfEntryAccountingFlags(CacheHashEntry *aEntry,
void *aUserData);
nsTHashtable<CacheHashEntry> mCache;
@ -914,36 +915,48 @@ TextRunWordCache::RemoveTextRun(gfxTextRun *aTextRun)
#endif
}
struct SizeOfEntryData {
nsMallocSizeOfFun mMallocSizeOf;
size_t mTotal;
SizeOfEntryData(nsMallocSizeOfFun mallocSizeOf)
: mMallocSizeOf(mallocSizeOf), mTotal(0) { }
};
/*static*/ PLDHashOperator
TextRunWordCache::AccountForStorage(CacheHashEntry *aEntry, void *aUserData)
TextRunWordCache::MaybeSizeOfEntry(CacheHashEntry *aEntry, void *aUserData)
{
gfxTextRun *run = aEntry->mTextRun;
if (run) {
PRUint64 *total = static_cast<PRUint64*>(aUserData);
run->AccountForSize(total);
SizeOfEntryData *data = static_cast<SizeOfEntryData*>(aUserData);
data->mTotal += run->MaybeSizeOfIncludingThis(data->mMallocSizeOf);
}
return PL_DHASH_NEXT;
}
/*static*/ PLDHashOperator
TextRunWordCache::ClearSizeAccounted(CacheHashEntry *aEntry, void *)
TextRunWordCache::ResetSizeOfEntryAccountingFlags(CacheHashEntry *aEntry, void *)
{
gfxTextRun *run = aEntry->mTextRun;
if (run) {
run->ClearSizeAccounted();
run->ResetSizeOfAccountingFlags();
}
return PL_DHASH_NEXT;
}
size_t
TextRunWordCache::MaybeSizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf)
{
size_t total = mCache.ShallowSizeOfExcludingThis(aMallocSizeOf);
SizeOfEntryData data(aMallocSizeOf);
mCache.EnumerateEntries(MaybeSizeOfEntry, &data);
total += data.mTotal;
return total;
}
void
TextRunWordCache::ComputeStorage(PRUint64 *aTotal)
TextRunWordCache::ResetSizeOfAccountingFlags()
{
if (aTotal) {
*aTotal += mCache.SizeOf();
mCache.EnumerateEntries(AccountForStorage, aTotal);
} else {
mCache.EnumerateEntries(ClearSizeAccounted, nsnull);
}
mCache.EnumerateEntries(ResetSizeOfEntryAccountingFlags, nsnull);
}
static bool
@ -1101,12 +1114,20 @@ gfxTextRunWordCache::Flush()
gTextRunWordCache->Flush();
}
void
gfxTextRunWordCache::ComputeStorage(PRUint64 *aTotal)
size_t
gfxTextRunWordCache::MaybeSizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf)
{
if (!gTextRunWordCache) {
return;
return 0;
}
return gTextRunWordCache->MaybeSizeOfExcludingThis(aMallocSizeOf);
}
void
gfxTextRunWordCache::ResetSizeOfAccountingFlags()
{
if (gTextRunWordCache) {
gTextRunWordCache->ResetSizeOfAccountingFlags();
}
gTextRunWordCache->ComputeStorage(aTotal);
}

View File

@ -106,13 +106,16 @@ public:
static void Flush();
/**
* If aTotal is NULL, just clears the TEXT_RUN_MEMORY_ACCOUNTED flag
* on each textRun found.
* If aTotal is non-NULL, adds the storage used for each textRun to the
* total, and sets the TEXT_RUN_MEMORY_ACCOUNTED flag to avoid double-
* accounting. (Runs with this flag already set will be skipped.)
* This adds the storage used for each textRun to the total, and sets the
* TEXT_RUN_MEMORY_ACCOUNTED flag to avoid double- accounting. (Runs with
* this flag already set will be skipped.)
*/
static void ComputeStorage(PRUint64 *aTotal);
static size_t MaybeSizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf);
/**
* This clears the TEXT_RUN_MEMORY_ACCOUNTED flag on each textRun found.
*/
static void ResetSizeOfAccountingFlags();
protected:
friend class gfxPlatform;

View File

@ -399,10 +399,15 @@ nsBMPDecoder::WriteInternal(const char* aBuffer, PRUint32 aCount)
break;
case 2:
mColors[colorNum].red = *aBuffer;
colorNum++;
// If there is no padding byte, increment the color index
// since we're done with the current color.
if (bytesPerColor == 3)
colorNum++;
break;
case 3:
// This is a padding byte
// This is a padding byte only in Windows BMPs. Increment
// the color index since we're done with the current color.
colorNum++;
break;
}
mPos++; aBuffer++; aCount--;

View File

@ -20,7 +20,8 @@ void NotifyEvent();
namespace base {
MessagePumpForUI::MessagePumpForUI()
: pump(*this)
: state_(NULL)
, pump(*this)
{
}

View File

@ -653,14 +653,12 @@ class HashTable : private AllocPolicy
return gen;
}
/*
* This counts the HashTable's |table| array. If |countMe| is true it also
* counts the HashTable object itself.
*/
size_t sizeOf(JSUsableSizeFun usf, bool countMe) const {
size_t usable = usf(table) + (countMe ? usf((void*)this) : 0);
return usable ? usable
: (capacity() * sizeof(Entry)) + (countMe ? sizeof(HashTable) : 0);
size_t sizeOfExcludingThis(JSMallocSizeOfFun mallocSizeOf) const {
return mallocSizeOf(table, capacity() * sizeof(Entry));
}
size_t sizeOfIncludingThis(JSMallocSizeOfFun mallocSizeOf) const {
return mallocSizeOf(this, sizeof(HashTable)) + sizeOfExcludingThis(mallocSizeOf);
}
Ptr lookup(const Lookup &l) const {
@ -1097,7 +1095,16 @@ class HashMap
Range all() const { return impl.all(); }
size_t count() const { return impl.count(); }
size_t capacity() const { return impl.capacity(); }
size_t sizeOf(JSUsableSizeFun usf, bool cm) const { return impl.sizeOf(usf, cm); }
size_t sizeOfExcludingThis(JSMallocSizeOfFun mallocSizeOf) const {
return impl.sizeOfExcludingThis(mallocSizeOf);
}
size_t sizeOfIncludingThis(JSMallocSizeOfFun mallocSizeOf) const {
/*
* Don't just call |impl.sizeOfExcludingThis()| because there's no
* guarantee that |impl| is the first field in HashMap.
*/
return mallocSizeOf(this, sizeof(*this)) + impl.sizeOfExcludingThis(mallocSizeOf);
}
/*
* Typedef for the enumeration class. An Enum may be used to examine and
@ -1298,7 +1305,16 @@ class HashSet
Range all() const { return impl.all(); }
size_t count() const { return impl.count(); }
size_t capacity() const { return impl.capacity(); }
size_t sizeOf(JSUsableSizeFun usf, bool cm) const { return impl.sizeOf(usf, cm); }
size_t sizeOfExcludingThis(JSMallocSizeOfFun mallocSizeOf) const {
return impl.sizeOfExcludingThis(mallocSizeOf);
}
size_t sizeOfIncludingThis(JSMallocSizeOfFun mallocSizeOf) const {
/*
* Don't just call |impl.sizeOfExcludingThis()| because there's no
* guarantee that |impl| is the first field in HashSet.
*/
return mallocSizeOf(this, sizeof(*this)) + impl.sizeOfExcludingThis(mallocSizeOf);
}
/*
* Typedef for the enumeration class. An Enum may be used to examine and

View File

@ -895,11 +895,9 @@ RoundUpPow2(size_t x)
#endif /* defined(__cplusplus) */
/*
* This signature is for malloc_usable_size-like functions used to measure
* memory usage. A return value of zero indicates that the size is unknown,
* and so a fall-back computation should be done for the size.
* This is SpiderMonkey's equivalent to |nsMallocSizeOfFun|.
*/
typedef size_t(*JSUsableSizeFun)(void *p);
typedef size_t(*JSMallocSizeOfFun)(const void *p, size_t computedSize);
/* sixgill annotation defines */
#ifndef HAVE_STATIC_ANNOTATIONS

1
js/src/aclocal.m4 vendored
View File

@ -8,6 +8,7 @@ builtin(include, build/autoconf/nspr.m4)dnl
builtin(include, build/autoconf/altoptions.m4)dnl
builtin(include, build/autoconf/moznbytetype.m4)dnl
builtin(include, build/autoconf/mozprog.m4)dnl
builtin(include, build/autoconf/mozheader.m4)dnl
builtin(include, build/autoconf/acwinpaths.m4)dnl
builtin(include, build/autoconf/lto.m4)dnl
builtin(include, build/autoconf/gcc-pr49911.m4)dnl

View File

@ -0,0 +1,66 @@
dnl ***** BEGIN LICENSE BLOCK *****
dnl Version: MPL 1.1/GPL 2.0/LGPL 2.1
dnl
dnl The contents of this file are subject to the Mozilla Public License Version
dnl 1.1 (the "License"); you may not use this file except in compliance with
dnl the License. You may obtain a copy of the License at
dnl http://www.mozilla.org/MPL/
dnl
dnl Software distributed under the License is distributed on an "AS IS" basis,
dnl WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
dnl for the specific language governing rights and limitations under the
dnl License.
dnl
dnl The Original Code is mozilla.org code.
dnl
dnl The Initial Developer of the Original Code is the
dnl Mozilla Foundation <http://www.mozilla.org>
dnl
dnl Portions created by the Initial Developer are Copyright (C) 2009
dnl the Initial Developer. All Rights Reserved.
dnl
dnl Contributor(s):
dnl Neil Rashbrook <neil@parkwaycc.co.uk>
dnl
dnl Alternatively, the contents of this file may be used under the terms of
dnl either of the GNU General Public License Version 2 or later (the "GPL"),
dnl or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
dnl in which case the provisions of the GPL or the LGPL are applicable instead
dnl of those above. If you wish to allow use of your version of this file only
dnl under the terms of either the GPL or the LGPL, and not to allow others to
dnl use your version of this file under the terms of the MPL, indicate your
dnl decision by deleting the provisions above and replace them with the notice
dnl and other provisions required by the GPL or the LGPL. If you do not delete
dnl the provisions above, a recipient may use your version of this file under
dnl the terms of any one of the MPL, the GPL or the LGPL.
dnl
dnl ***** END LICENSE BLOCK *****
dnl MOZ_CHECK_HEADER(HEADER-FILE, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND [, INCLUDES]]])
AC_DEFUN([MOZ_CHECK_HEADER],
[ dnl Do the transliteration at runtime so arg 1 can be a shell variable.
ac_safe=`echo "$1" | sed 'y%./+-%__p_%'`
AC_MSG_CHECKING([for $1])
AC_CACHE_VAL(ac_cv_header_$ac_safe,
[ AC_TRY_COMPILE([$4
#include <$1>], ,
eval "ac_cv_header_$ac_safe=yes",
eval "ac_cv_header_$ac_safe=no") ])
if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
AC_MSG_RESULT(yes)
ifelse([$2], , :, [$2])
else
AC_MSG_RESULT(no)
ifelse([$3], , , [$3])
fi
])
dnl MOZ_CHECK_HEADERS(HEADER-FILE... [, ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND [, INCLUDES]]])
AC_DEFUN([MOZ_CHECK_HEADERS],
[ for ac_hdr in $1
do
MOZ_CHECK_HEADER($ac_hdr,
[ ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'`
AC_DEFINE_UNQUOTED($ac_tr_hdr) $2], $3, [$4])
done
])

View File

@ -803,7 +803,7 @@ case "$target" in
# Identify which version of the SDK we're building with
# Windows Server 2008 and newer SDKs have WinSDKVer.h, get the version
# from there
AC_CHECK_HEADERS([winsdkver.h])
MOZ_CHECK_HEADERS([winsdkver.h])
if test "$ac_cv_header_winsdkver_h" = "yes"; then
# Get the highest _WIN32_WINNT and NTDDI versions supported
# Take the higher of the two
@ -830,7 +830,7 @@ EOF
else
# The Vista SDK is the only one to have sdkddkver.h but not
# WinSDKVer.h
AC_CHECK_HEADERS([sdkddkver.h])
MOZ_CHECK_HEADERS([sdkddkver.h])
if test "$ac_cv_header_sdkddkver_h" = "yes"; then
MOZ_WINSDK_MAXVER=0x06000000
else
@ -1190,7 +1190,7 @@ tools are selected during the Xcode/Developer Tools installation.])
CFLAGS="$CFLAGS -isysroot ${MACOS_SDK_DIR}"
CXXFLAGS="$CXXFLAGS -isysroot ${MACOS_SDK_DIR}"
dnl CPP/CXXCPP needs to be set for AC_CHECK_HEADER.
dnl CPP/CXXCPP needs to be set for MOZ_CHECK_HEADER.
CPP="$CPP -isysroot ${MACOS_SDK_DIR}"
CXXCPP="$CXXCPP -isysroot ${MACOS_SDK_DIR}"
@ -2164,7 +2164,7 @@ case "$target" in
;;
esac
if test "$COMPILE_ENVIRONMENT"; then
AC_CHECK_HEADERS(sys/inttypes.h)
MOZ_CHECK_HEADERS(sys/inttypes.h)
fi
AC_DEFINE(JS_SYS_TYPES_H_DEFINES_EXACT_SIZE_TYPES)
AC_DEFINE(NSCAP_DISABLE_DEBUG_PTR_TYPES)
@ -2501,7 +2501,7 @@ ia64*-hpux*)
CXXFLAGS="$CXXFLAGS -mstackrealign"
fi
AC_CHECK_HEADERS(mmintrin.h)
MOZ_CHECK_HEADERS(mmintrin.h)
AC_DEFINE(_X86_)
;;
x86_64-*)
@ -2926,7 +2926,7 @@ dnl ========================================================
dnl Once this is working, we can delete the code for int16_t,
dnl etc. below.
AC_CHECK_HEADER(stdint.h)
MOZ_CHECK_HEADER(stdint.h)
if test "$ac_cv_header_stdint_h" = yes; then
AC_DEFINE(JS_HAVE_STDINT_H)
else
@ -2954,12 +2954,12 @@ fi
MOZ_ALIGN_OF_TYPE(JS_ALIGN_OF_POINTER, void*, 2 4 8 16)
MOZ_SIZE_OF_TYPE(JS_BYTES_PER_DOUBLE, double, 6 8 10 12 14)
AC_CHECK_HEADERS(endian.h)
MOZ_CHECK_HEADERS(endian.h)
if test "$ac_cv_header_endian_h" = yes; then
AC_DEFINE(JS_HAVE_ENDIAN_H)
fi
AC_CHECK_HEADERS(sys/isa_defs.h)
MOZ_CHECK_HEADERS(sys/isa_defs.h)
if test "$ac_cv_header_sys_isa_defs_h" = yes; then
AC_DEFINE(JS_HAVE_SYS_ISA_DEFS_H)
fi
@ -3248,30 +3248,30 @@ freebsd*)
CPPFLAGS="${CPPFLAGS} ${X_CFLAGS}"
;;
esac
AC_CHECK_HEADERS(sys/byteorder.h compat.h getopt.h)
AC_CHECK_HEADERS(sys/bitypes.h memory.h unistd.h)
AC_CHECK_HEADERS(gnu/libc-version.h nl_types.h)
AC_CHECK_HEADERS(malloc.h)
AC_CHECK_HEADERS(X11/XKBlib.h)
AC_CHECK_HEADERS(io.h)
MOZ_CHECK_HEADERS(sys/byteorder.h compat.h getopt.h)
MOZ_CHECK_HEADERS(sys/bitypes.h memory.h unistd.h)
MOZ_CHECK_HEADERS(gnu/libc-version.h nl_types.h)
MOZ_CHECK_HEADERS(malloc.h)
MOZ_CHECK_HEADERS(X11/XKBlib.h)
MOZ_CHECK_HEADERS(io.h)
dnl These are all the places some variant of statfs can be hiding.
AC_CHECK_HEADERS(sys/statvfs.h sys/statfs.h sys/vfs.h sys/mount.h)
MOZ_CHECK_HEADERS(sys/statvfs.h sys/statfs.h sys/vfs.h sys/mount.h)
dnl Quota support
AC_CHECK_HEADERS(sys/quota.h)
AC_CHECK_HEADERS(linux/quota.h)
MOZ_CHECK_HEADERS(sys/quota.h)
MOZ_CHECK_HEADERS(linux/quota.h)
dnl Try for MMX support
dnl NB - later gcc versions require -mmmx for this header to be successfully
dnl included (or another option which implies it, such as -march=pentium-mmx)
AC_CHECK_HEADERS(mmintrin.h)
MOZ_CHECK_HEADERS(mmintrin.h)
dnl Check whether the compiler supports the new-style C++ standard
dnl library headers (i.e. <new>) or needs the old "new.h"
AC_LANG_CPLUSPLUS
NEW_H=new.h
AC_CHECK_HEADER(new, [NEW_H=new])
MOZ_CHECK_HEADER(new, [NEW_H=new])
AC_DEFINE_UNQUOTED(NEW_H, <$NEW_H>)
AC_LANG_C
@ -3279,7 +3279,7 @@ AC_ARG_ENABLE(dtrace,
[ --enable-dtrace build with dtrace support if available (default=no)],
[enable_dtrace="yes"],)
if test "x$enable_dtrace" = "xyes"; then
AC_CHECK_HEADER(sys/sdt.h, HAVE_DTRACE=1)
MOZ_CHECK_HEADER(sys/sdt.h, HAVE_DTRACE=1)
if test -n "$HAVE_DTRACE"; then
AC_DEFINE(INCLUDE_MOZILLA_DTRACE)
else
@ -3292,12 +3292,12 @@ case $target in
*-aix4.3*|*-aix5*)
;;
*)
AC_CHECK_HEADERS(sys/cdefs.h)
MOZ_CHECK_HEADERS(sys/cdefs.h)
;;
esac
dnl Performance measurement headers.
AC_CHECK_HEADER(linux/perf_event.h,
MOZ_CHECK_HEADER(linux/perf_event.h,
[AC_CACHE_CHECK(for perf_event_open system call,ac_cv_perf_event_open,
[AC_TRY_COMPILE([#include <sys/syscall.h>],[return sizeof(__NR_perf_event_open);],
ac_cv_perf_event_open=yes,
@ -3332,7 +3332,7 @@ case $target in
;;
*)
AC_SEARCH_LIBS(dlopen, dl,
AC_CHECK_HEADER(dlfcn.h,
MOZ_CHECK_HEADER(dlfcn.h,
AC_DEFINE(HAVE_DLOPEN)))
;;
esac
@ -3905,11 +3905,11 @@ fi
dnl Check for the existence of various allocation headers/functions
MALLOC_H=
AC_CHECK_HEADER(malloc.h, [MALLOC_H=malloc.h])
MOZ_CHECK_HEADER(malloc.h, [MALLOC_H=malloc.h])
if test "$MALLOC_H" = ""; then
AC_CHECK_HEADER(malloc/malloc.h, [MALLOC_H=malloc/malloc.h])
MOZ_CHECK_HEADER(malloc/malloc.h, [MALLOC_H=malloc/malloc.h])
if test "$MALLOC_H" = ""; then
AC_CHECK_HEADER(sys/malloc.h, [MALLOC_H=sys/malloc.h])
MOZ_CHECK_HEADER(sys/malloc.h, [MALLOC_H=sys/malloc.h])
fi
fi
if test "$MALLOC_H" != ""; then
@ -4462,7 +4462,7 @@ MOZ_ARG_ENABLE_BOOL(valgrind,
MOZ_VALGRIND=1,
MOZ_VALGRIND= )
if test -n "$MOZ_VALGRIND"; then
AC_CHECK_HEADER([valgrind/valgrind.h], [],
MOZ_CHECK_HEADER([valgrind/valgrind.h], [],
AC_MSG_ERROR(
[--enable-valgrind specified but Valgrind is not installed]))
AC_DEFINE(MOZ_VALGRIND)
@ -4667,7 +4667,7 @@ dnl ========================================================
dnl = Support for gcc stack unwinding (from gcc 3.3)
dnl ========================================================
if test -z "$SKIP_LIBRARY_CHECKS"; then
AC_CHECK_HEADER(unwind.h, AC_CHECK_FUNCS(_Unwind_Backtrace))
MOZ_CHECK_HEADER(unwind.h, AC_CHECK_FUNCS(_Unwind_Backtrace))
fi
dnl ========================================================

View File

@ -111,9 +111,8 @@ class BumpChunk
void setNext(BumpChunk *succ) { next_ = succ; }
size_t used() const { return bump - bumpBase(); }
size_t sizeOf(JSUsableSizeFun usf) {
size_t usable = usf((void*)this);
return usable ? usable : limit - headerBase();
size_t sizeOfIncludingThis(JSMallocSizeOfFun mallocSizeOf) {
return mallocSizeOf(this, limit - headerBase());
}
void resetBump() {
@ -294,22 +293,23 @@ class LifoAlloc
return accum;
}
/* Get the total size of the arena chunks (including unused space), plus,
* if |countMe| is true, the size of the LifoAlloc itself. */
size_t sizeOf(JSUsableSizeFun usf, bool countMe) const {
/* Get the total size of the arena chunks (including unused space). */
size_t sizeOfExcludingThis(JSMallocSizeOfFun mallocSizeOf) const {
size_t accum = 0;
if (countMe) {
size_t usable = usf((void*)this);
accum += usable ? usable : sizeof(LifoAlloc);
}
BumpChunk *it = first;
while (it) {
accum += it->sizeOf(usf);
accum += it->sizeOfIncludingThis(mallocSizeOf);
it = it->next();
}
return accum;
}
/* Like sizeOfExcludingThis(), but includes the size of the LifoAlloc itself. */
size_t sizeOfIncludingThis(JSMallocSizeOfFun mallocSizeOf) const {
return mallocSizeOf(this, sizeof(LifoAlloc)) +
sizeOfExcludingThis(mallocSizeOf);
}
/* Doesn't perform construction; useful for lazily-initialized POD types. */
template <typename T>
JS_ALWAYS_INLINE

View File

@ -5757,9 +5757,7 @@ frontend::EmitTree(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
JSOp op;
uint32 argc;
EmitLevelManager elm(bce);
#if JS_HAS_SHARP_VARS
jsint sharpnum;
#endif
jsint sharpnum = -1;
JS_CHECK_RECURSION(cx, return JS_FALSE);

View File

@ -116,12 +116,12 @@ typedef struct TypeInferenceMemoryStats
extern JS_FRIEND_API(void)
JS_GetTypeInferenceMemoryStats(JSContext *cx, JSCompartment *compartment,
TypeInferenceMemoryStats *stats,
JSUsableSizeFun usf);
JSMallocSizeOfFun mallocSizeOf);
extern JS_FRIEND_API(void)
JS_GetTypeInferenceObjectStats(/*TypeObject*/ void *object,
TypeInferenceMemoryStats *stats,
JSUsableSizeFun usf);
JSMallocSizeOfFun mallocSizeOf);
extern JS_FRIEND_API(JSPrincipals *)
JS_GetCompartmentPrincipals(JSCompartment *compartment);

View File

@ -1312,9 +1312,6 @@ typedef struct JSPtrTable {
void **array;
} JSPtrTable;
extern JSBool
js_RegisterCloseableIterator(JSContext *cx, JSObject *obj);
extern JSBool
js_LockGCThingRT(JSRuntime *rt, void *thing);

View File

@ -6150,8 +6150,8 @@ TypeSet::dynamicSize()
{
/*
* This memory is allocated within the temp pool (but accounted for
* elsewhere) so we can't use a JSUsableSizeFun to measure it. We must do
* it analytically.
* elsewhere) so we can't use a JSMallocSizeOfFun to measure it. We must
* do it analytically.
*/
uint32 count = baseObjectCount();
if (count >= 2)
@ -6164,8 +6164,8 @@ TypeObject::dynamicSize()
{
/*
* This memory is allocated within the temp pool (but accounted for
* elsewhere) so we can't use a JSUsableSizeFun to measure it. We must do
* it analytically.
* elsewhere) so we can't use a JSMallocSizeOfFun to measure it. We must
* do it analytically.
*/
size_t bytes = 0;
@ -6184,32 +6184,26 @@ TypeObject::dynamicSize()
}
static void
GetScriptMemoryStats(JSScript *script, TypeInferenceMemoryStats *stats, JSUsableSizeFun usf)
GetScriptMemoryStats(JSScript *script, TypeInferenceMemoryStats *stats, JSMallocSizeOfFun mallocSizeOf)
{
TypeScript *typeScript = script->types;
if (!typeScript)
return;
size_t usable;
/* If TI is disabled, a single TypeScript is still present. */
if (!script->compartment()->types.inferenceEnabled) {
usable = usf(typeScript);
stats->scripts += usable ? usable : sizeof(TypeScript);
stats->scripts += mallocSizeOf(typeScript, sizeof(TypeScript));
return;
}
usable = usf(typeScript->nesting);
stats->scripts += usable ? usable : sizeof(TypeScriptNesting);
stats->scripts += mallocSizeOf(typeScript->nesting, sizeof(TypeScriptNesting));
unsigned count = TypeScript::NumTypeSets(script);
usable = usf(typeScript);
stats->scripts += usable ? usable : sizeof(TypeScript) + count * sizeof(TypeSet);
stats->scripts += mallocSizeOf(typeScript, sizeof(TypeScript) + count * sizeof(TypeSet));
TypeResult *result = typeScript->dynamicList;
while (result) {
usable = usf(result);
stats->scripts += usable ? usable : sizeof(TypeResult);
stats->scripts += mallocSizeOf(result, sizeof(TypeResult));
result = result->next;
}
@ -6227,35 +6221,35 @@ GetScriptMemoryStats(JSScript *script, TypeInferenceMemoryStats *stats, JSUsable
JS_FRIEND_API(void)
JS_GetTypeInferenceMemoryStats(JSContext *cx, JSCompartment *compartment,
TypeInferenceMemoryStats *stats, JSUsableSizeFun usf)
TypeInferenceMemoryStats *stats,
JSMallocSizeOfFun mallocSizeOf)
{
/*
* Note: not all data in the pool is temporary, and some will survive GCs
* by being copied to the replacement pool. This memory will be counted
* elsewhere and deducted from the amount of temporary data.
*/
stats->temporary += compartment->typeLifoAlloc.sizeOf(usf, /* countMe = */false);
stats->temporary += compartment->typeLifoAlloc.sizeOfExcludingThis(mallocSizeOf);
/* Pending arrays are cleared on GC along with the analysis pool. */
size_t usable = usf(compartment->types.pendingArray);
stats->temporary +=
usable ? usable
: sizeof(TypeCompartment::PendingWork) * compartment->types.pendingCapacity;
mallocSizeOf(compartment->types.pendingArray,
sizeof(TypeCompartment::PendingWork) * compartment->types.pendingCapacity);
/* TypeCompartment::pendingRecompiles is non-NULL only while inference code is running. */
JS_ASSERT(!compartment->types.pendingRecompiles);
for (gc::CellIter i(cx, compartment, gc::FINALIZE_SCRIPT); !i.done(); i.next())
GetScriptMemoryStats(i.get<JSScript>(), stats, usf);
GetScriptMemoryStats(i.get<JSScript>(), stats, mallocSizeOf);
if (compartment->types.allocationSiteTable)
stats->tables += compartment->types.allocationSiteTable->sizeOf(usf, /* countMe = */true);
stats->tables += compartment->types.allocationSiteTable->sizeOfIncludingThis(mallocSizeOf);
if (compartment->types.arrayTypeTable)
stats->tables += compartment->types.arrayTypeTable->sizeOf(usf, /* countMe = */true);
stats->tables += compartment->types.arrayTypeTable->sizeOfIncludingThis(mallocSizeOf);
if (compartment->types.objectTypeTable) {
stats->tables += compartment->types.objectTypeTable->sizeOf(usf, /* countMe = */true);
stats->tables += compartment->types.objectTypeTable->sizeOfIncludingThis(mallocSizeOf);
for (ObjectTypeTable::Enum e(*compartment->types.objectTypeTable);
!e.empty();
@ -6265,14 +6259,14 @@ JS_GetTypeInferenceMemoryStats(JSContext *cx, JSCompartment *compartment,
const ObjectTableEntry &value = e.front().value;
/* key.ids and values.types have the same length. */
usable = usf(key.ids) + usf(value.types);
stats->tables += usable ? usable : key.nslots * (sizeof(jsid) + sizeof(Type));
stats->tables += mallocSizeOf(key.ids, key.nslots * sizeof(jsid)) +
mallocSizeOf(value.types, key.nslots * sizeof(Type));
}
}
}
JS_FRIEND_API(void)
JS_GetTypeInferenceObjectStats(void *object_, TypeInferenceMemoryStats *stats, JSUsableSizeFun usf)
JS_GetTypeInferenceObjectStats(void *object_, TypeInferenceMemoryStats *stats, JSMallocSizeOfFun mallocSizeOf)
{
TypeObject *object = (TypeObject *) object_;
@ -6288,23 +6282,19 @@ JS_GetTypeInferenceObjectStats(void *object_, TypeInferenceMemoryStats *stats, J
if (object->newScript) {
/* The initializerList is tacked onto the end of the TypeNewScript. */
size_t usable = usf(object->newScript);
if (usable) {
stats->objects += usable;
} else {
stats->objects += sizeof(TypeNewScript);
for (TypeNewScript::Initializer *init = object->newScript->initializerList; ; init++) {
stats->objects += sizeof(TypeNewScript::Initializer);
if (init->kind == TypeNewScript::Initializer::DONE)
break;
}
size_t computedSize = sizeof(TypeNewScript);
for (TypeNewScript::Initializer *init = object->newScript->initializerList; ; init++) {
computedSize += sizeof(TypeNewScript::Initializer);
if (init->kind == TypeNewScript::Initializer::DONE)
break;
}
stats->objects += mallocSizeOf(object->newScript, computedSize);
}
if (object->emptyShapes) {
size_t usable = usf(object->emptyShapes);
stats->emptyShapes +=
usable ? usable : sizeof(EmptyShape*) * gc::FINALIZE_OBJECT_LIMIT;
mallocSizeOf(object->emptyShapes,
sizeof(EmptyShape*) * gc::FINALIZE_OBJECT_LIMIT);
}
/*

View File

@ -2382,38 +2382,6 @@ END_CASE(JSOP_PICK)
} \
JS_END_MACRO
/*
* Skip the JSOP_POP typically found after a JSOP_SET* opcode, where oplen is
* the constant length of the SET opcode sequence, and spdec is the constant
* by which to decrease the stack pointer to pop all of the SET op's operands.
*
* NB: unlike macros that could conceivably be replaced by functions (ignoring
* goto error), where a call should not have to be braced in order to expand
* correctly (e.g., in if (cond) FOO(); else BAR()), these three macros lack
* JS_{BEGIN,END}_MACRO brackets. They are also indented so as to align with
* nearby opcode code.
*/
#define SKIP_POP_AFTER_SET(oplen,spdec) \
if (regs.pc[oplen] == JSOP_POP) { \
regs.sp -= spdec; \
regs.pc += oplen + JSOP_POP_LENGTH; \
op = (JSOp) *regs.pc; \
DO_OP(); \
}
#define END_SET_CASE(OP) \
SKIP_POP_AFTER_SET(OP##_LENGTH, 1); \
END_CASE(OP)
#define END_SET_CASE_STORE_RVAL(OP,spdec) \
SKIP_POP_AFTER_SET(OP##_LENGTH, spdec); \
{ \
Value *newsp = regs.sp - ((spdec) - 1); \
newsp[-1] = regs.sp[-1]; \
regs.sp = newsp; \
} \
END_CASE(OP)
BEGIN_CASE(JSOP_SETCONST)
{
JSAtom *atom;
@ -2426,7 +2394,7 @@ BEGIN_CASE(JSOP_SETCONST)
goto error;
}
}
END_SET_CASE(JSOP_SETCONST);
END_CASE(JSOP_SETCONST);
#if JS_HAS_DESTRUCTURING
BEGIN_CASE(JSOP_ENUMCONSTELEM)
@ -2935,17 +2903,23 @@ END_CASE(JSOP_DELELEM)
BEGIN_CASE(JSOP_TOID)
{
/*
* Increment or decrement requires use to lookup the same property twice, but we need to avoid
* the oberservable stringification the second time.
* There must be an object value below the id, which will not be popped
* but is necessary in interning the id for XML.
*/
JSObject *obj;
FETCH_OBJECT(cx, -2, obj);
jsid id;
FETCH_ELEMENT_ID(obj, -1, id);
if (!regs.sp[-1].isInt32())
Value &idval = regs.sp[-1];
if (!idval.isInt32()) {
JSObject *obj;
FETCH_OBJECT(cx, -2, obj);
jsid dummy;
if (!js_InternNonIntElementId(cx, obj, idval, &dummy, &idval))
goto error;
TypeScript::MonitorUnknown(cx, script, regs.pc);
}
}
END_CASE(JSOP_TOID)
@ -3176,7 +3150,6 @@ BEGIN_CASE(JSOP_LOCALINC)
if (JS_LIKELY(vp->isInt32() && CanIncDecWithoutOverflow(tmp = vp->toInt32()))) {
vp->getInt32Ref() = tmp + incr;
JS_ASSERT(JSOP_INCARG_LENGTH == js_CodeSpec[op].length);
SKIP_POP_AFTER_SET(JSOP_INCARG_LENGTH, 0);
PUSH_INT32(tmp + incr2);
} else {
PUSH_COPY(*vp);
@ -3549,8 +3522,11 @@ BEGIN_CASE(JSOP_SETMETHOD)
goto error;
}
} while (0);
regs.sp[-2] = regs.sp[-1];
regs.sp--;
}
END_SET_CASE_STORE_RVAL(JSOP_SETPROP, 2);
END_CASE(JSOP_SETPROP)
BEGIN_CASE(JSOP_GETELEM)
{
@ -3695,9 +3671,11 @@ BEGIN_CASE(JSOP_SETELEM)
rval = regs.sp[-1];
if (!obj->setGeneric(cx, id, &rval, script->strictModeCode))
goto error;
end_setelem:;
end_setelem:
regs.sp[-3] = regs.sp[-1];
regs.sp -= 2;
}
END_SET_CASE_STORE_RVAL(JSOP_SETELEM, 3)
END_CASE(JSOP_SETELEM)
BEGIN_CASE(JSOP_ENUMELEM)
{
@ -4213,7 +4191,7 @@ BEGIN_CASE(JSOP_SETARG)
JS_ASSERT(slot < regs.fp()->numFormalArgs());
argv[slot] = regs.sp[-1];
}
END_SET_CASE(JSOP_SETARG)
END_CASE(JSOP_SETARG)
BEGIN_CASE(JSOP_GETLOCAL)
{
@ -4249,7 +4227,7 @@ BEGIN_CASE(JSOP_SETLOCAL)
JS_ASSERT(slot < script->nslots);
regs.fp()->slots()[slot] = regs.sp[-1];
}
END_SET_CASE(JSOP_SETLOCAL)
END_CASE(JSOP_SETLOCAL)
BEGIN_CASE(JSOP_GETFCSLOT)
BEGIN_CASE(JSOP_CALLFCSLOT)

View File

@ -2708,12 +2708,11 @@ obj_preventExtensions(JSContext *cx, uintN argc, Value *vp)
}
size_t
JSObject::sizeOfSlotsArray(JSUsableSizeFun usf)
JSObject::sizeOfSlotsArray(JSMallocSizeOfFun mallocSizeOf)
{
if (!hasSlotsArray())
return 0;
size_t usable = usf((void *)slots);
return usable ? usable : numSlots() * sizeof(js::Value);
return mallocSizeOf(slots, numDynamicSlots(numSlots()) * sizeof(js::Value));
}
bool
@ -4559,10 +4558,16 @@ JSObject::shrinkSlots(JSContext *cx, size_t newcap)
}
uint32 fill = newcap;
newcap = Max(newcap, size_t(SLOT_CAPACITY_MIN));
newcap = Max(newcap, numFixedSlots());
if (isDenseArray()) {
newcap = Max(newcap, size_t(SLOT_CAPACITY_MIN));
newcap = Max(newcap, numFixedSlots());
} else {
newcap = Max(newcap, numFixedSlots() + SLOT_CAPACITY_MIN);
}
HeapValue *tmpslots = (HeapValue*) cx->realloc_(slots, newcap * sizeof(HeapValue));
uint32 allocCount = numDynamicSlots(newcap);
HeapValue *tmpslots = (HeapValue*) cx->realloc_(slots, allocCount * sizeof(Value));
if (!tmpslots)
return; /* Leave slots at its old size. */

View File

@ -486,7 +486,7 @@ struct JSObject : js::gc::Cell {
jsuword &initializedLength() { return *newType.unsafeGetUnioned(); }
JS_FRIEND_API(size_t) sizeOfSlotsArray(JSUsableSizeFun usf);
JS_FRIEND_API(size_t) sizeOfSlotsArray(JSMallocSizeOfFun mallocSizeOf);
js::HeapPtrObject parent; /* object's parent */
void *privateData; /* private data */

View File

@ -257,9 +257,9 @@ struct PropertyTable {
* This counts the PropertyTable object itself (which must be
* heap-allocated) and its |entries| array.
*/
size_t sizeOf(JSUsableSizeFun usf) const {
size_t usable = usf((void*)this) + usf(entries);
return usable ? usable : sizeOfEntries(capacity()) + sizeof(PropertyTable);
size_t sizeOfIncludingThis(JSMallocSizeOfFun mallocSizeOf) const {
return mallocSizeOf(this, sizeof(PropertyTable)) +
mallocSizeOf(entries, sizeOfEntries(capacity()));
}
/* Whether we need to grow. We want to do this if the load factor is >= 0.75 */
@ -449,15 +449,14 @@ struct Shape : public js::gc::Cell
return table;
}
size_t sizeOfPropertyTable(JSUsableSizeFun usf) const {
return hasTable() ? getTable()->sizeOf(usf) : 0;
size_t sizeOfPropertyTableIncludingThis(JSMallocSizeOfFun mallocSizeOf) const {
return hasTable() ? getTable()->sizeOfIncludingThis(mallocSizeOf) : 0;
}
size_t sizeOfKids(JSUsableSizeFun usf) const {
/* Nb: |countMe| is true because the kids HashTable is on the heap. */
size_t sizeOfKidsIncludingThis(JSMallocSizeOfFun mallocSizeOf) const {
JS_ASSERT(!inDictionary());
return kids.isHash()
? kids.toHash()->sizeOf(usf, /* countMe */true)
? kids.toHash()->sizeOfIncludingThis(mallocSizeOf)
: 0;
}

View File

@ -1273,15 +1273,14 @@ JSScript::dataSize()
}
size_t
JSScript::dataSize(JSUsableSizeFun usf)
JSScript::dataSize(JSMallocSizeOfFun mallocSizeOf)
{
#if JS_SCRIPT_INLINE_DATA_LIMIT
if (data == inlineData)
return 0;
#endif
size_t usable = usf(data);
return usable ? usable : dataSize();
return mallocSizeOf(data, dataSize());
}
/*

View File

@ -660,7 +660,7 @@ struct JSScript : public js::gc::Cell {
}
/* Size of the JITScript and all sections. (This method is implemented in MethodJIT.h.) */
JS_FRIEND_API(size_t) jitDataSize(JSUsableSizeFun usf);
JS_FRIEND_API(size_t) jitDataSize(JSMallocSizeOfFun mallocSizeOf);
#endif
@ -682,9 +682,9 @@ struct JSScript : public js::gc::Cell {
* second is the size of the block allocated to hold all the data sections
* (which can be larger than the in-use size).
*/
JS_FRIEND_API(size_t) dataSize(); /* Size of all data sections */
JS_FRIEND_API(size_t) dataSize(JSUsableSizeFun usf); /* Size of all data sections */
uint32 numNotes(); /* Number of srcnote slots in the srcnotes section */
JS_FRIEND_API(size_t) dataSize(); /* Size of all data sections */
JS_FRIEND_API(size_t) dataSize(JSMallocSizeOfFun mallocSizeOf); /* Size of all data sections */
uint32 numNotes(); /* Number of srcnote slots in the srcnotes section */
/* Script notes are allocated right after the code. */
jssrcnote *notes() { return (jssrcnote *)(code + length); }

View File

@ -1302,22 +1302,21 @@ mjit::JITScript::~JITScript()
}
size_t
JSScript::jitDataSize(JSUsableSizeFun usf)
JSScript::jitDataSize(JSMallocSizeOfFun mallocSizeOf)
{
size_t n = 0;
if (jitNormal)
n += jitNormal->scriptDataSize(usf);
n += jitNormal->scriptDataSize(mallocSizeOf);
if (jitCtor)
n += jitCtor->scriptDataSize(usf);
n += jitCtor->scriptDataSize(mallocSizeOf);
return n;
}
/* Please keep in sync with Compiler::finishThisUp! */
size_t
mjit::JITScript::scriptDataSize(JSUsableSizeFun usf)
mjit::JITScript::scriptDataSize(JSMallocSizeOfFun mallocSizeOf)
{
size_t usable = usf ? usf(this) : 0;
return usable ? usable :
size_t computedSize =
sizeof(JITScript) +
sizeof(NativeMapEntry) * nNmapPairs +
sizeof(InlineFrame) * nInlineFrames +
@ -1334,6 +1333,8 @@ mjit::JITScript::scriptDataSize(JSUsableSizeFun usf)
sizeof(ic::SetElementIC) * nSetElems +
#endif
0;
/* |mallocSizeOf| can be null here. */
return mallocSizeOf ? mallocSizeOf(this, computedSize) : computedSize;
}
void

View File

@ -682,8 +682,8 @@ struct JITScript {
void nukeScriptDependentICs();
/* |usf| can be NULL here, in which case the fallback size computation will be used. */
size_t scriptDataSize(JSUsableSizeFun usf);
/* |mallocSizeOf| can be NULL here, in which case the fallback size computation will be used. */
size_t scriptDataSize(JSMallocSizeOfFun mallocSizeOf);
jsbytecode *nativeToPC(void *returnAddress, CallSite **pinline) const;

View File

@ -3829,9 +3829,9 @@ MJitCodeStats(JSContext *cx, uintN argc, jsval *vp)
#ifdef JS_METHODJIT
static size_t
zero_usable_size(void *p)
computedSize(const void *p, size_t size)
{
return 0;
return size;
}
static void
@ -3842,10 +3842,10 @@ SumJitDataSizeCallback(JSContext *cx, void *data, void *thing,
JS_ASSERT(traceKind == JSTRACE_SCRIPT);
JSScript *script = static_cast<JSScript *>(thing);
/*
* Passing in zero_usable_size causes jitDataSize to fall back to its
* Passing in |computedSize| causes jitDataSize to fall back to its
* secondary size computation.
*/
*sump += script->jitDataSize(zero_usable_size);
*sump += script->jitDataSize(computedSize);
}
#endif

View File

@ -87,7 +87,7 @@ JSLinearString::mark(JSTracer *)
}
size_t
JSString::charsHeapSize(JSUsableSizeFun usf)
JSString::charsHeapSize(JSMallocSizeOfFun mallocSizeOf)
{
/* JSRope: do nothing, we'll count all children chars when we hit the leaf strings. */
if (isRope())
@ -104,8 +104,7 @@ JSString::charsHeapSize(JSUsableSizeFun usf)
/* JSExtensibleString: count the full capacity, not just the used space. */
if (isExtensible()) {
JSExtensibleString &extensible = asExtensible();
size_t usable = usf((void *)extensible.chars());
return usable ? usable : asExtensible().capacity() * sizeof(jschar);
return mallocSizeOf(extensible.chars(), asExtensible().capacity() * sizeof(jschar));
}
JS_ASSERT(isFixed());
@ -118,10 +117,9 @@ JSString::charsHeapSize(JSUsableSizeFun usf)
if (isInline())
return 0;
/* JSAtom, JSFixedString: count the chars. */
/* JSAtom, JSFixedString: count the chars. +1 for the null char. */
JSFixedString &fixed = asFixed();
size_t usable = usf((void *)fixed.chars());
return usable ? usable : length() * sizeof(jschar);
return mallocSizeOf(fixed.chars(), (length() + 1) * sizeof(jschar));
}
static JS_ALWAYS_INLINE bool

View File

@ -407,7 +407,7 @@ class JSString : public js::gc::Cell
/* Gets the number of bytes that the chars take on the heap. */
JS_FRIEND_API(size_t) charsHeapSize(JSUsableSizeFun usf);
JS_FRIEND_API(size_t) charsHeapSize(JSMallocSizeOfFun mallocSizeOf);
/* Offsets for direct field from jit code. */

View File

@ -1046,39 +1046,10 @@ public:
return JSRegExpErrorNoMatch;
}
void lookupForBeginChars()
{
int character;
bool firstSingleCharFound;
while (true) {
if (input.isNotAvailableInput(2))
return;
firstSingleCharFound = false;
character = input.readPair();
for (unsigned i = 0; i < pattern->m_beginChars.size(); ++i) {
BeginChar bc = pattern->m_beginChars[i];
if (!firstSingleCharFound && bc.value <= 0xFFFF) {
firstSingleCharFound = true;
character &= 0xFFFF;
}
if ((character | bc.mask) == bc.value)
return;
}
input.next();
}
}
#define MATCH_NEXT() { ++context->term; goto matchAgain; }
#define BACKTRACK() { --context->term; goto backtrack; }
#define currentTerm() (disjunction->terms[context->term])
JSRegExpResult matchDisjunction(ByteDisjunction* disjunction, DisjunctionContext* context, bool btrack = false, bool isBody = false)
JSRegExpResult matchDisjunction(ByteDisjunction* disjunction, DisjunctionContext* context, bool btrack = false)
{
if (!--remainingMatchCount)
return JSRegExpErrorHitLimit;
@ -1086,9 +1057,6 @@ public:
if (btrack)
BACKTRACK();
if (pattern->m_containsBeginChars && isBody)
lookupForBeginChars();
context->matchBegin = input.getPos();
context->term = 0;
@ -1266,9 +1234,6 @@ public:
input.next();
if (pattern->m_containsBeginChars && isBody)
lookupForBeginChars();
context->matchBegin = input.getPos();
if (currentTerm().alternative.onceThrough)
@ -1397,7 +1362,7 @@ public:
DisjunctionContext* context = allocDisjunctionContext(pattern->m_body.get());
JSRegExpResult result = matchDisjunction(pattern->m_body.get(), context, false, true);
JSRegExpResult result = matchDisjunction(pattern->m_body.get(), context, false);
if (result == JSRegExpMatch) {
output[0] = context->matchBegin;
output[1] = context->matchEnd;

View File

@ -335,7 +335,6 @@ public:
: m_body(body)
, m_ignoreCase(pattern.m_ignoreCase)
, m_multiline(pattern.m_multiline)
, m_containsBeginChars(pattern.m_containsBeginChars)
, m_allocator(allocator)
{
newlineCharacterClass = pattern.newlineCharacterClass();
@ -347,8 +346,6 @@ public:
// array, so that it won't delete them on destruction. We'll
// take responsibility for that.
pattern.m_userCharacterClasses.clear();
m_beginChars.append(pattern.m_beginChars);
}
~BytecodePattern()
@ -360,7 +357,6 @@ public:
OwnPtr<ByteDisjunction> m_body;
bool m_ignoreCase;
bool m_multiline;
bool m_containsBeginChars;
// Each BytecodePattern is associated with a RegExp, each RegExp is associated
// with a JSGlobalData. Cache a pointer to out JSGlobalData's m_regExpAllocator.
BumpPointerAllocator* m_allocator;
@ -368,8 +364,6 @@ public:
CharacterClass* newlineCharacterClass;
CharacterClass* wordcharCharacterClass;
Vector<BeginChar> m_beginChars;
private:
Vector<ByteDisjunction*> m_allParenthesesInfo;
Vector<CharacterClass*> m_userCharacterClasses;

View File

@ -242,117 +242,11 @@ private:
Vector<CharacterRange> m_rangesUnicode;
};
struct BeginCharHelper {
BeginCharHelper(Vector<BeginChar>* beginChars, bool isCaseInsensitive = false)
: m_beginChars(beginChars)
, m_isCaseInsensitive(isCaseInsensitive)
{}
void addBeginChar(BeginChar beginChar, Vector<TermChain>* hotTerms, QuantifierType quantityType, unsigned quantityCount)
{
if (quantityType == QuantifierFixedCount && quantityCount > 1) {
// We duplicate the first found character if the quantity of the term is more than one. eg.: /a{3}/
beginChar.value |= beginChar.value << 16;
beginChar.mask |= beginChar.mask << 16;
addCharacter(beginChar);
} else if (quantityType == QuantifierFixedCount && quantityCount == 1 && hotTerms->size())
// In case of characters with fixed quantifier we should check the next character as well.
linkHotTerms(beginChar, hotTerms);
else
// In case of greedy matching the next character checking is unnecessary therefore we just store
// the first character.
addCharacter(beginChar);
}
// Merge two following BeginChars in the vector to reduce the number of character checks.
void merge(unsigned size)
{
for (unsigned i = 0; i < size; i++) {
BeginChar* curr = &m_beginChars->at(i);
BeginChar* next = &m_beginChars->at(i + 1);
// If the current and the next size of value is different we should skip the merge process
// because the 16bit and 32bit values are unmergable.
if (curr->value <= 0xFFFF && next->value > 0xFFFF)
continue;
unsigned diff = curr->value ^ next->value;
curr->mask |= diff;
curr->value |= curr->mask;
m_beginChars->remove(i + 1);
size--;
}
}
private:
void addCharacter(BeginChar beginChar)
{
unsigned pos = 0;
unsigned range = m_beginChars->size();
// binary chop, find position to insert char.
while (range) {
unsigned index = range >> 1;
int val = m_beginChars->at(pos+index).value - beginChar.value;
if (!val)
return;
if (val < 0)
range = index;
else {
pos += (index+1);
range -= (index+1);
}
}
if (pos == m_beginChars->size())
m_beginChars->append(beginChar);
else
m_beginChars->insert(pos, beginChar);
}
// Create BeginChar objects by appending each terms from a hotTerms vector to an existing BeginChar object.
void linkHotTerms(BeginChar beginChar, Vector<TermChain>* hotTerms)
{
for (unsigned i = 0; i < hotTerms->size(); i++) {
PatternTerm hotTerm = hotTerms->at(i).term;
ASSERT(hotTerm.type == PatternTerm::TypePatternCharacter);
UChar characterNext = hotTerm.patternCharacter;
// Append a character to an existing BeginChar object.
if (characterNext <= 0x7f) {
unsigned mask = 0;
if (m_isCaseInsensitive && isASCIIAlpha(characterNext)) {
mask = 32;
characterNext = toASCIILower(characterNext);
}
addCharacter(BeginChar(beginChar.value | (characterNext << 16), beginChar.mask | (mask << 16)));
} else {
UChar upper, lower;
if (m_isCaseInsensitive && ((upper = Unicode::toUpper(characterNext)) != (lower = Unicode::toLower(characterNext)))) {
addCharacter(BeginChar(beginChar.value | (upper << 16), beginChar.mask));
addCharacter(BeginChar(beginChar.value | (lower << 16), beginChar.mask));
} else
addCharacter(BeginChar(beginChar.value | (characterNext << 16), beginChar.mask));
}
}
}
Vector<BeginChar>* m_beginChars;
bool m_isCaseInsensitive;
};
class YarrPatternConstructor {
public:
YarrPatternConstructor(YarrPattern& pattern)
: m_pattern(pattern)
, m_characterClassConstructor(pattern.m_ignoreCase)
, m_beginCharHelper(&pattern.m_beginChars, pattern.m_ignoreCase)
, m_invertParentheticalAssertion(false)
{
m_pattern.m_body = js::OffTheBooks::new_<PatternDisjunction>();
@ -789,144 +683,10 @@ public:
}
}
// This function collects the terms which are potentially matching the first number of depth characters in the result.
// If this function returns false then it found at least one term which makes the beginning character
// look-up optimization inefficient.
bool setupDisjunctionBeginTerms(PatternDisjunction* disjunction, Vector<TermChain>* beginTerms, unsigned depth)
{
for (unsigned alt = 0; alt < disjunction->m_alternatives.size(); ++alt) {
PatternAlternative* alternative = disjunction->m_alternatives[alt];
if (!setupAlternativeBeginTerms(alternative, beginTerms, 0, depth))
return false;
}
return true;
}
bool setupAlternativeBeginTerms(PatternAlternative* alternative, Vector<TermChain>* beginTerms, unsigned termIndex, unsigned depth)
{
bool checkNext = true;
unsigned numTerms = alternative->m_terms.size();
while (checkNext && termIndex < numTerms) {
PatternTerm term = alternative->m_terms[termIndex];
checkNext = false;
switch (term.type) {
case PatternTerm::TypeAssertionBOL:
case PatternTerm::TypeAssertionEOL:
case PatternTerm::TypeAssertionWordBoundary:
return false;
case PatternTerm::TypeBackReference:
case PatternTerm::TypeForwardReference:
return false;
case PatternTerm::TypePatternCharacter:
if (termIndex != numTerms - 1) {
beginTerms->append(TermChain(term));
termIndex++;
checkNext = true;
} else if (term.quantityType == QuantifierFixedCount) {
beginTerms->append(TermChain(term));
if (depth < 2 && termIndex < numTerms - 1 && term.quantityCount == 1)
if (!setupAlternativeBeginTerms(alternative, &beginTerms->last().hotTerms, termIndex + 1, depth + 1))
return false;
}
break;
case PatternTerm::TypeCharacterClass:
return false;
case PatternTerm::TypeParentheticalAssertion:
if (term.invert())
return false;
case PatternTerm::TypeParenthesesSubpattern:
if (term.quantityType != QuantifierFixedCount) {
if (termIndex == numTerms - 1)
break;
termIndex++;
checkNext = true;
}
if (!setupDisjunctionBeginTerms(term.parentheses.disjunction, beginTerms, depth))
return false;
break;
}
}
return true;
}
void setupBeginChars()
{
Vector<TermChain> beginTerms;
bool containsFixedCharacter = false;
if ((!m_pattern.m_body->m_hasFixedSize || m_pattern.m_body->m_alternatives.size() > 1)
&& setupDisjunctionBeginTerms(m_pattern.m_body, &beginTerms, 0)) {
unsigned size = beginTerms.size();
// If we haven't collected any terms we should abort the preparation of beginning character look-up optimization.
if (!size)
return;
m_pattern.m_containsBeginChars = true;
for (unsigned i = 0; i < size; i++) {
PatternTerm term = beginTerms[i].term;
// We have just collected PatternCharacter terms, other terms are not allowed.
ASSERT(term.type == PatternTerm::TypePatternCharacter);
if (term.quantityType == QuantifierFixedCount)
containsFixedCharacter = true;
UChar character = term.patternCharacter;
unsigned mask = 0;
if (character <= 0x7f) {
if (m_pattern.m_ignoreCase && isASCIIAlpha(character)) {
mask = 32;
character = toASCIILower(character);
}
m_beginCharHelper.addBeginChar(BeginChar(character, mask), &beginTerms[i].hotTerms, term.quantityType, term.quantityCount);
} else {
UChar upper, lower;
if (m_pattern.m_ignoreCase && ((upper = Unicode::toUpper(character)) != (lower = Unicode::toLower(character)))) {
m_beginCharHelper.addBeginChar(BeginChar(upper, mask), &beginTerms[i].hotTerms, term.quantityType, term.quantityCount);
m_beginCharHelper.addBeginChar(BeginChar(lower, mask), &beginTerms[i].hotTerms, term.quantityType, term.quantityCount);
} else
m_beginCharHelper.addBeginChar(BeginChar(character, mask), &beginTerms[i].hotTerms, term.quantityType, term.quantityCount);
}
}
// If the pattern doesn't contain terms with fixed quantifiers then the beginning character look-up optimization is inefficient.
if (!containsFixedCharacter) {
m_pattern.m_containsBeginChars = false;
return;
}
size = m_pattern.m_beginChars.size();
if (size > 2)
m_beginCharHelper.merge(size - 1);
else if (size <= 1)
m_pattern.m_containsBeginChars = false;
}
}
private:
YarrPattern& m_pattern;
PatternAlternative* m_alternative;
CharacterClassConstructor m_characterClassConstructor;
BeginCharHelper m_beginCharHelper;
bool m_invertCharacterClass;
bool m_invertParentheticalAssertion;
};
@ -959,7 +719,6 @@ ErrorCode YarrPattern::compile(const UString& patternString)
constructor.optimizeBOL();
constructor.setupOffsets();
constructor.setupBeginChars();
return NoError;
}
@ -968,7 +727,6 @@ YarrPattern::YarrPattern(const UString& pattern, bool ignoreCase, bool multiline
: m_ignoreCase(ignoreCase)
, m_multiline(multiline)
, m_containsBackreferences(false)
, m_containsBeginChars(false)
, m_containsBOL(false)
, m_numSubpatterns(0)
, m_maxBackReference(0)

View File

@ -332,21 +332,6 @@ struct TermChain {
Vector<TermChain> hotTerms;
};
struct BeginChar {
BeginChar()
: value(0)
, mask(0)
{}
BeginChar(unsigned value, unsigned mask)
: value(value)
, mask(mask)
{}
unsigned value;
unsigned mask;
};
struct YarrPattern {
YarrPattern(const UString& pattern, bool ignoreCase, bool multiline, ErrorCode* error);
@ -362,7 +347,6 @@ struct YarrPattern {
m_maxBackReference = 0;
m_containsBackreferences = false;
m_containsBeginChars = false;
m_containsBOL = false;
newlineCached = 0;
@ -377,7 +361,6 @@ struct YarrPattern {
m_disjunctions.clear();
deleteAllValues(m_userCharacterClasses);
m_userCharacterClasses.clear();
m_beginChars.clear();
}
bool containsIllegalBackReference()
@ -431,14 +414,12 @@ struct YarrPattern {
bool m_ignoreCase : 1;
bool m_multiline : 1;
bool m_containsBackreferences : 1;
bool m_containsBeginChars : 1;
bool m_containsBOL : 1;
unsigned m_numSubpatterns;
unsigned m_maxBackReference;
PatternDisjunction* m_body;
Vector<PatternDisjunction*, 4> m_disjunctions;
Vector<CharacterClass*> m_userCharacterClasses;
Vector<BeginChar> m_beginChars;
private:
ErrorCode compile(const UString& patternString);

View File

@ -1233,7 +1233,7 @@ CompartmentCallback(JSContext *cx, void *vdata, JSCompartment *compartment)
curr->mjitCodeUnused = unused;
#endif
JS_GetTypeInferenceMemoryStats(cx, compartment, &curr->typeInferenceMemory,
moz_malloc_usable_size);
MemoryReporterMallocSizeOf);
}
void
@ -1278,14 +1278,14 @@ CellCallback(JSContext *cx, void *vdata, void *thing, JSGCTraceKind traceKind,
} else {
curr->gcHeapObjectsNonFunction += thingSize;
}
curr->objectSlots += obj->sizeOfSlotsArray(moz_malloc_usable_size);
curr->objectSlots += obj->sizeOfSlotsArray(MemoryReporterMallocSizeOf);
break;
}
case JSTRACE_STRING:
{
JSString *str = static_cast<JSString *>(thing);
curr->gcHeapStrings += thingSize;
curr->stringChars += str->charsHeapSize(moz_malloc_usable_size);
curr->stringChars += str->charsHeapSize(MemoryReporterMallocSizeOf);
break;
}
case JSTRACE_SHAPE:
@ -1293,11 +1293,14 @@ CellCallback(JSContext *cx, void *vdata, void *thing, JSGCTraceKind traceKind,
js::Shape *shape = static_cast<js::Shape *>(thing);
if (shape->inDictionary()) {
curr->gcHeapShapesDict += thingSize;
curr->shapesExtraDictTables += shape->sizeOfPropertyTable(moz_malloc_usable_size);
curr->shapesExtraDictTables +=
shape->sizeOfPropertyTableIncludingThis(MemoryReporterMallocSizeOf);
} else {
curr->gcHeapShapesTree += thingSize;
curr->shapesExtraTreeTables += shape->sizeOfPropertyTable(moz_malloc_usable_size);
curr->shapesExtraTreeShapeKids += shape->sizeOfKids(moz_malloc_usable_size);
curr->shapesExtraTreeTables +=
shape->sizeOfPropertyTableIncludingThis(MemoryReporterMallocSizeOf);
curr->shapesExtraTreeShapeKids +=
shape->sizeOfKidsIncludingThis(MemoryReporterMallocSizeOf);
}
break;
}
@ -1305,9 +1308,9 @@ CellCallback(JSContext *cx, void *vdata, void *thing, JSGCTraceKind traceKind,
{
JSScript *script = static_cast<JSScript *>(thing);
curr->gcHeapScripts += thingSize;
curr->scriptData += script->dataSize(moz_malloc_usable_size);
curr->scriptData += script->dataSize(MemoryReporterMallocSizeOf);
#ifdef JS_METHODJIT
curr->mjitData += script->jitDataSize(moz_malloc_usable_size);
curr->mjitData += script->jitDataSize(MemoryReporterMallocSizeOf);
#endif
break;
}
@ -1315,7 +1318,8 @@ CellCallback(JSContext *cx, void *vdata, void *thing, JSGCTraceKind traceKind,
{
js::types::TypeObject *obj = static_cast<js::types::TypeObject *>(thing);
curr->gcHeapTypeObjects += thingSize;
JS_GetTypeInferenceObjectStats(obj, &curr->typeInferenceMemory, moz_malloc_usable_size);
JS_GetTypeInferenceObjectStats(obj, &curr->typeInferenceMemory,
MemoryReporterMallocSizeOf);
break;
}
case JSTRACE_XML:
@ -1530,13 +1534,12 @@ CollectCompartmentStatsForRuntime(JSRuntime *rt, IterateData *data)
for (js::ThreadDataIter i(rt); !i.empty(); i.popFront())
data->stackSize += i.threadData()->stackSpace.committedSize();
size_t usable = moz_malloc_usable_size(rt);
data->runtimeObjectSize = usable ? usable : sizeof(JSRuntime);
data->runtimeObjectSize = MemoryReporterMallocSizeOf(rt, sizeof(JSRuntime));
// Nb: |countMe| is false because atomState.atoms is within JSRuntime,
// and so counted when JSRuntime is counted.
// Nb: we use sizeOfExcludingThis() because atomState.atoms is within
// JSRuntime, and so counted when JSRuntime is counted.
data->atomsTableSize =
rt->atomState.atoms.sizeOf(moz_malloc_usable_size, /* countMe */false);
rt->atomState.atoms.sizeOfExcludingThis(MemoryReporterMallocSizeOf);
}
JS_DestroyContextNoGC(cx);

View File

@ -217,7 +217,19 @@ members = [
# Quick stubs handle the shadowing the same as XPConnect.
'nsIDOMHTMLCollection.length',
'nsIDOMHTMLCommandElement.*',
'nsIDOMHTMLDocument.*',
'nsIDOMHTMLDocument.body',
'nsIDOMHTMLDocument.getElementsByName',
'nsIDOMHTMLDocument.anchors',
'nsIDOMHTMLDocument.links',
'nsIDOMHTMLDocument.URL',
'nsIDOMHTMLDocument.forms',
'nsIDOMHTMLDocument.cookie',
'nsIDOMHTMLDocument.images',
'nsIDOMHTMLDocument.write',
'nsIDOMHTMLDocument.writeln',
'nsIDOMHTMLDocument.domain',
'nsIDOMHTMLDocument.getSelection',
'nsIDOMHTMLDocument.designMode',
'nsIDOMHTMLElement.*',
'nsIDOMHTMLFormElement.elements',
'nsIDOMHTMLFormElement.name',

View File

@ -4295,25 +4295,29 @@ nsLayoutUtils::GetFontFacesForText(nsIFrame* aFrame,
}
/* static */
nsresult
nsLayoutUtils::GetTextRunMemoryForFrames(nsIFrame* aFrame, PRUint64* aTotal)
size_t
nsLayoutUtils::SizeOfTextRunsForFrames(nsIFrame* aFrame,
nsMallocSizeOfFun aMallocSizeOf,
bool clear)
{
NS_PRECONDITION(aFrame, "NULL frame pointer");
size_t total = 0;
if (aFrame->GetType() == nsGkAtoms::textFrame) {
nsTextFrame* textFrame = static_cast<nsTextFrame*>(aFrame);
for (PRUint32 i = 0; i < 2; ++i) {
gfxTextRun *run = textFrame->GetTextRun(
(i != 0) ? nsTextFrame::eInflated : nsTextFrame::eNotInflated);
if (run) {
if (aTotal) {
run->AccountForSize(aTotal);
if (clear) {
run->ResetSizeOfAccountingFlags();
} else {
run->ClearSizeAccounted();
total += run->MaybeSizeOfIncludingThis(aMallocSizeOf);
}
}
}
return NS_OK;
return total;
}
nsAutoTArray<nsIFrame::ChildList,4> childListArray;
@ -4323,11 +4327,10 @@ nsLayoutUtils::GetTextRunMemoryForFrames(nsIFrame* aFrame, PRUint64* aTotal)
!childLists.IsDone(); childLists.Next()) {
for (nsFrameList::Enumerator e(childLists.CurrentList());
!e.AtEnd(); e.Next()) {
GetTextRunMemoryForFrames(e.get(), aTotal);
total += SizeOfTextRunsForFrames(e.get(), aMallocSizeOf, clear);
}
}
return NS_OK;
return total;
}
/* static */

View File

@ -1438,17 +1438,18 @@ public:
/**
* Walks the frame tree starting at aFrame looking for textRuns.
* If aTotal is NULL, just clears the TEXT_RUN_MEMORY_ACCOUNTED flag
* on each textRun found.
* If aTotal is non-NULL, adds the storage used for each textRun to the
* If |clear| is true, just clears the TEXT_RUN_MEMORY_ACCOUNTED flag
* on each textRun found (and |aMallocSizeOf| is not used).
* If |clear| is false, adds the storage used for each textRun to the
* total, and sets the TEXT_RUN_MEMORY_ACCOUNTED flag to avoid double-
* accounting. (Runs with this flag already set will be skipped.)
* Expected usage pattern is therefore to call twice:
* rv = GetTextRunMemoryForFrames(rootFrame, NULL);
* rv = GetTextRunMemoryForFrames(rootFrame, &total);
* (void)SizeOfTextRunsForFrames(rootFrame, nsnull, true);
* total = SizeOfTextRunsForFrames(rootFrame, mallocSizeOf, false);
*/
static nsresult GetTextRunMemoryForFrames(nsIFrame* aFrame,
PRUint64* aTotal);
static size_t SizeOfTextRunsForFrames(nsIFrame* aFrame,
nsMallocSizeOfFun aMallocSizeOf,
bool clear);
/**
* Checks if CSS 3D transforms are currently enabled.

View File

@ -661,8 +661,7 @@ PresShell::MemoryReporter::SizeEnumerator(PresShellPtrKey *aEntry,
PRUint32 styleSize;
styleSize = aShell->StyleSet()->SizeOf();
PRUint64 textRunsSize;
textRunsSize = aShell->ComputeTextRunMemoryUsed();
PRInt64 textRunsSize = aShell->SizeOfTextRuns(MemoryReporterMallocSizeOf);
data->callback->
Callback(EmptyCString(), arenaPath, nsIMemoryReporter::KIND_HEAP,
@ -693,7 +692,7 @@ PresShell::MemoryReporter::CollectReports(nsIMemoryMultiReporterCallback* aCb,
data.closure = aClosure;
// clear TEXT_RUN_SIZE_ACCOUNTED flag on cached runs
gfxTextRunWordCache::ComputeStorage(nsnull);
gfxTextRunWordCache::ResetSizeOfAccountingFlags();
sLiveShells->EnumerateEntries(SizeEnumerator, &data);
@ -704,8 +703,8 @@ PresShell::MemoryReporter::CollectReports(nsIMemoryMultiReporterCallback* aCb,
"not owned by a PresShell's frame tree.");
// now total up cached runs that aren't otherwise accounted for
PRUint64 textRunWordCacheSize = 0;
gfxTextRunWordCache::ComputeStorage(&textRunWordCacheSize);
PRInt64 textRunWordCacheSize =
gfxTextRunWordCache::MaybeSizeOfExcludingThis(MemoryReporterMallocSizeOf);
aCb->Callback(EmptyCString(), kTextRunWordCachePath,
nsIMemoryReporter::KIND_HEAP, nsIMemoryReporter::UNITS_BYTES,
@ -8808,8 +8807,8 @@ PresShell::GetRootPresShell()
return nsnull;
}
PRUint64
PresShell::ComputeTextRunMemoryUsed()
size_t
PresShell::SizeOfTextRuns(nsMallocSizeOfFun aMallocSizeOf)
{
nsIFrame* rootFrame = FrameManager()->GetRootFrame();
if (!rootFrame) {
@ -8817,12 +8816,11 @@ PresShell::ComputeTextRunMemoryUsed()
}
// clear the TEXT_RUN_MEMORY_ACCOUNTED flags
nsLayoutUtils::GetTextRunMemoryForFrames(rootFrame, nsnull);
nsLayoutUtils::SizeOfTextRunsForFrames(rootFrame, nsnull,
/* clear = */true);
// collect the total memory in use for textruns
PRUint64 total = 0;
nsLayoutUtils::GetTextRunMemoryForFrames(rootFrame, &total);
return total;
return nsLayoutUtils::SizeOfTextRunsForFrames(rootFrame, aMallocSizeOf,
/* clear = */false);
}

View File

@ -890,7 +890,7 @@ public:
return result;
}
PRUint64 ComputeTextRunMemoryUsed();
size_t SizeOfTextRuns(nsMallocSizeOfFun aMallocSizeOf);
class MemoryReporter : public nsIMemoryMultiReporter
{

View File

@ -99,28 +99,28 @@ nsTransformedTextRun::SetPotentialLineBreaks(PRUint32 aStart, PRUint32 aLength,
return changed;
}
PRUint64
nsTransformedTextRun::ComputeSize()
size_t
nsTransformedTextRun::SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf)
{
PRUint32 total = gfxTextRun::ComputeSize();
if (moz_malloc_usable_size(this) == 0) {
total += sizeof(nsTransformedTextRun) - sizeof(gfxTextRun);
}
size_t total = gfxTextRun::SizeOfExcludingThis(aMallocSizeOf);
total += mStyles.SizeOf();
total += mCapitalize.SizeOf();
if (mOwnsFactory) {
PRUint32 factorySize = moz_malloc_usable_size(mFactory);
if (factorySize == 0) {
// this may not quite account for everything
// (e.g. nsCaseTransformTextRunFactory adds a couple of members)
// but I'm not sure it's worth the effort to track more precisely
factorySize = sizeof(nsTransformingTextRunFactory);
}
total += factorySize;
// It's not worth the effort to get all the sub-class cases right for a
// small size in the fallback case. So we use a |computedSize| of 0, which
// disables any usable vs. computedSize checking done by aMallocSizeOf.
total += aMallocSizeOf(mFactory, 0);
}
return total;
}
size_t
nsTransformedTextRun::SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf)
{
return aMallocSizeOf(this, sizeof(nsTransformedTextRun)) +
SizeOfExcludingThis(aMallocSizeOf);
}
nsTransformedTextRun*
nsTransformingTextRunFactory::MakeTextRun(const PRUnichar* aString, PRUint32 aLength,
const gfxTextRunFactory::Parameters* aParams,

View File

@ -132,8 +132,9 @@ public:
}
}
// override the gfxTextRun impl to account for additional members here
virtual PRUint64 ComputeSize();
// override the gfxTextRun impls to account for additional members here
virtual NS_MUST_OVERRIDE size_t SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf);
virtual NS_MUST_OVERRIDE size_t SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf);
nsTransformingTextRunFactory *mFactory;
nsTArray<nsRefPtr<nsStyleContext> > mStyles;

View File

@ -301,7 +301,7 @@ fails-if(Android) != 192767-17.xul 192767-37.xul
== 283686-3.html about:blank
== 289384-1.xhtml 289384-ref.xhtml
fails-if(Android) random-if(d2d) HTTP == 289480.html#top 289480-ref.html # basically-verbatim acid2 test, HTTP for a 404 page -- bug 578114 for the d2d failures
asserts(1) == 290129-1.html 290129-1-ref.html # bug 315549/460637
== 290129-1.html 290129-1-ref.html
== 291078-1.html 291078-1-ref.html
== 291078-2.html 291078-2-ref.html
== 291262-1.html 291262-1-ref.html

View File

@ -0,0 +1,41 @@
<html xmlns="http://www.w3.org/1999/xhtml" class="reftest-wait">
<head><script type="text/javascript">
<![CDATA[
function boom() {
var HTML_NS = "http://www.w3.org/1999/xhtml";
var r = document.documentElement; while(r.firstChild) { r.removeChild(r.firstChild); }
var table = document.createElementNS(HTML_NS, "table");
table.setAttribute("border", "1");
var text = document.createTextNode("\n ");
table.appendChild(text);
var tr1 = document.createElementNS(HTML_NS, "tr");
table.appendChild(tr1);
var tr2 = document.createElementNS(HTML_NS, "tr");
var input = document.createElementNS(HTML_NS, "input");
tr2.appendChild(input);
table.appendChild(tr2);
document.documentElement.appendChild(table);
var tr3 = document.createElementNS(HTML_NS, 'tr');
table.insertBefore(tr3, text);
var td = document.createElementNS(HTML_NS, 'td');
td.setAttribute('rowspan', 0);
tr3.insertBefore(td, null);
table.removeAttribute('border');
var caption = document.createElementNS(HTML_NS, 'caption');
table.insertBefore(caption, tr2);
document.documentElement.removeAttribute("class");
}
function ol(e) {
window.removeEventListener("load", ol, false);
setTimeout(boom, 400);
}
window.addEventListener("load", ol, false);
]]></script>
</head>
<body></body>
</html>

View File

@ -0,0 +1,24 @@
<html xmlns="http://www.w3.org/1999/xhtml" class="reftest-wait">
<head><script type="text/javascript">
<![CDATA[
function boom() {
var tr = document.getElementById('tr');
th = document.createElementNS("http://www.w3.org/1999/xhtml", 'th');
th.setAttribute('rowspan', 9);
tr.appendChild(th);
document.documentElement.removeAttribute("class");
}
function ol(e) {
window.removeEventListener("load", ol, false);
setTimeout(boom, 400);
}
window.addEventListener("load", ol, false);
]]></script>
</head>
<body><table style="border-collapse: collapse;"><tbody><tr id="tr"></tr></tbody></table></body>
</html>

View File

@ -0,0 +1,26 @@
<html xmlns="http://www.w3.org/1999/xhtml" class="reftest-wait">
<head><script type="text/javascript">
<![CDATA[
function boom() {
const HTML_NS = "http://www.w3.org/1999/xhtml";
var tr4 = document.createElementNS(HTML_NS, 'tr');
document.getElementById('tbody1').appendChild(tr4);
var span1 = document.createElementNS(HTML_NS, 'td');
tr4.insertBefore(span1, null);
document.documentElement.removeAttribute("class");
}
function ol(e) {
window.removeEventListener("load", ol, false);
setTimeout(boom, 400);
}
window.addEventListener("load", ol, false);
]]>
</script>
</head>
<body><table><tbody id="tbody1"><tr><td rowspan="0"></td></tr></tbody></table></body>
</html>

View File

@ -96,6 +96,9 @@ load 448988-1.xhtml
load 450311-1.html
load 456041.html
load 457115.html
load 460637-1.xhtml
load 460637-2.xhtml
load 460637-3.xhtml
load 467141-1.html
load 488388-1.html
load 512749-1.html

View File

@ -41,6 +41,24 @@
#include "nsTableCellFrame.h"
#include "nsTableRowGroupFrame.h"
static void
SetDamageArea(PRInt32 aXOrigin,
PRInt32 aYOrigin,
PRInt32 aWidth,
PRInt32 aHeight,
nsRect& aDamageArea)
{
NS_ASSERTION(aXOrigin >= 0, "negative col index");
NS_ASSERTION(aYOrigin >= 0, "negative row index");
NS_ASSERTION(aWidth >= 0, "negative horizontal damage");
NS_ASSERTION(aHeight >= 0, "negative vertical damage");
aDamageArea.x = aXOrigin;
aDamageArea.y = aYOrigin;
aDamageArea.width = aWidth;
aDamageArea.height = aHeight;
}
// Empty static array used for SafeElementAt() calls on mRows.
static nsCellMap::CellDataArray * sEmptyRow;
@ -479,13 +497,13 @@ nsTableCellMap::InsertRows(nsTableRowGroupFrame* aParent,
if ((numNewRows <= 0) || (aFirstRowIndex < 0)) ABORT0();
PRInt32 rowIndex = aFirstRowIndex;
PRInt32 rgStartRowIndex = 0;
nsCellMap* cellMap = mFirstMap;
while (cellMap) {
nsTableRowGroupFrame* rg = cellMap->GetRowGroup();
if (rg == aParent) {
cellMap->InsertRows(*this, aRows, rowIndex, aConsiderSpans, aDamageArea);
aDamageArea.y = NS_MIN(aFirstRowIndex, aDamageArea.y);
aDamageArea.height = NS_MAX(0, GetRowCount() - aDamageArea.y);
cellMap->InsertRows(*this, aRows, rowIndex, aConsiderSpans,
rgStartRowIndex, aDamageArea);
#ifdef DEBUG_TABLE_CELLMAP
Dump("after InsertRows");
#endif
@ -507,7 +525,9 @@ nsTableCellMap::InsertRows(nsTableRowGroupFrame* aParent,
}
return;
}
rowIndex -= cellMap->GetRowCount();
PRInt32 rowCount = cellMap->GetRowCount();
rgStartRowIndex += rowCount;
rowIndex -= rowCount;
cellMap = cellMap->GetNextSibling();
}
@ -521,13 +541,13 @@ nsTableCellMap::RemoveRows(PRInt32 aFirstRowIndex,
nsRect& aDamageArea)
{
PRInt32 rowIndex = aFirstRowIndex;
PRInt32 rgStartRowIndex = 0;
nsCellMap* cellMap = mFirstMap;
while (cellMap) {
if (cellMap->GetRowCount() > rowIndex) {
cellMap->RemoveRows(*this, rowIndex, aNumRowsToRemove, aConsiderSpans, aDamageArea);
nsTableRowGroupFrame* rg = cellMap->GetRowGroup();
aDamageArea.y += (rg) ? rg->GetStartRowIndex() : 0;
aDamageArea.height = NS_MAX(0, GetRowCount() - aFirstRowIndex);
PRInt32 rowCount = cellMap->GetRowCount();
if (rowCount > rowIndex) {
cellMap->RemoveRows(*this, rowIndex, aNumRowsToRemove, aConsiderSpans,
rgStartRowIndex, aDamageArea);
if (mBCInfo) {
for (PRInt32 rowX = aFirstRowIndex + aNumRowsToRemove - 1; rowX >= aFirstRowIndex; rowX--) {
if (PRUint32(rowX) < mBCInfo->mRightBorders.Length()) {
@ -537,7 +557,8 @@ nsTableCellMap::RemoveRows(PRInt32 aFirstRowIndex,
}
break;
}
rowIndex -= cellMap->GetRowCount();
rgStartRowIndex += rowCount;
rowIndex -= rowCount;
cellMap = cellMap->GetNextSibling();
}
#ifdef DEBUG_TABLE_CELLMAP
@ -561,15 +582,18 @@ nsTableCellMap::AppendCell(nsTableCellFrame& aCellFrame,
CellData* result = nsnull;
PRInt32 rowIndex = aRowIndex;
PRInt32 rgStartRowIndex = 0;
nsCellMap* cellMap = mFirstMap;
while (cellMap) {
if (cellMap->GetRowGroup() == rgFrame) {
result = cellMap->AppendCell(*this, &aCellFrame, rowIndex, aRebuildIfNecessary, aDamageArea);
nsTableRowGroupFrame* rg = cellMap->GetRowGroup();
aDamageArea.y += (rg) ? rg->GetStartRowIndex() : 0;
result = cellMap->AppendCell(*this, &aCellFrame, rowIndex,
aRebuildIfNecessary, rgStartRowIndex,
aDamageArea);
break;
}
rowIndex -= cellMap->GetRowCount();
PRInt32 rowCount = cellMap->GetRowCount();
rgStartRowIndex += rowCount;
rowIndex -= rowCount;
cellMap = cellMap->GetNextSibling();
}
#ifdef DEBUG_TABLE_CELLMAP
@ -586,16 +610,17 @@ nsTableCellMap::InsertCells(nsTArray<nsTableCellFrame*>& aCellFrames,
nsRect& aDamageArea)
{
PRInt32 rowIndex = aRowIndex;
PRInt32 rgStartRowIndex = 0;
nsCellMap* cellMap = mFirstMap;
while (cellMap) {
if (cellMap->GetRowCount() > rowIndex) {
cellMap->InsertCells(*this, aCellFrames, rowIndex, aColIndexBefore, aDamageArea);
nsTableRowGroupFrame* rg = cellMap->GetRowGroup();
aDamageArea.y += (rg) ? rg->GetStartRowIndex() : 0;
aDamageArea.width = NS_MAX(0, GetColCount() - aColIndexBefore - 1);
PRInt32 rowCount = cellMap->GetRowCount();
if (rowCount > rowIndex) {
cellMap->InsertCells(*this, aCellFrames, rowIndex, aColIndexBefore,
rgStartRowIndex, aDamageArea);
break;
}
rowIndex -= cellMap->GetRowCount();
rgStartRowIndex += rowCount;
rowIndex -= rowCount;
cellMap = cellMap->GetNextSibling();
}
#ifdef DEBUG_TABLE_CELLMAP
@ -613,21 +638,20 @@ nsTableCellMap::RemoveCell(nsTableCellFrame* aCellFrame,
NS_ASSERTION(aCellFrame == (nsTableCellFrame *)aCellFrame->GetFirstInFlow(),
"invalid call on continuing frame");
PRInt32 rowIndex = aRowIndex;
PRInt32 rgStartRowIndex = 0;
nsCellMap* cellMap = mFirstMap;
while (cellMap) {
if (cellMap->GetRowCount() > rowIndex) {
cellMap->RemoveCell(*this, aCellFrame, rowIndex, aDamageArea);
nsTableRowGroupFrame* rg = cellMap->GetRowGroup();
aDamageArea.y += (rg) ? rg->GetStartRowIndex() : 0;
PRInt32 colIndex;
aCellFrame->GetColIndex(colIndex);
aDamageArea.width = NS_MAX(0, GetColCount() - colIndex - 1);
PRInt32 rowCount = cellMap->GetRowCount();
if (rowCount > rowIndex) {
cellMap->RemoveCell(*this, aCellFrame, rowIndex, rgStartRowIndex,
aDamageArea);
#ifdef DEBUG_TABLE_CELLMAP
Dump("after RemoveCell");
#endif
return;
}
rowIndex -= cellMap->GetRowCount();
rgStartRowIndex += rowCount;
rowIndex -= rowCount;
cellMap = cellMap->GetNextSibling();
}
// if we reach this point - the cell did not get removed, the caller of this routine
@ -637,19 +661,6 @@ nsTableCellMap::RemoveCell(nsTableCellFrame* aCellFrame,
NS_ERROR("nsTableCellMap::RemoveCell - could not remove cell");
}
void
SetDamageArea(PRInt32 aXOrigin,
PRInt32 aYOrigin,
PRInt32 aWidth,
PRInt32 aHeight,
nsRect& aDamageArea)
{
aDamageArea.x = aXOrigin;
aDamageArea.y = aYOrigin;
aDamageArea.width = NS_MAX(1, aWidth);
aDamageArea.height = NS_MAX(1, aHeight);
}
void
nsTableCellMap::RebuildConsideringCells(nsCellMap* aCellMap,
nsTArray<nsTableCellFrame*>* aCellFrames,
@ -664,11 +675,12 @@ nsTableCellMap::RebuildConsideringCells(nsCellMap* aCellMap,
PRInt32 rowCount = 0;
while (cellMap) {
if (cellMap == aCellMap) {
cellMap->RebuildConsideringCells(*this, numOrigCols, aCellFrames, aRowIndex, aColIndex, aInsert, aDamageArea);
cellMap->RebuildConsideringCells(*this, numOrigCols, aCellFrames,
aRowIndex, aColIndex, aInsert);
}
else {
cellMap->RebuildConsideringCells(*this, numOrigCols, nsnull, -1, 0, false, aDamageArea);
cellMap->RebuildConsideringCells(*this, numOrigCols, nsnull, -1, 0,
false);
}
rowCount += cellMap->GetRowCount();
cellMap = cellMap->GetNextSibling();
@ -692,10 +704,12 @@ nsTableCellMap::RebuildConsideringRows(nsCellMap* aCellMap,
PRInt32 rowCount = 0;
while (cellMap) {
if (cellMap == aCellMap) {
cellMap->RebuildConsideringRows(*this, aStartRowIndex, aRowsToInsert, aNumRowsToRemove, aDamageArea);
cellMap->RebuildConsideringRows(*this, aStartRowIndex, aRowsToInsert,
aNumRowsToRemove);
}
else {
cellMap->RebuildConsideringCells(*this, numOrigCols, nsnull, -1, 0, false, aDamageArea);
cellMap->RebuildConsideringCells(*this, numOrigCols, nsnull, -1, 0,
false);
}
rowCount += cellMap->GetRowCount();
cellMap = cellMap->GetNextSibling();
@ -1015,7 +1029,9 @@ nsTableCellMap::SetBCBorderEdge(mozilla::css::Side aSide,
PRInt32 numRgRows = aCellMap.GetRowCount();
if (yPos < numRgRows) { // add a dead cell data
nsRect damageArea;
cellData = (BCCellData*)aCellMap.AppendCell(*this, nsnull, rgYPos, false, damageArea); if (!cellData) ABORT0();
cellData = (BCCellData*)aCellMap.AppendCell(*this, nsnull, rgYPos,
false, 0, damageArea);
if (!cellData) ABORT0();
}
else {
NS_ASSERTION(aSide == NS_SIDE_BOTTOM, "program error");
@ -1028,7 +1044,9 @@ nsTableCellMap::SetBCBorderEdge(mozilla::css::Side aSide,
cellData = (BCCellData*)cellMap->GetDataAt(0, xIndex);
if (!cellData) { // add a dead cell
nsRect damageArea;
cellData = (BCCellData*)cellMap->AppendCell(*this, nsnull, 0, false, damageArea);
cellData = (BCCellData*)cellMap->AppendCell(*this, nsnull, 0,
false, 0,
damageArea);
}
}
else { // must be at the end of the table
@ -1121,7 +1139,8 @@ nsTableCellMap::SetBCBorderCorner(Corner aCorner,
PRInt32 numRgRows = aCellMap.GetRowCount();
if (yPos < numRgRows) { // add a dead cell data
nsRect damageArea;
cellData = (BCCellData*)aCellMap.AppendCell(*this, nsnull, rgYPos, false, damageArea);
cellData = (BCCellData*)aCellMap.AppendCell(*this, nsnull, rgYPos,
false, 0, damageArea);
}
else {
// try the next non empty row group
@ -1133,7 +1152,8 @@ nsTableCellMap::SetBCBorderCorner(Corner aCorner,
cellData = (BCCellData*)cellMap->GetDataAt(0, xPos);
if (!cellData) { // add a dead cell
nsRect damageArea;
cellData = (BCCellData*)cellMap->AppendCell(*this, nsnull, 0, false, damageArea);
cellData = (BCCellData*)cellMap->AppendCell(*this, nsnull, 0,
false, 0, damageArea);
}
}
else { // must be at the bottom of the table
@ -1337,6 +1357,7 @@ nsCellMap::InsertRows(nsTableCellMap& aMap,
nsTArray<nsTableRowFrame*>& aRows,
PRInt32 aFirstRowIndex,
bool aConsiderSpans,
PRInt32 aRgFirstRowIndex,
nsRect& aDamageArea)
{
PRInt32 numCols = aMap.GetColCount();
@ -1352,7 +1373,7 @@ nsCellMap::InsertRows(nsTableCellMap& aMap,
if (!aConsiderSpans) {
// update mContentRowCount, since non-empty rows will be added
mContentRowCount = NS_MAX(aFirstRowIndex, mContentRowCount);
ExpandWithRows(aMap, aRows, aFirstRowIndex, aDamageArea);
ExpandWithRows(aMap, aRows, aFirstRowIndex, aRgFirstRowIndex, aDamageArea);
return;
}
@ -1368,12 +1389,11 @@ nsCellMap::InsertRows(nsTableCellMap& aMap,
if (!spansCauseRebuild && (PRUint32(aFirstRowIndex) < mRows.Length())) {
spansCauseRebuild = CellsSpanOut(aRows);
}
if (spansCauseRebuild) {
aMap.RebuildConsideringRows(this, aFirstRowIndex, &aRows, 0, aDamageArea);
}
else {
ExpandWithRows(aMap, aRows, aFirstRowIndex, aDamageArea);
ExpandWithRows(aMap, aRows, aFirstRowIndex, aRgFirstRowIndex, aDamageArea);
}
}
@ -1382,6 +1402,7 @@ nsCellMap::RemoveRows(nsTableCellMap& aMap,
PRInt32 aFirstRowIndex,
PRInt32 aNumRowsToRemove,
bool aConsiderSpans,
PRInt32 aRgFirstRowIndex,
nsRect& aDamageArea)
{
PRInt32 numRows = mRows.Length();
@ -1395,7 +1416,8 @@ nsCellMap::RemoveRows(nsTableCellMap& aMap,
return;
}
if (!aConsiderSpans) {
ShrinkWithoutRows(aMap, aFirstRowIndex, aNumRowsToRemove, aDamageArea);
ShrinkWithoutRows(aMap, aFirstRowIndex, aNumRowsToRemove, aRgFirstRowIndex,
aDamageArea);
return;
}
PRInt32 endRowIndex = aFirstRowIndex + aNumRowsToRemove - 1;
@ -1405,12 +1427,13 @@ nsCellMap::RemoveRows(nsTableCellMap& aMap,
}
bool spansCauseRebuild = CellsSpanInOrOut(aFirstRowIndex, endRowIndex,
0, numCols - 1);
if (spansCauseRebuild) {
aMap.RebuildConsideringRows(this, aFirstRowIndex, nsnull, aNumRowsToRemove, aDamageArea);
aMap.RebuildConsideringRows(this, aFirstRowIndex, nsnull, aNumRowsToRemove,
aDamageArea);
}
else {
ShrinkWithoutRows(aMap, aFirstRowIndex, aNumRowsToRemove, aDamageArea);
ShrinkWithoutRows(aMap, aFirstRowIndex, aNumRowsToRemove, aRgFirstRowIndex,
aDamageArea);
}
}
@ -1422,6 +1445,7 @@ nsCellMap::AppendCell(nsTableCellMap& aMap,
nsTableCellFrame* aCellFrame,
PRInt32 aRowIndex,
bool aRebuildIfNecessary,
PRInt32 aRgFirstRowIndex,
nsRect& aDamageArea,
PRInt32* aColToBeginSearch)
{
@ -1514,7 +1538,15 @@ nsCellMap::AppendCell(nsTableCellMap& aMap,
SetDataAt(aMap, *origData, aRowIndex, startColIndex);
}
SetDamageArea(startColIndex, aRowIndex, 1 + endColIndex - startColIndex, 1 + endRowIndex - aRowIndex, aDamageArea);
if (aRebuildIfNecessary) {
//the caller depends on the damageArea
// The special case for zeroRowSpan is to adjust for the '2' in
// GetRowSpanForNewCell.
PRUint32 height = zeroRowSpan ? endRowIndex - aRowIndex :
1 + endRowIndex - aRowIndex;
SetDamageArea(startColIndex, aRgFirstRowIndex + aRowIndex,
1 + endColIndex - startColIndex, height, aDamageArea);
}
if (!aCellFrame) {
return origData;
@ -1723,6 +1755,7 @@ void nsCellMap::InsertCells(nsTableCellMap& aMap,
nsTArray<nsTableCellFrame*>& aCellFrames,
PRInt32 aRowIndex,
PRInt32 aColIndexBefore,
PRInt32 aRgFirstRowIndex,
nsRect& aDamageArea)
{
if (aCellFrames.Length() == 0) return;
@ -1779,12 +1812,13 @@ void nsCellMap::InsertCells(nsTableCellMap& aMap,
spansCauseRebuild = CellsSpanInOrOut(aRowIndex, aRowIndex + rowSpan - 1,
startColIndex, numCols - 1);
}
if (spansCauseRebuild) {
aMap.RebuildConsideringCells(this, &aCellFrames, aRowIndex, startColIndex, true, aDamageArea);
aMap.RebuildConsideringCells(this, &aCellFrames, aRowIndex, startColIndex,
true, aDamageArea);
}
else {
ExpandWithCells(aMap, aCellFrames, aRowIndex, startColIndex, rowSpan, zeroRowSpan, aDamageArea);
ExpandWithCells(aMap, aCellFrames, aRowIndex, startColIndex, rowSpan,
zeroRowSpan, aRgFirstRowIndex, aDamageArea);
}
}
@ -1792,6 +1826,7 @@ void
nsCellMap::ExpandWithRows(nsTableCellMap& aMap,
nsTArray<nsTableRowFrame*>& aRowFrames,
PRInt32 aStartRowIndexIn,
PRInt32 aRgFirstRowIndex,
nsRect& aDamageArea)
{
PRInt32 startRowIndex = (aStartRowIndexIn >= 0) ? aStartRowIndexIn : 0;
@ -1818,14 +1853,15 @@ nsCellMap::ExpandWithRows(nsTableCellMap& aMap,
while (cFrame) {
nsTableCellFrame *cellFrame = do_QueryFrame(cFrame);
if (cellFrame) {
AppendCell(aMap, cellFrame, rowX, false, aDamageArea, &colIndex);
AppendCell(aMap, cellFrame, rowX, false, aRgFirstRowIndex, aDamageArea,
&colIndex);
}
cFrame = cFrame->GetNextSibling();
}
newRowIndex++;
}
SetDamageArea(0, startRowIndex, aMap.GetColCount(), 1 + endRowIndex - startRowIndex, aDamageArea);
SetDamageArea(0, aRgFirstRowIndex + startRowIndex, aMap.GetColCount(),
1 + endRowIndex - startRowIndex, aDamageArea);
}
void nsCellMap::ExpandWithCells(nsTableCellMap& aMap,
@ -1834,6 +1870,7 @@ void nsCellMap::ExpandWithCells(nsTableCellMap& aMap,
PRInt32 aColIndex,
PRInt32 aRowSpan, // same for all cells
bool aRowSpanIsZero,
PRInt32 aRgFirstRowIndex,
nsRect& aDamageArea)
{
NS_ASSERTION(!!aMap.mBCInfo == mIsBC, "BC state mismatch");
@ -1908,8 +1945,10 @@ void nsCellMap::ExpandWithCells(nsTableCellMap& aMap,
}
cellFrame->SetColIndex(startColIndex);
}
PRInt32 damageHeight = NS_MIN(GetRowGroup()->GetRowCount() - aRowIndex, aRowSpan);
SetDamageArea(aColIndex, aRowIndex, 1 + endColIndex - aColIndex, damageHeight, aDamageArea);
PRInt32 damageHeight = NS_MIN(GetRowGroup()->GetRowCount() - aRowIndex,
aRowSpan);
SetDamageArea(aColIndex, aRgFirstRowIndex + aRowIndex,
1 + endColIndex - aColIndex, damageHeight, aDamageArea);
PRInt32 rowX;
@ -1951,6 +1990,7 @@ void nsCellMap::ExpandWithCells(nsTableCellMap& aMap,
void nsCellMap::ShrinkWithoutRows(nsTableCellMap& aMap,
PRInt32 aStartRowIndex,
PRInt32 aNumRowsToRemove,
PRInt32 aRgFirstRowIndex,
nsRect& aDamageArea)
{
NS_ASSERTION(!!aMap.mBCInfo == mIsBC, "BC state mismatch");
@ -1988,8 +2028,8 @@ void nsCellMap::ShrinkWithoutRows(nsTableCellMap& aMap,
mContentRowCount--;
}
aMap.RemoveColsAtEnd();
SetDamageArea(0, aStartRowIndex, aMap.GetColCount(), 0, aDamageArea);
SetDamageArea(0, aRgFirstRowIndex + aStartRowIndex, aMap.GetColCount(), 0,
aDamageArea);
}
PRInt32 nsCellMap::GetColSpanForNewCell(nsTableCellFrame& aCellFrameToAdd,
@ -2127,6 +2167,7 @@ void nsCellMap::ShrinkWithoutCell(nsTableCellMap& aMap,
nsTableCellFrame& aCellFrame,
PRInt32 aRowIndex,
PRInt32 aColIndex,
PRInt32 aRgFirstRowIndex,
nsRect& aDamageArea)
{
NS_ASSERTION(!!aMap.mBCInfo == mIsBC, "BC state mismatch");
@ -2139,8 +2180,9 @@ void nsCellMap::ShrinkWithoutCell(nsTableCellMap& aMap,
PRUint32 colSpan = GetEffectiveColSpan(aMap, aRowIndex, aColIndex, zeroColSpan);
PRUint32 endRowIndex = aRowIndex + rowSpan - 1;
PRUint32 endColIndex = aColIndex + colSpan - 1;
SetDamageArea(aColIndex, aRowIndex, 1 + endColIndex - aColIndex, 1 + endRowIndex - aRowIndex, aDamageArea);
SetDamageArea(aColIndex, aRgFirstRowIndex + aRowIndex,
NS_MAX(0, aMap.GetColCount() - aColIndex - 1),
1 + endRowIndex - aRowIndex, aDamageArea);
if (aMap.mTableFrame.HasZeroColSpans()) {
aMap.mTableFrame.SetNeedColSpanExpansion(true);
@ -2217,8 +2259,7 @@ void
nsCellMap::RebuildConsideringRows(nsTableCellMap& aMap,
PRInt32 aStartRowIndex,
nsTArray<nsTableRowFrame*>* aRowsToInsert,
PRInt32 aNumRowsToRemove,
nsRect& aDamageArea)
PRInt32 aNumRowsToRemove)
{
NS_ASSERTION(!!aMap.mBCInfo == mIsBC, "BC state mismatch");
// copy the old cell map into a new array
@ -2252,7 +2293,7 @@ nsCellMap::RebuildConsideringRows(nsTableCellMap& aMap,
// rowX keeps track of where we are in mRows while setting up the
// new cellmap.
PRUint32 rowX = 0;
nsRect damageArea;
// put back the rows before the affected ones just as before. Note that we
// can't just copy the old rows in bit-for-bit, because they might be
// spanning out into the rows we're adding/removing.
@ -2263,7 +2304,7 @@ nsCellMap::RebuildConsideringRows(nsTableCellMap& aMap,
// put in the original cell from the cell map
const CellData* data = row.ElementAt(colX);
if (data && data->IsOrig()) {
AppendCell(aMap, data->GetCellFrame(), rowX, false, aDamageArea);
AppendCell(aMap, data->GetCellFrame(), rowX, false, 0, damageArea);
}
}
}
@ -2280,7 +2321,7 @@ nsCellMap::RebuildConsideringRows(nsTableCellMap& aMap,
while (cFrame) {
nsTableCellFrame *cellFrame = do_QueryFrame(cFrame);
if (cellFrame) {
AppendCell(aMap, cellFrame, rowX, false, aDamageArea);
AppendCell(aMap, cellFrame, rowX, false, 0, damageArea);
}
cFrame = cFrame->GetNextSibling();
}
@ -2303,7 +2344,7 @@ nsCellMap::RebuildConsideringRows(nsTableCellMap& aMap,
// put in the original cell from the cell map
CellData* data = row.ElementAt(colX);
if (data && data->IsOrig()) {
AppendCell(aMap, data->GetCellFrame(), rowX, false, aDamageArea);
AppendCell(aMap, data->GetCellFrame(), rowX, false, 0, damageArea);
}
}
rowX++;
@ -2317,8 +2358,6 @@ nsCellMap::RebuildConsideringRows(nsTableCellMap& aMap,
DestroyCellData(row[colX]);
}
}
SetDamageArea(0, 0, aMap.GetColCount(), GetRowCount(), aDamageArea);
}
void
@ -2327,8 +2366,7 @@ nsCellMap::RebuildConsideringCells(nsTableCellMap& aMap,
nsTArray<nsTableCellFrame*>* aCellFrames,
PRInt32 aRowIndex,
PRInt32 aColIndex,
bool aInsert,
nsRect& aDamageArea)
bool aInsert)
{
NS_ASSERTION(!!aMap.mBCInfo == mIsBC, "BC state mismatch");
// copy the old cell map into a new array
@ -2345,6 +2383,7 @@ nsCellMap::RebuildConsideringCells(nsTableCellMap& aMap,
// build the new cell map. Hard to say what, if anything, we can preallocate
// here... Should come back to that sometime, perhaps.
PRInt32 rowX;
nsRect damageArea;
for (rowX = 0; rowX < numOrigRows; rowX++) {
const CellDataArray& row = origRows[rowX];
for (PRInt32 colX = 0; colX < numCols; colX++) {
@ -2353,7 +2392,7 @@ nsCellMap::RebuildConsideringCells(nsTableCellMap& aMap,
for (PRInt32 cellX = 0; cellX < numNewCells; cellX++) {
nsTableCellFrame* cell = aCellFrames->ElementAt(cellX);
if (cell) {
AppendCell(aMap, cell, rowX, false, aDamageArea);
AppendCell(aMap, cell, rowX, false, 0, damageArea);
}
}
}
@ -2364,7 +2403,7 @@ nsCellMap::RebuildConsideringCells(nsTableCellMap& aMap,
// put in the original cell from the cell map
CellData* data = row.SafeElementAt(colX);
if (data && data->IsOrig()) {
AppendCell(aMap, data->GetCellFrame(), rowX, false, aDamageArea);
AppendCell(aMap, data->GetCellFrame(), rowX, false, 0, damageArea);
}
}
}
@ -2373,7 +2412,7 @@ nsCellMap::RebuildConsideringCells(nsTableCellMap& aMap,
for (PRInt32 cellX = 0; cellX < numNewCells; cellX++) {
nsTableCellFrame* cell = aCellFrames->ElementAt(cellX);
if (cell) {
AppendCell(aMap, cell, aRowIndex, false, aDamageArea);
AppendCell(aMap, cell, aRowIndex, false, 0, damageArea);
}
}
}
@ -2396,6 +2435,7 @@ nsCellMap::RebuildConsideringCells(nsTableCellMap& aMap,
void nsCellMap::RemoveCell(nsTableCellMap& aMap,
nsTableCellFrame* aCellFrame,
PRInt32 aRowIndex,
PRInt32 aRgFirstRowIndex,
nsRect& aDamageArea)
{
PRUint32 numRows = mRows.Length();
@ -2429,10 +2469,12 @@ void nsCellMap::RemoveCell(nsTableCellMap& aMap,
spansCauseRebuild = true;
if (spansCauseRebuild) {
aMap.RebuildConsideringCells(this, nsnull, aRowIndex, startColIndex, false, aDamageArea);
aMap.RebuildConsideringCells(this, nsnull, aRowIndex, startColIndex, false,
aDamageArea);
}
else {
ShrinkWithoutCell(aMap, *aCellFrame, aRowIndex, startColIndex, aDamageArea);
ShrinkWithoutCell(aMap, *aCellFrame, aRowIndex, startColIndex,
aRgFirstRowIndex, aDamageArea);
}
}

View File

@ -378,6 +378,7 @@ public:
nsTableCellFrame* aCellFrame,
PRInt32 aRowIndex,
bool aRebuildIfNecessary,
PRInt32 aRgFirstRowIndex,
nsRect& aDamageArea,
PRInt32* aBeginSearchAtCol = nsnull);
@ -401,23 +402,27 @@ public:
nsTArray<nsTableCellFrame*>& aCellFrames,
PRInt32 aRowIndex,
PRInt32 aColIndexBefore,
PRInt32 aRgFirstRowIndex,
nsRect& aDamageArea);
void RemoveCell(nsTableCellMap& aMap,
nsTableCellFrame* aCellFrame,
PRInt32 aRowIndex,
PRInt32 aRgFirstRowIndex,
nsRect& aDamageArea);
void InsertRows(nsTableCellMap& aMap,
nsTArray<nsTableRowFrame*>& aRows,
PRInt32 aFirstRowIndex,
bool aConsiderSpans,
PRInt32 aRgFirstRowIndex,
nsRect& aDamageArea);
void RemoveRows(nsTableCellMap& aMap,
PRInt32 aFirstRowIndex,
PRInt32 aNumRowsToRemove,
bool aConsiderSpans,
PRInt32 aRgFirstRowIndex,
nsRect& aDamageArea);
PRInt32 GetNumCellsOriginatingInRow(PRInt32 aRowIndex) const;
@ -499,6 +504,7 @@ protected:
void ExpandWithRows(nsTableCellMap& aMap,
nsTArray<nsTableRowFrame*>& aRowFrames,
PRInt32 aStartRowIndex,
PRInt32 aRgFirstRowIndex,
nsRect& aDamageArea);
void ExpandWithCells(nsTableCellMap& aMap,
@ -507,17 +513,20 @@ protected:
PRInt32 aColIndex,
PRInt32 aRowSpan,
bool aRowSpanIsZero,
PRInt32 aRgFirstRowIndex,
nsRect& aDamageArea);
void ShrinkWithoutRows(nsTableCellMap& aMap,
PRInt32 aFirstRowIndex,
PRInt32 aNumRowsToRemove,
PRInt32 aRgFirstRowIndex,
nsRect& aDamageArea);
void ShrinkWithoutCell(nsTableCellMap& aMap,
nsTableCellFrame& aCellFrame,
PRInt32 aRowIndex,
PRInt32 aColIndex,
PRInt32 aRgFirstRowIndex,
nsRect& aDamageArea);
/**
@ -531,16 +540,14 @@ protected:
void RebuildConsideringRows(nsTableCellMap& aMap,
PRInt32 aStartRowIndex,
nsTArray<nsTableRowFrame*>* aRowsToInsert,
PRInt32 aNumRowsToRemove,
nsRect& aDamageArea);
PRInt32 aNumRowsToRemove);
void RebuildConsideringCells(nsTableCellMap& aMap,
PRInt32 aNumOrigCols,
nsTArray<nsTableCellFrame*>* aCellFrames,
PRInt32 aRowIndex,
PRInt32 aColIndex,
bool aInsert,
nsRect& aDamageArea);
bool aInsert);
bool CellsSpanOut(nsTArray<nsTableRowFrame*>& aNewRows) const;

View File

@ -256,7 +256,7 @@ nsTableCellFrame::DidSetStyleContext(nsStyleContext* aOldStyleContext)
GetColIndex(colIndex);
GetRowIndex(rowIndex);
nsRect damageArea(colIndex, rowIndex, GetColSpan(), GetRowSpan());
tableFrame->SetBCDamageArea(damageArea);
tableFrame->AddBCDamageArea(damageArea);
}
}

View File

@ -94,7 +94,7 @@ nsTableColFrame::DidSetStyleContext(nsStyleContext* aOldStyleContext)
if (tableFrame->IsBorderCollapse() &&
tableFrame->BCRecalcNeeded(aOldStyleContext, GetStyleContext())) {
nsRect damageArea = nsRect(GetColIndex(), 0, 1, tableFrame->GetRowCount());
tableFrame->SetBCDamageArea(damageArea);
tableFrame->AddBCDamageArea(damageArea);
}
return;
}

View File

@ -205,7 +205,7 @@ nsTableColGroupFrame::DidSetStyleContext(nsStyleContext* aOldStyleContext)
return; // this is a degenerated colgroup
nsRect damageArea(GetFirstColumn()->GetColIndex(), 0, colCount,
tableFrame->GetRowCount());
tableFrame->SetBCDamageArea(damageArea);
tableFrame->AddBCDamageArea(damageArea);
}
return;
}

View File

@ -148,11 +148,10 @@ struct nsTableReflowState {
struct BCPropertyData
{
BCPropertyData() { mDamageArea.x = mDamageArea.y = mDamageArea.width =
mDamageArea.height = mTopBorderWidth = mRightBorderWidth =
mBottomBorderWidth = mLeftBorderWidth =
mLeftCellBorderWidth = mRightCellBorderWidth = 0; }
nsRect mDamageArea;
BCPropertyData() : mTopBorderWidth(0), mRightBorderWidth(0),
mBottomBorderWidth(0), mLeftBorderWidth(0),
mLeftCellBorderWidth(0), mRightCellBorderWidth(0) {}
nsRect mDamageArea;
BCPixelSize mTopBorderWidth;
BCPixelSize mRightBorderWidth;
BCPixelSize mBottomBorderWidth;
@ -351,8 +350,7 @@ nsTableFrame::SetInitialChildList(ChildListID aListID,
InsertRowGroups(mFrames);
// calc collapsing borders
if (IsBorderCollapse()) {
nsRect damageArea(0, 0, GetColCount(), GetRowCount());
SetBCDamageArea(damageArea);
SetFullBCDamageArea();
}
}
@ -604,8 +602,8 @@ void nsTableFrame::InsertCol(nsTableColFrame& aColFrame,
}
// for now, just bail and recalc all of the collapsing borders
if (IsBorderCollapse()) {
nsRect damageArea(0, 0, NS_MAX(1, GetColCount()), NS_MAX(1, GetRowCount()));
SetBCDamageArea(damageArea);
nsRect damageArea(aColIndex, 0, 1, GetRowCount());
AddBCDamageArea(damageArea);
}
}
@ -626,7 +624,7 @@ void nsTableFrame::RemoveCol(nsTableColGroupFrame* aColGroupFrame,
// for now, just bail and recalc all of the collapsing borders
if (IsBorderCollapse()) {
nsRect damageArea(0, 0, GetColCount(), GetRowCount());
SetBCDamageArea(damageArea);
AddBCDamageArea(damageArea);
}
}
@ -799,7 +797,7 @@ nsTableFrame::AppendCell(nsTableCellFrame& aCellFrame,
cellMap->AppendCell(aCellFrame, aRowIndex, true, damageArea);
MatchCellMapToColCache(cellMap);
if (IsBorderCollapse()) {
SetBCDamageArea(damageArea);
AddBCDamageArea(damageArea);
}
}
}
@ -814,7 +812,7 @@ void nsTableFrame::InsertCells(nsTArray<nsTableCellFrame*>& aCellFrames,
cellMap->InsertCells(aCellFrames, aRowIndex, aColIndexBefore, damageArea);
MatchCellMapToColCache(cellMap);
if (IsBorderCollapse()) {
SetBCDamageArea(damageArea);
AddBCDamageArea(damageArea);
}
}
}
@ -854,7 +852,7 @@ void nsTableFrame::RemoveCell(nsTableCellFrame* aCellFrame,
cellMap->RemoveCell(aCellFrame, aRowIndex, damageArea);
MatchCellMapToColCache(cellMap);
if (IsBorderCollapse()) {
SetBCDamageArea(damageArea);
AddBCDamageArea(damageArea);
}
}
}
@ -919,7 +917,7 @@ nsTableFrame::InsertRows(nsTableRowGroupFrame* aRowGroupFrame,
rowFrame->SetRowIndex(aRowIndex + rowY);
}
if (IsBorderCollapse()) {
SetBCDamageArea(damageArea);
AddBCDamageArea(damageArea);
}
}
#ifdef DEBUG_TABLE_CELLMAP
@ -962,7 +960,7 @@ void nsTableFrame::RemoveRows(nsTableRowFrame& aFirstRowFrame,
cellMap->RemoveRows(firstRowIndex, aNumRowsToRemove, aConsiderSpans, damageArea);
MatchCellMapToColCache(cellMap);
if (IsBorderCollapse()) {
SetBCDamageArea(damageArea);
AddBCDamageArea(damageArea);
}
}
AdjustRowIndices(firstRowIndex, -aNumRowsToRemove);
@ -2049,8 +2047,7 @@ nsTableFrame::DidSetStyleContext(nsStyleContext* aOldStyleContext)
if (IsBorderCollapse() &&
BCRecalcNeeded(aOldStyleContext, GetStyleContext())) {
nsRect damageArea(0, 0, GetColCount(), GetRowCount());
SetBCDamageArea(damageArea);
SetFullBCDamageArea();
}
//avoid this on init or nextinflow
@ -2309,8 +2306,7 @@ nsTableFrame::RemoveFrame(ChildListID aListID,
// for now, just bail and recalc all of the collapsing borders
// as the cellmap changes we need to recalc
if (IsBorderCollapse()) {
nsRect damageArea(0, 0, NS_MAX(1, GetColCount()), NS_MAX(1, GetRowCount()));
SetBCDamageArea(damageArea);
SetFullBCDamageArea();
}
PresContext()->PresShell()->FrameNeedsReflow(this, nsIPresShell::eTreeChange,
NS_FRAME_HAS_DIRTY_CHILDREN);
@ -2357,6 +2353,20 @@ DestroyBCProperty(void* aPropertyValue)
NS_DECLARE_FRAME_PROPERTY(TableBCProperty, DestroyBCProperty)
BCPropertyData*
nsTableFrame::GetBCProperty(bool aCreateIfNecessary) const
{
FrameProperties props = Properties();
BCPropertyData* value = static_cast<BCPropertyData*>
(props.Get(TableBCProperty()));
if (!value && aCreateIfNecessary) {
value = new BCPropertyData();
props.Set(TableBCProperty(), value);
}
return value;
}
static void
DivideBCBorderSize(BCPixelSize aPixelSize,
BCPixelSize& aSmallHalf,
@ -2374,8 +2384,7 @@ nsTableFrame::GetOuterBCBorder() const
nsMargin border(0, 0, 0, 0);
PRInt32 p2t = nsPresContext::AppUnitsPerCSSPixel();
BCPropertyData* propData = static_cast<BCPropertyData*>
(Properties().Get(TableBCProperty()));
BCPropertyData* propData = GetBCProperty();
if (propData) {
border.top = BC_BORDER_TOP_HALF_COORD(p2t, propData->mTopBorderWidth);
border.right = BC_BORDER_RIGHT_HALF_COORD(p2t, propData->mRightBorderWidth);
@ -2393,8 +2402,7 @@ nsTableFrame::GetIncludedOuterBCBorder() const
nsMargin border(0, 0, 0, 0);
PRInt32 p2t = nsPresContext::AppUnitsPerCSSPixel();
BCPropertyData* propData = static_cast<BCPropertyData*>
(Properties().Get(TableBCProperty()));
BCPropertyData* propData = GetBCProperty();
if (propData) {
border.top += BC_BORDER_TOP_HALF_COORD(p2t, propData->mTopBorderWidth);
border.right += BC_BORDER_RIGHT_HALF_COORD(p2t, propData->mRightCellBorderWidth);
@ -3767,22 +3775,6 @@ nsTableFrame::ColumnHasCellSpacingBefore(PRInt32 aColIndex) const
return cellMap->GetNumCellsOriginatingInCol(aColIndex) > 0;
}
static void
CheckFixDamageArea(PRInt32 aNumRows,
PRInt32 aNumCols,
nsRect& aDamageArea)
{
if (((aDamageArea.XMost() > aNumCols) && (aDamageArea.width != 1) && (aNumCols != 0)) ||
((aDamageArea.YMost() > aNumRows) && (aDamageArea.height != 1) && (aNumRows != 0))) {
// the damage area was set incorrectly, just be safe and make it the entire table
NS_ASSERTION(false, "invalid BC damage area");
aDamageArea.x = 0;
aDamageArea.y = 0;
aDamageArea.width = aNumCols;
aDamageArea.height = aNumRows;
}
}
/********************************************************************************
* Collapsing Borders
*
@ -3796,31 +3788,77 @@ CheckFixDamageArea(PRInt32 aNumRows,
* 5) if all border styles are NONE, then that's the computed border style.
*******************************************************************************/
void
nsTableFrame::SetBCDamageArea(const nsRect& aValue)
{
nsRect newRect(aValue);
newRect.width = NS_MAX(1, newRect.width);
newRect.height = NS_MAX(1, newRect.height);
#ifdef DEBUG
#define VerifyNonNegativeDamageRect(r) \
NS_ASSERTION((r).x >= 0, "negative col index"); \
NS_ASSERTION((r).y >= 0, "negative row index"); \
NS_ASSERTION((r).width >= 0, "negative horizontal damage"); \
NS_ASSERTION((r).height >= 0, "negative vertical damage");
#define VerifyDamageRect(r) \
VerifyNonNegativeDamageRect(r); \
NS_ASSERTION((r).XMost() <= GetColCount(), \
"horizontal damage extends outside table"); \
NS_ASSERTION((r).YMost() <= GetRowCount(), \
"vertical damage extends outside table");
#endif
void
nsTableFrame::AddBCDamageArea(const nsRect& aValue)
{
NS_ASSERTION(IsBorderCollapse(), "invalid AddBCDamageArea call");
#ifdef DEBUG
VerifyDamageRect(aValue);
#endif
if (!IsBorderCollapse()) {
NS_ASSERTION(false, "invalid call - not border collapse model");
return;
}
SetNeedToCalcBCBorders(true);
// Get the property
FrameProperties props = Properties();
BCPropertyData* value = static_cast<BCPropertyData*>
(props.Get(TableBCProperty()));
if (!value) {
value = new BCPropertyData();
props.Set(TableBCProperty(), value);
BCPropertyData* value = GetBCProperty(true);
if (value) {
#ifdef DEBUG
VerifyNonNegativeDamageRect(value->mDamageArea);
#endif
// Clamp the old damage area to the current table area in case it shrunk.
PRInt32 cols = GetColCount();
if (value->mDamageArea.XMost() > cols) {
if (value->mDamageArea.x > cols) {
value->mDamageArea.x = cols;
value->mDamageArea.width = 0;
}
else {
value->mDamageArea.width = cols - value->mDamageArea.x;
}
}
PRInt32 rows = GetRowCount();
if (value->mDamageArea.YMost() > rows) {
if (value->mDamageArea.y > rows) {
value->mDamageArea.y = rows;
value->mDamageArea.height = 0;
}
else {
value->mDamageArea.height = rows - value->mDamageArea.y;
}
}
// Construct a union of the new and old damage areas.
value->mDamageArea.UnionRect(value->mDamageArea, aValue);
}
// for now just construct a union of the new and old damage areas
value->mDamageArea.UnionRect(value->mDamageArea, newRect);
CheckFixDamageArea(GetRowCount(), GetColCount(), value->mDamageArea);
}
void
nsTableFrame::SetFullBCDamageArea()
{
NS_ASSERTION(IsBorderCollapse(), "invalid SetFullBCDamageArea call");
SetNeedToCalcBCBorders(true);
BCPropertyData* value = GetBCProperty(true);
if (value) {
value->mDamageArea = nsRect(0, 0, GetColCount(), GetRowCount());
}
}
/* BCCellBorder represents a border segment which can be either a horizontal
* or a vertical segment. For each segment we need to know the color, width,
* style, who owns it and how long it is in cellmap coordinates.
@ -4216,7 +4254,9 @@ BCMapCellIterator::SetNewRow(nsTableRowFrame* aRow)
CellData* cellData = row.SafeElementAt(mColIndex);
if (!cellData) { // add a dead cell data
nsRect damageArea;
cellData = mCellMap->AppendCell(*mTableCellMap, nsnull, rgRowIndex, false, damageArea); if (!cellData) ABORT1(false);
cellData = mCellMap->AppendCell(*mTableCellMap, nsnull, rgRowIndex,
false, 0, damageArea);
if (!cellData) ABORT1(false);
}
if (cellData && (cellData->IsOrig() || cellData->IsDead())) {
break;
@ -4312,7 +4352,7 @@ BCMapCellIterator::Next(BCMapCellInfo& aMapInfo)
nsRect damageArea;
cellData =
static_cast<BCCellData*>(mCellMap->AppendCell(*mTableCellMap, nsnull,
rgRowIndex, false,
rgRowIndex, false, 0,
damageArea));
if (!cellData) ABORT0();
}
@ -4347,7 +4387,7 @@ BCMapCellIterator::PeekRight(BCMapCellInfo& aRefInfo,
nsRect damageArea;
cellData =
static_cast<BCCellData*>(mCellMap->AppendCell(*mTableCellMap, nsnull,
rgRowIndex, false,
rgRowIndex, false, 0,
damageArea));
if (!cellData) ABORT0();
}
@ -4405,7 +4445,7 @@ BCMapCellIterator::PeekBottom(BCMapCellInfo& aRefInfo,
nsRect damageArea;
cellData =
static_cast<BCCellData*>(cellMap->AppendCell(*mTableCellMap, nsnull,
rgRowIndex, false,
rgRowIndex, false, 0,
damageArea));
if (!cellData) ABORT0();
}
@ -5469,13 +5509,11 @@ nsTableFrame::CalcBCBorders()
return; // nothing to do
// Get the property holding the table damage area and border widths
BCPropertyData* propData = static_cast<BCPropertyData*>
(Properties().Get(TableBCProperty()));
BCPropertyData* propData = GetBCProperty();
if (!propData) ABORT0();
CheckFixDamageArea(numRows, numCols, propData->mDamageArea);
// calculate an expanded damage area
nsRect damageArea(propData->mDamageArea);
ExpandBCDamageArea(damageArea);

View File

@ -58,6 +58,7 @@ class nsStyleContext;
struct nsTableReflowState;
struct nsStylePosition;
struct BCPropertyData;
static inline bool IS_TABLE_CELL(nsIAtom* frameType) {
return nsGkAtoms::tableCellFrame == frameType ||
@ -291,7 +292,7 @@ public:
friend class nsDelayedCalcBCBorders;
void SetBCDamageArea(const nsRect& aValue);
void AddBCDamageArea(const nsRect& aValue);
bool BCRecalcNeeded(nsStyleContext* aOldStyleContext,
nsStyleContext* aNewStyleContext);
void PaintBCBorders(nsRenderingContext& aRenderingContext,
@ -688,10 +689,13 @@ public:
nsTArray<nsTableColFrame*>& GetColCache();
protected:
void SetBorderCollapse(bool aValue);
BCPropertyData* GetBCProperty(bool aCreateIfNecessary = false) const;
void SetFullBCDamageArea();
void CalcBCBorders();
void ExpandBCDamageArea(nsRect& aRect) const;

View File

@ -195,7 +195,7 @@ nsTableRowFrame::DidSetStyleContext(nsStyleContext* aOldStyleContext)
if (tableFrame->IsBorderCollapse() &&
tableFrame->BCRecalcNeeded(aOldStyleContext, GetStyleContext())) {
nsRect damageArea(0, GetRowIndex(), tableFrame->GetColCount(), 1);
tableFrame->SetBCDamageArea(damageArea);
tableFrame->AddBCDamageArea(damageArea);
}
return;
}

View File

@ -1389,7 +1389,7 @@ nsTableRowGroupFrame::DidSetStyleContext(nsStyleContext* aOldStyleContext)
tableFrame->BCRecalcNeeded(aOldStyleContext, GetStyleContext())) {
nsRect damageArea(0, GetStartRowIndex(), tableFrame->GetColCount(),
GetRowCount());
tableFrame->SetBCDamageArea(damageArea);
tableFrame->AddBCDamageArea(damageArea);
}
return;
}

View File

@ -268,6 +268,12 @@ moz_malloc_usable_size(void *ptr)
#endif
}
size_t moz_malloc_size_of(const void *ptr, size_t computedSize)
{
size_t usable = moz_malloc_usable_size((void *)ptr);
return usable ? usable : computedSize;
}
namespace mozilla {
const fallible_t fallible = fallible_t();

View File

@ -53,7 +53,6 @@
#include "xpcom-config.h"
#define MOZALLOC_HAVE_XMALLOC
#define MOZALLOC_HAVE_MALLOC_USABLE_SIZE
#if defined(MOZALLOC_EXPORT)
/* do nothing: it's been defined to __declspec(dllexport) by
@ -136,6 +135,8 @@ MOZALLOC_EXPORT char* moz_strdup(const char* str)
MOZALLOC_EXPORT size_t moz_malloc_usable_size(void *ptr);
MOZALLOC_EXPORT size_t moz_malloc_size_of(const void *ptr, size_t computedSize);
#if defined(HAVE_STRNDUP)
MOZALLOC_EXPORT char* moz_xstrndup(const char* str, size_t strsize)
NS_ATTR_MALLOC NS_WARN_UNUSED_RESULT;

View File

@ -401,11 +401,11 @@ Preferences::ReadUserPrefs(nsIFile *aFile)
nsresult rv;
if (nsnull == aFile) {
rv = UseDefaultPrefFile();
UseUserPrefFile();
NotifyServiceObservers(NS_PREFSERVICE_READ_TOPIC_ID);
rv = UseDefaultPrefFile();
UseUserPrefFile();
} else {
rv = ReadAndOwnUserPrefFile(aFile);
}

View File

@ -169,8 +169,8 @@ nsDiskCacheMap::Open(nsILocalFile * cacheDirectory)
{
// extra scope so the compiler doesn't barf on the above gotos jumping
// past this declaration down here
PRUint32 overhead = moz_malloc_usable_size(mRecordArray);
overhead = overhead ? overhead : mHeader.mRecordCount * sizeof(nsDiskCacheRecord);
PRUint32 overhead =
moz_malloc_size_of(mRecordArray, mHeader.mRecordCount * sizeof(nsDiskCacheRecord));
mozilla::Telemetry::Accumulate(mozilla::Telemetry::HTTP_DISK_CACHE_OVERHEAD,
overhead);
}

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