about:config - merge with trunk

This commit is contained in:
Daniel Brooks 2010-10-29 14:18:58 -05:00
commit 2895410af9
1446 changed files with 14258 additions and 9805 deletions

View File

@ -91,14 +91,6 @@ nsAccDocManager::FindAccessibleInCache(nsINode* aNode) const
return arg.mAccessible;
}
void
nsAccDocManager::ShutdownDocAccessiblesInTree(nsIDocument *aDocument)
{
nsCOMPtr<nsISupports> container = aDocument->GetContainer();
nsCOMPtr<nsIDocShellTreeItem> treeItem = do_QueryInterface(container);
ShutdownDocAccessiblesInTree(treeItem, aDocument);
}
////////////////////////////////////////////////////////////////////////////////
// nsAccDocManager protected
@ -132,21 +124,6 @@ nsAccDocManager::Shutdown()
ClearDocCache();
}
void
nsAccDocManager::ShutdownDocAccessible(nsIDocument *aDocument)
{
nsDocAccessible* docAccessible = mDocAccessibleCache.GetWeak(aDocument);
if (!docAccessible)
return;
// We're allowed to not remove listeners when accessible document is shutdown
// since we don't keep strong reference on chrome event target and listeners
// are removed automatically when chrome event target goes away.
docAccessible->Shutdown();
mDocAccessibleCache.Remove(aDocument);
}
////////////////////////////////////////////////////////////////////////////////
// nsISupports
@ -316,7 +293,14 @@ nsAccDocManager::HandleEvent(nsIDOMEvent *aEvent)
return NS_OK;
// Shutdown this one and sub document accessibles.
ShutdownDocAccessiblesInTree(document);
// We're allowed to not remove listeners when accessible document is
// shutdown since we don't keep strong reference on chrome event target and
// listeners are removed automatically when chrome event target goes away.
nsDocAccessible* docAccessible = mDocAccessibleCache.GetWeak(document);
if (docAccessible)
docAccessible->Shutdown();
return NS_OK;
}
@ -500,35 +484,6 @@ nsAccDocManager::CreateDocOrRootAccessible(nsIDocument *aDocument)
return docAcc;
}
void
nsAccDocManager::ShutdownDocAccessiblesInTree(nsIDocShellTreeItem *aTreeItem,
nsIDocument *aDocument)
{
nsCOMPtr<nsIDocShellTreeNode> treeNode(do_QueryInterface(aTreeItem));
if (treeNode) {
PRInt32 subDocumentsCount = 0;
treeNode->GetChildCount(&subDocumentsCount);
for (PRInt32 idx = 0; idx < subDocumentsCount; idx++) {
nsCOMPtr<nsIDocShellTreeItem> treeItemChild;
treeNode->GetChildAt(idx, getter_AddRefs(treeItemChild));
NS_ASSERTION(treeItemChild, "No tree item when there should be");
if (!treeItemChild)
continue;
nsCOMPtr<nsIDocShell> docShell(do_QueryInterface(treeItemChild));
nsCOMPtr<nsIContentViewer> contentViewer;
docShell->GetContentViewer(getter_AddRefs(contentViewer));
if (!contentViewer)
continue;
ShutdownDocAccessiblesInTree(treeItemChild, contentViewer->GetDocument());
}
}
ShutdownDocAccessible(aDocument);
}
////////////////////////////////////////////////////////////////////////////////
// nsAccDocManager static

View File

@ -75,13 +75,6 @@ public:
*/
nsAccessible* FindAccessibleInCache(nsINode* aNode) const;
/**
* Shutdown document accessibles in the tree starting from the given one.
*
* @param aDocument [in] the DOM document of start document accessible
*/
void ShutdownDocAccessiblesInTree(nsIDocument *aDocument);
/**
* Return document accessible from the cache. Convenient method for testing.
*/
@ -90,6 +83,14 @@ public:
return mDocAccessibleCache.GetWeak(aDocument);
}
/**
* Called by document accessible when it gets shutdown.
*/
inline void NotifyOfDocumentShutdown(nsIDocument* aDocument)
{
mDocAccessibleCache.Remove(aDocument);
}
protected:
nsAccDocManager() { };
@ -103,11 +104,6 @@ protected:
*/
void Shutdown();
/**
* Shutdown the document accessible.
*/
void ShutdownDocAccessible(nsIDocument* aDocument);
private:
nsAccDocManager(const nsAccDocManager&);
nsAccDocManager& operator =(const nsAccDocManager&);
@ -156,12 +152,6 @@ private:
*/
nsDocAccessible *CreateDocOrRootAccessible(nsIDocument *aDocument);
/**
* Shutdown document accessibles in the tree starting from given tree item.
*/
void ShutdownDocAccessiblesInTree(nsIDocShellTreeItem *aTreeItem,
nsIDocument *aDocument);
typedef nsRefPtrHashtable<nsPtrHashKey<const nsIDocument>, nsDocAccessible>
nsDocAccessibleHashtable;

View File

@ -382,7 +382,8 @@ nsAccessNode::ScrollTo(PRUint32 aScrollType)
PRInt16 vPercent, hPercent;
nsCoreUtils::ConvertScrollTypeToPercents(aScrollType, &vPercent, &hPercent);
return shell->ScrollContentIntoView(content, vPercent, hPercent);
return shell->ScrollContentIntoView(content, vPercent, hPercent,
nsIPresShell::SCROLL_OVERFLOW_HIDDEN);
}
NS_IMETHODIMP

View File

@ -543,7 +543,10 @@ nsAccessibilityService::PresShellDestroyed(nsIPresShell *aPresShell)
return;
NS_LOG_ACCDOCDESTROY("presshell destroyed", doc)
ShutdownDocAccessible(doc);
nsDocAccessible* docAccessible = GetDocAccessibleFromCache(doc);
if (docAccessible)
docAccessible->Shutdown();
}
void

View File

@ -2368,7 +2368,8 @@ nsAccessible::DispatchClickEvent(nsIContent *aContent, PRUint32 aActionIndex)
// Scroll into view.
presShell->ScrollContentIntoView(aContent, NS_PRESSHELL_SCROLL_ANYWHERE,
NS_PRESSHELL_SCROLL_ANYWHERE);
NS_PRESSHELL_SCROLL_ANYWHERE,
nsIPresShell::SCROLL_OVERFLOW_HIDDEN);
// Fire mouse down and mouse up events.
PRBool res = nsCoreUtils::DispatchMouseEvent(NS_MOUSE_BUTTON_DOWN, presShell,
@ -2766,6 +2767,13 @@ nsAccessible::RemoveChild(nsAccessible* aChild)
if (aChild->mParent != this || aChild->mIndexInParent == -1)
return PR_FALSE;
if (aChild->mIndexInParent >= mChildren.Length() ||
mChildren[aChild->mIndexInParent] != aChild) {
NS_ERROR("Child is bound to parent but parent hasn't this child at its index!");
aChild->UnbindFromParent();
return PR_FALSE;
}
for (PRUint32 idx = aChild->mIndexInParent + 1; idx < mChildren.Length(); idx++)
mChildren[idx]->mIndexInParent--;

View File

@ -675,6 +675,10 @@ nsDocAccessible::Shutdown()
mParent->RemoveChild(this);
}
PRUint32 childDocCount = mChildDocuments.Length();
for (PRUint32 idx = 0; idx < childDocCount; idx++)
mChildDocuments[idx]->Shutdown();
mChildDocuments.Clear();
mWeakShell = nsnull; // Avoid reentrancy
@ -686,6 +690,8 @@ nsDocAccessible::Shutdown()
mDocument = nsnull;
nsHyperTextAccessibleWrap::Shutdown();
GetAccService()->NotifyOfDocumentShutdown(kungFuDeathGripDoc);
}
nsIFrame*

View File

@ -169,7 +169,7 @@ nsOuterDocAccessible::Shutdown()
if (childAcc) {
NS_LOG_ACCDOCDESTROY("outerdoc's child document shutdown",
childAcc->GetDocumentNode())
GetAccService()->ShutdownDocAccessiblesInTree(childAcc->GetDocumentNode());
childAcc->Shutdown();
}
nsAccessibleWrap::Shutdown();

View File

@ -1538,7 +1538,7 @@ nsHyperTextAccessible::SetSelectionRange(PRInt32 aStartPos, PRInt32 aEndPos)
// XXX I'm not sure this can do synchronous scrolling. If the last param is
// set to true, this calling might flush the pending reflow. See bug 418470.
selCon->ScrollSelectionIntoView(nsISelectionController::SELECTION_NORMAL,
nsISelectionController::SELECTION_FOCUS_REGION, PR_FALSE);
nsISelectionController::SELECTION_FOCUS_REGION, 0);
}
return NS_OK;

View File

