зеркало из https://github.com/mozilla/pjs.git
Merge m-i to m-c.
This commit is contained in:
Коммит
2751180900
|
@ -38,7 +38,7 @@
|
|||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "nsApplicationAccessibleWrap.h"
|
||||
#include "ApplicationAccessibleWrap.h"
|
||||
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsMai.h"
|
||||
|
@ -466,25 +466,19 @@ mai_util_remove_key_event_listener (guint remove_listener)
|
|||
}
|
||||
}
|
||||
|
||||
AtkObject *
|
||||
AtkObject*
|
||||
mai_util_get_root(void)
|
||||
{
|
||||
if (nsAccessibilityService::IsShutdown()) {
|
||||
// We've shutdown, try to use gail instead
|
||||
// (to avoid assert in spi_atk_tidy_windows())
|
||||
if (gail_get_root)
|
||||
return gail_get_root();
|
||||
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
nsApplicationAccessible *applicationAcc =
|
||||
nsAccessNode::GetApplicationAccessible();
|
||||
|
||||
if (applicationAcc)
|
||||
return applicationAcc->GetAtkObject();
|
||||
if (nsAccessibilityService::IsShutdown()) {
|
||||
// We've shutdown, try to use gail instead
|
||||
// (to avoid assert in spi_atk_tidy_windows())
|
||||
if (gail_get_root)
|
||||
return gail_get_root();
|
||||
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
return nsAccessNode::GetApplicationAccessible()->GetAtkObject();
|
||||
}
|
||||
|
||||
G_CONST_RETURN gchar *
|
||||
|
@ -550,15 +544,15 @@ add_listener (GSignalEmissionHook listener,
|
|||
|
||||
static nsresult LoadGtkModule(GnomeAccessibilityModule& aModule);
|
||||
|
||||
// nsApplicationAccessibleWrap
|
||||
// ApplicationAccessibleWrap
|
||||
|
||||
nsApplicationAccessibleWrap::nsApplicationAccessibleWrap():
|
||||
nsApplicationAccessible()
|
||||
ApplicationAccessibleWrap::ApplicationAccessibleWrap():
|
||||
ApplicationAccessible()
|
||||
{
|
||||
MAI_LOG_DEBUG(("======Create AppRootAcc=%p\n", (void*)this));
|
||||
MAI_LOG_DEBUG(("======Create AppRootAcc=%p\n", (void*)this));
|
||||
}
|
||||
|
||||
nsApplicationAccessibleWrap::~nsApplicationAccessibleWrap()
|
||||
ApplicationAccessibleWrap::~ApplicationAccessibleWrap()
|
||||
{
|
||||
MAI_LOG_DEBUG(("======Destory AppRootAcc=%p\n", (void*)this));
|
||||
nsAccessibleWrap::ShutdownAtkObject();
|
||||
|
@ -613,7 +607,7 @@ toplevel_event_watcher(GSignalInvocationHint* ihint,
|
|||
}
|
||||
|
||||
bool
|
||||
nsApplicationAccessibleWrap::Init()
|
||||
ApplicationAccessibleWrap::Init()
|
||||
{
|
||||
if (ShouldA11yBeEnabled()) {
|
||||
// load and initialize gail library
|
||||
|
@ -655,11 +649,11 @@ nsApplicationAccessibleWrap::Init()
|
|||
}
|
||||
}
|
||||
|
||||
return nsApplicationAccessible::Init();
|
||||
return ApplicationAccessible::Init();
|
||||
}
|
||||
|
||||
void
|
||||
nsApplicationAccessibleWrap::Unload()
|
||||
ApplicationAccessibleWrap::Unload()
|
||||
{
|
||||
if (sToplevel_event_hook_added) {
|
||||
sToplevel_event_hook_added = false;
|
||||
|
@ -697,7 +691,7 @@ nsApplicationAccessibleWrap::Unload()
|
|||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsApplicationAccessibleWrap::GetName(nsAString& aName)
|
||||
ApplicationAccessibleWrap::GetName(nsAString& aName)
|
||||
{
|
||||
// ATK doesn't provide a way to obtain an application name (for example,
|
||||
// Firefox or Thunderbird) like IA2 does. Thus let's return an application
|
||||
|
@ -707,7 +701,7 @@ nsApplicationAccessibleWrap::GetName(nsAString& aName)
|
|||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsApplicationAccessibleWrap::GetNativeInterface(void **aOutAccessible)
|
||||
ApplicationAccessibleWrap::GetNativeInterface(void** aOutAccessible)
|
||||
{
|
||||
*aOutAccessible = nsnull;
|
||||
|
||||
|
@ -745,9 +739,9 @@ gboolean fireRootAccessibleAddedCB(gpointer data)
|
|||
}
|
||||
|
||||
bool
|
||||
nsApplicationAccessibleWrap::AppendChild(nsAccessible *aChild)
|
||||
ApplicationAccessibleWrap::AppendChild(nsAccessible* aChild)
|
||||
{
|
||||
if (!nsApplicationAccessible::AppendChild(aChild))
|
||||
if (!ApplicationAccessible::AppendChild(aChild))
|
||||
return false;
|
||||
|
||||
AtkObject *atkAccessible = nsAccessibleWrap::GetAtkObject(aChild);
|
||||
|
@ -772,7 +766,7 @@ nsApplicationAccessibleWrap::AppendChild(nsAccessible *aChild)
|
|||
}
|
||||
|
||||
bool
|
||||
nsApplicationAccessibleWrap::RemoveChild(nsAccessible* aChild)
|
||||
ApplicationAccessibleWrap::RemoveChild(nsAccessible* aChild)
|
||||
{
|
||||
PRInt32 index = aChild->IndexInParent();
|
||||
|
||||
|
@ -781,11 +775,11 @@ nsApplicationAccessibleWrap::RemoveChild(nsAccessible* aChild)
|
|||
g_signal_emit_by_name(mAtkObject, "children_changed::remove", index,
|
||||
atkAccessible, NULL);
|
||||
|
||||
return nsApplicationAccessible::RemoveChild(aChild);
|
||||
return ApplicationAccessible::RemoveChild(aChild);
|
||||
}
|
||||
|
||||
void
|
||||
nsApplicationAccessibleWrap::PreCreate()
|
||||
ApplicationAccessibleWrap::PreCreate()
|
||||
{
|
||||
if (!sATKChecked) {
|
||||
sATKLib = PR_LoadLibrary(sATKLibName);
|
|
@ -38,20 +38,20 @@
|
|||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef __NS_APP_ROOT_ACCESSIBLE_H__
|
||||
#define __NS_APP_ROOT_ACCESSIBLE_H__
|
||||
#ifndef MOZILLA_A11Y_APPLICATION_ACCESSIBLE_WRAP_H__
|
||||
#define MOZILLA_A11Y_APPLICATION_ACCESSIBLE_WRAP_H__
|
||||
|
||||
#include "nsApplicationAccessible.h"
|
||||
#include "ApplicationAccessible.h"
|
||||
|
||||
class nsApplicationAccessibleWrap: public nsApplicationAccessible
|
||||
class ApplicationAccessibleWrap: public ApplicationAccessible
|
||||
{
|
||||
public:
|
||||
static void Unload();
|
||||
static void PreCreate();
|
||||
|
||||
public:
|
||||
nsApplicationAccessibleWrap();
|
||||
virtual ~nsApplicationAccessibleWrap();
|
||||
ApplicationAccessibleWrap();
|
||||
virtual ~ApplicationAccessibleWrap();
|
||||
|
||||
// nsAccessNode
|
||||
virtual bool Init();
|
|
@ -53,7 +53,7 @@ CPPSRCS = \
|
|||
nsAccessibleWrap.cpp \
|
||||
nsDocAccessibleWrap.cpp \
|
||||
nsRootAccessibleWrap.cpp \
|
||||
nsApplicationAccessibleWrap.cpp \
|
||||
ApplicationAccessibleWrap.cpp \
|
||||
nsMaiInterfaceComponent.cpp \
|
||||
nsMaiInterfaceAction.cpp \
|
||||
nsMaiInterfaceText.cpp \
|
||||
|
|
|
@ -38,7 +38,6 @@
|
|||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "nsAccessNodeWrap.h"
|
||||
#include "nsApplicationAccessibleWrap.h"
|
||||
|
||||
/* For documentation of the accessibility architecture,
|
||||
* see http://lxr.mozilla.org/seamonkey/source/accessible/accessible-docs.html
|
||||
|
|
|
@ -41,9 +41,9 @@
|
|||
#include "nsAccessibleWrap.h"
|
||||
|
||||
#include "Accessible-inl.h"
|
||||
#include "ApplicationAccessibleWrap.h"
|
||||
#include "InterfaceInitFuncs.h"
|
||||
#include "nsAccUtils.h"
|
||||
#include "nsApplicationAccessibleWrap.h"
|
||||
#include "nsIAccessibleRelation.h"
|
||||
#include "nsRootAccessible.h"
|
||||
#include "nsDocAccessibleWrap.h"
|
||||
|
@ -68,7 +68,7 @@ using namespace mozilla::a11y;
|
|||
nsAccessibleWrap::EAvailableAtkSignals nsAccessibleWrap::gAvailableAtkSignals =
|
||||
eUnknown;
|
||||
|
||||
//defined in nsApplicationAccessibleWrap.cpp
|
||||
//defined in ApplicationAccessibleWrap.cpp
|
||||
extern "C" GType g_atk_hyperlink_impl_type;
|
||||
|
||||
/* MaiAtkObject */
|
||||
|
@ -976,25 +976,20 @@ refRelationSetCB(AtkObject *aAtkObj)
|
|||
// for it.
|
||||
nsAccessibleWrap *GetAccessibleWrap(AtkObject *aAtkObj)
|
||||
{
|
||||
NS_ENSURE_TRUE(IS_MAI_OBJECT(aAtkObj), nsnull);
|
||||
nsAccessibleWrap *tmpAccWrap = MAI_ATK_OBJECT(aAtkObj)->accWrap;
|
||||
NS_ENSURE_TRUE(IS_MAI_OBJECT(aAtkObj), nsnull);
|
||||
nsAccessibleWrap* accWrap = MAI_ATK_OBJECT(aAtkObj)->accWrap;
|
||||
|
||||
// Check if AccessibleWrap was deconstructed
|
||||
if (tmpAccWrap == nsnull) {
|
||||
return nsnull;
|
||||
}
|
||||
// Check if the accessible was deconstructed.
|
||||
if (!accWrap)
|
||||
return nsnull;
|
||||
|
||||
NS_ENSURE_TRUE(tmpAccWrap->GetAtkObject() == aAtkObj, nsnull);
|
||||
NS_ENSURE_TRUE(accWrap->GetAtkObject() == aAtkObj, nsnull);
|
||||
|
||||
nsApplicationAccessible *applicationAcc =
|
||||
nsAccessNode::GetApplicationAccessible();
|
||||
nsAccessibleWrap* tmpAppAccWrap =
|
||||
static_cast<nsAccessibleWrap*>(applicationAcc);
|
||||
nsAccessibleWrap* appAccWrap = nsAccessNode::GetApplicationAccessible();
|
||||
if (appAccWrap != accWrap && !accWrap->IsValidObject())
|
||||
return nsnull;
|
||||
|
||||
if (tmpAppAccWrap != tmpAccWrap && !tmpAccWrap->IsValidObject())
|
||||
return nsnull;
|
||||
|
||||
return tmpAccWrap;
|
||||
return accWrap;
|
||||
}
|
||||
|
||||
nsresult
|
||||
|
|
|
@ -39,9 +39,9 @@
|
|||
|
||||
#include "AccEvent.h"
|
||||
|
||||
#include "ApplicationAccessibleWrap.h"
|
||||
#include "nsAccessibilityService.h"
|
||||
#include "nsAccUtils.h"
|
||||
#include "nsApplicationAccessibleWrap.h"
|
||||
#include "nsDocAccessible.h"
|
||||
#include "nsIAccessibleText.h"
|
||||
#include "nsAccEvent.h"
|
||||
|
@ -155,7 +155,7 @@ AccEvent::CaptureIsFromUserInput(EIsFromUserInput aIsFromUserInput)
|
|||
// XXX: remove this hack during reorganization of 506907. Meanwhile we
|
||||
// want to get rid an assertion for application accessible events which
|
||||
// don't have DOM node (see bug 506206).
|
||||
nsApplicationAccessible *applicationAcc =
|
||||
ApplicationAccessible* applicationAcc =
|
||||
nsAccessNode::GetApplicationAccessible();
|
||||
|
||||
if (mAccessible != static_cast<nsIAccessible*>(applicationAcc))
|
||||
|
|
|
@ -69,7 +69,6 @@ CPPSRCS = \
|
|||
nsBaseWidgetAccessible.cpp \
|
||||
nsEventShell.cpp \
|
||||
nsRootAccessible.cpp \
|
||||
nsApplicationAccessible.cpp \
|
||||
nsCaretAccessible.cpp \
|
||||
nsTextAccessible.cpp \
|
||||
nsTextEquivUtils.cpp \
|
||||
|
|
|
@ -38,9 +38,9 @@
|
|||
|
||||
#include "nsAccDocManager.h"
|
||||
|
||||
#include "ApplicationAccessible.h"
|
||||
#include "nsAccessibilityService.h"
|
||||
#include "nsAccUtils.h"
|
||||
#include "nsApplicationAccessible.h"
|
||||
#include "nsARIAMap.h"
|
||||
#include "nsRootAccessibleWrap.h"
|
||||
#include "States.h"
|
||||
|
|
|
@ -38,9 +38,9 @@
|
|||
|
||||
#include "nsAccessNode.h"
|
||||
|
||||
#include "ApplicationAccessibleWrap.h"
|
||||
#include "nsAccessibilityService.h"
|
||||
#include "nsAccUtils.h"
|
||||
#include "nsApplicationAccessibleWrap.h"
|
||||
#include "nsCoreUtils.h"
|
||||
#include "nsRootAccessible.h"
|
||||
|
||||
|
@ -67,7 +67,7 @@ nsIStringBundle *nsAccessNode::gStringBundle = 0;
|
|||
|
||||
bool nsAccessNode::gIsFormFillEnabled = false;
|
||||
|
||||
nsApplicationAccessible *nsAccessNode::gApplicationAccessible = nsnull;
|
||||
ApplicationAccessible* nsAccessNode::gApplicationAccessible = nsnull;
|
||||
|
||||
/*
|
||||
* Class nsAccessNode
|
||||
|
@ -130,18 +130,16 @@ nsAccessNode::Shutdown()
|
|||
mDoc = nsnull;
|
||||
}
|
||||
|
||||
nsApplicationAccessible*
|
||||
ApplicationAccessible*
|
||||
nsAccessNode::GetApplicationAccessible()
|
||||
{
|
||||
NS_ASSERTION(!nsAccessibilityService::IsShutdown(),
|
||||
"Accessibility wasn't initialized!");
|
||||
|
||||
if (!gApplicationAccessible) {
|
||||
nsApplicationAccessibleWrap::PreCreate();
|
||||
ApplicationAccessibleWrap::PreCreate();
|
||||
|
||||
gApplicationAccessible = new nsApplicationAccessibleWrap();
|
||||
if (!gApplicationAccessible)
|
||||
return nsnull;
|
||||
gApplicationAccessible = new ApplicationAccessibleWrap();
|
||||
|
||||
// Addref on create. Will Release in ShutdownXPAccessibility()
|
||||
NS_ADDREF(gApplicationAccessible);
|
||||
|
@ -200,7 +198,7 @@ void nsAccessNode::ShutdownXPAccessibility()
|
|||
|
||||
// Release gApplicationAccessible after everything else is shutdown
|
||||
// so we don't accidently create it again while tearing down root accessibles
|
||||
nsApplicationAccessibleWrap::Unload();
|
||||
ApplicationAccessibleWrap::Unload();
|
||||
if (gApplicationAccessible) {
|
||||
gApplicationAccessible->Shutdown();
|
||||
NS_RELEASE(gApplicationAccessible);
|
||||
|
|
|
@ -53,8 +53,8 @@
|
|||
#include "nsIStringBundle.h"
|
||||
#include "nsWeakReference.h"
|
||||
|
||||
class ApplicationAccessible;
|
||||
class nsAccessNode;
|
||||
class nsApplicationAccessible;
|
||||
class nsDocAccessible;
|
||||
class nsIAccessibleDocument;
|
||||
class nsRootAccessible;
|
||||
|
@ -83,7 +83,7 @@ public:
|
|||
/**
|
||||
* Return an application accessible.
|
||||
*/
|
||||
static nsApplicationAccessible* GetApplicationAccessible();
|
||||
static ApplicationAccessible* GetApplicationAccessible();
|
||||
|
||||
/**
|
||||
* Return the document accessible for this access node.
|
||||
|
@ -174,7 +174,7 @@ private:
|
|||
nsAccessNode(const nsAccessNode&) MOZ_DELETE;
|
||||
nsAccessNode& operator =(const nsAccessNode&) MOZ_DELETE;
|
||||
|
||||
static nsApplicationAccessible *gApplicationAccessible;
|
||||
static ApplicationAccessible* gApplicationAccessible;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -40,6 +40,7 @@
|
|||
|
||||
// NOTE: alphabetically ordered
|
||||
#include "Accessible-inl.h"
|
||||
#include "ApplicationAccessibleWrap.h"
|
||||
#include "ARIAGridAccessibleWrap.h"
|
||||
#ifdef MOZ_ACCESSIBILITY_ATK
|
||||
#include "AtkSocketAccessible.h"
|
||||
|
@ -48,7 +49,6 @@
|
|||
#include "nsAccessiblePivot.h"
|
||||
#include "nsAccUtils.h"
|
||||
#include "nsARIAMap.h"
|
||||
#include "nsApplicationAccessibleWrap.h"
|
||||
#include "nsIAccessibleProvider.h"
|
||||
#include "nsHTMLCanvasAccessible.h"
|
||||
#include "nsHTMLImageMapAccessible.h"
|
||||
|
@ -678,7 +678,7 @@ nsAccessibilityService::RecreateAccessible(nsIPresShell* aPresShell,
|
|||
// nsIAccessibleRetrieval
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsAccessibilityService::GetApplicationAccessible(nsIAccessible **aAccessibleApplication)
|
||||
nsAccessibilityService::GetApplicationAccessible(nsIAccessible** aAccessibleApplication)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aAccessibleApplication);
|
||||
|
||||
|
@ -1724,7 +1724,7 @@ nsAccessible*
|
|||
nsAccessibilityService::AddNativeRootAccessible(void* aAtkAccessible)
|
||||
{
|
||||
#ifdef MOZ_ACCESSIBILITY_ATK
|
||||
nsApplicationAccessible* applicationAcc =
|
||||
ApplicationAccessible* applicationAcc =
|
||||
nsAccessNode::GetApplicationAccessible();
|
||||
if (!applicationAcc)
|
||||
return nsnull;
|
||||
|
@ -1745,7 +1745,7 @@ void
|
|||
nsAccessibilityService::RemoveNativeRootAccessible(nsAccessible* aAccessible)
|
||||
{
|
||||
#ifdef MOZ_ACCESSIBILITY_ATK
|
||||
nsApplicationAccessible* applicationAcc =
|
||||
ApplicationAccessible* applicationAcc =
|
||||
nsAccessNode::GetApplicationAccessible();
|
||||
|
||||
if (applicationAcc)
|
||||
|
|
|
@ -63,7 +63,7 @@ FocusManager* FocusMgr();
|
|||
/**
|
||||
* Perform initialization that should be done as soon as possible, in order
|
||||
* to minimize startup time.
|
||||
* XXX: this function and the next defined in nsApplicationAccessibleWrap.cpp
|
||||
* XXX: this function and the next defined in ApplicationAccessibleWrap.cpp
|
||||
*/
|
||||
void PreInit();
|
||||
|
||||
|
|
|
@ -42,7 +42,6 @@
|
|||
|
||||
#include "Accessible-inl.h"
|
||||
#include "nsAccessibilityService.h"
|
||||
#include "nsApplicationAccessibleWrap.h"
|
||||
#include "nsAccUtils.h"
|
||||
#include "nsCoreUtils.h"
|
||||
#include "Relation.h"
|
||||
|
|
|
@ -40,7 +40,7 @@
|
|||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "nsApplicationAccessible.h"
|
||||
#include "ApplicationAccessible.h"
|
||||
|
||||
#include "nsAccessibilityService.h"
|
||||
#include "nsAccUtils.h"
|
||||
|
@ -57,7 +57,7 @@
|
|||
|
||||
using namespace mozilla::a11y;
|
||||
|
||||
nsApplicationAccessible::nsApplicationAccessible() :
|
||||
ApplicationAccessible::ApplicationAccessible() :
|
||||
nsAccessibleWrap(nsnull, nsnull)
|
||||
{
|
||||
mFlags |= eApplicationAccessible;
|
||||
|
@ -66,14 +66,14 @@ nsApplicationAccessible::nsApplicationAccessible() :
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsISupports
|
||||
|
||||
NS_IMPL_ISUPPORTS_INHERITED1(nsApplicationAccessible, nsAccessible,
|
||||
NS_IMPL_ISUPPORTS_INHERITED1(ApplicationAccessible, nsAccessible,
|
||||
nsIAccessibleApplication)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsIAccessible
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsApplicationAccessible::GetParent(nsIAccessible **aAccessible)
|
||||
ApplicationAccessible::GetParent(nsIAccessible** aAccessible)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aAccessible);
|
||||
*aAccessible = nsnull;
|
||||
|
@ -81,7 +81,7 @@ nsApplicationAccessible::GetParent(nsIAccessible **aAccessible)
|
|||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsApplicationAccessible::GetNextSibling(nsIAccessible **aNextSibling)
|
||||
ApplicationAccessible::GetNextSibling(nsIAccessible** aNextSibling)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aNextSibling);
|
||||
*aNextSibling = nsnull;
|
||||
|
@ -89,7 +89,7 @@ nsApplicationAccessible::GetNextSibling(nsIAccessible **aNextSibling)
|
|||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsApplicationAccessible::GetPreviousSibling(nsIAccessible **aPreviousSibling)
|
||||
ApplicationAccessible::GetPreviousSibling(nsIAccessible** aPreviousSibling)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aPreviousSibling);
|
||||
*aPreviousSibling = nsnull;
|
||||
|
@ -97,7 +97,7 @@ nsApplicationAccessible::GetPreviousSibling(nsIAccessible **aPreviousSibling)
|
|||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsApplicationAccessible::GetName(nsAString& aName)
|
||||
ApplicationAccessible::GetName(nsAString& aName)
|
||||
{
|
||||
aName.Truncate();
|
||||
|
||||
|
@ -125,25 +125,25 @@ nsApplicationAccessible::GetName(nsAString& aName)
|
|||
}
|
||||
|
||||
void
|
||||
nsApplicationAccessible::Description(nsString &aDescription)
|
||||
ApplicationAccessible::Description(nsString& aDescription)
|
||||
{
|
||||
aDescription.Truncate();
|
||||
}
|
||||
|
||||
void
|
||||
nsApplicationAccessible::Value(nsString& aValue)
|
||||
ApplicationAccessible::Value(nsString& aValue)
|
||||
{
|
||||
aValue.Truncate();
|
||||
}
|
||||
|
||||
PRUint64
|
||||
nsApplicationAccessible::State()
|
||||
ApplicationAccessible::State()
|
||||
{
|
||||
return IsDefunct() ? states::DEFUNCT : 0;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsApplicationAccessible::GetAttributes(nsIPersistentProperties **aAttributes)
|
||||
ApplicationAccessible::GetAttributes(nsIPersistentProperties** aAttributes)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aAttributes);
|
||||
*aAttributes = nsnull;
|
||||
|
@ -151,9 +151,9 @@ nsApplicationAccessible::GetAttributes(nsIPersistentProperties **aAttributes)
|
|||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsApplicationAccessible::GroupPosition(PRInt32 *aGroupLevel,
|
||||
PRInt32 *aSimilarItemsInGroup,
|
||||
PRInt32 *aPositionInGroup)
|
||||
ApplicationAccessible::GroupPosition(PRInt32* aGroupLevel,
|
||||
PRInt32* aSimilarItemsInGroup,
|
||||
PRInt32* aPositionInGroup)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aGroupLevel);
|
||||
*aGroupLevel = 0;
|
||||
|
@ -165,14 +165,14 @@ nsApplicationAccessible::GroupPosition(PRInt32 *aGroupLevel,
|
|||
}
|
||||
|
||||
nsAccessible*
|
||||
nsApplicationAccessible::ChildAtPoint(PRInt32 aX, PRInt32 aY,
|
||||
EWhichChildAtPoint aWhichChild)
|
||||
ApplicationAccessible::ChildAtPoint(PRInt32 aX, PRInt32 aY,
|
||||
EWhichChildAtPoint aWhichChild)
|
||||
{
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
nsAccessible*
|
||||
nsApplicationAccessible::FocusedChild()
|
||||
ApplicationAccessible::FocusedChild()
|
||||
{
|
||||
nsAccessible* focus = FocusMgr()->FocusedAccessible();
|
||||
if (focus && focus->Parent() == this)
|
||||
|
@ -182,14 +182,14 @@ nsApplicationAccessible::FocusedChild()
|
|||
}
|
||||
|
||||
Relation
|
||||
nsApplicationAccessible::RelationByType(PRUint32 aRelationType)
|
||||
ApplicationAccessible::RelationByType(PRUint32 aRelationType)
|
||||
{
|
||||
return Relation();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsApplicationAccessible::GetBounds(PRInt32 *aX, PRInt32 *aY,
|
||||
PRInt32 *aWidth, PRInt32 *aHeight)
|
||||
ApplicationAccessible::GetBounds(PRInt32* aX, PRInt32* aY,
|
||||
PRInt32* aWidth, PRInt32* aHeight)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aX);
|
||||
*aX = 0;
|
||||
|
@ -203,46 +203,46 @@ nsApplicationAccessible::GetBounds(PRInt32 *aX, PRInt32 *aY,
|
|||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsApplicationAccessible::SetSelected(bool aIsSelected)
|
||||
ApplicationAccessible::SetSelected(bool aIsSelected)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsApplicationAccessible::TakeSelection()
|
||||
ApplicationAccessible::TakeSelection()
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsApplicationAccessible::TakeFocus()
|
||||
ApplicationAccessible::TakeFocus()
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
PRUint8
|
||||
nsApplicationAccessible::ActionCount()
|
||||
ApplicationAccessible::ActionCount()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsApplicationAccessible::GetActionName(PRUint8 aIndex, nsAString &aName)
|
||||
ApplicationAccessible::GetActionName(PRUint8 aIndex, nsAString& aName)
|
||||
{
|
||||
aName.Truncate();
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsApplicationAccessible::GetActionDescription(PRUint8 aIndex,
|
||||
nsAString &aDescription)
|
||||
ApplicationAccessible::GetActionDescription(PRUint8 aIndex,
|
||||
nsAString& aDescription)
|
||||
{
|
||||
aDescription.Truncate();
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsApplicationAccessible::DoAction(PRUint8 aIndex)
|
||||
ApplicationAccessible::DoAction(PRUint8 aIndex)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -251,7 +251,7 @@ nsApplicationAccessible::DoAction(PRUint8 aIndex)
|
|||
// nsIAccessibleApplication
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsApplicationAccessible::GetAppName(nsAString& aName)
|
||||
ApplicationAccessible::GetAppName(nsAString& aName)
|
||||
{
|
||||
aName.Truncate();
|
||||
|
||||
|
@ -267,7 +267,7 @@ nsApplicationAccessible::GetAppName(nsAString& aName)
|
|||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsApplicationAccessible::GetAppVersion(nsAString& aVersion)
|
||||
ApplicationAccessible::GetAppVersion(nsAString& aVersion)
|
||||
{
|
||||
aVersion.Truncate();
|
||||
|
||||
|
@ -283,14 +283,14 @@ nsApplicationAccessible::GetAppVersion(nsAString& aVersion)
|
|||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsApplicationAccessible::GetPlatformName(nsAString& aName)
|
||||
ApplicationAccessible::GetPlatformName(nsAString& aName)
|
||||
{
|
||||
aName.AssignLiteral("Gecko");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsApplicationAccessible::GetPlatformVersion(nsAString& aVersion)
|
||||
ApplicationAccessible::GetPlatformVersion(nsAString& aVersion)
|
||||
{
|
||||
aVersion.Truncate();
|
||||
|
||||
|
@ -309,20 +309,20 @@ nsApplicationAccessible::GetPlatformVersion(nsAString& aVersion)
|
|||
// nsAccessNode public methods
|
||||
|
||||
bool
|
||||
nsApplicationAccessible::Init()
|
||||
ApplicationAccessible::Init()
|
||||
{
|
||||
mAppInfo = do_GetService("@mozilla.org/xre/app-info;1");
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
nsApplicationAccessible::Shutdown()
|
||||
ApplicationAccessible::Shutdown()
|
||||
{
|
||||
mAppInfo = nsnull;
|
||||
}
|
||||
|
||||
bool
|
||||
nsApplicationAccessible::IsPrimaryForNode() const
|
||||
ApplicationAccessible::IsPrimaryForNode() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
@ -331,31 +331,31 @@ nsApplicationAccessible::IsPrimaryForNode() const
|
|||
// nsAccessible public methods
|
||||
|
||||
void
|
||||
nsApplicationAccessible::ApplyARIAState(PRUint64* aState)
|
||||
ApplicationAccessible::ApplyARIAState(PRUint64* aState)
|
||||
{
|
||||
}
|
||||
|
||||
role
|
||||
nsApplicationAccessible::NativeRole()
|
||||
ApplicationAccessible::NativeRole()
|
||||
{
|
||||
return roles::APP_ROOT;
|
||||
}
|
||||
|
||||
PRUint64
|
||||
nsApplicationAccessible::NativeState()
|
||||
ApplicationAccessible::NativeState()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
nsApplicationAccessible::InvalidateChildren()
|
||||
ApplicationAccessible::InvalidateChildren()
|
||||
{
|
||||
// Do nothing because application children are kept updated by AppendChild()
|
||||
// and RemoveChild() method calls.
|
||||
}
|
||||
|
||||
KeyBinding
|
||||
nsApplicationAccessible::AccessKey() const
|
||||
ApplicationAccessible::AccessKey() const
|
||||
{
|
||||
return KeyBinding();
|
||||
}
|
||||
|
@ -364,7 +364,7 @@ nsApplicationAccessible::AccessKey() const
|
|||
// nsAccessible protected methods
|
||||
|
||||
void
|
||||
nsApplicationAccessible::CacheChildren()
|
||||
ApplicationAccessible::CacheChildren()
|
||||
{
|
||||
// CacheChildren is called only once for application accessible when its
|
||||
// children are requested because empty InvalidateChldren() prevents its
|
||||
|
@ -404,8 +404,8 @@ nsApplicationAccessible::CacheChildren()
|
|||
}
|
||||
|
||||
nsAccessible*
|
||||
nsApplicationAccessible::GetSiblingAtOffset(PRInt32 aOffset,
|
||||
nsresult* aError) const
|
||||
ApplicationAccessible::GetSiblingAtOffset(PRInt32 aOffset,
|
||||
nsresult* aError) const
|
||||
{
|
||||
if (aError)
|
||||
*aError = NS_OK; // fail peacefully
|
||||
|
@ -417,7 +417,7 @@ nsApplicationAccessible::GetSiblingAtOffset(PRInt32 aOffset,
|
|||
// nsIAccessible
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsApplicationAccessible::GetDOMNode(nsIDOMNode **aDOMNode)
|
||||
ApplicationAccessible::GetDOMNode(nsIDOMNode** aDOMNode)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aDOMNode);
|
||||
*aDOMNode = nsnull;
|
||||
|
@ -425,7 +425,7 @@ nsApplicationAccessible::GetDOMNode(nsIDOMNode **aDOMNode)
|
|||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsApplicationAccessible::GetDocument(nsIAccessibleDocument **aDocument)
|
||||
ApplicationAccessible::GetDocument(nsIAccessibleDocument** aDocument)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aDocument);
|
||||
*aDocument = nsnull;
|
||||
|
@ -433,7 +433,7 @@ nsApplicationAccessible::GetDocument(nsIAccessibleDocument **aDocument)
|
|||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsApplicationAccessible::GetRootDocument(nsIAccessibleDocument **aRootDocument)
|
||||
ApplicationAccessible::GetRootDocument(nsIAccessibleDocument** aRootDocument)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aRootDocument);
|
||||
*aRootDocument = nsnull;
|
||||
|
@ -441,20 +441,20 @@ nsApplicationAccessible::GetRootDocument(nsIAccessibleDocument **aRootDocument)
|
|||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsApplicationAccessible::ScrollTo(PRUint32 aScrollType)
|
||||
ApplicationAccessible::ScrollTo(PRUint32 aScrollType)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsApplicationAccessible::ScrollToPoint(PRUint32 aCoordinateType,
|
||||
PRInt32 aX, PRInt32 aY)
|
||||
ApplicationAccessible::ScrollToPoint(PRUint32 aCoordinateType,
|
||||
PRInt32 aX, PRInt32 aY)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsApplicationAccessible::GetLanguage(nsAString &aLanguage)
|
||||
ApplicationAccessible::GetLanguage(nsAString& aLanguage)
|
||||
{
|
||||
aLanguage.Truncate();
|
||||
return NS_OK;
|
|
@ -40,8 +40,8 @@
|
|||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef __NS_APPLICATION_ACCESSIBLE_H__
|
||||
#define __NS_APPLICATION_ACCESSIBLE_H__
|
||||
#ifndef MOZILLA_A11Y_APPLICATION_ACCESSIBLE_H__
|
||||
#define MOZILLA_A11Y_APPLICATION_ACCESSIBLE_H__
|
||||
|
||||
#include "nsAccessibleWrap.h"
|
||||
#include "nsIAccessibleApplication.h"
|
||||
|
@ -50,21 +50,21 @@
|
|||
#include "nsIXULAppInfo.h"
|
||||
|
||||
/**
|
||||
* nsApplicationAccessible is for the whole application of Mozilla.
|
||||
* Only one instance of nsApplicationAccessible exists for one Mozilla instance.
|
||||
* ApplicationAccessible is for the whole application of Mozilla.
|
||||
* Only one instance of ApplicationAccessible exists for one Mozilla instance.
|
||||
* And this one should be created when Mozilla Startup (if accessibility
|
||||
* feature has been enabled) and destroyed when Mozilla Shutdown.
|
||||
*
|
||||
* All the accessibility objects for toplevel windows are direct children of
|
||||
* the nsApplicationAccessible instance.
|
||||
* the ApplicationAccessible instance.
|
||||
*/
|
||||
|
||||
class nsApplicationAccessible: public nsAccessibleWrap,
|
||||
public nsIAccessibleApplication
|
||||
class ApplicationAccessible: public nsAccessibleWrap,
|
||||
public nsIAccessibleApplication
|
||||
{
|
||||
public:
|
||||
|
||||
nsApplicationAccessible();
|
||||
ApplicationAccessible();
|
||||
|
||||
// nsISupports
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
|
@ -15,6 +15,7 @@ LIBXUL_LIBRARY = 1
|
|||
|
||||
|
||||
CPPSRCS = \
|
||||
ApplicationAccessible.cpp \
|
||||
ARIAGridAccessible.cpp \
|
||||
FormControlAccessible.cpp \
|
||||
OuterDocAccessible.cpp \
|
||||
|
|
|
@ -38,12 +38,12 @@
|
|||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef __NS_APPLICATION_ACCESSIBLE_WRAP_H__
|
||||
#define __NS_APPLICATION_ACCESSIBLE_WRAP_H__
|
||||
#ifndef MOZILLA_A11Y_APPLICATION_ACCESSIBLE_WRAP_H__
|
||||
#define MOZILLA_A11Y_APPLICATION_ACCESSIBLE_WRAP_H__
|
||||
|
||||
#include "nsApplicationAccessible.h"
|
||||
#include "ApplicationAccessible.h"
|
||||
|
||||
class nsApplicationAccessibleWrap: public nsApplicationAccessible
|
||||
class ApplicationAccessibleWrap: public ApplicationAccessible
|
||||
{
|
||||
public:
|
||||
static void PreCreate() {}
|
|
@ -62,6 +62,7 @@ CMMSRCS = nsAccessNodeWrap.mm \
|
|||
|
||||
|
||||
EXPORTS = \
|
||||
ApplicationAccessibleWrap.h \
|
||||
ARIAGridAccessibleWrap.h \
|
||||
nsAccessNodeWrap.h \
|
||||
nsTextAccessibleWrap.h \
|
||||
|
@ -74,7 +75,6 @@ EXPORTS = \
|
|||
nsHyperTextAccessibleWrap.h \
|
||||
nsHTMLImageAccessibleWrap.h \
|
||||
nsHTMLTableAccessibleWrap.h \
|
||||
nsApplicationAccessibleWrap.h \
|
||||
mozDocAccessible.h \
|
||||
mozAccessible.h \
|
||||
mozAccessibleProtocol.h \
|
||||
|
|
|
@ -38,7 +38,7 @@
|
|||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "nsApplicationAccessibleWrap.h"
|
||||
#include "ApplicationAccessibleWrap.h"
|
||||
|
||||
#include "AccessibleApplication_i.c"
|
||||
|
||||
|
@ -48,11 +48,11 @@
|
|||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsISupports
|
||||
NS_IMPL_ISUPPORTS_INHERITED0(nsApplicationAccessibleWrap,
|
||||
nsApplicationAccessible)
|
||||
NS_IMPL_ISUPPORTS_INHERITED0(ApplicationAccessibleWrap,
|
||||
ApplicationAccessible)
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsApplicationAccessibleWrap::GetAttributes(nsIPersistentProperties** aAttributes)
|
||||
ApplicationAccessibleWrap::GetAttributes(nsIPersistentProperties** aAttributes)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aAttributes);
|
||||
*aAttributes = nsnull;
|
||||
|
@ -80,7 +80,7 @@ nsApplicationAccessibleWrap::GetAttributes(nsIPersistentProperties** aAttributes
|
|||
// IUnknown
|
||||
|
||||
STDMETHODIMP
|
||||
nsApplicationAccessibleWrap::QueryInterface(REFIID iid, void** ppv)
|
||||
ApplicationAccessibleWrap::QueryInterface(REFIID iid, void** ppv)
|
||||
{
|
||||
*ppv = NULL;
|
||||
|
||||
|
@ -97,7 +97,7 @@ nsApplicationAccessibleWrap::QueryInterface(REFIID iid, void** ppv)
|
|||
// IAccessibleApplication
|
||||
|
||||
STDMETHODIMP
|
||||
nsApplicationAccessibleWrap::get_appName(BSTR *aName)
|
||||
ApplicationAccessibleWrap::get_appName(BSTR* aName)
|
||||
{
|
||||
__try {
|
||||
*aName = NULL;
|
||||
|
@ -121,7 +121,7 @@ __try {
|
|||
}
|
||||
|
||||
STDMETHODIMP
|
||||
nsApplicationAccessibleWrap::get_appVersion(BSTR *aVersion)
|
||||
ApplicationAccessibleWrap::get_appVersion(BSTR* aVersion)
|
||||
{
|
||||
__try {
|
||||
*aVersion = NULL;
|
||||
|
@ -145,7 +145,7 @@ __try {
|
|||
}
|
||||
|
||||
STDMETHODIMP
|
||||
nsApplicationAccessibleWrap::get_toolkitName(BSTR *aName)
|
||||
ApplicationAccessibleWrap::get_toolkitName(BSTR* aName)
|
||||
{
|
||||
__try {
|
||||
if (IsDefunct())
|
||||
|
@ -167,7 +167,7 @@ __try {
|
|||
}
|
||||
|
||||
STDMETHODIMP
|
||||
nsApplicationAccessibleWrap::get_toolkitVersion(BSTR *aVersion)
|
||||
ApplicationAccessibleWrap::get_toolkitVersion(BSTR* aVersion)
|
||||
{
|
||||
__try {
|
||||
*aVersion = NULL;
|
||||
|
@ -191,15 +191,15 @@ __try {
|
|||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsApplicationAccessibleWrap public static
|
||||
// ApplicationAccessibleWrap public static
|
||||
|
||||
void
|
||||
nsApplicationAccessibleWrap::PreCreate()
|
||||
ApplicationAccessibleWrap::PreCreate()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
nsApplicationAccessibleWrap::Unload()
|
||||
ApplicationAccessibleWrap::Unload()
|
||||
{
|
||||
}
|
||||
|
|
@ -38,15 +38,15 @@
|
|||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef __NS_APPLICATION_ACCESSIBLE_WRAP_H__
|
||||
#define __NS_APPLICATION_ACCESSIBLE_WRAP_H__
|
||||
#ifndef MOZILLA_A11Y_APPLICATION_ACCESSIBLE_WRAP_H__
|
||||
#define MOZILLA_A11Y_APPLICATION_ACCESSIBLE_WRAP_H__
|
||||
|
||||
#include "nsApplicationAccessible.h"
|
||||
#include "ApplicationAccessible.h"
|
||||
|
||||
#include "AccessibleApplication.h"
|
||||
|
||||
class nsApplicationAccessibleWrap: public nsApplicationAccessible,
|
||||
public IAccessibleApplication
|
||||
class ApplicationAccessibleWrap: public ApplicationAccessible,
|
||||
public IAccessibleApplication
|
||||
{
|
||||
public:
|
||||
// nsISupporst
|
|
@ -48,12 +48,13 @@ LIBXUL_LIBRARY = 1
|
|||
|
||||
|
||||
CPPSRCS = \
|
||||
ApplicationAccessibleWrap.cpp \
|
||||
ARIAGridAccessibleWrap.cpp \
|
||||
nsAccessNodeWrap.cpp \
|
||||
nsAccessibleWrap.cpp \
|
||||
nsTextAccessibleWrap.cpp \
|
||||
nsDocAccessibleWrap.cpp \
|
||||
nsHTMLWin32ObjectAccessible.cpp \
|
||||
ARIAGridAccessibleWrap.cpp \
|
||||
nsRootAccessibleWrap.cpp \
|
||||
nsXULMenuAccessibleWrap.cpp \
|
||||
nsXULListboxAccessibleWrap.cpp \
|
||||
|
@ -61,7 +62,6 @@ CPPSRCS = \
|
|||
nsHyperTextAccessibleWrap.cpp \
|
||||
nsHTMLImageAccessibleWrap.cpp \
|
||||
nsHTMLTableAccessibleWrap.cpp \
|
||||
nsApplicationAccessibleWrap.cpp \
|
||||
nsWinUtils.cpp \
|
||||
ia2AccessibleAction.cpp \
|
||||
ia2AccessibleComponent.cpp \
|
||||
|
@ -78,6 +78,7 @@ CPPSRCS = \
|
|||
$(NULL)
|
||||
|
||||
EXPORTS = \
|
||||
ApplicationAccessibleWrap.h \
|
||||
ARIAGridAccessibleWrap.h \
|
||||
nsAccessNodeWrap.h \
|
||||
nsAccessibleWrap.h \
|
||||
|
@ -91,7 +92,6 @@ EXPORTS = \
|
|||
nsHyperTextAccessibleWrap.h \
|
||||
nsHTMLImageAccessibleWrap.h \
|
||||
nsHTMLTableAccessibleWrap.h \
|
||||
nsApplicationAccessibleWrap.h \
|
||||
ia2AccessibleAction.h \
|
||||
ia2AccessibleComponent.h \
|
||||
CAccessibleImage.h \
|
||||
|
|
|
@ -39,11 +39,11 @@
|
|||
#include "nsAccessNodeWrap.h"
|
||||
|
||||
#include "AccessibleApplication.h"
|
||||
#include "ApplicationAccessibleWrap.h"
|
||||
#include "ISimpleDOMNode_i.c"
|
||||
|
||||
#include "Compatibility.h"
|
||||
#include "nsAccessibilityService.h"
|
||||
#include "nsApplicationAccessibleWrap.h"
|
||||
#include "nsCoreUtils.h"
|
||||
#include "nsRootAccessible.h"
|
||||
#include "nsWinUtils.h"
|
||||
|
@ -174,7 +174,7 @@ nsAccessNodeWrap::QueryService(REFGUID guidService, REFIID iid, void** ppv)
|
|||
|
||||
// Can get to IAccessibleApplication from any node via QS
|
||||
if (iid == IID_IAccessibleApplication) {
|
||||
nsApplicationAccessible *applicationAcc = GetApplicationAccessible();
|
||||
ApplicationAccessible* applicationAcc = GetApplicationAccessible();
|
||||
if (!applicationAcc)
|
||||
return E_NOINTERFACE;
|
||||
|
||||
|
|
|
@ -38,12 +38,12 @@
|
|||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef __NS_APPLICATION_ACCESSIBLE_WRAP_H__
|
||||
#define __NS_APPLICATION_ACCESSIBLE_WRAP_H__
|
||||
#ifndef MOZILLA_A11Y_APPLICATION_ACCESSIBLE_WRAP_H__
|
||||
#define MOZILLA_A11Y_APPLICATION_ACCESSIBLE_WRAP_H__
|
||||
|
||||
#include "nsApplicationAccessible.h"
|
||||
#include "ApplicationAccessible.h"
|
||||
|
||||
class nsApplicationAccessibleWrap: public nsApplicationAccessible
|
||||
class ApplicationAccessibleWrap: public ApplicationAccessible
|
||||
{
|
||||
public:
|
||||
static void PreCreate() {}
|
|
@ -54,6 +54,7 @@ CPPSRCS = \
|
|||
$(NULL)
|
||||
|
||||
EXPORTS = \
|
||||
ApplicationAccessibleWrap.h \
|
||||
ARIAGridAccessibleWrap.h \
|
||||
nsAccessNodeWrap.h \
|
||||
nsTextAccessibleWrap.h \
|
||||
|
@ -66,7 +67,6 @@ EXPORTS = \
|
|||
nsHyperTextAccessibleWrap.h \
|
||||
nsHTMLImageAccessibleWrap.h \
|
||||
nsHTMLTableAccessibleWrap.h \
|
||||
nsApplicationAccessibleWrap.h \
|
||||
$(NULL)
|
||||
|
||||
# we don't want the shared lib, but we want to force the creation of a static lib.
|
||||
|
|
|
@ -64,8 +64,7 @@
|
|||
this.preinvoke = function rootContentRemoved_preinvoke()
|
||||
{
|
||||
// Set up target for hide event before we invoke.
|
||||
var text =
|
||||
getAccessible(getAccessible(getDocNode(aID)).firstChild).DOMNode;
|
||||
var text = getAccessible(getAccessible(getDocNode(aID)).firstChild);
|
||||
this.eventSeq[0].target = text;
|
||||
}
|
||||
|
||||
|
@ -304,16 +303,21 @@
|
|||
|
||||
function insertElmUnderDocElmWhileBodyMissed(aID)
|
||||
{
|
||||
this.docNode = getDocNode(aID);
|
||||
this.inputNode = getDocNode(aID).createElement("input");
|
||||
this.docNode = null;
|
||||
this.inputNode = null;
|
||||
|
||||
function getInputNode()
|
||||
{ return this.inputNode; }
|
||||
|
||||
this.eventSeq = [
|
||||
new invokerChecker(EVENT_SHOW, this.inputNode),
|
||||
new invokerChecker(EVENT_REORDER, this.docNode)
|
||||
new invokerChecker(EVENT_SHOW, getInputNode.bind(this)),
|
||||
new invokerChecker(EVENT_REORDER, getDocNode, aID)
|
||||
];
|
||||
|
||||
this.invoke = function invoke()
|
||||
{
|
||||
this.docNode = getDocNode(aID);
|
||||
this.inputNode = this.docNode.createElement("input");
|
||||
this.docNode.documentElement.appendChild(this.inputNode);
|
||||
}
|
||||
|
||||
|
@ -389,6 +393,7 @@
|
|||
// Test
|
||||
|
||||
//gA11yEventDumpID = "eventdump"; // debug stuff
|
||||
//gA11yEventDumpToConsole = true;
|
||||
|
||||
var gQueue = null;
|
||||
|
||||
|
|
|
@ -425,9 +425,10 @@ pref("browser.link.open_newwindow", 3);
|
|||
// 2: don't divert window.open with features
|
||||
pref("browser.link.open_newwindow.restriction", 0);
|
||||
|
||||
// Enable browser frame
|
||||
// Enable browser frames, but not OOP.
|
||||
pref("dom.mozBrowserFramesEnabled", true);
|
||||
pref("dom.mozBrowserFramesWhitelist", "http://homescreen.gaiamobile.org,http://browser.gaiamobile.org");
|
||||
pref("dom.ipc.tabs.disabled", true);
|
||||
|
||||
// Temporary permission hack for WebSMS
|
||||
pref("dom.sms.enabled", true);
|
||||
|
|
|
@ -524,6 +524,25 @@
|
|||
phase="capturing"
|
||||
modifiers="accel"
|
||||
action="this.selectEngine(event, (event.detail > 0));"/>
|
||||
|
||||
<handler event="focus">
|
||||
<![CDATA[
|
||||
// Speculatively connect to the current engine's search URI (and
|
||||
// suggest URI, if different) to reduce request latency
|
||||
|
||||
const SUGGEST_TYPE = "application/x-suggestions+json";
|
||||
var engine = this.currentEngine;
|
||||
var connector =
|
||||
Services.io.QueryInterface(Components.interfaces.nsISpeculativeConnect);
|
||||
var searchURI = engine.getSubmission("dummy").uri;
|
||||
connector.speculativeConnect(searchURI, null, null);
|
||||
|
||||
if (engine.supportsResponseType(SUGGEST_TYPE)) {
|
||||
var suggestURI = engine.getSubmission("dummy", SUGGEST_TYPE).uri;
|
||||
if (suggestURI.prePath != searchURI.prePath)
|
||||
connector.speculativeConnect(suggestURI, null, null);
|
||||
}
|
||||
]]></handler>
|
||||
</handlers>
|
||||
</binding>
|
||||
|
||||
|
|
|
@ -18,11 +18,11 @@ function test() {
|
|||
|
||||
let browser = tab.linkedBrowser;
|
||||
|
||||
whenBrowserLoaded(browser, function () {
|
||||
ss.setTabState(tab, JSON.stringify(tabState));
|
||||
waitForTabState(tab, tabState, function () {
|
||||
|
||||
let sessionHistory = browser.sessionHistory;
|
||||
let entry = sessionHistory.getEntryAtIndex(0, false);
|
||||
entry.QueryInterface(Ci.nsISHContainer);
|
||||
|
||||
whenChildCount(entry, 1, function () {
|
||||
whenChildCount(entry, 2, function () {
|
||||
|
@ -49,13 +49,6 @@ function test() {
|
|||
});
|
||||
}
|
||||
|
||||
function whenBrowserLoaded(aBrowser, aCallback) {
|
||||
aBrowser.addEventListener("load", function onLoad() {
|
||||
aBrowser.removeEventListener("load", onLoad, true);
|
||||
executeSoon(aCallback);
|
||||
}, true);
|
||||
}
|
||||
|
||||
function whenChildCount(aEntry, aChildCount, aCallback) {
|
||||
if (aEntry.childCount == aChildCount)
|
||||
aCallback();
|
||||
|
|
|
@ -18,11 +18,11 @@ function test() {
|
|||
|
||||
let browser = tab.linkedBrowser;
|
||||
|
||||
whenBrowserLoaded(browser, function () {
|
||||
ss.setTabState(tab, JSON.stringify(tabState));
|
||||
waitForTabState(tab, tabState, function() {
|
||||
|
||||
let sessionHistory = browser.sessionHistory;
|
||||
let entry = sessionHistory.getEntryAtIndex(0, false);
|
||||
entry.QueryInterface(Ci.nsISHContainer);
|
||||
|
||||
whenChildCount(entry, 1, function () {
|
||||
whenChildCount(entry, 2, function () {
|
||||
|
@ -50,13 +50,6 @@ function test() {
|
|||
});
|
||||
}
|
||||
|
||||
function whenBrowserLoaded(aBrowser, aCallback) {
|
||||
aBrowser.addEventListener("load", function onLoad() {
|
||||
aBrowser.removeEventListener("load", onLoad, true);
|
||||
executeSoon(aCallback);
|
||||
}, true);
|
||||
}
|
||||
|
||||
function whenChildCount(aEntry, aChildCount, aCallback) {
|
||||
if (aEntry.childCount == aChildCount)
|
||||
aCallback();
|
||||
|
|
|
@ -45,6 +45,10 @@ registerCleanupFunction(function () {
|
|||
Services.prefs.clearUserPref("browser.sessionstore.restore_on_demand");
|
||||
});
|
||||
|
||||
// This kicks off the search service used on about:home and allows the
|
||||
// session restore tests to be run standalone without triggering errors.
|
||||
Cc["@mozilla.org/browser/clh;1"].getService(Ci.nsIBrowserHandler).defaultArgs;
|
||||
|
||||
// This assumes that tests will at least have some state/entries
|
||||
function waitForBrowserState(aState, aSetStateCallback) {
|
||||
let windows = [window];
|
||||
|
@ -128,6 +132,27 @@ function waitForBrowserState(aState, aSetStateCallback) {
|
|||
ss.setBrowserState(JSON.stringify(aState));
|
||||
}
|
||||
|
||||
// Doesn't assume that the tab needs to be closed in a cleanup function.
|
||||
// If that's the case, the test author should handle that in the test.
|
||||
function waitForTabState(aTab, aState, aCallback) {
|
||||
let listening = true;
|
||||
|
||||
function onSSTabRestored() {
|
||||
aTab.removeEventListener("SSTabRestored", onSSTabRestored, false);
|
||||
listening = false;
|
||||
aCallback();
|
||||
}
|
||||
|
||||
aTab.addEventListener("SSTabRestored", onSSTabRestored, false);
|
||||
|
||||
registerCleanupFunction(function() {
|
||||
if (listening) {
|
||||
aTab.removeEventListener("SSTabRestored", onSSTabRestored, false);
|
||||
}
|
||||
});
|
||||
ss.setTabState(aTab, JSON.stringify(aState));
|
||||
}
|
||||
|
||||
// waitForSaveState waits for a state write but not necessarily for the state to
|
||||
// turn dirty.
|
||||
function waitForSaveState(aSaveStateCallback) {
|
||||
|
@ -166,6 +191,13 @@ function waitForSaveState(aSaveStateCallback) {
|
|||
Services.obs.addObserver(observer, topic, false);
|
||||
};
|
||||
|
||||
function whenBrowserLoaded(aBrowser, aCallback) {
|
||||
aBrowser.addEventListener("load", function onLoad() {
|
||||
aBrowser.removeEventListener("load", onLoad, true);
|
||||
executeSoon(aCallback);
|
||||
}, true);
|
||||
}
|
||||
|
||||
var gUniqueCounter = 0;
|
||||
function r() {
|
||||
return Date.now() + "-" + (++gUniqueCounter);
|
||||
|
|
209
build/mozinfo.py
209
build/mozinfo.py
|
@ -1,209 +0,0 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
# ***** 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 Corporation Code.
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Mikeal Rogers.
|
||||
# Portions created by the Initial Developer are Copyright (C) 2008
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
# Mikeal Rogers <mikeal.rogers@gmail.com>
|
||||
# Henrik Skupin <hskupin@mozilla.com>
|
||||
# Clint Talbert <ctalbert@mozilla.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 *****
|
||||
|
||||
"""
|
||||
file for interface to transform introspected system information to a format
|
||||
pallatable to Mozilla
|
||||
|
||||
Information:
|
||||
- os : what operating system ['win', 'mac', 'linux', ...]
|
||||
- bits : 32 or 64
|
||||
- processor : processor architecture ['x86', 'x86_64', 'ppc', ...]
|
||||
- version : operating system version string
|
||||
|
||||
For windows, the service pack information is also included
|
||||
"""
|
||||
|
||||
# TODO: it might be a good idea of adding a system name (e.g. 'Ubuntu' for
|
||||
# linux) to the information; I certainly wouldn't want anyone parsing this
|
||||
# information and having behaviour depend on it
|
||||
|
||||
import os
|
||||
import platform
|
||||
import re
|
||||
import sys
|
||||
|
||||
# keep a copy of the os module since updating globals overrides this
|
||||
_os = os
|
||||
|
||||
class unknown(object):
|
||||
"""marker class for unknown information"""
|
||||
def __nonzero__(self):
|
||||
return False
|
||||
def __str__(self):
|
||||
return 'UNKNOWN'
|
||||
unknown = unknown() # singleton
|
||||
|
||||
# get system information
|
||||
info = {'os': unknown,
|
||||
'processor': unknown,
|
||||
'version': unknown,
|
||||
'bits': unknown }
|
||||
(system, node, release, version, machine, processor) = platform.uname()
|
||||
(bits, linkage) = platform.architecture()
|
||||
|
||||
# get os information and related data
|
||||
if system in ["Microsoft", "Windows"]:
|
||||
info['os'] = 'win'
|
||||
# There is a Python bug on Windows to determine platform values
|
||||
# http://bugs.python.org/issue7860
|
||||
if "PROCESSOR_ARCHITEW6432" in os.environ:
|
||||
processor = os.environ.get("PROCESSOR_ARCHITEW6432", processor)
|
||||
else:
|
||||
processor = os.environ.get('PROCESSOR_ARCHITECTURE', processor)
|
||||
system = os.environ.get("OS", system).replace('_', ' ')
|
||||
service_pack = os.sys.getwindowsversion()[4]
|
||||
info['service_pack'] = service_pack
|
||||
elif system == "Linux":
|
||||
(distro, version, codename) = platform.dist()
|
||||
version = distro + " " + version
|
||||
if not processor:
|
||||
processor = machine
|
||||
info['os'] = 'linux'
|
||||
elif system == "Darwin":
|
||||
(release, versioninfo, machine) = platform.mac_ver()
|
||||
version = "OS X " + release
|
||||
info['os'] = 'mac'
|
||||
elif sys.platform in ('solaris', 'sunos5'):
|
||||
info['os'] = 'unix'
|
||||
version = sys.platform
|
||||
info['version'] = version # os version
|
||||
|
||||
# processor type and bits
|
||||
if processor in ["i386", "i686"]:
|
||||
if bits == "32bit":
|
||||
processor = "x86"
|
||||
elif bits == "64bit":
|
||||
processor = "x86_64"
|
||||
elif processor == "AMD64":
|
||||
bits = "64bit"
|
||||
processor = "x86_64"
|
||||
elif processor == "Power Macintosh":
|
||||
processor = "ppc"
|
||||
bits = re.search('(\d+)bit', bits).group(1)
|
||||
info.update({'processor': processor,
|
||||
'bits': int(bits),
|
||||
})
|
||||
|
||||
# standard value of choices, for easy inspection
|
||||
choices = {'os': ['linux', 'win', 'mac', 'unix'],
|
||||
'bits': [32, 64],
|
||||
'processor': ['x86', 'x86_64', 'ppc']}
|
||||
|
||||
|
||||
def sanitize(info):
|
||||
"""Do some sanitization of input values, primarily
|
||||
to handle universal Mac builds."""
|
||||
if "processor" in info and info["processor"] == "universal-x86-x86_64":
|
||||
# If we're running on OS X 10.6 or newer, assume 64-bit
|
||||
if release[:4] >= "10.6":
|
||||
info["processor"] = "x86_64"
|
||||
info["bits"] = 64
|
||||
else:
|
||||
info["processor"] = "x86"
|
||||
info["bits"] = 32
|
||||
|
||||
# method for updating information
|
||||
def update(new_info):
|
||||
"""update the info"""
|
||||
info.update(new_info)
|
||||
sanitize(info)
|
||||
globals().update(info)
|
||||
|
||||
# convenience data for os access
|
||||
for os_name in choices['os']:
|
||||
globals()['is' + os_name.title()] = info['os'] == os_name
|
||||
# unix is special
|
||||
if isLinux:
|
||||
globals()['isUnix'] = True
|
||||
|
||||
update({})
|
||||
|
||||
# exports
|
||||
__all__ = info.keys()
|
||||
__all__ += ['is' + os_name.title() for os_name in choices['os']]
|
||||
__all__ += ['info', 'unknown', 'main', 'choices', 'update']
|
||||
|
||||
|
||||
def main(args=None):
|
||||
|
||||
# parse the command line
|
||||
from optparse import OptionParser
|
||||
parser = OptionParser()
|
||||
for key in choices:
|
||||
parser.add_option('--%s' % key, dest=key,
|
||||
action='store_true', default=False,
|
||||
help="display choices for %s" % key)
|
||||
options, args = parser.parse_args()
|
||||
|
||||
# args are JSON blobs to override info
|
||||
if args:
|
||||
try:
|
||||
from json import loads
|
||||
except ImportError:
|
||||
try:
|
||||
from simplejson import loads
|
||||
except ImportError:
|
||||
def loads(string):
|
||||
"""*really* simple json; will not work with unicode"""
|
||||
return eval(string, {'true': True, 'false': False, 'null': None})
|
||||
for arg in args:
|
||||
if _os.path.exists(arg):
|
||||
string = file(arg).read()
|
||||
else:
|
||||
string = arg
|
||||
update(loads(string))
|
||||
|
||||
# print out choices if requested
|
||||
flag = False
|
||||
for key, value in options.__dict__.items():
|
||||
if value is True:
|
||||
print '%s choices: %s' % (key, ' '.join([str(choice)
|
||||
for choice in choices[key]]))
|
||||
flag = True
|
||||
if flag: return
|
||||
|
||||
# otherwise, print out all info
|
||||
for key, value in info.items():
|
||||
print '%s: %s' % (key, value)
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
53
configure.in
53
configure.in
|
@ -6327,44 +6327,6 @@ if test -n "$MOZ_TREE_FREETYPE"; then
|
|||
AC_SUBST(CAIRO_FT_CFLAGS)
|
||||
fi
|
||||
|
||||
dnl ========================================================
|
||||
dnl Web App Runtime
|
||||
dnl ========================================================
|
||||
MOZ_ARG_DISABLE_BOOL(webapp-runtime,
|
||||
[ --disable-webapp-runtime Disable Web App Runtime],
|
||||
MOZ_WEBAPP_RUNTIME=,
|
||||
MOZ_WEBAPP_RUNTIME=1)
|
||||
if test -n "$MOZ_WEBAPP_RUNTIME" -a "$OS_ARCH" = "WINNT"; then
|
||||
# Disable Web App Runtime for Windows builds that use the new toolkit if the
|
||||
# required major version and minimum minor version of Unicode NSIS isn't in
|
||||
# the path.
|
||||
REQ_NSIS_MAJOR_VER=2
|
||||
MIN_NSIS_MINOR_VER=33
|
||||
MOZ_PATH_PROGS(MAKENSISU, $MAKENSISU makensisu-2.46 makensisu makensis)
|
||||
if test -z "$MAKENSISU" -o "$MAKENSISU" = ":"; then
|
||||
AC_MSG_ERROR([To build the Web App Runtime you must have the latest MozillaBuild or Unicode NSIS with a major version of $REQ_NSIS_MAJOR_VER and a minimum minor version of $MIN_NSIS_MINOR_VER in your path. To build without the Web App Runtime reconfigure using --disable-webapp-runtime.])
|
||||
fi
|
||||
changequote(,)
|
||||
MAKENSISU_VER=`"$MAKENSISU" -version 2>/dev/null | sed -e '/-Unicode/!s/.*//g' -e 's/^v\([0-9]\+\.[0-9]\+\)\-Unicode$/\1/g'`
|
||||
changequote([,])
|
||||
if test ! "$MAKENSISU_VER" = ""; then
|
||||
MAKENSISU_MAJOR_VER=`echo $MAKENSISU_VER | $AWK -F\. '{ print $1 }'`
|
||||
MAKENSISU_MINOR_VER=`echo $MAKENSISU_VER | $AWK -F\. '{ print $2 }'`
|
||||
fi
|
||||
AC_MSG_CHECKING([for Unicode NSIS with major version == $REQ_NSIS_MAJOR_VER and minor version >= $MIN_NSIS_MINOR_VER])
|
||||
if test "$MAKENSISU_VER" = "" ||
|
||||
test ! "$MAKENSISU_MAJOR_VER" = "$REQ_NSIS_MAJOR_VER" -o \
|
||||
! "$MAKENSISU_MINOR_VER" -ge $MIN_NSIS_MINOR_VER; then
|
||||
AC_MSG_RESULT([no])
|
||||
AC_MSG_ERROR([To build the Web App Runtime you must have the latest MozillaBuild or Unicode NSIS with a major version of $REQ_NSIS_MAJOR_VER and a minimum minor version of $MIN_NSIS_MINOR_VER in your path. To build without the Web App Runtime reconfigure using --disable-webapp-runtime.])
|
||||
fi
|
||||
AC_MSG_RESULT([yes])
|
||||
fi
|
||||
AC_SUBST(MOZ_WEBAPP_RUNTIME)
|
||||
if test "$MOZ_WEBAPP_RUNTIME"; then
|
||||
AC_DEFINE(MOZ_WEBAPP_RUNTIME)
|
||||
fi
|
||||
|
||||
dnl ========================================================
|
||||
dnl Installer
|
||||
dnl ========================================================
|
||||
|
@ -6403,6 +6365,21 @@ if test "$OS_ARCH" = "WINNT"; then
|
|||
fi
|
||||
fi
|
||||
|
||||
dnl ========================================================
|
||||
dnl Web App Runtime
|
||||
dnl ========================================================
|
||||
MOZ_ARG_DISABLE_BOOL(webapp-runtime,
|
||||
[ --disable-webapp-runtime Disable Web App Runtime],
|
||||
MOZ_WEBAPP_RUNTIME=,
|
||||
MOZ_WEBAPP_RUNTIME=1)
|
||||
if test "$OS_ARCH" = "WINNT" -a -z "$MAKENSISU" -a -n "$CROSS_COMPILE"; then
|
||||
MOZ_WEBAPP_RUNTIME=
|
||||
fi
|
||||
AC_SUBST(MOZ_WEBAPP_RUNTIME)
|
||||
if test "$MOZ_WEBAPP_RUNTIME"; then
|
||||
AC_DEFINE(MOZ_WEBAPP_RUNTIME)
|
||||
fi
|
||||
|
||||
AC_MSG_CHECKING([for tar archiver])
|
||||
AC_CHECK_PROGS(TAR, gnutar gtar tar, "")
|
||||
if test -z "$TAR"; then
|
||||
|
|
|
@ -457,8 +457,13 @@ nsFrameLoader::ReallyStartLoadingInternal()
|
|||
}
|
||||
}
|
||||
|
||||
// FIXME get error codes from child
|
||||
mRemoteBrowser->LoadURL(mURIToLoad);
|
||||
if (mRemoteBrowserShown || ShowRemoteFrame(nsIntSize(0, 0))) {
|
||||
// FIXME get error codes from child
|
||||
mRemoteBrowser->LoadURL(mURIToLoad);
|
||||
} else {
|
||||
NS_WARNING("[nsFrameLoader] ReallyStartLoadingInternal tried but couldn't show remote browser.\n");
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -912,6 +917,18 @@ nsFrameLoader::ShowRemoteFrame(const nsIntSize& size)
|
|||
// cross-process layers; need to figure out what behavior we really
|
||||
// want here. For now, hack.
|
||||
if (!mRemoteBrowserShown) {
|
||||
if (!mOwnerContent ||
|
||||
!mOwnerContent->GetCurrentDoc()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
nsRefPtr<layers::LayerManager> layerManager =
|
||||
nsContentUtils::LayerManagerForDocument(mOwnerContent->GetCurrentDoc());
|
||||
if (!layerManager) {
|
||||
// This is just not going to work.
|
||||
return false;
|
||||
}
|
||||
|
||||
mRemoteBrowser->Show(size);
|
||||
mRemoteBrowserShown = true;
|
||||
|
||||
|
@ -1355,19 +1372,27 @@ nsFrameLoader::SetOwnerContent(Element* aContent)
|
|||
}
|
||||
}
|
||||
|
||||
bool
|
||||
nsFrameLoader::OwnerIsBrowserFrame()
|
||||
{
|
||||
nsCOMPtr<nsIMozBrowserFrame> browserFrame = do_QueryInterface(mOwnerContent);
|
||||
bool isBrowser = false;
|
||||
if (browserFrame) {
|
||||
browserFrame->GetReallyIsBrowser(&isBrowser);
|
||||
}
|
||||
return isBrowser;
|
||||
}
|
||||
|
||||
bool
|
||||
nsFrameLoader::ShouldUseRemoteProcess()
|
||||
{
|
||||
// Check for *disabled* multi-process first: environment, pref
|
||||
// Then check for *enabled* multi-process attribute
|
||||
// Default is not-remote.
|
||||
|
||||
if (PR_GetEnv("MOZ_DISABLE_OOP_TABS") ||
|
||||
Preferences::GetBool("dom.ipc.tabs.disabled", false)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return (bool) mOwnerContent->AttrValueIs(kNameSpaceID_None,
|
||||
return OwnerIsBrowserFrame() ||
|
||||
(bool) mOwnerContent->AttrValueIs(kNameSpaceID_None,
|
||||
nsGkAtoms::Remote,
|
||||
nsGkAtoms::_true,
|
||||
eCaseMatters);
|
||||
|
@ -1842,24 +1867,27 @@ nsFrameLoader::TryRemoteBrowser()
|
|||
|
||||
nsCOMPtr<nsIDocShellTreeItem> parentAsItem(do_QueryInterface(parentAsWebNav));
|
||||
|
||||
PRInt32 parentType;
|
||||
parentAsItem->GetItemType(&parentType);
|
||||
// <iframe mozbrowser> gets to skip these checks.
|
||||
if (!OwnerIsBrowserFrame()) {
|
||||
PRInt32 parentType;
|
||||
parentAsItem->GetItemType(&parentType);
|
||||
|
||||
if (parentType != nsIDocShellTreeItem::typeChrome) {
|
||||
return false;
|
||||
}
|
||||
if (parentType != nsIDocShellTreeItem::typeChrome) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!mOwnerContent->IsXUL()) {
|
||||
return false;
|
||||
}
|
||||
if (!mOwnerContent->IsXUL()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
nsAutoString value;
|
||||
mOwnerContent->GetAttr(kNameSpaceID_None, nsGkAtoms::type, value);
|
||||
nsAutoString value;
|
||||
mOwnerContent->GetAttr(kNameSpaceID_None, nsGkAtoms::type, value);
|
||||
|
||||
if (!value.LowerCaseEqualsLiteral("content") &&
|
||||
!StringBeginsWith(value, NS_LITERAL_STRING("content-"),
|
||||
nsCaseInsensitiveStringComparator())) {
|
||||
return false;
|
||||
if (!value.LowerCaseEqualsLiteral("content") &&
|
||||
!StringBeginsWith(value, NS_LITERAL_STRING("content-"),
|
||||
nsCaseInsensitiveStringComparator())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
PRUint32 chromeFlags = 0;
|
||||
|
@ -2131,6 +2159,19 @@ nsFrameLoader::GetRootContentView(nsIContentView** aContentView)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
static already_AddRefed<nsIDocShell>
|
||||
GetRootDocShell(nsIDocument *aDocument)
|
||||
{
|
||||
nsCOMPtr<nsIWebNavigation> webNav = do_GetInterface(aDocument->GetWindow());
|
||||
nsCOMPtr<nsIDocShellTreeItem> treeItem = do_QueryInterface(webNav);
|
||||
NS_ENSURE_TRUE(treeItem, NULL);
|
||||
|
||||
nsCOMPtr<nsIDocShellTreeItem> rootItem;
|
||||
treeItem->GetRootTreeItem(getter_AddRefs(rootItem));
|
||||
nsCOMPtr<nsIDocShell> rootDocShell = do_QueryInterface(rootItem);
|
||||
return rootDocShell.forget();
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsFrameLoader::EnsureMessageManager()
|
||||
{
|
||||
|
@ -2159,8 +2200,12 @@ nsFrameLoader::EnsureMessageManager()
|
|||
NS_ENSURE_STATE(cx);
|
||||
|
||||
nsCOMPtr<nsIDOMChromeWindow> chromeWindow =
|
||||
do_QueryInterface(mOwnerContent->OwnerDoc()->GetWindow());
|
||||
NS_ENSURE_STATE(chromeWindow);
|
||||
do_QueryInterface(OwnerDoc()->GetWindow());
|
||||
if (!chromeWindow) {
|
||||
nsCOMPtr<nsIDocShell> rootDocShell = GetRootDocShell(OwnerDoc());
|
||||
nsCOMPtr<nsIDOMWindow> rootWindow = do_GetInterface(rootDocShell);
|
||||
chromeWindow = do_GetInterface(rootWindow);
|
||||
}
|
||||
nsCOMPtr<nsIChromeFrameMessageManager> parentManager;
|
||||
chromeWindow->GetMessageManager(getter_AddRefs(parentManager));
|
||||
|
||||
|
|
|
@ -295,6 +295,12 @@ private:
|
|||
|
||||
bool ShouldUseRemoteProcess();
|
||||
|
||||
/**
|
||||
* Is this a frameloader for a bona fide <iframe mozbrowser>? (I.e., does
|
||||
* the frame return true for nsIMozBrowserFrame::GetReallyIsBrowser()?)
|
||||
*/
|
||||
bool OwnerIsBrowserFrame();
|
||||
|
||||
/**
|
||||
* If we are an IPC frame, set mRemoteFrame. Otherwise, create and
|
||||
* initialize mDocShell.
|
||||
|
|
|
@ -83,9 +83,6 @@ nsresult NS_NewContentSubtreeIterator(nsIContentIterator** aInstancePtrResult);
|
|||
if (!nsContentUtils::CanCallerAccess(node_)) { \
|
||||
return NS_ERROR_DOM_SECURITY_ERR; \
|
||||
} \
|
||||
if (mIsDetached) { \
|
||||
return NS_ERROR_DOM_INVALID_STATE_ERR; \
|
||||
} \
|
||||
PR_END_MACRO
|
||||
|
||||
static void InvalidateAllFrames(nsINode* aNode)
|
||||
|
@ -653,9 +650,6 @@ nsRange::IsPointInRange(nsIDOMNode* aParent, PRInt32 aOffset, bool* aResult)
|
|||
NS_IMETHODIMP
|
||||
nsRange::ComparePoint(nsIDOMNode* aParent, PRInt32 aOffset, PRInt16* aResult)
|
||||
{
|
||||
if (mIsDetached)
|
||||
return NS_ERROR_DOM_INVALID_STATE_ERR;
|
||||
|
||||
// our range is in a good state?
|
||||
if (!mIsPositioned)
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
|
@ -755,8 +749,7 @@ nsRange::DoSetRange(nsINode* aStartN, PRInt32 aStartOffset,
|
|||
if (newCommonAncestor) {
|
||||
RegisterCommonAncestor(newCommonAncestor);
|
||||
} else {
|
||||
NS_ASSERTION(mIsDetached || !mIsPositioned,
|
||||
"unexpected disconnected nodes");
|
||||
NS_ASSERTION(!mIsPositioned, "unexpected disconnected nodes");
|
||||
mInSelection = false;
|
||||
}
|
||||
}
|
||||
|
@ -844,8 +837,6 @@ nsRange::GetEndOffset(PRInt32* aEndOffset)
|
|||
NS_IMETHODIMP
|
||||
nsRange::GetCollapsed(bool* aIsCollapsed)
|
||||
{
|
||||
if(mIsDetached)
|
||||
return NS_ERROR_DOM_INVALID_STATE_ERR;
|
||||
if (!mIsPositioned)
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
|
||||
|
@ -858,8 +849,6 @@ NS_IMETHODIMP
|
|||
nsRange::GetCommonAncestorContainer(nsIDOMNode** aCommonParent)
|
||||
{
|
||||
*aCommonParent = nsnull;
|
||||
if(mIsDetached)
|
||||
return NS_ERROR_DOM_INVALID_STATE_ERR;
|
||||
if (!mIsPositioned)
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
|
||||
|
@ -1049,8 +1038,6 @@ nsRange::SetEndAfter(nsIDOMNode* aSibling)
|
|||
NS_IMETHODIMP
|
||||
nsRange::Collapse(bool aToStart)
|
||||
{
|
||||
if(mIsDetached)
|
||||
return NS_ERROR_DOM_INVALID_STATE_ERR;
|
||||
if (!mIsPositioned)
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
|
||||
|
@ -1502,9 +1489,6 @@ nsresult nsRange::CutContents(nsIDOMDocumentFragment** aFragment)
|
|||
*aFragment = nsnull;
|
||||
}
|
||||
|
||||
if (IsDetached())
|
||||
return NS_ERROR_DOM_INVALID_STATE_ERR;
|
||||
|
||||
nsresult rv;
|
||||
|
||||
nsCOMPtr<nsIDocument> doc = mStartParent->OwnerDoc();
|
||||
|
@ -1782,8 +1766,6 @@ nsRange::CompareBoundaryPoints(PRUint16 aHow, nsIDOMRange* aOtherRange,
|
|||
nsRange* otherRange = static_cast<nsRange*>(aOtherRange);
|
||||
NS_ENSURE_TRUE(otherRange, NS_ERROR_NULL_POINTER);
|
||||
|
||||
if(mIsDetached || otherRange->IsDetached())
|
||||
return NS_ERROR_DOM_INVALID_STATE_ERR;
|
||||
if (!mIsPositioned || !otherRange->IsPositioned())
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
|
||||
|
@ -1883,9 +1865,6 @@ nsRange::CloneParentsBetween(nsIDOMNode *aAncestor,
|
|||
NS_IMETHODIMP
|
||||
nsRange::CloneContents(nsIDOMDocumentFragment** aReturn)
|
||||
{
|
||||
if (IsDetached())
|
||||
return NS_ERROR_DOM_INVALID_STATE_ERR;
|
||||
|
||||
nsresult res;
|
||||
nsCOMPtr<nsIDOMNode> commonAncestor;
|
||||
res = GetCommonAncestorContainer(getter_AddRefs(commonAncestor));
|
||||
|
@ -2078,9 +2057,6 @@ nsRange::CloneContents(nsIDOMDocumentFragment** aReturn)
|
|||
nsresult
|
||||
nsRange::CloneRange(nsRange** aReturn) const
|
||||
{
|
||||
if(mIsDetached)
|
||||
return NS_ERROR_DOM_INVALID_STATE_ERR;
|
||||
|
||||
if (aReturn == 0)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
|
@ -2264,9 +2240,6 @@ nsRange::SurroundContents(nsIDOMNode* aNewParent)
|
|||
NS_IMETHODIMP
|
||||
nsRange::ToString(nsAString& aReturn)
|
||||
{
|
||||
if(mIsDetached)
|
||||
return NS_ERROR_DOM_INVALID_STATE_ERR;
|
||||
|
||||
// clear the string
|
||||
aReturn.Truncate();
|
||||
|
||||
|
@ -2358,17 +2331,8 @@ nsRange::ToString(nsAString& aReturn)
|
|||
NS_IMETHODIMP
|
||||
nsRange::Detach()
|
||||
{
|
||||
if(mIsDetached)
|
||||
return NS_ERROR_DOM_INVALID_STATE_ERR;
|
||||
|
||||
if (IsInSelection()) {
|
||||
::InvalidateAllFrames(GetRegisteredCommonAncestor());
|
||||
}
|
||||
|
||||
// No-op, but still set mIsDetached for telemetry (bug 702948)
|
||||
mIsDetached = true;
|
||||
|
||||
DoSetRange(nsnull, 0, nsnull, 0, nsnull);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -108,11 +108,6 @@ public:
|
|||
return mIsPositioned;
|
||||
}
|
||||
|
||||
bool IsDetached() const
|
||||
{
|
||||
return mIsDetached;
|
||||
}
|
||||
|
||||
bool Collapsed() const
|
||||
{
|
||||
return mIsPositioned && mStartParent == mEndParent &&
|
||||
|
@ -138,7 +133,7 @@ public:
|
|||
*/
|
||||
void SetInSelection(bool aInSelection)
|
||||
{
|
||||
if (mInSelection == aInSelection || mIsDetached) {
|
||||
if (mInSelection == aInSelection) {
|
||||
return;
|
||||
}
|
||||
mInSelection = aInSelection;
|
||||
|
@ -245,7 +240,6 @@ protected:
|
|||
return;
|
||||
}
|
||||
mIsNested = true;
|
||||
NS_ASSERTION(!mRange->IsDetached(), "detached range in selection");
|
||||
mCommonAncestor = mRange->GetRegisteredCommonAncestor();
|
||||
}
|
||||
~AutoInvalidateSelection();
|
||||
|
|
|
@ -100,6 +100,8 @@
|
|||
#include "nsIDOMUIEvent.h"
|
||||
#include "nsDOMDragEvent.h"
|
||||
#include "nsIDOMNSEditableElement.h"
|
||||
#include "nsIDOMMozBrowserFrame.h"
|
||||
#include "nsIMozBrowserFrame.h"
|
||||
|
||||
#include "nsCaret.h"
|
||||
|
||||
|
@ -1701,12 +1703,30 @@ nsEventStateManager::DispatchCrossProcessEvent(nsEvent* aEvent, nsIFrameLoader*
|
|||
|
||||
bool
|
||||
nsEventStateManager::IsRemoteTarget(nsIContent* target) {
|
||||
return target &&
|
||||
(target->Tag() == nsGkAtoms::browser ||
|
||||
target->Tag() == nsGkAtoms::iframe) &&
|
||||
target->IsXUL() &&
|
||||
target->AttrValueIs(kNameSpaceID_None, nsGkAtoms::Remote,
|
||||
nsGkAtoms::_true, eIgnoreCase);
|
||||
if (!target) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// <browser/iframe remote=true> from XUL
|
||||
if ((target->Tag() == nsGkAtoms::browser ||
|
||||
target->Tag() == nsGkAtoms::iframe) &&
|
||||
target->IsXUL() &&
|
||||
target->AttrValueIs(kNameSpaceID_None, nsGkAtoms::Remote,
|
||||
nsGkAtoms::_true, eIgnoreCase)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// <frame/iframe mozbrowser>
|
||||
nsCOMPtr<nsIMozBrowserFrame> browserFrame = do_QueryInterface(target);
|
||||
if (browserFrame) {
|
||||
bool isRemote = false;
|
||||
browserFrame->GetReallyIsBrowser(&isRemote);
|
||||
if (isRemote) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -369,33 +369,6 @@ function run_extract_test() {
|
|||
|
||||
// Clean up after ourselves.
|
||||
walker = null;
|
||||
|
||||
/* Whenever a DOM range is detached, we cannot use any methods on
|
||||
it - including extracting its contents or deleting its contents. It
|
||||
should throw a NS_ERROR_DOM_INVALID_STATE_ERR exception.
|
||||
*/
|
||||
dump("Detached range test\n");
|
||||
var compareFrag = getFragment(baseSource);
|
||||
baseFrag = getFragment(baseSource);
|
||||
baseRange = getRange(baseSource, baseFrag);
|
||||
baseRange.detach();
|
||||
try {
|
||||
var cutFragment = baseRange.extractContents();
|
||||
do_throw("Should have thrown INVALID_STATE_ERR!");
|
||||
} catch (e if (e instanceof C_i.nsIException &&
|
||||
e.result == INVALID_STATE_ERR)) {
|
||||
// do nothing
|
||||
}
|
||||
do_check_true(compareFrag.isEqualNode(baseFrag));
|
||||
|
||||
try {
|
||||
baseRange.deleteContents();
|
||||
do_throw("Should have thrown INVALID_STATE_ERR!");
|
||||
} catch (e if (e instanceof C_i.nsIException &&
|
||||
e.result == INVALID_STATE_ERR)) {
|
||||
// do nothing
|
||||
}
|
||||
do_check_true(compareFrag.isEqualNode(baseFrag));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2762,6 +2762,11 @@ nsXULDocument::LoadOverlayInternal(nsIURI* aURI, bool aIsDynamic,
|
|||
// Not there. Initiate a load.
|
||||
PR_LOG(gXULLog, PR_LOG_DEBUG, ("xul: overlay was not cached"));
|
||||
|
||||
if (mIsGoingAway) {
|
||||
PR_LOG(gXULLog, PR_LOG_DEBUG, ("xul: ...and document already destroyed"));
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
// We'll set the right principal on the proto doc when we get
|
||||
// OnStartRequest from the parser, so just pass in a null principal for
|
||||
// now.
|
||||
|
|
|
@ -7505,18 +7505,34 @@ nsDocShell::CreateContentViewer(const char *aContentType,
|
|||
mLoadType = mFailedLoadType;
|
||||
|
||||
nsCOMPtr<nsIChannel> failedChannel = mFailedChannel;
|
||||
nsCOMPtr<nsIURI> failedURI = mFailedURI;
|
||||
|
||||
// Make sure we have a URI to set currentURI.
|
||||
nsCOMPtr<nsIURI> failedURI;
|
||||
if (failedChannel) {
|
||||
NS_GetFinalChannelURI(failedChannel, getter_AddRefs(failedURI));
|
||||
}
|
||||
|
||||
if (!failedURI) {
|
||||
failedURI = mFailedURI;
|
||||
}
|
||||
|
||||
// When we don't have failedURI, something wrong will happen. See
|
||||
// bug 291876.
|
||||
MOZ_ASSERT(failedURI, "We don't have a URI for history APIs.");
|
||||
|
||||
mFailedChannel = nsnull;
|
||||
mFailedURI = nsnull;
|
||||
|
||||
// Create an shistory entry for the old load, if we have a channel
|
||||
if (failedChannel) {
|
||||
mURIResultedInDocument = true;
|
||||
OnLoadingSite(failedChannel, true, false);
|
||||
} else if (failedURI) {
|
||||
mURIResultedInDocument = true;
|
||||
OnNewURI(failedURI, nsnull, nsnull, mLoadType, true, false,
|
||||
// Create an shistory entry for the old load.
|
||||
if (failedURI) {
|
||||
#ifdef DEBUG
|
||||
bool errorOnLocationChangeNeeded =
|
||||
#endif
|
||||
OnNewURI(failedURI, failedChannel, nsnull, mLoadType, true, false,
|
||||
false);
|
||||
|
||||
MOZ_ASSERT(!errorOnLocationChangeNeeded,
|
||||
"We have to fire onLocationChange again.");
|
||||
}
|
||||
|
||||
// Be sure to have a correct mLSHE, it may have been cleared by
|
||||
|
@ -7533,9 +7549,6 @@ nsDocShell::CreateContentViewer(const char *aContentType,
|
|||
mLSHE = do_QueryInterface(entry);
|
||||
}
|
||||
|
||||
// Set our current URI
|
||||
SetCurrentURI(failedURI);
|
||||
|
||||
mLoadType = LOAD_ERROR_PAGE;
|
||||
}
|
||||
|
||||
|
|
|
@ -79,11 +79,6 @@ function step1A() {
|
|||
}
|
||||
|
||||
function step1B(aWebProgress, aRequest, aLocation, aFlags) {
|
||||
/* XXX Here we receive 2 notifications, due to bug 673752. */
|
||||
if (!aRequest) {
|
||||
return;
|
||||
}
|
||||
|
||||
is(aLocation.spec, kDNSErrorURI, "Error page's URI (1)");
|
||||
|
||||
ok(!(aFlags & Components.interfaces.nsIWebProgressListener
|
||||
|
@ -161,9 +156,6 @@ function step4A() {
|
|||
}
|
||||
|
||||
function step4B(aWebProgress, aRequest, aLocation, aFlags) {
|
||||
if (!aRequest) // See step1B(...) and bug 673752.
|
||||
return;
|
||||
|
||||
is(aLocation.spec, kDNSErrorURI, "Go back to the error URI (4)");
|
||||
|
||||
ok(!(aFlags & Components.interfaces.nsIWebProgressListener
|
||||
|
|
|
@ -177,7 +177,7 @@ NSResultToNameAndMessage(nsresult aNSResult,
|
|||
|
||||
nsresult
|
||||
NS_GetNameAndMessageForDOMNSResult(nsresult aNSResult, const char** aName,
|
||||
const char** aMessage)
|
||||
const char** aMessage, PRUint16* aCode)
|
||||
{
|
||||
const char* name = nsnull;
|
||||
const char* message = nsnull;
|
||||
|
@ -187,6 +187,9 @@ NS_GetNameAndMessageForDOMNSResult(nsresult aNSResult, const char** aName,
|
|||
if (name && message) {
|
||||
*aName = name;
|
||||
*aMessage = message;
|
||||
if (aCode) {
|
||||
*aCode = code;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -64,7 +64,8 @@ protected:
|
|||
|
||||
nsresult
|
||||
NS_GetNameAndMessageForDOMNSResult(nsresult aNSResult, const char** aName,
|
||||
const char** aMessage);
|
||||
const char** aMessage,
|
||||
PRUint16* aCode = nsnull);
|
||||
|
||||
#define DECL_INTERNAL_DOM_EXCEPTION(domname) \
|
||||
nsresult \
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#define mozilla_dom_bindings_Utils_h__
|
||||
|
||||
#include "mozilla/dom/bindings/DOMJSClass.h"
|
||||
#include "mozilla/dom/workers/Workers.h"
|
||||
|
||||
#include "jsapi.h"
|
||||
#include "jsfriendapi.h"
|
||||
|
@ -25,12 +26,14 @@ template<bool mainThread>
|
|||
inline bool
|
||||
Throw(JSContext* cx, nsresult rv)
|
||||
{
|
||||
using mozilla::dom::workers::exceptions::ThrowDOMExceptionForNSResult;
|
||||
|
||||
// XXX Introduce exception machinery.
|
||||
if (mainThread) {
|
||||
XPCThrower::Throw(rv, cx);
|
||||
} else {
|
||||
if (!JS_IsExceptionPending(cx)) {
|
||||
JS_ReportError(cx, "Exception thrown (nsresult = %x).", rv);
|
||||
ThrowDOMExceptionForNSResult(cx, rv);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
|
|
@ -233,9 +233,9 @@ ConsoleListener::Observe(nsIConsoleMessage* aMessage)
|
|||
ContentChild* ContentChild::sSingleton;
|
||||
|
||||
ContentChild::ContentChild()
|
||||
: mID(PRUint64(-1))
|
||||
#ifdef ANDROID
|
||||
: mScreenSize(0, 0)
|
||||
, mID(PRUint64(-1))
|
||||
, mScreenSize(0, 0)
|
||||
#endif
|
||||
{
|
||||
// This process is a content process, so it's clearly running in
|
||||
|
|
|
@ -201,8 +201,6 @@ private:
|
|||
gfxIntSize mScreenSize;
|
||||
#endif
|
||||
|
||||
AppInfo mAppInfo;
|
||||
|
||||
/**
|
||||
* An ID unique to the process containing our corresponding
|
||||
* content parent.
|
||||
|
@ -212,6 +210,8 @@ private:
|
|||
*/
|
||||
PRUint64 mID;
|
||||
|
||||
AppInfo mAppInfo;
|
||||
|
||||
static ContentChild* sSingleton;
|
||||
|
||||
DISALLOW_EVIL_CONSTRUCTORS(ContentChild);
|
||||
|
|
|
@ -70,6 +70,7 @@
|
|||
#include "nsIViewManager.h"
|
||||
#include "mozilla/unused.h"
|
||||
#include "nsDebug.h"
|
||||
#include "nsPrintfCString.h"
|
||||
|
||||
using namespace mozilla::dom;
|
||||
using namespace mozilla::ipc;
|
||||
|
@ -93,6 +94,7 @@ TabParent::TabParent()
|
|||
, mIMESeqno(0)
|
||||
, mDPI(0)
|
||||
, mActive(false)
|
||||
, mShown(false)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -104,13 +106,7 @@ void
|
|||
TabParent::SetOwnerElement(nsIDOMElement* aElement)
|
||||
{
|
||||
mFrameElement = aElement;
|
||||
|
||||
// Cache the DPI of the screen, since we may lose the element/widget later
|
||||
if (aElement) {
|
||||
nsCOMPtr<nsIWidget> widget = GetWidget();
|
||||
NS_ABORT_IF_FALSE(widget, "Non-null OwnerElement must provide a widget!");
|
||||
mDPI = widget->GetDPI();
|
||||
}
|
||||
TryCacheDPI();
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -197,6 +193,16 @@ TabParent::AnswerCreateWindow(PBrowserParent** retval)
|
|||
void
|
||||
TabParent::LoadURL(nsIURI* aURI)
|
||||
{
|
||||
if (!mShown) {
|
||||
nsCAutoString spec;
|
||||
if (aURI) {
|
||||
aURI->GetSpec(spec);
|
||||
}
|
||||
NS_WARNING(nsPrintfCString("TabParent::LoadURL(%s) called before "
|
||||
"Show(). Ignoring LoadURL.\n", spec.get()).get());
|
||||
return;
|
||||
}
|
||||
|
||||
nsCString spec;
|
||||
aURI->GetSpec(spec);
|
||||
|
||||
|
@ -207,6 +213,7 @@ void
|
|||
TabParent::Show(const nsIntSize& size)
|
||||
{
|
||||
// sigh
|
||||
mShown = true;
|
||||
unused << SendShow(size);
|
||||
}
|
||||
|
||||
|
@ -621,6 +628,7 @@ TabParent::RecvSetInputContext(const PRInt32& aIMEEnabled,
|
|||
bool
|
||||
TabParent::RecvGetDPI(float* aValue)
|
||||
{
|
||||
TryCacheDPI();
|
||||
NS_ABORT_IF_FALSE(mDPI > 0,
|
||||
"Must not ask for DPI before OwnerElement is received!");
|
||||
*aValue = mDPI;
|
||||
|
@ -848,6 +856,19 @@ TabParent::GetFrameLoader() const
|
|||
return frameLoaderOwner ? frameLoaderOwner->GetFrameLoader() : nsnull;
|
||||
}
|
||||
|
||||
void
|
||||
TabParent::TryCacheDPI()
|
||||
{
|
||||
if (mDPI > 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIWidget> widget = GetWidget();
|
||||
if (widget) {
|
||||
mDPI = widget->GetDPI();
|
||||
}
|
||||
}
|
||||
|
||||
already_AddRefed<nsIWidget>
|
||||
TabParent::GetWidget() const
|
||||
{
|
||||
|
@ -859,7 +880,8 @@ TabParent::GetWidget() const
|
|||
if (!frame)
|
||||
return nsnull;
|
||||
|
||||
return nsCOMPtr<nsIWidget>(frame->GetNearestWidget()).forget();
|
||||
nsCOMPtr<nsIWidget> widget = frame->GetNearestWidget();
|
||||
return widget.forget();
|
||||
}
|
||||
|
||||
} // namespace tabs
|
||||
|
|
|
@ -233,10 +233,12 @@ protected:
|
|||
|
||||
float mDPI;
|
||||
bool mActive;
|
||||
bool mShown;
|
||||
|
||||
private:
|
||||
already_AddRefed<nsFrameLoader> GetFrameLoader() const;
|
||||
already_AddRefed<nsIWidget> GetWidget() const;
|
||||
void TryCacheDPI();
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
|
|
|
@ -314,8 +314,7 @@ typedef enum {
|
|||
NPDrawingModelSyncX = 6,
|
||||
NPDrawingModelAsyncBitmapSurface = 7
|
||||
#if defined(XP_WIN)
|
||||
, NPDrawingModelAsyncWindowsDXGISurface = 8,
|
||||
NPDrawingModelAsyncWindowsDX9ExSurface = 9
|
||||
, NPDrawingModelAsyncWindowsDXGISurface = 8
|
||||
#endif
|
||||
} NPDrawingModel;
|
||||
|
||||
|
@ -462,11 +461,9 @@ typedef enum {
|
|||
, NPNVsupportsCoreAnimationBool = 2003
|
||||
, NPNVsupportsInvalidatingCoreAnimationBool = 2004
|
||||
#endif
|
||||
, NPNVsupportsSyncDrawingBool = 2005
|
||||
, NPNVsupportsAsyncBitmapSurfaceBool = 2006
|
||||
, NPNVsupportsAsyncBitmapSurfaceBool = 2005
|
||||
#if defined(XP_WIN)
|
||||
, NPNVsupportsAsyncWindowsDXGISurfaceBool = 2007
|
||||
, NPNVsupportsAsyncWindowsDX9ExSurfaceBool = 2008
|
||||
, NPNVsupportsAsyncWindowsDXGISurfaceBool = 2006
|
||||
#endif
|
||||
|
||||
#if defined(XP_MACOSX)
|
||||
|
|
|
@ -93,7 +93,6 @@ inline bool IsDrawingModelAsync(int16_t aModel) {
|
|||
return aModel == NPDrawingModelAsyncBitmapSurface
|
||||
#ifdef XP_WIN
|
||||
|| aModel == NPDrawingModelAsyncWindowsDXGISurface
|
||||
|| aModel == NPDrawingModelAsyncWindowsDX9ExSurface
|
||||
#endif
|
||||
;
|
||||
}
|
||||
|
|
|
@ -1244,6 +1244,8 @@ DOMStorageImpl::RemoveValue(bool aCallerSecure, const nsAString& aKey,
|
|||
nsresult rv = InitDB();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
CacheKeysFromDB();
|
||||
|
||||
nsAutoString value;
|
||||
bool secureItem;
|
||||
rv = GetDBValue(aKey, value, &secureItem);
|
||||
|
|
|
@ -21,6 +21,15 @@ const browserFrameHelpers = {
|
|||
}
|
||||
},
|
||||
|
||||
'getOOPDisabledPref': function() {
|
||||
try {
|
||||
return SpecialPowers.getBoolPref('dom.ipc.tabs.disabled');
|
||||
}
|
||||
catch(e) {
|
||||
return undefined;
|
||||
}
|
||||
},
|
||||
|
||||
'setEnabledPref': function(enabled) {
|
||||
if (enabled !== undefined) {
|
||||
SpecialPowers.setBoolPref('dom.mozBrowserFramesEnabled', enabled);
|
||||
|
@ -39,6 +48,15 @@ const browserFrameHelpers = {
|
|||
}
|
||||
},
|
||||
|
||||
'setOOPDisabledPref': function(value) {
|
||||
if (value !== undefined) {
|
||||
SpecialPowers.setBoolPref('dom.ipc.tabs.disabled', value);
|
||||
}
|
||||
else {
|
||||
SpecialPowers.clearUserPref('dom.ipc.tabs.disabled');
|
||||
}
|
||||
},
|
||||
|
||||
'addToWhitelist': function() {
|
||||
var whitelist = browserFrameHelpers.getWhitelistPref();
|
||||
whitelist += ', http://' + window.location.host + ', ';
|
||||
|
@ -48,10 +66,12 @@ const browserFrameHelpers = {
|
|||
'restoreOriginalPrefs': function() {
|
||||
browserFrameHelpers.setEnabledPref(browserFrameHelpers.origEnabledPref);
|
||||
browserFrameHelpers.setWhitelistPref(browserFrameHelpers.origWhitelistPref);
|
||||
browserFrameHelpers.setOOPDisabledPref(browserFrameHelpers.origOOPDisabledPref);
|
||||
},
|
||||
|
||||
'origEnabledPref': null,
|
||||
'origWhitelistPref': null,
|
||||
'origOOPDisabledPref': null,
|
||||
|
||||
// Two basically-empty pages from two different domains you can load.
|
||||
'emptyPage1': 'http://example.com' +
|
||||
|
@ -64,6 +84,11 @@ const browserFrameHelpers = {
|
|||
|
||||
browserFrameHelpers.origEnabledPref = browserFrameHelpers.getEnabledPref();
|
||||
browserFrameHelpers.origWhitelistPref = browserFrameHelpers.getWhitelistPref();
|
||||
browserFrameHelpers.origOOPDisabledPref = browserFrameHelpers.getOOPDisabledPref();
|
||||
|
||||
// Set OOPDisabledPref to true, because none of these tests pass with OOP
|
||||
// browser frames, at the moment.
|
||||
browserFrameHelpers.setOOPDisabledPref(true);
|
||||
|
||||
addEventListener('unload', function() {
|
||||
browserFrameHelpers.restoreOriginalPrefs();
|
||||
|
|
|
@ -64,6 +64,8 @@ _TEST_FILES = \
|
|||
pbSwitch.js \
|
||||
test_brokenUTF-16.html \
|
||||
test_bug624047.html \
|
||||
test_bug746272-1.html \
|
||||
test_bug746272-2.html \
|
||||
test_cookieBlock.html \
|
||||
test_cookieSession-phase1.html \
|
||||
test_cookieSession-phase2.html \
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<title>incomplete UTF-16 test</title>
|
||||
<meta http-equiv="Content-type" content="text/html; charset=UTF-8" />
|
||||
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
|
||||
<script type="text/javascript">
|
||||
|
||||
function startTest()
|
||||
{
|
||||
localStorage.clear();
|
||||
localStorage.setItem("test1", "value1");
|
||||
localStorage.setItem("test2", "value2");
|
||||
localStorage.setItem("test3", "value3");
|
||||
|
||||
is(localStorage.length, 3, "expected number of items");
|
||||
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
</script>
|
||||
|
||||
</head>
|
||||
|
||||
<body onload="startTest();">
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,31 @@
|
|||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<title>incomplete UTF-16 test</title>
|
||||
<meta http-equiv="Content-type" content="text/html; charset=UTF-8" />
|
||||
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
|
||||
<script type="text/javascript">
|
||||
|
||||
function startTest()
|
||||
{
|
||||
var test2 = localStorage.getItem("test2");
|
||||
is(test2, "value2", "expected item");
|
||||
|
||||
localStorage.removeItem("test2");
|
||||
is(localStorage.length, 2, "expected number of items");
|
||||
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
</script>
|
||||
|
||||
</head>
|
||||
|
||||
<body onload="startTest();">
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -43,6 +43,7 @@
|
|||
#include "jsfriendapi.h"
|
||||
#include "jsprf.h"
|
||||
#include "mozilla/Util.h"
|
||||
#include "nsDOMException.h"
|
||||
#include "nsTraceRefcnt.h"
|
||||
|
||||
#include "WorkerInlines.h"
|
||||
|
@ -68,6 +69,7 @@ class DOMException : public PrivatizableBase
|
|||
enum SLOT {
|
||||
SLOT_code = 0,
|
||||
SLOT_name,
|
||||
SLOT_message,
|
||||
|
||||
SLOT_COUNT
|
||||
};
|
||||
|
@ -87,7 +89,7 @@ public:
|
|||
}
|
||||
|
||||
static JSObject*
|
||||
Create(JSContext* aCx, int aCode);
|
||||
Create(JSContext* aCx, nsresult aNSResult);
|
||||
|
||||
private:
|
||||
DOMException()
|
||||
|
@ -131,18 +133,23 @@ private:
|
|||
return false;
|
||||
}
|
||||
|
||||
char buf[100];
|
||||
JS_snprintf(buf, sizeof(buf), "%s: ", sClass.name);
|
||||
jsval name = JS_GetReservedSlot(obj, SLOT_name);
|
||||
JS_ASSERT(name.isString());
|
||||
|
||||
JSString* classString = JS_NewStringCopyZ(aCx, buf);
|
||||
if (!classString) {
|
||||
JSString *colon = JS_NewStringCopyN(aCx, ": ", 2);
|
||||
if (!colon){
|
||||
return false;
|
||||
}
|
||||
|
||||
jsval name = JS_GetReservedSlot(obj, SLOT_name);
|
||||
JS_ASSERT(JSVAL_IS_STRING(name));
|
||||
JSString* out = JS_ConcatStrings(aCx, name.toString(), colon);
|
||||
if (!out) {
|
||||
return false;
|
||||
}
|
||||
|
||||
JSString* out = JS_ConcatStrings(aCx, classString, JSVAL_TO_STRING(name));
|
||||
jsval message = JS_GetReservedSlot(obj, SLOT_message);
|
||||
JS_ASSERT(message.isString());
|
||||
|
||||
out = JS_ConcatStrings(aCx, out, message.toString());
|
||||
if (!out) {
|
||||
return false;
|
||||
}
|
||||
|
@ -190,6 +197,7 @@ JSClass DOMException::sClass = {
|
|||
JSPropertySpec DOMException::sProperties[] = {
|
||||
{ "code", SLOT_code, PROPERTY_FLAGS, GetProperty, js_GetterOnlyPropertyStub },
|
||||
{ "name", SLOT_name, PROPERTY_FLAGS, GetProperty, js_GetterOnlyPropertyStub },
|
||||
{ "message", SLOT_message, PROPERTY_FLAGS, GetProperty, js_GetterOnlyPropertyStub },
|
||||
{ 0, 0, 0, NULL, NULL }
|
||||
};
|
||||
|
||||
|
@ -203,9 +211,6 @@ JSPropertySpec DOMException::sStaticProperties[] = {
|
|||
#define EXCEPTION_ENTRY(_name) \
|
||||
{ #_name, _name, CONSTANT_FLAGS, GetConstant, NULL },
|
||||
|
||||
// Make sure this one is always first.
|
||||
EXCEPTION_ENTRY(UNKNOWN_ERR)
|
||||
|
||||
EXCEPTION_ENTRY(INDEX_SIZE_ERR)
|
||||
EXCEPTION_ENTRY(DOMSTRING_SIZE_ERR)
|
||||
EXCEPTION_ENTRY(HIERARCHY_REQUEST_ERR)
|
||||
|
@ -239,32 +244,35 @@ JSPropertySpec DOMException::sStaticProperties[] = {
|
|||
|
||||
// static
|
||||
JSObject*
|
||||
DOMException::Create(JSContext* aCx, int aCode)
|
||||
DOMException::Create(JSContext* aCx, nsresult aNSResult)
|
||||
{
|
||||
JSObject* obj = JS_NewObject(aCx, &sClass, NULL, NULL);
|
||||
if (!obj) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
size_t foundIndex = size_t(-1);
|
||||
for (size_t index = 0; index < ArrayLength(sStaticProperties) - 1; index++) {
|
||||
if (sStaticProperties[index].tinyid == aCode) {
|
||||
foundIndex = index;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (foundIndex == size_t(-1)) {
|
||||
foundIndex = 0;
|
||||
}
|
||||
|
||||
JSString* name = JS_NewStringCopyZ(aCx, sStaticProperties[foundIndex].name);
|
||||
if (!name) {
|
||||
const char* name;
|
||||
const char* message;
|
||||
uint16_t code;
|
||||
if (NS_FAILED(NS_GetNameAndMessageForDOMNSResult(aNSResult, &name, &message,
|
||||
&code))) {
|
||||
JS_ReportError(aCx, "Exception thrown (nsresult = 0x%x).", aNSResult);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
JS_SetReservedSlot(obj, SLOT_code, INT_TO_JSVAL(aCode));
|
||||
JS_SetReservedSlot(obj, SLOT_name, STRING_TO_JSVAL(name));
|
||||
JSString* jsname = JS_NewStringCopyZ(aCx, name);
|
||||
if (!jsname) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
JSString* jsmessage = JS_NewStringCopyZ(aCx, message);
|
||||
if (!jsmessage) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
JS_SetReservedSlot(obj, SLOT_code, INT_TO_JSVAL(code));
|
||||
JS_SetReservedSlot(obj, SLOT_name, STRING_TO_JSVAL(jsname));
|
||||
JS_SetReservedSlot(obj, SLOT_message, STRING_TO_JSVAL(jsmessage));
|
||||
|
||||
DOMException* priv = new DOMException();
|
||||
SetJSPrivateSafeish(obj, priv);
|
||||
|
@ -272,147 +280,6 @@ DOMException::Create(JSContext* aCx, int aCode)
|
|||
return obj;
|
||||
}
|
||||
|
||||
class FileException : public PrivatizableBase
|
||||
{
|
||||
static JSClass sClass;
|
||||
static JSPropertySpec sProperties[];
|
||||
static JSPropertySpec sStaticProperties[];
|
||||
|
||||
enum SLOT {
|
||||
SLOT_code = 0,
|
||||
SLOT_name,
|
||||
|
||||
SLOT_COUNT
|
||||
};
|
||||
|
||||
public:
|
||||
static JSObject*
|
||||
InitClass(JSContext* aCx, JSObject* aObj)
|
||||
{
|
||||
return JS_InitClass(aCx, aObj, NULL, &sClass, Construct, 0, sProperties,
|
||||
NULL, sStaticProperties, NULL);
|
||||
}
|
||||
|
||||
static JSObject*
|
||||
Create(JSContext* aCx, int aCode);
|
||||
|
||||
private:
|
||||
FileException()
|
||||
{
|
||||
MOZ_COUNT_CTOR(mozilla::dom::workers::exceptions::FileException);
|
||||
}
|
||||
|
||||
~FileException()
|
||||
{
|
||||
MOZ_COUNT_DTOR(mozilla::dom::workers::exceptions::FileException);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
Construct(JSContext* aCx, unsigned aArgc, jsval* aVp)
|
||||
{
|
||||
JS_ReportErrorNumber(aCx, js_GetErrorMessage, NULL, JSMSG_WRONG_CONSTRUCTOR,
|
||||
sClass.name);
|
||||
return false;
|
||||
}
|
||||
|
||||
static void
|
||||
Finalize(JSFreeOp* aFop, JSObject* aObj)
|
||||
{
|
||||
JS_ASSERT(JS_GetClass(aObj) == &sClass);
|
||||
delete GetJSPrivateSafeish<FileException>(aObj);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
GetProperty(JSContext* aCx, JSObject* aObj, jsid aIdval, jsval* aVp)
|
||||
{
|
||||
JS_ASSERT(JSID_IS_INT(aIdval));
|
||||
|
||||
int32 slot = JSID_TO_INT(aIdval);
|
||||
|
||||
JSClass* classPtr = JS_GetClass(aObj);
|
||||
|
||||
if (classPtr != &sClass || !GetJSPrivateSafeish<FileException>(aObj)) {
|
||||
JS_ReportErrorNumber(aCx, js_GetErrorMessage, NULL,
|
||||
JSMSG_INCOMPATIBLE_PROTO, sClass.name,
|
||||
sProperties[slot].name, classPtr->name);
|
||||
return false;
|
||||
}
|
||||
|
||||
*aVp = JS_GetReservedSlot(aObj, slot);
|
||||
return true;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
GetConstant(JSContext* aCx, JSObject* aObj, jsid idval, jsval* aVp)
|
||||
{
|
||||
JS_ASSERT(JSID_IS_INT(idval));
|
||||
*aVp = INT_TO_JSVAL(JSID_TO_INT(idval));
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
JSClass FileException::sClass = {
|
||||
"FileException",
|
||||
JSCLASS_HAS_PRIVATE | JSCLASS_HAS_RESERVED_SLOTS(SLOT_COUNT),
|
||||
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_StrictPropertyStub,
|
||||
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, Finalize
|
||||
};
|
||||
|
||||
JSPropertySpec FileException::sProperties[] = {
|
||||
{ "code", SLOT_code, PROPERTY_FLAGS, GetProperty, js_GetterOnlyPropertyStub },
|
||||
{ "name", SLOT_name, PROPERTY_FLAGS, GetProperty, js_GetterOnlyPropertyStub },
|
||||
{ 0, 0, 0, NULL, NULL }
|
||||
};
|
||||
|
||||
JSPropertySpec FileException::sStaticProperties[] = {
|
||||
|
||||
#define EXCEPTION_ENTRY(_name) \
|
||||
{ #_name, FILE_##_name, CONSTANT_FLAGS, GetConstant, NULL },
|
||||
|
||||
EXCEPTION_ENTRY(NOT_FOUND_ERR)
|
||||
EXCEPTION_ENTRY(SECURITY_ERR)
|
||||
EXCEPTION_ENTRY(ABORT_ERR)
|
||||
EXCEPTION_ENTRY(NOT_READABLE_ERR)
|
||||
EXCEPTION_ENTRY(ENCODING_ERR)
|
||||
|
||||
#undef EXCEPTION_ENTRY
|
||||
|
||||
{ 0, 0, 0, NULL, NULL }
|
||||
};
|
||||
|
||||
// static
|
||||
JSObject*
|
||||
FileException::Create(JSContext* aCx, int aCode)
|
||||
{
|
||||
JSObject* obj = JS_NewObject(aCx, &sClass, NULL, NULL);
|
||||
if (!obj) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
size_t foundIndex = size_t(-1);
|
||||
for (size_t index = 0; index < ArrayLength(sStaticProperties) - 1; index++) {
|
||||
if (sStaticProperties[index].tinyid == aCode) {
|
||||
foundIndex = index;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
JS_ASSERT(foundIndex != size_t(-1));
|
||||
|
||||
JSString* name = JS_NewStringCopyZ(aCx, sStaticProperties[foundIndex].name);
|
||||
if (!name) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
JS_SetReservedSlot(obj, SLOT_code, INT_TO_JSVAL(aCode));
|
||||
JS_SetReservedSlot(obj, SLOT_name, STRING_TO_JSVAL(name));
|
||||
|
||||
FileException* priv = new FileException();
|
||||
SetJSPrivateSafeish(obj, priv);
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
BEGIN_WORKERS_NAMESPACE
|
||||
|
@ -422,24 +289,16 @@ namespace exceptions {
|
|||
bool
|
||||
InitClasses(JSContext* aCx, JSObject* aGlobal)
|
||||
{
|
||||
return DOMException::InitClass(aCx, aGlobal) &&
|
||||
FileException::InitClass(aCx, aGlobal);
|
||||
return DOMException::InitClass(aCx, aGlobal);
|
||||
}
|
||||
|
||||
void
|
||||
ThrowDOMExceptionForCode(JSContext* aCx, int aCode)
|
||||
ThrowDOMExceptionForNSResult(JSContext* aCx, nsresult aNSResult)
|
||||
{
|
||||
JSObject* exception = DOMException::Create(aCx, aCode);
|
||||
JS_ASSERT(exception);
|
||||
|
||||
JS_SetPendingException(aCx, OBJECT_TO_JSVAL(exception));
|
||||
}
|
||||
|
||||
void
|
||||
ThrowFileExceptionForCode(JSContext* aCx, int aCode)
|
||||
{
|
||||
JSObject* exception = FileException::Create(aCx, aCode);
|
||||
JS_ASSERT(exception);
|
||||
JSObject* exception = DOMException::Create(aCx, aNSResult);
|
||||
if (!exception) {
|
||||
return;
|
||||
}
|
||||
|
||||
JS_SetPendingException(aCx, OBJECT_TO_JSVAL(exception));
|
||||
}
|
||||
|
|
|
@ -71,16 +71,6 @@
|
|||
#define INVALID_NODE_TYPE_ERR 24
|
||||
#define DATA_CLONE_ERR 25
|
||||
|
||||
// This one isn't actually spec'd anywhere, use it when we can't find a match.
|
||||
#define UNKNOWN_ERR 0
|
||||
|
||||
// FileException Codes
|
||||
#define FILE_NOT_FOUND_ERR 1
|
||||
#define FILE_SECURITY_ERR 2
|
||||
#define FILE_ABORT_ERR 3
|
||||
#define FILE_NOT_READABLE_ERR 4
|
||||
#define FILE_ENCODING_ERR 5
|
||||
|
||||
BEGIN_WORKERS_NAMESPACE
|
||||
|
||||
namespace exceptions {
|
||||
|
@ -88,12 +78,6 @@ namespace exceptions {
|
|||
bool
|
||||
InitClasses(JSContext* aCx, JSObject* aGlobal);
|
||||
|
||||
void
|
||||
ThrowDOMExceptionForCode(JSContext* aCx, int aCode);
|
||||
|
||||
void
|
||||
ThrowFileExceptionForCode(JSContext* aCx, int aCode);
|
||||
|
||||
} // namespace exceptions
|
||||
|
||||
END_WORKERS_NAMESPACE
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
|
||||
#include "nsIDOMFile.h"
|
||||
#include "nsDOMBlobBuilder.h"
|
||||
#include "nsDOMError.h"
|
||||
|
||||
#include "jsapi.h"
|
||||
#include "jsatom.h"
|
||||
|
@ -58,8 +59,7 @@
|
|||
|
||||
USING_WORKERS_NAMESPACE
|
||||
|
||||
using mozilla::dom::workers::exceptions::ThrowDOMExceptionForCode;
|
||||
using mozilla::dom::workers::exceptions::ThrowFileExceptionForCode;
|
||||
using mozilla::dom::workers::exceptions::ThrowDOMExceptionForNSResult;
|
||||
|
||||
namespace {
|
||||
|
||||
|
@ -125,9 +125,7 @@ private:
|
|||
nsresult rv = file->InitInternal(aCx, aArgc, JS_ARGV(aCx, aVp),
|
||||
Unwrap);
|
||||
if (NS_FAILED(rv)) {
|
||||
ThrowDOMExceptionForCode(aCx,
|
||||
NS_ERROR_GET_MODULE(rv) == NS_ERROR_MODULE_DOM ?
|
||||
NS_ERROR_GET_CODE(rv) : UNKNOWN_ERR);
|
||||
ThrowDOMExceptionForNSResult(aCx, rv);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -159,7 +157,8 @@ private:
|
|||
|
||||
PRUint64 size;
|
||||
if (NS_FAILED(blob->GetSize(&size))) {
|
||||
ThrowFileExceptionForCode(aCx, FILE_NOT_READABLE_ERR);
|
||||
ThrowDOMExceptionForNSResult(aCx, NS_ERROR_DOM_FILE_NOT_READABLE_ERR);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!JS_NewNumberValue(aCx, double(size), aVp)) {
|
||||
|
@ -179,7 +178,8 @@ private:
|
|||
|
||||
nsString type;
|
||||
if (NS_FAILED(blob->GetType(type))) {
|
||||
ThrowFileExceptionForCode(aCx, FILE_NOT_READABLE_ERR);
|
||||
ThrowDOMExceptionForNSResult(aCx, NS_ERROR_DOM_FILE_NOT_READABLE_ERR);
|
||||
return false;
|
||||
}
|
||||
|
||||
JSString* jsType = JS_NewUCStringCopyN(aCx, type.get(), type.Length());
|
||||
|
@ -223,7 +223,7 @@ private:
|
|||
static_cast<PRUint64>(end),
|
||||
contentType, optionalArgc,
|
||||
getter_AddRefs(rtnBlob)))) {
|
||||
ThrowFileExceptionForCode(aCx, FILE_NOT_READABLE_ERR);
|
||||
ThrowDOMExceptionForNSResult(aCx, NS_ERROR_DOM_FILE_NOT_READABLE_ERR);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -350,7 +350,7 @@ private:
|
|||
|
||||
if (GetWorkerPrivateFromContext(aCx)->UsesSystemPrincipal() &&
|
||||
NS_FAILED(file->GetMozFullPathInternal(fullPath))) {
|
||||
ThrowFileExceptionForCode(aCx, FILE_NOT_READABLE_ERR);
|
||||
ThrowDOMExceptionForNSResult(aCx, NS_ERROR_DOM_FILE_NOT_READABLE_ERR);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -40,6 +40,7 @@
|
|||
#include "FileReaderSync.h"
|
||||
|
||||
#include "nsIDOMFile.h"
|
||||
#include "nsDOMError.h"
|
||||
|
||||
#include "jsapi.h"
|
||||
#include "jsatom.h"
|
||||
|
@ -56,7 +57,7 @@
|
|||
|
||||
USING_WORKERS_NAMESPACE
|
||||
|
||||
using mozilla::dom::workers::exceptions::ThrowFileExceptionForCode;
|
||||
using mozilla::dom::workers::exceptions::ThrowDOMExceptionForNSResult;
|
||||
|
||||
namespace {
|
||||
|
||||
|
@ -67,10 +68,10 @@ EnsureSucceededOrThrow(JSContext* aCx, nsresult rv)
|
|||
return true;
|
||||
}
|
||||
|
||||
int code = rv == NS_ERROR_FILE_NOT_FOUND ?
|
||||
FILE_NOT_FOUND_ERR :
|
||||
FILE_NOT_READABLE_ERR;
|
||||
ThrowFileExceptionForCode(aCx, code);
|
||||
rv = rv == NS_ERROR_FILE_NOT_FOUND ?
|
||||
NS_ERROR_DOM_FILE_NOT_FOUND_ERR :
|
||||
NS_ERROR_DOM_FILE_NOT_READABLE_ERR;
|
||||
ThrowDOMExceptionForNSResult(aCx, rv);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -100,7 +100,7 @@
|
|||
using mozilla::MutexAutoLock;
|
||||
using mozilla::TimeDuration;
|
||||
using mozilla::TimeStamp;
|
||||
using mozilla::dom::workers::exceptions::ThrowDOMExceptionForCode;
|
||||
using mozilla::dom::workers::exceptions::ThrowDOMExceptionForNSResult;
|
||||
|
||||
USING_WORKERS_NAMESPACE
|
||||
using namespace mozilla::dom::workers::events;
|
||||
|
@ -415,7 +415,7 @@ struct WorkerStructuredCloneCallbacks
|
|||
static void
|
||||
Error(JSContext* aCx, uint32_t /* aErrorId */)
|
||||
{
|
||||
ThrowDOMExceptionForCode(aCx, DATA_CLONE_ERR);
|
||||
ThrowDOMExceptionForNSResult(aCx, NS_ERROR_DOM_DATA_CLONE_ERR);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -97,6 +97,14 @@ GetWorkerCrossThreadDispatcher(JSContext* aCx, jsval aWorker);
|
|||
// Random unique constant to facilitate JSPrincipal debugging
|
||||
const uint32_t kJSPrincipalsDebugToken = 0x7e2df9d2;
|
||||
|
||||
namespace exceptions {
|
||||
|
||||
// Implemented in Exceptions.cpp
|
||||
void
|
||||
ThrowDOMExceptionForNSResult(JSContext* aCx, nsresult aNSResult);
|
||||
|
||||
} // namespace exceptions
|
||||
|
||||
END_WORKERS_NAMESPACE
|
||||
|
||||
#endif // mozilla_dom_workers_workers_h__
|
||||
|
|
|
@ -34,7 +34,7 @@ USING_WORKERS_NAMESPACE
|
|||
namespace XMLHttpRequestResponseTypeValues =
|
||||
mozilla::dom::bindings::prototypes::XMLHttpRequestResponseType;
|
||||
|
||||
using mozilla::dom::workers::exceptions::ThrowDOMExceptionForCode;
|
||||
using mozilla::dom::workers::exceptions::ThrowDOMExceptionForNSResult;
|
||||
|
||||
// XXX Need to figure this out...
|
||||
#define UNCATCHABLE_EXCEPTION NS_ERROR_OUT_OF_MEMORY
|
||||
|
@ -214,21 +214,6 @@ END_WORKERS_NAMESPACE
|
|||
|
||||
namespace {
|
||||
|
||||
inline int
|
||||
GetDOMExceptionCodeFromResult(nsresult aResult)
|
||||
{
|
||||
if (NS_SUCCEEDED(aResult)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (NS_ERROR_GET_MODULE(aResult) == NS_ERROR_MODULE_DOM) {
|
||||
return NS_ERROR_GET_CODE(aResult);
|
||||
}
|
||||
|
||||
NS_WARNING("Update main thread implementation for a DOM error code here!");
|
||||
return INVALID_STATE_ERR;
|
||||
}
|
||||
|
||||
inline void
|
||||
ConvertResponseTypeToString(XMLHttpRequestResponseType aType, nsString& aString)
|
||||
{
|
||||
|
@ -783,11 +768,11 @@ private:
|
|||
class ResponseRunnable : public MainThreadProxyRunnable
|
||||
{
|
||||
PRUint32 mSyncQueueKey;
|
||||
int mErrorCode;
|
||||
nsresult mErrorCode;
|
||||
|
||||
public:
|
||||
ResponseRunnable(WorkerPrivate* aWorkerPrivate, Proxy* aProxy,
|
||||
PRUint32 aSyncQueueKey, int aErrorCode)
|
||||
PRUint32 aSyncQueueKey, nsresult aErrorCode)
|
||||
: MainThreadProxyRunnable(aWorkerPrivate, SkipWhenClearing, aProxy),
|
||||
mSyncQueueKey(aSyncQueueKey), mErrorCode(aErrorCode)
|
||||
{
|
||||
|
@ -797,8 +782,8 @@ private:
|
|||
bool
|
||||
WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate)
|
||||
{
|
||||
if (mErrorCode) {
|
||||
ThrowDOMExceptionForCode(aCx, mErrorCode);
|
||||
if (NS_FAILED(mErrorCode)) {
|
||||
ThrowDOMExceptionForNSResult(aCx, mErrorCode);
|
||||
aWorkerPrivate->StopSyncLoop(mSyncQueueKey, false);
|
||||
}
|
||||
else {
|
||||
|
@ -836,7 +821,7 @@ public:
|
|||
return true;
|
||||
}
|
||||
|
||||
virtual int
|
||||
virtual nsresult
|
||||
MainThreadRun() = 0;
|
||||
|
||||
NS_IMETHOD
|
||||
|
@ -847,7 +832,7 @@ public:
|
|||
PRUint32 oldSyncQueueKey = mProxy->mSyncEventResponseSyncQueueKey;
|
||||
mProxy->mSyncEventResponseSyncQueueKey = mSyncQueueKey;
|
||||
|
||||
int rv = MainThreadRun();
|
||||
nsresult rv = MainThreadRun();
|
||||
|
||||
nsRefPtr<ResponseRunnable> response =
|
||||
new ResponseRunnable(mWorkerPrivate, mProxy, mSyncQueueKey, rv);
|
||||
|
@ -871,7 +856,7 @@ public:
|
|||
MOZ_ASSERT(aProxy);
|
||||
}
|
||||
|
||||
virtual int
|
||||
virtual nsresult
|
||||
MainThreadRun()
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
|
@ -892,10 +877,10 @@ public:
|
|||
: WorkerThreadProxySyncRunnable(aWorkerPrivate, aProxy), mValue(aValue)
|
||||
{ }
|
||||
|
||||
int
|
||||
nsresult
|
||||
MainThreadRun()
|
||||
{
|
||||
return GetDOMExceptionCodeFromResult(mProxy->mXHR->SetMultipart(mValue));
|
||||
return mProxy->mXHR->SetMultipart(mValue);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -909,11 +894,10 @@ public:
|
|||
: WorkerThreadProxySyncRunnable(aWorkerPrivate, aProxy), mValue(aValue)
|
||||
{ }
|
||||
|
||||
int
|
||||
nsresult
|
||||
MainThreadRun()
|
||||
{
|
||||
nsresult rv = mProxy->mXHR->SetMozBackgroundRequest(mValue);
|
||||
return GetDOMExceptionCodeFromResult(rv);
|
||||
return mProxy->mXHR->SetMozBackgroundRequest(mValue);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -927,11 +911,10 @@ public:
|
|||
: WorkerThreadProxySyncRunnable(aWorkerPrivate, aProxy), mValue(aValue)
|
||||
{ }
|
||||
|
||||
int
|
||||
nsresult
|
||||
MainThreadRun()
|
||||
{
|
||||
nsresult rv = mProxy->mXHR->SetWithCredentials(mValue);
|
||||
return GetDOMExceptionCodeFromResult(rv);
|
||||
return mProxy->mXHR->SetWithCredentials(mValue);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -946,7 +929,7 @@ public:
|
|||
mResponseType(aResponseType)
|
||||
{ }
|
||||
|
||||
int
|
||||
nsresult
|
||||
MainThreadRun()
|
||||
{
|
||||
nsresult rv = mProxy->mXHR->SetResponseType(mResponseType);
|
||||
|
@ -954,7 +937,7 @@ public:
|
|||
if (NS_SUCCEEDED(rv)) {
|
||||
rv = mProxy->mXHR->GetResponseType(mResponseType);
|
||||
}
|
||||
return GetDOMExceptionCodeFromResult(rv);
|
||||
return rv;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -974,10 +957,10 @@ public:
|
|||
mTimeout(aTimeout)
|
||||
{ }
|
||||
|
||||
int
|
||||
nsresult
|
||||
MainThreadRun()
|
||||
{
|
||||
return GetDOMExceptionCodeFromResult(mProxy->mXHR->SetTimeout(mTimeout));
|
||||
return mProxy->mXHR->SetTimeout(mTimeout);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -988,7 +971,7 @@ public:
|
|||
: WorkerThreadProxySyncRunnable(aWorkerPrivate, aProxy)
|
||||
{ }
|
||||
|
||||
int
|
||||
nsresult
|
||||
MainThreadRun()
|
||||
{
|
||||
mProxy->mInnerEventStreamId++;
|
||||
|
@ -1002,7 +985,7 @@ public:
|
|||
|
||||
mProxy->Reset();
|
||||
|
||||
return 0;
|
||||
return NS_OK;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1017,11 +1000,11 @@ public:
|
|||
mResponseHeaders(aResponseHeaders)
|
||||
{ }
|
||||
|
||||
int
|
||||
nsresult
|
||||
MainThreadRun()
|
||||
{
|
||||
mProxy->mXHR->GetAllResponseHeaders(mResponseHeaders);
|
||||
return 0;
|
||||
return NS_OK;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1037,11 +1020,10 @@ public:
|
|||
mValue(aValue)
|
||||
{ }
|
||||
|
||||
int
|
||||
nsresult
|
||||
MainThreadRun()
|
||||
{
|
||||
nsresult rv = mProxy->mXHR->GetResponseHeader(mHeader, mValue);
|
||||
return GetDOMExceptionCodeFromResult(rv);
|
||||
return mProxy->mXHR->GetResponseHeader(mHeader, mValue);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1068,53 +1050,45 @@ public:
|
|||
mTimeout(aTimeout)
|
||||
{ }
|
||||
|
||||
int
|
||||
nsresult
|
||||
MainThreadRun()
|
||||
{
|
||||
WorkerPrivate* oldWorker = mProxy->mWorkerPrivate;
|
||||
mProxy->mWorkerPrivate = mWorkerPrivate;
|
||||
|
||||
int retval = MainThreadRunInternal();
|
||||
nsresult rv = MainThreadRunInternal();
|
||||
|
||||
mProxy->mWorkerPrivate = oldWorker;
|
||||
return retval;
|
||||
return rv;
|
||||
}
|
||||
|
||||
int
|
||||
nsresult
|
||||
MainThreadRunInternal()
|
||||
{
|
||||
if (!mProxy->Init()) {
|
||||
return INVALID_STATE_ERR;
|
||||
return NS_ERROR_DOM_INVALID_STATE_ERR;
|
||||
}
|
||||
|
||||
nsresult rv;
|
||||
|
||||
if (mMultipart) {
|
||||
rv = mProxy->mXHR->SetMultipart(mMultipart);
|
||||
if (NS_FAILED(rv)) {
|
||||
return GetDOMExceptionCodeFromResult(rv);
|
||||
}
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
if (mBackgroundRequest) {
|
||||
rv = mProxy->mXHR->SetMozBackgroundRequest(mBackgroundRequest);
|
||||
if (NS_FAILED(rv)) {
|
||||
return GetDOMExceptionCodeFromResult(rv);
|
||||
}
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
if (mWithCredentials) {
|
||||
rv = mProxy->mXHR->SetWithCredentials(mWithCredentials);
|
||||
if (NS_FAILED(rv)) {
|
||||
return GetDOMExceptionCodeFromResult(rv);
|
||||
}
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
if (mTimeout) {
|
||||
rv = mProxy->mXHR->SetTimeout(mTimeout);
|
||||
if (NS_FAILED(rv)) {
|
||||
return GetDOMExceptionCodeFromResult(rv);
|
||||
}
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
NS_ASSERTION(!mProxy->mInOpen, "Reentrancy is bad!");
|
||||
|
@ -1129,7 +1103,7 @@ public:
|
|||
rv = mProxy->mXHR->SetResponseType(NS_LITERAL_STRING("text"));
|
||||
}
|
||||
|
||||
return GetDOMExceptionCodeFromResult(rv);
|
||||
return rv;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1154,7 +1128,7 @@ public:
|
|||
mClonedObjects.SwapElements(aClonedObjects);
|
||||
}
|
||||
|
||||
int
|
||||
nsresult
|
||||
MainThreadRun()
|
||||
{
|
||||
nsCOMPtr<nsIVariant> variant;
|
||||
|
@ -1164,7 +1138,7 @@ public:
|
|||
nsIXPConnect* xpc = nsContentUtils::XPConnect();
|
||||
NS_ASSERTION(xpc, "This should never be null!");
|
||||
|
||||
int error = 0;
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
JSStructuredCloneCallbacks* callbacks =
|
||||
mWorkerPrivate->IsChromeWorker() ?
|
||||
|
@ -1175,24 +1149,22 @@ public:
|
|||
if (mBody.read(cx, &body, callbacks, &mClonedObjects)) {
|
||||
if (NS_FAILED(xpc->JSValToVariant(cx, &body,
|
||||
getter_AddRefs(variant)))) {
|
||||
error = INVALID_STATE_ERR;
|
||||
rv = NS_ERROR_DOM_INVALID_STATE_ERR;
|
||||
}
|
||||
}
|
||||
else {
|
||||
error = DATA_CLONE_ERR;
|
||||
rv = NS_ERROR_DOM_DATA_CLONE_ERR;
|
||||
}
|
||||
|
||||
mBody.clear();
|
||||
mClonedObjects.Clear();
|
||||
|
||||
if (error) {
|
||||
return error;
|
||||
}
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
else {
|
||||
nsCOMPtr<nsIWritableVariant> wvariant =
|
||||
do_CreateInstance(NS_VARIANT_CONTRACTID);
|
||||
NS_ENSURE_TRUE(wvariant, UNKNOWN_ERR);
|
||||
NS_ENSURE_TRUE(wvariant, NS_ERROR_UNEXPECTED);
|
||||
|
||||
if (NS_FAILED(wvariant->SetAsAString(mStringBody))) {
|
||||
NS_ERROR("This should never fail!");
|
||||
|
@ -1229,7 +1201,7 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
return GetDOMExceptionCodeFromResult(rv);
|
||||
return rv;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1245,11 +1217,10 @@ public:
|
|||
mValue(aValue)
|
||||
{ }
|
||||
|
||||
int
|
||||
nsresult
|
||||
MainThreadRun()
|
||||
{
|
||||
nsresult rv = mProxy->mXHR->SetRequestHeader(mHeader, mValue);
|
||||
return GetDOMExceptionCodeFromResult(rv);
|
||||
return mProxy->mXHR->SetRequestHeader(mHeader, mValue);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1263,11 +1234,11 @@ public:
|
|||
: WorkerThreadProxySyncRunnable(aWorkerPrivate, aProxy), mMimeType(aMimeType)
|
||||
{ }
|
||||
|
||||
int
|
||||
nsresult
|
||||
MainThreadRun()
|
||||
{
|
||||
mProxy->mXHR->OverrideMimeType(mMimeType);
|
||||
return 0;
|
||||
return NS_OK;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -66,6 +66,16 @@ onmessage = function(event) {
|
|||
throw new Error("Failed to throw when getting responseText on '" + type +
|
||||
"' type");
|
||||
}
|
||||
|
||||
if (exception.name != "InvalidStateError") {
|
||||
throw new Error("Unexpected error when getting responseText on '" + type +
|
||||
"' type");
|
||||
}
|
||||
|
||||
if (exception.code != DOMException.INVALID_STATE_ERR) {
|
||||
throw new Error("Unexpected error code when getting responseText on '" + type +
|
||||
"' type");
|
||||
}
|
||||
}
|
||||
|
||||
testResponseTextException("arraybuffer");
|
||||
|
@ -102,6 +112,16 @@ onmessage = function(event) {
|
|||
"calling open()");
|
||||
}
|
||||
|
||||
if (exception.name != "InvalidStateError") {
|
||||
throw new Error("Unexpected error when setting responseType before " +
|
||||
"calling open()");
|
||||
}
|
||||
|
||||
if (exception.code != DOMException.INVALID_STATE_ERR) {
|
||||
throw new Error("Unexpected error code when setting responseType before " +
|
||||
"calling open()");
|
||||
}
|
||||
|
||||
xhr.open("GET", url);
|
||||
xhr.responseType = "text";
|
||||
xhr.onload = function(event) {
|
||||
|
@ -152,4 +172,14 @@ onmessage = function(event) {
|
|||
throw new Error("Failed to throw when setting responseType after " +
|
||||
"calling send()");
|
||||
}
|
||||
|
||||
if (exception.name != "InvalidStateError") {
|
||||
throw new Error("Unexpected error when setting responseType after " +
|
||||
"calling send()");
|
||||
}
|
||||
|
||||
if (exception.code != DOMException.INVALID_STATE_ERR) {
|
||||
throw new Error("Unexpected error code when setting responseType after " +
|
||||
"calling send()");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -42,6 +42,7 @@
|
|||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <algorithm>
|
||||
|
||||
#include "prlink.h"
|
||||
#include "prenv.h"
|
||||
|
@ -1295,361 +1296,334 @@ PRUint32 TiledTextureImage::GetTileCount()
|
|||
return mImages.Length();
|
||||
}
|
||||
|
||||
bool
|
||||
GLContext::ResizeOffscreenFBO(const gfxIntSize& aSize, const bool aUseReadFBO, const bool aDisableAA)
|
||||
GLContext::GLFormats
|
||||
GLContext::ChooseGLFormats(ContextFormat& aCF)
|
||||
{
|
||||
if (!IsOffscreenSizeAllowed(aSize))
|
||||
return false;
|
||||
GLFormats formats;
|
||||
|
||||
MakeCurrent();
|
||||
if (aCF.alpha) {
|
||||
formats.texColor = LOCAL_GL_RGBA;
|
||||
if (mIsGLES2 && !IsExtensionSupported(OES_rgb8_rgba8)) {
|
||||
formats.rbColor = LOCAL_GL_RGBA4;
|
||||
aCF.red = aCF.green = aCF.blue = aCF.alpha = 4;
|
||||
} else {
|
||||
formats.rbColor = LOCAL_GL_RGBA8;
|
||||
aCF.red = aCF.green = aCF.blue = aCF.alpha = 8;
|
||||
}
|
||||
} else {
|
||||
formats.texColor = LOCAL_GL_RGB;
|
||||
if (mIsGLES2 && !IsExtensionSupported(OES_rgb8_rgba8)) {
|
||||
formats.rbColor = LOCAL_GL_RGB565;
|
||||
aCF.red = 5;
|
||||
aCF.green = 6;
|
||||
aCF.blue = 5;
|
||||
} else {
|
||||
formats.rbColor = LOCAL_GL_RGB8;
|
||||
aCF.red = aCF.green = aCF.blue = 8;
|
||||
}
|
||||
aCF.alpha = 0;
|
||||
}
|
||||
formats.texColorType = LOCAL_GL_UNSIGNED_BYTE;
|
||||
|
||||
const bool alpha = mCreationFormat.alpha > 0;
|
||||
const int depth = mCreationFormat.depth;
|
||||
const int stencil = mCreationFormat.stencil;
|
||||
int samples = mCreationFormat.samples;
|
||||
|
||||
GLint maxSamples = 0;
|
||||
if (SupportsFramebufferMultisample() && !aDisableAA)
|
||||
fGetIntegerv(LOCAL_GL_MAX_SAMPLES, &maxSamples);
|
||||
GLsizei samples = aCF.samples;
|
||||
|
||||
GLsizei maxSamples = 0;
|
||||
if (SupportsFramebufferMultisample())
|
||||
fGetIntegerv(LOCAL_GL_MAX_SAMPLES, (GLint*)&maxSamples);
|
||||
samples = NS_MIN(samples, maxSamples);
|
||||
|
||||
const bool useDrawMSFBO = (samples > 0);
|
||||
formats.samples = samples;
|
||||
aCF.samples = samples;
|
||||
|
||||
if (!useDrawMSFBO && !aUseReadFBO) {
|
||||
// Early out, as no FBO resize work is necessary.
|
||||
|
||||
const int depth = aCF.depth;
|
||||
const int stencil = aCF.stencil;
|
||||
const bool useDepthStencil =
|
||||
!mIsGLES2 || IsExtensionSupported(OES_packed_depth_stencil);
|
||||
|
||||
formats.depthStencil = 0;
|
||||
formats.depth = 0;
|
||||
formats.stencil = 0;
|
||||
if (depth && stencil && useDepthStencil) {
|
||||
formats.depthStencil = LOCAL_GL_DEPTH24_STENCIL8;
|
||||
aCF.depth = 24;
|
||||
aCF.stencil = 8;
|
||||
} else {
|
||||
if (depth) {
|
||||
if (mIsGLES2) {
|
||||
if (IsExtensionSupported(OES_depth24)) {
|
||||
formats.depth = LOCAL_GL_DEPTH_COMPONENT24;
|
||||
aCF.depth = 24;
|
||||
} else {
|
||||
formats.depth = LOCAL_GL_DEPTH_COMPONENT16;
|
||||
aCF.depth = 16;
|
||||
}
|
||||
} else {
|
||||
formats.depth = LOCAL_GL_DEPTH_COMPONENT24;
|
||||
aCF.depth = 24;
|
||||
}
|
||||
}
|
||||
|
||||
if (stencil) {
|
||||
formats.stencil = LOCAL_GL_STENCIL_INDEX8;
|
||||
aCF.stencil = 8;
|
||||
}
|
||||
}
|
||||
|
||||
return formats;
|
||||
}
|
||||
|
||||
void
|
||||
GLContext::CreateTextureForOffscreen(const GLFormats& aFormats, const gfxIntSize& aSize, GLuint& texture)
|
||||
{
|
||||
GLuint boundTexture = 0;
|
||||
fGetIntegerv(LOCAL_GL_TEXTURE_BINDING_2D, (GLint*)&boundTexture);
|
||||
|
||||
texture = 0;
|
||||
fGenTextures(1, &texture);
|
||||
fBindTexture(LOCAL_GL_TEXTURE_2D, texture);
|
||||
fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MIN_FILTER, LOCAL_GL_LINEAR);
|
||||
fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MAG_FILTER, LOCAL_GL_LINEAR);
|
||||
fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_WRAP_S, LOCAL_GL_CLAMP_TO_EDGE);
|
||||
fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_WRAP_T, LOCAL_GL_CLAMP_TO_EDGE);
|
||||
|
||||
fTexImage2D(LOCAL_GL_TEXTURE_2D,
|
||||
0,
|
||||
aFormats.texColor,
|
||||
aSize.width, aSize.height,
|
||||
0,
|
||||
aFormats.texColor,
|
||||
aFormats.texColorType,
|
||||
nsnull);
|
||||
|
||||
fBindTexture(LOCAL_GL_TEXTURE_2D, boundTexture);
|
||||
}
|
||||
|
||||
static inline void
|
||||
RenderbufferStorageBySamples(GLContext* gl, GLsizei samples, GLenum internalFormat, const gfxIntSize& size)
|
||||
{
|
||||
if (samples) {
|
||||
gl->fRenderbufferStorageMultisample(LOCAL_GL_RENDERBUFFER,
|
||||
samples,
|
||||
internalFormat,
|
||||
size.width, size.height);
|
||||
} else {
|
||||
gl->fRenderbufferStorage(LOCAL_GL_RENDERBUFFER,
|
||||
internalFormat,
|
||||
size.width, size.height);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
GLContext::CreateRenderbuffersForOffscreen(const GLContext::GLFormats& aFormats, const gfxIntSize& aSize,
|
||||
GLuint& colorMSRB, GLuint& depthRB, GLuint& stencilRB)
|
||||
{
|
||||
GLuint boundRB = 0;
|
||||
fGetIntegerv(LOCAL_GL_RENDERBUFFER_BINDING, (GLint*)&boundRB);
|
||||
|
||||
|
||||
colorMSRB = 0;
|
||||
depthRB = 0;
|
||||
stencilRB = 0;
|
||||
|
||||
if (aFormats.samples > 0) {
|
||||
fGenRenderbuffers(1, &colorMSRB);
|
||||
fBindRenderbuffer(LOCAL_GL_RENDERBUFFER, colorMSRB);
|
||||
RenderbufferStorageBySamples(this, aFormats.samples, aFormats.rbColor, aSize);
|
||||
}
|
||||
|
||||
// If depthStencil, disallow depth, stencil
|
||||
MOZ_ASSERT(!aFormats.depthStencil || (!aFormats.depth && !aFormats.stencil));
|
||||
|
||||
if (aFormats.depthStencil) {
|
||||
fGenRenderbuffers(1, &depthRB);
|
||||
stencilRB = depthRB;
|
||||
fBindRenderbuffer(LOCAL_GL_RENDERBUFFER, depthRB);
|
||||
RenderbufferStorageBySamples(this, aFormats.samples, aFormats.depthStencil, aSize);
|
||||
}
|
||||
|
||||
if (aFormats.depth) {
|
||||
fGenRenderbuffers(1, &depthRB);
|
||||
fBindRenderbuffer(LOCAL_GL_RENDERBUFFER, depthRB);
|
||||
RenderbufferStorageBySamples(this, aFormats.samples, aFormats.depth, aSize);
|
||||
}
|
||||
|
||||
if (aFormats.stencil) {
|
||||
fGenRenderbuffers(1, &stencilRB);
|
||||
fBindRenderbuffer(LOCAL_GL_RENDERBUFFER, stencilRB);
|
||||
RenderbufferStorageBySamples(this, aFormats.samples, aFormats.stencil, aSize);
|
||||
}
|
||||
|
||||
|
||||
fBindRenderbuffer(LOCAL_GL_RENDERBUFFER, boundRB);
|
||||
}
|
||||
|
||||
bool
|
||||
GLContext::AssembleOffscreenFBOs(const GLuint colorMSRB,
|
||||
const GLuint depthRB,
|
||||
const GLuint stencilRB,
|
||||
const GLuint texture,
|
||||
GLuint& drawFBO,
|
||||
GLuint& readFBO)
|
||||
{
|
||||
drawFBO = 0;
|
||||
readFBO = 0;
|
||||
|
||||
if (!colorMSRB && !texture) {
|
||||
MOZ_ASSERT(!depthRB && !stencilRB);
|
||||
return true;
|
||||
}
|
||||
|
||||
GLuint curBoundFramebufferDraw = 0;
|
||||
GLuint curBoundFramebufferRead = 0;
|
||||
GLuint curBoundRenderbuffer = 0;
|
||||
GLuint curBoundTexture = 0;
|
||||
GLuint boundDrawFBO = GetUserBoundDrawFBO();
|
||||
GLuint boundReadFBO = GetUserBoundReadFBO();
|
||||
|
||||
GLint viewport[4];
|
||||
|
||||
const bool useDepthStencil =
|
||||
!mIsGLES2 || IsExtensionSupported(OES_packed_depth_stencil);
|
||||
|
||||
// save a few things for later restoring
|
||||
curBoundFramebufferDraw = GetUserBoundDrawFBO();
|
||||
curBoundFramebufferRead = GetUserBoundReadFBO();
|
||||
fGetIntegerv(LOCAL_GL_RENDERBUFFER_BINDING, (GLint*) &curBoundRenderbuffer);
|
||||
fGetIntegerv(LOCAL_GL_TEXTURE_BINDING_2D, (GLint*) &curBoundTexture);
|
||||
fGetIntegerv(LOCAL_GL_VIEWPORT, viewport);
|
||||
|
||||
// the context format of what we're defining
|
||||
// This becomes mActualFormat on success
|
||||
ContextFormat cf(mCreationFormat);
|
||||
|
||||
// Create everything we need for the resize, so if it fails, we haven't broken anything
|
||||
// If successful, these new resized objects will replace their associated member vars in GLContext
|
||||
GLuint newOffscreenDrawFBO = 0;
|
||||
GLuint newOffscreenReadFBO = 0;
|
||||
GLuint newOffscreenTexture = 0;
|
||||
GLuint newOffscreenColorRB = 0;
|
||||
GLuint newOffscreenDepthRB = 0;
|
||||
GLuint newOffscreenStencilRB = 0;
|
||||
|
||||
// Create the buffers and texture
|
||||
if (aUseReadFBO) {
|
||||
fGenFramebuffers(1, &newOffscreenReadFBO);
|
||||
fGenTextures(1, &newOffscreenTexture);
|
||||
}
|
||||
|
||||
if (useDrawMSFBO) {
|
||||
fGenFramebuffers(1, &newOffscreenDrawFBO);
|
||||
fGenRenderbuffers(1, &newOffscreenColorRB);
|
||||
} else {
|
||||
newOffscreenDrawFBO = newOffscreenReadFBO;
|
||||
}
|
||||
|
||||
if (depth && stencil && useDepthStencil) {
|
||||
fGenRenderbuffers(1, &newOffscreenDepthRB);
|
||||
} else {
|
||||
if (depth) {
|
||||
fGenRenderbuffers(1, &newOffscreenDepthRB);
|
||||
}
|
||||
|
||||
if (stencil) {
|
||||
fGenRenderbuffers(1, &newOffscreenStencilRB);
|
||||
}
|
||||
}
|
||||
|
||||
// Allocate texture
|
||||
if (aUseReadFBO) {
|
||||
fBindTexture(LOCAL_GL_TEXTURE_2D, newOffscreenTexture);
|
||||
fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MIN_FILTER, LOCAL_GL_LINEAR);
|
||||
fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MAG_FILTER, LOCAL_GL_LINEAR);
|
||||
fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_WRAP_S, LOCAL_GL_CLAMP_TO_EDGE);
|
||||
fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_WRAP_T, LOCAL_GL_CLAMP_TO_EDGE);
|
||||
|
||||
if (alpha) {
|
||||
fTexImage2D(LOCAL_GL_TEXTURE_2D,
|
||||
0,
|
||||
LOCAL_GL_RGBA,
|
||||
aSize.width, aSize.height,
|
||||
0,
|
||||
LOCAL_GL_RGBA,
|
||||
LOCAL_GL_UNSIGNED_BYTE,
|
||||
NULL);
|
||||
|
||||
cf.red = cf.green = cf.blue = cf.alpha = 8;
|
||||
} else {
|
||||
fTexImage2D(LOCAL_GL_TEXTURE_2D,
|
||||
0,
|
||||
LOCAL_GL_RGB,
|
||||
aSize.width, aSize.height,
|
||||
0,
|
||||
LOCAL_GL_RGB,
|
||||
#ifdef XP_WIN
|
||||
LOCAL_GL_UNSIGNED_BYTE,
|
||||
#else
|
||||
mIsGLES2 ? LOCAL_GL_UNSIGNED_SHORT_5_6_5
|
||||
: LOCAL_GL_UNSIGNED_BYTE,
|
||||
#endif
|
||||
NULL);
|
||||
|
||||
#ifdef XP_WIN
|
||||
cf.red = cf.green = cf.blue = 8;
|
||||
#else
|
||||
cf.red = 5;
|
||||
cf.green = 6;
|
||||
cf.blue = 5;
|
||||
#endif
|
||||
cf.alpha = 0;
|
||||
}
|
||||
}
|
||||
cf.samples = samples;
|
||||
|
||||
// Allocate color buffer
|
||||
if (useDrawMSFBO) {
|
||||
GLenum colorFormat;
|
||||
if (!mIsGLES2 || IsExtensionSupported(OES_rgb8_rgba8))
|
||||
colorFormat = alpha ? LOCAL_GL_RGBA8 : LOCAL_GL_RGB8;
|
||||
else
|
||||
colorFormat = alpha ? LOCAL_GL_RGBA4 : LOCAL_GL_RGB565;
|
||||
|
||||
fBindRenderbuffer(LOCAL_GL_RENDERBUFFER, newOffscreenColorRB);
|
||||
fRenderbufferStorageMultisample(LOCAL_GL_RENDERBUFFER,
|
||||
samples,
|
||||
colorFormat,
|
||||
aSize.width, aSize.height);
|
||||
}
|
||||
|
||||
// Allocate depth and stencil buffers
|
||||
if (depth && stencil && useDepthStencil) {
|
||||
fBindRenderbuffer(LOCAL_GL_RENDERBUFFER, newOffscreenDepthRB);
|
||||
if (useDrawMSFBO) {
|
||||
fRenderbufferStorageMultisample(LOCAL_GL_RENDERBUFFER,
|
||||
samples,
|
||||
LOCAL_GL_DEPTH24_STENCIL8,
|
||||
aSize.width, aSize.height);
|
||||
} else {
|
||||
fRenderbufferStorage(LOCAL_GL_RENDERBUFFER,
|
||||
LOCAL_GL_DEPTH24_STENCIL8,
|
||||
aSize.width, aSize.height);
|
||||
}
|
||||
cf.depth = 24;
|
||||
cf.stencil = 8;
|
||||
} else {
|
||||
if (depth) {
|
||||
GLenum depthType;
|
||||
if (mIsGLES2) {
|
||||
if (IsExtensionSupported(OES_depth32)) {
|
||||
depthType = LOCAL_GL_DEPTH_COMPONENT32;
|
||||
cf.depth = 32;
|
||||
} else if (IsExtensionSupported(OES_depth24)) {
|
||||
depthType = LOCAL_GL_DEPTH_COMPONENT24;
|
||||
cf.depth = 24;
|
||||
} else {
|
||||
depthType = LOCAL_GL_DEPTH_COMPONENT16;
|
||||
cf.depth = 16;
|
||||
}
|
||||
} else {
|
||||
depthType = LOCAL_GL_DEPTH_COMPONENT24;
|
||||
cf.depth = 24;
|
||||
}
|
||||
|
||||
fBindRenderbuffer(LOCAL_GL_RENDERBUFFER, newOffscreenDepthRB);
|
||||
if (useDrawMSFBO) {
|
||||
fRenderbufferStorageMultisample(LOCAL_GL_RENDERBUFFER,
|
||||
samples,
|
||||
depthType,
|
||||
aSize.width, aSize.height);
|
||||
} else {
|
||||
fRenderbufferStorage(LOCAL_GL_RENDERBUFFER,
|
||||
depthType,
|
||||
aSize.width, aSize.height);
|
||||
}
|
||||
}
|
||||
|
||||
if (stencil) {
|
||||
fBindRenderbuffer(LOCAL_GL_RENDERBUFFER, newOffscreenStencilRB);
|
||||
if (useDrawMSFBO) {
|
||||
fRenderbufferStorageMultisample(LOCAL_GL_RENDERBUFFER,
|
||||
samples,
|
||||
LOCAL_GL_STENCIL_INDEX8,
|
||||
aSize.width, aSize.height);
|
||||
} else {
|
||||
fRenderbufferStorage(LOCAL_GL_RENDERBUFFER,
|
||||
LOCAL_GL_STENCIL_INDEX8,
|
||||
aSize.width, aSize.height);
|
||||
}
|
||||
cf.stencil = 8;
|
||||
}
|
||||
}
|
||||
|
||||
// Now assemble the FBO
|
||||
BindInternalFBO(newOffscreenDrawFBO); // If we're not using a separate draw FBO, this will be the read FBO
|
||||
if (useDrawMSFBO) {
|
||||
fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER,
|
||||
LOCAL_GL_COLOR_ATTACHMENT0,
|
||||
LOCAL_GL_RENDERBUFFER,
|
||||
newOffscreenColorRB);
|
||||
}
|
||||
|
||||
if (depth && stencil && useDepthStencil) {
|
||||
fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER,
|
||||
LOCAL_GL_DEPTH_ATTACHMENT,
|
||||
LOCAL_GL_RENDERBUFFER,
|
||||
newOffscreenDepthRB);
|
||||
fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER,
|
||||
LOCAL_GL_STENCIL_ATTACHMENT,
|
||||
LOCAL_GL_RENDERBUFFER,
|
||||
newOffscreenDepthRB);
|
||||
} else {
|
||||
if (depth) {
|
||||
fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER,
|
||||
LOCAL_GL_DEPTH_ATTACHMENT,
|
||||
LOCAL_GL_RENDERBUFFER,
|
||||
newOffscreenDepthRB);
|
||||
}
|
||||
|
||||
if (stencil) {
|
||||
fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER,
|
||||
LOCAL_GL_STENCIL_ATTACHMENT,
|
||||
LOCAL_GL_RENDERBUFFER,
|
||||
newOffscreenStencilRB);
|
||||
}
|
||||
}
|
||||
|
||||
if (aUseReadFBO) {
|
||||
BindInternalFBO(newOffscreenReadFBO);
|
||||
if (texture) {
|
||||
fGenFramebuffers(1, &readFBO);
|
||||
BindInternalFBO(readFBO);
|
||||
fFramebufferTexture2D(LOCAL_GL_FRAMEBUFFER,
|
||||
LOCAL_GL_COLOR_ATTACHMENT0,
|
||||
LOCAL_GL_TEXTURE_2D,
|
||||
newOffscreenTexture,
|
||||
texture,
|
||||
0);
|
||||
}
|
||||
|
||||
if (colorMSRB) {
|
||||
fGenFramebuffers(1, &drawFBO);
|
||||
BindInternalFBO(drawFBO);
|
||||
fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER,
|
||||
LOCAL_GL_COLOR_ATTACHMENT0,
|
||||
LOCAL_GL_RENDERBUFFER,
|
||||
colorMSRB);
|
||||
} else {
|
||||
drawFBO = readFBO;
|
||||
// drawFBO==readFBO is already bound from the 'if (texture)' block.
|
||||
}
|
||||
|
||||
if (depthRB) {
|
||||
fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER,
|
||||
LOCAL_GL_DEPTH_ATTACHMENT,
|
||||
LOCAL_GL_RENDERBUFFER,
|
||||
depthRB);
|
||||
}
|
||||
|
||||
if (stencilRB) {
|
||||
fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER,
|
||||
LOCAL_GL_STENCIL_ATTACHMENT,
|
||||
LOCAL_GL_RENDERBUFFER,
|
||||
stencilRB);
|
||||
}
|
||||
|
||||
// We should be all resized. Check for framebuffer completeness.
|
||||
GLenum status;
|
||||
bool framebuffersComplete = true;
|
||||
bool isComplete = true;
|
||||
|
||||
BindInternalFBO(newOffscreenDrawFBO);
|
||||
BindInternalFBO(drawFBO);
|
||||
status = fCheckFramebufferStatus(LOCAL_GL_FRAMEBUFFER);
|
||||
if (status != LOCAL_GL_FRAMEBUFFER_COMPLETE) {
|
||||
NS_WARNING("DrawFBO: Incomplete");
|
||||
#ifdef DEBUG
|
||||
#ifdef DEBUG
|
||||
printf_stderr("Framebuffer status: %X\n", status);
|
||||
#endif
|
||||
framebuffersComplete = false;
|
||||
#endif
|
||||
isComplete = false;
|
||||
}
|
||||
|
||||
BindInternalFBO(newOffscreenReadFBO);
|
||||
BindInternalFBO(readFBO);
|
||||
status = fCheckFramebufferStatus(LOCAL_GL_FRAMEBUFFER);
|
||||
if (status != LOCAL_GL_FRAMEBUFFER_COMPLETE) {
|
||||
NS_WARNING("ReadFBO: Incomplete");
|
||||
#ifdef DEBUG
|
||||
#ifdef DEBUG
|
||||
printf_stderr("Framebuffer status: %X\n", status);
|
||||
#endif
|
||||
framebuffersComplete = false;
|
||||
#endif
|
||||
isComplete = false;
|
||||
}
|
||||
|
||||
if (!framebuffersComplete) {
|
||||
NS_WARNING("Error resizing offscreen framebuffer -- framebuffer(s) not complete");
|
||||
BindUserDrawFBO(boundDrawFBO);
|
||||
BindUserReadFBO(boundReadFBO);
|
||||
|
||||
// Clean up the mess
|
||||
fDeleteFramebuffers(1, &newOffscreenDrawFBO);
|
||||
fDeleteFramebuffers(1, &newOffscreenReadFBO);
|
||||
fDeleteTextures(1, &newOffscreenTexture);
|
||||
fDeleteRenderbuffers(1, &newOffscreenColorRB);
|
||||
fDeleteRenderbuffers(1, &newOffscreenDepthRB);
|
||||
fDeleteRenderbuffers(1, &newOffscreenStencilRB);
|
||||
return isComplete;
|
||||
}
|
||||
|
||||
BindUserDrawFBO(curBoundFramebufferDraw);
|
||||
BindUserReadFBO(curBoundFramebufferRead);
|
||||
fBindTexture(LOCAL_GL_TEXTURE_2D, curBoundTexture);
|
||||
fBindRenderbuffer(LOCAL_GL_RENDERBUFFER, curBoundRenderbuffer);
|
||||
fViewport(viewport[0], viewport[1], viewport[2], viewport[3]);
|
||||
bool
|
||||
GLContext::ResizeOffscreenFBOs(const ContextFormat& aCF, const gfxIntSize& aSize, const bool aNeedsReadBuffer)
|
||||
{
|
||||
// Early out for when we're rendering directly to the context's 'screen'.
|
||||
if (!aNeedsReadBuffer && !aCF.samples)
|
||||
return true;
|
||||
|
||||
MakeCurrent();
|
||||
ContextFormat cf(aCF);
|
||||
GLFormats formats = ChooseGLFormats(cf);
|
||||
|
||||
GLuint texture = 0;
|
||||
if (aNeedsReadBuffer)
|
||||
CreateTextureForOffscreen(formats, aSize, texture);
|
||||
|
||||
GLuint colorMSRB = 0;
|
||||
GLuint depthRB = 0;
|
||||
GLuint stencilRB = 0;
|
||||
CreateRenderbuffersForOffscreen(formats, aSize, colorMSRB, depthRB, stencilRB);
|
||||
|
||||
GLuint drawFBO = 0;
|
||||
GLuint readFBO = 0;
|
||||
if (!AssembleOffscreenFBOs(colorMSRB, depthRB, stencilRB, texture,
|
||||
drawFBO, readFBO))
|
||||
{
|
||||
fDeleteFramebuffers(1, &drawFBO);
|
||||
fDeleteFramebuffers(1, &readFBO);
|
||||
fDeleteRenderbuffers(1, &colorMSRB);
|
||||
fDeleteRenderbuffers(1, &depthRB);
|
||||
fDeleteRenderbuffers(1, &stencilRB);
|
||||
fDeleteTextures(1, &texture);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Success, so delete the old and busted
|
||||
fDeleteFramebuffers(1, &mOffscreenDrawFBO);
|
||||
fDeleteFramebuffers(1, &mOffscreenReadFBO);
|
||||
fDeleteTextures(1, &mOffscreenTexture);
|
||||
fDeleteRenderbuffers(1, &mOffscreenColorRB);
|
||||
fDeleteRenderbuffers(1, &mOffscreenDepthRB);
|
||||
fDeleteRenderbuffers(1, &mOffscreenStencilRB);
|
||||
|
||||
// Update currently bound references if we're changing what they were point to
|
||||
// This way we don't rebind to old buffers when we're done here
|
||||
if (curBoundFramebufferDraw == mOffscreenDrawFBO)
|
||||
curBoundFramebufferDraw = newOffscreenDrawFBO;
|
||||
if (curBoundFramebufferRead == mOffscreenReadFBO)
|
||||
curBoundFramebufferRead = newOffscreenReadFBO;
|
||||
if (curBoundTexture == mOffscreenTexture)
|
||||
curBoundTexture = newOffscreenTexture;
|
||||
if (curBoundRenderbuffer == mOffscreenColorRB)
|
||||
curBoundRenderbuffer = newOffscreenColorRB;
|
||||
else if (curBoundRenderbuffer == mOffscreenDepthRB)
|
||||
curBoundRenderbuffer = newOffscreenDepthRB;
|
||||
else if (curBoundRenderbuffer == mOffscreenStencilRB)
|
||||
curBoundRenderbuffer = newOffscreenStencilRB;
|
||||
// Success, so switch everything out.
|
||||
// Store current user FBO bindings.
|
||||
GLuint boundDrawFBO = GetUserBoundDrawFBO();
|
||||
GLuint boundReadFBO = GetUserBoundReadFBO();
|
||||
|
||||
// Replace with the new hotness
|
||||
mOffscreenDrawFBO = newOffscreenDrawFBO;
|
||||
mOffscreenReadFBO = newOffscreenReadFBO;
|
||||
mOffscreenTexture = newOffscreenTexture;
|
||||
mOffscreenColorRB = newOffscreenColorRB;
|
||||
mOffscreenDepthRB = newOffscreenDepthRB;
|
||||
mOffscreenStencilRB = newOffscreenStencilRB;
|
||||
std::swap(mOffscreenDrawFBO, drawFBO);
|
||||
std::swap(mOffscreenReadFBO, readFBO);
|
||||
std::swap(mOffscreenColorRB, colorMSRB);
|
||||
std::swap(mOffscreenDepthRB, depthRB);
|
||||
std::swap(mOffscreenStencilRB, stencilRB);
|
||||
std::swap(mOffscreenTexture, texture);
|
||||
|
||||
// Delete the old and busted
|
||||
fDeleteFramebuffers(1, &drawFBO);
|
||||
fDeleteFramebuffers(1, &readFBO);
|
||||
fDeleteRenderbuffers(1, &colorMSRB);
|
||||
fDeleteRenderbuffers(1, &depthRB);
|
||||
fDeleteRenderbuffers(1, &stencilRB);
|
||||
fDeleteTextures(1, &texture);
|
||||
|
||||
// Rebind user FBOs, in case anything changed internally.
|
||||
BindUserDrawFBO(boundDrawFBO);
|
||||
BindUserReadFBO(boundReadFBO);
|
||||
|
||||
// Newly-created buffers are...unlikely to match.
|
||||
ForceDirtyFBOs();
|
||||
|
||||
// Finish up.
|
||||
mOffscreenSize = aSize;
|
||||
mOffscreenActualSize = aSize;
|
||||
|
||||
mActualFormat = cf;
|
||||
|
||||
#ifdef DEBUG
|
||||
if (DebugMode()) {
|
||||
printf_stderr("Resized %dx%d offscreen FBO: r: %d g: %d b: %d a: %d depth: %d stencil: %d samples: %d\n",
|
||||
mOffscreenActualSize.width, mOffscreenActualSize.height,
|
||||
mActualFormat.red, mActualFormat.green, mActualFormat.blue, mActualFormat.alpha,
|
||||
mActualFormat.depth, mActualFormat.stencil, mActualFormat.samples);
|
||||
}
|
||||
#endif
|
||||
|
||||
// We're good, and the framebuffer is already attached.
|
||||
// Now restore the GL state back to what it was before the resize took place.
|
||||
// If the user was using fb 0, this will bind the offscreen framebuffer we
|
||||
// just created.
|
||||
BindUserDrawFBO(curBoundFramebufferDraw);
|
||||
BindUserReadFBO(curBoundFramebufferRead);
|
||||
fBindTexture(LOCAL_GL_TEXTURE_2D, curBoundTexture);
|
||||
fBindRenderbuffer(LOCAL_GL_RENDERBUFFER, curBoundRenderbuffer);
|
||||
fViewport(viewport[0], viewport[1], viewport[2], viewport[3]);
|
||||
|
||||
// Make sure we know that the buffers are new and thus dirty:
|
||||
ForceDirtyFBOs();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
GLContext::DeleteOffscreenFBO()
|
||||
GLContext::DeleteOffscreenFBOs()
|
||||
{
|
||||
fDeleteFramebuffers(1, &mOffscreenDrawFBO);
|
||||
fDeleteFramebuffers(1, &mOffscreenReadFBO);
|
||||
|
@ -1770,7 +1744,7 @@ GLContext::MarkDestroyed()
|
|||
return;
|
||||
|
||||
MakeCurrent();
|
||||
DeleteOffscreenFBO();
|
||||
DeleteOffscreenFBOs();
|
||||
|
||||
fDeleteProgram(mBlitProgram);
|
||||
mBlitProgram = 0;
|
||||
|
|
|
@ -831,7 +831,7 @@ public:
|
|||
*/
|
||||
virtual bool ResizeOffscreen(const gfxIntSize& aNewSize) {
|
||||
if (mOffscreenDrawFBO || mOffscreenReadFBO)
|
||||
return ResizeOffscreenFBO(aNewSize, mOffscreenReadFBO != 0);
|
||||
return ResizeOffscreenFBOs(aNewSize, mOffscreenReadFBO != 0);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1631,30 +1631,62 @@ protected:
|
|||
// Helper to create/resize an offscreen FBO,
|
||||
// for offscreen implementations that use FBOs.
|
||||
// Note that it does -not- clear the resized buffers.
|
||||
bool ResizeOffscreenFBO(const gfxIntSize& aSize, const bool aUseReadFBO, const bool aDisableAA);
|
||||
bool ResizeOffscreenFBO(const gfxIntSize& aSize, const bool aUseReadFBO) {
|
||||
if (ResizeOffscreenFBO(aSize, aUseReadFBO, false))
|
||||
return true;
|
||||
|
||||
if (!mCreationFormat.samples) {
|
||||
NS_WARNING("ResizeOffscreenFBO failed to resize non-AA context!");
|
||||
bool ResizeOffscreenFBOs(const ContextFormat& aCF, const gfxIntSize& aSize, const bool aNeedsReadBuffer);
|
||||
bool ResizeOffscreenFBOs(const gfxIntSize& aSize, const bool aNeedsReadBuffer) {
|
||||
if (!IsOffscreenSizeAllowed(aSize))
|
||||
return false;
|
||||
} else {
|
||||
NS_WARNING("ResizeOffscreenFBO failed to resize AA context! Falling back to no AA...");
|
||||
|
||||
ContextFormat format(mCreationFormat);
|
||||
|
||||
if (format.samples) {
|
||||
// AA path
|
||||
if (ResizeOffscreenFBOs(format, aSize, aNeedsReadBuffer))
|
||||
return true;
|
||||
|
||||
NS_WARNING("ResizeOffscreenFBOs failed to resize an AA context! Falling back to no AA...");
|
||||
format.samples = 0;
|
||||
}
|
||||
|
||||
if (DebugMode()) {
|
||||
printf_stderr("Requested level of multisampling is unavailable, continuing without multisampling\n");
|
||||
}
|
||||
|
||||
if (ResizeOffscreenFBO(aSize, aUseReadFBO, true))
|
||||
if (ResizeOffscreenFBOs(format, aSize, aNeedsReadBuffer))
|
||||
return true;
|
||||
|
||||
NS_WARNING("ResizeOffscreenFBO failed to resize AA context even without AA!");
|
||||
NS_WARNING("ResizeOffscreenFBOs failed to resize non-AA context!");
|
||||
return false;
|
||||
}
|
||||
|
||||
void DeleteOffscreenFBO();
|
||||
struct GLFormats {
|
||||
GLFormats()
|
||||
: texColor(0)
|
||||
, texColorType(0)
|
||||
, rbColor(0)
|
||||
, depthStencil(0)
|
||||
, depth(0)
|
||||
, stencil(0)
|
||||
, samples(0)
|
||||
{}
|
||||
|
||||
GLenum texColor;
|
||||
GLenum texColorType;
|
||||
GLenum rbColor;
|
||||
GLenum depthStencil;
|
||||
GLenum depth;
|
||||
GLenum stencil;
|
||||
GLsizei samples;
|
||||
};
|
||||
|
||||
GLFormats ChooseGLFormats(ContextFormat& aCF);
|
||||
void CreateTextureForOffscreen(const GLFormats& aFormats, const gfxIntSize& aSize,
|
||||
GLuint& texture);
|
||||
void CreateRenderbuffersForOffscreen(const GLContext::GLFormats& aFormats, const gfxIntSize& aSize,
|
||||
GLuint& colorMSRB, GLuint& depthRB, GLuint& stencilRB);
|
||||
bool AssembleOffscreenFBOs(const GLuint colorMSRB,
|
||||
const GLuint depthRB,
|
||||
const GLuint stencilRB,
|
||||
const GLuint texture,
|
||||
GLuint& drawFBO,
|
||||
GLuint& readFBO);
|
||||
|
||||
void DeleteOffscreenFBOs();
|
||||
|
||||
GLuint mOffscreenDrawFBO;
|
||||
GLuint mOffscreenReadFBO;
|
||||
|
|
|
@ -289,7 +289,7 @@ GLContextCGL::ResizeOffscreen(const gfxIntSize& aNewSize)
|
|||
return false;
|
||||
}
|
||||
|
||||
if (!ResizeOffscreenFBO(aNewSize, false)) {
|
||||
if (!ResizeOffscreenFBOs(aNewSize, false)) {
|
||||
[pb release];
|
||||
return false;
|
||||
}
|
||||
|
@ -309,7 +309,7 @@ GLContextCGL::ResizeOffscreen(const gfxIntSize& aNewSize)
|
|||
return true;
|
||||
}
|
||||
|
||||
return ResizeOffscreenFBO(aNewSize, true);
|
||||
return ResizeOffscreenFBOs(aNewSize, true);
|
||||
}
|
||||
|
||||
class TextureImageCGL : public BasicTextureImage
|
||||
|
@ -601,7 +601,7 @@ GLContextProviderCGL::CreateOffscreen(const gfxIntSize& aSize,
|
|||
glContext = CreateOffscreenPBufferContext(aSize, actualFormat);
|
||||
if (glContext &&
|
||||
glContext->Init() &&
|
||||
glContext->ResizeOffscreenFBO(aSize, false))
|
||||
glContext->ResizeOffscreenFBOs(aSize, false))
|
||||
{
|
||||
glContext->mOffscreenSize = aSize;
|
||||
glContext->mOffscreenActualSize = aSize;
|
||||
|
@ -614,7 +614,7 @@ GLContextProviderCGL::CreateOffscreen(const gfxIntSize& aSize,
|
|||
glContext = CreateOffscreenFBOContext(actualFormat);
|
||||
if (glContext &&
|
||||
glContext->Init() &&
|
||||
glContext->ResizeOffscreenFBO(aSize, true))
|
||||
glContext->ResizeOffscreenFBOs(aSize, true))
|
||||
{
|
||||
return glContext.forget();
|
||||
}
|
||||
|
|
|
@ -724,7 +724,7 @@ GLContextEGL::ResizeOffscreen(const gfxIntSize& aNewSize)
|
|||
return false;
|
||||
}
|
||||
|
||||
if (!ResizeOffscreenFBO(pbsize, false))
|
||||
if (!ResizeOffscreenFBOs(pbsize, false))
|
||||
return false;
|
||||
|
||||
SetOffscreenSize(aNewSize, pbsize);
|
||||
|
@ -771,7 +771,7 @@ GLContextEGL::ResizeOffscreen(const gfxIntSize& aNewSize)
|
|||
if (!config) {
|
||||
return false;
|
||||
}
|
||||
if (!ResizeOffscreenFBO(aNewSize, true))
|
||||
if (!ResizeOffscreenFBOs(aNewSize, true))
|
||||
return false;
|
||||
|
||||
mThebesSurface = xsurface;
|
||||
|
@ -782,12 +782,12 @@ GLContextEGL::ResizeOffscreen(const gfxIntSize& aNewSize)
|
|||
|
||||
#if defined(MOZ_X11) && defined(MOZ_EGL_XRENDER_COMPOSITE)
|
||||
if (ResizeOffscreenPixmapSurface(aNewSize)) {
|
||||
if (ResizeOffscreenFBO(aNewSize, true))
|
||||
if (ResizeOffscreenFBOs(aNewSize, true))
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
return ResizeOffscreenFBO(aNewSize, true);
|
||||
return ResizeOffscreenFBOs(aNewSize, true);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1964,7 +1964,7 @@ GLContextProviderEGL::CreateOffscreen(const gfxIntSize& aSize,
|
|||
return nsnull;
|
||||
|
||||
gfxIntSize fboSize = usePBuffers ? glContext->OffscreenActualSize() : aSize;
|
||||
if (!(aFlags & GLContext::ContextFlagsGlobal) && !glContext->ResizeOffscreenFBO(fboSize, !usePBuffers))
|
||||
if (!(aFlags & GLContext::ContextFlagsGlobal) && !glContext->ResizeOffscreenFBOs(fboSize, !usePBuffers))
|
||||
return nsnull;
|
||||
|
||||
return glContext.forget();
|
||||
|
@ -1975,7 +1975,7 @@ GLContextProviderEGL::CreateOffscreen(const gfxIntSize& aSize,
|
|||
if (!glContext)
|
||||
return nsnull;
|
||||
|
||||
if (!(aFlags & GLContext::ContextFlagsGlobal) && !glContext->ResizeOffscreenFBO(glContext->OffscreenActualSize(), true))
|
||||
if (!(aFlags & GLContext::ContextFlagsGlobal) && !glContext->ResizeOffscreenFBOs(glContext->OffscreenActualSize(), true))
|
||||
return nsnull;
|
||||
|
||||
return glContext.forget();
|
||||
|
@ -1987,7 +1987,7 @@ GLContextProviderEGL::CreateOffscreen(const gfxIntSize& aSize,
|
|||
return nsnull;
|
||||
}
|
||||
|
||||
if (!(aFlags & GLContext::ContextFlagsGlobal) && !gUseBackingSurface && !glContext->ResizeOffscreenFBO(glContext->OffscreenActualSize(), true)) {
|
||||
if (!(aFlags & GLContext::ContextFlagsGlobal) && !gUseBackingSurface && !glContext->ResizeOffscreenFBOs(glContext->OffscreenActualSize(), true)) {
|
||||
// we weren't able to create the initial
|
||||
// offscreen FBO, so this is dead
|
||||
return nsnull;
|
||||
|
|
|
@ -1307,7 +1307,7 @@ GLContextProviderGLX::CreateOffscreen(const gfxIntSize& aSize,
|
|||
return nsnull;
|
||||
}
|
||||
|
||||
if (!glContext->ResizeOffscreenFBO(aSize, true)) {
|
||||
if (!glContext->ResizeOffscreenFBOs(aSize, true)) {
|
||||
// we weren't able to create the initial
|
||||
// offscreen FBO, so this is dead
|
||||
return nsnull;
|
||||
|
|
|
@ -524,10 +524,10 @@ GLContextWGL::ResizeOffscreen(const gfxIntSize& aNewSize)
|
|||
MakeCurrent();
|
||||
ClearSafely();
|
||||
|
||||
return ResizeOffscreenFBO(aNewSize, false);
|
||||
return ResizeOffscreenFBOs(aNewSize, false);
|
||||
}
|
||||
|
||||
return ResizeOffscreenFBO(aNewSize, true);
|
||||
return ResizeOffscreenFBOs(aNewSize, true);
|
||||
}
|
||||
|
||||
static GLContextWGL *
|
||||
|
@ -782,7 +782,7 @@ GLContextProviderWGL::CreateOffscreen(const gfxIntSize& aSize,
|
|||
return nsnull;
|
||||
}
|
||||
|
||||
if (!glContext->ResizeOffscreenFBO(aSize, !glContext->mPBuffer))
|
||||
if (!glContext->ResizeOffscreenFBOs(aSize, !glContext->mPBuffer))
|
||||
return nsnull;
|
||||
|
||||
glContext->mOffscreenSize = aSize;
|
||||
|
|
|
@ -110,6 +110,7 @@ public:
|
|||
, mViewportScrollOffset(0, 0)
|
||||
, mScrollId(NULL_SCROLL_ID)
|
||||
, mCSSContentSize(0, 0)
|
||||
, mResolution(1, 1)
|
||||
{}
|
||||
|
||||
// Default copy ctor and operator= are fine
|
||||
|
@ -151,6 +152,10 @@ public:
|
|||
// Consumers often want to know the size before scaling to pixels
|
||||
// so we record this size as well.
|
||||
gfx::Size mCSSContentSize;
|
||||
|
||||
// This represents the resolution at which the associated layer
|
||||
// will been rendered.
|
||||
gfxSize mResolution;
|
||||
};
|
||||
|
||||
#define MOZ_LAYER_DECL_NAME(n, e) \
|
||||
|
|
|
@ -86,6 +86,7 @@ CPPSRCS = \
|
|||
LayerManagerOGL.cpp \
|
||||
ThebesLayerOGL.cpp \
|
||||
TiledThebesLayerOGL.cpp \
|
||||
ReusableTileStoreOGL.cpp \
|
||||
LayerSorter.cpp \
|
||||
ImageLayers.cpp \
|
||||
$(NULL)
|
||||
|
|
|
@ -87,8 +87,20 @@ public:
|
|||
// (x*GetTileLength(), y*GetTileLength(), GetTileLength(), GetTileLength())
|
||||
Tile GetTile(int x, int y) const;
|
||||
|
||||
// This operates the same as GetTile(aTileOrigin), but will also replace the
|
||||
// specified tile with the placeholder tile. This does not call ReleaseTile
|
||||
// on the removed tile.
|
||||
bool RemoveTile(const nsIntPoint& aTileOrigin, Tile& aRemovedTile);
|
||||
|
||||
// This operates the same as GetTile(x, y), but will also replace the
|
||||
// specified tile with the placeholder tile. This does not call ReleaseTile
|
||||
// on the removed tile.
|
||||
bool RemoveTile(int x, int y, Tile& aRemovedTile);
|
||||
|
||||
uint16_t GetTileLength() const { return TILEDLAYERBUFFER_TILE_SIZE; }
|
||||
|
||||
unsigned int GetTileCount() const { return mRetainedTiles.Length(); }
|
||||
|
||||
const nsIntRegion& GetValidRegion() const { return mValidRegion; }
|
||||
const nsIntRegion& GetLastPaintRegion() const { return mLastPaintRegion; }
|
||||
void SetLastPaintRegion(const nsIntRegion& aLastPaintRegion) {
|
||||
|
@ -161,6 +173,30 @@ TiledLayerBuffer<Derived, Tile>::GetTile(int x, int y) const
|
|||
return mRetainedTiles.SafeElementAt(index, AsDerived().GetPlaceholderTile());
|
||||
}
|
||||
|
||||
template<typename Derived, typename Tile> bool
|
||||
TiledLayerBuffer<Derived, Tile>::RemoveTile(const nsIntPoint& aTileOrigin,
|
||||
Tile& aRemovedTile)
|
||||
{
|
||||
int firstTileX = mValidRegion.GetBounds().x / GetTileLength();
|
||||
int firstTileY = mValidRegion.GetBounds().y / GetTileLength();
|
||||
return RemoveTile(aTileOrigin.x / GetTileLength() - firstTileX,
|
||||
aTileOrigin.y / GetTileLength() - firstTileY,
|
||||
aRemovedTile);
|
||||
}
|
||||
|
||||
template<typename Derived, typename Tile> bool
|
||||
TiledLayerBuffer<Derived, Tile>::RemoveTile(int x, int y, Tile& aRemovedTile)
|
||||
{
|
||||
int index = x * mRetainedHeight + y;
|
||||
const Tile& tileToRemove = mRetainedTiles.SafeElementAt(index, AsDerived().GetPlaceholderTile());
|
||||
if (!IsPlaceholder(tileToRemove)) {
|
||||
aRemovedTile = tileToRemove;
|
||||
mRetainedTiles[index] = AsDerived().GetPlaceholderTile();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
template<typename Derived, typename Tile> void
|
||||
TiledLayerBuffer<Derived, Tile>::Update(const nsIntRegion& aNewValidRegion,
|
||||
const nsIntRegion& aPaintRegion)
|
||||
|
@ -209,14 +245,16 @@ TiledLayerBuffer<Derived, Tile>::Update(const nsIntRegion& aNewValidRegion,
|
|||
int tileY = (y - oldBufferOrigin.y) / GetTileLength();
|
||||
int index = tileX * oldRetainedHeight + tileY;
|
||||
|
||||
NS_ABORT_IF_FALSE(!IsPlaceholder(oldRetainedTiles.
|
||||
SafeElementAt(index, AsDerived().GetPlaceholderTile())),
|
||||
"Expected tile");
|
||||
// The tile may have been removed, skip over it in this case.
|
||||
if (IsPlaceholder(oldRetainedTiles.
|
||||
SafeElementAt(index, AsDerived().GetPlaceholderTile()))) {
|
||||
newRetainedTiles.AppendElement(AsDerived().GetPlaceholderTile());
|
||||
} else {
|
||||
Tile tileWithPartialValidContent = oldRetainedTiles[index];
|
||||
newRetainedTiles.AppendElement(tileWithPartialValidContent);
|
||||
oldRetainedTiles[index] = AsDerived().GetPlaceholderTile();
|
||||
}
|
||||
|
||||
Tile tileWithPartialValidContent = oldRetainedTiles[index];
|
||||
newRetainedTiles.AppendElement(tileWithPartialValidContent);
|
||||
|
||||
oldRetainedTiles[index] = AsDerived().GetPlaceholderTile();
|
||||
} else {
|
||||
// This tile is either:
|
||||
// 1) Outside the new valid region and will simply be an empty
|
||||
|
|
|
@ -353,6 +353,8 @@ ThebesLayerD3D10::VerifyContentType(SurfaceMode aMode)
|
|||
NS_WARNING("Failed to create drawtarget for ThebesLayerD3D10.");
|
||||
return;
|
||||
}
|
||||
|
||||
mValidRegion.SetEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -73,6 +73,7 @@ struct ParamTraits<mozilla::layers::FrameMetrics>
|
|||
WriteParam(aMsg, aParam.mViewportScrollOffset);
|
||||
WriteParam(aMsg, aParam.mDisplayPort);
|
||||
WriteParam(aMsg, aParam.mScrollId);
|
||||
WriteParam(aMsg, aParam.mResolution);
|
||||
}
|
||||
|
||||
static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
|
||||
|
@ -82,7 +83,8 @@ struct ParamTraits<mozilla::layers::FrameMetrics>
|
|||
ReadParam(aMsg, aIter, &aResult->mContentSize) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mViewportScrollOffset) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mDisplayPort) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mScrollId));
|
||||
ReadParam(aMsg, aIter, &aResult->mScrollId) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mResolution));
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -0,0 +1,188 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "ReusableTileStoreOGL.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
ReusableTileStoreOGL::~ReusableTileStoreOGL()
|
||||
{
|
||||
if (mTiles.Length() == 0)
|
||||
return;
|
||||
|
||||
mContext->MakeCurrent();
|
||||
for (int i = 0; i < mTiles.Length(); i++)
|
||||
mContext->fDeleteTextures(1, &mTiles[i]->mTexture.mTextureHandle);
|
||||
mTiles.Clear();
|
||||
}
|
||||
|
||||
void
|
||||
ReusableTileStoreOGL::HarvestTiles(TiledLayerBufferOGL* aVideoMemoryTiledBuffer,
|
||||
const nsIntRegion& aOldValidRegion,
|
||||
const nsIntRegion& aNewValidRegion,
|
||||
const gfxSize& aOldResolution,
|
||||
const gfxSize& aNewResolution)
|
||||
{
|
||||
gfxSize scaleFactor = gfxSize(aNewResolution.width / aOldResolution.width,
|
||||
aNewResolution.height / aOldResolution.height);
|
||||
|
||||
#ifdef GFX_TILEDLAYER_PREF_WARNINGS
|
||||
printf_stderr("Seeing if there are any tiles we can reuse\n");
|
||||
#endif
|
||||
|
||||
// Iterate over existing harvested tiles and release any that are contained
|
||||
// within the new valid region.
|
||||
mContext->MakeCurrent();
|
||||
for (int i = 0; i < mTiles.Length();) {
|
||||
ReusableTiledTextureOGL* tile = mTiles[i];
|
||||
|
||||
bool release = false;
|
||||
if (tile->mResolution == aNewResolution) {
|
||||
if (aNewValidRegion.Contains(tile->mTileRegion))
|
||||
release = true;
|
||||
} else {
|
||||
nsIntRegion transformedTileRegion(tile->mTileRegion);
|
||||
transformedTileRegion.ScaleRoundOut(tile->mResolution.width / aNewResolution.width,
|
||||
tile->mResolution.height / aNewResolution.height);
|
||||
if (aNewValidRegion.Contains(transformedTileRegion))
|
||||
release = true;
|
||||
}
|
||||
|
||||
if (release) {
|
||||
#ifdef GFX_TILEDLAYER_PREF_WARNINGS
|
||||
nsIntRect tileBounds = tile->mTileRegion.GetBounds();
|
||||
printf_stderr("Releasing obsolete reused tile at %d,%d, x%f\n",
|
||||
tileBounds.x, tileBounds.y, tile->mResolution.width);
|
||||
#endif
|
||||
mContext->fDeleteTextures(1, &tile->mTexture.mTextureHandle);
|
||||
mTiles.RemoveElementAt(i);
|
||||
continue;
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
// Iterate over the tiles and decide which ones we're going to harvest.
|
||||
// We harvest any tile that is entirely outside of the new valid region, or
|
||||
// any tile that is partially outside of the valid region and whose
|
||||
// resolution has changed.
|
||||
// XXX Tile iteration needs to be abstracted, or have some utility functions
|
||||
// to make it simpler.
|
||||
uint16_t tileSize = aVideoMemoryTiledBuffer->GetTileLength();
|
||||
nsIntRect validBounds = aOldValidRegion.GetBounds();
|
||||
for (int x = validBounds.x; x < validBounds.XMost();) {
|
||||
int w = tileSize - x % tileSize;
|
||||
if (x + w > validBounds.x + validBounds.width)
|
||||
w = validBounds.x + validBounds.width - x;
|
||||
|
||||
for (int y = validBounds.y; y < validBounds.YMost();) {
|
||||
int h = tileSize - y % tileSize;
|
||||
if (y + h > validBounds.y + validBounds.height)
|
||||
h = validBounds.y + validBounds.height - y;
|
||||
|
||||
// If the new valid region doesn't contain this tile region,
|
||||
// harvest the tile.
|
||||
nsIntRegion tileRegion;
|
||||
tileRegion.And(aOldValidRegion, nsIntRect(x, y, w, h));
|
||||
|
||||
nsIntRegion intersectingRegion;
|
||||
bool retainTile = false;
|
||||
if (aNewResolution != aOldResolution) {
|
||||
// Reconcile resolution changes.
|
||||
// If the resolution changes, we know the backing layer will have been
|
||||
// invalidated, so retain tiles that are partially encompassed by the
|
||||
// new valid area, instead of just tiles that don't intersect at all.
|
||||
nsIntRegion transformedTileRegion(tileRegion);
|
||||
transformedTileRegion.ScaleRoundOut(scaleFactor.width, scaleFactor.height);
|
||||
if (!aNewValidRegion.Contains(transformedTileRegion))
|
||||
retainTile = true;
|
||||
} else if (intersectingRegion.And(tileRegion, aNewValidRegion).IsEmpty()) {
|
||||
retainTile = true;
|
||||
}
|
||||
|
||||
if (retainTile) {
|
||||
#ifdef GFX_TILEDLAYER_PREF_WARNINGS
|
||||
printf_stderr("Retaining tile at %d,%d, x%f for reuse\n", x, y, aOldResolution.width);
|
||||
#endif
|
||||
TiledTexture removedTile;
|
||||
if (aVideoMemoryTiledBuffer->RemoveTile(nsIntPoint(x, y), removedTile)) {
|
||||
ReusableTiledTextureOGL* reusedTile =
|
||||
new ReusableTiledTextureOGL(removedTile, tileRegion, tileSize,
|
||||
aOldResolution);
|
||||
mTiles.AppendElement(reusedTile);
|
||||
}
|
||||
#ifdef GFX_TILEDLAYER_PREF_WARNINGS
|
||||
else
|
||||
printf_stderr("Failed to retain tile for reuse\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
y += h;
|
||||
}
|
||||
|
||||
x += w;
|
||||
}
|
||||
|
||||
// Now prune our reused tile store of its oldest tiles if it gets too large.
|
||||
while (mTiles.Length() > aVideoMemoryTiledBuffer->GetTileCount() * mSizeLimit) {
|
||||
#ifdef GFX_TILEDLAYER_PREF_WARNINGS
|
||||
nsIntRect tileBounds = mTiles[0]->mTileRegion.GetBounds();
|
||||
printf_stderr("Releasing old reused tile at %d,%d, x%f\n",
|
||||
tileBounds.x, tileBounds.y, mTiles[0]->mResolution.width);
|
||||
#endif
|
||||
mContext->fDeleteTextures(1, &mTiles[0]->mTexture.mTextureHandle);
|
||||
mTiles.RemoveElementAt(0);
|
||||
}
|
||||
|
||||
#ifdef GFX_TILEDLAYER_PREF_WARNINGS
|
||||
printf_stderr("Retained %d tiles\n", mTiles.Length());
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
ReusableTileStoreOGL::DrawTiles(TiledThebesLayerOGL* aLayer,
|
||||
const nsIntRegion& aValidRegion,
|
||||
const gfxSize& aResolution,
|
||||
const gfx3DMatrix& aTransform,
|
||||
const nsIntPoint& aRenderOffset)
|
||||
{
|
||||
// Render old tiles to fill in gaps we haven't had the time to render yet.
|
||||
for (size_t i = 0; i < mTiles.Length(); i++) {
|
||||
ReusableTiledTextureOGL* tile = mTiles[i];
|
||||
|
||||
// Work out the scaling factor in case of resolution differences.
|
||||
gfxSize scaleFactor = gfxSize(aResolution.width / tile->mResolution.width,
|
||||
aResolution.height / tile->mResolution.height);
|
||||
|
||||
// Get the valid tile region, in the given coordinate space.
|
||||
nsIntRegion transformedTileRegion(tile->mTileRegion);
|
||||
if (aResolution != tile->mResolution)
|
||||
transformedTileRegion.ScaleRoundOut(scaleFactor.width, scaleFactor.height);
|
||||
|
||||
// Skip drawing tiles that will be completely drawn over.
|
||||
if (aValidRegion.Contains(transformedTileRegion))
|
||||
continue;
|
||||
|
||||
// Reconcile the resolution difference by adjusting the transform.
|
||||
gfx3DMatrix transform = aTransform;
|
||||
if (aResolution != tile->mResolution)
|
||||
transform.Scale(scaleFactor.width, scaleFactor.height, 1);
|
||||
|
||||
// XXX We should clip here to make sure we don't overlap with the valid
|
||||
// region, otherwise we may end up with rendering artifacts on
|
||||
// semi-transparent layers.
|
||||
// Similarly, if we have multiple tiles covering the same area, we will
|
||||
// end up with rendering artifacts if the aLayer isn't opaque.
|
||||
nsIntRect tileRect = tile->mTileRegion.GetBounds();
|
||||
uint16_t tileStartX = tileRect.x % tile->mTileSize;
|
||||
uint16_t tileStartY = tileRect.y % tile->mTileSize;
|
||||
nsIntRect textureRect(tileStartX, tileStartY, tileRect.width, tileRect.height);
|
||||
nsIntSize textureSize(tile->mTileSize, tile->mTileSize);
|
||||
aLayer->RenderTile(tile->mTexture, transform, aRenderOffset, tileRect, textureRect, textureSize);
|
||||
}
|
||||
}
|
||||
|
||||
} // mozilla
|
||||
} // layers
|
|
@ -0,0 +1,96 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef GFX_REUSABLETILESTOREOGL_H
|
||||
#define GFX_REUSABLETILESTOREOGL_H
|
||||
|
||||
#include "TiledThebesLayerOGL.h"
|
||||
#include "nsTArray.h"
|
||||
#include "nsAutoPtr.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
namespace gl {
|
||||
class GLContext;
|
||||
}
|
||||
|
||||
namespace layers {
|
||||
|
||||
// A storage class for the information required to render a single tile from
|
||||
// a TiledLayerBufferOGL.
|
||||
class ReusableTiledTextureOGL
|
||||
{
|
||||
public:
|
||||
ReusableTiledTextureOGL(TiledTexture aTexture,
|
||||
const nsIntRegion& aTileRegion,
|
||||
uint16_t aTileSize,
|
||||
gfxSize aResolution)
|
||||
: mTexture(aTexture)
|
||||
, mTileRegion(aTileRegion)
|
||||
, mTileSize(aTileSize)
|
||||
, mResolution(aResolution)
|
||||
{}
|
||||
|
||||
~ReusableTiledTextureOGL() {}
|
||||
|
||||
TiledTexture mTexture;
|
||||
const nsIntRegion mTileRegion;
|
||||
uint16_t mTileSize;
|
||||
gfxSize mResolution;
|
||||
};
|
||||
|
||||
// This class will operate on a TiledLayerBufferOGL to harvest tiles that have
|
||||
// rendered content that is about to become invalid. We do this so that in the
|
||||
// situation that we need to render an area of a TiledThebesLayerOGL that hasn't
|
||||
// been updated quickly enough, we can still display something (and hopefully
|
||||
// it'll be the same as the valid rendered content). While this may end up
|
||||
// showing invalid data, it should only be momentarily.
|
||||
class ReusableTileStoreOGL
|
||||
{
|
||||
public:
|
||||
ReusableTileStoreOGL(gl::GLContext* aContext, float aSizeLimit)
|
||||
: mContext(aContext)
|
||||
, mSizeLimit(aSizeLimit)
|
||||
{}
|
||||
|
||||
~ReusableTileStoreOGL();
|
||||
|
||||
// Harvests tiles from a TiledLayerBufferOGL that are about to become
|
||||
// invalid. aOldValidRegion and aOldResolution should be the valid region
|
||||
// and resolution of the data currently in aVideoMemoryTiledBuffer, and
|
||||
// aNewValidRegion and aNewResolution should be the valid region and
|
||||
// resolution of the data that is about to update aVideoMemoryTiledBuffer.
|
||||
void HarvestTiles(TiledLayerBufferOGL* aVideoMemoryTiledBuffer,
|
||||
const nsIntRegion& aOldValidRegion,
|
||||
const nsIntRegion& aNewValidRegion,
|
||||
const gfxSize& aOldResolution,
|
||||
const gfxSize& aNewResolution);
|
||||
|
||||
// Draws all harvested tiles that don't intersect with the given valid region.
|
||||
// Differences in resolution will be reconciled via altering the given
|
||||
// transformation.
|
||||
void DrawTiles(TiledThebesLayerOGL* aLayer,
|
||||
const nsIntRegion& aValidRegion,
|
||||
const gfxSize& aResolution,
|
||||
const gfx3DMatrix& aTransform,
|
||||
const nsIntPoint& aRenderOffset);
|
||||
|
||||
private:
|
||||
// This GLContext should correspond to the one used in any TiledLayerBufferOGL
|
||||
// that is passed into HarvestTiles and DrawTiles.
|
||||
nsRefPtr<gl::GLContext> mContext;
|
||||
|
||||
// This determines the maximum number of tiles stored in this tile store,
|
||||
// as a fraction of the amount of tiles stored in the TiledLayerBufferOGL
|
||||
// given to HarvestTiles.
|
||||
float mSizeLimit;
|
||||
|
||||
// This stores harvested tiles, in the order in which they were harvested.
|
||||
nsTArray< nsAutoPtr<ReusableTiledTextureOGL> > mTiles;
|
||||
};
|
||||
|
||||
} // layers
|
||||
} // mozilla
|
||||
|
||||
#endif // GFX_REUSABLETILESTOREOGL_H
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
#include "mozilla/layers/PLayersChild.h"
|
||||
#include "TiledThebesLayerOGL.h"
|
||||
#include "ReusableTileStoreOGL.h"
|
||||
#include "BasicTiledThebesLayer.h"
|
||||
#include "gfxImageSurface.h"
|
||||
|
||||
|
@ -37,12 +38,15 @@ TiledLayerBufferOGL::ReleaseTile(TiledTexture aTile)
|
|||
void
|
||||
TiledLayerBufferOGL::Upload(const BasicTiledLayerBuffer* aMainMemoryTiledBuffer,
|
||||
const nsIntRegion& aNewValidRegion,
|
||||
const nsIntRegion& aInvalidateRegion)
|
||||
const nsIntRegion& aInvalidateRegion,
|
||||
const gfxSize& aResolution)
|
||||
{
|
||||
#ifdef GFX_TILEDLAYER_PREF_WARNINGS
|
||||
printf_stderr("Upload %i, %i, %i, %i\n", aInvalidateRegion.GetBounds().x, aInvalidateRegion.GetBounds().y, aInvalidateRegion.GetBounds().width, aInvalidateRegion.GetBounds().height);
|
||||
long start = PR_IntervalNow();
|
||||
#endif
|
||||
|
||||
mResolution = aResolution;
|
||||
mMainMemoryTiledBuffer = aMainMemoryTiledBuffer;
|
||||
mContext->MakeCurrent();
|
||||
Update(aNewValidRegion, aInvalidateRegion);
|
||||
|
@ -113,6 +117,15 @@ TiledThebesLayerOGL::TiledThebesLayerOGL(LayerManagerOGL *aManager)
|
|||
, mVideoMemoryTiledBuffer(aManager->gl())
|
||||
{
|
||||
mImplData = static_cast<LayerOGL*>(this);
|
||||
// XXX Add a pref for reusable tile store size
|
||||
mReusableTileStore = new ReusableTileStoreOGL(aManager->gl(), 1);
|
||||
}
|
||||
|
||||
TiledThebesLayerOGL::~TiledThebesLayerOGL()
|
||||
{
|
||||
mMainMemoryTiledBuffer.ReadUnlock();
|
||||
if (mReusableTileStore)
|
||||
delete mReusableTileStore;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -121,9 +134,6 @@ TiledThebesLayerOGL::PaintedTiledLayerBuffer(const BasicTiledLayerBuffer* mTiled
|
|||
mMainMemoryTiledBuffer = *mTiledBuffer;
|
||||
mRegionToUpload.Or(mRegionToUpload, mMainMemoryTiledBuffer.GetLastPaintRegion());
|
||||
|
||||
gl()->MakeCurrent();
|
||||
|
||||
ProcessUploadQueue(); // TODO: Remove me; this should be unnecessary.
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -132,7 +142,29 @@ TiledThebesLayerOGL::ProcessUploadQueue()
|
|||
if (mRegionToUpload.IsEmpty())
|
||||
return;
|
||||
|
||||
mVideoMemoryTiledBuffer.Upload(&mMainMemoryTiledBuffer, mMainMemoryTiledBuffer.GetValidRegion(), mRegionToUpload);
|
||||
gfxSize resolution(1, 1);
|
||||
if (mReusableTileStore) {
|
||||
// Work out render resolution by multiplying the resolution of our ancestors.
|
||||
// Only container layers can have frame metrics, so we start off with a
|
||||
// resolution of 1, 1.
|
||||
// XXX For large layer trees, it would be faster to do this once from the
|
||||
// root node upwards and store the value on each layer.
|
||||
for (ContainerLayer* parent = GetParent(); parent; parent = parent->GetParent()) {
|
||||
const FrameMetrics& metrics = parent->GetFrameMetrics();
|
||||
resolution.width *= metrics.mResolution.width;
|
||||
resolution.height *= metrics.mResolution.height;
|
||||
}
|
||||
|
||||
mReusableTileStore->HarvestTiles(&mVideoMemoryTiledBuffer,
|
||||
mVideoMemoryTiledBuffer.GetValidRegion(),
|
||||
mMainMemoryTiledBuffer.GetValidRegion(),
|
||||
mVideoMemoryTiledBuffer.GetResolution(),
|
||||
resolution);
|
||||
}
|
||||
|
||||
mVideoMemoryTiledBuffer.Upload(&mMainMemoryTiledBuffer,
|
||||
mMainMemoryTiledBuffer.GetValidRegion(),
|
||||
mRegionToUpload, resolution);
|
||||
mValidRegion = mVideoMemoryTiledBuffer.GetValidRegion();
|
||||
|
||||
mMainMemoryTiledBuffer.ReadUnlock();
|
||||
|
@ -146,12 +178,46 @@ TiledThebesLayerOGL::ProcessUploadQueue()
|
|||
|
||||
}
|
||||
|
||||
void
|
||||
TiledThebesLayerOGL::RenderTile(TiledTexture aTile,
|
||||
const gfx3DMatrix& aTransform,
|
||||
const nsIntPoint& aOffset,
|
||||
nsIntRect aScreenRect,
|
||||
nsIntRect aTextureRect,
|
||||
nsIntSize aTextureBounds)
|
||||
{
|
||||
gl()->fBindTexture(LOCAL_GL_TEXTURE_2D, aTile.mTextureHandle);
|
||||
ColorTextureLayerProgram *program;
|
||||
if (aTile.mFormat == LOCAL_GL_RGB) {
|
||||
program = mOGLManager->GetRGBXLayerProgram();
|
||||
} else {
|
||||
program = mOGLManager->GetBGRALayerProgram();
|
||||
}
|
||||
program->Activate();
|
||||
program->SetTextureUnit(0);
|
||||
program->SetLayerOpacity(GetEffectiveOpacity());
|
||||
program->SetLayerTransform(aTransform);
|
||||
program->SetRenderOffset(aOffset);
|
||||
program->SetLayerQuadRect(aScreenRect);
|
||||
|
||||
mOGLManager->BindAndDrawQuadWithTextureRect(program,
|
||||
aTextureRect,
|
||||
aTextureBounds);
|
||||
}
|
||||
|
||||
void
|
||||
TiledThebesLayerOGL::RenderLayer(int aPreviousFrameBuffer, const nsIntPoint& aOffset)
|
||||
{
|
||||
gl()->MakeCurrent();
|
||||
ProcessUploadQueue();
|
||||
|
||||
// Render old tiles to fill in gaps we haven't had the time to render yet.
|
||||
if (mReusableTileStore)
|
||||
mReusableTileStore->DrawTiles(this, mVideoMemoryTiledBuffer.GetValidRegion(),
|
||||
mVideoMemoryTiledBuffer.GetResolution(),
|
||||
GetEffectiveTransform(), aOffset);
|
||||
|
||||
// Render valid tiles.
|
||||
const nsIntRegion& visibleRegion = GetEffectiveVisibleRegion();
|
||||
const nsIntRect visibleRect = visibleRegion.GetBounds();
|
||||
unsigned int rowCount = 0;
|
||||
|
@ -173,22 +239,9 @@ TiledThebesLayerOGL::RenderLayer(int aPreviousFrameBuffer, const nsIntPoint& aOf
|
|||
GetTile(nsIntPoint(mVideoMemoryTiledBuffer.RoundDownToTileEdge(x),
|
||||
mVideoMemoryTiledBuffer.RoundDownToTileEdge(y)));
|
||||
if (tileTexture != mVideoMemoryTiledBuffer.GetPlaceholderTile()) {
|
||||
|
||||
gl()->fBindTexture(LOCAL_GL_TEXTURE_2D, tileTexture.mTextureHandle);
|
||||
ColorTextureLayerProgram *program;
|
||||
if (tileTexture.mFormat == LOCAL_GL_RGB) {
|
||||
program = mOGLManager->GetRGBXLayerProgram();
|
||||
} else {
|
||||
program = mOGLManager->GetBGRALayerProgram();
|
||||
}
|
||||
program->Activate();
|
||||
program->SetTextureUnit(0);
|
||||
program->SetLayerOpacity(GetEffectiveOpacity());
|
||||
program->SetLayerTransform(GetEffectiveTransform());
|
||||
program->SetRenderOffset(aOffset);
|
||||
program->SetLayerQuadRect(nsIntRect(x,y,w,h)); // screen
|
||||
mOGLManager->BindAndDrawQuadWithTextureRect(program, nsIntRect(tileStartX, tileStartY, w, h), nsIntSize(mVideoMemoryTiledBuffer.GetTileLength(), mVideoMemoryTiledBuffer.GetTileLength())); // texture bounds
|
||||
|
||||
uint16_t tileSize = mVideoMemoryTiledBuffer.GetTileLength();
|
||||
RenderTile(tileTexture, GetEffectiveTransform(), aOffset, nsIntRect(x,y,w,h),
|
||||
nsIntRect(tileStartX, tileStartY, w, h), nsIntSize(tileSize, tileSize));
|
||||
}
|
||||
tileY++;
|
||||
y += h;
|
||||
|
|
|
@ -20,6 +20,8 @@ class GLContext;
|
|||
|
||||
namespace layers {
|
||||
|
||||
class ReusableTileStoreOGL;
|
||||
|
||||
class TiledTexture {
|
||||
public:
|
||||
// Constructs a placeholder TiledTexture. See the comments above
|
||||
|
@ -73,10 +75,13 @@ public:
|
|||
|
||||
void Upload(const BasicTiledLayerBuffer* aMainMemoryTiledBuffer,
|
||||
const nsIntRegion& aNewValidRegion,
|
||||
const nsIntRegion& aInvalidateRegion);
|
||||
const nsIntRegion& aInvalidateRegion,
|
||||
const gfxSize& aResolution);
|
||||
|
||||
TiledTexture GetPlaceholderTile() const { return TiledTexture(); }
|
||||
|
||||
const gfxSize& GetResolution() { return mResolution; }
|
||||
|
||||
protected:
|
||||
TiledTexture ValidateTile(TiledTexture aTile,
|
||||
const nsIntPoint& aTileRect,
|
||||
|
@ -91,6 +96,7 @@ protected:
|
|||
private:
|
||||
nsRefPtr<gl::GLContext> mContext;
|
||||
const BasicTiledLayerBuffer* mMainMemoryTiledBuffer;
|
||||
gfxSize mResolution;
|
||||
|
||||
void GetFormatAndTileForImageFormat(gfxASurface::gfxImageFormat aFormat,
|
||||
GLenum& aOutFormat,
|
||||
|
@ -103,10 +109,7 @@ class TiledThebesLayerOGL : public ShadowThebesLayer,
|
|||
{
|
||||
public:
|
||||
TiledThebesLayerOGL(LayerManagerOGL *aManager);
|
||||
virtual ~TiledThebesLayerOGL()
|
||||
{
|
||||
mMainMemoryTiledBuffer.ReadUnlock();
|
||||
}
|
||||
virtual ~TiledThebesLayerOGL();
|
||||
|
||||
// LayerOGL impl
|
||||
void Destroy() {}
|
||||
|
@ -126,10 +129,22 @@ public:
|
|||
}
|
||||
void PaintedTiledLayerBuffer(const BasicTiledLayerBuffer* mTiledBuffer);
|
||||
void ProcessUploadQueue();
|
||||
|
||||
// Renders a single given tile.
|
||||
// XXX This currently takes an nsIntRect, but should actually take an
|
||||
// nsIntRegion and iterate over each rectangle in the region.
|
||||
void RenderTile(TiledTexture aTile,
|
||||
const gfx3DMatrix& aTransform,
|
||||
const nsIntPoint& aOffset,
|
||||
nsIntRect aScreenRect,
|
||||
nsIntRect aTextureRect,
|
||||
nsIntSize aTextureBounds);
|
||||
|
||||
private:
|
||||
nsIntRegion mRegionToUpload;
|
||||
BasicTiledLayerBuffer mMainMemoryTiledBuffer;
|
||||
TiledLayerBufferOGL mVideoMemoryTiledBuffer;
|
||||
ReusableTileStoreOGL* mReusableTileStore;
|
||||
};
|
||||
|
||||
} // layers
|
||||
|
|
|
@ -53,6 +53,7 @@
|
|||
#include "gfxColor.h"
|
||||
#include "gfxMatrix.h"
|
||||
#include "gfxPattern.h"
|
||||
#include "gfxPoint.h"
|
||||
#include "nsRect.h"
|
||||
#include "nsRegion.h"
|
||||
#include "gfxASurface.h"
|
||||
|
@ -458,6 +459,27 @@ struct ParamTraits<gfxMatrix>
|
|||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct ParamTraits<gfxSize>
|
||||
{
|
||||
typedef gfxSize paramType;
|
||||
|
||||
static void Write(Message* aMsg, const paramType& aParam)
|
||||
{
|
||||
WriteParam(aMsg, aParam.width);
|
||||
WriteParam(aMsg, aParam.height);
|
||||
}
|
||||
|
||||
static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
|
||||
{
|
||||
if (ReadParam(aMsg, aIter, &aResult->width) &&
|
||||
ReadParam(aMsg, aIter, &aResult->height))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct ParamTraits<gfx3DMatrix>
|
||||
{
|
||||
|
|
|
@ -475,3 +475,13 @@ xpc_DumpJSObject(JSObject* obj)
|
|||
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
void
|
||||
xpc_PrintAllReferencesTo(void *p)
|
||||
{
|
||||
/* p must be a JS object */
|
||||
XPCJSRuntime* rt = nsXPConnect::GetRuntimeInstance();
|
||||
JS_DumpHeap(rt->GetJSRuntime(), stdout, nsnull, JSTRACE_OBJECT, p, 0x7fffffff, nsnull);
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -119,9 +119,6 @@ nsXPConnect::nsXPConnect()
|
|||
mRuntime = XPCJSRuntime::newXPCJSRuntime(this);
|
||||
|
||||
nsCycleCollector_registerRuntime(nsIProgrammingLanguage::JAVASCRIPT, this);
|
||||
#ifdef DEBUG_CC
|
||||
mJSRoots.ops = nsnull;
|
||||
#endif
|
||||
|
||||
char* reportableEnv = PR_GetEnv("MOZ_REPORT_ALL_JS_EXCEPTIONS");
|
||||
if (reportableEnv && *reportableEnv)
|
||||
|
@ -399,14 +396,14 @@ nsXPConnect::Collect(PRUint32 reason, PRUint32 kind)
|
|||
// JS objects that are part of cycles the cycle collector breaks will be
|
||||
// collected by the next JS.
|
||||
//
|
||||
// If DEBUG_CC is not defined the cycle collector will not traverse roots
|
||||
// If WantAllTraces() is false the cycle collector will not traverse roots
|
||||
// from category 1 or any JS objects held by them. Any JS objects they hold
|
||||
// will already be marked by the JS GC and will thus be colored black
|
||||
// themselves. Any C++ objects they hold will have a missing (untraversed)
|
||||
// edge from the JS object to the C++ object and so it will be marked black
|
||||
// too. This decreases the number of objects that the cycle collector has to
|
||||
// deal with.
|
||||
// To improve debugging, if DEBUG_CC is defined all JS objects are
|
||||
// To improve debugging, if WantAllTraces() is true all JS objects are
|
||||
// traversed.
|
||||
|
||||
MOZ_ASSERT(reason < js::gcreason::NUM_REASONS);
|
||||
|
@ -431,37 +428,6 @@ nsXPConnect::GarbageCollect(PRUint32 reason, PRUint32 kind)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_CC
|
||||
struct NoteJSRootTracer : public JSTracer
|
||||
{
|
||||
NoteJSRootTracer(PLDHashTable *aObjects,
|
||||
nsCycleCollectionTraversalCallback& cb)
|
||||
: mObjects(aObjects),
|
||||
mCb(cb)
|
||||
{
|
||||
}
|
||||
PLDHashTable* mObjects;
|
||||
nsCycleCollectionTraversalCallback& mCb;
|
||||
};
|
||||
|
||||
static void
|
||||
NoteJSRoot(JSTracer *trc, void *thing, JSGCTraceKind kind)
|
||||
{
|
||||
if (AddToCCKind(kind)) {
|
||||
NoteJSRootTracer *tracer = static_cast<NoteJSRootTracer*>(trc);
|
||||
PLDHashEntryHdr *entry = PL_DHashTableOperate(tracer->mObjects, thing,
|
||||
PL_DHASH_ADD);
|
||||
if (entry && !reinterpret_cast<PLDHashEntryStub*>(entry)->key) {
|
||||
reinterpret_cast<PLDHashEntryStub*>(entry)->key = thing;
|
||||
tracer->mCb.NoteRoot(nsIProgrammingLanguage::JAVASCRIPT, thing,
|
||||
nsXPConnect::GetXPConnect());
|
||||
}
|
||||
} else if (kind != JSTRACE_STRING) {
|
||||
JS_TraceChildren(trc, thing, kind);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
struct NoteWeakMapChildrenTracer : public JSTracer
|
||||
{
|
||||
NoteWeakMapChildrenTracer(nsCycleCollectionTraversalCallback &cb)
|
||||
|
@ -538,8 +504,7 @@ TraceWeakMapping(js::WeakMapTracer *trc, JSObject *m,
|
|||
}
|
||||
|
||||
nsresult
|
||||
nsXPConnect::BeginCycleCollection(nsCycleCollectionTraversalCallback &cb,
|
||||
bool explainLiveExpectedGarbage)
|
||||
nsXPConnect::BeginCycleCollection(nsCycleCollectionTraversalCallback &cb)
|
||||
{
|
||||
// It is important not to call GetSafeJSContext while on the
|
||||
// cycle-collector thread since this context will be destroyed
|
||||
|
@ -565,31 +530,6 @@ nsXPConnect::BeginCycleCollection(nsCycleCollectionTraversalCallback &cb,
|
|||
gcHasRun = true;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_CC
|
||||
NS_ASSERTION(!mJSRoots.ops, "Didn't call FinishCycleCollection?");
|
||||
|
||||
if (explainLiveExpectedGarbage) {
|
||||
// Being called from nsCycleCollector::ExplainLiveExpectedGarbage.
|
||||
|
||||
// Record all objects held by the JS runtime. This avoids doing a
|
||||
// complete GC if we're just tracing to explain (from
|
||||
// ExplainLiveExpectedGarbage), which makes the results of cycle
|
||||
// collection identical for DEBUG_CC and non-DEBUG_CC builds.
|
||||
if (!PL_DHashTableInit(&mJSRoots, PL_DHashGetStubOps(), nsnull,
|
||||
sizeof(PLDHashEntryStub), PL_DHASH_MIN_SIZE)) {
|
||||
mJSRoots.ops = nsnull;
|
||||
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
NoteJSRootTracer trc(&mJSRoots, cb);
|
||||
JS_TracerInit(&trc, mCycleCollectionContext->GetJSContext(), NoteJSRoot);
|
||||
JS_TraceRuntime(&trc);
|
||||
}
|
||||
#else
|
||||
NS_ASSERTION(!explainLiveExpectedGarbage, "Didn't call nsXPConnect::Collect()?");
|
||||
#endif
|
||||
|
||||
GetRuntime()->AddXPConnectRoots(cb);
|
||||
|
||||
NoteWeakMapsTracer trc(GetRuntime()->GetJSRuntime(), TraceWeakMapping, cb);
|
||||
|
@ -638,19 +578,6 @@ nsXPConnect::FinishTraverse()
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsXPConnect::FinishCycleCollection()
|
||||
{
|
||||
#ifdef DEBUG_CC
|
||||
if (mJSRoots.ops) {
|
||||
PL_DHashTableFinish(&mJSRoots);
|
||||
mJSRoots.ops = nsnull;
|
||||
}
|
||||
#endif
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCycleCollectionParticipant *
|
||||
nsXPConnect::ToParticipant(void *p)
|
||||
{
|
||||
|
@ -665,19 +592,6 @@ nsXPConnect::Root(void *p)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_CC
|
||||
void
|
||||
nsXPConnect::PrintAllReferencesTo(void *p)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
XPCCallContext ccx(NATIVE_CALLER);
|
||||
if (ccx.IsValid())
|
||||
JS_DumpHeap(ccx.GetJSContext(), stdout, nsnull, 0, p,
|
||||
0x7fffffff, nsnull);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXPConnect::Unlink(void *p)
|
||||
{
|
||||
|
@ -909,30 +823,7 @@ nsXPConnect::Traverse(void *p, nsCycleCollectionTraversalCallback &cb)
|
|||
}
|
||||
}
|
||||
|
||||
bool isMarked;
|
||||
|
||||
#ifdef DEBUG_CC
|
||||
// Note that the conditions under which we specify GCMarked vs.
|
||||
// GCUnmarked are different between ExplainLiveExpectedGarbage and
|
||||
// the normal case. In the normal case, we're saying that anything
|
||||
// reachable from a JS runtime root is itself such a root. This
|
||||
// doesn't actually break anything; it really just does some of the
|
||||
// cycle collector's work for it. However, when debugging, we
|
||||
// (1) actually need to know what the root is and (2) don't want to
|
||||
// do an extra GC, so we use mJSRoots, built from JS_TraceRuntime,
|
||||
// which produces a different result because we didn't call
|
||||
// JS_TraceChildren to trace everything that was reachable.
|
||||
if (mJSRoots.ops) {
|
||||
// ExplainLiveExpectedGarbage codepath
|
||||
PLDHashEntryHdr* entry =
|
||||
PL_DHashTableOperate(&mJSRoots, p, PL_DHASH_LOOKUP);
|
||||
isMarked = markJSObject || PL_DHASH_ENTRY_IS_BUSY(entry);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
// Normal codepath (matches non-DEBUG_CC codepath).
|
||||
isMarked = markJSObject || !xpc_IsGrayGCThing(p);
|
||||
}
|
||||
bool isMarked = markJSObject || !xpc_IsGrayGCThing(p);
|
||||
|
||||
if (cb.WantDebugInfo()) {
|
||||
char name[72];
|
||||
|
@ -982,8 +873,8 @@ nsXPConnect::Traverse(void *p, nsCycleCollectionTraversalCallback &cb)
|
|||
|
||||
// There's no need to trace objects that have already been marked by the JS
|
||||
// GC. Any JS objects hanging from them will already be marked. Only do this
|
||||
// if DEBUG_CC is not defined, else we do want to know about all JS objects
|
||||
// to get better graphs and explanations.
|
||||
// if cb.WantAllTraces() is false, otherwise we do want to know about all JS
|
||||
// objects to get better graphs and explanations.
|
||||
if (!cb.WantAllTraces() && isMarked)
|
||||
return NS_OK;
|
||||
|
||||
|
|
|
@ -537,16 +537,11 @@ public:
|
|||
virtual void NotifyEnterCycleCollectionThread();
|
||||
virtual void NotifyLeaveCycleCollectionThread();
|
||||
virtual void NotifyEnterMainThread();
|
||||
virtual nsresult BeginCycleCollection(nsCycleCollectionTraversalCallback &cb,
|
||||
bool explainExpectedLiveGarbage);
|
||||
virtual nsresult BeginCycleCollection(nsCycleCollectionTraversalCallback &cb);
|
||||
virtual nsresult FinishTraverse();
|
||||
virtual nsresult FinishCycleCollection();
|
||||
virtual nsCycleCollectionParticipant *ToParticipant(void *p);
|
||||
virtual bool NeedCollect();
|
||||
virtual void Collect(PRUint32 reason, PRUint32 kind);
|
||||
#ifdef DEBUG_CC
|
||||
virtual void PrintAllReferencesTo(void *p);
|
||||
#endif
|
||||
|
||||
XPCCallContext *GetCycleCollectionContext()
|
||||
{
|
||||
|
@ -598,9 +593,6 @@ private:
|
|||
// an 'after' notification without getting an 'on' notification. If we don't
|
||||
// watch out for this, we'll do an unmatched |pop| on the context stack.
|
||||
PRUint16 mEventDepth;
|
||||
#ifdef DEBUG_CC
|
||||
PLDHashTable mJSRoots;
|
||||
#endif
|
||||
nsAutoPtr<XPCCallContext> mCycleCollectionContext;
|
||||
|
||||
typedef nsBaseHashtable<nsPtrHashKey<void>, nsISupports*, nsISupports*> ScopeSet;
|
||||
|
|
|
@ -250,6 +250,10 @@ static void RecordFrameMetrics(nsIFrame* aForFrame,
|
|||
}
|
||||
|
||||
metrics.mScrollId = aScrollId;
|
||||
|
||||
nsIPresShell* presShell = presContext->GetPresShell();
|
||||
metrics.mResolution = gfxSize(presShell->GetXResolution(), presShell->GetYResolution());
|
||||
|
||||
aRoot->SetFrameMetrics(metrics);
|
||||
}
|
||||
|
||||
|
|
|
@ -78,12 +78,6 @@ function run() {
|
|||
sel.removeAllRanges();
|
||||
sel.modify("move", "forward", "character");
|
||||
|
||||
// Similarly, we should silently fail if the selection has been detached.
|
||||
$("c").focus();
|
||||
sel.collapse($("p1"), 0);
|
||||
sel.getRangeAt(0).detach();
|
||||
sel.modify("move", "forward", "character");
|
||||
|
||||
// Now focus our first div and put the cursor at the beginning of p1.
|
||||
$("c").focus();
|
||||
sel.collapse($("p1"), 0);
|
||||
|
|
|
@ -52,6 +52,7 @@
|
|||
#include "nsViewportFrame.h"
|
||||
#include "nsSubDocumentFrame.h"
|
||||
#include "nsIObserver.h"
|
||||
#include "nsContentUtils.h"
|
||||
|
||||
typedef nsContentView::ViewConfig ViewConfig;
|
||||
using namespace mozilla::layers;
|
||||
|
@ -641,7 +642,9 @@ RenderFrameParent::AllocPLayers(LayerManager::LayersBackend* aBackendType)
|
|||
*aBackendType = LayerManager::LAYERS_NONE;
|
||||
return nsnull;
|
||||
}
|
||||
LayerManager* lm = GetLayerManager();
|
||||
|
||||
nsRefPtr<LayerManager> lm =
|
||||
nsContentUtils::LayerManagerForDocument(mFrameLoader->OwnerDoc());
|
||||
ShadowLayerManager* slm = lm->AsShadowManager();
|
||||
if (!slm) {
|
||||
*aBackendType = LayerManager::LAYERS_NONE;
|
||||
|
@ -692,13 +695,6 @@ RenderFrameParent::BuildViewMap()
|
|||
mContentViews = newContentViews;
|
||||
}
|
||||
|
||||
LayerManager*
|
||||
RenderFrameParent::GetLayerManager() const
|
||||
{
|
||||
nsIDocument* doc = mFrameLoader->OwnerDoc();
|
||||
return doc->GetShell()->GetLayerManager();
|
||||
}
|
||||
|
||||
ShadowLayersParent*
|
||||
RenderFrameParent::GetShadowLayers() const
|
||||
{
|
||||
|
|
|
@ -111,7 +111,6 @@ protected:
|
|||
private:
|
||||
void BuildViewMap();
|
||||
|
||||
LayerManager* GetLayerManager() const;
|
||||
ShadowLayersParent* GetShadowLayers() const;
|
||||
ContainerLayer* GetRootLayer() const;
|
||||
|
||||
|
|
|
@ -8,5 +8,5 @@
|
|||
|
||||
<!-- From https://bugzilla.mozilla.org/show_bug.cgi?id=368840 -->
|
||||
|
||||
<rect x="0%" y="0%" width="100%" height="100%" fill="black"/>
|
||||
<rect x="0%" y="0%" width="100%" height="100%" fill="white"/>
|
||||
</svg>
|
||||
|
|
До Ширина: | Высота: | Размер: 345 B После Ширина: | Высота: | Размер: 345 B |
|
@ -9266,7 +9266,7 @@ CSSParserImpl::ParsePaint(nsCSSProperty aPropID)
|
|||
return false;
|
||||
if (x.GetUnit() == eCSSUnit_URL) {
|
||||
if (!ParseVariant(y, VARIANT_COLOR | VARIANT_NONE, nsnull))
|
||||
y.SetColorValue(NS_RGB(0, 0, 0));
|
||||
y.SetNoneValue();
|
||||
}
|
||||
if (!ExpectEndProperty())
|
||||
return false;
|
||||
|
|
|
@ -365,7 +365,7 @@ pref("places.frecency.unvisitedTypedBonus", 200);
|
|||
pref("gfx.color_management.mode", 0);
|
||||
|
||||
#ifdef ANDROID
|
||||
// 0=fixed margin, 1=velocity bias, 2=dynamic resolution, 3=no margins
|
||||
// 0=fixed margin, 1=velocity bias, 2=dynamic resolution, 3=no margins, 4=prediction bias
|
||||
pref("gfx.displayport.strategy", 1);
|
||||
// all of the following displayport strategy prefs will be divided by 1000
|
||||
// to obtain some multiplier which is then used in the strategy.
|
||||
|
@ -375,12 +375,14 @@ pref("gfx.displayport.strategy_fm.danger_x", -1); // danger zone on x-axis when
|
|||
pref("gfx.displayport.strategy_fm.danger_y", -1); // danger zone on y-axis when multiplied by viewport height
|
||||
// velocity bias strategy options
|
||||
pref("gfx.displayport.strategy_vb.multiplier", -1); // displayport dimension multiplier
|
||||
pref("gfx.displayport.strategy_vb.threshold", -1); // velocity threshold in pixels/frame when multiplied by screen DPI
|
||||
pref("gfx.displayport.strategy_vb.threshold", -1); // velocity threshold in inches/frame
|
||||
pref("gfx.displayport.strategy_vb.reverse_buffer", -1); // fraction of buffer to keep in reverse direction from scroll
|
||||
pref("gfx.displayport.strategy_vb.danger_x_base", -1); // danger zone on x-axis when multiplied by viewport width
|
||||
pref("gfx.displayport.strategy_vb.danger_y_base", -1); // danger zone on y-axis when multiplied by viewport height
|
||||
pref("gfx.displayport.strategy_vb.danger_x_incr", -1); // additional danger zone on x-axis when multiplied by viewport width and velocity
|
||||
pref("gfx.displayport.strategy_vb.danger_y_incr", -1); // additional danger zone on y-axis when multiplied by viewport height and velocity
|
||||
// prediction bias strategy options
|
||||
pref("gfx.displayport.strategy_pb.threshold", -1); // velocity threshold in inches/frame
|
||||
#endif
|
||||
|
||||
// don't allow JS to move and resize existing windows
|
||||
|
|
|
@ -124,6 +124,7 @@ FENNEC_JAVA_FILES = \
|
|||
gfx/CheckerboardImage.java \
|
||||
gfx/DisplayPortCalculator.java \
|
||||
gfx/DisplayPortMetrics.java \
|
||||
gfx/DrawTimingQueue.java \
|
||||
gfx/FloatSize.java \
|
||||
gfx/GeckoLayerClient.java \
|
||||
gfx/GLController.java \
|
||||
|
|
|
@ -32,6 +32,7 @@ final class DisplayPortCalculator {
|
|||
private static final String PREF_DISPLAYPORT_VB_DANGER_Y_BASE = "gfx.displayport.strategy_vb.danger_y_base";
|
||||
private static final String PREF_DISPLAYPORT_VB_DANGER_X_INCR = "gfx.displayport.strategy_vb.danger_x_incr";
|
||||
private static final String PREF_DISPLAYPORT_VB_DANGER_Y_INCR = "gfx.displayport.strategy_vb.danger_y_incr";
|
||||
private static final String PREF_DISPLAYPORT_PB_VELOCITY_THRESHOLD = "gfx.displayport.strategy_pb.threshold";
|
||||
|
||||
private static DisplayPortStrategy sStrategy = new VelocityBiasStrategy(null);
|
||||
|
||||
|
@ -46,6 +47,14 @@ final class DisplayPortCalculator {
|
|||
return sStrategy.aboutToCheckerboard(metrics, (velocity == null ? ZERO_VELOCITY : velocity), displayPort);
|
||||
}
|
||||
|
||||
static boolean drawTimeUpdate(long millis, int pixels) {
|
||||
return sStrategy.drawTimeUpdate(millis, pixels);
|
||||
}
|
||||
|
||||
static void resetPageState() {
|
||||
sStrategy.resetPageState();
|
||||
}
|
||||
|
||||
static void addPrefNames(JSONArray prefs) {
|
||||
prefs.put(PREF_DISPLAYPORT_STRATEGY);
|
||||
prefs.put(PREF_DISPLAYPORT_FM_MULTIPLIER);
|
||||
|
@ -58,6 +67,7 @@ final class DisplayPortCalculator {
|
|||
prefs.put(PREF_DISPLAYPORT_VB_DANGER_Y_BASE);
|
||||
prefs.put(PREF_DISPLAYPORT_VB_DANGER_X_INCR);
|
||||
prefs.put(PREF_DISPLAYPORT_VB_DANGER_Y_INCR);
|
||||
prefs.put(PREF_DISPLAYPORT_PB_VELOCITY_THRESHOLD);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -84,6 +94,9 @@ final class DisplayPortCalculator {
|
|||
case 3:
|
||||
sStrategy = new NoMarginStrategy(prefs);
|
||||
break;
|
||||
case 4:
|
||||
sStrategy = new PredictionBiasStrategy(prefs);
|
||||
break;
|
||||
default:
|
||||
Log.e(LOGTAG, "Invalid strategy index specified");
|
||||
return false;
|
||||
|
@ -97,11 +110,15 @@ final class DisplayPortCalculator {
|
|||
return (float)(value == null || value < 0 ? defaultValue : value) / 1000f;
|
||||
}
|
||||
|
||||
private interface DisplayPortStrategy {
|
||||
private static abstract class DisplayPortStrategy {
|
||||
/** Calculates a displayport given a viewport and panning velocity. */
|
||||
public DisplayPortMetrics calculate(ImmutableViewportMetrics metrics, PointF velocity);
|
||||
public abstract DisplayPortMetrics calculate(ImmutableViewportMetrics metrics, PointF velocity);
|
||||
/** Returns true if a checkerboard is about to be visible and we should not throttle drawing. */
|
||||
public boolean aboutToCheckerboard(ImmutableViewportMetrics metrics, PointF velocity, DisplayPortMetrics displayPort);
|
||||
public abstract boolean aboutToCheckerboard(ImmutableViewportMetrics metrics, PointF velocity, DisplayPortMetrics displayPort);
|
||||
/** Notify the strategy of a new recorded draw time. Return false to turn off draw time recording. */
|
||||
public boolean drawTimeUpdate(long millis, int pixels) { return false; }
|
||||
/** Reset any page-specific state stored, as the page being displayed has changed. */
|
||||
public void resetPageState() {}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -194,10 +211,21 @@ final class DisplayPortCalculator {
|
|||
return margins;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clamp the given rect to the page bounds and return it.
|
||||
*/
|
||||
private static RectF clampToPageBounds(RectF rect, ImmutableViewportMetrics metrics) {
|
||||
rect.left = Math.max(rect.left, 0);
|
||||
rect.top = Math.max(rect.top, 0);
|
||||
rect.right = Math.min(rect.right, metrics.pageSizeWidth);
|
||||
rect.bottom = Math.min(rect.bottom, metrics.pageSizeHeight);
|
||||
return rect;
|
||||
}
|
||||
|
||||
/**
|
||||
* This class implements the variation where we basically don't bother with a a display port.
|
||||
*/
|
||||
private static class NoMarginStrategy implements DisplayPortStrategy {
|
||||
private static class NoMarginStrategy extends DisplayPortStrategy {
|
||||
NoMarginStrategy(Map<String, Integer> prefs) {
|
||||
// no prefs in this strategy
|
||||
}
|
||||
|
@ -228,7 +256,7 @@ final class DisplayPortCalculator {
|
|||
* and/or (b) increasing the buffer on the other axis to compensate for the reduced buffer on
|
||||
* one axis.
|
||||
*/
|
||||
private static class FixedMarginStrategy implements DisplayPortStrategy {
|
||||
private static class FixedMarginStrategy extends DisplayPortStrategy {
|
||||
// The length of each axis of the display port will be the corresponding view length
|
||||
// multiplied by this factor.
|
||||
private final float SIZE_MULTIPLIER;
|
||||
|
@ -294,7 +322,7 @@ final class DisplayPortCalculator {
|
|||
* so that it is almost entirely in the direction of the pan, with a little bit in the
|
||||
* reverse direction.
|
||||
*/
|
||||
private static class VelocityBiasStrategy implements DisplayPortStrategy {
|
||||
private static class VelocityBiasStrategy extends DisplayPortStrategy {
|
||||
// The length of each axis of the display port will be the corresponding view length
|
||||
// multiplied by this factor.
|
||||
private final float SIZE_MULTIPLIER;
|
||||
|
@ -420,7 +448,7 @@ final class DisplayPortCalculator {
|
|||
* looks blurry. The assumption is that drawing extra that we never display is better than checkerboarding,
|
||||
* where we draw less but never even show it on the screen.
|
||||
*/
|
||||
private static class DynamicResolutionStrategy implements DisplayPortStrategy {
|
||||
private static class DynamicResolutionStrategy extends DisplayPortStrategy {
|
||||
// The length of each axis of the display port will be the corresponding view length
|
||||
// multiplied by this factor.
|
||||
private static final float SIZE_MULTIPLIER = 1.5f;
|
||||
|
@ -609,4 +637,117 @@ final class DisplayPortCalculator {
|
|||
return "DynamicResolutionStrategy";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This class implements the variation where we use the draw time to predict where we will be when
|
||||
* a draw completes, and draw that instead of where we are now. In this variation, when our panning
|
||||
* speed drops below a certain threshold, we draw 9 viewports' worth of content so that the user can
|
||||
* pan in any direction without encountering checkerboarding.
|
||||
* Once the user is panning, we modify the displayport to encompass an area range of where we think
|
||||
* the user will be when the draw completes. This heuristic relies on both the estimated draw time
|
||||
* the panning velocity; unexpected changes in either of these values will cause the heuristic to
|
||||
* fail and show checkerboard.
|
||||
*/
|
||||
private static class PredictionBiasStrategy extends DisplayPortStrategy {
|
||||
private static float VELOCITY_THRESHOLD;
|
||||
|
||||
private int mPixelArea; // area of the viewport, used in draw time calculations
|
||||
private int mMinFramesToDraw; // minimum number of frames we take to draw
|
||||
private int mMaxFramesToDraw; // maximum number of frames we take to draw
|
||||
|
||||
PredictionBiasStrategy(Map<String, Integer> prefs) {
|
||||
VELOCITY_THRESHOLD = GeckoAppShell.getDpi() * getFloatPref(prefs, PREF_DISPLAYPORT_PB_VELOCITY_THRESHOLD, 16);
|
||||
resetPageState();
|
||||
}
|
||||
|
||||
public DisplayPortMetrics calculate(ImmutableViewportMetrics metrics, PointF velocity) {
|
||||
float width = metrics.getWidth();
|
||||
float height = metrics.getHeight();
|
||||
mPixelArea = (int)(width * height);
|
||||
|
||||
if (velocity.length() < VELOCITY_THRESHOLD) {
|
||||
// if we're going slow, expand the displayport to 9x viewport size
|
||||
RectF margins = new RectF(width, height, width, height);
|
||||
return getTileAlignedDisplayPortMetrics(margins, metrics.zoomFactor, metrics);
|
||||
}
|
||||
|
||||
// figure out how far we expect to be
|
||||
float minDx = velocity.x * mMinFramesToDraw;
|
||||
float minDy = velocity.y * mMinFramesToDraw;
|
||||
float maxDx = velocity.x * mMaxFramesToDraw;
|
||||
float maxDy = velocity.y * mMaxFramesToDraw;
|
||||
|
||||
// figure out how many pixels we will be drawing when we draw the above-calculated range.
|
||||
// this will be larger than the viewport area.
|
||||
float pixelsToDraw = (width + Math.abs(maxDx - minDx)) * (height + Math.abs(maxDy - minDy));
|
||||
// adjust how far we will get because of the time spent drawing all these extra pixels. this
|
||||
// will again increase the number of pixels drawn so really we could keep iterating this over
|
||||
// and over, but once seems enough for now.
|
||||
maxDx = maxDx * pixelsToDraw / mPixelArea;
|
||||
maxDy = maxDy * pixelsToDraw / mPixelArea;
|
||||
|
||||
// and finally generate the displayport. the min/max stuff takes care of
|
||||
// negative velocities as well as positive.
|
||||
RectF margins = new RectF(
|
||||
-Math.min(minDx, maxDx),
|
||||
-Math.min(minDy, maxDy),
|
||||
Math.max(minDx, maxDx),
|
||||
Math.max(minDy, maxDy));
|
||||
return getTileAlignedDisplayPortMetrics(margins, metrics.zoomFactor, metrics);
|
||||
}
|
||||
|
||||
public boolean aboutToCheckerboard(ImmutableViewportMetrics metrics, PointF velocity, DisplayPortMetrics displayPort) {
|
||||
// the code below is the same as in calculate() but is awkward to refactor since it has multiple outputs.
|
||||
// refer to the comments in calculate() to understand what this is doing.
|
||||
float minDx = velocity.x * mMinFramesToDraw;
|
||||
float minDy = velocity.y * mMinFramesToDraw;
|
||||
float maxDx = velocity.x * mMaxFramesToDraw;
|
||||
float maxDy = velocity.y * mMaxFramesToDraw;
|
||||
float pixelsToDraw = (metrics.getWidth() + Math.abs(maxDx - minDx)) * (metrics.getHeight() + Math.abs(maxDy - minDy));
|
||||
maxDx = maxDx * pixelsToDraw / mPixelArea;
|
||||
maxDy = maxDy * pixelsToDraw / mPixelArea;
|
||||
|
||||
// now that we have an idea of how far we will be when the draw completes, take the farthest
|
||||
// end of that range and see if it falls outside the displayport bounds. if it does, allow
|
||||
// the draw to go through
|
||||
RectF predictedViewport = metrics.getViewport();
|
||||
predictedViewport.left += maxDx;
|
||||
predictedViewport.top += maxDy;
|
||||
predictedViewport.right += maxDx;
|
||||
predictedViewport.bottom += maxDy;
|
||||
|
||||
predictedViewport = clampToPageBounds(predictedViewport, metrics);
|
||||
return !displayPort.contains(predictedViewport);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean drawTimeUpdate(long millis, int pixels) {
|
||||
// calculate the number of frames it took to draw a viewport-sized area
|
||||
float normalizedTime = (float)mPixelArea * (float)millis / (float)pixels;
|
||||
int normalizedFrames = (int)FloatMath.ceil(normalizedTime * 60f / 1000f);
|
||||
// broaden our range on how long it takes to draw if the draw falls outside
|
||||
// the range. this allows it to grow gradually. this heuristic may need to
|
||||
// be tweaked into more of a floating window average or something.
|
||||
if (normalizedFrames <= mMinFramesToDraw) {
|
||||
mMinFramesToDraw--;
|
||||
} else if (normalizedFrames > mMaxFramesToDraw) {
|
||||
mMaxFramesToDraw++;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
Log.d(LOGTAG, "Widened draw range to [" + mMinFramesToDraw + ", " + mMaxFramesToDraw + "]");
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resetPageState() {
|
||||
mMinFramesToDraw = 0;
|
||||
mMaxFramesToDraw = 2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "PredictionBiasStrategy threshold=" + VELOCITY_THRESHOLD;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
package org.mozilla.gecko.gfx;
|
||||
|
||||
import android.graphics.RectF;
|
||||
import org.mozilla.gecko.FloatUtils;
|
||||
|
||||
/*
|
||||
* This class keeps track of the area we request Gecko to paint, as well
|
||||
|
@ -32,6 +33,11 @@ public final class DisplayPortMetrics {
|
|||
return mPosition.contains(rect);
|
||||
}
|
||||
|
||||
public boolean fuzzyEquals(DisplayPortMetrics metrics) {
|
||||
return RectUtils.fuzzyEquals(mPosition, metrics.mPosition)
|
||||
&& FloatUtils.fuzzyEquals(mResolution, metrics.mResolution);
|
||||
}
|
||||
|
||||
public String toJSON() {
|
||||
StringBuffer sb = new StringBuffer(256);
|
||||
sb.append("{ \"left\": ").append(mPosition.left)
|
||||
|
|
|
@ -0,0 +1,95 @@
|
|||
/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
package org.mozilla.gecko.gfx;
|
||||
|
||||
import android.os.SystemClock;
|
||||
|
||||
/**
|
||||
* A custom-built data structure to assist with measuring draw times.
|
||||
*
|
||||
* This class maintains a fixed-size circular buffer of DisplayPortMetrics
|
||||
* objects and associated timestamps. It provides only three operations, which
|
||||
* is all we require for our purposes of measuring draw times. Note
|
||||
* in particular that the class is designed so that even though it is
|
||||
* accessed from multiple threads, it does not require synchronization;
|
||||
* any concurrency errors that result from this are handled gracefully.
|
||||
*
|
||||
* Assuming an unrolled buffer so that mTail is greater than mHead, the data
|
||||
* stored in the buffer at entries [mHead, mTail) will never be modified, and
|
||||
* so are "safe" to read. If this reading is done on the same thread that
|
||||
* owns mHead, then reading the range [mHead, mTail) is guaranteed to be safe
|
||||
* since the range itself will not shrink.
|
||||
*/
|
||||
final class DrawTimingQueue {
|
||||
private static final String LOGTAG = "GeckoDrawTimingQueue";
|
||||
private static final int BUFFER_SIZE = 16;
|
||||
|
||||
private final DisplayPortMetrics[] mMetrics;
|
||||
private final long[] mTimestamps;
|
||||
|
||||
private int mHead;
|
||||
private int mTail;
|
||||
|
||||
DrawTimingQueue() {
|
||||
mMetrics = new DisplayPortMetrics[BUFFER_SIZE];
|
||||
mTimestamps = new long[BUFFER_SIZE];
|
||||
mHead = BUFFER_SIZE - 1;
|
||||
mTail = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a new entry to the tail of the queue. If the buffer is full,
|
||||
* do nothing. This must only be called from the Java UI thread.
|
||||
*/
|
||||
boolean add(DisplayPortMetrics metrics) {
|
||||
if (mHead == mTail) {
|
||||
return false;
|
||||
}
|
||||
mMetrics[mTail] = metrics;
|
||||
mTimestamps[mTail] = SystemClock.uptimeMillis();
|
||||
mTail = (mTail + 1) % BUFFER_SIZE;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the timestamp associated with the given metrics, AND remove
|
||||
* all metrics objects from the start of the queue up to and including
|
||||
* the one provided. Note that because of draw coalescing, the metrics
|
||||
* object passed in here may not be the one at the head of the queue,
|
||||
* and so we must iterate our way through the list to find it.
|
||||
* This must only be called from the compositor thread.
|
||||
*/
|
||||
long findTimeFor(DisplayPortMetrics metrics) {
|
||||
// keep a copy of the tail pointer so that we ignore new items
|
||||
// added to the queue while we are searching. this is fine because
|
||||
// the one we are looking for will either have been added already
|
||||
// or will not be in the queue at all.
|
||||
int tail = mTail;
|
||||
// walk through the "safe" range from mHead to tail; these entries
|
||||
// will not be modified unless we change mHead.
|
||||
int i = (mHead + 1) % BUFFER_SIZE;
|
||||
while (i != tail) {
|
||||
if (mMetrics[i].fuzzyEquals(metrics)) {
|
||||
// found it, copy out the timestamp to a local var BEFORE
|
||||
// changing mHead or add could clobber the timestamp.
|
||||
long timestamp = mTimestamps[i];
|
||||
mHead = i;
|
||||
return timestamp;
|
||||
}
|
||||
i = (i + 1) % BUFFER_SIZE;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the buffer to empty.
|
||||
* This must only be called from the compositor thread.
|
||||
*/
|
||||
void reset() {
|
||||
// we can only modify mHead on this thread.
|
||||
mHead = (mTail + BUFFER_SIZE - 1) % BUFFER_SIZE;
|
||||
}
|
||||
}
|
|
@ -74,6 +74,9 @@ public class GeckoLayerClient implements GeckoEventResponder,
|
|||
private DisplayPortMetrics mDisplayPort;
|
||||
private DisplayPortMetrics mReturnDisplayPort;
|
||||
|
||||
private boolean mRecordDrawTimes;
|
||||
private DrawTimingQueue mDrawTimingQueue;
|
||||
|
||||
private VirtualLayer mRootLayer;
|
||||
|
||||
/* The Gecko viewport as per the UI thread. Must be touched only on the UI thread. */
|
||||
|
@ -99,6 +102,8 @@ public class GeckoLayerClient implements GeckoEventResponder,
|
|||
mScreenSize = new IntSize(0, 0);
|
||||
mWindowSize = new IntSize(0, 0);
|
||||
mDisplayPort = new DisplayPortMetrics();
|
||||
mRecordDrawTimes = true;
|
||||
mDrawTimingQueue = new DrawTimingQueue();
|
||||
mCurrentViewTransform = new ViewTransform(0, 0, 1);
|
||||
}
|
||||
|
||||
|
@ -193,6 +198,10 @@ public class GeckoLayerClient implements GeckoEventResponder,
|
|||
mDisplayPort = displayPort;
|
||||
mGeckoViewport = clampedMetrics;
|
||||
|
||||
if (mRecordDrawTimes) {
|
||||
mDrawTimingQueue.add(displayPort);
|
||||
}
|
||||
|
||||
GeckoAppShell.sendEventToGecko(GeckoEvent.createViewportEvent(clampedMetrics, displayPort));
|
||||
}
|
||||
|
||||
|
@ -342,6 +351,8 @@ public class GeckoLayerClient implements GeckoEventResponder,
|
|||
mLayerController.abortPanZoomAnimation();
|
||||
mLayerController.getView().setPaintState(LayerView.PAINT_BEFORE_FIRST);
|
||||
}
|
||||
DisplayPortCalculator.resetPageState();
|
||||
mDrawTimingQueue.reset();
|
||||
mLayerController.getView().getRenderer().resetCheckerboard();
|
||||
GeckoAppShell.screenshotWholePage(Tabs.getInstance().getSelectedTab());
|
||||
}
|
||||
|
@ -393,6 +404,19 @@ public class GeckoLayerClient implements GeckoEventResponder,
|
|||
|
||||
mRootLayer.setPositionAndResolution(x, y, x + width, y + height, resolution);
|
||||
|
||||
if (layersUpdated && mRecordDrawTimes) {
|
||||
// If we got a layers update, that means a draw finished. Check to see if the area drawn matches
|
||||
// one of our requested displayports; if it does calculate the draw time and notify the
|
||||
// DisplayPortCalculator
|
||||
DisplayPortMetrics drawn = new DisplayPortMetrics(x, y, x + width, y + height, resolution);
|
||||
long time = mDrawTimingQueue.findTimeFor(drawn);
|
||||
if (time >= 0) {
|
||||
long now = SystemClock.uptimeMillis();
|
||||
time = now - time;
|
||||
mRecordDrawTimes = DisplayPortCalculator.drawTimeUpdate(time, width * height);
|
||||
}
|
||||
}
|
||||
|
||||
if (layersUpdated && mDrawListener != null) {
|
||||
/* Used by robocop for testing purposes */
|
||||
mDrawListener.drawFinished();
|
||||
|
|
|
@ -103,6 +103,7 @@ XPIDLSRCS = \
|
|||
nsITransport.idl \
|
||||
nsISocketTransport.idl \
|
||||
nsISocketTransportService.idl \
|
||||
nsISpeculativeConnect.idl \
|
||||
nsIServerSocket.idl \
|
||||
nsIResumableChannel.idl \
|
||||
nsIRequestObserverProxy.idl \
|
||||
|
|
|
@ -0,0 +1,69 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* ***** 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.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2012
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Patrick McManus <mcmanus@ducksong.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "nsISupports.idl"
|
||||
|
||||
interface nsIURI;
|
||||
interface nsIInterfaceRequestor;
|
||||
interface nsIEventTarget;
|
||||
|
||||
[scriptable, uuid(b3c53863-1313-480a-90a2-5b0da651ee5e)]
|
||||
interface nsISpeculativeConnect : nsISupports
|
||||
{
|
||||
/**
|
||||
* Called as a hint to indicate a new transaction for the URI is likely coming
|
||||
* soon. The implementer may use this information to start a TCP
|
||||
* and/or SSL level handshake for that resource immediately so that it is
|
||||
* ready and/or progressed when the transaction is actually submitted.
|
||||
*
|
||||
* No obligation is taken on by the implementer, nor is the submitter obligated
|
||||
* to actually open the new channel.
|
||||
*
|
||||
* @param aURI the URI of the hinted transaction
|
||||
* @param aCallbacks any security callbacks for use with SSL for interfaces
|
||||
* such as nsIBadCertListener. May be null.
|
||||
* @param aTarget the thread on which the release of the callbacks will
|
||||
* occur. May be null for "any thread".
|
||||
*
|
||||
*/
|
||||
void speculativeConnect(in nsIURI aURI,
|
||||
in nsIInterfaceRequestor aCallbacks,
|
||||
in nsIEventTarget aTarget);
|
||||
|
||||
};
|
||||
|
|
@ -341,10 +341,11 @@ nsIOService::GetInstance() {
|
|||
return gIOService;
|
||||
}
|
||||
|
||||
NS_IMPL_THREADSAFE_ISUPPORTS5(nsIOService,
|
||||
NS_IMPL_THREADSAFE_ISUPPORTS6(nsIOService,
|
||||
nsIIOService,
|
||||
nsIIOService2,
|
||||
nsINetUtil,
|
||||
nsISpeculativeConnect,
|
||||
nsIObserver,
|
||||
nsISupportsWeakReference)
|
||||
|
||||
|
@ -608,10 +609,47 @@ nsIOService::NewChannelFromURI(nsIURI *aURI, nsIChannel **result)
|
|||
return NewChannelFromURIWithProxyFlags(aURI, nsnull, 0, result);
|
||||
}
|
||||
|
||||
void
|
||||
nsIOService::LookupProxyInfo(nsIURI *aURI,
|
||||
nsIURI *aProxyURI,
|
||||
PRUint32 aProxyFlags,
|
||||
nsCString *aScheme,
|
||||
nsIProxyInfo **outPI)
|
||||
{
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIProxyInfo> pi;
|
||||
|
||||
if (!mProxyService) {
|
||||
mProxyService = do_GetService(NS_PROTOCOLPROXYSERVICE_CONTRACTID);
|
||||
if (!mProxyService)
|
||||
NS_WARNING("failed to get protocol proxy service");
|
||||
}
|
||||
if (mProxyService) {
|
||||
PRUint32 flags = 0;
|
||||
if (aScheme->EqualsLiteral("http") || aScheme->EqualsLiteral("https"))
|
||||
flags = nsIProtocolProxyService::RESOLVE_NON_BLOCKING;
|
||||
rv = mProxyService->Resolve(aProxyURI ? aProxyURI : aURI, aProxyFlags,
|
||||
getter_AddRefs(pi));
|
||||
if (rv == NS_BASE_STREAM_WOULD_BLOCK) {
|
||||
// Use an UNKNOWN proxy to defer resolution and avoid blocking.
|
||||
rv = mProxyService->NewProxyInfo(NS_LITERAL_CSTRING("unknown"),
|
||||
NS_LITERAL_CSTRING(""),
|
||||
-1, 0, 0, nsnull,
|
||||
getter_AddRefs(pi));
|
||||
}
|
||||
if (NS_FAILED(rv))
|
||||
pi = nsnull;
|
||||
}
|
||||
*outPI = pi;
|
||||
if (pi)
|
||||
pi.forget();
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsIOService::NewChannelFromURIWithProxyFlags(nsIURI *aURI,
|
||||
nsIURI *aProxyURI,
|
||||
PRUint32 proxyFlags,
|
||||
PRUint32 aProxyFlags,
|
||||
nsIChannel **result)
|
||||
{
|
||||
nsresult rv;
|
||||
|
@ -636,27 +674,7 @@ nsIOService::NewChannelFromURIWithProxyFlags(nsIURI *aURI,
|
|||
// skip this step. This allows us to lazily load the PPS at startup.
|
||||
if (protoFlags & nsIProtocolHandler::ALLOWS_PROXY) {
|
||||
nsCOMPtr<nsIProxyInfo> pi;
|
||||
if (!mProxyService) {
|
||||
mProxyService = do_GetService(NS_PROTOCOLPROXYSERVICE_CONTRACTID);
|
||||
if (!mProxyService)
|
||||
NS_WARNING("failed to get protocol proxy service");
|
||||
}
|
||||
if (mProxyService) {
|
||||
PRUint32 flags = 0;
|
||||
if (scheme.EqualsLiteral("http") || scheme.EqualsLiteral("https"))
|
||||
flags = nsIProtocolProxyService::RESOLVE_NON_BLOCKING;
|
||||
rv = mProxyService->Resolve(aProxyURI ? aProxyURI : aURI, proxyFlags,
|
||||
getter_AddRefs(pi));
|
||||
if (rv == NS_BASE_STREAM_WOULD_BLOCK) {
|
||||
// Use an UNKNOWN proxy to defer resolution and avoid blocking.
|
||||
rv = mProxyService->NewProxyInfo(NS_LITERAL_CSTRING("unknown"),
|
||||
NS_LITERAL_CSTRING(""),
|
||||
-1, 0, 0, nsnull,
|
||||
getter_AddRefs(pi));
|
||||
}
|
||||
if (NS_FAILED(rv))
|
||||
pi = nsnull;
|
||||
}
|
||||
LookupProxyInfo(aURI, aProxyURI, aProxyFlags, &scheme, getter_AddRefs(pi));
|
||||
if (pi) {
|
||||
nsCAutoString type;
|
||||
if (NS_SUCCEEDED(pi->GetType(type)) && type.EqualsLiteral("http")) {
|
||||
|
@ -1236,3 +1254,37 @@ nsIOService::ExtractCharsetFromContentType(const nsACString &aTypeHeader,
|
|||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// nsISpeculativeConnect
|
||||
NS_IMETHODIMP
|
||||
nsIOService::SpeculativeConnect(nsIURI *aURI,
|
||||
nsIInterfaceRequestor *aCallbacks,
|
||||
nsIEventTarget *aTarget)
|
||||
{
|
||||
nsCAutoString scheme;
|
||||
nsresult rv = aURI->GetScheme(scheme);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
// Check for proxy information. If there is a proxy configured then a
|
||||
// speculative connect should not be performed because the potential
|
||||
// reward is slim with tcp peers closely located to the browser.
|
||||
nsCOMPtr<nsIProxyInfo> pi;
|
||||
LookupProxyInfo(aURI, nsnull, 0, &scheme, getter_AddRefs(pi));
|
||||
if (pi)
|
||||
return NS_OK;
|
||||
|
||||
nsCOMPtr<nsIProtocolHandler> handler;
|
||||
rv = GetProtocolHandler(scheme.get(), getter_AddRefs(handler));
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
nsCOMPtr<nsISpeculativeConnect> speculativeHandler =
|
||||
do_QueryInterface(handler);
|
||||
if (!handler)
|
||||
return NS_OK;
|
||||
|
||||
return speculativeHandler->SpeculativeConnect(aURI,
|
||||
aCallbacks,
|
||||
aTarget);
|
||||
}
|
||||
|
|
|
@ -58,6 +58,7 @@
|
|||
#include "nsCategoryCache.h"
|
||||
#include "nsINetworkLinkService.h"
|
||||
#include "nsAsyncRedirectVerifyHelper.h"
|
||||
#include "nsISpeculativeConnect.h"
|
||||
|
||||
#define NS_N(x) (sizeof(x)/sizeof(*x))
|
||||
|
||||
|
@ -74,6 +75,7 @@ class nsIPrefBranch;
|
|||
class nsIOService : public nsIIOService2
|
||||
, public nsIObserver
|
||||
, public nsINetUtil
|
||||
, public nsISpeculativeConnect
|
||||
, public nsSupportsWeakReference
|
||||
{
|
||||
public:
|
||||
|
@ -82,6 +84,7 @@ public:
|
|||
NS_DECL_NSIIOSERVICE2
|
||||
NS_DECL_NSIOBSERVER
|
||||
NS_DECL_NSINETUTIL
|
||||
NS_DECL_NSISPECULATIVECONNECT
|
||||
|
||||
// Gets the singleton instance of the IO Service, creating it as needed
|
||||
// Returns nsnull on out of memory or failure to initialize.
|
||||
|
@ -135,6 +138,10 @@ private:
|
|||
nsresult InitializeSocketTransportService();
|
||||
nsresult InitializeNetworkLinkService();
|
||||
|
||||
// consolidated helper function
|
||||
void LookupProxyInfo(nsIURI *aURI, nsIURI *aProxyURI, PRUint32 aProxyFlags,
|
||||
nsCString *aScheme, nsIProxyInfo **outPI);
|
||||
|
||||
private:
|
||||
bool mOffline;
|
||||
bool mOfflineForProfileChange;
|
||||
|
|
|
@ -112,6 +112,7 @@ CPPSRCS = \
|
|||
HttpChannelParentListener.cpp \
|
||||
SpdySession.cpp \
|
||||
SpdyStream.cpp \
|
||||
NullHttpTransaction.cpp \
|
||||
$(NULL)
|
||||
|
||||
LOCAL_INCLUDES = \
|
||||
|
|
|
@ -0,0 +1,223 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set sw=2 ts=8 et tw=80 : */
|
||||
/* ***** 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.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2012
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Patrick McManus <mcmanus@ducksong.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "nsHttp.h"
|
||||
#include "NullHttpTransaction.h"
|
||||
#include "nsProxyRelease.h"
|
||||
#include "nsHttpHandler.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace net {
|
||||
|
||||
NS_IMPL_THREADSAFE_ISUPPORTS0(NullHttpTransaction);
|
||||
|
||||
NullHttpTransaction::NullHttpTransaction(nsHttpConnectionInfo *ci,
|
||||
nsIInterfaceRequestor *callbacks,
|
||||
nsIEventTarget *target,
|
||||
PRUint8 caps)
|
||||
: mStatus(NS_OK)
|
||||
, mCaps(caps)
|
||||
, mCallbacks(callbacks)
|
||||
, mEventTarget(target)
|
||||
, mConnectionInfo(ci)
|
||||
, mRequestHead(nsnull)
|
||||
{
|
||||
}
|
||||
|
||||
NullHttpTransaction::~NullHttpTransaction()
|
||||
{
|
||||
if (mCallbacks) {
|
||||
nsIInterfaceRequestor *cbs = nsnull;
|
||||
mCallbacks.swap(cbs);
|
||||
NS_ProxyRelease(mEventTarget, cbs);
|
||||
}
|
||||
delete mRequestHead;
|
||||
}
|
||||
|
||||
void
|
||||
NullHttpTransaction::SetConnection(nsAHttpConnection *conn)
|
||||
{
|
||||
mConnection = conn;
|
||||
}
|
||||
|
||||
nsAHttpConnection *
|
||||
NullHttpTransaction::Connection()
|
||||
{
|
||||
return mConnection.get();
|
||||
}
|
||||
|
||||
void
|
||||
NullHttpTransaction::GetSecurityCallbacks(nsIInterfaceRequestor **outCB,
|
||||
nsIEventTarget **outTarget)
|
||||
{
|
||||
nsCOMPtr<nsIInterfaceRequestor> copyCB(mCallbacks);
|
||||
*outCB = copyCB;
|
||||
copyCB.forget();
|
||||
|
||||
if (outTarget) {
|
||||
nsCOMPtr<nsIEventTarget> copyET(mEventTarget);
|
||||
*outTarget = copyET;
|
||||
copyET.forget();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
NullHttpTransaction::OnTransportStatus(nsITransport* transport,
|
||||
nsresult status, PRUint64 progress)
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
NullHttpTransaction::IsDone()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
nsresult
|
||||
NullHttpTransaction::Status()
|
||||
{
|
||||
return mStatus;
|
||||
}
|
||||
|
||||
PRUint8
|
||||
NullHttpTransaction::Caps()
|
||||
{
|
||||
return mCaps;
|
||||
}
|
||||
|
||||
PRUint32
|
||||
NullHttpTransaction::Available()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
nsresult
|
||||
NullHttpTransaction::ReadSegments(nsAHttpSegmentReader *reader,
|
||||
PRUint32 count, PRUint32 *countRead)
|
||||
{
|
||||
*countRead = 0;
|
||||
return NS_BASE_STREAM_CLOSED;
|
||||
}
|
||||
|
||||
nsresult
|
||||
NullHttpTransaction::WriteSegments(nsAHttpSegmentWriter *writer,
|
||||
PRUint32 count, PRUint32 *countWritten)
|
||||
{
|
||||
*countWritten = 0;
|
||||
return NS_BASE_STREAM_CLOSED;
|
||||
}
|
||||
|
||||
PRUint32
|
||||
NullHttpTransaction::Http1xTransactionCount()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
nsHttpRequestHead *
|
||||
NullHttpTransaction::RequestHead()
|
||||
{
|
||||
// We suport a requesthead at all so that a CONNECT tunnel transaction
|
||||
// can obtain a Host header from it, but we lazy-popualate that header.
|
||||
|
||||
if (!mRequestHead) {
|
||||
mRequestHead = new nsHttpRequestHead();
|
||||
|
||||
nsCAutoString hostHeader;
|
||||
nsCString host(mConnectionInfo->GetHost());
|
||||
nsresult rv = nsHttpHandler::GenerateHostPort(host,
|
||||
mConnectionInfo->Port(),
|
||||
hostHeader);
|
||||
if (NS_SUCCEEDED(rv))
|
||||
mRequestHead->SetHeader(nsHttp::Host, hostHeader);
|
||||
|
||||
// CONNECT tunnels may also want Proxy-Authorization but that is a lot
|
||||
// harder to determine, so for now we will let those connections fail in
|
||||
// the NullHttpTransaction and let them be retried from the pending queue
|
||||
// with a bound transcation
|
||||
}
|
||||
|
||||
return mRequestHead;
|
||||
}
|
||||
|
||||
nsresult
|
||||
NullHttpTransaction::TakeSubTransactions(
|
||||
nsTArray<nsRefPtr<nsAHttpTransaction> > &outTransactions)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
void
|
||||
NullHttpTransaction::SetSSLConnectFailed()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
NullHttpTransaction::Close(nsresult reason)
|
||||
{
|
||||
mStatus = reason;
|
||||
mConnection = nsnull;
|
||||
}
|
||||
|
||||
nsresult
|
||||
NullHttpTransaction::AddTransaction(nsAHttpTransaction *trans)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
PRUint32
|
||||
NullHttpTransaction::PipelineDepth()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
nsresult
|
||||
NullHttpTransaction::SetPipelinePosition(PRInt32 position)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
PRInt32
|
||||
NullHttpTransaction::PipelinePosition()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
} // namespace mozilla::net
|
||||
} // namespace mozilla
|
||||
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче