Merge from mozilla-central.

This commit is contained in:
Jan de Mooij 2013-02-15 19:28:19 +01:00
commit 394bc589f0
558 changed files with 10187 additions and 3737 deletions

View File

@ -15,4 +15,4 @@
#
# Note: The description below will be part of the error message shown to users.
#
Bug 755724 - Move browser application in a subdirectory
Bug 836654 - IndexedDB test failures without clobber

View File

@ -9,16 +9,11 @@ VPATH = @srcdir@
LIBRARY_NAME = AccessibleMarshal
MODULE = accessibility
XPIDL_MODULE = accessibility-msaa
GRE_MODULE = 1
DEFFILE = $(win_srcdir)/AccessibleMarshal.def
include $(DEPTH)/config/autoconf.mk
XPIDLSRCS = \
nsIWinAccessNode.idl \
$(NULL)
DEFINES += -DREGISTER_PROXY_DLL
GARBAGE += $(MIDL_GENERATED_FILES) done_gen dlldata.c

View File

@ -1,20 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* 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 "nsISupports.idl"
%{C++
#include "guiddef.h"
%}
[ref] native MSCOMIIDRef(IID);
[uuid(63efe9c5-2610-4d2f-861b-e4ddfe1b70d9)]
interface nsIWinAccessNode : nsISupports
{
voidPtr queryNativeInterface([const] in MSCOMIIDRef aIID);
};

View File

@ -272,6 +272,16 @@ aria::MapToState(EStateRule aRule, dom::Element* aElement, uint64_t* aState)
return true;
}
case eARIAReadonlyOrEditableIfDefined:
{
static const TokenTypeData data(
nsGkAtoms::aria_readonly, eBoolType,
0, states::READONLY, states::EDITABLE);
MapTokenType(aElement, aState, data);
return true;
}
case eARIARequired:
{
static const TokenTypeData data(

View File

@ -39,6 +39,7 @@ enum EStateRule
eARIAPressed,
eARIAReadonly,
eARIAReadonlyOrEditable,
eARIAReadonlyOrEditableIfDefined,
eARIARequired,
eARIASelectable,
eReadonlyUntilEditable,

View File

@ -53,7 +53,7 @@ AccEvent::CreateXPCOMObject()
////////////////////////////////////////////////////////////////////////////////
// AccEvent cycle collection
NS_IMPL_CYCLE_COLLECTION_NATIVE_1(AccEvent, mAccessible)
NS_IMPL_CYCLE_COLLECTION_1(AccEvent, mAccessible)
NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(AccEvent, AddRef)
NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(AccEvent, Release)

View File

@ -178,7 +178,7 @@ static nsRoleMapEntry sWAIRoleMaps[] =
eSelect | eTable,
states::FOCUSABLE,
eARIAMultiSelectable,
eARIAReadonly
eARIAReadonlyOrEditable
},
{ // gridcell
&nsGkAtoms::gridcell,
@ -190,7 +190,7 @@ static nsRoleMapEntry sWAIRoleMaps[] =
eTableCell,
kNoReqStates,
eARIASelectable,
eARIAReadonly
eARIAReadonlyOrEditableIfDefined
},
{ // group
&nsGkAtoms::group,

View File

@ -15,7 +15,6 @@
#include "mozilla/dom/Element.h"
#include "nsIDocShell.h"
#include "nsIDocShellTreeItem.h"
#include "nsIPersistentProperties2.h"
#include "nsIPresShell.h"
#include "nsPoint.h"

View File

@ -11,7 +11,6 @@
#include "RootAccessible.h"
#include "nsIDocShell.h"
#include "nsIDocShellTreeItem.h"
#include "nsIDOMWindow.h"
#include "nsIFrame.h"
#include "nsIInterfaceRequestorUtils.h"
@ -82,14 +81,13 @@ nsAccessNode::Shutdown()
RootAccessible*
nsAccessNode::RootAccessible() const
{
nsCOMPtr<nsIDocShellTreeItem> docShellTreeItem =
nsCoreUtils::GetDocShellTreeItemFor(GetNode());
NS_ASSERTION(docShellTreeItem, "No docshell tree item for mContent");
if (!docShellTreeItem) {
nsCOMPtr<nsIDocShell> docShell = nsCoreUtils::GetDocShellFor(GetNode());
NS_ASSERTION(docShell, "No docshell for mContent");
if (!docShell) {
return nullptr;
}
nsCOMPtr<nsIDocShellTreeItem> root;
docShellTreeItem->GetRootTreeItem(getter_AddRefs(root));
docShell->GetRootTreeItem(getter_AddRefs(root));
NS_ASSERTION(root, "No root content tree item");
if (!root) {
return nullptr;

View File

@ -38,7 +38,6 @@
#include "mozilla/dom/Element.h"
#include "nsITreeBoxObject.h"
#include "nsIDocShellTreeItem.h"
#include "nsITreeColumns.h"
////////////////////////////////////////////////////////////////////////////////
@ -380,7 +379,7 @@ nsIntPoint
nsCoreUtils::GetScreenCoordsForWindow(nsINode *aNode)
{
nsIntPoint coords(0, 0);
nsCOMPtr<nsIDocShellTreeItem> treeItem(GetDocShellTreeItemFor(aNode));
nsCOMPtr<nsIDocShellTreeItem> treeItem(GetDocShellFor(aNode));
if (!treeItem)
return coords;
@ -396,18 +395,15 @@ nsCoreUtils::GetScreenCoordsForWindow(nsINode *aNode)
return coords;
}
already_AddRefed<nsIDocShellTreeItem>
nsCoreUtils::GetDocShellTreeItemFor(nsINode *aNode)
already_AddRefed<nsIDocShell>
nsCoreUtils::GetDocShellFor(nsINode *aNode)
{
if (!aNode)
return nullptr;
nsCOMPtr<nsISupports> container = aNode->OwnerDoc()->GetContainer();
nsIDocShellTreeItem *docShellTreeItem = nullptr;
if (container)
CallQueryInterface(container, &docShellTreeItem);
return docShellTreeItem;
nsCOMPtr<nsIDocShell> docShell = do_QueryInterface(container);
return docShell.forget();
}
bool

View File

@ -17,7 +17,7 @@
class nsRange;
class nsIFrame;
class nsIDocShellTreeItem;
class nsIDocShell;
class nsITreeColumn;
class nsITreeBoxObject;
class nsIWidget;
@ -176,10 +176,9 @@ public:
static nsIntPoint GetScreenCoordsForWindow(nsINode *aNode);
/**
* Return document shell tree item for the given DOM node.
* Return document shell for the given DOM node.
*/
static already_AddRefed<nsIDocShellTreeItem>
GetDocShellTreeItemFor(nsINode *aNode);
static already_AddRefed<nsIDocShell> GetDocShellFor(nsINode *aNode);
/**
* Return true if the given document is root document.

View File

@ -48,6 +48,19 @@ nsTextEquivUtils::GetNameFromSubtree(Accessible* aAccessible,
return NS_OK;
}
void
nsTextEquivUtils::GetTextEquivFromSubtree(Accessible* aAccessible,
nsString& aTextEquiv)
{
aTextEquiv.Truncate();
uint32_t nameRule = GetRoleRule(aAccessible->Role());
if (nameRule & eNameFromSubtreeIfReqRule) {
AppendFromAccessibleChildren(aAccessible, &aTextEquiv);
aTextEquiv.CompressWhitespace();
}
}
nsresult
nsTextEquivUtils::GetTextEquivFromIDRefs(Accessible* aAccessible,
nsIAtom *aIDRefsAttr,

View File

@ -53,6 +53,14 @@ public:
static nsresult GetNameFromSubtree(Accessible* aAccessible,
nsAString& aName);
/**
* Calculates text equivalent from the subtree. Similar to GetNameFromSubtree.
* The difference it returns not empty result for things like HTML p, i.e.
* if the role has eNameFromSubtreeIfReq rule.
*/
static void GetTextEquivFromSubtree(Accessible* aAccessible,
nsString& aTextEquiv);
/**
* Calculates text equivalent for the given accessible from its IDRefs
* attribute (like aria-labelledby or aria-describedby).

View File

@ -22,6 +22,8 @@
#include "RootAccessible.h"
#include "States.h"
#include "StyleInfo.h"
#include "TableAccessible.h"
#include "TableCellAccessible.h"
#include "TreeWalker.h"
#include "nsContentUtils.h"
@ -1597,6 +1599,22 @@ Accessible::ApplyARIAState(uint64_t* aState) const
if (aria::MapToState(mRoleMapEntry->attributeMap1, element, aState) &&
aria::MapToState(mRoleMapEntry->attributeMap2, element, aState))
aria::MapToState(mRoleMapEntry->attributeMap3, element, aState);
// ARIA gridcell inherits editable/readonly states from the grid until it's
// overridden.
if (mRoleMapEntry->Is(nsGkAtoms::gridcell) &&
!(*aState & (states::READONLY | states::EDITABLE))) {
const TableCellAccessible* cell = AsTableCell();
if (cell) {
TableAccessible* table = cell->Table();
if (table) {
Accessible* grid = table->AsAccessible();
uint64_t gridState = 0;
grid->ApplyARIAState(&gridState);
*aState |= (gridState & (states::READONLY | states::EDITABLE));
}
}
}
}
NS_IMETHODIMP
@ -1652,7 +1670,7 @@ Accessible::Value(nsString& aValue)
}
if (option)
nsTextEquivUtils::GetNameFromSubtree(option, aValue);
nsTextEquivUtils::GetTextEquivFromSubtree(option, aValue);
}
}

View File

@ -514,6 +514,8 @@ public:
virtual TableAccessible* AsTable() { return nullptr; }
virtual TableCellAccessible* AsTableCell() { return nullptr; }
const TableCellAccessible* AsTableCell() const
{ return const_cast<Accessible*>(this)->AsTableCell(); }
bool IsTableRow() const { return HasGenericType(eTableRow); }

View File

@ -18,7 +18,6 @@
#include "nsIMutableArray.h"
#include "nsICommandManager.h"
#include "nsIDocShell.h"
#include "nsIDocShellTreeItem.h"
#include "nsIDocument.h"
#include "nsIDOMAttr.h"
#include "nsIDOMCharacterData.h"
@ -185,14 +184,13 @@ DocAccessible::Name(nsString& aName)
role
DocAccessible::NativeRole()
{
nsCOMPtr<nsIDocShellTreeItem> docShellTreeItem =
nsCoreUtils::GetDocShellTreeItemFor(mDocumentNode);
if (docShellTreeItem) {
nsCOMPtr<nsIDocShell> docShell = nsCoreUtils::GetDocShellFor(mDocumentNode);
if (docShell) {
nsCOMPtr<nsIDocShellTreeItem> sameTypeRoot;
docShellTreeItem->GetSameTypeRootTreeItem(getter_AddRefs(sameTypeRoot));
docShell->GetSameTypeRootTreeItem(getter_AddRefs(sameTypeRoot));
int32_t itemType;
docShellTreeItem->GetItemType(&itemType);
if (sameTypeRoot == docShellTreeItem) {
docShell->GetItemType(&itemType);
if (sameTypeRoot == docShell) {
// Root of content or chrome tree
if (itemType == nsIDocShellTreeItem::typeChrome)
return roles::CHROME_WINDOW;

View File

@ -1482,9 +1482,8 @@ HyperTextAccessible::GetEditor() const
return nullptr;
}
nsCOMPtr<nsIDocShellTreeItem> docShellTreeItem =
nsCoreUtils::GetDocShellTreeItemFor(mContent);
nsCOMPtr<nsIEditingSession> editingSession(do_GetInterface(docShellTreeItem));
nsCOMPtr<nsIDocShell> docShell = nsCoreUtils::GetDocShellFor(mContent);
nsCOMPtr<nsIEditingSession> editingSession(do_GetInterface(docShell));
if (!editingSession)
return nullptr; // No editing session interface

View File

@ -108,11 +108,10 @@ RootAccessible::GetChromeFlags()
// Return the flag set for the top level window as defined
// by nsIWebBrowserChrome::CHROME_WINDOW_[FLAGNAME]
// Not simple: nsIXULWindow is not just a QI from nsIDOMWindow
nsCOMPtr<nsIDocShellTreeItem> treeItem =
nsCoreUtils::GetDocShellTreeItemFor(mDocumentNode);
NS_ENSURE_TRUE(treeItem, 0);
nsCOMPtr<nsIDocShell> docShell = nsCoreUtils::GetDocShellFor(mDocumentNode);
NS_ENSURE_TRUE(docShell, 0);
nsCOMPtr<nsIDocShellTreeOwner> treeOwner;
treeItem->GetTreeOwner(getter_AddRefs(treeOwner));
docShell->GetTreeOwner(getter_AddRefs(treeOwner));
NS_ENSURE_TRUE(treeOwner, 0);
nsCOMPtr<nsIXULWindow> xulWin(do_GetInterface(treeOwner));
if (!xulWin) {

View File

@ -45,18 +45,7 @@ nsAccessNodeWrap::~nsAccessNodeWrap()
// nsISupports methods
//-----------------------------------------------------
NS_IMPL_ISUPPORTS_INHERITED1(nsAccessNodeWrap, nsAccessNode, nsIWinAccessNode)
//-----------------------------------------------------
// nsIWinAccessNode methods
//-----------------------------------------------------
NS_IMETHODIMP
nsAccessNodeWrap::QueryNativeInterface(REFIID aIID, void** aInstancePtr)
{
// XXX Wrong for E_NOINTERFACE
return static_cast<nsresult>(QueryInterface(aIID, aInstancePtr));
}
NS_IMPL_ISUPPORTS_INHERITED0(nsAccessNodeWrap, nsAccessNode)
STDMETHODIMP nsAccessNodeWrap::QueryInterface(REFIID iid, void** ppv)
{
@ -88,15 +77,14 @@ nsAccessNodeWrap::QueryService(REFGUID guidService, REFIID iid, void** ppv)
if (iid != IID_IAccessible)
return E_NOINTERFACE;
nsCOMPtr<nsIDocShellTreeItem> docShellTreeItem =
nsCoreUtils::GetDocShellTreeItemFor(mContent);
if (!docShellTreeItem)
nsCOMPtr<nsIDocShell> docShell = nsCoreUtils::GetDocShellFor(mContent);
if (!docShell)
return E_UNEXPECTED;
// Walk up the parent chain without crossing the boundary at which item
// types change, preventing us from walking up out of tab content.
nsCOMPtr<nsIDocShellTreeItem> root;
docShellTreeItem->GetSameTypeRootTreeItem(getter_AddRefs(root));
docShell->GetSameTypeRootTreeItem(getter_AddRefs(root));
if (!root)
return E_UNEXPECTED;
@ -122,12 +110,12 @@ nsAccessNodeWrap::QueryService(REFGUID guidService, REFIID iid, void** ppv)
// Can get to IAccessibleApplication from any node via QS
if (guidService == IID_IAccessibleApplication ||
(Compatibility::IsJAWS() && iid == IID_IAccessibleApplication)) {
ApplicationAccessible* applicationAcc = ApplicationAcc();
ApplicationAccessibleWrap* applicationAcc =
static_cast<ApplicationAccessibleWrap*>(ApplicationAcc());
if (!applicationAcc)
return E_NOINTERFACE;
nsresult rv = applicationAcc->QueryNativeInterface(iid, ppv);
return NS_SUCCEEDED(rv) ? S_OK : E_NOINTERFACE;
return applicationAcc->QueryInterface(iid, ppv);
}
/**

View File

@ -22,7 +22,6 @@
#include "nsCOMPtr.h"
#include "nsIAccessible.h"
#include "nsIAccessibleEvent.h"
#include "nsIWinAccessNode.h"
#include "nsIDOMElement.h"
#include "nsIContent.h"
#include "nsAccessNode.h"
@ -55,12 +54,10 @@ namespace a11y {
#endif
class nsAccessNodeWrap : public nsAccessNode,
public nsIWinAccessNode,
public IServiceProvider
{
public:
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_NSIWINACCESSNODE
public: // construction, destruction
nsAccessNodeWrap(nsIContent* aContent, DocAccessible* aDoc);

View File

@ -43,59 +43,6 @@ nsWinUtils::GetComputedStyleDeclaration(nsIContent* aContent)
return cssDecl.forget();
}
HRESULT
nsWinUtils::ConvertToIA2Array(nsIArray *aGeckoArray, IUnknown ***aIA2Array,
long *aIA2ArrayLen)
{
*aIA2Array = NULL;
*aIA2ArrayLen = 0;
if (!aGeckoArray)
return S_FALSE;
uint32_t length = 0;
nsresult rv = aGeckoArray->GetLength(&length);
if (NS_FAILED(rv))
return GetHRESULT(rv);
if (length == 0)
return S_FALSE;
*aIA2Array =
static_cast<IUnknown**>(::CoTaskMemAlloc((length) * sizeof(IUnknown*)));
if (!*aIA2Array)
return E_OUTOFMEMORY;
uint32_t idx = 0;
for (; idx < length; ++idx) {
nsCOMPtr<nsIWinAccessNode> winAccessNode =
do_QueryElementAt(aGeckoArray, idx, &rv);
if (NS_FAILED(rv))
break;
void *instancePtr = NULL;
nsresult rv = winAccessNode->QueryNativeInterface(IID_IUnknown,
&instancePtr);
if (NS_FAILED(rv))
break;
(*aIA2Array)[idx] = static_cast<IUnknown*>(instancePtr);
}
if (NS_FAILED(rv)) {
for (uint32_t idx2 = 0; idx2 < idx; idx2++) {
(*aIA2Array)[idx2]->Release();
(*aIA2Array)[idx2] = NULL;
}
::CoTaskMemFree(*aIA2Array);
return GetHRESULT(rv);
}
*aIA2ArrayLen = length;
return S_OK;
}
bool
nsWinUtils::MaybeStartWindowEmulation()
{

View File

@ -30,13 +30,6 @@ public:
static already_AddRefed<nsIDOMCSSStyleDeclaration>
GetComputedStyleDeclaration(nsIContent* aContent);
/**
* Convert nsIArray array of accessible objects to an array of IUnknown*
* objects used in IA2 methods.
*/
static HRESULT ConvertToIA2Array(nsIArray *aCollection,
IUnknown ***aAccessibles, long *aCount);
/**
* Start window emulation if presence of specific AT is detected.
*/

View File

@ -10,7 +10,6 @@
#include "AccessibleHyperlink_i.c"
#include "AccessibleWrap.h"
#include "nsIWinAccessNode.h"
using namespace mozilla::a11y;

View File

@ -45,17 +45,12 @@ ia2AccessibleHypertext::get_hyperlink(long aLinkIndex,
return CO_E_OBJNOTCONNECTED;
Accessible* hyperLink = hyperText->GetLinkAt(aLinkIndex);
nsCOMPtr<nsIWinAccessNode> winAccessNode(do_QueryObject(hyperLink));
if (!winAccessNode)
if (!hyperText)
return E_FAIL;
void *instancePtr = NULL;
nsresult rv = winAccessNode->QueryNativeInterface(IID_IAccessibleHyperlink,
&instancePtr);
if (NS_FAILED(rv))
return E_FAIL;
*aHyperlink = static_cast<IAccessibleHyperlink*>(instancePtr);
*aHyperlink =
static_cast<IAccessibleHyperlink*>(static_cast<AccessibleWrap*>(hyperLink));
(*aHyperlink)->AddRef();
return S_OK;
A11Y_TRYBLOCK_END

View File

@ -163,7 +163,11 @@ ia2AccessibleRelation::get_target(long aTargetIndex, IUnknown **aTarget)
if (aTargetIndex < 0 || (uint32_t)aTargetIndex >= mTargets.Length() || !aTarget)
return E_INVALIDARG;
mTargets[aTargetIndex]->QueryNativeInterface(IID_IUnknown, (void**) aTarget);
AccessibleWrap* target =
static_cast<AccessibleWrap*>(mTargets[aTargetIndex].get());
*aTarget = static_cast<IAccessible*>(target);
(*aTarget)->AddRef();
return S_OK;
A11Y_TRYBLOCK_END

View File

@ -171,6 +171,7 @@
testName("ctrlvalue_scrollbar:input", "foo 5 baz");
testName("ctrlvalue_slider:input", "foo 5 baz");
testName("ctrlvalue_spinbutton:input", "foo 5 baz");
testName("ctrlvalue_combobox:input", "foo 5 baz");
/////////////////////////////////////////////////////////////////////////
@ -270,6 +271,11 @@
title="Text is jammed with control's text in name computation">
Bug 823927
</a>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=835666"
title="ARIA combobox selected value is not a part of name computation">
Bug 835666
</a>
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test">
@ -505,6 +511,20 @@
baz
</label>
<input type="checkbox" id="ctrlvalue_combobox:input">
<label for="ctrlvalue_combobox:input">
foo
<div role="combobox">
<div role="textbox"></div>
<ul role="listbox" style="list-style-type: none;">
<li role="option">1</li>
<li role="option" aria-selected="true">5</li>
<li role="option">3</li>
</ul>
</div>
baz
</label>
<!-- a label with a nested control in the start, middle and end -->
<form>
<!-- at the start (without and with whitespaces) -->

View File

@ -110,6 +110,20 @@
// aria-readonly
testStates("aria_readonly_textbox", STATE_READONLY);
// readonly/editable on grid and gridcell
testStates("aria_grid_default", 0, EXT_STATE_EDITABLE,
STATE_READONLY, 0);
testStates("aria_grid_default_cell_readonly", STATE_READONLY, 0,
0, EXT_STATE_EDITABLE);
testStates("aria_grid_default_cell_inherited", 0, EXT_STATE_EDITABLE,
STATE_READONLY, 0);
testStates("aria_grid_readonly", STATE_READONLY, 0,
0, EXT_STATE_EDITABLE);
testStates("aria_grid_readonly_cell_editable", 0, EXT_STATE_EDITABLE,
STATE_READONLY, 0);
testStates("aria_grid_readonly_cell_inherited", STATE_READONLY, 0,
0, EXT_STATE_EDITABLE);
// aria-selectable
testStates("aria_selectable_listitem", STATE_SELECTABLE | STATE_SELECTED);
@ -230,6 +244,11 @@
title="fix default horizontal / vertical state of role=scrollbar and ensure only one of horizontal / vertical states is exposed">
Mozilla Bug 762876
</a>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=835121
title="ARIA grid should be editable by default">
Mozilla Bug 835121
</a>
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test">
@ -265,7 +284,26 @@
<div id="aria_multiline_textbox" role="textbox" aria-multiline="true"></div>
<div id="aria_multiselectable_listbox" role="listbox" aria-multiselectable="true"></div>
<div id="aria_pressed_button" role="button" aria-pressed="true">Button</div>
<div id="aria_readonly_textbox" role="textbox" aria-readonly="true">This text should be readonly</div>
<div id="aria_readonly_textbox"
role="textbox" aria-readonly="true">This text should be readonly</div>
<div id="aria_grid_default" role="grid">
<div role="row">
<div id="aria_grid_default_cell_readonly"
role="gridcell" aria-readonly="true">gridcell1</div>
<div id="aria_grid_default_cell_inherited"
role="gridcell">gridcell2</div>
</div>
<div id="aria_grid_readonly" role="grid" aria-readonly="true">
<div role="row">
<div id="aria_grid_readonly_cell_editable"
role="gridcell" aria-readonly="false">gridcell1</div>
<div id="aria_grid_readonly_cell_inherited"
role="gridcell">gridcell2</div>
</div>
<div role="listbox">
<div id="aria_selectable_listitem" role="option" aria-selected="true">Item1</div>
</div>
@ -313,7 +351,7 @@
<a id="aria_application_link" role="application" href="foo">app</a>
<a id="aria_main_link" role="main" href="foo">main</a>
<a id="aria_navigation_link" role="navigation" href="foo">nav</a>
<!-- landmarks: anchors -->
<a id="aria_application_anchor" role="application" name="app_anchor">app</a>
<a id="aria_main_anchor" role="main" name="main_anchor">main</a>

View File

@ -11,13 +11,9 @@ include $(topsrcdir)/config/config.mk
TEST_DIRS += test
COMMONJS_FILES = \
source/lib/toolkit \
source/lib/sdk \
$(NULL)
COMMONJS_DEST = $(FINAL_TARGET)/modules/commonjs
INSTALL_TARGETS += COMMONJS
libs::
$(PYTHON) $(srcdir)/copy_source.py $(topsrcdir) $(srcdir)/source/lib $(FINAL_TARGET)/modules/commonjs >copy_source.mk
$(MAKE) -f copy_source.mk libs
include $(topsrcdir)/config/rules.mk

46
addon-sdk/copy_source.py Normal file
View File

@ -0,0 +1,46 @@
# 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/.
import os
import sys
if len(sys.argv) != 4:
print >> sys.stderr, "Usage: copy_source.py " \
"<topsrcdir> <source directory> <target directory>"
sys.exit(1)
topsrcdir = sys.argv[1]
source_dir = sys.argv[2]
target_dir = sys.argv[3]
print """
DEPTH = ..
topsrcdir = %(topsrcdir)s
srcdir = %(topsrcdir)s/addon-sdk
VPATH = %(topsrcdir)s/addon-sdk
include $(topsrcdir)/config/config.mk
""" % {'topsrcdir': topsrcdir}
real_source = source_dir.replace('/', os.sep)
if not os.path.exists(real_source):
print >> sys.stderr, "Error: Missing source file %s" % real_source
sys.exit(1)
elif not os.path.isdir(real_source):
print >> sys.stderr, "Error: Source %s is not a directory" % real_source
sys.exit(1)
for dirpath, dirnames, filenames in os.walk(real_source):
if not filenames:
continue
dirpath = dirpath.replace(os.sep, '/')
relative = dirpath[len(source_dir):]
varname = "COMMONJS%s" % relative.replace('/', '_')
print "%s_FILES = \\" % varname
for name in filenames:
print " %s/%s \\" % (dirpath, name)
print " $(NULL)"
print "%s_DEST = %s%s" % (varname, target_dir, relative)
print "INSTALL_TARGETS += %s\n" % varname
print "include $(topsrcdir)/config/rules.mk"

View File

@ -38,8 +38,8 @@ Bugs
* file a bug: https://bugzilla.mozilla.org/enter_bug.cgi?product=Add-on%20SDK
Style Guidelines
--------------------
* https://github.com/mozilla/addon-sdk/wiki/Coding-style-guide
* https://github.com/mozilla/addon-sdk/wiki/Coding-style-guide

View File

@ -18,7 +18,7 @@
<Description>
<em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>
<em:minVersion>18.0</em:minVersion>
<em:maxVersion>21.0a1</em:maxVersion>
<em:maxVersion>20.*</em:maxVersion>
</Description>
</em:targetApplication>

View File

@ -1,7 +1,6 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
module.metadata = {
@ -14,7 +13,7 @@ const { ns } = require("./core/namespace");
const { validateOptions, getTypeOf } = require("./deprecated/api-utils");
const { URL } = require("./url");
const { WindowTracker, browserWindowIterator } = require("./deprecated/window-utils");
const { isBrowser } = require("./window/utils");
const { isBrowser, getInnerId } = require("./window/utils");
const { Ci } = require("chrome");
const { MatchPattern } = require("./page-mod/match-pattern");
const { Worker } = require("./content/worker");
@ -325,11 +324,11 @@ function hasMatchingContext(contexts, popupNode) {
}
// Gets the matched context from any worker for this item. If there is no worker
// or no matched context then returns null.
// or no matched context then returns false.
function getCurrentWorkerContext(item, popupNode) {
let worker = getItemWorkerForWindow(item, popupNode.ownerDocument.defaultView);
if (!worker)
return null;
if (!worker || !worker.anyContextListeners())
return true;
return worker.getMatchedContext(popupNode);
}
@ -346,18 +345,10 @@ function isItemVisible(item, popupNode, defaultVisibility) {
return false;
let context = getCurrentWorkerContext(item, popupNode);
if (typeof(context) === "string")
if (typeof(context) === "string" && context != "")
item.label = context;
return context !== false;
}
// Destroys any item's content scripts workers associated with the given window
function destroyItemWorkerForWindow(item, window) {
let worker = internal(item).workerMap.get(window);
if (worker)
worker.destroy();
internal(item).workerMap.delete(window);
return !!context;
}
// Gets the item's content script worker for a window, creating one if necessary
@ -367,7 +358,8 @@ function getItemWorkerForWindow(item, window) {
if (!item.contentScript && !item.contentScriptFile)
return null;
let worker = internal(item).workerMap.get(window);
let id = getInnerId(window);
let worker = internal(item).workerMap.get(id);
if (worker)
return worker;
@ -380,11 +372,11 @@ function getItemWorkerForWindow(item, window) {
emit(item, "message", msg);
},
onDetach: function() {
destroyItemWorkerForWindow(item, window);
internal(item).workerMap.delete(id);
}
});
internal(item).workerMap.set(window, worker);
internal(item).workerMap.set(id, worker);
return worker;
}
@ -463,8 +455,8 @@ let LabelledItem = Class({
},
destroy: function destroy() {
for (let [window] of internal(this).workerMap)
destroyItemWorkerForWindow(this, window);
for (let [,worker] of internal(this).workerMap)
worker.destroy();
BaseItem.prototype.destroy.call(this);
},
@ -645,6 +637,12 @@ when(function() {
// App specific UI code lives here, it should handle populating the context
// menu and passing clicks etc. through to the items.
function countVisibleItems(nodes) {
return Array.reduce(nodes, function(sum, node) {
return node.hidden ? sum : sum + 1;
}, 0);
}
let MenuWrapper = Class({
initialize: function initialize(winWrapper, items, contextMenu) {
this.winWrapper = winWrapper;
@ -654,11 +652,17 @@ let MenuWrapper = Class({
this.populated = false;
this.menuMap = new Map();
this.contextMenu.addEventListener("popupshowing", this, false);
// updateItemVisibilities will run first, updateOverflowState will run after
// all other instances of this module have run updateItemVisibilities
this._updateItemVisibilities = this.updateItemVisibilities.bind(this);
this.contextMenu.addEventListener("popupshowing", this._updateItemVisibilities, true);
this._updateOverflowState = this.updateOverflowState.bind(this);
this.contextMenu.addEventListener("popupshowing", this._updateOverflowState, false);
},
destroy: function destroy() {
this.contextMenu.removeEventListener("popupshowing", this, false);
this.contextMenu.removeEventListener("popupshowing", this._updateOverflowState, false);
this.contextMenu.removeEventListener("popupshowing", this._updateItemVisibilities, true);
if (!this.populated)
return;
@ -693,7 +697,7 @@ let MenuWrapper = Class({
},
get overflowItems() {
return this.contextMenu.querySelectorAll("." + OVERFLOW_ITEM_CLASS + " > ." + ITEM_CLASS);
return this.contextMenu.querySelectorAll("." + OVERFLOW_ITEM_CLASS);
},
getXULNodeForItem: function getXULNodeForItem(item) {
@ -741,31 +745,11 @@ let MenuWrapper = Class({
let menu = item.parentMenu;
if (menu === this.items) {
// Insert into the overflow popup if it exists, otherwise the normal
// context menu
menupopup = this.overflowPopup;
// If there isn't already an overflow menu then check if we need to
// create one, otherwise use the main context menu
if (!menupopup) {
if (!menupopup)
menupopup = this.contextMenu;
let toplevel = this.topLevelItems;
if (toplevel.length >= MenuManager.overflowThreshold) {
// Create the overflow menu and move everything there
let overflowMenu = this.window.document.createElement("menu");
overflowMenu.setAttribute("class", OVERFLOW_MENU_CLASS);
overflowMenu.setAttribute("label", OVERFLOW_MENU_LABEL);
this.contextMenu.insertBefore(overflowMenu, this.separator.nextSibling);
menupopup = this.window.document.createElement("menupopup");
menupopup.setAttribute("class", OVERFLOW_POPUP_CLASS);
overflowMenu.appendChild(menupopup);
for (let xulNode of toplevel) {
menupopup.appendChild(xulNode);
this.updateXULClass(xulNode);
}
}
}
}
else {
let xulNode = this.getXULNodeForItem(menu);
@ -839,7 +823,7 @@ let MenuWrapper = Class({
xulNode.setAttribute("value", item.data);
let self = this;
xulNode.addEventListener("click", function(event) {
xulNode.addEventListener("command", function(event) {
// Only care about clicks directly on this item
if (event.target !== xulNode)
return;
@ -932,30 +916,18 @@ let MenuWrapper = Class({
}
}
else if (parent == this.overflowPopup) {
// If there are no more items then remove the overflow menu and separator
if (parent.childNodes.length == 0) {
// It's possible that this add-on had all the items in the overflow
// menu and they're now all gone, so remove the separator and overflow
// menu directly
let separator = this.separator;
separator.parentNode.removeChild(separator);
this.contextMenu.removeChild(parent.parentNode);
}
else if (parent.childNodes.length <= MenuManager.overflowThreshold) {
// Otherwise if the overflow menu is empty enough move everything in
// the overflow menu back to top level and remove the overflow menu
while (parent.firstChild) {
let node = parent.firstChild;
this.contextMenu.insertBefore(node, parent.parentNode);
this.updateXULClass(node);
}
this.contextMenu.removeChild(parent.parentNode);
}
}
},
handleEvent: function handleEvent(event) {
// Recurses through all the items owned by this module and sets their hidden
// state
updateItemVisibilities: function updateItemVisibilities(event) {
try {
if (event.type != "popupshowing")
return;
@ -970,28 +942,77 @@ let MenuWrapper = Class({
this.populate(this.items);
}
let separator = this.separator;
let popup = this.overflowMenu;
let popupNode = event.target.triggerNode;
if (this.setVisibility(this.items, popupNode, PageContext().isCurrent(popupNode))) {
// Some of this instance's items are visible so make sure the separator
// and if necessary the overflow popup are visible
separator.hidden = false;
if (popup)
popup.hidden = false;
this.setVisibility(this.items, popupNode, PageContext().isCurrent(popupNode));
}
catch (e) {
console.exception(e);
}
},
// Counts the number of visible items across all modules and makes sure they
// are in the right place between the top level context menu and the overflow
// menu
updateOverflowState: function updateOverflowState(event) {
try {
if (event.type != "popupshowing")
return;
if (event.target != this.contextMenu)
return;
// The main items will be in either the top level context menu or the
// overflow menu at this point. Count the visible ones and if they are in
// the wrong place move them
let toplevel = this.topLevelItems;
let overflow = this.overflowItems;
let visibleCount = countVisibleItems(toplevel) +
countVisibleItems(overflow);
if (visibleCount == 0) {
let separator = this.separator;
if (separator)
separator.hidden = true;
let overflowMenu = this.overflowMenu;
if (overflowMenu)
overflowMenu.hidden = true;
}
else if (visibleCount > MenuManager.overflowThreshold) {
this.separator.hidden = false;
let overflowPopup = this.overflowPopup;
if (overflowPopup)
overflowPopup.parentNode.hidden = false;
if (toplevel.length > 0) {
// The overflow menu shouldn't exist here but let's play it safe
if (!overflowPopup) {
let overflowMenu = this.window.document.createElement("menu");
overflowMenu.setAttribute("class", OVERFLOW_MENU_CLASS);
overflowMenu.setAttribute("label", OVERFLOW_MENU_LABEL);
this.contextMenu.insertBefore(overflowMenu, this.separator.nextSibling);
overflowPopup = this.window.document.createElement("menupopup");
overflowPopup.setAttribute("class", OVERFLOW_POPUP_CLASS);
overflowMenu.appendChild(overflowPopup);
}
for (let xulNode of toplevel) {
overflowPopup.appendChild(xulNode);
this.updateXULClass(xulNode);
}
}
}
else {
// We need to test whether any other instance has visible items.
// Get all the highest level items and see if any are visible.
let anyVisible = (Array.some(this.topLevelItems, function(item) !item.hidden)) ||
(Array.some(this.overflowItems, function(item) !item.hidden));
// If any were visible make sure the separator and if necessary the
// overflow popup are visible, otherwise hide them
separator.hidden = !anyVisible;
if (popup)
popup.hidden = !anyVisible;
this.separator.hidden = false;
if (overflow.length > 0) {
// Move all the overflow nodes out of the overflow menu and position
// them immediately before it
for (let xulNode of overflow) {
this.contextMenu.insertBefore(xulNode, xulNode.parentNode.parentNode);
this.updateXULClass(xulNode);
}
this.contextMenu.removeChild(this.overflowMenu);
}
}
}
catch (e) {

View File

@ -57,7 +57,11 @@ const TabTrait = Trait.compose(EventEmitter, {
},
destroy: function destroy() {
this._removeAllListeners();
this._browser.removeEventListener(EVENTS.ready.dom, this._onReady, true);
if (this._tab) {
this._browser.removeEventListener(EVENTS.ready.dom, this._onReady, true);
this._tab = null;
TABS.splice(TABS.indexOf(this), 1);
}
},
/**
@ -98,35 +102,35 @@ const TabTrait = Trait.compose(EventEmitter, {
/**
* Unique id for the tab, actually maps to tab.linkedPanel but with some munging.
*/
get id() getTabId(this._tab),
get id() this._tab ? getTabId(this._tab) : undefined,
/**
* The title of the page currently loaded in the tab.
* Changing this property changes an actual title.
* @type {String}
*/
get title() getTabTitle(this._tab),
set title(title) setTabTitle(this._tab, title),
get title() this._tab ? getTabTitle(this._tab) : undefined,
set title(title) this._tab && setTabTitle(this._tab, title),
/**
* Returns the MIME type that the document loaded in the tab is being
* rendered as.
* @type {String}
*/
get contentType() getTabContentType(this._tab),
get contentType() this._tab ? getTabContentType(this._tab) : undefined,
/**
* Location of the page currently loaded in this tab.
* Changing this property will loads page under under the specified location.
* @type {String}
*/
get url() getTabURL(this._tab),
set url(url) setTabURL(this._tab, url),
get url() this._tab ? getTabURL(this._tab) : undefined,
set url(url) this._tab && setTabURL(this._tab, url),
/**
* URI of the favicon for the page currently loaded in this tab.
* @type {String}
*/
get favicon() getFaviconURIForLocation(this.url),
get favicon() this._tab ? getFaviconURIForLocation(this.url) : undefined,
/**
* The CSS style for the tab
*/
@ -137,23 +141,30 @@ const TabTrait = Trait.compose(EventEmitter, {
* @type {Number}
*/
get index()
this._window.gBrowser.getBrowserIndexForDocument(this._contentDocument),
set index(value) this._window.gBrowser.moveTabTo(this._tab, value),
this._tab ?
this._window.gBrowser.getBrowserIndexForDocument(this._contentDocument) :
undefined,
set index(value)
this._tab && this._window.gBrowser.moveTabTo(this._tab, value),
/**
* Thumbnail data URI of the page currently loaded in this tab.
* @type {String}
*/
getThumbnail: function getThumbnail()
getThumbnailURIForWindow(this._contentWindow),
this._tab ? getThumbnailURIForWindow(this._contentWindow) : undefined,
/**
* Whether or not tab is pinned (Is an app-tab).
* @type {Boolean}
*/
get isPinned() this._tab.pinned,
get isPinned() this._tab ? this._tab.pinned : undefined,
pin: function pin() {
if (!this._tab)
return;
this._window.gBrowser.pinTab(this._tab);
},
unpin: function unpin() {
if (!this._tab)
return;
this._window.gBrowser.unpinTab(this._tab);
},
@ -162,6 +173,8 @@ const TabTrait = Trait.compose(EventEmitter, {
* @type {Worker}
*/
attach: function attach(options) {
if (!this._tab)
return;
// BUG 792946 https://bugzilla.mozilla.org/show_bug.cgi?id=792946
// TODO: fix this circular dependency
let { Worker } = require('./worker');
@ -175,12 +188,16 @@ const TabTrait = Trait.compose(EventEmitter, {
* we would like to return instance before firing a 'TabActivated' event.
*/
activate: defer(function activate() {
if (!this._tab)
return;
activateTab(this._tab);
}),
/**
* Close the tab
*/
close: function close(callback) {
if (!this._tab)
return;
if (callback)
this.once(EVENTS.close.name, callback);
this._window.gBrowser.removeTab(this._tab);
@ -189,6 +206,8 @@ const TabTrait = Trait.compose(EventEmitter, {
* Reload the tab
*/
reload: function reload() {
if (!this._tab)
return;
this._window.gBrowser.reloadTab(this._tab);
}
});

View File

@ -86,6 +86,9 @@ const WindowLoader = Trait.compose({
this._onLoad(window)
}
}
else {
this.__window = null;
}
}
},
__window: null,

View File

@ -196,3 +196,4 @@ def replace_file(env_root, dest_path, file_contents, must_rewrite_links):
if must_rewrite_links and dest_path.endswith(".html"):
file_contents = rewrite_links(env_root, get_sdk_docs_path(env_root), file_contents, dest_path)
open(dest_path, "w").write(file_contents)

View File

@ -169,7 +169,7 @@ def gen_manifest(template_root_dir, target_cfg, jid,
ta_desc.appendChild(elem)
elem = dom.createElement("em:maxVersion")
elem.appendChild(dom.createTextNode("21.0a1"))
elem.appendChild(dom.createTextNode("20.*"))
ta_desc.appendChild(elem)
if target_cfg.get("homepage"):

View File

@ -3,8 +3,10 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
'use strict';
let { Cc, Ci } = require("chrome");
let {Cc,Ci} = require("chrome");
const { Loader } = require('sdk/test/loader');
const timer = require("sdk/timers");
@ -480,6 +482,52 @@ exports.testURLContextRemove = function (test) {
});
};
// Loading a new page in the same tab should correctly start a new worker for
// any content scripts
exports.testPageReload = function (test) {
test = new TestHelper(test);
let loader = test.newLoader();
let item = loader.cm.Item({
label: "Item",
contentScript: "var doc = document; self.on('context', function(node) doc.body.getAttribute('showItem') == 'true');"
});
test.withTestDoc(function (window, doc) {
// Set a flag on the document that the item uses
doc.body.setAttribute("showItem", "true");
test.showMenu(null, function (popup) {
// With the attribute true the item should be visible in the menu
test.checkMenu([item], [], []);
test.hideMenu(function() {
let browser = this.tabBrowser.getBrowserForTab(this.tab)
test.delayedEventListener(browser, "load", function() {
test.delayedEventListener(browser, "load", function() {
window = browser.contentWindow;
doc = window.document;
// Set a flag on the document that the item uses
doc.body.setAttribute("showItem", "false");
test.showMenu(null, function (popup) {
// In the new document with the attribute false the item should be
// hidden, but if the contentScript hasn't been reloaded it will
// still see the old value
test.checkMenu([item], [item], []);
test.done();
});
}, true);
browser.loadURI(TEST_DOC_URL, null, null);
}, true);
// Required to make sure we load a new page in history rather than
// just reloading the current page which would unload it
browser.loadURI("about:blank", null, null);
});
});
});
};
// Closing a page after it's been used with a worker should cause the worker
// to be destroyed
@ -555,6 +603,143 @@ exports.testContentContextNoMatch = function (test) {
};
// Content contexts that return undefined should cause their items to be absent
// from the menu.
exports.testContentContextUndefined = function (test) {
test = new TestHelper(test);
let loader = test.newLoader();
let item = new loader.cm.Item({
label: "item",
contentScript: 'self.on("context", function () {});'
});
test.showMenu(null, function (popup) {
test.checkMenu([item], [item], []);
test.done();
});
};
// Content contexts that return an empty string should cause their items to be
// absent from the menu and shouldn't wipe the label
exports.testContentContextEmptyString = function (test) {
test = new TestHelper(test);
let loader = test.newLoader();
let item = new loader.cm.Item({
label: "item",
contentScript: 'self.on("context", function () "");'
});
test.showMenu(null, function (popup) {
test.checkMenu([item], [item], []);
test.assertEqual(item.label, "item", "Label should still be correct");
test.done();
});
};
// If any content contexts returns true then their items should be present in
// the menu.
exports.testMultipleContentContextMatch1 = function (test) {
test = new TestHelper(test);
let loader = test.newLoader();
let item = new loader.cm.Item({
label: "item",
contentScript: 'self.on("context", function () true); ' +
'self.on("context", function () false);',
onMessage: function() {
test.fail("Should not have called the second context listener");
}
});
test.showMenu(null, function (popup) {
test.checkMenu([item], [], []);
test.done();
});
};
// If any content contexts returns true then their items should be present in
// the menu.
exports.testMultipleContentContextMatch2 = function (test) {
test = new TestHelper(test);
let loader = test.newLoader();
let item = new loader.cm.Item({
label: "item",
contentScript: 'self.on("context", function () false); ' +
'self.on("context", function () true);'
});
test.showMenu(null, function (popup) {
test.checkMenu([item], [], []);
test.done();
});
};
// If any content contexts returns a string then their items should be present
// in the menu.
exports.testMultipleContentContextString1 = function (test) {
test = new TestHelper(test);
let loader = test.newLoader();
let item = new loader.cm.Item({
label: "item",
contentScript: 'self.on("context", function () "new label"); ' +
'self.on("context", function () false);'
});
test.showMenu(null, function (popup) {
test.checkMenu([item], [], []);
test.assertEqual(item.label, "new label", "Label should have changed");
test.done();
});
};
// If any content contexts returns a string then their items should be present
// in the menu.
exports.testMultipleContentContextString2 = function (test) {
test = new TestHelper(test);
let loader = test.newLoader();
let item = new loader.cm.Item({
label: "item",
contentScript: 'self.on("context", function () false); ' +
'self.on("context", function () "new label");'
});
test.showMenu(null, function (popup) {
test.checkMenu([item], [], []);
test.assertEqual(item.label, "new label", "Label should have changed");
test.done();
});
};
// If many content contexts returns a string then the first should take effect
exports.testMultipleContentContextString3 = function (test) {
test = new TestHelper(test);
let loader = test.newLoader();
let item = new loader.cm.Item({
label: "item",
contentScript: 'self.on("context", function () "new label 1"); ' +
'self.on("context", function () "new label 2");'
});
test.showMenu(null, function (popup) {
test.checkMenu([item], [], []);
test.assertEqual(item.label, "new label 1", "Label should have changed");
test.done();
});
};
// Content contexts that return true should cause their items to be present
// in the menu when context clicking an active element.
exports.testContentContextMatchActiveElement = function (test) {
@ -631,6 +816,44 @@ exports.testContentContextNoMatchActiveElement = function (test) {
};
// Content contexts that return undefined should cause their items to be absent
// from the menu when context clicking an active element.
exports.testContentContextNoMatchActiveElement = function (test) {
test = new TestHelper(test);
let loader = test.newLoader();
let items = [
new loader.cm.Item({
label: "item 1",
contentScript: 'self.on("context", function () {});'
}),
new loader.cm.Item({
label: "item 2",
context: undefined,
contentScript: 'self.on("context", function () {});'
}),
// These items will always be hidden by the declarative usage of PageContext
new loader.cm.Item({
label: "item 3",
context: loader.cm.PageContext(),
contentScript: 'self.on("context", function () {});'
}),
new loader.cm.Item({
label: "item 4",
context: [loader.cm.PageContext()],
contentScript: 'self.on("context", function () {});'
})
];
test.withTestDoc(function (window, doc) {
test.showMenu(doc.getElementById("image"), function (popup) {
test.checkMenu(items, items, []);
test.done();
});
});
};
// Content contexts that return a string should cause their items to be present
// in the menu and the items' labels to be updated.
exports.testContentContextMatchString = function (test) {
@ -799,7 +1022,7 @@ exports.testUnload = function (test) {
// Using multiple module instances to add items without causing overflow should
// work OK. Assumes OVERFLOW_THRESH_DEFAULT <= 2.
// work OK. Assumes OVERFLOW_THRESH_DEFAULT >= 2.
exports.testMultipleModulesAdd = function (test) {
test = new TestHelper(test);
let loader0 = test.newLoader();
@ -1164,7 +1387,6 @@ exports.testMultipleModulesOrderOverflow = function (test) {
// Same again
test.checkMenu([item0, item2, item1, item3], [], []);
prefs.set(OVERFLOW_THRESH_PREF, OVERFLOW_THRESH_DEFAULT);
test.done();
});
});
@ -1172,6 +1394,401 @@ exports.testMultipleModulesOrderOverflow = function (test) {
};
// Checks that if a module's items are all hidden then the overflow menu doesn't
// get hidden
exports.testMultipleModulesOverflowHidden = function (test) {
test = new TestHelper(test);
let loader0 = test.newLoader();
let loader1 = test.newLoader();
let prefs = loader0.loader.require("preferences-service");
prefs.set(OVERFLOW_THRESH_PREF, 0);
// Use each module to add an item, then unload each module in turn.
let item0 = new loader0.cm.Item({ label: "item 0" });
let item1 = new loader1.cm.Item({
label: "item 1",
context: loader1.cm.SelectorContext("a")
});
test.showMenu(null, function (popup) {
// One should be hidden
test.checkMenu([item0, item1], [item1], []);
test.done();
});
};
// Checks that if a module's items are all hidden then the overflow menu doesn't
// get hidden (reverse order to above)
exports.testMultipleModulesOverflowHidden2 = function (test) {
test = new TestHelper(test);
let loader0 = test.newLoader();
let loader1 = test.newLoader();
let prefs = loader0.loader.require("preferences-service");
prefs.set(OVERFLOW_THRESH_PREF, 0);
// Use each module to add an item, then unload each module in turn.
let item0 = new loader0.cm.Item({
label: "item 0",
context: loader0.cm.SelectorContext("a")
});
let item1 = new loader1.cm.Item({ label: "item 1" });
test.showMenu(null, function (popup) {
// One should be hidden
test.checkMenu([item0, item1], [item0], []);
test.done();
});
};
// Checks that we don't overflow if there are more items than the overflow
// threshold but not all of them are visible
exports.testOverflowIgnoresHidden = function (test) {
test = new TestHelper(test);
let loader = test.newLoader();
let prefs = loader.loader.require("preferences-service");
prefs.set(OVERFLOW_THRESH_PREF, 2);
let allItems = [
new loader.cm.Item({
label: "item 0"
}),
new loader.cm.Item({
label: "item 1"
}),
new loader.cm.Item({
label: "item 2",
context: loader.cm.SelectorContext("a")
})
];
test.showMenu(null, function (popup) {
// One should be hidden
test.checkMenu(allItems, [allItems[2]], []);
test.done();
});
};
// Checks that we don't overflow if there are more items than the overflow
// threshold but not all of them are visible
exports.testOverflowIgnoresHiddenMultipleModules1 = function (test) {
test = new TestHelper(test);
let loader0 = test.newLoader();
let loader1 = test.newLoader();
let prefs = loader0.loader.require("preferences-service");
prefs.set(OVERFLOW_THRESH_PREF, 2);
let allItems = [
new loader0.cm.Item({
label: "item 0"
}),
new loader0.cm.Item({
label: "item 1"
}),
new loader1.cm.Item({
label: "item 2",
context: loader1.cm.SelectorContext("a")
}),
new loader1.cm.Item({
label: "item 3",
context: loader1.cm.SelectorContext("a")
})
];
test.showMenu(null, function (popup) {
// One should be hidden
test.checkMenu(allItems, [allItems[2], allItems[3]], []);
test.done();
});
};
// Checks that we don't overflow if there are more items than the overflow
// threshold but not all of them are visible
exports.testOverflowIgnoresHiddenMultipleModules2 = function (test) {
test = new TestHelper(test);
let loader0 = test.newLoader();
let loader1 = test.newLoader();
let prefs = loader0.loader.require("preferences-service");
prefs.set(OVERFLOW_THRESH_PREF, 2);
let allItems = [
new loader0.cm.Item({
label: "item 0"
}),
new loader0.cm.Item({
label: "item 1",
context: loader0.cm.SelectorContext("a")
}),
new loader1.cm.Item({
label: "item 2"
}),
new loader1.cm.Item({
label: "item 3",
context: loader1.cm.SelectorContext("a")
})
];
test.showMenu(null, function (popup) {
// One should be hidden
test.checkMenu(allItems, [allItems[1], allItems[3]], []);
test.done();
});
};
// Checks that we don't overflow if there are more items than the overflow
// threshold but not all of them are visible
exports.testOverflowIgnoresHiddenMultipleModules3 = function (test) {
test = new TestHelper(test);
let loader0 = test.newLoader();
let loader1 = test.newLoader();
let prefs = loader0.loader.require("preferences-service");
prefs.set(OVERFLOW_THRESH_PREF, 2);
let allItems = [
new loader0.cm.Item({
label: "item 0",
context: loader0.cm.SelectorContext("a")
}),
new loader0.cm.Item({
label: "item 1",
context: loader0.cm.SelectorContext("a")
}),
new loader1.cm.Item({
label: "item 2"
}),
new loader1.cm.Item({
label: "item 3"
})
];
test.showMenu(null, function (popup) {
// One should be hidden
test.checkMenu(allItems, [allItems[0], allItems[1]], []);
test.done();
});
};
// Tests that we transition between overflowing to non-overflowing to no items
// and back again
exports.testOverflowTransition = function (test) {
test = new TestHelper(test);
let loader = test.newLoader();
let prefs = loader.loader.require("preferences-service");
prefs.set(OVERFLOW_THRESH_PREF, 2);
let pItems = [
new loader.cm.Item({
label: "item 0",
context: loader.cm.SelectorContext("p")
}),
new loader.cm.Item({
label: "item 1",
context: loader.cm.SelectorContext("p")
})
];
let aItems = [
new loader.cm.Item({
label: "item 2",
context: loader.cm.SelectorContext("a")
}),
new loader.cm.Item({
label: "item 3",
context: loader.cm.SelectorContext("a")
})
];
let allItems = pItems.concat(aItems);
test.withTestDoc(function (window, doc) {
test.showMenu(doc.getElementById("link"), function (popup) {
// The menu should contain all items and will overflow
test.checkMenu(allItems, [], []);
popup.hidePopup();
test.showMenu(doc.getElementById("text"), function (popup) {
// Only contains hald the items and will not overflow
test.checkMenu(allItems, aItems, []);
popup.hidePopup();
test.showMenu(null, function (popup) {
// None of the items will be visible
test.checkMenu(allItems, allItems, []);
popup.hidePopup();
test.showMenu(doc.getElementById("text"), function (popup) {
// Only contains hald the items and will not overflow
test.checkMenu(allItems, aItems, []);
popup.hidePopup();
test.showMenu(doc.getElementById("link"), function (popup) {
// The menu should contain all items and will overflow
test.checkMenu(allItems, [], []);
popup.hidePopup();
test.showMenu(null, function (popup) {
// None of the items will be visible
test.checkMenu(allItems, allItems, []);
popup.hidePopup();
test.showMenu(doc.getElementById("link"), function (popup) {
// The menu should contain all items and will overflow
test.checkMenu(allItems, [], []);
test.done();
});
});
});
});
});
});
});
});
};
// An item's command listener should work.
exports.testItemCommand = function (test) {
test = new TestHelper(test);
let loader = test.newLoader();
let item = new loader.cm.Item({
label: "item",
data: "item data",
contentScript: 'self.on("click", function (node, data) {' +
' self.postMessage({' +
' tagName: node.tagName,' +
' data: data' +
' });' +
'});',
onMessage: function (data) {
test.assertEqual(this, item, "`this` inside onMessage should be item");
test.assertEqual(data.tagName, "HTML", "node should be an HTML element");
test.assertEqual(data.data, item.data, "data should be item data");
test.done();
}
});
test.showMenu(null, function (popup) {
test.checkMenu([item], [], []);
let elt = test.getItemElt(popup, item);
// create a command event
let evt = elt.ownerDocument.createEvent('Event');
evt.initEvent('command', true, true);
elt.dispatchEvent(evt);
});
};
// A menu's click listener should work and receive bubbling 'command' events from
// sub-items appropriately. This also tests menus and ensures that when a CSS
// selector context matches the clicked node's ancestor, the matching ancestor
// is passed to listeners as the clicked node.
exports.testMenuCommand = function (test) {
// Create a top-level menu, submenu, and item, like this:
// topMenu -> submenu -> item
// Click the item and make sure the click bubbles.
test = new TestHelper(test);
let loader = test.newLoader();
let item = new loader.cm.Item({
label: "submenu item",
data: "submenu item data",
context: loader.cm.SelectorContext("a"),
});
let submenu = new loader.cm.Menu({
label: "submenu",
context: loader.cm.SelectorContext("a"),
items: [item]
});
let topMenu = new loader.cm.Menu({
label: "top menu",
contentScript: 'self.on("click", function (node, data) {' +
' let Ci = Components["interfaces"];' +
' self.postMessage({' +
' tagName: node.tagName,' +
' data: data' +
' });' +
'});',
onMessage: function (data) {
test.assertEqual(this, topMenu, "`this` inside top menu should be menu");
test.assertEqual(data.tagName, "A", "Clicked node should be anchor");
test.assertEqual(data.data, item.data,
"Clicked item data should be correct");
test.done();
},
items: [submenu],
context: loader.cm.SelectorContext("a")
});
test.withTestDoc(function (window, doc) {
test.showMenu(doc.getElementById("span-link"), function (popup) {
test.checkMenu([topMenu], [], []);
let topMenuElt = test.getItemElt(popup, topMenu);
let topMenuPopup = topMenuElt.firstChild;
let submenuElt = test.getItemElt(topMenuPopup, submenu);
let submenuPopup = submenuElt.firstChild;
let itemElt = test.getItemElt(submenuPopup, item);
// create a command event
let evt = itemElt.ownerDocument.createEvent('Event');
evt.initEvent('command', true, true);
itemElt.dispatchEvent(evt);
});
});
};
// Click listeners should work when multiple modules are loaded.
exports.testItemCommandMultipleModules = function (test) {
test = new TestHelper(test);
let loader0 = test.newLoader();
let loader1 = test.newLoader();
let item0 = loader0.cm.Item({
label: "loader 0 item",
contentScript: 'self.on("click", self.postMessage);',
onMessage: function () {
test.fail("loader 0 item should not emit click event");
}
});
let item1 = loader1.cm.Item({
label: "loader 1 item",
contentScript: 'self.on("click", self.postMessage);',
onMessage: function () {
test.pass("loader 1 item clicked as expected");
test.done();
}
});
test.showMenu(null, function (popup) {
test.checkMenu([item0, item1], [], []);
let item1Elt = test.getItemElt(popup, item1);
// create a command event
let evt = item1Elt.ownerDocument.createEvent('Event');
evt.initEvent('command', true, true);
item1Elt.dispatchEvent(evt);
});
};
// An item's click listener should work.
exports.testItemClick = function (test) {
test = new TestHelper(test);
@ -1526,6 +2143,7 @@ exports.testDrawImageOnClickNode = function (test) {
});
};
// Setting an item's label before the menu is ever shown should correctly change
// its label.
exports.testSetLabelBeforeShow = function (test) {
@ -1589,7 +2207,6 @@ exports.testSetLabelBeforeShowOverflow = function (test) {
test.showMenu(null, function (popup) {
test.checkMenu(items, [], []);
prefs.set(OVERFLOW_THRESH_PREF, OVERFLOW_THRESH_DEFAULT);
test.done();
});
};
@ -1617,7 +2234,6 @@ exports.testSetLabelAfterShowOverflow = function (test) {
test.assertEqual(items[0].label, "z");
test.showMenu(null, function (popup) {
test.checkMenu(items, [], []);
prefs.set(OVERFLOW_THRESH_PREF, OVERFLOW_THRESH_DEFAULT);
test.done();
});
});
@ -2090,6 +2706,8 @@ exports.testSubItemDefaultVisible = function (test) {
});
};
// Tests that the click event on sub menuitem
// tiggers the click event for the sub menuitem and the parent menu
exports.testSubItemClick = function (test) {
test = new TestHelper(test);
let loader = test.newLoader();
@ -2145,6 +2763,68 @@ exports.testSubItemClick = function (test) {
});
};
// Tests that the command event on sub menuitem
// tiggers the click event for the sub menuitem and the parent menu
exports.testSubItemCommand = function (test) {
test = new TestHelper(test);
let loader = test.newLoader();
let state = 0;
let items = [
loader.cm.Menu({
label: "menu 1",
items: [
loader.cm.Item({
label: "subitem 1",
data: "foobar",
contentScript: 'self.on("click", function (node, data) {' +
' self.postMessage({' +
' tagName: node.tagName,' +
' data: data' +
' });' +
'});',
onMessage: function(msg) {
test.assertEqual(msg.tagName, "HTML", "should have seen the right node");
test.assertEqual(msg.data, "foobar", "should have seen the right data");
test.assertEqual(state, 0, "should have seen the event at the right time");
state++;
}
})
],
contentScript: 'self.on("click", function (node, data) {' +
' self.postMessage({' +
' tagName: node.tagName,' +
' data: data' +
' });' +
'});',
onMessage: function(msg) {
test.assertEqual(msg.tagName, "HTML", "should have seen the right node");
test.assertEqual(msg.data, "foobar", "should have seen the right data");
test.assertEqual(state, 1, "should have seen the event at the right time");
state++
test.done();
}
})
];
test.withTestDoc(function (window, doc) {
test.showMenu(null, function (popup) {
test.checkMenu(items, [], []);
let topMenuElt = test.getItemElt(popup, items[0]);
let topMenuPopup = topMenuElt.firstChild;
let itemElt = test.getItemElt(topMenuPopup, items[0].items[0]);
// create a command event
let evt = itemElt.ownerDocument.createEvent('Event');
evt.initEvent('command', true, true);
itemElt.dispatchEvent(evt);
});
});
};
// Tests that opening a context menu for an outer frame when an inner frame
// has a selection doesn't activate the SelectionContext
exports.testSelectionInInnerFrameNoMatch = function (test) {
@ -2249,6 +2929,8 @@ function TestHelper(test) {
this.browserWindow = Cc["@mozilla.org/appshell/window-mediator;1"].
getService(Ci.nsIWindowMediator).
getMostRecentWindow("navigator:browser");
this.overflowThreshValue = require("sdk/preferences/service").
get(OVERFLOW_THRESH_PREF, OVERFLOW_THRESH_DEFAULT);
}
TestHelper.prototype = {
@ -2351,6 +3033,9 @@ TestHelper.prototype = {
let mainNodes = this.browserWindow.document.querySelectorAll("#contentAreaContextMenu > ." + ITEM_CLASS);
let overflowNodes = this.browserWindow.document.querySelectorAll("." + OVERFLOW_POPUP_CLASS + " > ." + ITEM_CLASS);
this.test.assert(mainNodes.length == 0 || overflowNodes.length == 0,
"Should only see nodes at the top level or in overflow");
let overflow = this.overflowSubmenu;
if (this.shouldOverflow(total)) {
this.test.assert(overflow && !overflow.hidden,
@ -2361,12 +3046,15 @@ TestHelper.prototype = {
else {
this.test.assert(!overflow || overflow.hidden,
"overflow menu should not be present");
this.test.assertEqual(overflowNodes.length, 0,
"should be no items in the overflow context menu");
// When visible nodes == 0 they could be in overflow or top level
if (total > 0) {
this.test.assertEqual(overflowNodes.length, 0,
"should be no items in the overflow context menu");
}
}
let nodes = this.shouldOverflow(total) ? overflowNodes : mainNodes;
// Iterate over wherever the nodes have ended up
let nodes = mainNodes.length ? mainNodes : overflowNodes;
this.checkNodes(nodes, presentItems, absentItems, removedItems)
let pos = 0;
},
@ -2382,6 +3070,11 @@ TestHelper.prototype = {
if (removedItems.indexOf(item) >= 0)
continue;
if (nodes.length <= pos) {
this.test.assert(false, "Not enough nodes");
return;
}
let hidden = absentItems.indexOf(item) >= 0;
this.checkItemElt(nodes[pos], item);
@ -2432,12 +3125,16 @@ TestHelper.prototype = {
// Call to finish the test.
done: function () {
const self = this;
function commonDone() {
this.closeTab();
while (this.loaders.length) {
this.loaders[0].unload();
}
require("sdk/preferences/service").set(OVERFLOW_THRESH_PREF, self.overflowThreshValue);
this.test.done();
}

View File

@ -5,23 +5,19 @@
const port = 8099;
const file = require("sdk/io/file");
const { pathFor } = require("sdk/system");
const { Loader } = require("sdk/test/loader");
const options = require("@test/options");
const loader = Loader(module);
const httpd = loader.require("sdk/test/httpd");
if (options.parseable || options.verbose)
loader.sandbox("sdk/test/httpd").DEBUG = true;
exports.testBasicHTTPServer = function(test) {
let basePath = pathFor("TmpD");
// Use the profile directory for the temporary file as that will be deleted
// when tests are complete
let basePath = pathFor("ProfD");
let filePath = file.join(basePath, 'test-httpd.txt');
let content = "This is the HTTPD test file.\n";
let fileStream = file.open(filePath, 'w');
fileStream.write(content);
fileStream.close();
let srv = httpd.startServerAsync(port, basePath);
let { startServerAsync } = require("sdk/test/httpd");
let srv = startServerAsync(port, basePath);
test.waitUntilDone();
@ -45,7 +41,8 @@ exports.testBasicHTTPServer = function(test) {
exports.testDynamicServer = function (test) {
let content = "This is the HTTPD test file.\n";
let srv = httpd.startServerAsync(port);
let { startServerAsync } = require("sdk/test/httpd");
let srv = startServerAsync(port);
// See documentation here:
//http://doxygen.db48x.net/mozilla/html/interfacensIHttpServer.html#a81fc7e7e29d82aac5ce7d56d0bedfb3a

View File

@ -1029,3 +1029,4 @@ if (require("sdk/system/xul-app").is("Fennec")) {
}
}
}

View File

@ -28,3 +28,4 @@ exports.testIsActiveDefault = function(test) {
test.assertEqual(pb.isActive, false,
'pb.isActive returns false when private browsing isn\'t supported');
};

View File

@ -15,7 +15,9 @@ if (options.parseable || options.verbose)
loader.sandbox("sdk/test/httpd").DEBUG = true;
const { startServerAsync } = httpd;
const basePath = pathFor("TmpD")
// Use the profile directory for the temporary files as that will be deleted
// when tests are complete
const basePath = pathFor("ProfD")
const port = 8099;

View File

@ -109,6 +109,28 @@ function step3(assert, done) {
});
}
exports["test behavior on close"] = function(assert, done) {
tabs.open({
url: "about:mozilla",
onReady: function(tab) {
assert.equal(tab.url, "about:mozilla", "Tab has the expected url");
assert.equal(tab.index, 1, "Tab has the expected index");
tab.close(function () {
assert.equal(tab.url, undefined,
"After being closed, tab attributes are undefined (url)");
assert.equal(tab.index, undefined,
"After being closed, tab attributes are undefined (index)");
// Ensure that we can call destroy multiple times without throwing
tab.destroy();
tab.destroy();
done();
});
}
});
};
if (require("sdk/system/xul-app").is("Fennec")) {
module.exports = {
"test Unsupported Test": function UnsupportedTest (assert) {

View File

@ -546,17 +546,19 @@ pref("ui.showHideScrollbars", 1);
// background.
pref("dom.ipc.processPriorityManager.enabled", true);
pref("dom.ipc.processPriorityManager.backgroundGracePeriodMS", 1000);
pref("dom.ipc.processPriorityManager.temporaryPriorityMS", 5000);
pref("dom.ipc.processPriorityManager.temporaryPriorityLockMS", 5000);
// Kernel parameters for how processes are killed on low-memory.
pref("gonk.systemMemoryPressureRecoveryPollMS", 5000);
pref("hal.processPriorityManager.gonk.masterOomScoreAdjust", 0);
pref("hal.processPriorityManager.gonk.masterKillUnderMB", 1);
pref("hal.processPriorityManager.gonk.foregroundOomScoreAdjust", 67);
pref("hal.processPriorityManager.gonk.foregroundHighOomScoreAdjust", 67);
pref("hal.processPriorityManager.gonk.foregroundHighKillUnderMB", 3);
pref("hal.processPriorityManager.gonk.foregroundOomScoreAdjust", 134);
pref("hal.processPriorityManager.gonk.foregroundKillUnderMB", 4);
pref("hal.processPriorityManager.gonk.backgroundPerceivableOomScoreAdjust", 134);
pref("hal.processPriorityManager.gonk.backgroundPerceivableOomScoreAdjust", 200);
pref("hal.processPriorityManager.gonk.backgroundPerceivableKillUnderMB", 5);
pref("hal.processPriorityManager.gonk.backgroundHomescreenOomScoreAdjust", 200);
pref("hal.processPriorityManager.gonk.backgroundHomescreenOomScoreAdjust", 267);
pref("hal.processPriorityManager.gonk.backgroundHomescreenKillUnderMB", 5);
pref("hal.processPriorityManager.gonk.backgroundOomScoreAdjust", 400);
pref("hal.processPriorityManager.gonk.backgroundKillUnderMB", 8);
@ -564,6 +566,7 @@ pref("hal.processPriorityManager.gonk.notifyLowMemUnderMB", 10);
// Niceness values (i.e., CPU priorities) for B2G processes.
pref("hal.processPriorityManager.gonk.masterNice", 0);
pref("hal.processPriorityManager.gonk.foregroundHighNice", 0);
pref("hal.processPriorityManager.gonk.foregroundNice", 1);
pref("hal.processPriorityManager.gonk.backgroundPerceivableNice", 10);
pref("hal.processPriorityManager.gonk.backgroundHomescreenNice", 20);
@ -577,6 +580,11 @@ pref("dom.ipc.processPrelaunch.enabled", true);
pref("dom.ipc.processPrelaunch.delayMs", 5000);
#endif
// When a process receives a system message, we hold a CPU wake lock on its
// behalf for this many seconds, or until it handles the system message,
// whichever comes first.
pref("dom.ipc.systemMessageCPULockTimeoutSec", 30);
// Ignore the "dialog=1" feature in window.open.
pref("dom.disable_window_open_dialog_feature", true);

View File

@ -526,7 +526,8 @@ var shell = {
url: msg.uri,
manifestURL: msg.manifest,
isActivity: (msg.type == 'activity'),
target: msg.target
target: msg.target,
expectingSystemMessage: true
});
},

View File

@ -129,7 +129,6 @@
#ifdef ACCESSIBILITY
#ifdef XP_WIN32
@BINPATH@/AccessibleMarshal.dll
@BINPATH@/components/accessibility-msaa.xpt
#endif
@BINPATH@/components/accessibility.xpt
#endif

View File

@ -119,10 +119,6 @@ ifeq ($(OS_ARCH),WINNT) #{
#
ifndef GNU_CC #{
LDFLAGS += /HEAP:0x40000
ifeq ($(OS_TEST),x86_64) #{
# set stack to 2MB on x64 build. See bug 582910
LDFLAGS += -STACK:2097152
endif #}
endif #}
endif #}

View File

@ -8,6 +8,11 @@ var gPluginHandler = {
PLUGIN_SCRIPTED_STATE_FIRED: 1,
PLUGIN_SCRIPTED_STATE_DONE: 2,
getPluginUI: function (plugin, className) {
return plugin.ownerDocument.
getAnonymousElementByAttribute(plugin, "class", className);
},
#ifdef MOZ_CRASHREPORTER
get CrashSubmit() {
delete this.CrashSubmit;
@ -304,10 +309,19 @@ var gPluginHandler = {
let browser = gBrowser.getBrowserForDocument(objLoadingContent.ownerDocument.defaultView.top.document);
let pluginPermission = Services.perms.testPermission(browser.currentURI, permissionString);
let isFallbackTypeValid =
objLoadingContent.pluginFallbackType >= Ci.nsIObjectLoadingContent.PLUGIN_CLICK_TO_PLAY &&
objLoadingContent.pluginFallbackType <= Ci.nsIObjectLoadingContent.PLUGIN_VULNERABLE_NO_UPDATE;
if (objLoadingContent.pluginFallbackType == Ci.nsIObjectLoadingContent.PLUGIN_PLAY_PREVIEW) {
// checking if play preview is subject to CTP rules
let playPreviewInfo = pluginHost.getPlayPreviewInfo(objLoadingContent.actualType);
isFallbackTypeValid = !playPreviewInfo.ignoreCTP;
}
return !objLoadingContent.activated &&
pluginPermission != Ci.nsIPermissionManager.DENY_ACTION &&
objLoadingContent.pluginFallbackType >= Ci.nsIObjectLoadingContent.PLUGIN_CLICK_TO_PLAY &&
objLoadingContent.pluginFallbackType <= Ci.nsIObjectLoadingContent.PLUGIN_VULNERABLE_NO_UPDATE;
isFallbackTypeValid;
},
activatePlugins: function PH_activatePlugins(aContentWindow) {
@ -400,11 +414,16 @@ var gPluginHandler = {
},
#ifdef MOZ_CRASHREPORTER
// Callback for user clicking "submit a report" link
submitReport : function(pluginDumpID, browserDumpID) {
// The crash reporter wants a DOM element it can append an IFRAME to,
// which it uses to submit a form. Let's just give it gBrowser.
this.CrashSubmit.submit(pluginDumpID);
submitReport: function submitReport(pluginDumpID, browserDumpID, plugin) {
let keyVals = {};
if (plugin) {
let userComment = this.getPluginUI(plugin, "submitComment").value.trim();
if (userComment)
keyVals.PluginUserComment = userComment;
if (this.getPluginUI(plugin, "submitURLOptIn").checked)
keyVals.PluginContentURL = plugin.ownerDocument.URL;
}
this.CrashSubmit.submit(pluginDumpID, { extraExtraKeyVals: keyVals });
if (browserDumpID)
this.CrashSubmit.submit(browserDumpID);
},
@ -472,6 +491,21 @@ var gPluginHandler = {
_handlePlayPreviewEvent: function PH_handlePlayPreviewEvent(aPlugin) {
let doc = aPlugin.ownerDocument;
let browser = gBrowser.getBrowserForDocument(doc.defaultView.top.document);
let pluginHost = Cc["@mozilla.org/plugin/host;1"].getService(Ci.nsIPluginHost);
let pluginInfo = this._getPluginInfo(aPlugin);
let playPreviewInfo = pluginHost.getPlayPreviewInfo(pluginInfo.mimetype);
if (!playPreviewInfo.ignoreCTP) {
// if click-to-play rules used, play plugin at once if plugins were
// activated for this window
if (browser._clickToPlayAllPluginsActivated ||
browser._clickToPlayPluginsActivated.get(pluginInfo.pluginName)) {
objLoadingContent.playPlugin();
return;
}
}
let previewContent = doc.getAnonymousElementByAttribute(aPlugin, "class", "previewPluginContent");
let iframe = previewContent.getElementsByClassName("previewPluginContentFrame")[0];
if (!iframe) {
@ -483,9 +517,7 @@ var gPluginHandler = {
// Force a style flush, so that we ensure our binding is attached.
aPlugin.clientTop;
}
let pluginInfo = this._getPluginInfo(aPlugin);
let playPreviewUri = "data:application/x-moz-playpreview;," + pluginInfo.mimetype;
iframe.src = playPreviewUri;
iframe.src = playPreviewInfo.redirectURL;
// MozPlayPlugin event can be dispatched from the extension chrome
// code to replace the preview content with the native plugin
@ -503,6 +535,10 @@ var gPluginHandler = {
if (iframe)
previewContent.removeChild(iframe);
}, true);
if (!playPreviewInfo.ignoreCTP) {
gPluginHandler._showClickToPlayNotification(browser);
}
},
reshowClickToPlayNotification: function PH_reshowClickToPlayNotification() {
@ -911,11 +947,16 @@ var gPluginHandler = {
}
else { // doPrompt
status = "please";
// XXX can we make the link target actually be blank?
let pleaseLink = doc.getAnonymousElementByAttribute(
plugin, "class", "pleaseSubmitLink");
this.addLinkClickCallback(pleaseLink, "submitReport",
pluginDumpID, browserDumpID);
this.getPluginUI(plugin, "submitButton").addEventListener("click",
function (event) {
if (event.button != 0 || !event.isTrusted)
return;
this.submitReport(pluginDumpID, browserDumpID, plugin);
pref.setBoolPref("", optInCB.checked);
}.bind(this));
let optInCB = this.getPluginUI(plugin, "submitURLOptIn");
let pref = Services.prefs.getBranch("dom.ipc.plugins.reportCrashURL");
optInCB.checked = pref.getBoolPref("");
}
// If we don't have a minidumpID, we can't (or didn't) submit anything.
@ -926,8 +967,6 @@ var gPluginHandler = {
statusDiv.setAttribute("status", status);
let bottomLinks = doc.getAnonymousElementByAttribute(plugin, "class", "msg msgBottomLinks");
bottomLinks.style.display = "block";
let helpIcon = doc.getAnonymousElementByAttribute(plugin, "class", "helpIcon");
this.addLinkClickCallback(helpIcon, "openHelpPage");
@ -964,7 +1003,7 @@ var gPluginHandler = {
}
#endif
let crashText = doc.getAnonymousElementByAttribute(plugin, "class", "msg msgCrashed");
let crashText = doc.getAnonymousElementByAttribute(plugin, "class", "msgCrashedText");
crashText.textContent = messageString;
let browser = gBrowser.getBrowserForDocument(doc.defaultView.top.document);
@ -974,21 +1013,32 @@ var gPluginHandler = {
let notificationBox = gBrowser.getNotificationBox(browser);
let isShowing = true;
// Is the <object>'s size too small to hold what we want to show?
if (this.isTooSmall(plugin, overlay)) {
// Hide the overlay's contents. Use visibility style, so that it
// doesn't collapse down to 0x0.
// First try hiding the crash report submission UI.
statusDiv.removeAttribute("status");
if (this.isTooSmall(plugin, overlay)) {
// Hide the overlay's contents. Use visibility style, so that it doesn't
// collapse down to 0x0.
overlay.style.visibility = "hidden";
// If another plugin on the page was large enough to show our UI, we
// don't want to show a notification bar.
if (!doc.mozNoPluginCrashedNotification)
showNotificationBar(pluginDumpID, browserDumpID);
isShowing = false;
}
}
if (isShowing) {
// If a previous plugin on the page was too small and resulted in adding a
// notification bar, then remove it because this plugin instance it big
// enough to serve as in-content notification.
hideNotificationBar();
doc.mozNoPluginCrashedNotification = true;
} else {
// If a previous plugin on the page was too small and resulted in
// adding a notification bar, then remove it because this plugin
// instance it big enough to serve as in-content notification.
hideNotificationBar();
doc.mozNoPluginCrashedNotification = true;
// If another plugin on the page was large enough to show our UI, we don't
// want to show a notification bar.
if (!doc.mozNoPluginCrashedNotification)
showNotificationBar(pluginDumpID, browserDumpID);
}
function hideNotificationBar() {

View File

@ -994,6 +994,9 @@ let gGestureSupport = {
let contentElement = content.document.body.firstElementChild;
if (!contentElement)
return;
// If we're currently snapping, cancel that snap
if (contentElement.classList.contains("completeRotation"))
this._clearCompleteRotation();
this.rotation = Math.round(this.rotation + aEvent.delta);
contentElement.style.transform = "rotate(" + this.rotation + "deg)";
@ -1036,8 +1039,11 @@ let gGestureSupport = {
this.rotation < transitionRotation)
transitionRotation -= 90;
contentElement.classList.add("completeRotation");
contentElement.addEventListener("transitionend", this._clearCompleteRotation);
// Only add the completeRotation class if it is is necessary
if (transitionRotation != this.rotation) {
contentElement.classList.add("completeRotation");
contentElement.addEventListener("transitionend", this._clearCompleteRotation);
}
contentElement.style.transform = "rotate(" + transitionRotation + "deg)";
this.rotation = transitionRotation;
@ -1094,8 +1100,14 @@ let gGestureSupport = {
* Removes the transition rule by removing the completeRotation class
*/
_clearCompleteRotation: function() {
this.classList.remove("completeRotation");
this.removeEventListener("transitionend", this._clearCompleteRotation);
let contentElement = content.document &&
content.document instanceof ImageDocument &&
content.document.body &&
content.document.body.firstElementChild;
if (!contentElement)
return;
contentElement.classList.remove("completeRotation");
contentElement.removeEventListener("transitionend", this._clearCompleteRotation);
},
};

View File

@ -265,7 +265,6 @@
class="social-panel"
type="arrow"
hidden="true"
consumeoutsideclicks="false"
noautofocus="true"/>
<panel id="social-flyout-panel"
class="social-panel"

View File

@ -186,6 +186,7 @@ _BROWSER_FILES = \
browser_plugins_added_dynamically.js \
browser_CTPScriptPlugin.js \
browser_pluginplaypreview.js \
browser_pluginplaypreview2.js \
browser_private_browsing_window.js \
browser_relatedTabs.js \
browser_sanitize-passwordDisabledHosts.js \
@ -222,6 +223,7 @@ _BROWSER_FILES = \
browser_urlbarRevert.js \
browser_urlbarStop.js \
browser_urlbarTrimURLs.js \
browser_urlbar_search_healthreport.js \
browser_urlHighlight.js \
browser_visibleFindSelection.js \
browser_visibleTabs.js \
@ -301,6 +303,8 @@ _BROWSER_FILES = \
browser_pageInfo_plugins.js \
browser_pageInfo.js \
feed_tab.html \
browser_pluginCrashCommentAndURL.js \
pluginCrashCommentAndURL.html \
$(NULL)
ifneq (cocoa,$(MOZ_WIDGET_TOOLKIT))

View File

@ -0,0 +1,154 @@
/* 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/. */
Cu.import("resource://gre/modules/Services.jsm");
const CRASH_URL = "http://example.com/browser/browser/base/content/test/pluginCrashCommentAndURL.html";
const SERVER_URL = "http://example.com/browser/toolkit/crashreporter/test/browser/crashreport.sjs";
function test() {
// Crashing the plugin takes up a lot of time, so extend the test timeout.
requestLongerTimeout(runs.length);
waitForExplicitFinish();
// The test harness sets MOZ_CRASHREPORTER_NO_REPORT, which disables plugin
// crash reports. This test needs them enabled. The test also needs a mock
// report server, and fortunately one is already set up by toolkit/
// crashreporter/test/Makefile.in. Assign its URL to MOZ_CRASHREPORTER_URL,
// which CrashSubmit.jsm uses as a server override.
let env = Cc["@mozilla.org/process/environment;1"].
getService(Components.interfaces.nsIEnvironment);
let noReport = env.get("MOZ_CRASHREPORTER_NO_REPORT");
let serverURL = env.get("MOZ_CRASHREPORTER_URL");
env.set("MOZ_CRASHREPORTER_NO_REPORT", "");
env.set("MOZ_CRASHREPORTER_URL", SERVER_URL);
let tab = gBrowser.loadOneTab("about:blank", { inBackground: false });
let browser = gBrowser.getBrowserForTab(tab);
browser.addEventListener("PluginCrashed", onCrash, false);
Services.obs.addObserver(onSubmitStatus, "crash-report-status", false);
registerCleanupFunction(function cleanUp() {
env.set("MOZ_CRASHREPORTER_NO_REPORT", noReport);
env.set("MOZ_CRASHREPORTER_URL", serverURL);
gBrowser.selectedBrowser.removeEventListener("PluginCrashed", onCrash,
false);
Services.obs.removeObserver(onSubmitStatus, "crash-report-status");
gBrowser.removeCurrentTab();
});
doNextRun();
}
let runs = [
{
shouldSubmissionUIBeVisible: true,
comment: "",
urlOptIn: false,
},
{
shouldSubmissionUIBeVisible: true,
comment: "a test comment",
urlOptIn: true,
},
{
width: 300,
height: 300,
shouldSubmissionUIBeVisible: false,
},
];
let currentRun = null;
function doNextRun() {
try {
if (!runs.length) {
finish();
return;
}
currentRun = runs.shift();
let args = ["width", "height"].reduce(function (memo, arg) {
if (arg in currentRun)
memo[arg] = currentRun[arg];
return memo;
}, {});
gBrowser.loadURI(CRASH_URL + "?" +
encodeURIComponent(JSON.stringify(args)));
// And now wait for the crash.
}
catch (err) {
failWithException(err);
finish();
}
}
function onCrash() {
try {
let plugin = gBrowser.contentDocument.getElementById("plugin");
let elt = gPluginHandler.getPluginUI.bind(gPluginHandler, plugin);
let style =
gBrowser.contentWindow.getComputedStyle(elt("msg msgPleaseSubmit"));
is(style.display,
currentRun.shouldSubmissionUIBeVisible ? "block" : "none",
"Submission UI visibility should be correct");
if (!currentRun.shouldSubmissionUIBeVisible) {
// Done with this run.
doNextRun();
return;
}
elt("submitComment").value = currentRun.comment;
elt("submitURLOptIn").checked = currentRun.urlOptIn;
elt("submitButton").click();
// And now wait for the submission status notification.
}
catch (err) {
failWithException(err);
doNextRun();
}
}
function onSubmitStatus(subj, topic, data) {
try {
// Wait for success or failed, doesn't matter which.
if (data != "success" && data != "failed")
return;
let extra = getPropertyBagValue(subj.QueryInterface(Ci.nsIPropertyBag),
"extra");
ok(extra instanceof Ci.nsIPropertyBag, "Extra data should be property bag");
let val = getPropertyBagValue(extra, "PluginUserComment");
if (currentRun.comment)
is(val, currentRun.comment,
"Comment in extra data should match comment in textbox");
else
ok(val === undefined,
"Comment should be absent from extra data when textbox is empty");
val = getPropertyBagValue(extra, "PluginContentURL");
if (currentRun.urlOptIn)
is(val, gBrowser.currentURI.spec,
"URL in extra data should match browser URL when opt-in checked");
else
ok(val === undefined,
"URL should be absent from extra data when opt-in not checked");
}
catch (err) {
failWithException(err);
}
doNextRun();
}
function getPropertyBagValue(bag, key) {
try {
var val = bag.getProperty(key);
}
catch (e if e.result == Cr.NS_ERROR_FAILURE) {}
return val;
}
function failWithException(err) {
ok(false, "Uncaught exception: " + err + "\n" + err.stack);
}

View File

@ -111,7 +111,7 @@ function registerPlayPreview(mimeType, targetUrl) {
};
var ph = Cc["@mozilla.org/plugin/host;1"].getService(Ci.nsIPluginHost);
ph.registerPlayPreviewMimeType(mimeType);
ph.registerPlayPreviewMimeType(mimeType, true); // ignoring CTP rules
var factory = new StreamConverterFactory();
factory.register(OverlayStreamConverter);

View File

@ -0,0 +1,173 @@
/* 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/. */
var rootDir = getRootDirectory(gTestPath);
const gTestRoot = rootDir;
var gTestBrowser = null;
var gNextTest = null;
var gNextTestSkip = 0;
var gPlayPreviewPluginActualEvents = 0;
var gPlayPreviewPluginExpectedEvents = 1;
var gPlayPreviewRegistration = null;
function registerPlayPreview(mimeType, targetUrl) {
var ph = Cc["@mozilla.org/plugin/host;1"].getService(Ci.nsIPluginHost);
ph.registerPlayPreviewMimeType(mimeType, false, targetUrl);
return (gPlayPreviewRegistration = {
unregister: function() {
ph.unregisterPlayPreviewMimeType(mimeType);
gPlayPreviewRegistration = null;
}
});
}
function unregisterPlayPreview() {
gPlayPreviewRegistration.unregister();
}
Components.utils.import('resource://gre/modules/XPCOMUtils.jsm');
Components.utils.import("resource://gre/modules/Services.jsm");
function test() {
waitForExplicitFinish();
registerCleanupFunction(function() {
if (gPlayPreviewRegistration)
gPlayPreviewRegistration.unregister();
Services.prefs.clearUserPref("plugins.click_to_play");
});
var newTab = gBrowser.addTab();
gBrowser.selectedTab = newTab;
gTestBrowser = gBrowser.selectedBrowser;
gTestBrowser.addEventListener("load", pageLoad, true);
gTestBrowser.addEventListener("PluginBindingAttached", handleBindingAttached, true, true);
Services.prefs.setBoolPref("plugins.click_to_play", true);
registerPlayPreview('application/x-test', 'about:');
prepareTest(test1a, gTestRoot + "plugin_test.html", 1);
}
function finishTest() {
gTestBrowser.removeEventListener("load", pageLoad, true);
gTestBrowser.removeEventListener("PluginBindingAttached", handleBindingAttached, true, true);
gBrowser.removeCurrentTab();
window.focus();
finish();
}
function handleBindingAttached(evt) {
if (evt.target instanceof Ci.nsIObjectLoadingContent &&
evt.target.pluginFallbackType == Ci.nsIObjectLoadingContent.PLUGIN_PLAY_PREVIEW)
gPlayPreviewPluginActualEvents++;
}
function pageLoad() {
// The plugin events are async dispatched and can come after the load event
// This just allows the events to fire before we then go on to test the states
// iframe might triggers load event as well, making sure we skip some to let
// all iframes on the page be loaded as well
if (gNextTestSkip) {
gNextTestSkip--;
return;
}
executeSoon(gNextTest);
}
function prepareTest(nextTest, url, skip) {
gNextTest = nextTest;
gNextTestSkip = skip;
gTestBrowser.contentWindow.location = url;
}
// Tests a page with normal play preview registration (1/2)
function test1a() {
var notificationBox = gBrowser.getNotificationBox(gTestBrowser);
ok(!notificationBox.getNotificationWithValue("missing-plugins"), "Test 1a, Should not have displayed the missing plugin notification");
ok(!notificationBox.getNotificationWithValue("blocked-plugins"), "Test 1a, Should not have displayed the blocked plugin notification");
var pluginInfo = getTestPlugin();
ok(pluginInfo, "Should have a test plugin");
var doc = gTestBrowser.contentDocument;
var plugin = doc.getElementById("test");
var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
is(objLoadingContent.pluginFallbackType, Ci.nsIObjectLoadingContent.PLUGIN_PLAY_PREVIEW, "Test 1a, plugin fallback type should be PLUGIN_PLAY_PREVIEW");
ok(!objLoadingContent.activated, "Test 1a, Plugin should not be activated");
var overlay = doc.getAnonymousElementByAttribute(plugin, "class", "previewPluginContent");
ok(overlay, "Test 1a, the overlay div is expected");
var iframe = overlay.getElementsByClassName("previewPluginContentFrame")[0];
ok(iframe && iframe.localName == "iframe", "Test 1a, the overlay iframe is expected");
var iframeHref = iframe.contentWindow.location.href;
ok(iframeHref == "about:", "Test 1a, the overlay about: content is expected");
var rect = iframe.getBoundingClientRect();
ok(rect.width == 200, "Test 1a, Plugin with id=" + plugin.id + " overlay rect should have 200px width before being replaced by actual plugin");
ok(rect.height == 200, "Test 1a, Plugin with id=" + plugin.id + " overlay rect should have 200px height before being replaced by actual plugin");
var e = overlay.ownerDocument.createEvent("CustomEvent");
e.initCustomEvent("MozPlayPlugin", true, true, null);
overlay.dispatchEvent(e);
var condition = function() objLoadingContent.activated;
waitForCondition(condition, test1b, "Test 1a, Waited too long for plugin to stop play preview");
}
// Tests that activating via MozPlayPlugin through the notification works (part 2/2)
function test1b() {
var plugin = gTestBrowser.contentDocument.getElementById("test");
var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
ok(objLoadingContent.activated, "Test 1b, Plugin should be activated");
is(gPlayPreviewPluginActualEvents, gPlayPreviewPluginExpectedEvents,
"There should be exactly one PluginPlayPreview event");
unregisterPlayPreview();
prepareTest(test2, gTestRoot + "plugin_test.html");
}
// Tests a page with a working plugin in it -- the mime type was just unregistered.
function test2() {
var doc = gTestBrowser.contentDocument;
var plugin = doc.getElementById("test");
var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
ok(objLoadingContent.pluginFallbackType != Ci.nsIObjectLoadingContent.PLUGIN_PLAY_PREVIEW, "Test 2, plugin fallback type should not be PLUGIN_PLAY_PREVIEW");
ok(!objLoadingContent.activated, "Test 2, Plugin should not be activated");
registerPlayPreview('application/x-unknown', 'about:');
prepareTest(test3, gTestRoot + "plugin_test.html");
}
// Tests a page with a working plugin in it -- diffent play preview type is reserved.
function test3() {
var doc = gTestBrowser.contentDocument;
var plugin = doc.getElementById("test");
var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
ok(objLoadingContent.pluginFallbackType != Ci.nsIObjectLoadingContent.PLUGIN_PLAY_PREVIEW, "Test 3, plugin fallback type should not be PLUGIN_PLAY_PREVIEW");
ok(!objLoadingContent.activated, "Test 3, Plugin should not be activated");
unregisterPlayPreview();
registerPlayPreview('application/x-test', 'about:');
Services.prefs.setBoolPref("plugins.click_to_play", false);
prepareTest(test4, gTestRoot + "plugin_test.html");
}
// Tests a page with a working plugin in it -- click-to-play is off
function test4() {
var plugin = gTestBrowser.contentDocument.getElementById("test");
var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
ok(objLoadingContent.activated, "Test 4, Plugin should be activated");
finishTest();
}

View File

@ -0,0 +1,62 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
function test() {
waitForExplicitFinish();
if (!("@mozilla.org/datareporting/service;1" in Cc)) {
ok(true, "Firefox Health Report is not enabled.");
finish();
return;
}
let reporter = Cc["@mozilla.org/datareporting/service;1"]
.getService()
.wrappedJSObject
.healthReporter;
ok(reporter, "Health Reporter available.");
reporter.onInit().then(function onInit() {
let provider = reporter.getProvider("org.mozilla.searches");
ok(provider, "Searches provider is available.");
let m = provider.getMeasurement("counts", 1);
m.getValues().then(function onData(data) {
let now = new Date();
let oldCount = 0;
// This will need changed if default search engine is not Google.
let field = "google.urlbar";
if (data.days.hasDay(now)) {
let day = data.days.getDay(now);
if (day.has(field)) {
oldCount = day.get(field);
}
}
let tab = gBrowser.addTab();
gBrowser.selectedTab = tab;
gURLBar.value = "firefox health report";
gURLBar.handleCommand();
executeSoon(function afterSearch() {
gBrowser.removeTab(tab);
m.getValues().then(function onData(data) {
ok(data.days.hasDay(now), "FHR has data for today.");
let day = data.days.getDay(now);
ok(day.has(field), "FHR has url bar count for today.");
let newCount = day.get(field);
is(newCount, oldCount + 1, "Exactly one search has been recorded.");
finish();
});
});
});
});
}

View File

@ -0,0 +1,27 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<script type="text/javascript">
function crash() {
var plugin = document.getElementById("plugin");
var argStr = decodeURIComponent(window.location.search.substr(1));
if (argStr) {
var args = JSON.parse(argStr);
for (var key in args)
plugin.setAttribute(key, args[key]);
}
try {
plugin.crash();
}
catch (err) {}
}
</script>
</head>
<body onload="crash();">
<embed id="plugin" type="application/x-test"
width="400" height="400"
drawmode="solid" color="FF00FFFF">
</embed>
</body>
</html>

View File

@ -290,8 +290,33 @@ BrowserGlue.prototype = {
case "profile-before-change":
this._onProfileShutdown();
break;
#ifdef MOZ_SERVICES_HEALTHREPORT
case "keyword-search":
// This is very similar to code in
// browser.js:BrowserSearch.recordSearchInHealthReport(). The code could
// be consolidated if there is will. We need the observer in
// nsBrowserGlue to prevent double counting.
let reporter = Cc["@mozilla.org/datareporting/service;1"]
.getService()
.wrappedJSObject
.healthReporter;
if (!reporter) {
return;
}
reporter.onInit().then(function record() {
try {
reporter.getProvider("org.mozilla.searches").recordSearch(data,
"urlbar");
} catch (ex) {
Cu.reportError(ex);
}
});
break;
#endif
}
},
},
// initialization (called on application startup)
_init: function BG__init() {
@ -322,6 +347,9 @@ BrowserGlue.prototype = {
os.addObserver(this, "defaultURIFixup-using-keyword-pref", false);
os.addObserver(this, "handle-xul-text-link", false);
os.addObserver(this, "profile-before-change", false);
#ifdef MOZ_SERVICES_HEALTHREPORT
os.addObserver(this, "keyword-search", false);
#endif
},
// cleanup (called on application shutdown)
@ -353,6 +381,9 @@ BrowserGlue.prototype = {
os.removeObserver(this, "defaultURIFixup-using-keyword-pref");
os.removeObserver(this, "handle-xul-text-link");
os.removeObserver(this, "profile-before-change");
#ifdef MOZ_SERVICES_HEALTHREPORT
os.removeObserver(this, "keyword-search");
#endif
},
_onAppDefaults: function BG__onAppDefaults() {

View File

@ -3,6 +3,7 @@
ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL}
ac_add_options --enable-update-packaging
ac_add_options --with-l10n-base=../../l10n-central
ac_add_options --enable-metro
export MOZILLA_OFFICIAL=1

View File

@ -6,6 +6,7 @@
const Cu = Components.utils;
Cu.import("resource:///modules/devtools/gDevTools.jsm");
Cu.import("resource:///modules/devtools/ProfilerController.jsm");
Cu.import("resource:///modules/devtools/ProfilerHelpers.jsm");
Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js");
@ -14,10 +15,11 @@ Cu.import("resource://gre/modules/XPCOMUtils.jsm");
this.EXPORTED_SYMBOLS = ["ProfilerPanel"];
XPCOMUtils.defineLazyGetter(this, "DebuggerServer", function () {
Cu.import("resource://gre/modules/devtools/dbg-server.jsm");
return DebuggerServer;
});
XPCOMUtils.defineLazyModuleGetter(this, "DebuggerServer",
"resource://gre/modules/devtools/dbg-server.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "Services",
"resource://gre/modules/Services.jsm");
/**
* An instance of a profile UI. Profile UI consists of
@ -105,6 +107,9 @@ function ProfileUI(uid, panel) {
break;
case "enabled":
this.emit("enabled");
break;
case "displaysource":
this.panel.displaySource(event.data.data);
}
}.bind(this));
}
@ -219,6 +224,7 @@ ProfilerPanel.prototype = {
_uid: null,
_activeUid: null,
_runningUid: null,
_browserWin: null,
get activeProfile() {
return this.profiles.get(this._activeUid);
@ -228,6 +234,21 @@ ProfilerPanel.prototype = {
this._activeUid = profile.uid;
},
get browserWindow() {
if (this._browserWin) {
return this._browserWin;
}
let win = this.window.top;
let type = win.document.documentElement.getAttribute("windowtype");
if (type !== "navigator:browser") {
win = Services.wm.getMostRecentWindow("navigator:browser");
}
return this._browserWin = win;
},
/**
* Open a debug connection and, on success, switch to the newly created
* profile.
@ -416,6 +437,48 @@ ProfilerPanel.prototype = {
}
},
/**
* Open file specified in data in either a debugger or view-source.
*
* @param object data
* An object describing the file. It must have three properties:
* - uri
* - line
* - isChrome (chrome files are opened via view-source)
*/
displaySource: function PP_displaySource(data, onOpen=function() {}) {
let win = this.window;
let panelWin, timeout;
function onSourceShown(event) {
if (event.detail.url !== data.uri) {
return;
}
panelWin.removeEventListener("Debugger:SourceShown", onSourceShown, false);
panelWin.editor.setCaretPosition(data.line - 1);
onOpen();
}
if (data.isChrome) {
return void this.browserWindow.gViewSourceUtils.
viewSource(data.uri, null, this.document, data.line);
}
gDevTools.showToolbox(this.target, "jsdebugger").then(function (toolbox) {
let dbg = toolbox.getCurrentPanel();
panelWin = dbg.panelWin;
let view = dbg.panelWin.DebuggerView;
if (view.Source && view.Sources.selectedValue === data.uri) {
return void view.editor.setCaretPosition(data.line - 1);
}
panelWin.addEventListener("Debugger:SourceShown", onSourceShown, false);
panelWin.DebuggerView.Sources.preferredSource = data.uri;
}.bind(this));
},
/**
* Cleanup.
*/

View File

@ -15,15 +15,19 @@ var gInstanceUID;
* - stop, when user wants to stop profiling.
* - disabled, when the profiler was disabled
* - enabled, when the profiler was enabled
* - displaysource, when user wants to display source
* @param object data (optional)
* Additional data to send to the parent page.
*/
function notifyParent(status) {
function notifyParent(status, data={}) {
if (!gInstanceUID) {
gInstanceUID = window.location.search.substr(1);
}
window.parent.postMessage({
uid: gInstanceUID,
status: status
status: status,
data: data
}, "*");
}
@ -197,7 +201,7 @@ function enterFinishedProfileUI() {
var currentBreadcrumb = gSampleFilters;
gBreadcrumbTrail.add({
title: "Complete Profile",
title: gStrings["Complete Profile"],
enterCallback: function () {
gSampleFilters = [];
filtersChanged();

View File

@ -466,7 +466,8 @@ TreeView.prototype = {
'<span class="resourceIcon" data-resource="' + node.library + '"></span> ' +
'<span class="functionName">' + nodeName + '</span>' +
'<span class="libraryName">' + libName + '</span>' +
'<input type="button" value="Focus Callstack" title="Focus Callstack" class="focusCallstackButton" tabindex="-1">';
(nodeName === '(total)' ? '' :
'<input type="button" value="Focus Callstack" title="Focus Callstack" class="focusCallstackButton" tabindex="-1">');
},
_resolveChildren: function TreeView__resolveChildren(div, childrenCollapsedValue) {
while (div.pendingExpand != null && div.pendingExpand.length > 0) {

View File

@ -169,8 +169,12 @@ function ProfileTreeManager() {
self._onContextMenuClick(e);
});
this.treeView.addEventListener("focusCallstackButtonClicked", function (frameData) {
var focusedCallstack = self._getCallstackUpTo(frameData);
focusOnCallstack(focusedCallstack, frameData.name);
// NOTE: Not in the original Cleopatra source code.
notifyParent("displaysource", {
line: frameData.scriptLocation.lineInformation,
uri: frameData.scriptLocation.scriptURI,
isChrome: /^otherhost_*/.test(frameData.library)
});
});
this._container = document.createElement("div");
this._container.className = "tree";
@ -1566,7 +1570,8 @@ function focusOnSymbol(focusSymbol, name) {
}
function focusOnCallstack(focusedCallstack, name, overwriteCallstack) {
var invertCallback = gInvertCallstack;
var invertCallstack = gInvertCallstack;
if (overwriteCallstack != null) {
invertCallstack = overwriteCallstack;
}

View File

@ -10,12 +10,21 @@ relativesrcdir = @relativesrcdir@
include $(DEPTH)/config/autoconf.mk
MOCHITEST_BROWSER_FILES = \
MOCHITEST_BROWSER_TESTS = \
browser_profiler_run.js \
browser_profiler_controller.js \
browser_profiler_profiles.js \
browser_profiler_remote.js \
browser_profiler_bug_830664_multiple_profiles.js \
browser_profiler_bug_834878_source_buttons.js \
head.js \
$(NULL)
MOCHITEST_BROWSER_PAGES = \
mock_profiler_bug_834878_page.html \
mock_profiler_bug_834878_script.js \
$(NULL)
MOCHITEST_BROWSER_FILES_PARTS = MOCHITEST_BROWSER_TESTS MOCHITEST_BROWSER_PAGES
include $(topsrcdir)/config/rules.mk

View File

@ -0,0 +1,29 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
const BASE = "http://example.com/browser/browser/devtools/profiler/test/";
const URL = BASE + "mock_profiler_bug_834878_page.html";
const SCRIPT = BASE + "mock_profiler_bug_834878_script.js";
function test() {
waitForExplicitFinish();
setUp(URL, function onSetUp(tab, browser, panel) {
panel.once("profileCreated", function () {
let data = { uri: SCRIPT, line: 5, isChrome: false };
panel.displaySource(data, function onOpen() {
let target = TargetFactory.forTab(tab);
let dbg = gDevTools.getToolbox(target).getPanel("jsdebugger");
let view = dbg.panelWin.DebuggerView;
is(view.Sources.selectedValue, data.uri, "URI is different");
is(view.editor.getCaretPosition().line, data.line - 1, "Line is different");
tearDown(tab);
});
});
panel.createProfile();
});
}

View File

@ -0,0 +1,14 @@
<!-- Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ -->
<!DOCTYPE HTML>
<html>
<head>
<meta charset='utf-8'/>
<title>Profiler Script Linking Test</title>
<script type="text/javascript" src="mock_profiler_bug_834878_script.js">
</script>
</head>
<body>
</body>
</html>

View File

@ -0,0 +1,7 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
function main() {
console.log("Hello, World!");
return 0;
}

View File

@ -139,7 +139,6 @@
#ifdef ACCESSIBILITY
#ifdef XP_WIN32
@BINPATH@/AccessibleMarshal.dll
@BINPATH@/components/accessibility-msaa.xpt
#endif
@BINPATH@/components/accessibility.xpt
#endif

View File

@ -6,6 +6,37 @@
; to launch the Win8 metro browser or desktop browser.
!define DELEGATE_EXECUTE_HANDLER_ID {5100FEC1-212B-4BF5-9BF8-3E650FD794A3}
; Does metro registration for the command execute handler
Function RegisterCEH
!ifdef MOZ_METRO
${If} ${AtLeastWin8}
${CleanupMetroBrowserHandlerValues} ${DELEGATE_EXECUTE_HANDLER_ID}
${AddMetroBrowserHandlerValues} ${DELEGATE_EXECUTE_HANDLER_ID} \
"$INSTDIR\CommandExecuteHandler.exe" \
$AppUserModelID \
"FirefoxURL" \
"FirefoxHTML"
${EndIf}
!endif
FunctionEnd
; If MOZ_METRO is defined and we're at least win8, then we should re-create
; the start menu shortcut so that the Metro browser is accessible.
; This is also for zip builds who won't have a start menu shortcut yet.
Function CreateStartMenuTile
!ifdef MOZ_METRO
Delete "$SMPROGRAMS\${BrandFullName}.lnk"
CreateShortCut "$SMPROGRAMS\${BrandFullName}.lnk" "$INSTDIR\${FileMainEXE}"
${If} ${FileExists} "$SMPROGRAMS\${BrandFullName}.lnk"
ShellLink::SetShortCutWorkingDirectory "$SMPROGRAMS\${BrandFullName}.lnk" \
"$INSTDIR"
${If} "$AppUserModelID" != ""
ApplicationID::Set "$SMPROGRAMS\${BrandFullName}.lnk" "$AppUserModelID" "true"
${EndIf}
${EndIf}
!endif
FunctionEnd
!macro PostUpdate
${CreateShortcutsLog}
@ -23,6 +54,10 @@
; Win7 taskbar and start menu link maintenance
Call FixShortcutAppModelIDs
; Win8 specific registration
Call RegisterCEH
Call CreateStartMenuTile
ClearErrors
WriteRegStr HKLM "Software\Mozilla" "${BrandShortName}InstallerTest" "Write Test"
${If} ${Errors}
@ -342,16 +377,7 @@
${AddDisabledDDEHandlerValues} "FirefoxURL" "$2" "$8,1" "${AppRegName} URL" \
"true"
!ifdef MOZ_METRO
${If} ${AtLeastWin8}
${CleanupMetroBrowserHandlerValues} ${DELEGATE_EXECUTE_HANDLER_ID}
${AddMetroBrowserHandlerValues} ${DELEGATE_EXECUTE_HANDLER_ID} \
"$INSTDIR\CommandExecuteHandler.exe" \
$AppUserModelID \
"FirefoxURL" \
"FirefoxHTML"
${EndIf}
!endif
Call RegisterCEH
; An empty string is used for the 4th & 5th params because the following
; protocol handlers already have a display name and the additional keys
@ -1149,20 +1175,7 @@ Function SetAsDefaultAppUserHKCU
${SetStartMenuInternet} "HKCU"
${FixShellIconHandler} "HKCU"
${FixClassKeys} ; Does not use SHCTX
; If MOZ_METRO is defined and we're at least win8, then we should re-create
; the start menu shortcut so that the Metro browser is accessible.
; This is also for zip builds who won't have a start menu shortcut yet.
!ifdef MOZ_METRO
Delete "$SMPROGRAMS\${BrandFullName}.lnk"
CreateShortCut "$SMPROGRAMS\${BrandFullName}.lnk" "$INSTDIR\${FileMainEXE}"
${If} ${FileExists} "$SMPROGRAMS\${BrandFullName}.lnk"
ShellLink::SetShortCutWorkingDirectory "$SMPROGRAMS\${BrandFullName}.lnk" \
"$INSTDIR"
${If} "$AppUserModelID" != ""
ApplicationID::Set "$SMPROGRAMS\${BrandFullName}.lnk" "$AppUserModelID" "true"
${EndIf}
${EndIf}
!endif
Call CreateStartMenuTile
${EndIf}
${SetHandlers}

View File

@ -18,7 +18,7 @@ profiler.label=Profiler
# LOCALIZATION NOTE (profiler.commandkey, profiler.accesskey)
# Used for the menuitem in the tool menu
profiler.commandkey=Y
profiler.accesskey=Y
profiler.accesskey=P
# LOCALIZATION NOTE (profiler.tooltip):
# This string is displayed in the tooltip of the tab when the profiler is

View File

@ -5,6 +5,10 @@
#include "CEHHelper.h"
#ifdef SHOW_CONSOLE
#include <io.h> // _open_osfhandle
#endif
HANDLE sCon;
LPCWSTR metroDX10Available = L"MetroD3DAvailable";

View File

@ -21,7 +21,7 @@ extern LPCWSTR metroDX10Available;
void Log(const wchar_t *fmt, ...);
#if defined(SHOW_CONSOLE)
static void SetupConsole();
void SetupConsole();
#endif
bool IsDX10Available();

View File

@ -146,7 +146,7 @@ public:
#ifdef SHOW_CONSOLE
Log(L"SetSelection param count: %d", count);
for (int idx = 0; idx < count; idx++) {
for (DWORD idx = 0; idx < count; idx++) {
IShellItem* item = NULL;
if (SUCCEEDED(aArray->GetItemAt(idx, &item))) {
LPWSTR str = NULL;

View File

@ -56,13 +56,13 @@ fi
CLANG_CC=
CLANG_CXX=
if test "$GCC" = yes; then
if test "`$CC -v 2>&1 | grep -c 'clang version'`" != "0"; then
if test "`$CC -v 2>&1 | grep -c 'clang version\|Apple.*clang'`" != "0"; then
CLANG_CC=1
fi
fi
if test "$GXX" = yes; then
if test "`$CXX -v 2>&1 | grep -c 'clang version'`" != "0"; then
if test "`$CXX -v 2>&1 | grep -c 'clang version\|Apple.*clang'`" != "0"; then
CLANG_CXX=1
fi
fi

View File

@ -533,6 +533,10 @@ user_pref("network.activity.blipIntervalMilliseconds", 250);
// Don't allow the Data Reporting service to prompt for policy acceptance.
user_pref("datareporting.policy.dataSubmissionPolicyBypassAcceptance", true);
// Point Firefox Health Report at a local server. We don't care if it actually
// works. It just can't hit the default production endpoint.
user_pref("datareporting.healthreport.documentServerURI", "http://%(server)s/healthreport/");
// Make sure CSS error reporting is enabled for tests
user_pref("layout.css.report_errors", true);
""" % { "server" : self.webServer + ":" + str(self.httpPort) }
@ -1290,4 +1294,5 @@ user_pref("camino.use_system_proxy_settings", false); // Camino-only, harmless t
def elf_arm(self, filename):
data = open(filename, 'rb').read(20)
return data[:4] == "\x7fELF" and ord(data[18]) == 40 # EM_ARM
return data[:4] == "\x7fELF" and ord(data[18]) == 40 # EM_ARM

View File

@ -40,7 +40,6 @@
#include "nsIScriptGlobalObject.h"
#include "nsPIDOMWindow.h"
#include "nsIDocShell.h"
#include "nsIDocShellTreeItem.h"
#include "nsIPrompt.h"
#include "nsIWindowWatcher.h"
#include "nsIConsoleService.h"

View File

@ -589,6 +589,13 @@ endif
endif
endif
ifdef _MSC_VER
ifeq ($(CPU_ARCH),x86_64)
# set stack to 2MB on x64 build. See bug 582910
WIN32_EXE_LDFLAGS += -STACK:2097152
endif
endif
# If we're building a component on MSVC, we don't want to generate an
# import lib, because that import lib will collide with the name of a
# static version of the same library.

View File

@ -267,6 +267,14 @@ class SectionFinder(object):
syms.append((tmp[-1], tmp[0]))
return syms
def print_command(out, args):
print >>out, "Executing: " + " ".join(args)
for tmp in [f for f in args.tmp if os.path.isfile(f)]:
print >>out, tmp + ":"
with open(tmp) as file:
print >>out, "".join([" " + l for l in file.readlines()])
out.flush()
def main():
parser = OptionParser()
parser.add_option("--depend", dest="depend", metavar="FILE",
@ -302,15 +310,15 @@ def main():
args.makelist()
if options.verbose:
print >>sys.stderr, "Executing: " + " ".join(args)
for tmp in [f for f in args.tmp if os.path.isfile(f)]:
print >>sys.stderr, tmp + ":"
with open(tmp) as file:
print >>sys.stderr, "".join([" " + l for l in file.readlines()])
sys.stderr.flush()
ret = subprocess.call(args)
if ret:
exit(ret)
print_command(sys.stderr, args)
proc = subprocess.Popen(args, stdout = subprocess.PIPE, stderr = subprocess.STDOUT)
(stdout, stderr) = proc.communicate()
if proc.returncode and not options.verbose:
print_command(sys.stderr, args)
sys.stderr.write(stdout)
sys.stderr.flush()
if proc.returncode:
exit(proc.returncode)
if not options.depend:
return
ensureParentDir(options.depend)

View File

@ -32,8 +32,3 @@ ifneq (,$(filter OS2 WINNT,$(OS_ARCH))) # {
else # } {
$(RM) -f $(DIST)/sdk/lib/$(LIB_PREFIX)nspr4.$(LIB_SUFFIX) $(DIST)/sdk/lib/$(LIB_PREFIX)plc4.$(LIB_SUFFIX) $(DIST)/sdk/lib/$(LIB_PREFIX)plds4.$(LIB_SUFFIX)
endif # }
install::
$(MAKE) -C $(DEPTH)/nsprpub install DESTDIR=$(DESTDIR) libdir=$(mozappdir) includedir=$(includedir)/nspr
$(RM) -f $(addprefix $(DESTDIR)$(mozappdir)/$(LIB_PREFIX), $(addsuffix .$(LIB_SUFFIX), nspr4 plds4 plc4))
$(RM) -f $(addprefix $(DESTDIR)$(bindir)/,nspr-config compile-et.pl prerr.properties)

View File

@ -1,10 +0,0 @@
# 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/.
TIERS += nspr
ifndef MOZ_NATIVE_NSPR
tier_nspr_staticdirs += nsprpub
tier_nspr_dirs += config/nspr
endif

View File

@ -18,7 +18,7 @@ interface nsINode;
* @version 1.0
*/
[scriptable, uuid(12cf5a4d-fffb-4f2f-9cec-c65195661d76)]
[scriptable, builtinclass, uuid(12cf5a4d-fffb-4f2f-9cec-c65195661d76)]
interface nsISelection : nsISupports
{
/**

View File

@ -31,7 +31,7 @@ struct ScrollAxis;
native nsDirection(nsDirection);
native ScrollAxis(nsIPresShell::ScrollAxis);
[scriptable, uuid(2e44b10f-7d6d-4bf4-92e2-f9551d22f422)]
[scriptable, builtinclass, uuid(2e44b10f-7d6d-4bf4-92e2-f9551d22f422)]
interface nsISelectionPrivate : nsISelection
{
const short ENDOFPRECEDINGLINE=0;

View File

@ -89,7 +89,6 @@
#include "nsGenericHTMLElement.h"
#include "nsIEditor.h"
#include "nsIEditorIMESupport.h"
#include "nsIEditorDocShell.h"
#include "nsEventDispatcher.h"
#include "nsContentCreatorFunctions.h"
#include "nsIControllers.h"

View File

@ -88,7 +88,6 @@
#include "nsGenericHTMLElement.h"
#include "nsIEditor.h"
#include "nsIEditorIMESupport.h"
#include "nsIEditorDocShell.h"
#include "nsEventDispatcher.h"
#include "nsContentCreatorFunctions.h"
#include "nsIControllers.h"

View File

@ -6,7 +6,6 @@
#include "nsCCUncollectableMarker.h"
#include "nsIObserverService.h"
#include "nsIDocShell.h"
#include "nsIDocShellTreeItem.h"
#include "nsServiceManagerUtils.h"
#include "nsIContentViewer.h"
#include "nsIDocument.h"

View File

@ -17,7 +17,6 @@
#include "nsStyleLinkElement.h"
#include "nsIDocShell.h"
#include "nsILoadContext.h"
#include "nsIDocShellTreeItem.h"
#include "nsCPrefetchService.h"
#include "nsIURI.h"
#include "nsNetUtil.h"
@ -807,22 +806,18 @@ nsContentSink::PrefetchHref(const nsAString &aHref,
nsCOMPtr<nsIDocShell> docshell = mDocShell;
nsCOMPtr<nsIDocShellTreeItem> treeItem, parentItem;
nsCOMPtr<nsIDocShellTreeItem> parentItem;
do {
uint32_t appType = 0;
nsresult rv = docshell->GetAppType(&appType);
if (NS_FAILED(rv) || appType == nsIDocShell::APP_TYPE_MAIL)
return; // do not prefetch from mailnews
treeItem = do_QueryInterface(docshell);
if (treeItem) {
treeItem->GetParent(getter_AddRefs(parentItem));
if (parentItem) {
treeItem = parentItem;
docshell = do_QueryInterface(treeItem);
if (!docshell) {
NS_ERROR("cannot get a docshell from a treeItem!");
return;
}
docshell->GetParent(getter_AddRefs(parentItem));
if (parentItem) {
docshell = do_QueryInterface(parentItem);
if (!docshell) {
NS_ERROR("cannot get a docshell from a treeItem!");
return;
}
}
} while (parentItem);

View File

@ -41,7 +41,6 @@
#include "nsPIDOMWindow.h"
#include "nsIJSContextStack.h"
#include "nsIDocShell.h"
#include "nsIDocShellTreeItem.h"
#include "nsParserCIID.h"
#include "nsIParser.h"
#include "nsIFragmentContentSink.h"
@ -160,7 +159,6 @@
#include "nsICharsetDetectionObserver.h"
#include "nsIPlatformCharset.h"
#include "nsIEditor.h"
#include "nsIEditorDocShell.h"
#include "mozilla/Attributes.h"
#include "nsIParserService.h"
#include "nsIDOMScriptObjectFactory.h"
@ -6123,15 +6121,15 @@ nsContentUtils::CheckCCWrapperTraversal(void* aScriptObjectHolder,
DebugWrapperTraversalCallback callback(wrapper);
aTracer->Traverse(aScriptObjectHolder, callback);
NS_ASSERTION(callback.mFound,
"Cycle collection participant didn't traverse to preserved "
"wrapper! This will probably crash.");
MOZ_ASSERT(callback.mFound,
"Cycle collection participant didn't traverse to preserved "
"wrapper! This will probably crash.");
callback.mFound = false;
aTracer->Trace(aScriptObjectHolder, DebugWrapperTraceCallback, &callback);
NS_ASSERTION(callback.mFound,
"Cycle collection participant didn't trace preserved wrapper! "
"This will probably crash.");
MOZ_ASSERT(callback.mFound,
"Cycle collection participant didn't trace preserved wrapper! "
"This will probably crash.");
}
#endif
@ -6802,14 +6800,14 @@ nsIEditor*
nsContentUtils::GetHTMLEditor(nsPresContext* aPresContext)
{
nsCOMPtr<nsISupports> container = aPresContext->GetContainer();
nsCOMPtr<nsIEditorDocShell> editorDocShell(do_QueryInterface(container));
nsCOMPtr<nsIDocShell> docShell(do_QueryInterface(container));
bool isEditable;
if (!editorDocShell ||
NS_FAILED(editorDocShell->GetEditable(&isEditable)) || !isEditable)
if (!docShell ||
NS_FAILED(docShell->GetEditable(&isEditable)) || !isEditable)
return nullptr;
nsCOMPtr<nsIEditor> editor;
editorDocShell->GetEditor(getter_AddRefs(editor));
docShell->GetEditor(getter_AddRefs(editor));
return editor;
}

View File

@ -34,12 +34,11 @@
#include "nsICharsetConverterManager.h"
#include "nsGkAtoms.h"
#include "nsIContent.h"
#include "nsIEnumerator.h"
#include "nsIParserService.h"
#include "nsIScriptContext.h"
#include "nsIScriptGlobalObject.h"
#include "nsIScriptSecurityManager.h"
#include "nsISelection.h"
#include "mozilla/Selection.h"
#include "nsISelectionPrivate.h"
#include "nsITransferable.h" // for kUnicodeMime
#include "nsContentUtils.h"
@ -49,7 +48,6 @@
#include "nsIFrame.h"
#include "nsStringBuffer.h"
#include "mozilla/dom/Element.h"
#include "nsIEditorDocShell.h"
#include "nsIEditor.h"
#include "nsIHTMLEditor.h"
#include "nsIDocShell.h"
@ -344,17 +342,14 @@ IsInvisibleBreak(nsINode *aNode) {
if (window) {
nsIDocShell *docShell = window->GetDocShell();
if (docShell) {
nsCOMPtr<nsIEditorDocShell> editorDocShell = do_QueryInterface(docShell);
if (editorDocShell) {
nsCOMPtr<nsIEditor> editor;
editorDocShell->GetEditor(getter_AddRefs(editor));
nsCOMPtr<nsIHTMLEditor> htmlEditor = do_QueryInterface(editor);
if (htmlEditor) {
bool isVisible = false;
nsCOMPtr<nsIDOMNode> domNode = do_QueryInterface(aNode);
htmlEditor->BreakIsVisible(domNode, &isVisible);
return !isVisible;
}
nsCOMPtr<nsIEditor> editor;
docShell->GetEditor(getter_AddRefs(editor));
nsCOMPtr<nsIHTMLEditor> htmlEditor = do_QueryInterface(editor);
if (htmlEditor) {
bool isVisible = false;
nsCOMPtr<nsIDOMNode> domNode = do_QueryInterface(aNode);
htmlEditor->BreakIsVisible(domNode, &isVisible);
return !isVisible;
}
}
}
@ -1348,19 +1343,17 @@ nsHTMLCopyEncoder::SetSelection(nsISelection* aSelection)
nsCOMPtr<nsIDOMRange> range;
nsCOMPtr<nsIDOMNode> commonParent;
int32_t count = 0;
nsresult rv = aSelection->GetRangeCount(&count);
NS_ENSURE_SUCCESS(rv, rv);
Selection* selection = static_cast<Selection*>(aSelection);
uint32_t rangeCount = selection->GetRangeCount();
// if selection is uninitialized return
if (!count)
if (!rangeCount)
return NS_ERROR_FAILURE;
// we'll just use the common parent of the first range. Implicit assumption
// here that multi-range selections are table cell selections, in which case
// the common parent is somewhere in the table and we don't really care where.
rv = aSelection->GetRangeAt(0, getter_AddRefs(range));
nsresult rv = aSelection->GetRangeAt(0, getter_AddRefs(range));
NS_ENSURE_SUCCESS(rv, rv);
if (!range)
return NS_ERROR_NULL_POINTER;
@ -1412,25 +1405,10 @@ nsHTMLCopyEncoder::SetSelection(nsISelection* aSelection)
//NS_ENSURE_SUCCESS(rv, rv);
NS_NewDomSelection(getter_AddRefs(mSelection));
NS_ENSURE_TRUE(mSelection, NS_ERROR_FAILURE);
nsCOMPtr<nsISelectionPrivate> privSelection( do_QueryInterface(aSelection) );
NS_ENSURE_TRUE(privSelection, NS_ERROR_FAILURE);
// get selection range enumerator
nsCOMPtr<nsIEnumerator> enumerator;
rv = privSelection->GetEnumerator(getter_AddRefs(enumerator));
NS_ENSURE_SUCCESS(rv, rv);
NS_ENSURE_TRUE(enumerator, NS_ERROR_FAILURE);
// loop thru the ranges in the selection
enumerator->First();
nsCOMPtr<nsISupports> currentItem;
while (static_cast<nsresult>(NS_ENUMERATOR_FALSE) == enumerator->IsDone())
{
rv = enumerator->CurrentItem(getter_AddRefs(currentItem));
NS_ENSURE_SUCCESS(rv, rv);
NS_ENSURE_TRUE(currentItem, NS_ERROR_FAILURE);
range = do_QueryInterface(currentItem);
for (uint32_t rangeIdx = 0; rangeIdx < rangeCount; ++rangeIdx) {
range = selection->GetRangeAt(rangeIdx);
NS_ENSURE_TRUE(range, NS_ERROR_FAILURE);
nsCOMPtr<nsIDOMRange> myRange;
range->CloneRange(getter_AddRefs(myRange));
@ -1442,8 +1420,6 @@ nsHTMLCopyEncoder::SetSelection(nsISelection* aSelection)
rv = mSelection->AddRange(myRange);
NS_ENSURE_SUCCESS(rv, rv);
enumerator->Next();
}
return NS_OK;

View File

@ -28,8 +28,6 @@
#include "nsIWebNavigation.h"
#include "nsIWebProgress.h"
#include "nsIDocShell.h"
#include "nsIDocShellTreeItem.h"
#include "nsIDocShellTreeNode.h"
#include "nsIDocShellTreeOwner.h"
#include "nsIDocShellLoadInfo.h"
#include "nsIDOMApplicationRegistry.h"
@ -55,7 +53,6 @@
#include "nsIDOMHTMLDocument.h"
#include "nsIXULWindow.h"
#include "nsIEditor.h"
#include "nsIEditorDocShell.h"
#include "nsIMozBrowserFrame.h"
#include "nsIPermissionManager.h"
@ -99,6 +96,7 @@
#endif
using namespace mozilla;
using namespace mozilla::hal;
using namespace mozilla::dom;
using namespace mozilla::dom::ipc;
using namespace mozilla::layers;
@ -853,26 +851,22 @@ nsFrameLoader::Show(int32_t marginWidth, int32_t marginHeight,
if (designMode.EqualsLiteral("on")) {
// Hold on to the editor object to let the document reattach to the
// same editor object, instead of creating a new one.
nsCOMPtr<nsIEditorDocShell> editorDocshell = do_QueryInterface(mDocShell);
nsCOMPtr<nsIEditor> editor;
nsresult rv = editorDocshell->GetEditor(getter_AddRefs(editor));
nsresult rv = mDocShell->GetEditor(getter_AddRefs(editor));
NS_ENSURE_SUCCESS(rv, false);
doc->SetDesignMode(NS_LITERAL_STRING("off"));
doc->SetDesignMode(NS_LITERAL_STRING("on"));
} else {
// Re-initialize the presentation for contenteditable documents
nsCOMPtr<nsIEditorDocShell> editorDocshell = do_QueryInterface(mDocShell);
if (editorDocshell) {
bool editable = false,
hasEditingSession = false;
editorDocshell->GetEditable(&editable);
editorDocshell->GetHasEditingSession(&hasEditingSession);
nsCOMPtr<nsIEditor> editor;
editorDocshell->GetEditor(getter_AddRefs(editor));
if (editable && hasEditingSession && editor) {
editor->PostCreate();
}
bool editable = false,
hasEditingSession = false;
mDocShell->GetEditable(&editable);
mDocShell->GetHasEditingSession(&hasEditingSession);
nsCOMPtr<nsIEditor> editor;
mDocShell->GetEditor(getter_AddRefs(editor));
if (editable && hasEditingSession && editor) {
editor->PostCreate();
}
}
}
@ -1030,12 +1024,9 @@ nsFrameLoader::SwapWithOtherLoader(nsFrameLoader* aOther,
// To avoid having to mess with session history, avoid swapping
// frameloaders that don't correspond to root same-type docshells,
// unless both roots have session history disabled.
nsCOMPtr<nsIDocShellTreeItem> ourTreeItem = do_QueryInterface(ourDocshell);
nsCOMPtr<nsIDocShellTreeItem> otherTreeItem =
do_QueryInterface(otherDocshell);
nsCOMPtr<nsIDocShellTreeItem> ourRootTreeItem, otherRootTreeItem;
ourTreeItem->GetSameTypeRootTreeItem(getter_AddRefs(ourRootTreeItem));
otherTreeItem->GetSameTypeRootTreeItem(getter_AddRefs(otherRootTreeItem));
ourDocshell->GetSameTypeRootTreeItem(getter_AddRefs(ourRootTreeItem));
otherDocshell->GetSameTypeRootTreeItem(getter_AddRefs(otherRootTreeItem));
nsCOMPtr<nsIWebNavigation> ourRootWebnav =
do_QueryInterface(ourRootTreeItem);
nsCOMPtr<nsIWebNavigation> otherRootWebnav =
@ -1050,7 +1041,7 @@ nsFrameLoader::SwapWithOtherLoader(nsFrameLoader* aOther,
ourRootWebnav->GetSessionHistory(getter_AddRefs(ourHistory));
otherRootWebnav->GetSessionHistory(getter_AddRefs(otherHistory));
if ((ourRootTreeItem != ourTreeItem || otherRootTreeItem != otherTreeItem) &&
if ((ourRootTreeItem != ourDocshell || otherRootTreeItem != otherDocshell) &&
(ourHistory || otherHistory)) {
return NS_ERROR_NOT_IMPLEMENTED;
}
@ -1060,8 +1051,8 @@ nsFrameLoader::SwapWithOtherLoader(nsFrameLoader* aOther,
// the code below needs to be audited as it assumes identical types.
int32_t ourType = nsIDocShellTreeItem::typeChrome;
int32_t otherType = nsIDocShellTreeItem::typeChrome;
ourTreeItem->GetItemType(&ourType);
otherTreeItem->GetItemType(&otherType);
ourDocshell->GetItemType(&ourType);
otherDocshell->GetItemType(&otherType);
if (ourType != otherType) {
return NS_ERROR_NOT_IMPLEMENTED;
}
@ -1071,21 +1062,21 @@ nsFrameLoader::SwapWithOtherLoader(nsFrameLoader* aOther,
// nsIDocShellTreeItem::typeContent then all of our descendants are the same
// type as us.
if (ourType != nsIDocShellTreeItem::typeContent &&
(!AllDescendantsOfType(ourTreeItem, ourType) ||
!AllDescendantsOfType(otherTreeItem, otherType))) {
(!AllDescendantsOfType(ourDocshell, ourType) ||
!AllDescendantsOfType(otherDocshell, otherType))) {
return NS_ERROR_NOT_IMPLEMENTED;
}
// Save off the tree owners, frame elements, chrome event handlers, and
// docshell and document parents before doing anything else.
nsCOMPtr<nsIDocShellTreeOwner> ourOwner, otherOwner;
ourTreeItem->GetTreeOwner(getter_AddRefs(ourOwner));
otherTreeItem->GetTreeOwner(getter_AddRefs(otherOwner));
ourDocshell->GetTreeOwner(getter_AddRefs(ourOwner));
otherDocshell->GetTreeOwner(getter_AddRefs(otherOwner));
// Note: it's OK to have null treeowners.
nsCOMPtr<nsIDocShellTreeItem> ourParentItem, otherParentItem;
ourTreeItem->GetParent(getter_AddRefs(ourParentItem));
otherTreeItem->GetParent(getter_AddRefs(otherParentItem));
ourDocshell->GetParent(getter_AddRefs(ourParentItem));
otherDocshell->GetParent(getter_AddRefs(otherParentItem));
if (!ourParentItem || !otherParentItem) {
return NS_ERROR_NOT_IMPLEMENTED;
}
@ -1163,25 +1154,25 @@ nsFrameLoader::SwapWithOtherLoader(nsFrameLoader* aOther,
// Fire pageshow events on still-loading pages, and then fire pagehide
// events. Note that we do NOT fire these in the normal way, but just fire
// them on the chrome event handlers.
FirePageShowEvent(ourTreeItem, ourChromeEventHandler, false);
FirePageShowEvent(otherTreeItem, otherChromeEventHandler, false);
FirePageHideEvent(ourTreeItem, ourChromeEventHandler);
FirePageHideEvent(otherTreeItem, otherChromeEventHandler);
FirePageShowEvent(ourDocshell, ourChromeEventHandler, false);
FirePageShowEvent(otherDocshell, otherChromeEventHandler, false);
FirePageHideEvent(ourDocshell, ourChromeEventHandler);
FirePageHideEvent(otherDocshell, otherChromeEventHandler);
nsIFrame* ourFrame = ourContent->GetPrimaryFrame();
nsIFrame* otherFrame = otherContent->GetPrimaryFrame();
if (!ourFrame || !otherFrame) {
mInSwap = aOther->mInSwap = false;
FirePageShowEvent(ourTreeItem, ourChromeEventHandler, true);
FirePageShowEvent(otherTreeItem, otherChromeEventHandler, true);
FirePageShowEvent(ourDocshell, ourChromeEventHandler, true);
FirePageShowEvent(otherDocshell, otherChromeEventHandler, true);
return NS_ERROR_NOT_IMPLEMENTED;
}
nsSubDocumentFrame* ourFrameFrame = do_QueryFrame(ourFrame);
if (!ourFrameFrame) {
mInSwap = aOther->mInSwap = false;
FirePageShowEvent(ourTreeItem, ourChromeEventHandler, true);
FirePageShowEvent(otherTreeItem, otherChromeEventHandler, true);
FirePageShowEvent(ourDocshell, ourChromeEventHandler, true);
FirePageShowEvent(otherDocshell, otherChromeEventHandler, true);
return NS_ERROR_NOT_IMPLEMENTED;
}
@ -1189,31 +1180,31 @@ nsFrameLoader::SwapWithOtherLoader(nsFrameLoader* aOther,
rv = ourFrameFrame->BeginSwapDocShells(otherFrame);
if (NS_FAILED(rv)) {
mInSwap = aOther->mInSwap = false;
FirePageShowEvent(ourTreeItem, ourChromeEventHandler, true);
FirePageShowEvent(otherTreeItem, otherChromeEventHandler, true);
FirePageShowEvent(ourDocshell, ourChromeEventHandler, true);
FirePageShowEvent(otherDocshell, otherChromeEventHandler, true);
return rv;
}
// Now move the docshells to the right docshell trees. Note that this
// resets their treeowners to null.
ourParentItem->RemoveChild(ourTreeItem);
otherParentItem->RemoveChild(otherTreeItem);
ourParentItem->RemoveChild(ourDocshell);
otherParentItem->RemoveChild(otherDocshell);
if (ourType == nsIDocShellTreeItem::typeContent) {
ourOwner->ContentShellRemoved(ourTreeItem);
otherOwner->ContentShellRemoved(otherTreeItem);
ourOwner->ContentShellRemoved(ourDocshell);
otherOwner->ContentShellRemoved(otherDocshell);
}
ourParentItem->AddChild(otherTreeItem);
otherParentItem->AddChild(ourTreeItem);
ourParentItem->AddChild(otherDocshell);
otherParentItem->AddChild(ourDocshell);
// Restore the correct chrome event handlers.
ourDocshell->SetChromeEventHandler(otherChromeEventHandler);
otherDocshell->SetChromeEventHandler(ourChromeEventHandler);
// Restore the correct treeowners
// (and also chrome event handlers for content frames only).
SetTreeOwnerAndChromeEventHandlerOnDocshellTree(ourTreeItem, otherOwner,
SetTreeOwnerAndChromeEventHandlerOnDocshellTree(ourDocshell, otherOwner,
ourType == nsIDocShellTreeItem::typeContent ? otherChromeEventHandler : nullptr);
SetTreeOwnerAndChromeEventHandlerOnDocshellTree(otherTreeItem, ourOwner,
SetTreeOwnerAndChromeEventHandlerOnDocshellTree(otherDocshell, ourOwner,
ourType == nsIDocShellTreeItem::typeContent ? ourChromeEventHandler : nullptr);
// Switch the owner content before we start calling AddTreeItemToTreeOwner.
@ -1222,8 +1213,8 @@ nsFrameLoader::SwapWithOtherLoader(nsFrameLoader* aOther,
SetOwnerContent(otherContent);
aOther->SetOwnerContent(ourContent);
AddTreeItemToTreeOwner(ourTreeItem, otherOwner, otherParentType, nullptr);
aOther->AddTreeItemToTreeOwner(otherTreeItem, ourOwner, ourParentType,
AddTreeItemToTreeOwner(ourDocshell, otherOwner, otherParentType, nullptr);
aOther->AddTreeItemToTreeOwner(otherDocshell, ourOwner, ourParentType,
nullptr);
// SetSubDocumentFor nulls out parent documents on the old child doc if a
@ -1307,8 +1298,8 @@ nsFrameLoader::SwapWithOtherLoader(nsFrameLoader* aOther,
ourParentDocument->FlushPendingNotifications(Flush_Layout);
otherParentDocument->FlushPendingNotifications(Flush_Layout);
FirePageShowEvent(ourTreeItem, otherChromeEventHandler, true);
FirePageShowEvent(otherTreeItem, ourChromeEventHandler, true);
FirePageShowEvent(ourDocshell, otherChromeEventHandler, true);
FirePageShowEvent(otherDocshell, ourChromeEventHandler, true);
mInSwap = aOther->mInSwap = false;
return NS_OK;
@ -1360,13 +1351,12 @@ nsFrameLoader::Destroy()
// Let the tree owner know we're gone.
if (mIsTopLevelContent) {
nsCOMPtr<nsIDocShellTreeItem> ourItem = do_QueryInterface(mDocShell);
if (ourItem) {
if (mDocShell) {
nsCOMPtr<nsIDocShellTreeItem> parentItem;
ourItem->GetParent(getter_AddRefs(parentItem));
mDocShell->GetParent(getter_AddRefs(parentItem));
nsCOMPtr<nsIDocShellTreeOwner> owner = do_GetInterface(parentItem);
if (owner) {
owner->ContentShellRemoved(ourItem);
owner->ContentShellRemoved(mDocShell);
}
}
}
@ -1569,8 +1559,7 @@ nsFrameLoader::MaybeCreateDocShell()
}
// Get the frame name and tell the docshell about it.
nsCOMPtr<nsIDocShellTreeItem> docShellAsItem(do_QueryInterface(mDocShell));
NS_ENSURE_TRUE(docShellAsItem, NS_ERROR_FAILURE);
NS_ENSURE_TRUE(mDocShell, NS_ERROR_FAILURE);
nsAutoString frameName;
int32_t namespaceID = mOwnerContent->GetNameSpaceID();
@ -1586,7 +1575,7 @@ nsFrameLoader::MaybeCreateDocShell()
}
if (!frameName.IsEmpty()) {
docShellAsItem->SetName(frameName.get());
mDocShell->SetName(frameName.get());
}
// If our container is a web-shell, inform it that it has a new
@ -1610,7 +1599,7 @@ nsFrameLoader::MaybeCreateDocShell()
parentAsItem->GetTreeOwner(getter_AddRefs(parentTreeOwner));
NS_ENSURE_STATE(parentTreeOwner);
mIsTopLevelContent =
AddTreeItemToTreeOwner(docShellAsItem, parentTreeOwner, parentType,
AddTreeItemToTreeOwner(mDocShell, parentTreeOwner, parentType,
parentAsNode);
// Make sure all shells have links back to the content element
@ -1734,19 +1723,16 @@ nsFrameLoader::CheckForRecursiveLoad(nsIURI* aURI)
return NS_ERROR_FAILURE;
}
nsCOMPtr<nsIDocShellTreeItem> treeItem = do_QueryInterface(mDocShell);
NS_ASSERTION(treeItem, "docshell must be a treeitem!");
// Check that we're still in the docshell tree.
nsCOMPtr<nsIDocShellTreeOwner> treeOwner;
treeItem->GetTreeOwner(getter_AddRefs(treeOwner));
mDocShell->GetTreeOwner(getter_AddRefs(treeOwner));
NS_WARN_IF_FALSE(treeOwner,
"Trying to load a new url to a docshell without owner!");
NS_ENSURE_STATE(treeOwner);
int32_t ourType;
rv = treeItem->GetItemType(&ourType);
rv = mDocShell->GetItemType(&ourType);
if (NS_SUCCEEDED(rv) && ourType != nsIDocShellTreeItem::typeContent) {
// No need to do recursion-protection here XXXbz why not?? Do we really
// trust people not to screw up with non-content docshells?
@ -1756,7 +1742,7 @@ nsFrameLoader::CheckForRecursiveLoad(nsIURI* aURI)
// Bug 8065: Don't exceed some maximum depth in content frames
// (MAX_DEPTH_CONTENT_FRAMES)
nsCOMPtr<nsIDocShellTreeItem> parentAsItem;
treeItem->GetSameTypeParent(getter_AddRefs(parentAsItem));
mDocShell->GetSameTypeParent(getter_AddRefs(parentAsItem));
int32_t depth = 0;
while (parentAsItem) {
++depth;
@ -1775,7 +1761,7 @@ nsFrameLoader::CheckForRecursiveLoad(nsIURI* aURI)
// Bug 136580: Check for recursive frame loading
int32_t matchCount = 0;
treeItem->GetSameTypeParent(getter_AddRefs(parentAsItem));
mDocShell->GetSameTypeParent(getter_AddRefs(parentAsItem));
while (parentAsItem) {
// Check the parent URI with the URI we're loading
nsCOMPtr<nsIWebNavigation> parentAsNav(do_QueryInterface(parentAsItem));
@ -2060,19 +2046,9 @@ nsFrameLoader::TryRemoteBrowser()
context.SetTabContextForBrowserFrame(containingApp, scrollingBehavior);
}
mRemoteBrowser = ContentParent::CreateBrowserOrApp(context);
nsCOMPtr<nsIDOMElement> ownerElement = do_QueryInterface(mOwnerContent);
mRemoteBrowser = ContentParent::CreateBrowserOrApp(context, ownerElement);
if (mRemoteBrowser) {
nsCOMPtr<nsIDOMElement> element = do_QueryInterface(mOwnerContent);
mRemoteBrowser->SetOwnerElement(element);
// If we're an app, send the frame element's mozapptype down to the child
// process. This ends up in TabChild::GetAppType().
if (ownApp) {
nsAutoString appType;
mOwnerContent->GetAttr(kNameSpaceID_None, nsGkAtoms::mozapptype, appType);
mRemoteBrowser->SendSetAppType(appType);
}
nsCOMPtr<nsIDocShellTreeItem> rootItem;
parentAsItem->GetRootTreeItem(getter_AddRefs(rootItem));
nsCOMPtr<nsIDOMWindow> rootWin = do_GetInterface(rootItem);
@ -2481,14 +2457,12 @@ nsFrameLoader::AttributeChanged(nsIDocument* aDocument,
// Notify our enclosing chrome that our type has changed. We only do this
// if our parent is chrome, since in all other cases we're random content
// subframes and the treeowner shouldn't worry about us.
nsCOMPtr<nsIDocShellTreeItem> docShellAsItem(do_QueryInterface(mDocShell));
if (!docShellAsItem) {
if (!mDocShell) {
return;
}
nsCOMPtr<nsIDocShellTreeItem> parentItem;
docShellAsItem->GetParent(getter_AddRefs(parentItem));
mDocShell->GetParent(getter_AddRefs(parentItem));
if (!parentItem) {
return;
}
@ -2516,18 +2490,18 @@ nsFrameLoader::AttributeChanged(nsIDocument* aDocument,
if (!is_primary) {
nsXULPopupManager* pm = nsXULPopupManager::GetInstance();
if (pm)
pm->HidePopupsInDocShell(docShellAsItem);
pm->HidePopupsInDocShell(mDocShell);
}
#endif
parentTreeOwner->ContentShellRemoved(docShellAsItem);
parentTreeOwner->ContentShellRemoved(mDocShell);
if (value.LowerCaseEqualsLiteral("content") ||
StringBeginsWith(value, NS_LITERAL_STRING("content-"),
nsCaseInsensitiveStringComparator())) {
bool is_targetable = is_primary ||
value.LowerCaseEqualsLiteral("content-targetable");
parentTreeOwner->ContentShellAdded(docShellAsItem, is_primary,
parentTreeOwner->ContentShellAdded(mDocShell, is_primary,
is_targetable, value);
}
}

View File

@ -342,6 +342,7 @@ GK_ATOM(events, "events")
GK_ATOM(excludeResultPrefixes, "exclude-result-prefixes")
GK_ATOM(excludes, "excludes")
GK_ATOM(expr, "expr")
GK_ATOM(expectingSystemMessage, "expecting-system-message")
GK_ATOM(extends, "extends")
GK_ATOM(extensionElementPrefixes, "extension-element-prefixes")
GK_ATOM(face, "face")

View File

@ -33,7 +33,6 @@
#include "nsIScriptElement.h"
#include "nsAttrName.h"
#include "nsIDocShell.h"
#include "nsIEditorDocShell.h"
#include "nsIEditor.h"
#include "nsIHTMLEditor.h"
#include "mozilla/dom/Element.h"

View File

@ -58,7 +58,6 @@
#include "nsIDOMMutationEvent.h"
#include "nsIDOMNodeList.h"
#include "nsIDOMUserDataHandler.h"
#include "nsIEditorDocShell.h"
#include "nsIEditor.h"
#include "nsIEditorIMESupport.h"
#include "nsIFrame.h"

View File

@ -9,7 +9,6 @@
#include "nsINode.h"
#include "nsCOMPtr.h"
#include "nsIDocShell.h"
#include "nsIDocShellTreeItem.h"
#include "nsISecurityEventSink.h"
#include "nsIWebProgressListener.h"
#include "nsContentUtils.h"
@ -61,12 +60,11 @@ public:
// set the approriate flag to true if we are about to load Mixed Active
// Content.
nsCOMPtr<nsIDocShell> docShell = NS_CP_GetDocShellFromContext(mContext);
nsCOMPtr<nsIDocShellTreeItem> currentDocShellTreeItem(do_QueryInterface(docShell));
if (!currentDocShellTreeItem) {
if (!docShell) {
return NS_OK;
}
nsCOMPtr<nsIDocShellTreeItem> sameTypeRoot;
currentDocShellTreeItem->GetSameTypeRootTreeItem(getter_AddRefs(sameTypeRoot));
docShell->GetSameTypeRootTreeItem(getter_AddRefs(sameTypeRoot));
NS_ASSERTION(sameTypeRoot, "No document shell root tree item from document shell tree item!");
// now get the document from sameTypeRoot
@ -368,10 +366,8 @@ nsMixedContentBlocker::ShouldLoad(uint32_t aContentType,
}
// Get the root document from the docshell
nsCOMPtr<nsIDocShellTreeItem> currentDocShellTreeItem(do_QueryInterface(docShell));
NS_ASSERTION(currentDocShellTreeItem, "No DocShellTreeItem from docshell");
nsCOMPtr<nsIDocShellTreeItem> sameTypeRoot;
currentDocShellTreeItem->GetSameTypeRootTreeItem(getter_AddRefs(sameTypeRoot));
docShell->GetSameTypeRootTreeItem(getter_AddRefs(sameTypeRoot));
NS_ASSERTION(sameTypeRoot, "No document shell root tree item from document shell tree item!");
nsCOMPtr<nsIDocument> rootDoc = do_GetInterface(sameTypeRoot);
NS_ASSERTION(rootDoc, "No root document from document shell root tree item.");

View File

@ -1758,26 +1758,20 @@ nsObjectLoadingContent::LoadObject(bool aNotify,
}
}
// Items resolved as Image/Document will not be checked for previews, as well
// as invalid plugins (they will not have the mContentType set).
if ((mType == eType_Null || mType == eType_Plugin) && ShouldPreview()) {
// If plugin preview exists, we shall use it
LOG(("OBJLC [%p]: Using plugin preview", this));
mType = eType_Null;
fallbackType = eFallbackPlayPreview;
}
// If we're a plugin but shouldn't start yet, load fallback with
// reason click-to-play instead
// reason click-to-play instead. Items resolved as Image/Document
// will not be checked for previews, as well as invalid plugins
// (they will not have the mContentType set).
FallbackType clickToPlayReason;
if (mType == eType_Plugin && !ShouldPlay(clickToPlayReason)) {
if ((mType == eType_Null || mType == eType_Plugin) &&
!ShouldPlay(clickToPlayReason)) {
LOG(("OBJLC [%p]: Marking plugin as click-to-play", this));
mType = eType_Null;
fallbackType = clickToPlayReason;
}
if (!mActivated && mType == eType_Plugin) {
// Object passed ShouldPlay and !ShouldPreview, so it should be considered
// Object passed ShouldPlay, so it should be considered
// activated until it changes content type
LOG(("OBJLC [%p]: Object implicitly activated", this));
mActivated = true;
@ -2649,18 +2643,6 @@ nsObjectLoadingContent::CancelPlayPreview()
return NS_OK;
}
bool
nsObjectLoadingContent::ShouldPreview()
{
if (mPlayPreviewCanceled || mActivated)
return false;
nsRefPtr<nsPluginHost> pluginHost =
already_AddRefed<nsPluginHost>(nsPluginHost::GetInst());
return pluginHost->IsPluginPlayPreviewForType(mContentType.get());
}
bool
nsObjectLoadingContent::ShouldPlay(FallbackType &aReason)
{
@ -2671,6 +2653,25 @@ nsObjectLoadingContent::ShouldPlay(FallbackType &aReason)
nsRefPtr<nsPluginHost> pluginHost =
already_AddRefed<nsPluginHost>(nsPluginHost::GetInst());
nsCOMPtr<nsIPluginPlayPreviewInfo> playPreviewInfo;
bool isPlayPreviewSpecified = NS_SUCCEEDED(pluginHost->GetPlayPreviewInfo(
mContentType, getter_AddRefs(playPreviewInfo)));
bool ignoreCTP = false;
if (isPlayPreviewSpecified) {
playPreviewInfo->GetIgnoreCTP(&ignoreCTP);
}
if (isPlayPreviewSpecified && !mPlayPreviewCanceled && !mActivated &&
ignoreCTP) {
// play preview in ignoreCTP mode is shown even if the native plugin
// is not present/installed
aReason = eFallbackPlayPreview;
return false;
}
// at this point if it's not a plugin, we let it play/fallback
if (mType != eType_Plugin) {
return true;
}
bool isCTP;
nsresult rv = pluginHost->IsPluginClickToPlayForType(mContentType, &isCTP);
if (NS_FAILED(rv)) {
@ -2735,6 +2736,12 @@ nsObjectLoadingContent::ShouldPlay(FallbackType &aReason)
allowPerm = permission == nsIPermissionManager::ALLOW_ACTION;
}
if (aReason == eFallbackClickToPlay && isPlayPreviewSpecified &&
!mPlayPreviewCanceled && !ignoreCTP) {
// play preview in click-to-play mode is shown instead of standard CTP UI
aReason = eFallbackPlayPreview;
}
return allowPerm;
}

View File

@ -301,11 +301,6 @@ class nsObjectLoadingContent : public nsImageLoadingContent
*/
bool ShouldPlay(FallbackType &aReason);
/**
* If the object should display preview content for the current mContentType
*/
bool ShouldPreview();
/**
* Helper to check if our current URI passes policy
*

View File

@ -43,8 +43,6 @@
#include "nsIDocShell.h"
#include "nsIDOMWindow.h"
#include "nsPIDOMWindow.h"
#include "nsIDocShellTreeItem.h"
#include "nsIDocShellTreeNode.h"
#include "nsIXPConnect.h"
#include "nsDisplayList.h"

View File

@ -11,8 +11,6 @@
#include "nsPIDOMWindow.h"
#include "nsIDOMWindow.h"
#include "nsIDocShell.h"
#include "nsIDocShellTreeNode.h"
#include "nsIDocShellTreeItem.h"
#include "nsIInterfaceRequestorUtils.h"
#include "nsComponentManagerUtils.h"
#include "nsCSSParser.h"

View File

@ -25,7 +25,6 @@
#include "nsCRT.h"
#include "nsIScriptObjectPrincipal.h"
#include "nsIWebNavigation.h"
#include "nsIDocShellTreeItem.h"
#include "nsIScriptContext.h"
using namespace mozilla;

View File

@ -20,7 +20,6 @@
#include "nsIPresShell.h"
#include "nsDOMEvent.h"
#include "nsGkAtoms.h"
#include "nsIEditorDocShell.h"
#include "nsIFormControl.h"
#include "nsIComboboxControlFrame.h"
#include "nsIScrollableFrame.h"
@ -33,8 +32,6 @@
#include "nsPIDOMWindow.h"
#include "nsPIWindowRoot.h"
#include "nsIEnumerator.h"
#include "nsIDocShellTreeItem.h"
#include "nsIDocShellTreeNode.h"
#include "nsIWebNavigation.h"
#include "nsIContentViewer.h"
#include <algorithm>

View File

@ -11,7 +11,6 @@
#include "nsISupports.h"
#include "nsPIDOMWindow.h"
#include "nsIInterfaceRequestorUtils.h"
#include "nsIEditorDocShell.h"
#include "nsIContent.h"
#include "nsIDocument.h"
#include "nsPresContext.h"

View File

@ -19,7 +19,7 @@
#include "AudioStream.h"
#include "VideoFrameContainer.h"
#include "mozilla/CORSMode.h"
#include "nsDOMMediaStream.h"
#include "DOMMediaStream.h"
#include "mozilla/Mutex.h"
#include "nsTimeRanges.h"
#include "nsIDOMWakeLock.h"
@ -54,6 +54,7 @@ public:
typedef mozilla::MetadataTags MetadataTags;
typedef mozilla::AudioStream AudioStream;
typedef mozilla::MediaDecoder MediaDecoder;
typedef mozilla::DOMMediaStream DOMMediaStream;
mozilla::CORSMode GetCORSMode() {
return mCORSMode;
@ -368,7 +369,7 @@ protected:
/**
* Initialize the media element for playback of aStream
*/
void SetupSrcMediaStreamPlayback(nsDOMMediaStream* aStream);
void SetupSrcMediaStreamPlayback(DOMMediaStream* aStream);
/**
* Stop playback on mSrcStream.
*/
@ -381,7 +382,7 @@ protected:
* When aFinishWhenEnded is false, ending playback does not finish the stream.
* The stream will never finish.
*/
already_AddRefed<nsDOMMediaStream> CaptureStreamInternal(bool aFinishWhenEnded);
already_AddRefed<DOMMediaStream> CaptureStreamInternal(bool aFinishWhenEnded);
/**
* Create a decoder for the given aMIMEType. Returns null if we
@ -639,17 +640,17 @@ protected:
// Holds a reference to the DOM wrapper for the MediaStream that has been
// set in the src attribute.
nsRefPtr<nsDOMMediaStream> mSrcAttrStream;
nsRefPtr<DOMMediaStream> mSrcAttrStream;
// Holds a reference to the DOM wrapper for the MediaStream that we're
// actually playing.
// At most one of mDecoder and mSrcStream can be non-null.
nsRefPtr<nsDOMMediaStream> mSrcStream;
nsRefPtr<DOMMediaStream> mSrcStream;
// Holds references to the DOM wrappers for the MediaStreams that we're
// writing to.
struct OutputMediaStream {
nsRefPtr<nsDOMMediaStream> mStream;
nsRefPtr<DOMMediaStream> mStream;
bool mFinishWhenEnded;
};
nsTArray<OutputMediaStream> mOutputStreams;

View File

@ -19,7 +19,6 @@
#include "nsMappedAttributes.h"
#include "nsRuleData.h"
#include "nsIDocShell.h"
#include "nsIEditorDocShell.h"
#include "nsRuleWalker.h"
#include "nsGlobalWindow.h"
@ -476,12 +475,12 @@ HTMLBodyElement::GetAssociatedEditor()
}
nsCOMPtr<nsISupports> container = presContext->GetContainer();
nsCOMPtr<nsIEditorDocShell> editorDocShell = do_QueryInterface(container);
if (!editorDocShell) {
nsCOMPtr<nsIDocShell> docShell = do_QueryInterface(container);
if (!docShell) {
return nullptr;
}
editorDocShell->GetEditor(getter_AddRefs(editor));
docShell->GetEditor(getter_AddRefs(editor));
return editor.forget();
}

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