@ -972,8 +972,9 @@ var PlacesStarButton = {
this.updateState();
this._batching = false;
},
onItemAdded: function PSB_onItemAdded(aItemId, aFolder, aIndex, aItemType) {
onItemAdded: function PSB_onItemAdded(aItemId, aFolder, aIndex, aItemType,
aURI) {
if (!this._batching && !this._starred)
this.updateState();
},

View File

@ -819,8 +819,7 @@ const gFormSubmitObserver = {
return;
}
// Limit the message to 256 characters.
this.panel.firstChild.textContent = element.validationMessage.substring(0, 256);
this.panel.firstChild.textContent = element.validationMessage;
element.focus();
@ -3986,6 +3985,27 @@ var XULBrowserWindow = {
encodeURIComponent);
gURLBar.setOverLink(link);
},
// Called before links are navigated to to allow us to retarget them if needed.
onBeforeLinkTraversal: function(originalTarget, linkURI, linkNode, isAppTab) {
// Don't modify non-default targets or targets that aren't in top-level app
// tab docshells (isAppTab will be false for app tab subframes).
if (originalTarget != "" || !isAppTab)
return originalTarget;
let docURI = linkNode.ownerDocument.documentURIObject;
try {
let docURIDomain = Services.eTLD.getBaseDomain(docURI, 0);
let linkURIDomain = Services.eTLD.getBaseDomain(linkURI, 0);
// External links from within app tabs should always open in new tabs
// instead of replacing the app tab's page (Bug 575561)
if (docURIDomain != linkURIDomain)
return "_blank";
} catch(e) {
// If getBaseDomain fails, we return originalTarget below.
}
return originalTarget;
},
onLinkIconAvailable: function (aIconURL) {
if (gProxyFavIcon && gBrowser.userTypedValue === null)
@ -7487,6 +7507,7 @@ let gPrivateBrowsingUI = {
// temporary fix until bug 463607 is fixed
document.getElementById("Tools:Sanitize").setAttribute("disabled", "true");
let docElement = document.documentElement;
if (this._privateBrowsingService.autoStarted) {
// Disable the menu item in auto-start mode
document.getElementById("privateBrowsingItem")
@ -7497,15 +7518,16 @@ let gPrivateBrowsingUI = {
#endif
document.getElementById("Tools:PrivateBrowsing")
.setAttribute("disabled", "true");
if (window.location.href == getBrowserURL())
docElement.setAttribute("privatebrowsingmode", "permanent");
}
else if (window.location.href == getBrowserURL()) {
// Adjust the window's title
let docElement = document.documentElement;
docElement.setAttribute("title",
docElement.getAttribute("title_privatebrowsing"));
docElement.setAttribute("titlemodifier",
docElement.getAttribute("titlemodifier_privatebrowsing"));
docElement.setAttribute("browsingmode", "private");
docElement.setAttribute("privatebrowsingmode", "temporary");
gBrowser.updateTitlebar();
}
@ -7552,7 +7574,7 @@ let gPrivateBrowsingUI = {
docElement.getAttribute("title_normal"));
docElement.setAttribute("titlemodifier",
docElement.getAttribute("titlemodifier_normal"));
docElement.setAttribute("browsingmode", "normal");
docElement.removeAttribute("privatebrowsingmode");
}
// Enable the menu item in after exiting the auto-start mode

View File

@ -826,12 +826,7 @@
#ifdef WINCE
defaulticonsize="small" iconsize="small"
#endif
#ifdef XP_WIN
tabsontop="true"
#endif
#ifdef XP_MACOSX
tabsontop="true"
#endif
persist="tabsontop">
<!-- Menu -->
<toolbar type="menubar" id="toolbar-menubar" class="chromeclass-menubar" customizable="true"
@ -1014,7 +1009,9 @@
key="manBookmarkKb"/>
<menuseparator/>
<menuitem id="BMB_bookmarkThisPage"
#ifndef XP_MACOSX
class="menuitem-iconic"
#endif
label="&bookmarkThisPageCmd.label;"
command="Browser:AddBookmarkAs"
key="addBookmarkAsKb"/>

View File

@ -958,14 +958,17 @@ nsContextMenu.prototype = {
}
}
// in case we need to prompt the user for authentication
function callbacks() {}
callbacks.prototype = {
getInterface: function sLA_callbacks_getInterface(aIID) {
if (aIID.equals(Ci.nsIAuthPrompt) || aIID.equals(Ci.nsIAuthPrompt2)) {
var ww = Cc["@mozilla.org/embedcomp/window-watcher;1"].
getService(Ci.nsIPromptFactory);
return ww.getPrompt(doc.defaultView, aIID);
// If the channel demands authentication prompt, we must cancel it
// because the save-as-timer would expire and cancel the channel
// before we get credentials from user. Both authentication dialog
// and save as dialog would appear on the screen as we fall back to
// the old fashioned way after the timeout.
timer.cancel();
channel.cancel(NS_ERROR_SAVE_LINK_AS_TIMEOUT);
}
throw Cr.NS_ERROR_NO_INTERFACE;
}

View File

@ -191,6 +191,8 @@
this.tabContainer._positionPinnedTabs();
this.tabContainer.adjustTabstrip();
this.getBrowserForTab(aTab).docShell.isAppTab = true;
let event = document.createEvent("Events");
event.initEvent("TabPinned", true, false);
aTab.dispatchEvent(event);
@ -210,6 +212,8 @@
this.tabContainer._positionPinnedTabs();
this.tabContainer.adjustTabstrip();
this.getBrowserForTab(aTab).docShell.isAppTab = false;
let event = document.createEvent("Events");
event.initEvent("TabUnpinned", true, false);
aTab.dispatchEvent(event);

View File

@ -70,6 +70,7 @@ function GroupItem(listOfEls, options) {
options = {};
this._inited = false;
this._uninited = false;
this._children = []; // an array of Items
this.defaultSize = new Point(TabItems.tabWidth * 1.5, TabItems.tabHeight * 1.5);
this.isAGroupItem = true;
@ -366,7 +367,7 @@ GroupItem.prototype = Utils.extend(new Item(), new Subscribable(), {
// Function: save
// Saves this groupItem to persistent storage.
save: function GroupItem_save() {
if (!this._inited) // too soon to save now
if (!this._inited || this._uninited) // too soon/late to save
return;
var data = this.getStorageData();
@ -374,6 +375,14 @@ GroupItem.prototype = Utils.extend(new Item(), new Subscribable(), {
Storage.saveGroupItem(gWindow, data);
},
// ----------
// Function: deleteData
// Deletes the groupItem in the persistent storage.
deleteData: function GroupItem_deleteData() {
this._uninited = true;
Storage.deleteGroupItem(gWindow, this.id);
},
// ----------
// Function: getTitle
// Returns the title of this groupItem as a string.
@ -561,7 +570,7 @@ GroupItem.prototype = Utils.extend(new Item(), new Subscribable(), {
}
});
Storage.deleteGroupItem(gWindow, this.id);
this.deleteData();
},
// ----------
@ -647,7 +656,7 @@ GroupItem.prototype = Utils.extend(new Item(), new Subscribable(), {
self.$undoContainer = null;
Items.unsquish();
Storage.deleteGroupItem(gWindow, self.id);
self.deleteData();
};
this.$undoContainer.click(function(e) {
@ -2072,7 +2081,7 @@ let GroupItems = {
child.close();
});
Storage.deleteGroupItem(gWindow, groupItem.id);
groupItem.deleteData();
}
});
}

View File

@ -202,11 +202,10 @@ function TabItem(tab, options) {
this._updateDebugBounds();
TabItems.register(this);
if (!this.reconnected) {
if (!this.reconnected)
GroupItems.newTab(this, options);
}
// tabs which were not reconnected at all or were not immediately added
// to a group get the same treatment.
if (!this.reconnected || (reconnected && !reconnected.addedToGroup) ) {
@ -804,7 +803,7 @@ let TabItems = {
let oldURL = tabItem.url;
tabItem.url = tabUrl;
if (!tabItem.reconnected && (oldURL == 'about:blank' || !oldURL))
if (!tabItem.reconnected)
this.reconnect(tabItem);
tabItem.save();
@ -1057,10 +1056,10 @@ let TabItems = {
item.reconnected = true;
found = {addedToGroup: tabData.groupID};
} else {
// if it's not a blank tab or it belongs to a group, it would mean
// the item is reconnected.
item.reconnected =
(item.tab.linkedBrowser.currentURI.spec != 'about:blank' || item.parent);
// We should never have any orphaned tabs. Therefore, item is not
// connected if it has no parent and GroupItems.newTab() would handle
// the group creation.
item.reconnected = (item.parent != null);
}
item.save();

View File

@ -145,6 +145,7 @@ _BROWSER_FILES = \
browser_bug561636.js \
browser_bug562649.js \
browser_bug563588.js \
browser_bug575561.js \
browser_bug577121.js \
browser_bug579872.js \
browser_bug580956.js \
@ -218,6 +219,8 @@ _BROWSER_FILES = \
file_bug550565_favicon.ico \
browser_overLinkInLocationBar.js \
browser_aboutHome.js \
app_bug575561.html \
app_subframe_bug575561.html \
$(NULL)
# compartment-disabled

View File

@ -0,0 +1,16 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=575561
-->
<head>
<title>Test for links in app tabs</title>
</head>
<body>
<a href="http://example.com/browser/browser/base/content/test/dummy_page.html">same domain</a>
<a href="http://test1.example.com/browser/browser/base/content/test/dummy_page.html">same domain (different subdomain)</a>
<a href="http://example.org/browser/browser/base/content/test/dummy_page.html">different domain</a>
<a href="http://example.org/browser/browser/base/content/test/dummy_page.html" target="foo">different domain (with target)</a>
<iframe src="app_subframe_bug575561.html"></iframe>
</body>
</html>

View File

@ -0,0 +1,12 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=575561
-->
<head>
<title>Test for links in app tab subframes</title>
</head>
<body>
<a href="http://example.org/browser/browser/base/content/test/dummy_page.html">different domain</a>
</body>
</html>

View File

@ -608,6 +608,15 @@ function test() {
Services.obs.addObserver(XPInstallObserver, "addon-install-complete", false);
registerCleanupFunction(function() {
// Make sure no more test parts run in case we were timed out
TESTS = [];
AddonManager.getAllInstalls(function(aInstalls) {
aInstalls.forEach(function(aInstall) {
aInstall.cancel();
});
});
Services.prefs.clearUserPref("extensions.logging.enabled");
Services.obs.removeObserver(XPInstallObserver, "addon-install-started");

View File

@ -17,8 +17,8 @@ function checkPopupHide()
function checkPopupMessage(doc)
{
is(gInvalidFormPopup.firstChild.textContent,
doc.getElementById('i').validationMessage.substring(0,256),
"The panel should show the 256 first characters of the validationMessage");
doc.getElementById('i').validationMessage,
"The panel should show the message from validationMessage");
}
let gObserver = {
@ -132,50 +132,11 @@ function test3()
gBrowser.selectedTab.linkedBrowser.loadURI(uri);
}
/**
* In this test, we check that the validation message is correctly cut.
*/
function test4()
{
let uri = "data:text/html,<iframe name='t'></iframe><form target='t' action='data:text/html,'><input id='i'><input id='s' type='submit'></form>";
let tab = gBrowser.addTab();
gInvalidFormPopup.addEventListener("popupshown", function() {
gInvalidFormPopup.removeEventListener("popupshown", arguments.callee, false);
let doc = gBrowser.contentDocument;
is(doc.activeElement, doc.getElementById('i'),
"First invalid element should be focused");
checkPopupShow();
checkPopupMessage(doc);
// Clean-up and next test.
gBrowser.removeTab(gBrowser.selectedTab, {animate: false});
executeSoon(test5);
}, false);
tab.linkedBrowser.addEventListener("load", function(aEvent) {
tab.linkedBrowser.removeEventListener("load", arguments.callee, true);
let msg = "";
for (let i=0; i<50; ++i) {
msg += "abcde ";
}
// msg has 300 characters
gBrowser.contentDocument.getElementById('i').setCustomValidity(msg);
gBrowser.contentDocument.getElementById('s').click();
}, true);
gBrowser.selectedTab = tab;
gBrowser.selectedTab.linkedBrowser.loadURI(uri);
}
/**
* In this test, we check that, we can hide the popup by interacting with the
* invalid element.
*/
function test5()
function test4()
{
let uri = "data:text/html,<iframe name='t'></iframe><form target='t' action='data:text/html,'><input id='i' required><input id='s' type='submit'></form>";
let tab = gBrowser.addTab();
@ -197,7 +158,7 @@ function test5()
// Clean-up and next test.
gBrowser.removeTab(gBrowser.selectedTab, {animate: false});
executeSoon(test6);
executeSoon(test5);
});
}, false);
@ -215,7 +176,7 @@ function test5()
* In this test, we check that we can hide the popup by blurring the invalid
* element.
*/
function test6()
function test5()
{
let uri = "data:text/html,<iframe name='t'></iframe><form target='t' action='data:text/html,'><input id='i' required><input id='s' type='submit'></form>";
let tab = gBrowser.addTab();
@ -237,7 +198,7 @@ function test6()
// Clean-up and next test.
gBrowser.removeTab(gBrowser.selectedTab, {animate: false});
executeSoon(test7);
executeSoon(test6);
});
}, false);
@ -254,7 +215,7 @@ function test6()
/**
* In this test, we check that we can hide the popup by pressing TAB.
*/
function test7()
function test6()
{
let uri = "data:text/html,<iframe name='t'></iframe><form target='t' action='data:text/html,'><input id='i' required><input id='s' type='submit'></form>";
let tab = gBrowser.addTab();
@ -276,7 +237,7 @@ function test7()
// Clean-up and next test.
gBrowser.removeTab(gBrowser.selectedTab, {animate: false});
executeSoon(test8);
executeSoon(test7);
});
}, false);
@ -293,7 +254,7 @@ function test7()
/**
* In this test, we check that the popup will hide if we move to another tab.
*/
function test8()
function test7()
{
let uri = "data:text/html,<iframe name='t'></iframe><form target='t' action='data:text/html,'><input id='i' required><input id='s' type='submit'></form>";
let tab = gBrowser.addTab();
@ -317,7 +278,7 @@ function test8()
// Clean-up and next test.
gBrowser.removeTab(gBrowser.selectedTab, {animate: false});
gBrowser.removeTab(gBrowser.selectedTab, {animate: false});
executeSoon(test9);
executeSoon(test8);
});
}, false);
@ -336,7 +297,7 @@ function test8()
* invalid form is submitted in another tab than the current focused one
* (submitted in background).
*/
function test9()
function test8()
{
let uri = "data:text/html,<iframe name='t'></iframe><form target='t' action='data:text/html,'><input id='i' required><input id='s' type='submit'></form>";
let tab = gBrowser.addTab();
@ -355,7 +316,7 @@ function test9()
gBrowser.removeTab(tab, {animate: false});
// Next test
executeSoon(test10);
executeSoon(test9);
});
};
@ -376,7 +337,7 @@ function test9()
/**
* In this test, we check that the author defined error message is shown.
*/
function test10()
function test9()
{
let uri = "data:text/html,<iframe name='t'></iframe><form target='t' action='data:text/html,'><input x-moz-errormessage='foo' required id='i'><input id='s' type='submit'></form>";
let tab = gBrowser.addTab();

View File

@ -0,0 +1,77 @@
function test() {
waitForExplicitFinish();
// Pinned: Link to the same domain should not open a new tab
// Tests link to http://example.com/browser/browser/base/content/test/dummy_page.html
testLink(0, true, false, function() {
// Pinned: Link to the same domain should not open a new tab
// Tests link to http://test1.example.com/browser/browser/base/content/test/dummy_page.html
testLink(1, true, false, function() {
// Pinned: Link to a different domain should open a new tab
// Tests link to http://example.org/browser/browser/base/content/test/dummy_page.html
testLink(2, true, true, function() {
// Not Pinned: Link to a different domain should not open a new tab
// Tests link to http://example.org/browser/browser/base/content/test/dummy_page.html
testLink(2, false, false, function() {
// Pinned: Targetted link should open a new tab
// Tests link to http://example.org/browser/browser/base/content/test/dummy_page.html with target="foo"
testLink(3, true, true, function() {
// Pinned: Link in a subframe should not open a new tab
// Tests link to http://example.org/browser/browser/base/content/test/dummy_page.html in subframe
testLink(0, true, false, finish, true);
});
});
});
});
});
}
function testLink(aLinkIndex, pinTab, expectNewTab, nextTest, testSubFrame) {
let appTab = gBrowser.addTab("http://example.com/browser/browser/base/content/test/app_bug575561.html", {skipAnimation: true});
if (pinTab)
gBrowser.pinTab(appTab);
gBrowser.selectedTab = appTab;
appTab.linkedBrowser.addEventListener("load", onLoad, true);
let loadCount = 0;
function onLoad() {
loadCount++;
if (loadCount < 2)
return;
appTab.linkedBrowser.removeEventListener("load", onLoad, true);
let browser = gBrowser.getBrowserForTab(appTab);
if (testSubFrame)
browser = browser.contentDocument.getElementsByTagName("iframe")[0];
let links = browser.contentDocument.getElementsByTagName("a");
if (expectNewTab)
gBrowser.tabContainer.addEventListener("TabOpen", onTabOpen, true);
else
browser.addEventListener("load", onPageLoad, true);
info("Clicking " + links[aLinkIndex].textContent);
EventUtils.sendMouseEvent({type:"click"}, links[aLinkIndex], browser.contentWindow);
function onPageLoad() {
browser.removeEventListener("load", onPageLoad, true);
is(browser.contentDocument.location.href, links[aLinkIndex].href, "Link should not open in a new tab");
executeSoon(function(){
gBrowser.removeTab(appTab);
nextTest();
});
}
function onTabOpen(event) {
gBrowser.tabContainer.removeEventListener("TabOpen", onTabOpen, true);
ok(true, "Link should open a new tab");
executeSoon(function(){
gBrowser.removeTab(appTab);
gBrowser.removeCurrentTab();
nextTest();
});
}
}
}

View File

@ -1,5 +1,4 @@
var tab;
var performedTest = false;
function test() {
waitForExplicitFinish();
@ -7,25 +6,31 @@ function test() {
tab = gBrowser.addTab();
isnot(tab.getAttribute("fadein"), "true", "newly opened tab is yet to fade in");
// Remove the tab right before the opening animation's first frame
// Try to remove the tab right before the opening animation's first frame
window.mozRequestAnimationFrame(checkAnimationState);
executeSoon(checkAnimationState);
}
function checkAnimationState() {
if (performedTest)
return;
if (tab.getAttribute("fadein") != "true") {
window.mozRequestAnimationFrame(checkAnimationState);
executeSoon(checkAnimationState);
return;
}
performedTest = true;
info(window.getComputedStyle(tab).maxWidth);
gBrowser.removeTab(tab, {animate:true});
ok(!tab.parentNode, "tab successfully removed");
finish();
gBrowser.removeTab(tab, { animate: true });
if (!tab.parentNode) {
ok(true, "tab removed synchronously since the opening animation hasn't moved yet");
finish();
return;
}
info("tab didn't close immediately, so the tab opening animation must have started moving");
info("waiting for the tab to close asynchronously");
tab.addEventListener("transitionend", function (event) {
if (event.propertyName == "max-width")
executeSoon(function () {
ok(!tab.parentNode, "tab removed asynchronously");
finish();
});
}, false);
}

View File

@ -56,6 +56,7 @@ _BROWSER_FILES = \
browser_tabview_bug595804.js \
browser_tabview_bug595930.js \
browser_tabview_bug595943.js \
browser_tabview_bug598600.js \
browser_tabview_dragdrop.js \
browser_tabview_exit_button.js \
browser_tabview_group.js \
@ -67,6 +68,7 @@ _BROWSER_FILES = \
browser_tabview_startup_transitions.js \
browser_tabview_undo_group.js \
browser_tabview_firstrun_pref.js \
head.js \
search1.html \
search2.html \
$(NULL)

View File

@ -59,7 +59,7 @@ function test() {
"The currently selected tab should be the first tab in the groupItemOne");
// create another group with a tab.
let groupItemTwo = createEmptyGroupItem(contentWindow, 200);
let groupItemTwo = createEmptyGroupItem(contentWindow, 300, 300, 200);
let onTabViewHidden = function() {
window.removeEventListener("tabviewhidden", onTabViewHidden, false);
@ -111,16 +111,3 @@ function testGroupSwitch(contentWindow, groupItemOne, groupItemTwo) {
finish();
}
function createEmptyGroupItem(contentWindow, padding) {
let pageBounds = contentWindow.Items.getPageBounds();
pageBounds.inset(padding, padding);
let box = new contentWindow.Rect(pageBounds);
box.width = 300;
box.height = 300;
let emptyGroupItem = new contentWindow.GroupItem([], { bounds: box });
return emptyGroupItem;
}

View File

@ -0,0 +1,115 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is tabview bug598600 test.
*
* The Initial Developer of the Original Code is
* Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2010
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Raymond Lee <raymond@appcoast.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
let newWin;
let prefService;
function test() {
let ss = Cc["@mozilla.org/browser/sessionstore;1"].getService(Ci.nsISessionStore);
prefService =
Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefService).
getBranch("browser.panorama.");
// make sure we don't trigger the 'first run' behavior
prefService.setBoolPref("experienced_first_run", true);
waitForExplicitFinish();
// open a new window and setup the window state.
newWin = openDialog(getBrowserURL(), "_blank", "chrome,all,dialog=no");
newWin.addEventListener("load", function(event) {
this.removeEventListener("load", arguments.callee, false);
let newState = {
windows: [{
tabs: [{
entries: [{ "url": "about:blank" }],
hidden: true,
attributes: {},
extData: {
"tabview-tab":
'{"bounds":{"left":20,"top":35,"width":280,"height":210},' +
'"userSize":null,"url":"about:blank","groupID":1,' +
'"imageData":null,"title":null}'
}
},{
entries: [{ url: "about:blank" }],
index: 1,
hidden: false,
attributes: {},
extData: {
"tabview-tab":
'{"bounds":{"left":375,"top":35,"width":280,"height":210},' +
'"userSize":null,"url":"about:blank","groupID":2,' +
'"imageData":null,"title":null}'
}
}],
selected:2,
_closedTabs: [],
extData: {
"tabview-groups": '{"nextID":3,"activeGroupId":2}',
"tabview-group":
'{"1":{"bounds":{"left":15,"top":10,"width":320,"height":375},' +
'"userSize":null,"locked":{},"title":"","id":1},' +
'"2":{"bounds":{"left":380,"top":5,"width":320,"height":375},' +
'"userSize":null,"locked":{},"title":"","id":2}}',
"tabview-ui": '{"pageBounds":{"left":0,"top":0,"width":875,"height":650}}'
}, sizemode:"normal"
}]
};
ss.setWindowState(newWin, JSON.stringify(newState), true);
// add a new tab.
newWin.gBrowser.addTab();
is(newWin.gBrowser.tabs.length, 3, "There are 3 browser tabs");
let onTabViewShow = function() {
newWin.removeEventListener("tabviewshown", onTabViewShow, false);
let contentWindow = newWin.document.getElementById("tab-view").contentWindow;
is(contentWindow.GroupItems.groupItems.length, 2, "Has two group items");
is(contentWindow.GroupItems.getOrphanedTabs().length, 0, "No orphan tabs");
// clean up and finish
prefService.setBoolPref("experienced_first_run", false);
newWin.close();
finish();
}
newWin.addEventListener("tabviewshown", onTabViewShow, false);
newWin.TabView.toggle();
}, false);
}

View File

@ -95,10 +95,8 @@ function addTest(contentWindow, groupOneId, groupTwoId, originalTab) {
ok(tabItem, "The tab item exists");
// calculate the offsets
let groupTwoRect = groupTwo.getBounds();
let groupTwoRectCenter = groupTwoRect.center();
let tabItemRect = tabItem.getBounds();
let tabItemRectCenter = tabItemRect.center();
let groupTwoRectCenter = groupTwo.getBounds().center();
let tabItemRectCenter = tabItem.getBounds().center();
let offsetX =
Math.round(groupTwoRectCenter.x - tabItemRectCenter.x);
let offsetY =
@ -132,41 +130,23 @@ function addTest(contentWindow, groupOneId, groupTwoId, originalTab) {
simulateDragDrop(tabItem.container, offsetX, offsetY, contentWindow);
}
function simulateDragDrop(tabItem, offsetX, offsetY, contentWindow) {
// enter drag mode
let dataTransfer;
function simulateDragDrop(element, offsetX, offsetY, contentWindow) {
let rect = element.getBoundingClientRect();
let startX = (rect.right - rect.left)/2;
let startY = (rect.bottom - rect.top)/2;
let incrementX = offsetX / 2;
let incrementY = offsetY / 2;
EventUtils.synthesizeMouse(
tabItem, 1, 1, { type: "mousedown" }, contentWindow);
event = contentWindow.document.createEvent("DragEvents");
event.initDragEvent(
"dragenter", true, true, contentWindow, 0, 0, 0, 0, 0,
false, false, false, false, 1, null, dataTransfer);
tabItem.dispatchEvent(event);
// drag over
if (offsetX || offsetY) {
let Ci = Components.interfaces;
let utils = contentWindow.QueryInterface(Ci.nsIInterfaceRequestor).
getInterface(Ci.nsIDOMWindowUtils);
let rect = tabItem.getBoundingClientRect();
for (let i = 1; i <= 5; i++) {
let left = rect.left + Math.round(i * offsetX / 5);
let top = rect.top + Math.round(i * offsetY / 5);
utils.sendMouseEvent("mousemove", left, top, 0, 1, 0);
}
event = contentWindow.document.createEvent("DragEvents");
event.initDragEvent(
"dragover", true, true, contentWindow, 0, 0, 0, 0, 0,
false, false, false, false, 0, null, dataTransfer);
tabItem.dispatchEvent(event);
}
element, startX, startY, { type: "mousedown" });
// drop
EventUtils.synthesizeMouse(tabItem, 0, 0, { type: "mouseup" }, contentWindow);
event = contentWindow.document.createEvent("DragEvents");
event.initDragEvent(
"drop", true, true, contentWindow, 0, 0, 0, 0, 0,
false, false, false, false, 0, null, dataTransfer);
tabItem.dispatchEvent(event);
for (let i = 1; i <= 2; i++) {
EventUtils.synthesizeMouse(
element, (startX + incrementX * i), (startY + incrementY * i),
{ type: "mousemove" });
}
EventUtils.synthesizeMouse(
element, (startX + incrementX * 2), (startY + incrementY * 2),
{ type: "mouseup" });
}

View File

@ -65,7 +65,7 @@ function testEmptyGroupItem(contentWindow) {
let groupItemCount = contentWindow.GroupItems.groupItems.length;
// create empty group item
let emptyGroupItem = createEmptyGroupItem(contentWindow, 100);
let emptyGroupItem = createEmptyGroupItem(contentWindow, 300, 300, 100, true);
ok(emptyGroupItem.isEmpty(), "This group is empty");
is(contentWindow.GroupItems.groupItems.length, ++groupItemCount,
@ -89,7 +89,7 @@ function testEmptyGroupItem(contentWindow) {
}
function testGroupItemWithTabItem(contentWindow) {
let groupItem = createEmptyGroupItem(contentWindow, 200);
let groupItem = createEmptyGroupItem(contentWindow, 300, 300, 200, true);
let tabItemCount = 0;
let onTabViewHidden = function() {
@ -161,17 +161,3 @@ function testGroupItemWithTabItem(contentWindow) {
EventUtils.synthesizeMouse(newTabButton[0], 1, 1, {}, contentWindow);
}
function createEmptyGroupItem(contentWindow, padding) {
let pageBounds = contentWindow.Items.getPageBounds();
pageBounds.inset(padding, padding);
let box = new contentWindow.Rect(pageBounds);
box.width = 300;
box.height = 300;
let emptyGroupItem = new contentWindow.GroupItem([], { bounds: box,
immediately: true });
return emptyGroupItem;
}

View File

@ -67,7 +67,7 @@ function onTabViewWindowLoaded() {
is(contentWindow.GroupItems.getOrphanedTabs().length, 0, "No orphaned tabs");
// 2) create a group, add a blank tab
let groupItem = createEmptyGroupItem(contentWindow, 200);
let groupItem = createEmptyGroupItem(contentWindow, 300, 300, 200);
let onTabViewHidden = function() {
newWin.removeEventListener("tabviewhidden", onTabViewHidden, false);
@ -110,19 +110,6 @@ function onTabViewWindowLoaded() {
EventUtils.sendMouseEvent({ type: "click" }, newTabButton[0], contentWindow);
}
function createEmptyGroupItem(contentWindow, padding) {
let pageBounds = contentWindow.Items.getPageBounds();
pageBounds.inset(padding, padding);
let box = new contentWindow.Rect(pageBounds);
box.width = 300;
box.height = 300;
let emptyGroupItem = new contentWindow.GroupItem([], { bounds: box });
return emptyGroupItem;
}
function whenWindowObservesOnce(win, topic, callback) {
let windowWatcher =
Cc["@mozilla.org/embedcomp/window-watcher;1"].getService(Ci.nsIWindowWatcher);

View File

@ -1,4 +1,3 @@
/* -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 8 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
@ -12,14 +11,15 @@
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla Fenntrolysis.
* The Original Code is the utilities for tabview.
*
* The Initial Developer of the Original Code is
* Nokia.
* Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2010
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Raymond Lee <raymond@appcoast.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
@ -35,20 +35,17 @@
*
* ***** END LICENSE BLOCK ***** */
include protocol PBrowser;
function createEmptyGroupItem(contentWindow, width, height, padding, noAnimation) {
let pageBounds = contentWindow.Items.getPageBounds();
pageBounds.inset(padding, padding);
namespace mozilla {
namespace ipc {
let box = new contentWindow.Rect(pageBounds);
box.width = width;
box.height = height;
let immediately = noAnimation ? true: false;
let emptyGroupItem =
new contentWindow.GroupItem([], { bounds: box, immediately: immediately });
protocol PDocumentRendererNativeID
{
manager PBrowser;
parent:
// Returns the offset, width and height, in pixels, of the area in the
// buffer that was drawn.
__delete__(PRInt32 x, PRInt32 y, PRInt32 w, PRInt32 h, PRUint32 nativeID);
};
} // namespace ipc
} // namespace mozilla
return emptyGroupItem;
}

View File

@ -130,11 +130,24 @@
if (!pasteAndGo)
return;
var controller = document.commandDispatcher.getControllerForCommand("cmd_paste");
var enabled = controller.isCommandEnabled("cmd_paste");
if (enabled)
pasteAndGo.removeAttribute("disabled");
else
pasteAndGo.setAttribute("disabled", "true");
var couldBeURL = controller.isCommandEnabled("cmd_paste");
if (couldBeURL) {
let cbSvc = Cc["@mozilla.org/widget/clipboard;1"].
getService(Ci.nsIClipboard);
let xferable = Cc["@mozilla.org/widget/transferable;1"].
createInstance(Ci.nsITransferable);
xferable.addDataFlavor("text/unicode");
cbSvc.getData(xferable, cbSvc.kGlobalClipboard);
let data = {};
xferable.getTransferData("text/unicode", data, {});
data = data.value.QueryInterface(Ci.nsISupportsString).data;
try {
makeURI(data);
} catch (ex) { // clipboard data is not a URL
couldBeURL = false;
}
}
pasteAndGo.hidden = !couldBeURL;
}, false);
var insertLocation = cxmenu.firstChild;
@ -147,7 +160,8 @@
GetStringFromName("pasteAndGo.label");
pasteAndGo.setAttribute("label", label);
pasteAndGo.setAttribute("anonid", "paste-and-go");
pasteAndGo.setAttribute("oncommand", "goDoCommand('cmd_paste'); gURLBar.handleCommand();");
pasteAndGo.setAttribute("oncommand",
"gURLBar.value = ''; goDoCommand('cmd_paste'); gURLBar.handleCommand();");
cxmenu.insertBefore(pasteAndGo, insertLocation.nextSibling);
}
]]></constructor>

View File

@ -483,7 +483,7 @@ function openTroubleshootingPage()
*/
function openFeedbackPage()
{
openUILinkIn("http://input.mozilla.com/sad", "tab");
openUILinkIn("http://input.mozilla.com/feedback", "tab");
}

View File

@ -1161,7 +1161,8 @@ var gEditItemOverlay = {
this._folderMenuList.selectedItem = folderItem;
},
onItemAdded: function EIO_onItemAdded(aItemId, aFolder, aIndex, aItemType) {
onItemAdded: function EIO_onItemAdded(aItemId, aFolder, aIndex, aItemType,
aURI) {
this._lastNewItem = aItemId;
},

View File

@ -46,8 +46,6 @@
<?xul-overlay href="chrome://browser/content/places/placesOverlay.xul"?>
<!DOCTYPE page [
<!ENTITY % historyDTD SYSTEM "chrome://browser/locale/history/history.dtd">
%historyDTD;
<!ENTITY % placesDTD SYSTEM "chrome://browser/locale/places/places.dtd">
%placesDTD;
]>

View File

@ -391,7 +391,7 @@
<vbox id="defaultView" flex="1">
<vbox id="searchModifiers" hidden="true">
<toolbar id="organizerScopeBar" class="chromeclass-toolbar" align="center">
<label id="scopeBarTitle" value="&search.label;"/>
<label id="scopeBarTitle" value="&search.in.label;"/>
<toolbarbutton id="scopeBarAll" type="radio" group="scopeBar"
oncommand="PlacesQueryBuilder.onScopeSelected(this);"
label="&search.scopeBookmarks.label;"

View File

@ -204,7 +204,7 @@ var bookmarksObserver = {
},
// nsINavBookmarkObserver
onItemAdded: function PSB_onItemAdded(aItemId, aFolderId, aIndex) {
onItemAdded: function PSB_onItemAdded(aItemId, aFolderId, aIndex, aURI) {
var node = null;
var index = null;
[node, index] = getNodeForTreeItem(aItemId, gLibrary.PlacesOrganizer._places);

View File

@ -223,7 +223,7 @@ var bookmarksObserver = {
// nsINavBookmarkObserver
onItemAdded: function PSB_onItemAdded(aItemId, aFolderId, aIndex,
aItemType) {
aItemType, aURI) {
var views = getViewsForFolder(aFolderId);
ok(views.length > 0, "Found affected views (" + views.length + "): " + views);

View File

@ -53,7 +53,7 @@ var observer = {
onEndUpdateBatch: function() {
this._endUpdateBatch = true;
},
onItemAdded: function(id, folder, index, itemType) {
onItemAdded: function(id, folder, index, itemType, uri) {
this._itemAddedId = id;
this._itemAddedParent = folder;
this._itemAddedIndex = index;

View File

@ -35,7 +35,7 @@
*
* ***** END LICENSE BLOCK ***** */
// This test makes sure that browsingmode attribute of the window is correctly
// This test makes sure that privatebrowsingmode attribute of the window is correctly
// switched with private browsing mode changes.
function test() {
@ -45,20 +45,20 @@ function test() {
getService(Ci.nsIPrivateBrowsingService);
let docRoot = document.documentElement;
is(docRoot.getAttribute("browsingmode"), "normal",
"browsingmode should be \"normal\" initially");
ok(!docRoot.hasAttribute("privatebrowsingmode"),
"privatebrowsingmode should not be present in normal mode");
// enter private browsing mode
pb.privateBrowsingEnabled = true;
is(docRoot.getAttribute("browsingmode"), "private",
"browsingmode should be \"private\" inside the private browsing mode");
is(docRoot.getAttribute("privatebrowsingmode"), "temporary",
"privatebrowsingmode should be \"temporary\" inside the private browsing mode");
// leave private browsing mode
pb.privateBrowsingEnabled = false;
is(docRoot.getAttribute("browsingmode"), "normal",
"browsingmode should be \"normal\" outside the private browsing mode");
ok(!docRoot.hasAttribute("privatebrowsingmode"),
"privatebrowsingmode should not be present in normal mode");
// cleanup
gPrefService.clearUserPref("browser.privatebrowsing.keep_current_session");

View File

@ -604,7 +604,8 @@
label = this._stringBundle.getString("cmd_pasteAndSearch");
element.setAttribute("label", label);
element.setAttribute("anonid", "paste-and-search");
element.setAttribute("oncommand", "goDoCommand('cmd_paste'); document.getElementById('searchbar').handleSearchCommand();");
element.setAttribute("oncommand",
"BrowserSearch.searchBar.value = ''; goDoCommand('cmd_paste'); BrowserSearch.searchBar.handleSearchCommand();");
cxmenu.insertBefore(element, insertLocation.nextSibling);
pasteAndSearch = element;
}

View File

@ -45,8 +45,9 @@ include $(DEPTH)/config/autoconf.mk
include $(topsrcdir)/config/rules.mk
_BROWSER_TEST_FILES = browser_405664.js \
browser_415700.js \
browser_addEngine.js \
testEngine.xml \
testEngine.src \
browser_426329.js \
426329.xml \
browser_483086.js \

View File

@ -1,85 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2008
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Ryan Flint <rflint@dslr.net> (Original Author)
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
var gSS = Services.search;
function observers(aSubject, aTopic, aData) {
switch (aData) {
case "engine-added":
test2();
break;
case "engine-current":
test3();
break;
case "engine-removed":
test4();
break;
}
}
function test() {
waitForExplicitFinish();
Services.obs.addObserver(observers, "browser-search-engine-modified", false);
gSS.addEngine("http://mochi.test:8888/browser/browser/components/search/test/testEngine.xml",
Ci.nsISearchEngine.DATA_XML, "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAABGklEQVQoz2NgGB6AnZ1dUlJSXl4eSDIyMhLW4Ovr%2B%2Fr168uXL69Zs4YoG%2BLi4i5dusTExMTGxsbNzd3f37937976%2BnpmZmagbHR09J49e5YvX66kpATVEBYW9ubNm2nTphkbG7e2tp44cQLIuHfvXm5urpaWFlDKysqqu7v73LlzECMYIiIiHj58mJCQoKKicvXq1bS0NKBgW1vbjh074uPjgeqAXE1NzSdPnvDz84M0AEUvXLgAsW379u1z5swBen3jxo2zZ892cHB4%2BvQp0KlAfwI1cHJyghQFBwfv2rULokFXV%2FfixYu7d%2B8GGqGgoMDKyrpu3br9%2B%2FcDuXl5eVA%2FAEWBfoWHAdAYoNuAYQ0XAeoUERFhGDYAAPoUaT2dfWJuAAAAAElFTkSuQmCC",
false);
}
function test2() {
var engine = gSS.getEngineByName("Foo");
ok(engine, "Engine was added.");
var aEngine = gSS.getEngineByAlias("fooalias");
ok(!aEngine, "Alias was not parsed from engine description");
gSS.currentEngine = engine;
}
function test3() {
var engine = gSS.currentEngine;
is(engine.name, "Foo", "Current engine was changed successfully");
gSS.removeEngine(engine);
}
function test4() {
var engine = gSS.currentEngine;
ok(engine, "An engine is present.");
isnot(engine.name, "Foo", "Current engine reset after removal");
Services.obs.removeObserver(observers, "browser-search-engine-modified");
finish();
}

View File

@ -0,0 +1,168 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2008
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Ryan Flint <rflint@dslr.net> (Original Author)
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
var gSS = Services.search;
function observer(aSubject, aTopic, aData) {
if (!gCurrentTest) {
info("Observer called with no test active");
return;
}
let engine = aSubject.QueryInterface(Ci.nsISearchEngine);
info("Observer: " + aData + " for " + engine.name);
let method;
switch (aData) {
case "engine-added":
if (gCurrentTest.added)
method = "added"
break;
case "engine-current":
if (gCurrentTest.current)
method = "current";
break;
case "engine-removed":
if (gCurrentTest.removed)
method = "removed";
break;
}
if (method)
gCurrentTest[method](engine);
}
function checkEngine(checkObj, engineObj) {
info("Checking engine");
for (var prop in checkObj)
is(checkObj[prop], engineObj[prop], prop + " is correct");
}
var gTests = [
{
name: "opensearch install",
engine: {
name: "Foo",
alias: null,
description: "Foo Search",
searchForm: "http://mochi.test:8888/browser/browser/components/search/test/",
type: Ci.nsISearchEngine.TYPE_OPENSEARCH
},
run: function () {
gSS.addEngine("http://mochi.test:8888/browser/browser/components/search/test/testEngine.xml",
Ci.nsISearchEngine.DATA_XML, "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAABGklEQVQoz2NgGB6AnZ1dUlJSXl4eSDIyMhLW4Ovr%2B%2Fr168uXL69Zs4YoG%2BLi4i5dusTExMTGxsbNzd3f37937976%2BnpmZmagbHR09J49e5YvX66kpATVEBYW9ubNm2nTphkbG7e2tp44cQLIuHfvXm5urpaWFlDKysqqu7v73LlzECMYIiIiHj58mJCQoKKicvXq1bS0NKBgW1vbjh074uPjgeqAXE1NzSdPnvDz84M0AEUvXLgAsW379u1z5swBen3jxo2zZ892cHB4%2BvQp0KlAfwI1cHJyghQFBwfv2rULokFXV%2FfixYu7d%2B8GGqGgoMDKyrpu3br9%2B%2FcDuXl5eVA%2FAEWBfoWHAdAYoNuAYQ0XAeoUERFhGDYAAPoUaT2dfWJuAAAAAElFTkSuQmCC",
false);
},
added: function (engine) {
ok(engine, "engine was added.");
checkEngine(this.engine, engine);
let engineFromSS = gSS.getEngineByName(this.engine.name);
is(engine, engineFromSS, "engine is obtainable via getEngineByName");
let aEngine = gSS.getEngineByAlias("fooalias");
ok(!aEngine, "Alias was not parsed from engine description");
gSS.currentEngine = engine;
},
current: function (engine) {
let currentEngine = gSS.currentEngine;
is(engine, currentEngine, "engine is current");
is(engine.name, this.engine.name, "current engine was changed successfully");
gSS.removeEngine(engine);
},
removed: function (engine) {
let currentEngine = gSS.currentEngine;
ok(currentEngine, "An engine is present.");
isnot(currentEngine.name, this.engine.name, "Current engine reset after removal");
nextTest();
}
},
{
name: "sherlock install",
engine: {
name: "Test Sherlock",
alias: null,
description: "Test Description",
searchForm: "http://example.com/searchform",
type: Ci.nsISearchEngine.TYPE_SHERLOCK
},
run: function () {
gSS.addEngine("http://mochi.test:8888/browser/browser/components/search/test/testEngine.src",
Ci.nsISearchEngine.DATA_TEXT, "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAABGklEQVQoz2NgGB6AnZ1dUlJSXl4eSDIyMhLW4Ovr%2B%2Fr168uXL69Zs4YoG%2BLi4i5dusTExMTGxsbNzd3f37937976%2BnpmZmagbHR09J49e5YvX66kpATVEBYW9ubNm2nTphkbG7e2tp44cQLIuHfvXm5urpaWFlDKysqqu7v73LlzECMYIiIiHj58mJCQoKKicvXq1bS0NKBgW1vbjh074uPjgeqAXE1NzSdPnvDz84M0AEUvXLgAsW379u1z5swBen3jxo2zZ892cHB4%2BvQp0KlAfwI1cHJyghQFBwfv2rULokFXV%2FfixYu7d%2B8GGqGgoMDKyrpu3br9%2B%2FcDuXl5eVA%2FAEWBfoWHAdAYoNuAYQ0XAeoUERFhGDYAAPoUaT2dfWJuAAAAAElFTkSuQmCC",
false);
},
added: function (engine) {
ok(engine, "engine was added.");
checkEngine(this.engine, engine);
let engineFromSS = gSS.getEngineByName(this.engine.name);
is(engineFromSS, engine, "engine is obtainable via getEngineByName");
gSS.removeEngine(engine);
},
removed: function (engine) {
let currentEngine = gSS.currentEngine;
ok(currentEngine, "An engine is present.");
isnot(currentEngine.name, this.engine.name, "Current engine reset after removal");
nextTest();
}
}
];
var gCurrentTest = null;
function nextTest() {
if (gTests.length) {
gCurrentTest = gTests.shift();
info("Running " + gCurrentTest.name);
gCurrentTest.run();
} else
executeSoon(finish);
}
function test() {
waitForExplicitFinish();
Services.obs.addObserver(observer, "browser-search-engine-modified", false);
registerCleanupFunction(cleanup);
nextTest();
}
function cleanup() {
Services.obs.removeObserver(observer, "browser-search-engine-modified");
}

View File

@ -0,0 +1,11 @@
<search
name="Test Sherlock"
description="Test Description"
method="GET"
searchform="http://example.com/searchform"
action="http://example.com/action"
queryCharset="UTF-8"
>
<input name="userParam" user>
<input name="param" value="value">
</search>

View File

@ -36,6 +36,7 @@
const Cc = Components.classes;
const Ci = Components.interfaces;
const Cu = Components.utils;
var gStateObject;
var gTreeData;
@ -54,13 +55,26 @@ window.onload = function() {
return;
}
}
// remove unneeded braces (added for compatibility with Firefox 2.0 and 3.0)
if (sessionData.value.charAt(0) == '(')
sessionData.value = sessionData.value.slice(1, -1);
try {
gStateObject = JSON.parse(sessionData.value);
}
catch (exJSON) {
var s = new Cu.Sandbox("about:blank");
gStateObject = Cu.evalInSandbox("(" + sessionData.value + ")", s);
// If we couldn't parse the string with JSON.parse originally, make sure
// that the value in the textbox will be parsable.
sessionData.value = JSON.stringify(gStateObject);
}
// make sure the data is tracked to be restored in case of a subsequent crash
var event = document.createEvent("UIEvents");
event.initUIEvent("input", true, true, window, 0);
sessionData.dispatchEvent(event);
gStateObject = JSON.parse(sessionData.value);
initTreeView();
document.getElementById("errorTryAgain").focus();

View File

@ -1268,15 +1268,32 @@ SessionStoreService.prototype = {
},
getTabValue: function sss_getTabValue(aTab, aKey) {
var data = aTab.__SS_extdata || {};
let data = {};
if (aTab.__SS_extdata) {
data = aTab.__SS_extdata;
}
else if (aTab.linkedBrowser.__SS_data && aTab.linkedBrowser.__SS_data.extData) {
// If the tab hasn't been fully restored, get the data from the to-be-restored data
data = aTab.linkedBrowser.__SS_data.extData;
}
return data[aKey] || "";
},
setTabValue: function sss_setTabValue(aTab, aKey, aStringValue) {
if (!aTab.__SS_extdata) {
aTab.__SS_extdata = {};
// If the tab hasn't been restored, then set the data there, otherwise we
// could lose newly added data.
let saveTo;
if (aTab.__SS_extdata) {
saveTo = aTab.__SS_extdata;
}
aTab.__SS_extdata[aKey] = aStringValue;
else if (aTab.linkedBrowser.__SS_data && aTab.linkedBrowser.__SS_data.extData) {
saveTo = aTab.linkedBrowser.__SS_data.extData;
}
else {
aTab.__SS_extdata = {};
saveTo = aTab.__SS_extdata;
}
saveTo[aKey] = aStringValue;
this.saveStateDelayed(aTab.ownerDocument.defaultView);
},

View File

@ -117,8 +117,10 @@ _BROWSER_TEST_FILES = \
browser_579868.js \
browser_579879.js \
browser_580512.js \
browser_581593.js \
browser_586147.js \
browser_586068-cascaded_restore.js \
browser_590268.js \
browser_600545.js \
$(NULL)

View File

@ -0,0 +1,90 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is sessionstore test code.
*
* The Initial Developer of the Original Code is
* Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2010
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Paul OShannessy <paul@oshannessy.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
Cu.import("resource://gre/modules/Services.jsm");
let ss = Cc["@mozilla.org/browser/sessionstore;1"].
getService(Ci.nsISessionStore);
let stateBackup = ss.getBrowserState();
function test() {
/** Test for bug 581593 **/
waitForExplicitFinish();
let oldState = { windows: [{ tabs: [{ entries: [{ url: "example.com" }] }] }]};
let pageData = {
url: "about:sessionrestore",
formdata: { "#sessionData": "(" + JSON.stringify(oldState) + ")" }
};
let state = { windows: [{ tabs: [{ entries: [pageData] }] }] };
// The form data will be restored before SSTabRestored, so we want to listen
// for that on the currently selected tab (it will be reused)
gBrowser.selectedTab.addEventListener("SSTabRestored", onSSTabRestored, true);
ss.setBrowserState(JSON.stringify(state));
}
function onSSTabRestored(aEvent) {
info("SSTabRestored event");
gBrowser.selectedTab.removeEventListener("SSTabRestored", onSSTabRestored, true);
gBrowser.selectedBrowser.addEventListener("input", onInput, true);
}
function onInput(aEvent) {
info("input event");
gBrowser.selectedBrowser.removeEventListener("input", onInput, true);
// This is an ok way to check this because we will make sure that the text
// field is parsable.
let val = gBrowser.selectedBrowser.contentDocument.getElementById("sessionData").value;
try {
JSON.parse(val);
ok(true, "JSON.parse succeeded");
}
catch (e) {
ok(false, "JSON.parse failed");
}
cleanup();
}
function cleanup() {
ss.setBrowserState(stateBackup);
executeSoon(finish);
}

View File

@ -0,0 +1,148 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is sessionstore test code.
*
* The Initial Developer of the Original Code is
* Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2010
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Paul OShannessy <paul@oshannessy.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
const NUM_TABS = 12;
Cu.import("resource://gre/modules/Services.jsm");
let ss = Cc["@mozilla.org/browser/sessionstore;1"].
getService(Ci.nsISessionStore);
let stateBackup = ss.getBrowserState();
function test() {
/** Test for Bug 590268 - Provide access to sessionstore tab data sooner **/
waitForExplicitFinish();
let startedTest = false;
// wasLoaded will be used to keep track of tabs that have already had SSTabRestoring
// fired for them.
let wasLoaded = { };
let restoringTabsCount = 0;
let uniq2 = { };
let uniq2Count = 0;
let state = { windows: [{ tabs: [] }] };
// We're going to put a bunch of tabs into this state
for (let i = 0; i < NUM_TABS; i++) {
let uniq = r();
let tabData = {
entries: [{ url: "http://example.com/#" + i }],
extData: { "uniq": uniq }
};
state.windows[0].tabs.push(tabData);
wasLoaded[uniq] = false;
}
function onSSTabRestoring(aEvent) {
restoringTabsCount++;
let uniq = ss.getTabValue(aEvent.originalTarget, "uniq");
wasLoaded[uniq] = true;
// On the first SSTabRestoring we're going to run the the real test.
// We'll keep this listener around so we can keep marking tabs as restored.
if (restoringTabsCount == 1)
onFirstSSTabRestoring();
else if (restoringTabsCount == NUM_TABS)
onLastSSTabRestoring();
}
// This does the actual testing. SSTabRestoring should be firing on tabs from
// left to right, so we're going to start with the rightmost tab.
function onFirstSSTabRestoring() {
info("onFirstSSTabRestoring...");
for (let i = gBrowser.tabs.length - 1; i >= 0; i--) {
let tab = gBrowser.tabs[i];
let actualUniq = ss.getTabValue(tab, "uniq");
let expectedUniq = state.windows[0].tabs[i].extData["uniq"];
if (wasLoaded[actualUniq]) {
info("tab " + i + ": already restored");
continue;
}
is(actualUniq, expectedUniq, "tab " + i + ": extData was correct");
// Now we're going to set a piece of data back on the tab so it can be read
// to test setting a value "early".
uniq2[actualUniq] = r();
ss.setTabValue(tab, "uniq2", uniq2[actualUniq]);
// This will be used in the final comparison to make sure we checked the
// same number as we set.
uniq2Count++;
}
}
function onLastSSTabRestoring() {
let checked = 0;
for (let i = 0; i < gBrowser.tabs.length; i++) {
let tab = gBrowser.tabs[i];
let uniq = ss.getTabValue(tab, "uniq");
// Look to see if we set a uniq2 value for this uniq value
if (uniq in uniq2) {
is(ss.getTabValue(tab, "uniq2"), uniq2[uniq], "tab " + i + " has correct uniq2 value");
checked++;
}
}
is(checked, uniq2Count, "checked the same number of uniq2 as we set");
cleanup();
}
function cleanup() {
// remove the event listener and clean up before finishing
gBrowser.tabContainer.removeEventListener("SSTabRestoring", onSSTabRestoring, false);
// Put this in an executeSoon because we still haven't called restoreNextTab
// in sessionstore for the last tab (we'll call it after this). We end up
// trying to restore the tab (since we then add a closed tab to the array).
executeSoon(function() {
ss.setBrowserState(stateBackup);
executeSoon(finish);
});
}
// Add the event listener
gBrowser.tabContainer.addEventListener("SSTabRestoring", onSSTabRestoring, false);
// Restore state
ss.setBrowserState(JSON.stringify(state));
}
// Helper function to create a random value
function r() {
return "" + Date.now() + Math.random();
}

View File

@ -394,7 +394,7 @@ Bookmark.prototype = {
onEndUpdateBatch : function bm_oeub() {
},
onItemAdded : function bm_oia(aId, aFolder, aIndex) {
onItemAdded : function bm_oia(aId, aFolder, aIndex, aItemType, aURI) {
// bookmark object doesn't exist at this point
},
@ -547,7 +547,7 @@ BookmarkFolder.prototype = {
onEndUpdateBatch : function bmf_oeub() {
},
onItemAdded : function bmf_oia(aId, aFolder, aIndex) {
onItemAdded : function bmf_oia(aId, aFolder, aIndex, aItemType, aURI) {
// handle root folder events
if (!this._parent)
this._events.dispatch("add", aId);

View File

@ -1,26 +0,0 @@
<!ENTITY find.label "Search:">
<!ENTITY find.accesskey "S">
<!ENTITY expand.label "Expand">
<!ENTITY expand.accesskey "E">
<!ENTITY collapse.label "Collapse">
<!ENTITY collapse.accesskey "C">
<!ENTITY byDate.label "By Date">
<!ENTITY byDate.accesskey "D">
<!ENTITY bySite.label "By Site">
<!ENTITY bySite.accesskey "S">
<!ENTITY view.label "View">
<!ENTITY view.accesskey "w">
<!ENTITY byMostVisited.label "By Most Visited">
<!ENTITY byMostVisited.accesskey "V">
<!ENTITY byLastVisited.label "By Last Visited">
<!ENTITY byLastVisited.accesskey "L">
<!ENTITY byDayAndSite.label "By Date and Site">
<!ENTITY byDayAndSite.accesskey "t">
<!ENTITY openLinkInWindow.label "Open">
<!ENTITY openLinkInWindow.accesskey "O">
<!ENTITY openInNewTab.label "Open in New Tab">
<!ENTITY openInNewTab.accesskey "T">
<!ENTITY openInNewWindow.label "Open in New Window">
<!ENTITY openInNewWindow.accesskey "W">
<!ENTITY copyLink.label "Copy Link Location">
<!ENTITY copyLink.accesskey "C">

View File

@ -94,6 +94,8 @@
<!ENTITY search.label "Search:">
<!ENTITY search.accesskey "S">
<!ENTITY search.in.label "Search in:">
<!ENTITY search.scopeFolder.label "Selected Folder">
<!ENTITY search.scopeFolder.accesskey "r">
<!ENTITY search.scopeBookmarks.label "Bookmarks">
@ -123,3 +125,18 @@
<!ENTITY detailsPane.less.accesskey "e">
<!ENTITY detailsPane.noPreviewAvailable.label "Preview">
<!ENTITY detailsPane.selectAnItemText.description "Select an item to view and edit its properties">
<!ENTITY find.label "Search:">
<!ENTITY find.accesskey "S">
<!ENTITY view.label "View">
<!ENTITY view.accesskey "w">
<!ENTITY byDate.label "By Date">
<!ENTITY byDate.accesskey "D">
<!ENTITY bySite.label "By Site">
<!ENTITY bySite.accesskey "S">
<!ENTITY byMostVisited.label "By Most Visited">
<!ENTITY byMostVisited.accesskey "V">
<!ENTITY byLastVisited.label "By Last Visited">
<!ENTITY byLastVisited.accesskey "L">
<!ENTITY byDayAndSite.label "By Date and Site">
<!ENTITY byDayAndSite.accesskey "t">

View File

@ -45,7 +45,6 @@
#endif
locale/browser/feeds/subscribe.dtd (%chrome/browser/feeds/subscribe.dtd)
locale/browser/feeds/subscribe.properties (%chrome/browser/feeds/subscribe.properties)
locale/browser/history/history.dtd (%chrome/browser/history/history.dtd)
locale/browser/migration/migration.dtd (%chrome/browser/migration/migration.dtd)
locale/browser/migration/migration.properties (%chrome/browser/migration/migration.properties)
locale/browser/preferences/advanced.dtd (%chrome/browser/preferences/advanced.dtd)

View File

@ -46,6 +46,7 @@ ro
ru
sk
son
sq
sv-SE
tr
uk

View File

@ -474,11 +474,15 @@ menuitem:not([type]) {
#bookmarksToolbarFolderMenu,
#BMB_bookmarksToolbar {
list-style-image: url("chrome://browser/skin/places/bookmarksToolbar.png");
list-style-image: url("chrome://browser/skin/places/bookmarksToolbar.png");
}
#BMB_bookmarkThisPage {
list-style-image: url("chrome://browser/skin/places/starPage.png");
}
#BMB_unsortedBookmarks {
list-style-image: url("chrome://browser/skin/places/unsortedBookmarks.png");
list-style-image: url("chrome://browser/skin/places/unsortedBookmarks.png");
}
#menu_openDownloads {

View File

@ -4,6 +4,8 @@
%define customToolbarColor hsl(214,44%,87%)
%define glassToolbarBorderColor rgb(40%,40%,40%)
%define glassActiveBorderColor rgb(37, 44, 51)
%define glassInactiveBorderColor rgb(102, 102, 102)
@media all and (-moz-windows-default-theme) {
#navigator-toolbox > toolbar:not(:-moz-lwtheme) {
@ -31,6 +33,12 @@
0 0 2px 1px rgba(255,255,255,.25) inset;
}
#main-window[privatebrowsingmode=temporary] #appmenu-button:not(:-moz-window-inactive) {
-moz-border-left-colors: rgba(255,255,255,.5) rgba(43,8,65,.9);
-moz-border-bottom-colors: rgba(255,255,255,.5) rgba(43,8,65,.9);
-moz-border-right-colors: rgba(255,255,255,.5) rgba(43,8,65,.9);
}
#appmenu-button:-moz-window-inactive {
-moz-border-left-colors: rgba(255,255,255,.4) rgba(0,0,0,.5);
-moz-border-bottom-colors: rgba(255,255,255,.4) rgba(0,0,0,.5);
@ -85,6 +93,24 @@
margin-top: -7px;
}
/* Artificially draw window borders that are covered by lwtheme, see bug 591930. */
#main-window[sizemode="normal"] > #titlebar > #titlebar-content:-moz-lwtheme {
border-top: 2px solid;
-moz-border-top-colors: @glassActiveBorderColor@ rgba(255,255,255,.6);
}
#main-window[sizemode="normal"] > #titlebar > #titlebar-content:-moz-lwtheme:-moz-window-inactive {
-moz-border-top-colors: @glassInactiveBorderColor@ rgba(255,255,255,.6);
}
#main-window[sizemode="normal"] > #titlebar > #titlebar-content > #appmenu-button-container:-moz-lwtheme {
margin-top: -1px;
}
#main-window[sizemode="normal"] > #titlebar > #titlebar-content > #titlebar-buttonbox:-moz-lwtheme {
margin-top: -2px;
}
#main-window:not(:-moz-lwtheme)[inFullscreen="true"] {
-moz-appearance: none;
background-color: #556;

View File

@ -126,6 +126,11 @@
margin: 0;
}
#main-window[privatebrowsingmode=temporary] #appmenu-button:not(:-moz-window-inactive) {
background-image: -moz-linear-gradient(rgb(153,38,211), rgb(105,19,163) 95%);
border-color: rgba(43,8,65,.9);
}
#appmenu-button:-moz-window-inactive {
background-image: none;
border-color: rgba(0,0,0,.4);
@ -141,6 +146,16 @@
0 -1px 0 rgba(250,234,169,.5) inset;
}
#main-window[privatebrowsingmode=temporary] #appmenu-button:hover:not(:active):not([open]) {
background-image: -moz-radial-gradient(center bottom, farthest-side, rgba(240,193,255,.5) 10%, rgba(240,193,255,0) 70%),
-moz-radial-gradient(center bottom, farthest-side, rgb(192,81,247), rgba(236,172,255,0)),
-moz-linear-gradient(rgb(144,20,207), rgb(95,0,158) 95%);
border-color: rgba(43,8,65,.9);
box-shadow: 0 1px 0 rgba(255,255,255,.1) inset,
0 0 2px 1px rgba(240,193,255,.7) inset,
0 -1px 0 rgba(240,193,255,.5) inset;
}
#appmenu-button:hover:active,
#appmenu-button[open] {
background-image: -moz-linear-gradient(rgb(246,170,69), rgb(209,74,0) 95%);
@ -149,6 +164,11 @@
0 1px 1px rgba(0,0,0,.2) inset;
}
#main-window[privatebrowsingmode=temporary] #appmenu-button:hover:active,
#main-window[privatebrowsingmode=temporary] #appmenu-button[open] {
background-image: -moz-linear-gradient(rgb(144,20,207), rgb(95,0,158) 95%);
}
#appmenu-button > .button-box {
border-style: none;
padding: 0;

View File

@ -351,6 +351,7 @@ user_pref("layout.debug.enable_data_xbl", true);
user_pref("browser.EULA.override", true);
user_pref("javascript.options.tracejit.content", true);
user_pref("javascript.options.methodjit.content", true);
user_pref("javascript.options.jitprofiling.content", true);
user_pref("gfx.color_management.force_srgb", true);
user_pref("network.manage-offline-status", false);
user_pref("test.mousescroll", true);

View File

@ -5006,8 +5006,8 @@ BUILD_CTYPES=1
XPC_IDISPATCH_SUPPORT=
case "$target_os" in
darwin*|*wince*|*winmo*)
case "${target}" in
*android*|*darwin*|*wince*|*winmo*)
ACCESSIBILITY=
;;
*)
@ -8512,31 +8512,6 @@ if test "$MOZ_TREE_CAIRO"; then
AC_CHECK_HEADER(d3d10.h, MOZ_ENABLE_D3D10_LAYER=1)
fi
AC_TRY_COMPILE([#include <ddraw.h>], [int foo = DDLOCK_WAITNOTBUSY;], HAS_DDRAW=1, HAS_DDRAW=)
if test -z "$HAS_DDRAW"; then
AC_MSG_WARN([DirectDraw ddraw.h header not found or it's missing DDLOCK_WAITNOTBUSY, disabling DirectDraw surface. If you have an older SDK (such as the CE5 SDK), try copying in ddraw.lib and ddraw.h from the WM6 SDK.])
DDRAW_SURFACE_FEATURE=
else
DDRAW_SURFACE_FEATURE="#define CAIRO_HAS_DDRAW_SURFACE 1"
fi
if test -z "$OGLES_SDK_DIR"; then
OGLES_SURFACE_FEATURE=
else
AC_TRY_COMPILE([
#include <EGL/egl.h>
#include <EGL/eglext.h>
#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>
], [ EGLDisplay _cairo_ddraw_egl_dpy = EGL_NO_DISPLAY;], HAS_OGLES=1, HAS_OGLES=)
if test -z "$HAS_OGLES"; then
AC_MSG_WARN([OpenGL ES2 headers not found, disabling OpenGL acceleration surfaces.])
OGLES_SURFACE_FEATURE=
else
OGLES_SURFACE_FEATURE="#define CAIRO_DDRAW_USE_GL 1"
fi
fi
PDF_SURFACE_FEATURE="#define CAIRO_HAS_PDF_SURFACE 1"
fi
if test "$MOZ_WIDGET_TOOLKIT" = "os2"; then
@ -8581,8 +8556,6 @@ if test "$MOZ_TREE_CAIRO"; then
AC_SUBST(QUARTZ_IMAGE_SURFACE_FEATURE)
AC_SUBST(XCB_SURFACE_FEATURE)
AC_SUBST(WIN32_SURFACE_FEATURE)
AC_SUBST(DDRAW_SURFACE_FEATURE)
AC_SUBST(OGLES_SURFACE_FEATURE)
AC_SUBST(OS2_SURFACE_FEATURE)
AC_SUBST(BEOS_SURFACE_FEATURE)
AC_SUBST(DIRECTFB_SURFACE_FEATURE)

View File

@ -51,7 +51,7 @@ interface nsIDOMNode;
interface nsISelection;
interface nsISelectionDisplay;
[scriptable, uuid(bc5795ab-bcb5-448b-b3c7-a111bead7c26)]
[scriptable, uuid(ff11fa25-788f-444f-8f69-dcdf14348fb3)]
interface nsISelectionController : nsISelectionDisplay
{
const short SELECTION_NONE=0;
@ -94,20 +94,27 @@ interface nsISelectionController : nsISelectionDisplay
*/
nsISelection getSelection(in short type);
const short SCROLL_SYNCHRONOUS = 1<<1;
const short SCROLL_FIRST_ANCESTOR_ONLY = 1<<2;
/**
* ScrollSelectionIntoView scrolls a region of the selection,
* so that it is visible in the scrolled view.
*
* @param aType the selection to scroll into view. //SelectionType
* @param aRegion the region inside the selection to scroll into view. //SelectionRegion
* @param aIsSynchronous when true, scrolls the selection into view
* before returning. If false, posts a request which is processed
* @param aFlags the scroll flags. Valid bits include:
* SCROLL_SYNCHRONOUS: when set, scrolls the selection into view
* before returning. If not set, posts a request which is processed
* at some point after the method returns.
* SCROLL_FIRST_ANCESTOR_ONLY: if set, only the first ancestor will be scrolled
* into view.
*
* Note that if isSynchronous is true, then this might flush the pending
* reflow. It's dangerous for some objects. See bug 418470 comment 12.
*/
void scrollSelectionIntoView(in short type, in short region, in boolean isSynchronous);
void scrollSelectionIntoView(in short type, in short region, in short flags);
/**
* RepaintSelection repaints the selection specified by aType.
*

View File

@ -380,8 +380,7 @@ CSPRep.prototype = {
},
/**
* Generates string representation of the policy. Should be fairly similar
* to the original.
* Generates canonical string representation of the policy.
*/
toString:
function csp_toString() {
@ -607,8 +606,7 @@ CSPSourceList.prototype = {
},
/**
* Generates string representation of the Source List.
* Should be fairly similar to the original.
* Generates canonical string representation of the Source List.
*/
toString:
function() {
@ -639,7 +637,7 @@ CSPSourceList.prototype = {
},
/**
* Makes a new instance that resembles this object.
* Makes a new deep copy of this object.
* @returns
* a new CSPSourceList
*/
@ -951,7 +949,7 @@ CSPSource.fromString = function(aStr, self, enforceSelfChecks) {
// Allow scheme-only sources! These default to wildcard host/port,
// especially since host and port don't always matter.
// Example: "javascript:" and "data:"
if (!sObj._host) sObj._host = "*";
if (!sObj._host) sObj._host = CSPHost.fromString("*");
if (!sObj._port) sObj._port = "*";
} else {
// some host was defined.
@ -1050,8 +1048,7 @@ CSPSource.prototype = {
},
/**
* Generates string representation of the Source.
* Should be fairly similar to the original.
* Generates canonical string representation of the Source.
*/
toString:
function() {
@ -1069,7 +1066,7 @@ CSPSource.prototype = {
},
/**
* Makes a new instance that resembles this object.
* Makes a new deep copy of this object.
* @returns
* a new CSPSource
*/
@ -1172,13 +1169,28 @@ CSPSource.prototype = {
return null;
}
// NOTE: Both sources must have a host, if they don't, something funny is
// going on. The fromString() factory method should have set the host to
// * if there's no host specified in the input. Regardless, if a host is
// not present either the scheme is hostless or any host should be allowed.
// This means we can use the other source's host as the more restrictive
// host expression, or if neither are present, we can use "*", but the
// error should still be reported.
// host
if (!this._host)
newSource._host = that._host;
else if (!that._host)
newSource._host = this._host;
else // both this and that have hosts
if (this._host && that._host) {
newSource._host = this._host.intersectWith(that._host);
} else if (this._host) {
CSPError("intersecting source with undefined host: " + that.toString());
newSource._host = this._host.clone();
} else if (that._host) {
CSPError("intersecting source with undefined host: " + this.toString());
newSource._host = that._host.clone();
} else {
CSPError("intersecting two sources with undefined hosts: " +
this.toString() + " and " + that.toString());
newSource._host = CSPHost.fromString("*");
}
return newSource;
},
@ -1266,8 +1278,7 @@ CSPHost.fromString = function(aStr) {
CSPHost.prototype = {
/**
* Generates string representation of the Source.
* Should be fairly similar to the original.
* Generates canonical string representation of the Host.
*/
toString:
function() {
@ -1275,7 +1286,7 @@ CSPHost.prototype = {
},
/**
* Makes a new instance that resembles this object.
* Makes a new deep copy of this object.
* @returns
* a new CSPHost
*/
@ -1297,7 +1308,7 @@ CSPHost.prototype = {
*/
permits:
function(aHost) {
if (!aHost) return false;
if (!aHost) aHost = CSPHost.fromString("*");
if (!(aHost instanceof CSPHost)) {
// -- compare CSPHost to String

View File

@ -5854,7 +5854,7 @@ CloneSimpleValues(JSContext* cx,
}
// Security wrapped objects are not allowed either.
if (obj->getClass()->ext.wrappedObject)
if (obj->isWrapper() && !obj->getClass()->ext.innerObject)
return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
// See if this JSObject is backed by some C++ object. If it is then we assume

View File

@ -3568,18 +3568,18 @@ nsINode::doInsertChildAt(nsIContent* aKid, PRUint32 aIndex,
}
}
PRUint32 childCount = aChildArray.ChildCount();
NS_ENSURE_TRUE(aIndex <= childCount, NS_ERROR_ILLEGAL_VALUE);
// The id-handling code, and in the future possibly other code, need to
// react to unexpected attribute changes.
nsMutationGuard::DidMutate();
PRBool isAppend = (aIndex == childCount);
// Do this before checking the child-count since this could cause mutations
nsIDocument* doc = GetCurrentDoc();
mozAutoDocUpdate updateBatch(doc, UPDATE_CONTENT_MODEL, aNotify);
PRUint32 childCount = aChildArray.ChildCount();
NS_ENSURE_TRUE(aIndex <= childCount, NS_ERROR_ILLEGAL_VALUE);
PRBool isAppend = (aIndex == childCount);
rv = aChildArray.InsertChildAt(aKid, aIndex);
NS_ENSURE_SUCCESS(rv, rv);
if (aIndex == 0) {
@ -4019,6 +4019,8 @@ nsINode::ReplaceOrInsertBefore(PRBool aReplace, nsINode* aNewChild,
nsresult res = NS_OK;
PRInt32 insPos;
mozAutoDocConditionalContentUpdateBatch batch(GetCurrentDoc(), PR_TRUE);
// Figure out which index to insert at
if (aRefChild) {
insPos = IndexOf(aRefChild);
@ -4080,11 +4082,6 @@ nsINode::ReplaceOrInsertBefore(PRBool aReplace, nsINode* aNewChild,
}
}
// We want an update batch when we expect several mutations to be performed,
// which is when we're replacing a node, or when we're inserting a fragment.
mozAutoDocConditionalContentUpdateBatch batch(GetCurrentDoc(),
aReplace || nodeType == nsIDOMNode::DOCUMENT_FRAGMENT_NODE);
// If we're replacing
if (aReplace) {
refContent = GetChildAt(insPos + 1);
@ -5328,7 +5325,7 @@ nsGenericElement::PostHandleEventForLinks(nsEventChainPostVisitor& aVisitor)
nsIEventStateManager* esm =
aVisitor.mPresContext->EventStateManager();
nsEventStateManager::SetGlobalActiveContent(
nsEventStateManager::SetActiveManager(
static_cast<nsEventStateManager*>(esm), this);
}
}

View File

@ -6,15 +6,13 @@
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"/>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<script type="application/x-javascript">
var bodyOnLoad = false;
function checkOnLoad()
function onLoadFired()
{
ok(bodyOnLoad, "Body onload event should fire");
ok(true, "Body onload event should fire");
SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
setTimeout(checkOnLoad, 500);
</script>
</head>
<body onload="bodyOnLoad = true;"/>
<body onload="onLoadFired();"/>
</html>

View File

@ -35,6 +35,7 @@
//load('CSPUtils.jsm');
Components.utils.import('resource://gre/modules/CSPUtils.jsm');
Components.utils.import('resource://gre/modules/NetUtil.jsm');
// load the HTTP server
do_load_httpd_js();
@ -190,6 +191,7 @@ test(
//"funny characters (#) should not work for host.");
do_check_eq(null, CSPSource.fromString("a#2-c.com"));
//print(" --- Stop ignoring errors that print ---\n");
//"failed to parse host with port.");
@ -229,6 +231,16 @@ test(
do_check_true(src.permits("https://foobar.com"));
//"src should reject other hosts"
do_check_false(src.permits("https://a.com"));
src = CSPSource.create("javascript:", "https://foobar.com:443");
//"hostless schemes should be parseable."
var aUri = NetUtil.newURI("javascript:alert('foo');");
do_check_true(src.permits(aUri));
//"src should reject other hosts"
do_check_false(src.permits("https://a.com"));
//"nothing else should be allowed"
do_check_false(src.permits("https://foobar.com"));
});
///////////////////// Test the source list //////////////////////

View File

@ -53,9 +53,11 @@ public:
DocumentRendererChild();
virtual ~DocumentRendererChild();
bool RenderDocument(nsIDOMWindow *window, const PRInt32& x, const PRInt32& y, const PRInt32& w, const PRInt32& h,
const nsString& bgcolor, const PRUint32& flags, const PRBool& flush,
PRUint32& _width, PRUint32& _height, nsCString& data);
bool RenderDocument(nsIDOMWindow *window,
const nsRect& documentRect, const gfxMatrix& transform,
const nsString& bgcolor,
PRUint32 renderFlags, PRBool flushLayout,
const nsIntSize& renderSize, nsCString& data);
private:

View File

@ -54,10 +54,10 @@ public:
void SetCanvasContext(nsICanvasRenderingContextInternal* aCanvas,
gfxContext* ctx);
void DrawToCanvas(PRUint32 aWidth, PRUint32 aHeight,
void DrawToCanvas(const nsIntSize& renderedSize,
const nsCString& aData);
virtual bool Recv__delete__(const PRUint32& w, const PRUint32& h,
virtual bool Recv__delete__(const nsIntSize& renderedSize,
const nsCString& data);
private:

View File

@ -120,16 +120,6 @@ public:
// anything into this canvas before changing the shmem state, it will be
// lost.
NS_IMETHOD SetIsIPC(PRBool isIPC) = 0;
// Swap this back buffer with the front, and copy its contents to the new
// back. x, y, w, and h specify the area of |back| that is dirty.
NS_IMETHOD Swap(mozilla::ipc::Shmem& back,
PRInt32 x, PRInt32 y, PRInt32 w, PRInt32 h) = 0;
// Sync back and front buffer, move ownership of back buffer to parent
NS_IMETHOD Swap(PRUint32 nativeID,
PRInt32 x, PRInt32 y, PRInt32 w, PRInt32 h) = 0;
};
NS_DEFINE_STATIC_IID_ACCESSOR(nsICanvasRenderingContextInternal,

View File

@ -99,11 +99,16 @@ FlushLayoutForTree(nsIDOMWindow* aWindow)
}
bool
DocumentRendererChild::RenderDocument(nsIDOMWindow *window, const PRInt32& x, const PRInt32& y, const PRInt32& w, const PRInt32& h,
const nsString& aBGColor, const PRUint32& flags, const PRBool& flush,
PRUint32& _width, PRUint32& _height, nsCString& data)
DocumentRendererChild::RenderDocument(nsIDOMWindow *window,
const nsRect& documentRect,
const gfxMatrix& transform,
const nsString& bgcolor,
PRUint32 renderFlags,
PRBool flushLayout,
const nsIntSize& renderSize,
nsCString& data)
{
if (flush)
if (flushLayout)
FlushLayoutForTree(window);
nsCOMPtr<nsPresContext> presContext;
@ -119,26 +124,25 @@ DocumentRendererChild::RenderDocument(nsIDOMWindow *window, const PRInt32& x, co
nscolor bgColor;
nsCSSParser parser;
nsresult rv = parser.ParseColorString(PromiseFlatString(aBGColor),
nsresult rv = parser.ParseColorString(PromiseFlatString(bgcolor),
nsnull, 0, &bgColor);
if (NS_FAILED(rv))
return false;
nsIPresShell* presShell = presContext->PresShell();
nsRect r(x, y, w, h);
_width = nsPresContext::AppUnitsToIntCSSPixels(w);
_height = nsPresContext::AppUnitsToIntCSSPixels(h);
// Draw directly into the output array.
data.SetLength(_width * _height * 4);
nsRefPtr<gfxImageSurface> surf = new gfxImageSurface(reinterpret_cast<PRUint8*>(const_cast<char*>(data.get())),
gfxIntSize(_width, _height),
4 * _width, gfxASurface::ImageFormatARGB32);
nsRefPtr<gfxContext> ctx = new gfxContext(surf);
data.SetLength(renderSize.width * renderSize.height * 4);
presShell->RenderDocument(r, flags, bgColor, ctx);
nsRefPtr<gfxImageSurface> surf =
new gfxImageSurface(reinterpret_cast<uint8*>(data.BeginWriting()),
gfxIntSize(renderSize.width, renderSize.height),
4 * renderSize.width,
gfxASurface::ImageFormatARGB32);
nsRefPtr<gfxContext> ctx = new gfxContext(surf);
ctx->SetMatrix(transform);
presShell->RenderDocument(documentRect, renderFlags, bgColor, ctx);
return true;
}

View File

@ -1,185 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Fennec Electrolysis.
*
* The Initial Developer of the Original Code is
* Nokia.
* Portions created by the Initial Developer are Copyright (C) 2010
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifdef MOZ_WIDGET_QT
#include <QX11Info>
#define DISPLAY QX11Info::display
#endif
#ifdef MOZ_WIDGET_GTK2
#include <gdk/gdkx.h>
#define DISPLAY GDK_DISPLAY
#endif
#include "base/basictypes.h"
#include "gfxImageSurface.h"
#include "gfxPattern.h"
#include "nsPIDOMWindow.h"
#include "nsIDOMWindow.h"
#include "nsIDOMDocument.h"
#include "nsIDocShell.h"
#include "nsIDocShellTreeNode.h"
#include "nsIDocShellTreeItem.h"
#include "nsIDocument.h"
#include "nsIInterfaceRequestorUtils.h"
#include "nsComponentManagerUtils.h"
#include "nsCSSParser.h"
#include "nsPresContext.h"
#include "nsCOMPtr.h"
#include "nsColor.h"
#include "gfxContext.h"
#include "gfxImageSurface.h"
#include "nsLayoutUtils.h"
#include "mozilla/ipc/DocumentRendererNativeIDChild.h"
#ifdef MOZ_X11
#include "gfxXlibSurface.h"
#endif
using namespace mozilla::ipc;
DocumentRendererNativeIDChild::DocumentRendererNativeIDChild()
{}
DocumentRendererNativeIDChild::~DocumentRendererNativeIDChild()
{}
static void
FlushLayoutForTree(nsIDOMWindow* aWindow)
{
nsCOMPtr<nsPIDOMWindow> piWin = do_QueryInterface(aWindow);
if (!piWin)
return;
// Note that because FlushPendingNotifications flushes parents, this
// is O(N^2) in docshell tree depth. However, the docshell tree is
// usually pretty shallow.
nsCOMPtr<nsIDOMDocument> domDoc;
aWindow->GetDocument(getter_AddRefs(domDoc));
nsCOMPtr<nsIDocument> doc = do_QueryInterface(domDoc);
if (doc) {
doc->FlushPendingNotifications(Flush_Layout);
}
nsCOMPtr<nsIDocShellTreeNode> node =
do_QueryInterface(piWin->GetDocShell());
if (node) {
PRInt32 i = 0, i_end;
node->GetChildCount(&i_end);
for (; i < i_end; ++i) {
nsCOMPtr<nsIDocShellTreeItem> item;
node->GetChildAt(i, getter_AddRefs(item));
nsCOMPtr<nsIDOMWindow> win = do_GetInterface(item);
if (win) {
FlushLayoutForTree(win);
}
}
}
}
bool
DocumentRendererNativeIDChild::RenderDocument(nsIDOMWindow* window, const PRInt32& x,
const PRInt32& y, const PRInt32& w,
const PRInt32& h, const nsString& aBGColor,
const PRUint32& flags, const PRBool& flush,
const gfxMatrix& aMatrix,
const PRInt32& nativeID)
{
if (!nativeID)
return false;
if (flush)
FlushLayoutForTree(window);
nsCOMPtr<nsPresContext> presContext;
nsCOMPtr<nsPIDOMWindow> win = do_QueryInterface(window);
if (win) {
nsIDocShell* docshell = win->GetDocShell();
if (docshell) {
docshell->GetPresContext(getter_AddRefs(presContext));
}
}
if (!presContext)
return false;
nscolor bgColor;
nsCSSParser parser;
nsresult rv = parser.ParseColorString(PromiseFlatString(aBGColor), nsnull, 0, &bgColor);
if (NS_FAILED(rv))
return false;
nsIPresShell* presShell = presContext->PresShell();
nsRect r(x, y, w, h);
// Draw directly into the output array.
nsRefPtr<gfxASurface> surf;
#ifdef MOZ_X11
// Initialize gfxXlibSurface from native XID by using toolkit functionality
// Would be nice to have gfxXlibSurface(nativeID) implementation
Display* dpy = DISPLAY();
int depth = DefaultDepth(dpy, DefaultScreen(dpy));
XVisualInfo vinfo;
int foundVisual = XMatchVisualInfo(dpy,
DefaultScreen(dpy),
depth,
TrueColor,
&vinfo);
if (!foundVisual)
return false;
surf = new gfxXlibSurface(dpy, nativeID, vinfo.visual);
#else
NS_ERROR("NativeID handler not implemented for your platform");
#endif
nsRefPtr<gfxContext> ctx = new gfxContext(surf);
ctx->SetMatrix(aMatrix);
presShell->RenderDocument(r, flags, bgColor, ctx);
#ifdef MOZ_X11
// We are about to pass this buffer across process boundaries, and when we
// try to read from the surface in the other process, we're not guaranteed
// the drawing has actually happened, as the drawing commands might still
// be queued. By syncing with X, we guarantee the drawing has finished
// before we pass the buffer back.
XSync(dpy, False);
#endif
return true;
}

View File

@ -53,33 +53,36 @@ void DocumentRendererParent::SetCanvasContext(nsICanvasRenderingContextInternal*
mCanvasContext = ctx;
}
void DocumentRendererParent::DrawToCanvas(PRUint32 aWidth, PRUint32 aHeight,
void DocumentRendererParent::DrawToCanvas(const nsIntSize& aSize,
const nsCString& aData)
{
if (!mCanvas || !mCanvasContext)
return;
nsRefPtr<gfxImageSurface> surf = new gfxImageSurface(reinterpret_cast<PRUint8*>(const_cast<char*>(aData.Data())),
gfxIntSize(aWidth, aHeight),
aWidth * 4,
gfxASurface::ImageFormatARGB32);
nsRefPtr<gfxImageSurface> surf =
new gfxImageSurface(reinterpret_cast<uint8*>(const_cast<nsCString&>(aData).BeginWriting()),
gfxIntSize(aSize.width, aSize.height),
aSize.width * 4,
gfxASurface::ImageFormatARGB32);
nsRefPtr<gfxPattern> pat = new gfxPattern(surf);
gfxRect rect(gfxPoint(0, 0), gfxSize(aSize.width, aSize.height));
mCanvasContext->NewPath();
mCanvasContext->PixelSnappedRectangleAndSetPattern(gfxRect(0, 0, aWidth, aHeight), pat);
mCanvasContext->PixelSnappedRectangleAndSetPattern(rect, pat);
mCanvasContext->Fill();
// get rid of the pattern surface ref, because aData is very likely to go away shortly
// get rid of the pattern surface ref, because aData is very
// likely to go away shortly
mCanvasContext->SetColor(gfxRGBA(1,1,1,1));
gfxRect damageRect = mCanvasContext->UserToDevice(gfxRect(0, 0, aWidth, aHeight));
gfxRect damageRect = mCanvasContext->UserToDevice(rect);
mCanvas->Redraw(damageRect);
}
bool
DocumentRendererParent::Recv__delete__(const PRUint32& w, const PRUint32& h,
DocumentRendererParent::Recv__delete__(const nsIntSize& renderedSize,
const nsCString& data)
{
DrawToCanvas(w, h, data);
DrawToCanvas(renderedSize, data);
return true;
}

View File

@ -1,144 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Fennec Electrolysis.
*
* The Initial Developer of the Original Code is
* The Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2009
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "base/basictypes.h"
#include "gfxImageSurface.h"
#include "gfxPattern.h"
#include "nsPIDOMWindow.h"
#include "nsIDOMWindow.h"
#include "nsIDOMDocument.h"
#include "nsIDocShell.h"
#include "nsIDocShellTreeNode.h"
#include "nsIDocShellTreeItem.h"
#include "nsIDocument.h"
#include "nsIInterfaceRequestorUtils.h"
#include "nsComponentManagerUtils.h"
#include "nsCSSParser.h"
#include "nsPresContext.h"
#include "nsCOMPtr.h"
#include "nsColor.h"
#include "gfxContext.h"
#include "gfxImageSurface.h"
#include "nsLayoutUtils.h"
#ifdef MOZ_IPC
#include "gfxSharedImageSurface.h"
#endif
#include "mozilla/ipc/DocumentRendererShmemChild.h"
using namespace mozilla::ipc;
DocumentRendererShmemChild::DocumentRendererShmemChild()
{}
DocumentRendererShmemChild::~DocumentRendererShmemChild()
{}
static void
FlushLayoutForTree(nsIDOMWindow* aWindow)
{
nsCOMPtr<nsPIDOMWindow> piWin = do_QueryInterface(aWindow);
if (!piWin)
return;
// Note that because FlushPendingNotifications flushes parents, this
// is O(N^2) in docshell tree depth. However, the docshell tree is
// usually pretty shallow.
nsCOMPtr<nsIDOMDocument> domDoc;
aWindow->GetDocument(getter_AddRefs(domDoc));
nsCOMPtr<nsIDocument> doc = do_QueryInterface(domDoc);
if (doc) {
doc->FlushPendingNotifications(Flush_Layout);
}
nsCOMPtr<nsIDocShellTreeNode> node =
do_QueryInterface(piWin->GetDocShell());
if (node) {
PRInt32 i = 0, i_end;
node->GetChildCount(&i_end);
for (; i < i_end; ++i) {
nsCOMPtr<nsIDocShellTreeItem> item;
node->GetChildAt(i, getter_AddRefs(item));
nsCOMPtr<nsIDOMWindow> win = do_GetInterface(item);
if (win) {
FlushLayoutForTree(win);
}
}
}
}
bool
DocumentRendererShmemChild::RenderDocument(nsIDOMWindow *window, const PRInt32& x,
const PRInt32& y, const PRInt32& w,
const PRInt32& h, const nsString& aBGColor,
const PRUint32& flags, const PRBool& flush,
const gfxMatrix& aMatrix,
Shmem& data)
{
if (flush)
FlushLayoutForTree(window);
nsCOMPtr<nsPresContext> presContext;
nsCOMPtr<nsPIDOMWindow> win = do_QueryInterface(window);
if (win) {
nsIDocShell* docshell = win->GetDocShell();
if (docshell) {
docshell->GetPresContext(getter_AddRefs(presContext));
}
}
if (!presContext)
return false;
nscolor bgColor;
nsCSSParser parser;
nsresult rv = parser.ParseColorString(PromiseFlatString(aBGColor), nsnull, 0, &bgColor);
if (NS_FAILED(rv))
return false;
nsIPresShell* presShell = presContext->PresShell();
nsRect r(x, y, w, h);
// Draw directly into the output array.
nsRefPtr<gfxASurface> surf = new gfxSharedImageSurface(data);
nsRefPtr<gfxContext> ctx = new gfxContext(surf);
ctx->SetMatrix(aMatrix);
presShell->RenderDocument(r, flags, bgColor, ctx);
return true;
}

View File

@ -60,10 +60,6 @@ ifdef MOZ_IPC
CPPSRCS += \
DocumentRendererParent.cpp \
DocumentRendererChild.cpp \
DocumentRendererNativeIDParent.cpp \
DocumentRendererNativeIDChild.cpp \
DocumentRendererShmemParent.cpp \
DocumentRendererShmemChild.cpp \
$(NULL)
endif

View File

@ -103,9 +103,6 @@
#include "gfxContext.h"
#include "gfxASurface.h"
#include "gfxImageSurface.h"
#ifdef MOZ_IPC
#include "gfxSharedImageSurface.h"
#endif
#include "gfxPlatform.h"
#include "gfxFont.h"
#include "gfxTextRunCache.h"
@ -130,13 +127,8 @@
# include <algorithm>
# include "mozilla/dom/ContentParent.h"
# include "mozilla/ipc/PDocumentRendererParent.h"
# include "mozilla/ipc/PDocumentRendererShmemParent.h"
# include "mozilla/ipc/PDocumentRendererNativeIDParent.h"
# include "mozilla/dom/PBrowserParent.h"
# include "mozilla/ipc/DocumentRendererParent.h"
# include "mozilla/ipc/DocumentRendererShmemParent.h"
# include "mozilla/ipc/DocumentRendererNativeIDParent.h"
# include "mozilla/ipc/SharedMemorySysV.h"
// windows.h (included by chromium code) defines this, in its infinite wisdom
# undef DrawText
@ -144,10 +136,6 @@
using namespace mozilla::ipc;
#endif
#ifdef MOZ_X11
#include "gfxXlibSurface.h"
#endif
#ifdef MOZ_SVG
#include "nsSVGEffects.h"
#endif
@ -429,13 +417,6 @@ public:
NS_IMETHOD SetIsIPC(PRBool isIPC);
// this rect is in CSS pixels
NS_IMETHOD Redraw(const gfxRect &r);
// Swap this back buffer with the front, and copy its contents to the new back.
// x, y, w, and h specify the area of |back| that is dirty.
NS_IMETHOD Swap(mozilla::ipc::Shmem& back, PRInt32 x, PRInt32 y,
PRInt32 w, PRInt32 h);
NS_IMETHOD Swap(PRUint32 nativeID, PRInt32 x, PRInt32 y,
PRInt32 w, PRInt32 h);
// nsISupports interface + CC
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
@ -500,30 +481,13 @@ protected:
*/
gfxASurface::gfxImageFormat GetImageFormat() const;
#ifdef MOZ_IPC
/**
* Sync data from mBackSurface to mSurface.
*/
nsresult Swap(const gfxRect& aRect);
#endif
// Member vars
PRInt32 mWidth, mHeight;
PRPackedBool mValid;
PRPackedBool mOpaque;
PRPackedBool mResetLayer;
#ifdef MOZ_IPC
PRPackedBool mIPC;
// for rendering with NativeID protocol, we should track backbuffer ownership
PRPackedBool mIsBackSurfaceReadable;
// We always have a front buffer. We hand the mBackSurface to the other
// process to render to,
// and then sync data from mBackSurface to mSurface when it finishes.
nsRefPtr<gfxASurface> mBackSurface;
#endif
// the canvas element we're a context of
nsCOMPtr<nsIDOMHTMLCanvasElement> mCanvasElement;
nsHTMLCanvasElement *HTMLCanvasElement() {
@ -814,18 +778,6 @@ protected:
}
friend struct nsCanvasBidiProcessor;
private:
#ifdef MOZ_IPC
void DeallocShmemIfShared(nsRefPtr<gfxASurface> &aSurface) {
ContentParent* allocator = ContentParent::GetSingleton(PR_FALSE);
if (allocator && gfxSharedImageSurface::IsSharedImage(aSurface)) {
Shmem mem = static_cast<gfxSharedImageSurface*>(aSurface.get())->GetShmem();
allocator->DeallocShmem(mem);
}
}
#endif
};
NS_IMPL_CYCLE_COLLECTING_ADDREF_AMBIGUOUS(nsCanvasRenderingContext2D, nsIDOMCanvasRenderingContext2D)
@ -871,9 +823,7 @@ NS_NewCanvasRenderingContext2D(nsIDOMCanvasRenderingContext2D** aResult)
nsCanvasRenderingContext2D::nsCanvasRenderingContext2D()
: mValid(PR_FALSE), mOpaque(PR_FALSE), mResetLayer(PR_TRUE)
#ifdef MOZ_IPC
, mIPC(PR_FALSE)
#endif
, mCanvasElement(nsnull)
, mSaveCount(0), mIsEntireFrameInvalid(PR_FALSE), mInvalidateCount(0)
, mLastStyle(STYLE_MAX), mStyleStack(20)
@ -884,12 +834,6 @@ nsCanvasRenderingContext2D::nsCanvasRenderingContext2D()
nsCanvasRenderingContext2D::~nsCanvasRenderingContext2D()
{
Reset();
#ifdef MOZ_IPC
DeallocShmemIfShared(mBackSurface);
mBackSurface = nsnull;
#endif
sNumLivingContexts--;
if (!sNumLivingContexts) {
delete[] sUnpremultiplyTable;
@ -902,10 +846,6 @@ nsCanvasRenderingContext2D::~nsCanvasRenderingContext2D()
nsresult
nsCanvasRenderingContext2D::Reset()
{
#ifdef MOZ_IPC
DeallocShmemIfShared(mSurface);
#endif
// only do this for non-docshell created contexts,
// since those are the ones that we created a surface for
if (mValid && !mDocShell)
@ -1152,33 +1092,6 @@ nsCanvasRenderingContext2D::SetDimensions(PRInt32 width, PRInt32 height)
if (surface && surface->CairoStatus() != 0)
surface = NULL;
#ifdef MOZ_IPC
if (mIPC && surface) {
#ifdef MOZ_X11
if (surface->GetType() == gfxASurface::SurfaceTypeXlib) {
mBackSurface =
gfxPlatform::GetPlatform()->CreateOffscreenSurface(size, gfxASurface::ContentFromFormat(format));
NS_ABORT_IF_FALSE(mBackSurface->GetType() ==
gfxASurface::SurfaceTypeXlib, "need xlib surface");
mIsBackSurfaceReadable = PR_TRUE;
// Make sure that our XSurface created and synced properly
XSync(static_cast<gfxXlibSurface*>(mBackSurface.get())->XDisplay(), False);
} else
#endif
{
if (surface->GetType() == gfxASurface::SurfaceTypeImage)
format = static_cast<gfxImageSurface*>(surface.get())->Format();
SharedMemory::SharedMemoryType shmtype = SharedMemory::TYPE_BASIC;
#ifdef MOZ_HAVE_SHAREDMEMORYSYSV
shmtype = SharedMemory::TYPE_SYSV;
#endif
ContentParent* allocator = ContentParent::GetSingleton();
mBackSurface = new gfxSharedImageSurface();
static_cast<gfxSharedImageSurface*>(mBackSurface.get())->Init(allocator, size, format, shmtype);
}
}
#endif
}
if (surface) {
if (gCanvasMemoryReporter == nsnull) {
@ -1288,84 +1201,6 @@ nsCanvasRenderingContext2D::SetIsIPC(PRBool isIPC)
#endif
}
#ifdef MOZ_IPC
nsresult
nsCanvasRenderingContext2D::Swap(const gfxRect& aRect)
{
gfxContextPathAutoSaveRestore pathSR(mThebes);
gfxContextAutoSaveRestore autoSR(mThebes);
mThebes->SetOperator(gfxContext::OPERATOR_SOURCE);
mThebes->NewPath();
mThebes->SetSource(mBackSurface);
mThebes->Rectangle(aRect, PR_TRUE);
mThebes->Clip();
mThebes->Paint();
Redraw(aRect);
// Notify listeners that we've finished drawing
nsCOMPtr<nsIContent> content =
do_QueryInterface(static_cast<nsIDOMHTMLCanvasElement*>(mCanvasElement));
nsIDocument* ownerDoc = nsnull;
if (content)
ownerDoc = content->GetOwnerDoc();
if (ownerDoc && mCanvasElement) {
nsContentUtils::DispatchTrustedEvent(ownerDoc,
static_cast<nsIDOMHTMLCanvasElement*>(mCanvasElement),
NS_LITERAL_STRING("MozAsyncCanvasRender"),
/* aCanBubble = */ PR_TRUE,
/* aCancelable = */ PR_TRUE);
}
return NS_OK;
}
#endif
NS_IMETHODIMP
nsCanvasRenderingContext2D::Swap(mozilla::ipc::Shmem& aBack,
PRInt32 x, PRInt32 y, PRInt32 w, PRInt32 h)
{
#ifdef MOZ_IPC
if (!gfxSharedImageSurface::IsSharedImage(mBackSurface))
return NS_ERROR_FAILURE;
nsRefPtr<gfxSharedImageSurface> aBackImage = new gfxSharedImageSurface(aBack);
if (aBackImage->Data() != static_cast<gfxImageSurface*>(mBackSurface.get())->Data()) {
NS_ERROR("Incoming back surface is not equal to our back surface");
// Delete orphaned memory and return
ContentParent* allocator = ContentParent::GetSingleton(PR_FALSE);
if (allocator)
allocator->DeallocShmem(aBack);
return NS_ERROR_FAILURE;
}
Shmem& mem = static_cast<gfxSharedImageSurface*>(mBackSurface.get())->GetShmem();
if (mem.IsReadable())
NS_ERROR("Back surface readable before swap, this must not happen");
// Take mBackSurface shared memory ownership
mem = aBack;
return Swap(gfxRect(x, y, w, h));
#else
return NS_ERROR_NOT_IMPLEMENTED;
#endif
}
NS_IMETHODIMP
nsCanvasRenderingContext2D::Swap(PRUint32 nativeID,
PRInt32 x, PRInt32 y, PRInt32 w, PRInt32 h)
{
#ifdef MOZ_IPC
if (mIsBackSurfaceReadable)
NS_ERROR("Back surface readable before swap, this must not happen");
mIsBackSurfaceReadable = PR_TRUE;
return Swap(gfxRect(x, y, w, h));
#else
return NS_ERROR_NOT_IMPLEMENTED;
#endif
}
NS_IMETHODIMP
nsCanvasRenderingContext2D::Render(gfxContext *ctx, gfxPattern::GraphicsFilter aFilter)
{
@ -3904,62 +3739,17 @@ nsCanvasRenderingContext2D::AsyncDrawXULElement(nsIDOMXULElement* aElem, float a
renderDocFlags &= ~nsIPresShell::RENDER_IGNORE_VIEWPORT_SCROLLING;
}
PRInt32 x = nsPresContext::CSSPixelsToAppUnits(aX),
y = nsPresContext::CSSPixelsToAppUnits(aY),
w = nsPresContext::CSSPixelsToAppUnits(aW),
h = nsPresContext::CSSPixelsToAppUnits(aH);
nsRect rect(nsPresContext::CSSPixelsToAppUnits(aX),
nsPresContext::CSSPixelsToAppUnits(aY),
nsPresContext::CSSPixelsToAppUnits(aW),
nsPresContext::CSSPixelsToAppUnits(aH));
if (mIPC) {
#ifdef MOZ_X11
if (mBackSurface &&
mBackSurface->GetType() == gfxASurface::SurfaceTypeXlib) {
if (!mIsBackSurfaceReadable)
return NS_ERROR_FAILURE;
PRInt32 nativeID = static_cast<gfxXlibSurface*>(mBackSurface.get())->XDrawable();
mIsBackSurfaceReadable = PR_FALSE;
PDocumentRendererNativeIDParent* pdocrender =
child->SendPDocumentRendererNativeIDConstructor(x, y, w, h,
nsString(aBGColor),
renderDocFlags, flush,
mThebes->CurrentMatrix(),
nativeID);
if (!pdocrender)
return NS_ERROR_FAILURE;
DocumentRendererNativeIDParent* docrender =
static_cast<DocumentRendererNativeIDParent *>(pdocrender);
docrender->SetCanvas(this);
}
else
#endif
if (gfxSharedImageSurface::IsSharedImage(mBackSurface)) {
Shmem& backmem = static_cast<gfxSharedImageSurface*>(mBackSurface.get())->GetShmem();
if (!backmem.IsWritable())
return NS_ERROR_FAILURE;
PDocumentRendererShmemParent* pdocrender =
child->SendPDocumentRendererShmemConstructor(x, y, w, h,
nsString(aBGColor),
renderDocFlags, flush,
mThebes->CurrentMatrix(),
backmem);
if (!pdocrender)
return NS_ERROR_FAILURE;
DocumentRendererShmemParent* docrender =
static_cast<DocumentRendererShmemParent*>(pdocrender);
docrender->SetCanvas(this);
} else
return NS_ERROR_FAILURE;
} else {
PDocumentRendererParent *pdocrender =
child->SendPDocumentRendererConstructor(x, y, w, h,
child->SendPDocumentRendererConstructor(rect,
mThebes->CurrentMatrix(),
nsString(aBGColor),
renderDocFlags, flush);
renderDocFlags, flush,
nsIntSize(mWidth, mHeight));
if (!pdocrender)
return NS_ERROR_FAILURE;

View File

@ -2074,6 +2074,7 @@ nsEventStateManager::GenerateDragGesture(nsPresContext* aPresContext,
PRBool dragStarted = DoDefaultDragStart(aPresContext, event, dataTransfer,
targetContent, isSelection);
if (dragStarted) {
sActiveESM = nsnull;
aEvent->flags |= NS_EVENT_FLAG_STOP_DISPATCH;
}
}
@ -2935,7 +2936,6 @@ nsEventStateManager::PostHandleEvent(nsPresContext* aPresContext,
if (par)
activeContent = par;
}
SetGlobalActiveContent(this, activeContent);
}
}
else {
@ -2943,11 +2943,12 @@ nsEventStateManager::PostHandleEvent(nsPresContext* aPresContext,
// any of our own processing of a drag. Workaround for bug 43258.
StopTrackingDragGesture();
}
SetActiveManager(this, activeContent);
}
break;
case NS_MOUSE_BUTTON_UP:
{
ClearGlobalActiveContent();
ClearGlobalActiveContent(this);
if (IsMouseEventReal(aEvent)) {
if (!mCurrentTarget) {
nsIFrame* targ;
@ -3206,6 +3207,7 @@ nsEventStateManager::PostHandleEvent(nsPresContext* aPresContext,
targetContent, &status);
}
}
ClearGlobalActiveContent(this);
break;
}
case NS_DRAGDROP_EXIT:
@ -4706,22 +4708,25 @@ nsEventStateManager::DoContentCommandScrollEvent(nsContentCommandEvent* aEvent)
}
void
nsEventStateManager::SetGlobalActiveContent(nsEventStateManager* aNewESM,
nsIContent* aContent)
nsEventStateManager::SetActiveManager(nsEventStateManager* aNewESM,
nsIContent* aContent)
{
if (sActiveESM && aNewESM != sActiveESM) {
sActiveESM->SetContentState(nsnull, NS_EVENT_STATE_ACTIVE);
}
sActiveESM = aNewESM;
if (sActiveESM) {
if (sActiveESM && aContent) {
sActiveESM->SetContentState(aContent, NS_EVENT_STATE_ACTIVE);
}
}
void
nsEventStateManager::ClearGlobalActiveContent()
nsEventStateManager::ClearGlobalActiveContent(nsEventStateManager* aClearer)
{
if (sActiveESM) {
if (aClearer) {
aClearer->SetContentState(nsnull, NS_EVENT_STATE_ACTIVE);
}
if (sActiveESM && aClearer != sActiveESM) {
sActiveESM->SetContentState(nsnull, NS_EVENT_STATE_ACTIVE);
}
sActiveESM = nsnull;

View File

@ -159,8 +159,10 @@ public:
static nsIEventStateManager* GetActiveEventStateManager() { return sActiveESM; }
static void SetGlobalActiveContent(nsEventStateManager* aNewESM,
nsIContent* aContent);
// Sets aNewESM to be the active event state manager, and
// if aContent is non-null, marks the object as active.
static void SetActiveManager(nsEventStateManager* aNewESM,
nsIContent* aContent);
protected:
void UpdateCursor(nsPresContext* aPresContext, nsEvent* aEvent, nsIFrame* aTargetFrame, nsEventStatus* aStatus);
/**
@ -415,7 +417,7 @@ protected:
static nsEventStateManager* sActiveESM;
static void ClearGlobalActiveContent();
static void ClearGlobalActiveContent(nsEventStateManager* aClearer);
// Functions used for click hold context menus
PRBool mClickHoldContextMenu;

View File

@ -0,0 +1,31 @@
<!DOCTYPE html>
<html>
<head>
<script>
function boom()
{
var r = document.documentElement;
var i = document.getElementById("i");
document.removeChild(r);
document.appendChild(r);
w("dump('A\\n')");
document.removeChild(r);
w("dump('B\\n')");
document.appendChild(r);
function w(s)
{
var ns = document.createElement("script");
var nt = document.createTextNode(s);
ns.appendChild(nt);
i.appendChild(ns);
}
}
</script>
</head>
<body onload="boom();"><input id="i"></body>
</html>

View File

@ -20,3 +20,4 @@ load 580507-1.xhtml
load 590387.html
load 596785-1.html
load 596785-2.html
load 606430-1.html

View File

@ -64,6 +64,8 @@ public:
friend class nsDOMValidityState;
static const PRUint16 sContentSpecifiedMaxLengthMessage;
virtual ~nsIConstraintValidation();
PRBool IsValid() const { return mValidityBitField == 0; }

View File

@ -808,7 +808,8 @@ nsGenericHTMLElement::ScrollIntoView(PRBool aTop, PRUint8 optional_argc)
NS_PRESSHELL_SCROLL_BOTTOM;
presShell->ScrollContentIntoView(this, vpercent,
NS_PRESSHELL_SCROLL_ANYWHERE);
NS_PRESSHELL_SCROLL_ANYWHERE,
nsIPresShell::SCROLL_OVERFLOW_HIDDEN);
return NS_OK;
}

View File

@ -439,7 +439,7 @@ nsHTMLButtonElement::PostHandleEvent(nsEventChainPostVisitor& aVisitor)
if (NS_IS_TRUSTED_EVENT(aVisitor.mEvent)) {
nsIEventStateManager* esm =
aVisitor.mPresContext->EventStateManager();
nsEventStateManager::SetGlobalActiveContent(
nsEventStateManager::SetActiveManager(
static_cast<nsEventStateManager*>(esm), this);
}
nsIFocusManager* fm = nsFocusManager::GetFocusManager();

View File

@ -3972,6 +3972,9 @@ nsHTMLInputElement::GetValidationMessage(nsAString& aValidationMessage,
"FormValidationPatternMismatch",
message);
} else {
if (title.Length() > nsIConstraintValidation::sContentSpecifiedMaxLengthMessage) {
title.Truncate(nsIConstraintValidation::sContentSpecifiedMaxLengthMessage);
}
const PRUnichar* params[] = { title.get() };
rv = nsContentUtils::FormatLocalizedString(nsContentUtils::eDOM_PROPERTIES,
"FormValidationPatternMismatchWithTitle",

View File

@ -45,6 +45,8 @@
#include "nsHTMLFormElement.h"
const PRUint16 nsIConstraintValidation::sContentSpecifiedMaxLengthMessage = 256;
nsIConstraintValidation::nsIConstraintValidation()
: mValidityBitField(0)
, mValidity(nsnull)
@ -87,8 +89,14 @@ nsIConstraintValidation::GetValidationMessage(nsAString& aValidationMessage)
if (!authorMessage.IsEmpty()) {
aValidationMessage.Assign(authorMessage);
if (aValidationMessage.Length() > sContentSpecifiedMaxLengthMessage) {
aValidationMessage.Truncate(sContentSpecifiedMaxLengthMessage);
}
} else if (GetValidityState(VALIDITY_STATE_CUSTOM_ERROR)) {
aValidationMessage.Assign(mCustomValidity);
if (aValidationMessage.Length() > sContentSpecifiedMaxLengthMessage) {
aValidationMessage.Truncate(sContentSpecifiedMaxLengthMessage);
}
} else if (GetValidityState(VALIDITY_STATE_TOO_LONG)) {
GetValidationMessage(aValidationMessage, VALIDITY_STATE_TOO_LONG);
} else if (GetValidityState(VALIDITY_STATE_VALUE_MISSING)) {

View File

@ -78,6 +78,30 @@ struct SelectionState {
PRInt32 mEnd;
};
class RestoreSelectionState : public nsRunnable {
public:
RestoreSelectionState(nsTextControlFrame *aFrame, PRInt32 aStart, PRInt32 aEnd)
: mFrame(aFrame),
mWeakFrame(aFrame),
mStart(aStart),
mEnd(aEnd)
{
}
NS_IMETHOD Run() {
if (mWeakFrame.IsAlive()) {
mFrame->SetSelectionRange(mStart, mEnd);
}
return NS_OK;
}
private:
nsTextControlFrame* mFrame;
nsWeakFrame mWeakFrame;
PRInt32 mStart;
PRInt32 mEnd;
};
/*static*/
PRBool
nsITextControlElement::GetWrapPropertyEnum(nsIContent* aContent,
@ -160,7 +184,7 @@ public:
NS_IMETHOD SetSelectionFlags(PRInt16 aInEnable);
NS_IMETHOD GetSelectionFlags(PRInt16 *aOutEnable);
NS_IMETHOD GetSelection(PRInt16 type, nsISelection **_retval);
NS_IMETHOD ScrollSelectionIntoView(PRInt16 aType, PRInt16 aRegion, PRBool aIsSynchronous);
NS_IMETHOD ScrollSelectionIntoView(PRInt16 aType, PRInt16 aRegion, PRInt16 aFlags);
NS_IMETHOD RepaintSelection(PRInt16 type);
NS_IMETHOD RepaintSelection(nsPresContext* aPresContext, SelectionType aSelectionType);
NS_IMETHOD SetCaretEnabled(PRBool enabled);
@ -279,12 +303,12 @@ nsTextInputSelectionImpl::GetSelection(PRInt16 type, nsISelection **_retval)
}
NS_IMETHODIMP
nsTextInputSelectionImpl::ScrollSelectionIntoView(PRInt16 aType, PRInt16 aRegion, PRBool aIsSynchronous)
nsTextInputSelectionImpl::ScrollSelectionIntoView(PRInt16 aType, PRInt16 aRegion, PRInt16 aFlags)
{
if (!mFrameSelection)
return NS_ERROR_FAILURE;
return mFrameSelection->ScrollSelectionIntoView(aType, aRegion, aIsSynchronous);
return mFrameSelection->ScrollSelectionIntoView(aType, aRegion, aFlags);
}
NS_IMETHODIMP
@ -461,7 +485,8 @@ nsTextInputSelectionImpl::PageMove(PRBool aForward, PRBool aExtend)
}
// After ScrollSelectionIntoView(), the pending notifications might be
// flushed and PresShell/PresContext/Frames may be dead. See bug 418470.
return ScrollSelectionIntoView(nsISelectionController::SELECTION_NORMAL, nsISelectionController::SELECTION_FOCUS_REGION, PR_TRUE);
return ScrollSelectionIntoView(nsISelectionController::SELECTION_NORMAL, nsISelectionController::SELECTION_FOCUS_REGION,
nsISelectionController::SCROLL_SYNCHRONOUS);
}
NS_IMETHODIMP
@ -1328,7 +1353,7 @@ nsTextEditorState::PrepareEditor(const nsAString *aValue)
// Restore our selection after being bound to a new frame
if (mSelState) {
mBoundFrame->SetSelectionRange(mSelState->mStart, mSelState->mEnd);
nsContentUtils::AddScriptRunner(new RestoreSelectionState(mBoundFrame, mSelState->mStart, mSelState->mEnd));
mSelState = nsnull;
}

View File

@ -235,6 +235,9 @@ _TEST_FILES = \
test_bug596350.html \
test_bug600155.html \
test_bug556007.html \
test_bug606817.html \
test_bug297761.html \
file_bug297761.html \
$(NULL)
libs:: $(_TEST_FILES)

View File

@ -0,0 +1,13 @@
<!DOCTYPE html>
<html>
<head>
<base href="http://www.mozilla.org/">
</head>
<body>
<form action="">
<input type='submit' formaction="">
<button type='submit' formaction=""></button>
<input id='i' type='image' formaction="">
</form>
</body>
</html>

View File

@ -0,0 +1,78 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=297761
-->
<head>
<title>Test for Bug 297761</title>
<script type="application/javascript" src="/MochiKit/packed.js"></script>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=297761">Mozilla Bug 297761</a>
<p id="display"></p>
<div id="content">
<iframe src="file_bug297761.html"></iframe>
<iframe src="file_bug297761.html"></iframe>
<iframe src="file_bug297761.html"></iframe>
<iframe src="file_bug297761.html"></iframe>
</div>
<pre id="test">
<script type="application/javascript">
/** Test for Bug 297761 **/
SimpleTest.waitForExplicitFinish();
var nbTests = 4;
var curTest = 0;
function nextTest()
{
if (curTest == 3) {
frames[curTest].document.forms[0].submit();
} else {
var el = null;
if (curTest == 2) {
el = frames[curTest].document.getElementById('i');
} else {
el = frames[curTest].document.forms[0].elements[curTest];
}
el.focus();
el.click();
}
}
function frameLoaded(aFrame)
{
var documentLocation = location.href.replace(/\.html.*/, "\.html");
is(aFrame.contentWindow.location.href.replace(/\?x=0&y=0/, ""),
documentLocation.replace(/test_bug/, "file_bug"),
"form should have been submitted to the document location");
if (++curTest == nbTests) {
SimpleTest.finish();
} else {
nextTest();
}
}
function runTest()
{
// Initialize event handlers.
var frames = document.getElementsByTagName('iframe');
for (var i=0; i<nbTests; ++i) {
frames[i].setAttribute('onload', "frameLoaded(this);");
}
nextTest();
}
addLoadEvent(runTest);
</script>
</pre>
</body>
</html>

View File

@ -22,57 +22,68 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=392567
/** Test for Bug 392567 **/
var dataUrl = "http://mochi.test:8888/tests/content/html/content/test/bug392567.jar";
var jarUrl = "jar:" + dataUrl + "!/index.html";
var httpUrl = location.href.replace(/\.html.*/, "_404");
var previousDir = location.href.replace(/test\/[^\/]*$/, "");
SimpleTest.waitForExplicitFinish();
var form = document.forms.testForm;
var frame = frames.testFrame;
document.getElementById("testFrame").onload = processTestResult;
// List of tests to run, each test consists of form action URL and expected result URL
var tests = [
[jarUrl, jarUrl + "?$PARAMS", null],
[jarUrl + "?jarTest1=jarTest2", jarUrl + "?$PARAMS", null],
[jarUrl + "?jarTest3=jarTest4#jarTest5", jarUrl + "?$PARAMS#jarTest5", null],
["data:text/html,<html></html>", "data:text/html,<html></html>?$PARAMS", null],
["data:text/html,<html>How%20about%20this?</html>", "data:text/html,<html>How%20about%20this?$PARAMS", null],
[httpUrl, httpUrl + "?$PARAMS", null],
[httpUrl + "?httpTest1=httpTest2", httpUrl + "?$PARAMS", null ],
[httpUrl + "?httpTest3=httpTest4#httpTest5", httpUrl + "?$PARAMS#httpTest5", null],
["", jarUrl + "?key=value0", null],
[" ", jarUrl + "?key=value0", document.location],
["../", previousDir + "?$PARAMS", previousDir],
];
var currentTest = -1;
SimpleTest.waitForExplicitFinish();
runNextTest();
function runNextTest() {
currentTest++;
if (currentTest >= tests.length) {
SimpleTest.finish();
function runTests()
{
if (window.location.search.match(/\?key=value/)) {
return;
}
form.setAttribute("action", tests[currentTest][0]);
is(form.action, tests[currentTest][0],
"action IDL attribute should reflect the action content attribute");
is(form.mozActionUri, tests[currentTest][2] ? tests[currentTest][2] : tests[currentTest][0],
"mozActionUri IDL attribute should resolve the action URI");
form.key.value = "value" + currentTest;
form.submit();
var dataUrl = "http://mochi.test:8888/tests/content/html/content/test/bug392567.jar";
var jarUrl = "jar:" + dataUrl + "!/index.html";
var httpUrl = location.href.replace(/\.html.*/, "_404");
var previousDir = location.href.replace(/test\/[^\/]*$/, "");
var documentURL = location.href.replace(/\.html.*/, "\.html");
var form = document.forms.testForm;
var frame = frames.testFrame;
document.getElementById("testFrame").onload = processTestResult;
// List of tests to run, each test consists of form action URL and expected result URL
var tests = [
[jarUrl, jarUrl + "?$PARAMS", null],
[jarUrl + "?jarTest1=jarTest2", jarUrl + "?$PARAMS", null],
[jarUrl + "?jarTest3=jarTest4#jarTest5", jarUrl + "?$PARAMS#jarTest5", null],
["data:text/html,<html></html>", "data:text/html,<html></html>?$PARAMS", null],
["data:text/html,<html>How%20about%20this?</html>", "data:text/html,<html>How%20about%20this?$PARAMS", null],
[httpUrl, httpUrl + "?$PARAMS", null],
[httpUrl + "?httpTest1=httpTest2", httpUrl + "?$PARAMS", null ],
[httpUrl + "?httpTest3=httpTest4#httpTest5", httpUrl + "?$PARAMS#httpTest5", null],
["", documentURL + "?$PARAMS", null],
[" ", documentURL + "?$PARAMS", document.location],
["../", previousDir + "?$PARAMS", previousDir],
];
var currentTest = -1;
runNextTest();
function runNextTest() {
currentTest++;
if (currentTest >= tests.length) {
SimpleTest.finish();
return;
}
form.setAttribute("action", tests[currentTest][0]);
is(form.action, tests[currentTest][0],
"action IDL attribute should reflect the action content attribute");
is(form.mozActionUri, tests[currentTest][2] ? tests[currentTest][2] : tests[currentTest][0],
"mozActionUri IDL attribute should resolve the action URI");
form.key.value = "value" + currentTest;
form.submit();
}
function processTestResult() {
var expected = tests[currentTest][1].replace(/\$PARAMS/, "key=value" + currentTest);
is(frame.location.href, expected, "Submitting to " + tests[currentTest][0]);
setTimeout(runNextTest, 0);
}
}
function processTestResult() {
var expected = tests[currentTest][1].replace(/\$PARAMS/, "key=value" + currentTest);
is(frame.location.href, expected, "Submitting to " + tests[currentTest][0]);
setTimeout(runNextTest, 0);
}
addLoadEvent(runTests);
</script>
</pre>

View File

@ -0,0 +1,65 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=606817
-->
<head>
<title>Test for Bug 606817</title>
<script type="application/javascript" src="/MochiKit/packed.js"></script>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=606817">Mozilla Bug 606817</a>
<p id="display"></p>
<pre id="test">
<script type="application/javascript">
/** Test for Bug 606817 **/
var messageMaxLength = 256;
function checkMessage(aInput, aMsg, aWithTerminalPeriod)
{
ok(aInput.validationMessage != aMsg,
"Original content-defined message should have been truncate");
is(aInput.validationMessage.length - aInput.validationMessage.indexOf("_42_"),
aWithTerminalPeriod ? messageMaxLength+1 : messageMaxLength,
"validation message should be 256 characters length");
}
var input = document.createElement("input");
var msg = "";
for (var i=0; i<75; ++i) {
msg += "_42_";
}
// msg is now 300 chars long
// Testing with setCustomValidity().
input.setCustomValidity(msg);
checkMessage(input, msg, false);
// The input is still invalid but x-moz-errormessage will be used as the message.
input.setAttribute("x-moz-errormessage", msg);
checkMessage(input, msg, false);
// Cleaning.
input.setCustomValidity("");
input.removeAttribute("x-moz-errormessage");
// Testing with pattern and titl.
input.pattern = "[0-9]*";
input.value = "foo";
input.title = msg;
checkMessage(input, msg, true);
// Cleaning.
input.removeAttribute("pattern");
input.removeAttribute("title");
input.value = "";
</script>
</pre>
</body>
</html>

View File

@ -65,9 +65,10 @@ function startTest(test, token) {
if (v.parentNode) {
v.parentNode.removeChild(v);
}
dump("SEEK-TEST: Finished " + name + "\n");
manager.finished(v.token);
}}(v, manager);
dump("Seek test: " + test.number + "\n");
dump("SEEK-TEST: Started " + name + "\n");
window['test_seek' + test.number](v, test.duration/2, localIs, localOk, localFinish);
}

View File

@ -404,6 +404,8 @@ nsXULCommandDispatcher::UpdateCommands(const nsAString& aEventName)
if (NS_FAILED(rv)) return rv;
}
nsCOMArray<nsIContent> updaters;
for (Updater* updater = mUpdaters; updater != nsnull; updater = updater->mNext) {
// Skip any nodes that don't match our 'events' or 'targets'
// filters.
@ -418,6 +420,12 @@ nsXULCommandDispatcher::UpdateCommands(const nsAString& aEventName)
if (! content)
return NS_ERROR_UNEXPECTED;
updaters.AppendObject(content);
}
for (PRUint32 u = 0; u < updaters.Count(); u++) {
nsIContent* content = updaters[u];
nsCOMPtr<nsIDocument> document = content->GetDocument();
NS_ASSERTION(document != nsnull, "element has no document");
@ -430,7 +438,7 @@ nsXULCommandDispatcher::UpdateCommands(const nsAString& aEventName)
CopyUTF16toUTF8(aEventName, aeventnameC);
PR_LOG(gLog, PR_LOG_NOTICE,
("xulcmd[%p] update %p event=%s",
this, updater->mElement.get(),
this, content,
aeventnameC.get()));
}
#endif

View File

@ -145,6 +145,7 @@ NS_NewXULPrototypeCache(nsISupports* aOuter, REFNSIID aIID, void** aResult)
nsXULPrototypeCache *p = result;
obsSvc->AddObserver(p, "chrome-flush-skin-caches", PR_FALSE);
obsSvc->AddObserver(p, "chrome-flush-caches", PR_FALSE);
obsSvc->AddObserver(p, "startupcache-invalidate", PR_FALSE);
}
return rv;
@ -410,10 +411,6 @@ nsXULPrototypeCache::AbortFastLoads()
NS_BREAK();
#endif
// Save a strong ref to the FastLoad file, so we can remove it after we
// close open streams to it.
nsCOMPtr<nsIFile> file = gFastLoadFile;
// Flush the XUL cache for good measure, in case we cached a bogus/downrev
// script, somehow.
Flush();
@ -421,29 +418,42 @@ nsXULPrototypeCache::AbortFastLoads()
// Clear the FastLoad set
mFastLoadURITable.Clear();
if (! gFastLoadService)
return;
nsCOMPtr<nsIFastLoadService> fastLoadService = gFastLoadService;
nsCOMPtr<nsIFile> file = gFastLoadFile;
nsresult rv;
if (! fastLoadService) {
fastLoadService = do_GetFastLoadService();
if (! fastLoadService)
return;
rv = fastLoadService->NewFastLoadFile(XUL_FASTLOAD_FILE_BASENAME,
getter_AddRefs(file));
if (NS_FAILED(rv))
return;
}
// Fetch the current input (if FastLoad file existed) or output (if we're
// creating the FastLoad file during this app startup) stream.
nsCOMPtr<nsIObjectInputStream> objectInput;
nsCOMPtr<nsIObjectOutputStream> objectOutput;
gFastLoadService->GetInputStream(getter_AddRefs(objectInput));
gFastLoadService->GetOutputStream(getter_AddRefs(objectOutput));
fastLoadService->GetInputStream(getter_AddRefs(objectInput));
fastLoadService->GetOutputStream(getter_AddRefs(objectOutput));
if (objectOutput) {
gFastLoadService->SetOutputStream(nsnull);
fastLoadService->SetOutputStream(nsnull);
if (NS_SUCCEEDED(objectOutput->Close()) && gChecksumXULFastLoadFile)
gFastLoadService->CacheChecksum(gFastLoadFile,
objectOutput);
fastLoadService->CacheChecksum(file,
objectOutput);
}
if (objectInput) {
// If this is the last of one or more XUL master documents loaded
// together at app startup, close the FastLoad service's singleton
// input stream now.
gFastLoadService->SetInputStream(nsnull);
fastLoadService->SetInputStream(nsnull);
objectInput->Close();
}
@ -462,13 +472,15 @@ nsXULPrototypeCache::AbortFastLoads()
}
file->MoveToNative(nsnull, NS_LITERAL_CSTRING("Aborted.mfasl"));
#else
file->Remove(PR_FALSE);
rv = file->Remove(PR_FALSE);
if (NS_FAILED(rv))
NS_WARNING("Failed to remove fastload file, fastload data may be outdated");
#endif
}
// If the list is empty now, the FastLoad process is done.
NS_RELEASE(gFastLoadService);
NS_RELEASE(gFastLoadFile);
NS_IF_RELEASE(gFastLoadService);
NS_IF_RELEASE(gFastLoadFile);
}

View File

@ -57,6 +57,8 @@ _TEST_FILES = \
$(NULL)
_CHROME_FILES = \
test_bug583948.xul \
window_bug583948.xul \
test_bug497875.xul \
bug497875-iframe.xul \
$(NULL)

View File

@ -0,0 +1,41 @@
<?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
type="text/css"?>
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<script type="application/javascript" src="chrome://mochikit/content/MochiKit/packed.js"></script>
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
<body xmlns="http://www.w3.org/1999/xhtml">
<div id="content" style="display: none"/>
</body>
<script>
SimpleTest.waitForExplicitFinish();
var attempts = 0;
function update() {
setTimeout(function() {
if (otherWindow.location)
otherWindow.location.reload()
}, 1);
otherWindow.document.commandDispatcher.updateCommands('');
// without the crash fix, this usually crashes after 2 to 4 reloads
if (++attempts == 6) {
ok(true, "didn't crash after 6 attempts");
otherWindow.close();
SimpleTest.finish();
}
else {
setTimeout(update, 100);
}
}
var otherWindow = window.open("window_bug583948.xul", "_new", "chrome");
setTimeout(update, 100);
</script>
</window>

View File

@ -0,0 +1,8 @@
<?xml-stylesheet href="chrome://browser/skin/" type="text/css"?>
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<command oncommandupdate="document.removeChild(document.documentElement)" commandupdater="true"/>
<box command="c"/>
<iframe/>
</window>

View File

@ -1139,13 +1139,8 @@ nsXULTemplateBuilder::AttributeChanged(nsIDocument* aDocument,
// Check for a change to the 'datasources' attribute. If so, setup
// mDB by parsing the new value and rebuild.
else if (aAttribute == nsGkAtoms::datasources) {
Uninit(PR_FALSE); // Reset results
PRBool shouldDelay;
LoadDataSources(aDocument, &shouldDelay);
if (!shouldDelay)
nsContentUtils::AddScriptRunner(
NS_NewRunnableMethod(this, &nsXULTemplateBuilder::RunnableRebuild));
nsContentUtils::AddScriptRunner(
NS_NewRunnableMethod(this, &nsXULTemplateBuilder::RunnableLoadAndRebuild));
}
}
}
@ -1163,8 +1158,9 @@ nsXULTemplateBuilder::ContentRemoved(nsIDocument* aDocument,
if (mQueryProcessor)
mQueryProcessor->Done();
// use false since content is going away anyway
Uninit(PR_FALSE);
// Pass false to Uninit since content is going away anyway
nsContentUtils::AddScriptRunner(
NS_NewRunnableMethod(this, &nsXULTemplateBuilder::UninitFalse));
aDocument->RemoveObserver(this);
@ -1201,7 +1197,8 @@ nsXULTemplateBuilder::NodeWillBeDestroyed(const nsINode* aNode)
mCompDB = nsnull;
mRoot = nsnull;
Uninit(PR_TRUE);
nsContentUtils::AddScriptRunner(
NS_NewRunnableMethod(this, &nsXULTemplateBuilder::UninitTrue));
}

View File

@ -152,6 +152,20 @@ public:
RebuildAll() = 0; // must be implemented by subclasses
void RunnableRebuild() { Rebuild(); }
void RunnableLoadAndRebuild() {
Uninit(PR_FALSE); // Reset results
nsCOMPtr<nsIDocument> doc = mRoot ? mRoot->GetDocument() : nsnull;
if (doc) {
PRBool shouldDelay;
LoadDataSources(doc, &shouldDelay);
if (!shouldDelay) {
Rebuild();
}
}
}
void UninitFalse() { Uninit(PR_FALSE); }
void UninitTrue() { Uninit(PR_TRUE); }
/**
* Find the <template> tag that applies for this builder

View File

@ -27,8 +27,7 @@ function checkConsole(expectedError)
{
var out = {};
consoleService.getMessageArray(out, {});
var messages = out.value || [];
is(messages[0].message, expectedError, "logged message " + expectedError);
is(out.value[0].message, expectedError, "logged message " + expectedError);
}
// each test consists of a pre function executed before the template build, an

View File

@ -159,7 +159,7 @@
#include "nsIController.h"
#include "nsPICommandUpdater.h"
#include "nsIDOMHTMLAnchorElement.h"
#include "nsIWebBrowserChrome2.h"
#include "nsIWebBrowserChrome3.h"
#include "nsITabChild.h"
#include "nsIStrictTransportSecurityService.h"
@ -711,6 +711,7 @@ nsDocShell::nsDocShell():
mAllowKeywordFixup(PR_FALSE),
mIsOffScreenBrowser(PR_FALSE),
mIsActive(PR_TRUE),
mIsAppTab(PR_FALSE),
mFiredUnloadEvent(PR_FALSE),
mEODForCurrentDocument(PR_FALSE),
mURIResultedInDocument(PR_FALSE),
@ -4802,6 +4803,20 @@ nsDocShell::GetIsActive(PRBool *aIsActive)
return NS_OK;
}
NS_IMETHODIMP
nsDocShell::SetIsAppTab(PRBool aIsAppTab)
{
mIsAppTab = aIsAppTab;
return NS_OK;
}
NS_IMETHODIMP
nsDocShell::GetIsAppTab(PRBool *aIsAppTab)
{
*aIsAppTab = mIsAppTab;
return NS_OK;
}
NS_IMETHODIMP
nsDocShell::SetVisibility(PRBool aVisibility)
{
@ -11311,8 +11326,22 @@ nsDocShell::OnLinkClick(nsIContent* aContent,
return NS_OK;
}
nsresult rv = NS_ERROR_FAILURE;
nsAutoString target;
nsCOMPtr<nsIWebBrowserChrome3> browserChrome3 = do_GetInterface(mTreeOwner);
if (browserChrome3) {
nsCOMPtr<nsIDOMNode> linkNode = do_QueryInterface(aContent);
nsAutoString oldTarget(aTargetSpec);
rv = browserChrome3->OnBeforeLinkTraversal(oldTarget, aURI,
linkNode, mIsAppTab, target);
}
if (NS_FAILED(rv))
target = aTargetSpec;
nsCOMPtr<nsIRunnable> ev =
new OnLinkClickEvent(this, aContent, aURI, aTargetSpec,
new OnLinkClickEvent(this, aContent, aURI, target.get(),
aPostDataStream, aHeadersDataStream);
return NS_DispatchToCurrentThread(ev);
}

View File

@ -790,6 +790,7 @@ protected:
PRPackedBool mAllowKeywordFixup;
PRPackedBool mIsOffScreenBrowser;
PRPackedBool mIsActive;
PRPackedBool mIsAppTab;
// This boolean is set to true right before we fire pagehide and generally
// unset when we embed a new content viewer. While it's true no navigation

View File

@ -71,7 +71,7 @@ interface nsIPrincipal;
interface nsIWebBrowserPrint;
interface nsIVariant;
[scriptable, uuid(74470127-87eb-4f79-8293-1616fe9cb689)]
[scriptable, uuid(98cdbcc4-2d81-4191-a63f-b6c52085edbc)]
interface nsIDocShell : nsISupports
{
/**
@ -529,11 +529,17 @@ interface nsIDocShell : nsISupports
*/
attribute boolean isActive;
/**
* The ID of the docshell in the session history.
*/
readonly attribute unsigned long long historyID;
/**
* Sets whether a docshell is an app tab. An app tab docshell may behave
* differently than a non-app tab docshell in some cases, such as when
* handling link clicks. Docshells are not app tabs unless told otherwise.
*/
attribute boolean isAppTab;
};
[uuid(5f7a2184-31b6-4d67-9c75-0c17477766e2)]

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