mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Merge from mc
This commit is contained in:
commit
c92986c46a
@ -438,6 +438,11 @@ HandlerInfoWrapper.prototype = {
|
||||
|
||||
this._prefSvc.setCharPref(PREF_DISABLED_PLUGIN_TYPES,
|
||||
disabledPluginTypes.join(","));
|
||||
|
||||
// Update the category manager so existing browser windows update.
|
||||
this._categoryMgr.deleteCategoryEntry("Gecko-Content-Viewers",
|
||||
this.type,
|
||||
false);
|
||||
},
|
||||
|
||||
enablePluginType: function() {
|
||||
@ -448,6 +453,14 @@ HandlerInfoWrapper.prototype = {
|
||||
|
||||
this._prefSvc.setCharPref(PREF_DISABLED_PLUGIN_TYPES,
|
||||
disabledPluginTypes.join(","));
|
||||
|
||||
// Update the category manager so existing browser windows update.
|
||||
this._categoryMgr.
|
||||
addCategoryEntry("Gecko-Content-Viewers",
|
||||
this.type,
|
||||
"@mozilla.org/content/plugin/document-loader-factory;1",
|
||||
false,
|
||||
true);
|
||||
},
|
||||
|
||||
|
||||
|
@ -365,7 +365,122 @@
|
||||
@BINPATH@/extensions/{972ce4c6-7e08-4474-a285-3208198ce6fd}/icon.png
|
||||
@BINPATH@/extensions/{972ce4c6-7e08-4474-a285-3208198ce6fd}/preview.png
|
||||
#if MOZ_UPDATE_CHANNEL == beta
|
||||
@BINPATH@/extensions/testpilot@labs.mozilla.com/*
|
||||
@BINPATH@/extensions/testpilot@labs.mozilla.com/chrome.manifest
|
||||
@BINPATH@/extensions/testpilot@labs.mozilla.com/components/TestPilot.js
|
||||
@BINPATH@/extensions/testpilot@labs.mozilla.com/content/all-studies-window.js
|
||||
@BINPATH@/extensions/testpilot@labs.mozilla.com/content/all-studies-window.xul
|
||||
@BINPATH@/extensions/testpilot@labs.mozilla.com/content/browser.css
|
||||
@BINPATH@/extensions/testpilot@labs.mozilla.com/content/browser.js
|
||||
@BINPATH@/extensions/testpilot@labs.mozilla.com/content/debug.html
|
||||
@BINPATH@/extensions/testpilot@labs.mozilla.com/content/experiment-page.js
|
||||
@BINPATH@/extensions/testpilot@labs.mozilla.com/content/feedback-browser.xul
|
||||
@BINPATH@/extensions/testpilot@labs.mozilla.com/content/flot/jquery.colorhelpers.js
|
||||
@BINPATH@/extensions/testpilot@labs.mozilla.com/content/flot/jquery.colorhelpers.min.js
|
||||
@BINPATH@/extensions/testpilot@labs.mozilla.com/content/flot/jquery.flot.crosshair.js
|
||||
@BINPATH@/extensions/testpilot@labs.mozilla.com/content/flot/jquery.flot.crosshair.min.js
|
||||
@BINPATH@/extensions/testpilot@labs.mozilla.com/content/flot/jquery.flot.image.js
|
||||
@BINPATH@/extensions/testpilot@labs.mozilla.com/content/flot/jquery.flot.image.min.js
|
||||
@BINPATH@/extensions/testpilot@labs.mozilla.com/content/flot/jquery.flot.js
|
||||
@BINPATH@/extensions/testpilot@labs.mozilla.com/content/flot/jquery.flot.min.js
|
||||
@BINPATH@/extensions/testpilot@labs.mozilla.com/content/flot/jquery.flot.navigate.js
|
||||
@BINPATH@/extensions/testpilot@labs.mozilla.com/content/flot/jquery.flot.navigate.min.js
|
||||
@BINPATH@/extensions/testpilot@labs.mozilla.com/content/flot/jquery.flot.selection.js
|
||||
@BINPATH@/extensions/testpilot@labs.mozilla.com/content/flot/jquery.flot.selection.min.js
|
||||
@BINPATH@/extensions/testpilot@labs.mozilla.com/content/flot/jquery.flot.stack.js
|
||||
@BINPATH@/extensions/testpilot@labs.mozilla.com/content/flot/jquery.flot.stack.min.js
|
||||
@BINPATH@/extensions/testpilot@labs.mozilla.com/content/flot/jquery.flot.threshold.js
|
||||
@BINPATH@/extensions/testpilot@labs.mozilla.com/content/flot/jquery.flot.threshold.min.js
|
||||
@BINPATH@/extensions/testpilot@labs.mozilla.com/content/flot/jquery.js
|
||||
@BINPATH@/extensions/testpilot@labs.mozilla.com/content/flot/jquery.min.js
|
||||
@BINPATH@/extensions/testpilot@labs.mozilla.com/content/raw-data-dialog.js
|
||||
@BINPATH@/extensions/testpilot@labs.mozilla.com/content/raw-data-dialog.xul
|
||||
@BINPATH@/extensions/testpilot@labs.mozilla.com/content/screen.css
|
||||
@BINPATH@/extensions/testpilot@labs.mozilla.com/content/status-quit.html
|
||||
@BINPATH@/extensions/testpilot@labs.mozilla.com/content/status.html
|
||||
@BINPATH@/extensions/testpilot@labs.mozilla.com/content/survey-generator.js
|
||||
@BINPATH@/extensions/testpilot@labs.mozilla.com/content/take-survey.html
|
||||
@BINPATH@/extensions/testpilot@labs.mozilla.com/content/tp-browser.xul
|
||||
@BINPATH@/extensions/testpilot@labs.mozilla.com/content/welcome-page.js
|
||||
@BINPATH@/extensions/testpilot@labs.mozilla.com/content/welcome.html
|
||||
@BINPATH@/extensions/testpilot@labs.mozilla.com/content/window-utils.js
|
||||
@BINPATH@/extensions/testpilot@labs.mozilla.com/defaults/preferences/preferences.js
|
||||
@BINPATH@/extensions/testpilot@labs.mozilla.com/install.rdf
|
||||
@BINPATH@/extensions/testpilot@labs.mozilla.com/instrument/chrome.manifest
|
||||
@BINPATH@/extensions/testpilot@labs.mozilla.com/instrument/install.rdf
|
||||
@BINPATH@/extensions/testpilot@labs.mozilla.com/instrument/instrument.jsm
|
||||
@BINPATH@/extensions/testpilot@labs.mozilla.com/instrument/instrument.xul
|
||||
@BINPATH@/extensions/testpilot@labs.mozilla.com/modules/dbutils.js
|
||||
@BINPATH@/extensions/testpilot@labs.mozilla.com/modules/experiment_data_store.js
|
||||
@BINPATH@/extensions/testpilot@labs.mozilla.com/modules/extension-update.js
|
||||
@BINPATH@/extensions/testpilot@labs.mozilla.com/modules/feedback.js
|
||||
@BINPATH@/extensions/testpilot@labs.mozilla.com/modules/jar-code-store.js
|
||||
@BINPATH@/extensions/testpilot@labs.mozilla.com/modules/lib/cuddlefish.js
|
||||
@BINPATH@/extensions/testpilot@labs.mozilla.com/modules/lib/memory.js
|
||||
@BINPATH@/extensions/testpilot@labs.mozilla.com/modules/lib/observer-service.js
|
||||
@BINPATH@/extensions/testpilot@labs.mozilla.com/modules/lib/plain-text-console.js
|
||||
@BINPATH@/extensions/testpilot@labs.mozilla.com/modules/lib/preferences-service.js
|
||||
@BINPATH@/extensions/testpilot@labs.mozilla.com/modules/lib/securable-module.js
|
||||
@BINPATH@/extensions/testpilot@labs.mozilla.com/modules/lib/timer.js
|
||||
@BINPATH@/extensions/testpilot@labs.mozilla.com/modules/lib/traceback.js
|
||||
@BINPATH@/extensions/testpilot@labs.mozilla.com/modules/lib/unit-test.js
|
||||
@BINPATH@/extensions/testpilot@labs.mozilla.com/modules/lib/unload.js
|
||||
@BINPATH@/extensions/testpilot@labs.mozilla.com/modules/lib/url.js
|
||||
@BINPATH@/extensions/testpilot@labs.mozilla.com/modules/log4moz.js
|
||||
@BINPATH@/extensions/testpilot@labs.mozilla.com/modules/metadata.js
|
||||
@BINPATH@/extensions/testpilot@labs.mozilla.com/modules/Observers.js
|
||||
@BINPATH@/extensions/testpilot@labs.mozilla.com/modules/remote-experiment-loader.js
|
||||
@BINPATH@/extensions/testpilot@labs.mozilla.com/modules/setup.js
|
||||
@BINPATH@/extensions/testpilot@labs.mozilla.com/modules/string_sanitizer.js
|
||||
@BINPATH@/extensions/testpilot@labs.mozilla.com/modules/tasks.js
|
||||
@BINPATH@/extensions/testpilot@labs.mozilla.com/skin/all/badge-default.png
|
||||
@BINPATH@/extensions/testpilot@labs.mozilla.com/skin/all/bg.jpg
|
||||
@BINPATH@/extensions/testpilot@labs.mozilla.com/skin/all/css/screen-standalone.css
|
||||
@BINPATH@/extensions/testpilot@labs.mozilla.com/skin/all/dino_32x32.png
|
||||
@BINPATH@/extensions/testpilot@labs.mozilla.com/skin/all/images/bg-status.jpg
|
||||
@BINPATH@/extensions/testpilot@labs.mozilla.com/skin/all/images/callout.png
|
||||
@BINPATH@/extensions/testpilot@labs.mozilla.com/skin/all/images/callout_continue.png
|
||||
@BINPATH@/extensions/testpilot@labs.mozilla.com/skin/all/images/data1.jpg
|
||||
@BINPATH@/extensions/testpilot@labs.mozilla.com/skin/all/images/data2.jpg
|
||||
@BINPATH@/extensions/testpilot@labs.mozilla.com/skin/all/images/home_comments.png
|
||||
@BINPATH@/extensions/testpilot@labs.mozilla.com/skin/all/images/home_computer.png
|
||||
@BINPATH@/extensions/testpilot@labs.mozilla.com/skin/all/images/home_continue.png
|
||||
@BINPATH@/extensions/testpilot@labs.mozilla.com/skin/all/images/home_quit.png
|
||||
@BINPATH@/extensions/testpilot@labs.mozilla.com/skin/all/images/home_results.png
|
||||
@BINPATH@/extensions/testpilot@labs.mozilla.com/skin/all/images/home_twitter.png
|
||||
@BINPATH@/extensions/testpilot@labs.mozilla.com/skin/all/images/home_upcoming.png
|
||||
@BINPATH@/extensions/testpilot@labs.mozilla.com/skin/all/logo.png
|
||||
@BINPATH@/extensions/testpilot@labs.mozilla.com/skin/all/mozilla-logo.png
|
||||
@BINPATH@/extensions/testpilot@labs.mozilla.com/skin/all/status-completed.png
|
||||
@BINPATH@/extensions/testpilot@labs.mozilla.com/skin/all/status-ejected.png
|
||||
@BINPATH@/extensions/testpilot@labs.mozilla.com/skin/all/status-missed.png
|
||||
@BINPATH@/extensions/testpilot@labs.mozilla.com/skin/all/testpilot_16x16.png
|
||||
@BINPATH@/extensions/testpilot@labs.mozilla.com/skin/all/testPilot_200x200.png
|
||||
@BINPATH@/extensions/testpilot@labs.mozilla.com/skin/all/testpilot_32x32.png
|
||||
@BINPATH@/extensions/testpilot@labs.mozilla.com/skin/all/tp-completedstudies-32x32.png
|
||||
@BINPATH@/extensions/testpilot@labs.mozilla.com/skin/all/tp-currentstudies-32x32.png
|
||||
@BINPATH@/extensions/testpilot@labs.mozilla.com/skin/all/tp-generic-32x32.png
|
||||
@BINPATH@/extensions/testpilot@labs.mozilla.com/skin/all/tp-learned-32x32.png
|
||||
@BINPATH@/extensions/testpilot@labs.mozilla.com/skin/all/tp-results-48x48.png
|
||||
@BINPATH@/extensions/testpilot@labs.mozilla.com/skin/all/tp-settings-32x32.png
|
||||
@BINPATH@/extensions/testpilot@labs.mozilla.com/skin/all/tp-study-48x48.png
|
||||
@BINPATH@/extensions/testpilot@labs.mozilla.com/skin/all/tp-submit-48x48.png
|
||||
@BINPATH@/extensions/testpilot@labs.mozilla.com/skin/linux/close_button.png
|
||||
@BINPATH@/extensions/testpilot@labs.mozilla.com/skin/linux/feedback-frown-16x16.png
|
||||
@BINPATH@/extensions/testpilot@labs.mozilla.com/skin/linux/feedback-smile-16x16.png
|
||||
@BINPATH@/extensions/testpilot@labs.mozilla.com/skin/linux/feedback.css
|
||||
@BINPATH@/extensions/testpilot@labs.mozilla.com/skin/mac/close_button.png
|
||||
@BINPATH@/extensions/testpilot@labs.mozilla.com/skin/mac/feedback-frown-16x16.png
|
||||
@BINPATH@/extensions/testpilot@labs.mozilla.com/skin/mac/feedback-smile-16x16.png
|
||||
@BINPATH@/extensions/testpilot@labs.mozilla.com/skin/mac/feedback.css
|
||||
@BINPATH@/extensions/testpilot@labs.mozilla.com/skin/mac/notification-tail-down.png
|
||||
@BINPATH@/extensions/testpilot@labs.mozilla.com/skin/mac/notification-tail-up.png
|
||||
@BINPATH@/extensions/testpilot@labs.mozilla.com/skin/win/close_button.png
|
||||
@BINPATH@/extensions/testpilot@labs.mozilla.com/skin/win/feedback-frown-16x16.png
|
||||
@BINPATH@/extensions/testpilot@labs.mozilla.com/skin/win/feedback-smile-16x16.png
|
||||
@BINPATH@/extensions/testpilot@labs.mozilla.com/skin/win/feedback.css
|
||||
@BINPATH@/extensions/testpilot@labs.mozilla.com/skin/win/notification-tail-down.png
|
||||
@BINPATH@/extensions/testpilot@labs.mozilla.com/skin/win/notification-tail-up.png
|
||||
@BINPATH@/extensions/testpilot@labs.mozilla.com/tests/test_data_store.js
|
||||
#endif
|
||||
@BINPATH@/chrome/toolkit.jar
|
||||
@BINPATH@/chrome/toolkit.manifest
|
||||
|
@ -1778,30 +1778,10 @@ nsScriptSecurityManager::CanExecuteScripts(JSContext* cx,
|
||||
docshell = window->GetDocShell();
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDocShellTreeItem> globalObjTreeItem =
|
||||
do_QueryInterface(docshell);
|
||||
|
||||
if (globalObjTreeItem)
|
||||
{
|
||||
nsCOMPtr<nsIDocShellTreeItem> treeItem(globalObjTreeItem);
|
||||
nsCOMPtr<nsIDocShellTreeItem> parentItem;
|
||||
|
||||
// Walk up the docshell tree to see if any containing docshell disallows scripts
|
||||
do
|
||||
{
|
||||
rv = docshell->GetAllowJavascript(result);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
if (!*result)
|
||||
return NS_OK; // Do not run scripts
|
||||
treeItem->GetParent(getter_AddRefs(parentItem));
|
||||
treeItem.swap(parentItem);
|
||||
docshell = do_QueryInterface(treeItem);
|
||||
#ifdef DEBUG
|
||||
if (treeItem && !docshell) {
|
||||
NS_ERROR("cannot get a docshell from a treeItem!");
|
||||
}
|
||||
#endif // DEBUG
|
||||
} while (treeItem && docshell);
|
||||
if (docshell) {
|
||||
rv = docshell->GetCanExecuteScripts(result);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
if (!*result) return NS_OK;
|
||||
}
|
||||
|
||||
// OK, the docshell doesn't have script execution explicitly disabled.
|
||||
|
@ -6183,41 +6183,22 @@ nsIContentUtils::FindInternalContentViewer(const char* aType,
|
||||
if (!catMan)
|
||||
return NULL;
|
||||
|
||||
FullPagePluginEnabledType pluginEnabled = NOT_ENABLED;
|
||||
|
||||
nsCOMPtr<nsIPluginHost> pluginHost =
|
||||
do_GetService(MOZ_PLUGIN_HOST_CONTRACTID);
|
||||
if (pluginHost) {
|
||||
pluginHost->IsFullPagePluginEnabledForType(aType, &pluginEnabled);
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDocumentLoaderFactory> docFactory;
|
||||
|
||||
if (OVERRIDE_BUILTIN == pluginEnabled) {
|
||||
docFactory = do_GetService(PLUGIN_DLF_CONTRACTID);
|
||||
if (docFactory && aLoaderType) {
|
||||
*aLoaderType = TYPE_PLUGIN;
|
||||
}
|
||||
return docFactory.forget();
|
||||
}
|
||||
|
||||
nsXPIDLCString contractID;
|
||||
nsresult rv = catMan->GetCategoryEntry("Gecko-Content-Viewers", aType, getter_Copies(contractID));
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
docFactory = do_GetService(contractID);
|
||||
if (docFactory && aLoaderType) {
|
||||
*aLoaderType = contractID.EqualsLiteral(CONTENT_DLF_CONTRACTID) ? TYPE_CONTENT : TYPE_UNKNOWN;
|
||||
if (contractID.EqualsLiteral(CONTENT_DLF_CONTRACTID))
|
||||
*aLoaderType = TYPE_CONTENT;
|
||||
else if (contractID.EqualsLiteral(PLUGIN_DLF_CONTRACTID))
|
||||
*aLoaderType = TYPE_PLUGIN;
|
||||
else
|
||||
*aLoaderType = TYPE_UNKNOWN;
|
||||
}
|
||||
return docFactory.forget();
|
||||
}
|
||||
|
||||
if (AVAILABLE == pluginEnabled) {
|
||||
docFactory = do_GetService(PLUGIN_DLF_CONTRACTID);
|
||||
if (docFactory && aLoaderType) {
|
||||
*aLoaderType = TYPE_PLUGIN;
|
||||
}
|
||||
return docFactory.forget();
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
@ -65,7 +65,6 @@ _TEST_FILES = test_bug1682.html \
|
||||
test_bug369370.html \
|
||||
bug369370-popup.png \
|
||||
test_bug380383.html \
|
||||
test_bug386495.html \
|
||||
test_bug391777.html \
|
||||
test_bug402680.html \
|
||||
test_bug403868.html \
|
||||
|
@ -1,42 +0,0 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=386495
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 386495</title>
|
||||
<script type="text/javascript" src="/MochiKit/packed.js"></script>
|
||||
<script type="text/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=386495">Mozilla Bug 386495</a>
|
||||
<p id="display"></p>
|
||||
<div id="content">
|
||||
<iframe id="testIframe"></iframe>
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
/** Test for Bug 386495 **/
|
||||
|
||||
function finishTest() {
|
||||
is(document.getElementById("testIframe").contentWindow.timeoutFired, false, "Timeout shouldn't fire.");
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
function testContentEditable() {
|
||||
document.getElementById('testIframe').style.display = 'block';
|
||||
document.getElementById('testIframe').contentWindow.timeoutFired = false;
|
||||
document.getElementById('testIframe').contentWindow.setTimeout("window.timeoutFired = true", 50);
|
||||
document.getElementById('testIframe').contentDocument.designMode = 'on';
|
||||
setTimeout(finishTest, 100);
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
addLoadEvent(testContentEditable);
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
28
content/xul/content/crashtests/467869-1.xul
Normal file
28
content/xul/content/crashtests/467869-1.xul
Normal file
@ -0,0 +1,28 @@
|
||||
<?xml version="1.0"?>
|
||||
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
|
||||
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" onload="boom();" class="reftest-wait">
|
||||
|
||||
<script type="text/javascript">
|
||||
// <![CDATA[
|
||||
|
||||
function boom()
|
||||
{
|
||||
var t = document.getBoxObjectFor(document.documentElement).lastChild;
|
||||
document.documentElement.style.counterIncrement = "c";
|
||||
setTimeout(boom2, 0, t);
|
||||
}
|
||||
|
||||
function boom2(t)
|
||||
{
|
||||
try {
|
||||
document.documentElement.appendChild(t);
|
||||
} catch(e) {
|
||||
// appendChild is expected to throw
|
||||
document.documentElement.removeAttribute("class");
|
||||
}
|
||||
}
|
||||
|
||||
// ]]>
|
||||
</script>
|
||||
|
||||
</window>
|
@ -21,3 +21,4 @@ load 429085-1.xhtml
|
||||
load 431906-1.html
|
||||
load 451311-1.xul
|
||||
load 461917-1.xhtml
|
||||
load 467869-1.xul
|
||||
|
@ -43,6 +43,7 @@
|
||||
#include "nsISupports.h"
|
||||
|
||||
class nsIURI;
|
||||
class nsString;
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
@ -51,7 +52,7 @@ namespace mozilla {
|
||||
}
|
||||
|
||||
#define IHISTORY_IID \
|
||||
{0xaf27265d, 0x5672, 0x4d23, {0xa0, 0x75, 0x34, 0x8e, 0xb9, 0x73, 0x5a, 0x9a}}
|
||||
{0x6f736049, 0x6370, 0x4376, {0xb7, 0x17, 0xfa, 0xfc, 0x0b, 0x4f, 0xd0, 0xf1}}
|
||||
|
||||
class IHistory : public nsISupports
|
||||
{
|
||||
@ -96,6 +97,50 @@ public:
|
||||
*/
|
||||
NS_IMETHOD UnregisterVisitedCallback(nsIURI *aURI, dom::Link *aLink) = 0;
|
||||
|
||||
enum VisitFlags {
|
||||
/**
|
||||
* Indicates whether the URI was loaded in a top-level window.
|
||||
*/
|
||||
TOP_LEVEL = 1 << 0,
|
||||
/**
|
||||
* Indicates whether the URI was loaded as part of a permanent redirect.
|
||||
*/
|
||||
REDIRECT_PERMANENT = 1 << 1,
|
||||
/**
|
||||
* Indicates whether the URI was loaded as part of a temporary redirect.
|
||||
*/
|
||||
REDIRECT_TEMPORARY = 1 << 2
|
||||
};
|
||||
|
||||
/**
|
||||
* Adds a history visit for the URI.
|
||||
*
|
||||
* @pre aURI must not be null.
|
||||
*
|
||||
* @param aURI
|
||||
* The URI of the page being visited.
|
||||
* @param aLastVisitedURI
|
||||
* The URI of the last visit in the chain.
|
||||
* @param aFlags
|
||||
* The VisitFlags describing this visit.
|
||||
*/
|
||||
NS_IMETHOD VisitURI(
|
||||
nsIURI *aURI,
|
||||
nsIURI *aLastVisitedURI,
|
||||
PRUint32 aFlags
|
||||
) = 0;
|
||||
|
||||
/**
|
||||
* Set the title of the URI.
|
||||
*
|
||||
* @pre aURI must not be null.
|
||||
*
|
||||
* @param aURI
|
||||
* The URI to set the title for.
|
||||
* @param aTitle
|
||||
* The title string.
|
||||
*/
|
||||
NS_IMETHOD SetURITitle(nsIURI* aURI, const nsAString& aTitle) = 0;
|
||||
};
|
||||
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(IHistory, IHISTORY_IID)
|
||||
@ -104,7 +149,11 @@ NS_DEFINE_STATIC_IID_ACCESSOR(IHistory, IHISTORY_IID)
|
||||
NS_IMETHOD RegisterVisitedCallback(nsIURI *aURI, \
|
||||
mozilla::dom::Link *aContent); \
|
||||
NS_IMETHOD UnregisterVisitedCallback(nsIURI *aURI, \
|
||||
mozilla::dom::Link *aContent);
|
||||
mozilla::dom::Link *aContent); \
|
||||
NS_IMETHOD VisitURI(nsIURI *aURI, \
|
||||
nsIURI *aLastVisitedURI, \
|
||||
PRUint32 aFlags); \
|
||||
NS_IMETHOD SetURITitle(nsIURI* aURI, const nsAString& aTitle);
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
|
@ -112,6 +112,8 @@
|
||||
#include "nsIOfflineCacheUpdate.h"
|
||||
#include "nsCPrefetchService.h"
|
||||
#include "nsJSON.h"
|
||||
#include "IHistory.h"
|
||||
#include "mozilla/Services.h"
|
||||
|
||||
// we want to explore making the document own the load group
|
||||
// so we can associate the document URI with the load group.
|
||||
@ -4702,11 +4704,16 @@ nsDocShell::SetTitle(const PRUnichar * aTitle)
|
||||
treeOwnerAsWin->SetTitle(aTitle);
|
||||
}
|
||||
|
||||
if (mGlobalHistory && mCurrentURI && mLoadType != LOAD_ERROR_PAGE) {
|
||||
mGlobalHistory->SetPageTitle(mCurrentURI, nsString(mTitle));
|
||||
if (mCurrentURI && mLoadType != LOAD_ERROR_PAGE) {
|
||||
nsCOMPtr<IHistory> history = services::GetHistoryService();
|
||||
if (history) {
|
||||
history->SetURITitle(mCurrentURI, mTitle);
|
||||
}
|
||||
else if (mGlobalHistory) {
|
||||
mGlobalHistory->SetPageTitle(mCurrentURI, nsString(mTitle));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Update SessionHistory with the document's title.
|
||||
if (mOSHE && mLoadType != LOAD_BYPASS_HISTORY &&
|
||||
mLoadType != LOAD_ERROR_PAGE) {
|
||||
@ -5672,32 +5679,53 @@ nsDocShell::OnRedirectStateChange(nsIChannel* aOldChannel,
|
||||
if (!(aStateFlags & STATE_IS_DOCUMENT))
|
||||
return; // not a toplevel document
|
||||
|
||||
nsCOMPtr<nsIGlobalHistory3> history3(do_QueryInterface(mGlobalHistory));
|
||||
nsresult result = NS_ERROR_NOT_IMPLEMENTED;
|
||||
if (history3) {
|
||||
// notify global history of this redirect
|
||||
result = history3->AddDocumentRedirect(aOldChannel, aNewChannel,
|
||||
aRedirectFlags, !IsFrame());
|
||||
nsCOMPtr<nsIURI> oldURI, newURI;
|
||||
aOldChannel->GetURI(getter_AddRefs(oldURI));
|
||||
aNewChannel->GetURI(getter_AddRefs(newURI));
|
||||
if (!oldURI || !newURI) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (result == NS_ERROR_NOT_IMPLEMENTED) {
|
||||
// when there is no GlobalHistory3, or it doesn't implement
|
||||
// AddToplevelRedirect, we fall back to GlobalHistory2. Just notify
|
||||
// that the redirecting page was a rePdirect so it will be link colored
|
||||
// but not visible.
|
||||
nsCOMPtr<nsIURI> oldURI;
|
||||
aOldChannel->GetURI(getter_AddRefs(oldURI));
|
||||
if (! oldURI)
|
||||
return; // nothing to tell anybody about
|
||||
AddToGlobalHistory(oldURI, PR_TRUE, aOldChannel);
|
||||
// Below a URI visit is saved (see AddURIVisit method doc).
|
||||
// The visit chain looks something like:
|
||||
// ...
|
||||
// Site N - 1
|
||||
// => Site N
|
||||
// (redirect to =>) Site N + 1 (we are here!)
|
||||
|
||||
// Get N - 1 and transition type
|
||||
nsCOMPtr<nsIURI> previousURI;
|
||||
PRUint32 previousFlags = 0;
|
||||
ExtractLastVisit(aOldChannel, getter_AddRefs(previousURI), &previousFlags);
|
||||
|
||||
if (aRedirectFlags & nsIChannelEventSink::REDIRECT_INTERNAL ||
|
||||
ChannelIsPost(aOldChannel)) {
|
||||
// 1. Internal redirects are ignored because they are specific to the
|
||||
// channel implementation.
|
||||
// 2. POSTs are not saved by global history.
|
||||
//
|
||||
// Regardless, we need to propagate the previous visit to the new
|
||||
// channel.
|
||||
SaveLastVisit(aNewChannel, previousURI, previousFlags);
|
||||
}
|
||||
else {
|
||||
nsCOMPtr<nsIURI> referrer;
|
||||
// Treat referrer as null if there is an error getting it.
|
||||
(void)NS_GetReferrerFromChannel(aOldChannel,
|
||||
getter_AddRefs(referrer));
|
||||
|
||||
// Add visit N -1 => N
|
||||
AddURIVisit(oldURI, referrer, previousURI, previousFlags);
|
||||
|
||||
// Since N + 1 could be the final destination, we will not save N => N + 1
|
||||
// here. OnNewURI will do that, so we will cache it.
|
||||
SaveLastVisit(aNewChannel, oldURI, aRedirectFlags);
|
||||
}
|
||||
|
||||
// check if the new load should go through the application cache.
|
||||
nsCOMPtr<nsIApplicationCacheChannel> appCacheChannel =
|
||||
do_QueryInterface(aNewChannel);
|
||||
if (appCacheChannel) {
|
||||
nsCOMPtr<nsIURI> newURI;
|
||||
aNewChannel->GetURI(getter_AddRefs(newURI));
|
||||
appCacheChannel->SetChooseApplicationCache(ShouldCheckAppCache(newURI));
|
||||
}
|
||||
|
||||
@ -8937,7 +8965,7 @@ nsDocShell::OnNewURI(nsIURI * aURI, nsIChannel * aChannel, nsISupports* aOwner,
|
||||
nsCOMPtr<nsIInputStream> inputStream;
|
||||
if (aChannel) {
|
||||
nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(aChannel));
|
||||
|
||||
|
||||
// Check if the HTTPChannel is hiding under a multiPartChannel
|
||||
if (!httpChannel) {
|
||||
GetHttpChannel(aChannel, getter_AddRefs(httpChannel));
|
||||
@ -9027,8 +9055,8 @@ nsDocShell::OnNewURI(nsIURI * aURI, nsIChannel * aChannel, nsISupports* aOwner,
|
||||
|
||||
nsCOMPtr<nsICachingChannel> cacheChannel(do_QueryInterface(aChannel));
|
||||
nsCOMPtr<nsISupports> cacheKey;
|
||||
// Get the Cache Key and store it in SH.
|
||||
if (cacheChannel)
|
||||
// Get the Cache Key and store it in SH.
|
||||
if (cacheChannel)
|
||||
cacheChannel->GetCacheKey(getter_AddRefs(cacheKey));
|
||||
// If we already have a loading history entry, store the new cache key
|
||||
// in it. Otherwise, since we're doing a reload and won't be updating
|
||||
@ -9050,10 +9078,22 @@ nsDocShell::OnNewURI(nsIURI * aURI, nsIChannel * aChannel, nsISupports* aOwner,
|
||||
getter_AddRefs(mLSHE));
|
||||
}
|
||||
|
||||
// Update Global history
|
||||
if (aAddToGlobalHistory) {
|
||||
// Get the referrer uri from the channel
|
||||
AddToGlobalHistory(aURI, PR_FALSE, aChannel);
|
||||
// If this is a POST request, we do not want to include this in global
|
||||
// history.
|
||||
if (!ChannelIsPost(aChannel)) {
|
||||
nsCOMPtr<nsIURI> previousURI;
|
||||
PRUint32 previousFlags = 0;
|
||||
ExtractLastVisit(aChannel, getter_AddRefs(previousURI),
|
||||
&previousFlags);
|
||||
|
||||
nsCOMPtr<nsIURI> referrer;
|
||||
// Treat referrer as null if there is an error getting it.
|
||||
(void)NS_GetReferrerFromChannel(aChannel,
|
||||
getter_AddRefs(referrer));
|
||||
|
||||
AddURIVisit(aURI, referrer, previousURI, previousFlags);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -9372,7 +9412,7 @@ nsDocShell::AddState(nsIVariant *aData, const nsAString& aTitle,
|
||||
SetCurrentURI(newURI, nsnull, PR_TRUE);
|
||||
document->SetDocumentURI(newURI);
|
||||
|
||||
AddToGlobalHistory(newURI, PR_FALSE, oldURI);
|
||||
AddURIVisit(newURI, oldURI, oldURI, 0);
|
||||
}
|
||||
else {
|
||||
FireOnLocationChange(this, nsnull, mCurrentURI);
|
||||
@ -10068,53 +10108,109 @@ NS_IMETHODIMP nsDocShell::MakeEditable(PRBool inWaitForUriLoad)
|
||||
return mEditorData->MakeEditable(inWaitForUriLoad);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDocShell::AddToGlobalHistory(nsIURI * aURI, PRBool aRedirect,
|
||||
nsIChannel * aChannel)
|
||||
bool
|
||||
nsDocShell::ChannelIsPost(nsIChannel* aChannel)
|
||||
{
|
||||
// If this is a POST request, we do not want to include this in global
|
||||
// history, so return early.
|
||||
nsCOMPtr<nsIHttpChannel> hchan(do_QueryInterface(aChannel));
|
||||
if (hchan) {
|
||||
nsCAutoString type;
|
||||
nsresult rv = hchan->GetRequestMethod(type);
|
||||
if (NS_SUCCEEDED(rv) && type.EqualsLiteral("POST"))
|
||||
return NS_OK;
|
||||
nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(aChannel));
|
||||
if (!httpChannel) {
|
||||
return false;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIURI> referrer;
|
||||
if (aChannel)
|
||||
NS_GetReferrerFromChannel(aChannel, getter_AddRefs(referrer));
|
||||
|
||||
return AddToGlobalHistory(aURI, aRedirect, referrer);
|
||||
nsCAutoString method;
|
||||
httpChannel->GetRequestMethod(method);
|
||||
return method.Equals("POST");
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDocShell::AddToGlobalHistory(nsIURI * aURI, PRBool aRedirect,
|
||||
nsIURI * aReferrer)
|
||||
void
|
||||
nsDocShell::ExtractLastVisit(nsIChannel* aChannel,
|
||||
nsIURI** aURI,
|
||||
PRUint32* aChannelRedirectFlags)
|
||||
{
|
||||
if (mItemType != typeContent || !mGlobalHistory)
|
||||
return NS_OK;
|
||||
|
||||
PRBool visited;
|
||||
nsresult rv = mGlobalHistory->IsVisited(aURI, &visited);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
rv = mGlobalHistory->AddURI(aURI, aRedirect, !IsFrame(), aReferrer);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
if (!visited) {
|
||||
nsCOMPtr<nsIObserverService> obsService =
|
||||
mozilla::services::GetObserverService();
|
||||
if (obsService) {
|
||||
obsService->NotifyObservers(aURI, NS_LINK_VISITED_EVENT_TOPIC, nsnull);
|
||||
}
|
||||
nsCOMPtr<nsIPropertyBag2> props(do_QueryInterface(aChannel));
|
||||
if (!props) {
|
||||
return;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
nsresult rv = props->GetPropertyAsInterface(
|
||||
NS_LITERAL_STRING("docshell.previousURI"),
|
||||
NS_GET_IID(nsIURI),
|
||||
reinterpret_cast<void**>(aURI)
|
||||
);
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
// There is no last visit for this channel, so this must be the first
|
||||
// link. Link the visit to the referrer of this request, if any.
|
||||
// Treat referrer as null if there is an error getting it.
|
||||
(void)NS_GetReferrerFromChannel(aChannel, aURI);
|
||||
}
|
||||
else {
|
||||
rv = props->GetPropertyAsUint32(
|
||||
NS_LITERAL_STRING("docshell.previousFlags"),
|
||||
aChannelRedirectFlags
|
||||
);
|
||||
|
||||
NS_WARN_IF_FALSE(
|
||||
NS_FAILED(rv),
|
||||
"Could not fetch previous flags, URI will be treated like referrer"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsDocShell::SaveLastVisit(nsIChannel* aChannel,
|
||||
nsIURI* aURI,
|
||||
PRUint32 aChannelRedirectFlags)
|
||||
{
|
||||
nsCOMPtr<nsIWritablePropertyBag2> props(do_QueryInterface(aChannel));
|
||||
if (!props || !aURI) {
|
||||
return;
|
||||
}
|
||||
|
||||
props->SetPropertyAsInterface(NS_LITERAL_STRING("docshell.previousURI"),
|
||||
aURI);
|
||||
props->SetPropertyAsUint32(NS_LITERAL_STRING("docshell.previousFlags"),
|
||||
aChannelRedirectFlags);
|
||||
}
|
||||
|
||||
void
|
||||
nsDocShell::AddURIVisit(nsIURI* aURI,
|
||||
nsIURI* aReferrerURI,
|
||||
nsIURI* aPreviousURI,
|
||||
PRUint32 aChannelRedirectFlags)
|
||||
{
|
||||
NS_ASSERTION(aURI, "Visited URI is null!");
|
||||
|
||||
// Only content-type docshells save URI visits.
|
||||
if (mItemType != typeContent) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<IHistory> history = services::GetHistoryService();
|
||||
|
||||
if (history) {
|
||||
PRUint32 visitURIFlags = 0;
|
||||
|
||||
if (!IsFrame()) {
|
||||
visitURIFlags |= IHistory::TOP_LEVEL;
|
||||
}
|
||||
|
||||
if (aChannelRedirectFlags & nsIChannelEventSink::REDIRECT_TEMPORARY) {
|
||||
visitURIFlags |= IHistory::REDIRECT_TEMPORARY;
|
||||
}
|
||||
else if (aChannelRedirectFlags &
|
||||
nsIChannelEventSink::REDIRECT_PERMANENT) {
|
||||
visitURIFlags |= IHistory::REDIRECT_PERMANENT;
|
||||
}
|
||||
|
||||
(void)history->VisitURI(aURI, aPreviousURI, visitURIFlags);
|
||||
}
|
||||
else if (mGlobalHistory) {
|
||||
// Falls back to sync global history interface.
|
||||
(void)mGlobalHistory->AddURI(aURI,
|
||||
!!aChannelRedirectFlags,
|
||||
!IsFrame(),
|
||||
aReferrerURI);
|
||||
}
|
||||
}
|
||||
|
||||
//*****************************************************************************
|
||||
@ -11171,3 +11267,97 @@ nsDocShell::GetPrintPreview(nsIWebBrowserPrint** aPrintPreview)
|
||||
#ifdef DEBUG
|
||||
unsigned long nsDocShell::gNumberOfDocShells = 0;
|
||||
#endif
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDocShell::GetCanExecuteScripts(PRBool *aResult)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aResult);
|
||||
*aResult = PR_FALSE; // disallow by default
|
||||
|
||||
nsCOMPtr<nsIDocShell> docshell = this;
|
||||
nsCOMPtr<nsIDocShellTreeItem> globalObjTreeItem =
|
||||
do_QueryInterface(docshell);
|
||||
|
||||
if (globalObjTreeItem)
|
||||
{
|
||||
nsCOMPtr<nsIDocShellTreeItem> treeItem(globalObjTreeItem);
|
||||
nsCOMPtr<nsIDocShellTreeItem> parentItem;
|
||||
PRBool firstPass = PR_TRUE;
|
||||
PRBool lookForParents = PR_FALSE;
|
||||
|
||||
// Walk up the docshell tree to see if any containing docshell disallows scripts
|
||||
do
|
||||
{
|
||||
nsresult rv = docshell->GetAllowJavascript(aResult);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
if (!*aResult) {
|
||||
nsDocShell* realDocshell = static_cast<nsDocShell*>(docshell.get());
|
||||
if (realDocshell->mContentViewer) {
|
||||
nsIDocument* doc = realDocshell->mContentViewer->GetDocument();
|
||||
if (doc && doc->HasFlag(NODE_IS_EDITABLE) &&
|
||||
realDocshell->mEditorData) {
|
||||
nsCOMPtr<nsIEditingSession> editSession;
|
||||
realDocshell->mEditorData->GetEditingSession(getter_AddRefs(editSession));
|
||||
PRBool jsDisabled = PR_FALSE;
|
||||
if (editSession &&
|
||||
NS_SUCCEEDED(rv = editSession->GetJsAndPluginsDisabled(&jsDisabled))) {
|
||||
if (firstPass) {
|
||||
if (jsDisabled) {
|
||||
// We have a docshell which has been explicitly set
|
||||
// to design mode, so we disallow scripts.
|
||||
return NS_OK;
|
||||
}
|
||||
// The docshell was not explicitly set to design mode,
|
||||
// so it must be so because a parent was explicitly
|
||||
// set to design mode. We don't need to look at higher
|
||||
// docshells.
|
||||
*aResult = PR_TRUE;
|
||||
break;
|
||||
} else if (lookForParents && jsDisabled) {
|
||||
// If a parent was explicitly set to design mode,
|
||||
// we should allow script execution on the child.
|
||||
*aResult = PR_TRUE;
|
||||
break;
|
||||
}
|
||||
// If the child docshell allows scripting, and the
|
||||
// parent is inside design mode, we don't need to look
|
||||
// further.
|
||||
*aResult = PR_TRUE;
|
||||
return NS_OK;
|
||||
}
|
||||
NS_WARNING("The editing session does not work?");
|
||||
return NS_FAILED(rv) ? rv : NS_ERROR_FAILURE;
|
||||
}
|
||||
if (firstPass) {
|
||||
// Don't be too hard on docshells on the first pass.
|
||||
// There may be a parent docshell which has been set
|
||||
// to design mode, so look for it.
|
||||
lookForParents = PR_TRUE;
|
||||
} else {
|
||||
// We have a docshell which disallows scripts
|
||||
// and is not editable, so we shouldn't allow
|
||||
// scripts at all.
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
} else if (lookForParents) {
|
||||
// The parent docshell was not explicitly set to design
|
||||
// mode, so js on the child docshell was disabled for
|
||||
// another reason. Therefore, we need to disable js.
|
||||
return NS_OK;
|
||||
}
|
||||
firstPass = PR_FALSE;
|
||||
|
||||
treeItem->GetParent(getter_AddRefs(parentItem));
|
||||
treeItem.swap(parentItem);
|
||||
docshell = do_QueryInterface(treeItem);
|
||||
#ifdef DEBUG
|
||||
if (treeItem && !docshell) {
|
||||
NS_ERROR("cannot get a docshell from a treeItem!");
|
||||
}
|
||||
#endif // DEBUG
|
||||
} while (treeItem && docshell);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -433,12 +433,77 @@ protected:
|
||||
PRUint32 aRedirectFlags,
|
||||
PRUint32 aStateFlags);
|
||||
|
||||
// Global History
|
||||
/**
|
||||
* Helper function that determines if channel is an HTTP POST.
|
||||
*
|
||||
* @param aChannel
|
||||
* The channel to test
|
||||
*
|
||||
* @return True iff channel is an HTTP post.
|
||||
*/
|
||||
bool ChannelIsPost(nsIChannel* aChannel);
|
||||
|
||||
nsresult AddToGlobalHistory(nsIURI * aURI, PRBool aRedirect,
|
||||
nsIChannel * aChannel);
|
||||
nsresult AddToGlobalHistory(nsIURI * aURI, PRBool aRedirect,
|
||||
nsIURI * aReferrer);
|
||||
/**
|
||||
* Helper function that finds the last URI and its transition flags for a
|
||||
* channel.
|
||||
*
|
||||
* This method first checks the channel's property bag to see if previous
|
||||
* info has been saved. If not, it gives back the referrer of the channel.
|
||||
*
|
||||
* @param aChannel
|
||||
* The channel we are transitioning to
|
||||
* @param aURI
|
||||
* Output parameter with the previous URI, not addref'd
|
||||
* @param aChannelRedirectFlags
|
||||
* If a redirect, output parameter with the previous redirect flags
|
||||
* from nsIChannelEventSink
|
||||
*/
|
||||
void ExtractLastVisit(nsIChannel* aChannel,
|
||||
nsIURI** aURI,
|
||||
PRUint32* aChannelRedirectFlags);
|
||||
|
||||
/**
|
||||
* Helper function that caches a URI and a transition for saving later.
|
||||
*
|
||||
* @param aChannel
|
||||
* Channel that will have these properties saved
|
||||
* @param aURI
|
||||
* The URI to save for later
|
||||
* @param aChannelRedirectFlags
|
||||
* The nsIChannelEventSink redirect flags to save for later
|
||||
*/
|
||||
void SaveLastVisit(nsIChannel* aChannel,
|
||||
nsIURI* aURI,
|
||||
PRUint32 aChannelRedirectFlags);
|
||||
|
||||
/**
|
||||
* Helper function for adding a URI visit using IHistory. If IHistory is
|
||||
* not available, the method tries nsIGlobalHistory2.
|
||||
*
|
||||
* The IHistory API maintains chains of visits, tracking both HTTP referrers
|
||||
* and redirects for a user session. VisitURI requires the current URI and
|
||||
* the previous URI in the chain.
|
||||
*
|
||||
* Visits can be saved either during a redirect or when the request has
|
||||
* reached its final destination. The previous URI in the visit may be
|
||||
* from another redirect or it may be the referrer.
|
||||
*
|
||||
* @pre aURI is not null.
|
||||
*
|
||||
* @param aURI
|
||||
* The URI that was just visited
|
||||
* @param aReferrerURI
|
||||
* The referrer URI of this request
|
||||
* @param aPreviousURI
|
||||
* The previous URI of this visit (may be the same as aReferrerURI)
|
||||
* @param aChannelRedirectFlags
|
||||
* For redirects, the redirect flags from nsIChannelEventSink
|
||||
* (0 otherwise)
|
||||
*/
|
||||
void AddURIVisit(nsIURI* aURI,
|
||||
nsIURI* aReferrerURI,
|
||||
nsIURI* aPreviousURI,
|
||||
PRUint32 aChannelRedirectFlags);
|
||||
|
||||
// Helper Routines
|
||||
nsresult ConfirmRepost(PRBool * aRepost);
|
||||
@ -700,6 +765,9 @@ protected:
|
||||
|
||||
PRInt32 mMarginWidth;
|
||||
PRInt32 mMarginHeight;
|
||||
|
||||
// This can either be a content docshell or a chrome docshell. After
|
||||
// Create() is called, the type is not expected to change.
|
||||
PRInt32 mItemType;
|
||||
|
||||
// Index into the SHTransaction list, indicating the previous and current
|
||||
|
@ -71,7 +71,7 @@ interface nsIPrincipal;
|
||||
interface nsIWebBrowserPrint;
|
||||
interface nsIVariant;
|
||||
|
||||
[scriptable, uuid(3adde256-05a9-43a7-a190-f8fe75eecfd6)]
|
||||
[scriptable, uuid(8ac6b880-776a-44d4-b271-a7e64ae3debd)]
|
||||
interface nsIDocShell : nsISupports
|
||||
{
|
||||
/**
|
||||
@ -511,4 +511,14 @@ interface nsIDocShell : nsISupports
|
||||
* is loaded.
|
||||
*/
|
||||
readonly attribute nsIWebBrowserPrint printPreview;
|
||||
|
||||
/**
|
||||
* Whether this docshell can execute scripts based on its hierarchy.
|
||||
* The rule of thumb here is that we disable js if this docshell or any
|
||||
* of its parents disallow scripting, unless the only reason for js being
|
||||
* disabled in this docshell is a parent docshell having a document that
|
||||
* is in design mode. In that case, we explicitly allow scripting on the
|
||||
* current docshell.
|
||||
*/
|
||||
readonly attribute boolean canExecuteScripts;
|
||||
};
|
||||
|
@ -61,4 +61,5 @@ EmptyGetElementByIdParam=Empty string passed to getElementById().
|
||||
LowMemoryTitle=Warning: Low memory
|
||||
LowMemoryMessage=A script on this page has been stopped due to a low memory condition.
|
||||
WrongEventPropertyAccessWarning=The '%S' property of a %S event should not be used. The value is meaningless.
|
||||
SpeculationFailed=An unbalanced tree was written using document.write() causing data from the network to be reparsed. For more information https://developer.mozilla.org/en/Optimizing_Your_Pages_for_Speculative_Parsing
|
||||
|
||||
|
@ -43,7 +43,7 @@
|
||||
|
||||
interface nsIEditor;
|
||||
|
||||
[scriptable, uuid(274cd32e-3675-47e1-9d8a-fc6504ded9ce)]
|
||||
[scriptable, uuid(24f3f4da-18a4-448d-876d-7360fefac029)]
|
||||
|
||||
interface nsIEditingSession : nsISupports
|
||||
{
|
||||
@ -128,5 +128,10 @@ interface nsIEditingSession : nsISupports
|
||||
* to the window.
|
||||
*/
|
||||
void reattachToWindow(in nsIDOMWindow aWindow);
|
||||
|
||||
/**
|
||||
* Whether this session has disabled JS and plugins.
|
||||
*/
|
||||
readonly attribute boolean jsAndPluginsDisabled;
|
||||
};
|
||||
|
||||
|
@ -261,6 +261,14 @@ nsEditingSession::RestoreJSAndPlugins(nsIDOMWindow *aWindow)
|
||||
return docShell->SetAllowPlugins(mPluginsEnabled);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsEditingSession::GetJsAndPluginsDisabled(PRBool *aResult)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aResult);
|
||||
*aResult = mDisabledJSAndPlugins;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
|
||||
WindowIsEditable
|
||||
|
@ -48,6 +48,7 @@ _TEST_FILES = \
|
||||
test_bug348497.html \
|
||||
test_bug384147.html \
|
||||
test_bug389350.html \
|
||||
test_bug519928.html \
|
||||
$(NULL)
|
||||
|
||||
libs:: $(_TEST_FILES)
|
||||
|
96
editor/composer/test/test_bug519928.html
Normal file
96
editor/composer/test/test_bug519928.html
Normal file
@ -0,0 +1,96 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=519928
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 519928</title>
|
||||
<script type="text/javascript" src="/MochiKit/packed.js"></script>
|
||||
<script type="text/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=519928">Mozilla Bug 519928</a>
|
||||
<p id="display"></p>
|
||||
<div id="content">
|
||||
<iframe id="load-frame"></iframe>
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
var iframe = document.getElementById("load-frame");
|
||||
|
||||
function enableJS() allowJS(true);
|
||||
function disableJS() allowJS(false);
|
||||
function allowJS(allow) {
|
||||
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||||
iframe.contentWindow.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
|
||||
.getInterface(Components.interfaces.nsIWebNavigation)
|
||||
.QueryInterface(Components.interfaces.nsIDocShell)
|
||||
.allowJavascript = allow;
|
||||
}
|
||||
function expectJSAllowed(allowed, testCondition, callback) {
|
||||
window.ICanRunMyJS = false;
|
||||
var self_ = window;
|
||||
testCondition();
|
||||
|
||||
var doc = iframe.contentDocument;
|
||||
doc.body.innerHTML = "<iframe></iframe>";
|
||||
var innerFrame = doc.querySelector("iframe");
|
||||
innerFrame.addEventListener("load", function() {
|
||||
innerFrame.removeEventListener("load", arguments.callee, false);
|
||||
|
||||
var msg = "The inner iframe should" + (allowed ? "" : " not") + " be able to run Javascript";
|
||||
is(self_.ICanRunMyJS, allowed, msg);
|
||||
callback();
|
||||
}, false);
|
||||
var iframeSrc = "data:text/html,<script>parent.parent.ICanRunMyJS = true;</scr" + "ipt>";
|
||||
innerFrame.src = iframeSrc;
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
addLoadEvent(function() {
|
||||
var enterDesignMode = function() document.designMode = "on";
|
||||
var leaveDesignMode = function() document.designMode = "off";
|
||||
expectJSAllowed(false, disableJS, function() {
|
||||
expectJSAllowed(true, enableJS, function() {
|
||||
expectJSAllowed(true, enterDesignMode, function() {
|
||||
expectJSAllowed(true, leaveDesignMode, function() {
|
||||
expectJSAllowed(false, disableJS, function() {
|
||||
expectJSAllowed(false, enterDesignMode, function() {
|
||||
expectJSAllowed(false, leaveDesignMode, function() {
|
||||
expectJSAllowed(true, enableJS, function() {
|
||||
enterDesignMode = function() iframe.contentDocument.designMode = "on";
|
||||
leaveDesignMode = function() iframe.contentDocument.designMode = "off";
|
||||
expectJSAllowed(false, disableJS, function() {
|
||||
expectJSAllowed(true, enableJS, function() {
|
||||
expectJSAllowed(true, enterDesignMode, function() {
|
||||
expectJSAllowed(true, leaveDesignMode, function() {
|
||||
expectJSAllowed(false, disableJS, function() {
|
||||
expectJSAllowed(true, enterDesignMode, function() {
|
||||
expectJSAllowed(false, leaveDesignMode, function() {
|
||||
expectJSAllowed(true, enableJS, function() {
|
||||
SimpleTest.finish();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -249,7 +249,9 @@ nsRangeUpdater::SelAdjCreateNode(nsIDOMNode *aParent, PRInt32 aPosition)
|
||||
if (mLock) return NS_OK; // lock set by Will/DidReplaceParent, etc...
|
||||
NS_ENSURE_TRUE(aParent, NS_ERROR_NULL_POINTER);
|
||||
PRUint32 i, count = mArray.Length();
|
||||
NS_ENSURE_TRUE(count, NS_OK);
|
||||
if (!count) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsRangeStore *item;
|
||||
|
||||
|
@ -60,8 +60,6 @@ abstract public class GeckoApp
|
||||
public static GeckoSurfaceView surfaceView;
|
||||
public static GeckoApp mAppContext;
|
||||
|
||||
public static boolean useSoftwareDrawing;
|
||||
|
||||
void launch()
|
||||
{
|
||||
// unpack files in the components directory
|
||||
@ -121,8 +119,6 @@ abstract public class GeckoApp
|
||||
new ViewGroup.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT,
|
||||
ViewGroup.LayoutParams.FILL_PARENT));
|
||||
|
||||
useSoftwareDrawing = true; //isInEmulator() == 1;
|
||||
|
||||
if (!GeckoAppShell.sGeckoRunning) {
|
||||
// Load our JNI libs; we need to do this before launch() because
|
||||
// setInitialSize will be called even before Gecko is actually up
|
||||
|
@ -100,6 +100,13 @@ class GeckoSurfaceView
|
||||
Log.w("GeckoAppJava", "surfaceChanged while mInDrawing is true!");
|
||||
}
|
||||
|
||||
if (width == 0 || height == 0)
|
||||
mSoftwareBuffer = null;
|
||||
else if (mSoftwareBuffer == null ||
|
||||
mSoftwareBuffer.capacity() < (width * height * 2) ||
|
||||
mWidth != width || mHeight != height)
|
||||
mSoftwareBuffer = ByteBuffer.allocateDirect(width * height * 2);
|
||||
|
||||
mFormat = format;
|
||||
mWidth = width;
|
||||
mHeight = height;
|
||||
@ -122,8 +129,6 @@ class GeckoSurfaceView
|
||||
}
|
||||
|
||||
mSurfaceChanged = true;
|
||||
|
||||
//Log.i("GeckoAppJava", "<< surfaceChanged");
|
||||
} finally {
|
||||
mSurfaceLock.unlock();
|
||||
}
|
||||
@ -137,14 +142,10 @@ class GeckoSurfaceView
|
||||
public void surfaceDestroyed(SurfaceHolder holder) {
|
||||
Log.i("GeckoAppJava", "surface destroyed");
|
||||
mSurfaceValid = false;
|
||||
mSoftwareBuffer = null;
|
||||
}
|
||||
|
||||
public ByteBuffer getSoftwareDrawBuffer() {
|
||||
//#ifdef DEBUG
|
||||
if (!mSurfaceLock.isHeldByCurrentThread())
|
||||
Log.e("GeckoAppJava", "getSoftwareDrawBuffer called outside of mSurfaceLock!");
|
||||
//#endif
|
||||
|
||||
return mSoftwareBuffer;
|
||||
}
|
||||
|
||||
@ -154,42 +155,8 @@ class GeckoSurfaceView
|
||||
|
||||
public static final int DRAW_ERROR = 0;
|
||||
public static final int DRAW_GLES_2 = 1;
|
||||
public static final int DRAW_SOFTWARE = 2;
|
||||
|
||||
int innerBeginDrawing() {
|
||||
/*
|
||||
* Software (non-GL) rendering
|
||||
*/
|
||||
if (GeckoApp.useSoftwareDrawing) {
|
||||
if (mWidth != mBufferWidth ||
|
||||
mHeight != mBufferHeight ||
|
||||
mSurfaceChanged)
|
||||
{
|
||||
if (mWidth*mHeight != mBufferWidth*mBufferHeight)
|
||||
mSoftwareBuffer = ByteBuffer.allocateDirect(mWidth*mHeight*4);
|
||||
|
||||
mSoftwareBitmap = Bitmap.createBitmap(mWidth, mHeight, Bitmap.Config.ARGB_8888);
|
||||
|
||||
mBufferWidth = mWidth;
|
||||
mBufferHeight = mHeight;
|
||||
mSurfaceChanged = false;
|
||||
}
|
||||
|
||||
mSoftwareCanvas = getHolder().lockCanvas(null);
|
||||
if (mSoftwareCanvas == null) {
|
||||
Log.e("GeckoAppJava", "lockCanvas failed! << beginDrawing");
|
||||
return DRAW_ERROR;
|
||||
}
|
||||
|
||||
return DRAW_SOFTWARE;
|
||||
}
|
||||
|
||||
return DRAW_GLES_2;
|
||||
}
|
||||
|
||||
public int beginDrawing() {
|
||||
//Log.i("GeckoAppJava", ">> beginDrawing");
|
||||
|
||||
if (mInDrawing) {
|
||||
Log.e("GeckoAppJava", "Recursive beginDrawing call!");
|
||||
return DRAW_ERROR;
|
||||
@ -214,21 +181,11 @@ class GeckoSurfaceView
|
||||
return DRAW_ERROR;
|
||||
}
|
||||
|
||||
// call the inner function to do the work, so we can sanely unlock on error
|
||||
int result = innerBeginDrawing();
|
||||
|
||||
if (result == DRAW_ERROR) {
|
||||
mSurfaceLock.unlock();
|
||||
return DRAW_ERROR;
|
||||
}
|
||||
|
||||
mInDrawing = true;
|
||||
return result;
|
||||
return DRAW_GLES_2;
|
||||
}
|
||||
|
||||
public void endDrawing() {
|
||||
//Log.w("GeckoAppJava", ">> endDrawing");
|
||||
|
||||
if (!mInDrawing) {
|
||||
Log.e("GeckoAppJava", "endDrawing without beginDrawing!");
|
||||
return;
|
||||
@ -239,30 +196,36 @@ class GeckoSurfaceView
|
||||
Log.e("GeckoAppJava", "endDrawing with false mSurfaceValid");
|
||||
return;
|
||||
}
|
||||
|
||||
if (GeckoApp.useSoftwareDrawing) {
|
||||
if (!mSurfaceChanged) {
|
||||
mSoftwareBitmap.copyPixelsFromBuffer(mSoftwareBuffer);
|
||||
mSoftwareCanvas.drawBitmap(mSoftwareBitmap, 0, 0, null);
|
||||
|
||||
getHolder().unlockCanvasAndPost(mSoftwareCanvas);
|
||||
mSoftwareCanvas = null;
|
||||
}
|
||||
}
|
||||
} catch (java.lang.IllegalArgumentException ex) {
|
||||
mSurfaceChanged = true;
|
||||
} finally {
|
||||
mInDrawing = false;
|
||||
|
||||
//#ifdef DEBUG
|
||||
if (!mSurfaceLock.isHeldByCurrentThread())
|
||||
Log.e("GeckoAppJava", "endDrawing while mSurfaceLock not held by current thread!");
|
||||
//#endif
|
||||
|
||||
mSurfaceLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public void draw2D(ByteBuffer buffer) {
|
||||
Canvas c = getHolder().lockCanvas();
|
||||
if (c == null)
|
||||
return;
|
||||
if (buffer != mSoftwareBuffer) {
|
||||
getHolder().unlockCanvasAndPost(c);
|
||||
return;
|
||||
}
|
||||
if (mSoftwareBitmap == null ||
|
||||
mSoftwareBitmap.getHeight() != mHeight ||
|
||||
mSoftwareBitmap.getWidth() != mWidth) {
|
||||
mSoftwareBitmap = Bitmap.createBitmap(mWidth, mHeight, Bitmap.Config.RGB_565);
|
||||
}
|
||||
mSoftwareBitmap.copyPixelsFromBuffer(mSoftwareBuffer);
|
||||
c.drawBitmap(mSoftwareBitmap, 0, 0, null);
|
||||
getHolder().unlockCanvasAndPost(c);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCheckIsTextEditor () {
|
||||
return false;
|
||||
@ -347,7 +310,6 @@ class GeckoSurfaceView
|
||||
// Software rendering
|
||||
ByteBuffer mSoftwareBuffer;
|
||||
Bitmap mSoftwareBitmap;
|
||||
Canvas mSoftwareCanvas;
|
||||
}
|
||||
|
||||
class GeckoInputConnection
|
||||
|
@ -87,8 +87,11 @@ already_AddRefed<gfxASurface>
|
||||
gfxAndroidPlatform::CreateOffscreenSurface(const gfxIntSize& size,
|
||||
gfxASurface::gfxImageFormat imageFormat)
|
||||
{
|
||||
nsRefPtr<gfxASurface> newSurface =
|
||||
new gfxImageSurface (size, imageFormat);
|
||||
nsRefPtr<gfxASurface> newSurface;
|
||||
if (imageFormat == gfxImageSurface::ImageFormatRGB24)
|
||||
newSurface = new gfxImageSurface (size, gfxASurface::ImageFormatRGB16_565);
|
||||
else
|
||||
newSurface = new gfxImageSurface (size, imageFormat);
|
||||
|
||||
return newSurface.forget();
|
||||
}
|
||||
|
53
layout/generic/crashtests/570160.html
Normal file
53
layout/generic/crashtests/570160.html
Normal file
@ -0,0 +1,53 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html class="reftest-print">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
|
||||
<title>Testcase for bug 570160</title>
|
||||
<!-- distilled from href="http://www.musicalcriticism.com/concerts/usherhall-rsno-clein-0510.shtml" -->
|
||||
|
||||
<style type="text/css">
|
||||
|
||||
.manuscript {
|
||||
position: absolute;
|
||||
left: 770px;
|
||||
top: 134px;
|
||||
width: 233px;
|
||||
height: 133px;
|
||||
}
|
||||
|
||||
#maintext {
|
||||
padding: 0px px 15px 15px;
|
||||
position: absolute;
|
||||
left: 16px;
|
||||
top: 299px;
|
||||
width: 752px;
|
||||
height: 636px;
|
||||
}
|
||||
|
||||
|
||||
#maintext img {
|
||||
padding: 10px 10px 10px 25px;
|
||||
float: right;
|
||||
}
|
||||
|
||||
</style></head>
|
||||
|
||||
<body>
|
||||
|
||||
<div class="manuscript"></div>
|
||||
|
||||
|
||||
<div id="maintext">
|
||||
|
||||
<div style="height:98%"></div>
|
||||
|
||||
<p><img src="yyyyyyy" alt="line" width="750" height="50" /></p>
|
||||
<p><strong><img src="xxxxx" alt="maxwell davies" width="100" height="100" />Related articles:</strong></p>
|
||||
<p>The RSNO and Denève in Mahler 6<br />
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
@ -324,4 +324,5 @@ load 547843-1.xhtml
|
||||
load 551635-1.html
|
||||
load 564368-1.xhtml
|
||||
load 564968.xhtml
|
||||
load 570160.html
|
||||
load 571618-1.svg
|
||||
|
@ -718,90 +718,88 @@ nsInlineFrame::ReflowInlineFrame(nsPresContext* aPresContext,
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
if (NS_INLINE_IS_BREAK(aStatus)) {
|
||||
if (NS_INLINE_IS_BREAK_BEFORE(aStatus)) {
|
||||
if (aFrame != mFrames.FirstChild()) {
|
||||
// Change break-before status into break-after since we have
|
||||
// already placed at least one child frame. This preserves the
|
||||
// break-type so that it can be propagated upward.
|
||||
aStatus = NS_FRAME_NOT_COMPLETE |
|
||||
NS_INLINE_BREAK | NS_INLINE_BREAK_AFTER |
|
||||
(aStatus & NS_INLINE_BREAK_TYPE_MASK);
|
||||
PushFrames(aPresContext, aFrame, irs.mPrevFrame, irs);
|
||||
}
|
||||
else {
|
||||
// Preserve reflow status when breaking-before our first child
|
||||
// and propagate it upward without modification.
|
||||
// Note: if we're lazily setting the frame pointer for our child
|
||||
// frames, then we need to set it now. Don't return and leave the
|
||||
// remaining child frames in our child list with the wrong parent
|
||||
// frame pointer...
|
||||
if (irs.mSetParentPointer) {
|
||||
if (irs.mLineContainer && irs.mLineContainer->GetPrevContinuation()) {
|
||||
ReparentFloatsForInlineChild(irs.mLineContainer, aFrame->GetNextSibling(),
|
||||
PR_TRUE);
|
||||
}
|
||||
for (nsIFrame* f = aFrame->GetNextSibling(); f; f = f->GetNextSibling()) {
|
||||
f->SetParent(this);
|
||||
if (lineLayout->GetInFirstLine()) {
|
||||
aPresContext->FrameManager()->ReparentStyleContext(f);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (NS_INLINE_IS_BREAK_BEFORE(aStatus)) {
|
||||
if (aFrame != mFrames.FirstChild()) {
|
||||
// Change break-before status into break-after since we have
|
||||
// already placed at least one child frame. This preserves the
|
||||
// break-type so that it can be propagated upward.
|
||||
aStatus = NS_FRAME_NOT_COMPLETE |
|
||||
NS_INLINE_BREAK | NS_INLINE_BREAK_AFTER |
|
||||
(aStatus & NS_INLINE_BREAK_TYPE_MASK);
|
||||
PushFrames(aPresContext, aFrame, irs.mPrevFrame, irs);
|
||||
}
|
||||
else {
|
||||
// Break-after
|
||||
if (NS_FRAME_IS_NOT_COMPLETE(aStatus)) {
|
||||
nsIFrame* newFrame;
|
||||
rv = CreateNextInFlow(aPresContext, aFrame, newFrame);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
// Preserve reflow status when breaking-before our first child
|
||||
// and propagate it upward without modification.
|
||||
// Note: if we're lazily setting the frame pointer for our child
|
||||
// frames, then we need to set it now. Don't return and leave the
|
||||
// remaining child frames in our child list with the wrong parent
|
||||
// frame pointer...
|
||||
if (irs.mSetParentPointer) {
|
||||
if (irs.mLineContainer && irs.mLineContainer->GetPrevContinuation()) {
|
||||
ReparentFloatsForInlineChild(irs.mLineContainer, aFrame->GetNextSibling(),
|
||||
PR_TRUE);
|
||||
}
|
||||
}
|
||||
nsIFrame* nextFrame = aFrame->GetNextSibling();
|
||||
if (nextFrame) {
|
||||
NS_FRAME_SET_INCOMPLETE(aStatus);
|
||||
PushFrames(aPresContext, nextFrame, aFrame, irs);
|
||||
}
|
||||
else if (nsnull != GetNextInFlow()) {
|
||||
// We must return an incomplete status if there are more child
|
||||
// frames remaining in a next-in-flow that follows this frame.
|
||||
nsInlineFrame* nextInFlow = (nsInlineFrame*) GetNextInFlow();
|
||||
while (nsnull != nextInFlow) {
|
||||
if (nextInFlow->mFrames.NotEmpty()) {
|
||||
NS_FRAME_SET_INCOMPLETE(aStatus);
|
||||
break;
|
||||
for (nsIFrame* f = aFrame->GetNextSibling(); f; f = f->GetNextSibling()) {
|
||||
f->SetParent(this);
|
||||
if (lineLayout->GetInFirstLine()) {
|
||||
aPresContext->FrameManager()->ReparentStyleContext(f);
|
||||
}
|
||||
nextInFlow = (nsInlineFrame*) nextInFlow->GetNextInFlow();
|
||||
}
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
else if (!NS_FRAME_IS_FULLY_COMPLETE(aStatus)) {
|
||||
|
||||
// Create a next-in-flow if needed.
|
||||
if (!NS_FRAME_IS_FULLY_COMPLETE(aStatus)) {
|
||||
if (nsGkAtoms::placeholderFrame == aFrame->GetType()) {
|
||||
nsBlockReflowState* blockRS = lineLayout->mBlockRS;
|
||||
nsPlaceholderFrame* placeholder = static_cast<nsPlaceholderFrame*>(aFrame);
|
||||
rv = blockRS->mBlock->SplitFloat(*blockRS, placeholder->GetOutOfFlowFrame(),
|
||||
nsPlaceholderFrame* placeholder =
|
||||
static_cast<nsPlaceholderFrame*>(aFrame);
|
||||
rv = blockRS->mBlock->SplitFloat(*blockRS,
|
||||
placeholder->GetOutOfFlowFrame(),
|
||||
aStatus);
|
||||
// Allow the parent to continue reflowing
|
||||
// Allow the parent to continue reflowing.
|
||||
aStatus = NS_FRAME_COMPLETE;
|
||||
return rv;
|
||||
}
|
||||
else {
|
||||
nsIFrame* newFrame;
|
||||
rv = CreateNextInFlow(aPresContext, aFrame, newFrame);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
if (!reflowingFirstLetter) {
|
||||
nsIFrame* nextFrame = aFrame->GetNextSibling();
|
||||
if (nextFrame) {
|
||||
PushFrames(aPresContext, nextFrame, aFrame, irs);
|
||||
}
|
||||
}
|
||||
nsIFrame* newFrame;
|
||||
rv = CreateNextInFlow(aPresContext, aFrame, newFrame);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
|
||||
if (NS_INLINE_IS_BREAK_AFTER(aStatus)) {
|
||||
nsIFrame* nextFrame = aFrame->GetNextSibling();
|
||||
if (nextFrame) {
|
||||
NS_FRAME_SET_INCOMPLETE(aStatus);
|
||||
PushFrames(aPresContext, nextFrame, aFrame, irs);
|
||||
}
|
||||
else {
|
||||
// We must return an incomplete status if there are more child
|
||||
// frames remaining in a next-in-flow that follows this frame.
|
||||
nsInlineFrame* nextInFlow = static_cast<nsInlineFrame*>(GetNextInFlow());
|
||||
while (nextInFlow) {
|
||||
if (nextInFlow->mFrames.NotEmpty()) {
|
||||
NS_FRAME_SET_INCOMPLETE(aStatus);
|
||||
break;
|
||||
}
|
||||
nextInFlow = static_cast<nsInlineFrame*>(nextInFlow->GetNextInFlow());
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (!NS_FRAME_IS_FULLY_COMPLETE(aStatus) && !reflowingFirstLetter) {
|
||||
nsIFrame* nextFrame = aFrame->GetNextSibling();
|
||||
if (nextFrame) {
|
||||
PushFrames(aPresContext, nextFrame, aFrame, irs);
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsIFrame*
|
||||
|
@ -1,6 +1,6 @@
|
||||
== dynamic-1-remove-to-none-grouped.xul dynamic-1-ref.xul
|
||||
== dynamic-1-add-to-one-grouped.xul dynamic-1-ref.xul
|
||||
== dynamic-1-remove-to-one-grouped-1.xul dynamic-1-ref.xul
|
||||
fails == dynamic-1-remove-to-one-grouped-2.xul dynamic-1-ref.xul
|
||||
fails == dynamic-1-remove-to-one-grouped-2.xul dynamic-1-ref.xul # bug 575500
|
||||
== dynamic-1-add-to-two-grouped-1.xul dynamic-1-ref.xul
|
||||
== dynamic-1-add-to-two-grouped-2.xul dynamic-1-ref.xul
|
||||
|
@ -64,23 +64,6 @@ interface nsIPluginStreamListener;
|
||||
[ptr] native PRLibraryPtr(PRLibrary);
|
||||
[ref] native nsIStreamListenerRef(nsIStreamListener *);
|
||||
[ptr] native nsPluginNativeWindowPtr(nsPluginNativeWindow);
|
||||
native FullPagePluginEnabledType(FullPagePluginEnabledType);
|
||||
|
||||
%{C++
|
||||
enum FullPagePluginEnabledType
|
||||
{
|
||||
// No plugin was found for this MIME type.
|
||||
NOT_ENABLED,
|
||||
|
||||
// A plugin is available and should take precedence over builtin
|
||||
// content viewers.
|
||||
OVERRIDE_BUILTIN,
|
||||
|
||||
// A plugin is available, but a builtin content viewers should be used if
|
||||
// present.
|
||||
AVAILABLE
|
||||
};
|
||||
%}
|
||||
|
||||
[scriptable, uuid(D419142E-0571-416B-B797-2A8E6624491D)]
|
||||
interface nsIPluginHost : nsISupports
|
||||
@ -123,8 +106,6 @@ interface nsIPluginHost : nsISupports
|
||||
// NS_ERROR_FAILURE if there is no plugin for this type.
|
||||
[noscript] void isPluginEnabledForType(in string aMimeType);
|
||||
|
||||
[noscript] FullPagePluginEnabledType isFullPagePluginEnabledForType(in string aMimeType);
|
||||
|
||||
// The return code is NS_OK if the plugin is enabled and NS_ERROR_FAILURE if
|
||||
// the plugin is explicitly disabled or there is no plugin.
|
||||
[noscript] void isPluginEnabledForExtension(in string aExtension, in constCharStarRef aMimeType);
|
||||
|
@ -2606,42 +2606,6 @@ nsPluginHost::IsPluginEnabledForType(const char* aMimeType)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsPluginHost::IsFullPagePluginEnabledForType(const char* aMimeType,
|
||||
FullPagePluginEnabledType* aResult)
|
||||
{
|
||||
*aResult = NOT_ENABLED;
|
||||
|
||||
nsCOMPtr<nsIPrefBranch> psvc(do_GetService(NS_PREFSERVICE_CONTRACTID));
|
||||
if (!psvc)
|
||||
return NS_OK;
|
||||
|
||||
// A preference controls whether or not the full page plugin is disabled for
|
||||
// a particular type. The string must be in the form:
|
||||
// type1,type2,type3,type4
|
||||
// Note: need an actual interface to control this and subsequent disabling
|
||||
// (and other plugin host settings) so applications can reliably disable
|
||||
// plugins - without relying on implementation details such as prefs/category
|
||||
// manager entries.
|
||||
nsXPIDLCString overrideTypes;
|
||||
psvc->GetCharPref("plugin.disable_full_page_plugin_for_types", getter_Copies(overrideTypes));
|
||||
overrideTypes.Insert(',', 0);
|
||||
overrideTypes.Append(',');
|
||||
|
||||
nsCAutoString commaSeparated(',');
|
||||
commaSeparated.Append(aMimeType);
|
||||
commaSeparated.Append(',');
|
||||
if (overrideTypes.Find(commaSeparated) != kNotFound)
|
||||
return NS_OK;
|
||||
|
||||
nsPluginTag* plugin = FindPluginForType(aMimeType, PR_TRUE);
|
||||
if (!plugin || !plugin->IsEnabled())
|
||||
return NS_OK;
|
||||
|
||||
*aResult = mOverrideInternalTypes ? OVERRIDE_BUILTIN : AVAILABLE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// check comma delimitered extensions
|
||||
static int CompareExtensions(const char *aExtensionList, const char *aExtension)
|
||||
{
|
||||
@ -3386,6 +3350,9 @@ nsresult nsPluginHost::ScanPluginsDirectory(nsIFile * pluginsDir,
|
||||
pluginTag->SetHost(this);
|
||||
pluginTag->mNext = mPlugins;
|
||||
mPlugins = pluginTag;
|
||||
|
||||
if (pluginTag->IsEnabled())
|
||||
pluginTag->RegisterWithCategoryManager(mOverrideInternalTypes);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -412,16 +412,104 @@ nsPluginTag::SetBlocklisted(PRBool aBlocklisted)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsPluginTag::RegisterWithCategoryManager(PRBool aOverrideInternalTypes,
|
||||
nsPluginTag::nsRegisterType aType)
|
||||
{
|
||||
if (!mMimeTypeArray)
|
||||
return;
|
||||
|
||||
PLUGIN_LOG(PLUGIN_LOG_NORMAL,
|
||||
("nsPluginTag::RegisterWithCategoryManager plugin=%s, removing = %s\n",
|
||||
mFileName.get(), aType == ePluginUnregister ? "yes" : "no"));
|
||||
|
||||
nsCOMPtr<nsICategoryManager> catMan = do_GetService(NS_CATEGORYMANAGER_CONTRACTID);
|
||||
if (!catMan)
|
||||
return;
|
||||
|
||||
const char *contractId = "@mozilla.org/content/plugin/document-loader-factory;1";
|
||||
|
||||
nsCOMPtr<nsIPrefBranch> psvc(do_GetService(NS_PREFSERVICE_CONTRACTID));
|
||||
if (!psvc)
|
||||
return; // NS_ERROR_OUT_OF_MEMORY
|
||||
|
||||
// A preference controls whether or not the full page plugin is disabled for
|
||||
// a particular type. The string must be in the form:
|
||||
// type1,type2,type3,type4
|
||||
// Note: need an actual interface to control this and subsequent disabling
|
||||
// (and other plugin host settings) so applications can reliably disable
|
||||
// plugins - without relying on implementation details such as prefs/category
|
||||
// manager entries.
|
||||
nsXPIDLCString overrideTypes;
|
||||
psvc->GetCharPref("plugin.disable_full_page_plugin_for_types", getter_Copies(overrideTypes));
|
||||
nsCAutoString overrideTypesFormatted;
|
||||
overrideTypesFormatted.Assign(',');
|
||||
overrideTypesFormatted += overrideTypes;
|
||||
overrideTypesFormatted.Append(',');
|
||||
|
||||
nsACString::const_iterator start, end;
|
||||
for (int i = 0; i < mVariants; i++) {
|
||||
if (aType == ePluginUnregister) {
|
||||
nsXPIDLCString value;
|
||||
if (NS_SUCCEEDED(catMan->GetCategoryEntry("Gecko-Content-Viewers",
|
||||
mMimeTypeArray[i],
|
||||
getter_Copies(value)))) {
|
||||
// Only delete the entry if a plugin registered for it
|
||||
if (strcmp(value, contractId) == 0) {
|
||||
catMan->DeleteCategoryEntry("Gecko-Content-Viewers",
|
||||
mMimeTypeArray[i],
|
||||
PR_TRUE);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
overrideTypesFormatted.BeginReading(start);
|
||||
overrideTypesFormatted.EndReading(end);
|
||||
|
||||
nsDependentCString mimeType(mMimeTypeArray[i]);
|
||||
nsCAutoString commaSeparated;
|
||||
commaSeparated.Assign(',');
|
||||
commaSeparated += mimeType;
|
||||
commaSeparated.Append(',');
|
||||
if (!FindInReadable(commaSeparated, start, end)) {
|
||||
catMan->AddCategoryEntry("Gecko-Content-Viewers",
|
||||
mMimeTypeArray[i],
|
||||
contractId,
|
||||
PR_FALSE, /* persist: broken by bug 193031 */
|
||||
aOverrideInternalTypes, /* replace if we're told to */
|
||||
nsnull);
|
||||
}
|
||||
}
|
||||
|
||||
PLUGIN_LOG(PLUGIN_LOG_NOISY,
|
||||
("nsPluginTag::RegisterWithCategoryManager mime=%s, plugin=%s\n",
|
||||
mMimeTypeArray[i], mFileName.get()));
|
||||
}
|
||||
}
|
||||
|
||||
void nsPluginTag::Mark(PRUint32 mask)
|
||||
{
|
||||
PRBool wasEnabled = IsEnabled();
|
||||
mFlags |= mask;
|
||||
// Update entries in the category manager if necessary.
|
||||
if (mPluginHost && wasEnabled != IsEnabled()) {
|
||||
if (wasEnabled)
|
||||
RegisterWithCategoryManager(PR_FALSE, nsPluginTag::ePluginUnregister);
|
||||
else
|
||||
RegisterWithCategoryManager(PR_FALSE, nsPluginTag::ePluginRegister);
|
||||
}
|
||||
}
|
||||
|
||||
void nsPluginTag::UnMark(PRUint32 mask)
|
||||
{
|
||||
PRBool wasEnabled = IsEnabled();
|
||||
mFlags &= ~mask;
|
||||
// Update entries in the category manager if necessary.
|
||||
if (mPluginHost && wasEnabled != IsEnabled()) {
|
||||
if (wasEnabled)
|
||||
RegisterWithCategoryManager(PR_FALSE, nsPluginTag::ePluginUnregister);
|
||||
else
|
||||
RegisterWithCategoryManager(PR_FALSE, nsPluginTag::ePluginRegister);
|
||||
}
|
||||
}
|
||||
|
||||
PRBool nsPluginTag::HasFlag(PRUint32 flag)
|
||||
@ -475,6 +563,12 @@ void nsPluginTag::TryUnloadPlugin()
|
||||
// again so the calling code should not be fooled and reload
|
||||
// the library fresh
|
||||
mLibrary = nsnull;
|
||||
|
||||
// Remove mime types added to the category manager
|
||||
// only if we were made 'active' by setting the host
|
||||
if (mPluginHost) {
|
||||
RegisterWithCategoryManager(PR_FALSE, nsPluginTag::ePluginUnregister);
|
||||
}
|
||||
}
|
||||
|
||||
/* nsPluginInstanceTag */
|
||||
|
@ -66,6 +66,11 @@ struct nsPluginInfo;
|
||||
class nsPluginTag : public nsIPluginTag
|
||||
{
|
||||
public:
|
||||
enum nsRegisterType {
|
||||
ePluginRegister,
|
||||
ePluginUnregister
|
||||
};
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIPLUGINTAG
|
||||
|
||||
@ -93,6 +98,8 @@ public:
|
||||
PRUint32 Flags();
|
||||
PRBool Equals(nsPluginTag* aPluginTag);
|
||||
PRBool IsEnabled();
|
||||
void RegisterWithCategoryManager(PRBool aOverrideInternalTypes,
|
||||
nsRegisterType aType = ePluginRegister);
|
||||
|
||||
nsRefPtr<nsPluginTag> mNext;
|
||||
nsPluginHost *mPluginHost;
|
||||
|
@ -211,8 +211,8 @@ public final class ElementName
|
||||
// return "ISINDEX";
|
||||
// case TreeBuilder.LI:
|
||||
// return "LI";
|
||||
// case TreeBuilder.LINK:
|
||||
// return "LINK";
|
||||
// case TreeBuilder.LINK_OR_BASEFONT_OR_BGSOUND:
|
||||
// return "LINK_OR_BASEFONT_OR_BGSOUND";
|
||||
// case TreeBuilder.MATH:
|
||||
// return "MATH";
|
||||
// case TreeBuilder.META:
|
||||
@ -283,8 +283,8 @@ public final class ElementName
|
||||
// return "NOEMBED";
|
||||
// case TreeBuilder.EMBED_OR_IMG:
|
||||
// return "EMBED_OR_IMG";
|
||||
// case TreeBuilder.AREA_OR_BASEFONT_OR_BGSOUND_OR_SPACER_OR_WBR:
|
||||
// return "AREA_OR_BASEFONT_OR_BGSOUND_OR_SPACER_OR_WBR";
|
||||
// case TreeBuilder.AREA_OR_SPACER_OR_WBR:
|
||||
// return "AREA_OR_SPACER_OR_WBR";
|
||||
// case TreeBuilder.DIV_OR_BLOCKQUOTE_OR_CENTER_OR_MENU:
|
||||
// return "DIV_OR_BLOCKQUOTE_OR_CENTER_OR_MENU";
|
||||
// case TreeBuilder.FIELDSET:
|
||||
@ -433,10 +433,10 @@ public final class ElementName
|
||||
public static final ElementName TAN = new ElementName("tan", "tan", TreeBuilder.OTHER, false, false, false);
|
||||
public static final ElementName USE = new ElementName("use", "use", TreeBuilder.OTHER, false, false, false);
|
||||
public static final ElementName VAR = new ElementName("var", "var", TreeBuilder.RUBY_OR_SPAN_OR_SUB_OR_SUP_OR_VAR, false, false, false);
|
||||
public static final ElementName WBR = new ElementName("wbr", "wbr", TreeBuilder.AREA_OR_BASEFONT_OR_BGSOUND_OR_SPACER_OR_WBR, true, false, false);
|
||||
public static final ElementName WBR = new ElementName("wbr", "wbr", TreeBuilder.AREA_OR_SPACER_OR_WBR, true, false, false);
|
||||
public static final ElementName XMP = new ElementName("xmp", "xmp", TreeBuilder.XMP, false, false, false);
|
||||
public static final ElementName XOR = new ElementName("xor", "xor", TreeBuilder.OTHER, false, false, false);
|
||||
public static final ElementName AREA = new ElementName("area", "area", TreeBuilder.AREA_OR_BASEFONT_OR_BGSOUND_OR_SPACER_OR_WBR, true, false, false);
|
||||
public static final ElementName AREA = new ElementName("area", "area", TreeBuilder.AREA_OR_SPACER_OR_WBR, true, false, false);
|
||||
public static final ElementName ABBR = new ElementName("abbr", "abbr", TreeBuilder.OTHER, false, false, false);
|
||||
public static final ElementName BASE = new ElementName("base", "base", TreeBuilder.BASE, true, false, false);
|
||||
public static final ElementName BVAR = new ElementName("bvar", "bvar", TreeBuilder.OTHER, false, false, false);
|
||||
@ -457,7 +457,7 @@ public final class ElementName
|
||||
public static final ElementName HEAD = new ElementName("head", "head", TreeBuilder.HEAD, true, false, false);
|
||||
public static final ElementName HTML = new ElementName("html", "html", TreeBuilder.HTML, false, true, false);
|
||||
public static final ElementName LINE = new ElementName("line", "line", TreeBuilder.OTHER, false, false, false);
|
||||
public static final ElementName LINK = new ElementName("link", "link", TreeBuilder.LINK, true, false, false);
|
||||
public static final ElementName LINK = new ElementName("link", "link", TreeBuilder.LINK_OR_BASEFONT_OR_BGSOUND, true, false, false);
|
||||
public static final ElementName LIST = new ElementName("list", "list", TreeBuilder.OTHER, false, false, false);
|
||||
public static final ElementName META = new ElementName("meta", "meta", TreeBuilder.META, true, false, false);
|
||||
public static final ElementName MSUB = new ElementName("msub", "msub", TreeBuilder.OTHER, false, false, false);
|
||||
@ -578,7 +578,7 @@ public final class ElementName
|
||||
public static final ElementName STRONG = new ElementName("strong", "strong", TreeBuilder.B_OR_BIG_OR_CODE_OR_EM_OR_I_OR_S_OR_SMALL_OR_STRIKE_OR_STRONG_OR_TT_OR_U, false, false, false);
|
||||
public static final ElementName SWITCH = new ElementName("switch", "switch", TreeBuilder.OTHER, false, false, false);
|
||||
public static final ElementName SYMBOL = new ElementName("symbol", "symbol", TreeBuilder.OTHER, false, false, false);
|
||||
public static final ElementName SPACER = new ElementName("spacer", "spacer", TreeBuilder.AREA_OR_BASEFONT_OR_BGSOUND_OR_SPACER_OR_WBR, true, false, false);
|
||||
public static final ElementName SPACER = new ElementName("spacer", "spacer", TreeBuilder.AREA_OR_SPACER_OR_WBR, true, false, false);
|
||||
public static final ElementName SELECT = new ElementName("select", "select", TreeBuilder.SELECT, true, false, false);
|
||||
public static final ElementName SUBSET = new ElementName("subset", "subset", TreeBuilder.OTHER, false, false, false);
|
||||
public static final ElementName SCRIPT = new ElementName("script", "script", TreeBuilder.SCRIPT, true, false, false);
|
||||
@ -594,7 +594,7 @@ public final class ElementName
|
||||
public static final ElementName ARCCOTH = new ElementName("arccoth", "arccoth", TreeBuilder.OTHER, false, false, false);
|
||||
public static final ElementName ACRONYM = new ElementName("acronym", "acronym", TreeBuilder.OTHER, false, false, false);
|
||||
public static final ElementName ADDRESS = new ElementName("address", "address", TreeBuilder.ADDRESS_OR_DIR_OR_ARTICLE_OR_ASIDE_OR_DATAGRID_OR_DETAILS_OR_HGROUP_OR_FIGURE_OR_FOOTER_OR_HEADER_OR_NAV_OR_SECTION, true, false, false);
|
||||
public static final ElementName BGSOUND = new ElementName("bgsound", "bgsound", TreeBuilder.AREA_OR_BASEFONT_OR_BGSOUND_OR_SPACER_OR_WBR, true, false, false);
|
||||
public static final ElementName BGSOUND = new ElementName("bgsound", "bgsound", TreeBuilder.LINK_OR_BASEFONT_OR_BGSOUND, true, false, false);
|
||||
public static final ElementName COMMAND = new ElementName("command", "command", TreeBuilder.COMMAND, true, false, false);
|
||||
public static final ElementName COMPOSE = new ElementName("compose", "compose", TreeBuilder.OTHER, false, false, false);
|
||||
public static final ElementName CEILING = new ElementName("ceiling", "ceiling", TreeBuilder.OTHER, false, false, false);
|
||||
@ -632,7 +632,7 @@ public final class ElementName
|
||||
public static final ElementName TENDSTO = new ElementName("tendsto", "tendsto", TreeBuilder.OTHER, false, false, false);
|
||||
public static final ElementName UPLIMIT = new ElementName("uplimit", "uplimit", TreeBuilder.OTHER, false, false, false);
|
||||
public static final ElementName ALTGLYPH = new ElementName("altglyph", "altGlyph", TreeBuilder.OTHER, false, false, false);
|
||||
public static final ElementName BASEFONT = new ElementName("basefont", "basefont", TreeBuilder.AREA_OR_BASEFONT_OR_BGSOUND_OR_SPACER_OR_WBR, true, false, false);
|
||||
public static final ElementName BASEFONT = new ElementName("basefont", "basefont", TreeBuilder.LINK_OR_BASEFONT_OR_BGSOUND, true, false, false);
|
||||
public static final ElementName CLIPPATH = new ElementName("clippath", "clipPath", TreeBuilder.OTHER, false, false, false);
|
||||
public static final ElementName CODOMAIN = new ElementName("codomain", "codomain", TreeBuilder.OTHER, false, false, false);
|
||||
public static final ElementName COLGROUP = new ElementName("colgroup", "colgroup", TreeBuilder.COLGROUP, true, false, false);
|
||||
|
@ -5860,7 +5860,7 @@ public class Tokenizer implements Locator {
|
||||
private void emitReplacementCharacter(@NoLength char[] buf, int pos)
|
||||
throws SAXException {
|
||||
flushChars(buf, pos);
|
||||
tokenHandler.characters(Tokenizer.REPLACEMENT_CHARACTER, 0, 1);
|
||||
tokenHandler.zeroOriginatingReplacementCharacter();
|
||||
cstart = pos + 1;
|
||||
}
|
||||
|
||||
|
@ -60,6 +60,11 @@ import org.xml.sax.SAXParseException;
|
||||
public abstract class TreeBuilder<T> implements TokenHandler,
|
||||
TreeBuilderState<T> {
|
||||
|
||||
/**
|
||||
* Array version of U+FFFD.
|
||||
*/
|
||||
private static final @NoLength char[] REPLACEMENT_CHARACTER = { '\uFFFD' };
|
||||
|
||||
// Start dispatch groups
|
||||
|
||||
final static int OTHER = 0;
|
||||
@ -94,7 +99,7 @@ public abstract class TreeBuilder<T> implements TokenHandler,
|
||||
|
||||
final static int LI = 15;
|
||||
|
||||
final static int LINK = 16;
|
||||
final static int LINK_OR_BASEFONT_OR_BGSOUND = 16;
|
||||
|
||||
final static int MATH = 17;
|
||||
|
||||
@ -158,7 +163,7 @@ public abstract class TreeBuilder<T> implements TokenHandler,
|
||||
|
||||
final static int EMBED_OR_IMG = 48;
|
||||
|
||||
final static int AREA_OR_BASEFONT_OR_BGSOUND_OR_SPACER_OR_WBR = 49;
|
||||
final static int AREA_OR_SPACER_OR_WBR = 49;
|
||||
|
||||
final static int DIV_OR_BLOCKQUOTE_OR_CENTER_OR_MENU = 50;
|
||||
|
||||
@ -839,8 +844,11 @@ public abstract class TreeBuilder<T> implements TokenHandler,
|
||||
needToDropLF = false;
|
||||
}
|
||||
|
||||
if (inForeign) {
|
||||
accumulateCharacters(buf, start, length);
|
||||
return;
|
||||
}
|
||||
// optimize the most common case
|
||||
// XXX should there be an IN FOREIGN check here?
|
||||
switch (mode) {
|
||||
case IN_BODY:
|
||||
case IN_CELL:
|
||||
@ -1206,6 +1214,16 @@ public abstract class TreeBuilder<T> implements TokenHandler,
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see nu.validator.htmlparser.common.TokenHandler#zeroOriginatingReplacementCharacter()
|
||||
*/
|
||||
@Override public void zeroOriginatingReplacementCharacter()
|
||||
throws SAXException {
|
||||
if (inForeign || mode == TEXT) {
|
||||
characters(REPLACEMENT_CHARACTER, 0, 1);
|
||||
}
|
||||
}
|
||||
|
||||
public final void eof() throws SAXException {
|
||||
flushCharacters();
|
||||
if (inForeign) {
|
||||
@ -1768,7 +1786,7 @@ public abstract class TreeBuilder<T> implements TokenHandler,
|
||||
case MARQUEE_OR_APPLET:
|
||||
case OBJECT:
|
||||
case TABLE:
|
||||
case AREA_OR_BASEFONT_OR_BGSOUND_OR_SPACER_OR_WBR:
|
||||
case AREA_OR_SPACER_OR_WBR:
|
||||
case BR:
|
||||
case EMBED_OR_IMG:
|
||||
case INPUT:
|
||||
@ -1797,7 +1815,7 @@ public abstract class TreeBuilder<T> implements TokenHandler,
|
||||
}
|
||||
break starttagloop;
|
||||
case BASE:
|
||||
case LINK:
|
||||
case LINK_OR_BASEFONT_OR_BGSOUND:
|
||||
case META:
|
||||
case STYLE:
|
||||
case SCRIPT:
|
||||
@ -1989,7 +2007,7 @@ public abstract class TreeBuilder<T> implements TokenHandler,
|
||||
break starttagloop;
|
||||
case BR:
|
||||
case EMBED_OR_IMG:
|
||||
case AREA_OR_BASEFONT_OR_BGSOUND_OR_SPACER_OR_WBR:
|
||||
case AREA_OR_SPACER_OR_WBR:
|
||||
reconstructTheActiveFormattingElements();
|
||||
// FALL THROUGH to PARAM_OR_SOURCE
|
||||
case PARAM_OR_SOURCE:
|
||||
@ -2313,7 +2331,7 @@ public abstract class TreeBuilder<T> implements TokenHandler,
|
||||
attributes = null; // CPP
|
||||
break starttagloop;
|
||||
case META:
|
||||
case LINK:
|
||||
case LINK_OR_BASEFONT_OR_BGSOUND:
|
||||
// Fall through to IN_HEAD_NOSCRIPT
|
||||
break inheadloop;
|
||||
case TITLE:
|
||||
@ -2390,7 +2408,7 @@ public abstract class TreeBuilder<T> implements TokenHandler,
|
||||
attributes = null; // CPP
|
||||
}
|
||||
break starttagloop;
|
||||
case LINK:
|
||||
case LINK_OR_BASEFONT_OR_BGSOUND:
|
||||
appendVoidElementToCurrentMayFoster(
|
||||
"http://www.w3.org/1999/xhtml",
|
||||
elementName, attributes);
|
||||
@ -2766,7 +2784,7 @@ public abstract class TreeBuilder<T> implements TokenHandler,
|
||||
pop(); // head
|
||||
attributes = null; // CPP
|
||||
break starttagloop;
|
||||
case LINK:
|
||||
case LINK_OR_BASEFONT_OR_BGSOUND:
|
||||
err("\u201Clink\u201D element outside \u201Chead\u201D.");
|
||||
pushHeadPointerOntoStack();
|
||||
appendVoidElementToCurrentMayFoster(
|
||||
@ -3576,7 +3594,7 @@ public abstract class TreeBuilder<T> implements TokenHandler,
|
||||
elementName,
|
||||
HtmlAttributes.EMPTY_ATTRIBUTES);
|
||||
break endtagloop;
|
||||
case AREA_OR_BASEFONT_OR_BGSOUND_OR_SPACER_OR_WBR:
|
||||
case AREA_OR_SPACER_OR_WBR:
|
||||
case PARAM_OR_SOURCE:
|
||||
case EMBED_OR_IMG:
|
||||
case IMAGE:
|
||||
|
@ -224,10 +224,10 @@ nsHtml5ElementName::initializeStatics()
|
||||
ELT_TAN = new nsHtml5ElementName(nsHtml5Atoms::tan, nsHtml5Atoms::tan, NS_HTML5TREE_BUILDER_OTHER, PR_FALSE, PR_FALSE, PR_FALSE);
|
||||
ELT_USE = new nsHtml5ElementName(nsHtml5Atoms::use, nsHtml5Atoms::use, NS_HTML5TREE_BUILDER_OTHER, PR_FALSE, PR_FALSE, PR_FALSE);
|
||||
ELT_VAR = new nsHtml5ElementName(nsHtml5Atoms::var, nsHtml5Atoms::var, NS_HTML5TREE_BUILDER_RUBY_OR_SPAN_OR_SUB_OR_SUP_OR_VAR, PR_FALSE, PR_FALSE, PR_FALSE);
|
||||
ELT_WBR = new nsHtml5ElementName(nsHtml5Atoms::wbr, nsHtml5Atoms::wbr, NS_HTML5TREE_BUILDER_AREA_OR_BASEFONT_OR_BGSOUND_OR_SPACER_OR_WBR, PR_TRUE, PR_FALSE, PR_FALSE);
|
||||
ELT_WBR = new nsHtml5ElementName(nsHtml5Atoms::wbr, nsHtml5Atoms::wbr, NS_HTML5TREE_BUILDER_AREA_OR_SPACER_OR_WBR, PR_TRUE, PR_FALSE, PR_FALSE);
|
||||
ELT_XMP = new nsHtml5ElementName(nsHtml5Atoms::xmp, nsHtml5Atoms::xmp, NS_HTML5TREE_BUILDER_XMP, PR_FALSE, PR_FALSE, PR_FALSE);
|
||||
ELT_XOR = new nsHtml5ElementName(nsHtml5Atoms::xor_, nsHtml5Atoms::xor_, NS_HTML5TREE_BUILDER_OTHER, PR_FALSE, PR_FALSE, PR_FALSE);
|
||||
ELT_AREA = new nsHtml5ElementName(nsHtml5Atoms::area, nsHtml5Atoms::area, NS_HTML5TREE_BUILDER_AREA_OR_BASEFONT_OR_BGSOUND_OR_SPACER_OR_WBR, PR_TRUE, PR_FALSE, PR_FALSE);
|
||||
ELT_AREA = new nsHtml5ElementName(nsHtml5Atoms::area, nsHtml5Atoms::area, NS_HTML5TREE_BUILDER_AREA_OR_SPACER_OR_WBR, PR_TRUE, PR_FALSE, PR_FALSE);
|
||||
ELT_ABBR = new nsHtml5ElementName(nsHtml5Atoms::abbr, nsHtml5Atoms::abbr, NS_HTML5TREE_BUILDER_OTHER, PR_FALSE, PR_FALSE, PR_FALSE);
|
||||
ELT_BASE = new nsHtml5ElementName(nsHtml5Atoms::base, nsHtml5Atoms::base, NS_HTML5TREE_BUILDER_BASE, PR_TRUE, PR_FALSE, PR_FALSE);
|
||||
ELT_BVAR = new nsHtml5ElementName(nsHtml5Atoms::bvar, nsHtml5Atoms::bvar, NS_HTML5TREE_BUILDER_OTHER, PR_FALSE, PR_FALSE, PR_FALSE);
|
||||
@ -248,7 +248,7 @@ nsHtml5ElementName::initializeStatics()
|
||||
ELT_HEAD = new nsHtml5ElementName(nsHtml5Atoms::head, nsHtml5Atoms::head, NS_HTML5TREE_BUILDER_HEAD, PR_TRUE, PR_FALSE, PR_FALSE);
|
||||
ELT_HTML = new nsHtml5ElementName(nsHtml5Atoms::html, nsHtml5Atoms::html, NS_HTML5TREE_BUILDER_HTML, PR_FALSE, PR_TRUE, PR_FALSE);
|
||||
ELT_LINE = new nsHtml5ElementName(nsHtml5Atoms::line, nsHtml5Atoms::line, NS_HTML5TREE_BUILDER_OTHER, PR_FALSE, PR_FALSE, PR_FALSE);
|
||||
ELT_LINK = new nsHtml5ElementName(nsHtml5Atoms::link, nsHtml5Atoms::link, NS_HTML5TREE_BUILDER_LINK, PR_TRUE, PR_FALSE, PR_FALSE);
|
||||
ELT_LINK = new nsHtml5ElementName(nsHtml5Atoms::link, nsHtml5Atoms::link, NS_HTML5TREE_BUILDER_LINK_OR_BASEFONT_OR_BGSOUND, PR_TRUE, PR_FALSE, PR_FALSE);
|
||||
ELT_LIST = new nsHtml5ElementName(nsHtml5Atoms::list, nsHtml5Atoms::list, NS_HTML5TREE_BUILDER_OTHER, PR_FALSE, PR_FALSE, PR_FALSE);
|
||||
ELT_META = new nsHtml5ElementName(nsHtml5Atoms::meta, nsHtml5Atoms::meta, NS_HTML5TREE_BUILDER_META, PR_TRUE, PR_FALSE, PR_FALSE);
|
||||
ELT_MSUB = new nsHtml5ElementName(nsHtml5Atoms::msub, nsHtml5Atoms::msub, NS_HTML5TREE_BUILDER_OTHER, PR_FALSE, PR_FALSE, PR_FALSE);
|
||||
@ -369,7 +369,7 @@ nsHtml5ElementName::initializeStatics()
|
||||
ELT_STRONG = new nsHtml5ElementName(nsHtml5Atoms::strong, nsHtml5Atoms::strong, NS_HTML5TREE_BUILDER_B_OR_BIG_OR_CODE_OR_EM_OR_I_OR_S_OR_SMALL_OR_STRIKE_OR_STRONG_OR_TT_OR_U, PR_FALSE, PR_FALSE, PR_FALSE);
|
||||
ELT_SWITCH = new nsHtml5ElementName(nsHtml5Atoms::switch_, nsHtml5Atoms::switch_, NS_HTML5TREE_BUILDER_OTHER, PR_FALSE, PR_FALSE, PR_FALSE);
|
||||
ELT_SYMBOL = new nsHtml5ElementName(nsHtml5Atoms::symbol, nsHtml5Atoms::symbol, NS_HTML5TREE_BUILDER_OTHER, PR_FALSE, PR_FALSE, PR_FALSE);
|
||||
ELT_SPACER = new nsHtml5ElementName(nsHtml5Atoms::spacer, nsHtml5Atoms::spacer, NS_HTML5TREE_BUILDER_AREA_OR_BASEFONT_OR_BGSOUND_OR_SPACER_OR_WBR, PR_TRUE, PR_FALSE, PR_FALSE);
|
||||
ELT_SPACER = new nsHtml5ElementName(nsHtml5Atoms::spacer, nsHtml5Atoms::spacer, NS_HTML5TREE_BUILDER_AREA_OR_SPACER_OR_WBR, PR_TRUE, PR_FALSE, PR_FALSE);
|
||||
ELT_SELECT = new nsHtml5ElementName(nsHtml5Atoms::select, nsHtml5Atoms::select, NS_HTML5TREE_BUILDER_SELECT, PR_TRUE, PR_FALSE, PR_FALSE);
|
||||
ELT_SUBSET = new nsHtml5ElementName(nsHtml5Atoms::subset, nsHtml5Atoms::subset, NS_HTML5TREE_BUILDER_OTHER, PR_FALSE, PR_FALSE, PR_FALSE);
|
||||
ELT_SCRIPT = new nsHtml5ElementName(nsHtml5Atoms::script, nsHtml5Atoms::script, NS_HTML5TREE_BUILDER_SCRIPT, PR_TRUE, PR_FALSE, PR_FALSE);
|
||||
@ -385,7 +385,7 @@ nsHtml5ElementName::initializeStatics()
|
||||
ELT_ARCCOTH = new nsHtml5ElementName(nsHtml5Atoms::arccoth, nsHtml5Atoms::arccoth, NS_HTML5TREE_BUILDER_OTHER, PR_FALSE, PR_FALSE, PR_FALSE);
|
||||
ELT_ACRONYM = new nsHtml5ElementName(nsHtml5Atoms::acronym, nsHtml5Atoms::acronym, NS_HTML5TREE_BUILDER_OTHER, PR_FALSE, PR_FALSE, PR_FALSE);
|
||||
ELT_ADDRESS = new nsHtml5ElementName(nsHtml5Atoms::address, nsHtml5Atoms::address, NS_HTML5TREE_BUILDER_ADDRESS_OR_DIR_OR_ARTICLE_OR_ASIDE_OR_DATAGRID_OR_DETAILS_OR_HGROUP_OR_FIGURE_OR_FOOTER_OR_HEADER_OR_NAV_OR_SECTION, PR_TRUE, PR_FALSE, PR_FALSE);
|
||||
ELT_BGSOUND = new nsHtml5ElementName(nsHtml5Atoms::bgsound, nsHtml5Atoms::bgsound, NS_HTML5TREE_BUILDER_AREA_OR_BASEFONT_OR_BGSOUND_OR_SPACER_OR_WBR, PR_TRUE, PR_FALSE, PR_FALSE);
|
||||
ELT_BGSOUND = new nsHtml5ElementName(nsHtml5Atoms::bgsound, nsHtml5Atoms::bgsound, NS_HTML5TREE_BUILDER_LINK_OR_BASEFONT_OR_BGSOUND, PR_TRUE, PR_FALSE, PR_FALSE);
|
||||
ELT_COMMAND = new nsHtml5ElementName(nsHtml5Atoms::command, nsHtml5Atoms::command, NS_HTML5TREE_BUILDER_COMMAND, PR_TRUE, PR_FALSE, PR_FALSE);
|
||||
ELT_COMPOSE = new nsHtml5ElementName(nsHtml5Atoms::compose, nsHtml5Atoms::compose, NS_HTML5TREE_BUILDER_OTHER, PR_FALSE, PR_FALSE, PR_FALSE);
|
||||
ELT_CEILING = new nsHtml5ElementName(nsHtml5Atoms::ceiling, nsHtml5Atoms::ceiling, NS_HTML5TREE_BUILDER_OTHER, PR_FALSE, PR_FALSE, PR_FALSE);
|
||||
@ -423,7 +423,7 @@ nsHtml5ElementName::initializeStatics()
|
||||
ELT_TENDSTO = new nsHtml5ElementName(nsHtml5Atoms::tendsto, nsHtml5Atoms::tendsto, NS_HTML5TREE_BUILDER_OTHER, PR_FALSE, PR_FALSE, PR_FALSE);
|
||||
ELT_UPLIMIT = new nsHtml5ElementName(nsHtml5Atoms::uplimit, nsHtml5Atoms::uplimit, NS_HTML5TREE_BUILDER_OTHER, PR_FALSE, PR_FALSE, PR_FALSE);
|
||||
ELT_ALTGLYPH = new nsHtml5ElementName(nsHtml5Atoms::altglyph, nsHtml5Atoms::altGlyph, NS_HTML5TREE_BUILDER_OTHER, PR_FALSE, PR_FALSE, PR_FALSE);
|
||||
ELT_BASEFONT = new nsHtml5ElementName(nsHtml5Atoms::basefont, nsHtml5Atoms::basefont, NS_HTML5TREE_BUILDER_AREA_OR_BASEFONT_OR_BGSOUND_OR_SPACER_OR_WBR, PR_TRUE, PR_FALSE, PR_FALSE);
|
||||
ELT_BASEFONT = new nsHtml5ElementName(nsHtml5Atoms::basefont, nsHtml5Atoms::basefont, NS_HTML5TREE_BUILDER_LINK_OR_BASEFONT_OR_BGSOUND, PR_TRUE, PR_FALSE, PR_FALSE);
|
||||
ELT_CLIPPATH = new nsHtml5ElementName(nsHtml5Atoms::clippath, nsHtml5Atoms::clipPath, NS_HTML5TREE_BUILDER_OTHER, PR_FALSE, PR_FALSE, PR_FALSE);
|
||||
ELT_CODOMAIN = new nsHtml5ElementName(nsHtml5Atoms::codomain, nsHtml5Atoms::codomain, NS_HTML5TREE_BUILDER_OTHER, PR_FALSE, PR_FALSE, PR_FALSE);
|
||||
ELT_COLGROUP = new nsHtml5ElementName(nsHtml5Atoms::colgroup, nsHtml5Atoms::colgroup, NS_HTML5TREE_BUILDER_COLGROUP, PR_TRUE, PR_FALSE, PR_FALSE);
|
||||
|
@ -51,6 +51,7 @@
|
||||
#include "nsHtml5AtomTable.h"
|
||||
#include "nsHtml5Module.h"
|
||||
#include "nsHtml5RefPtr.h"
|
||||
#include "nsIScriptError.h"
|
||||
|
||||
static NS_DEFINE_CID(kCharsetAliasCID, NS_CHARSETALIAS_CID);
|
||||
|
||||
@ -959,6 +960,17 @@ nsHtml5StreamParser::ContinueAfterScripts(nsHtml5Tokenizer* aTokenizer,
|
||||
mFirstBuffer = speculation->GetBuffer();
|
||||
mFirstBuffer->setStart(speculation->GetStart());
|
||||
mTokenizer->setLineNumber(speculation->GetStartLineNumber());
|
||||
|
||||
nsContentUtils::ReportToConsole(nsContentUtils::eDOM_PROPERTIES,
|
||||
"SpeculationFailed",
|
||||
nsnull, 0,
|
||||
mExecutor->GetDocument()->GetDocumentURI(),
|
||||
EmptyString(),
|
||||
speculation->GetStartLineNumber(),
|
||||
0,
|
||||
nsIScriptError::warningFlag,
|
||||
"DOM Events");
|
||||
|
||||
nsHtml5UTF16Buffer* buffer = mFirstBuffer->next;
|
||||
while (buffer) {
|
||||
buffer->setStart(0);
|
||||
@ -992,6 +1004,13 @@ nsHtml5StreamParser::ContinueAfterScripts(nsHtml5Tokenizer* aTokenizer,
|
||||
mSpeculations.RemoveElementAt(0);
|
||||
if (mSpeculations.IsEmpty()) {
|
||||
// yes, it was still the only speculation. Now stop speculating
|
||||
if (mTreeBuilder->IsDiscretionaryFlushSafe()) {
|
||||
// However, before telling the executor to read from stage, flush
|
||||
// any pending ops straight to the executor, because otherwise
|
||||
// they remain unflushed until we get more data from the network.
|
||||
mTreeBuilder->SetOpSink(mExecutor);
|
||||
mTreeBuilder->Flush();
|
||||
}
|
||||
mTreeBuilder->SetOpSink(mExecutor->GetStage());
|
||||
mExecutor->StartReadingFromStage();
|
||||
mSpeculating = PR_FALSE;
|
||||
|
@ -3339,7 +3339,7 @@ void
|
||||
nsHtml5Tokenizer::emitReplacementCharacter(PRUnichar* buf, PRInt32 pos)
|
||||
{
|
||||
flushChars(buf, pos);
|
||||
tokenHandler->characters(nsHtml5Tokenizer::REPLACEMENT_CHARACTER, 0, 1);
|
||||
tokenHandler->zeroOriginatingReplacementCharacter();
|
||||
cstart = pos + 1;
|
||||
}
|
||||
|
||||
|
@ -190,6 +190,10 @@ nsHtml5TreeBuilder::characters(const PRUnichar* buf, PRInt32 start, PRInt32 leng
|
||||
}
|
||||
needToDropLF = PR_FALSE;
|
||||
}
|
||||
if (inForeign) {
|
||||
accumulateCharacters(buf, start, length);
|
||||
return;
|
||||
}
|
||||
switch(mode) {
|
||||
case NS_HTML5TREE_BUILDER_IN_BODY:
|
||||
case NS_HTML5TREE_BUILDER_IN_CELL:
|
||||
@ -413,6 +417,14 @@ nsHtml5TreeBuilder::characters(const PRUnichar* buf, PRInt32 start, PRInt32 leng
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsHtml5TreeBuilder::zeroOriginatingReplacementCharacter()
|
||||
{
|
||||
if (inForeign || mode == NS_HTML5TREE_BUILDER_TEXT) {
|
||||
characters(REPLACEMENT_CHARACTER, 0, 1);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsHtml5TreeBuilder::eof()
|
||||
{
|
||||
@ -864,7 +876,7 @@ nsHtml5TreeBuilder::startTag(nsHtml5ElementName* elementName, nsHtml5HtmlAttribu
|
||||
case NS_HTML5TREE_BUILDER_MARQUEE_OR_APPLET:
|
||||
case NS_HTML5TREE_BUILDER_OBJECT:
|
||||
case NS_HTML5TREE_BUILDER_TABLE:
|
||||
case NS_HTML5TREE_BUILDER_AREA_OR_BASEFONT_OR_BGSOUND_OR_SPACER_OR_WBR:
|
||||
case NS_HTML5TREE_BUILDER_AREA_OR_SPACER_OR_WBR:
|
||||
case NS_HTML5TREE_BUILDER_BR:
|
||||
case NS_HTML5TREE_BUILDER_EMBED_OR_IMG:
|
||||
case NS_HTML5TREE_BUILDER_INPUT:
|
||||
@ -895,7 +907,7 @@ nsHtml5TreeBuilder::startTag(nsHtml5ElementName* elementName, nsHtml5HtmlAttribu
|
||||
NS_HTML5_BREAK(starttagloop);
|
||||
}
|
||||
case NS_HTML5TREE_BUILDER_BASE:
|
||||
case NS_HTML5TREE_BUILDER_LINK:
|
||||
case NS_HTML5TREE_BUILDER_LINK_OR_BASEFONT_OR_BGSOUND:
|
||||
case NS_HTML5TREE_BUILDER_META:
|
||||
case NS_HTML5TREE_BUILDER_STYLE:
|
||||
case NS_HTML5TREE_BUILDER_SCRIPT:
|
||||
@ -1060,7 +1072,7 @@ nsHtml5TreeBuilder::startTag(nsHtml5ElementName* elementName, nsHtml5HtmlAttribu
|
||||
}
|
||||
case NS_HTML5TREE_BUILDER_BR:
|
||||
case NS_HTML5TREE_BUILDER_EMBED_OR_IMG:
|
||||
case NS_HTML5TREE_BUILDER_AREA_OR_BASEFONT_OR_BGSOUND_OR_SPACER_OR_WBR: {
|
||||
case NS_HTML5TREE_BUILDER_AREA_OR_SPACER_OR_WBR: {
|
||||
reconstructTheActiveFormattingElements();
|
||||
}
|
||||
case NS_HTML5TREE_BUILDER_PARAM_OR_SOURCE: {
|
||||
@ -1304,7 +1316,7 @@ nsHtml5TreeBuilder::startTag(nsHtml5ElementName* elementName, nsHtml5HtmlAttribu
|
||||
NS_HTML5_BREAK(starttagloop);
|
||||
}
|
||||
case NS_HTML5TREE_BUILDER_META:
|
||||
case NS_HTML5TREE_BUILDER_LINK: {
|
||||
case NS_HTML5TREE_BUILDER_LINK_OR_BASEFONT_OR_BGSOUND: {
|
||||
NS_HTML5_BREAK(inheadloop);
|
||||
}
|
||||
case NS_HTML5TREE_BUILDER_TITLE: {
|
||||
@ -1368,7 +1380,7 @@ nsHtml5TreeBuilder::startTag(nsHtml5ElementName* elementName, nsHtml5HtmlAttribu
|
||||
}
|
||||
NS_HTML5_BREAK(starttagloop);
|
||||
}
|
||||
case NS_HTML5TREE_BUILDER_LINK: {
|
||||
case NS_HTML5TREE_BUILDER_LINK_OR_BASEFONT_OR_BGSOUND: {
|
||||
appendVoidElementToCurrentMayFoster(kNameSpaceID_XHTML, elementName, attributes);
|
||||
selfClosing = PR_FALSE;
|
||||
attributes = nsnull;
|
||||
@ -1671,7 +1683,7 @@ nsHtml5TreeBuilder::startTag(nsHtml5ElementName* elementName, nsHtml5HtmlAttribu
|
||||
attributes = nsnull;
|
||||
NS_HTML5_BREAK(starttagloop);
|
||||
}
|
||||
case NS_HTML5TREE_BUILDER_LINK: {
|
||||
case NS_HTML5TREE_BUILDER_LINK_OR_BASEFONT_OR_BGSOUND: {
|
||||
|
||||
pushHeadPointerOntoStack();
|
||||
appendVoidElementToCurrentMayFoster(kNameSpaceID_XHTML, elementName, attributes);
|
||||
@ -2386,7 +2398,7 @@ nsHtml5TreeBuilder::endTag(nsHtml5ElementName* elementName)
|
||||
appendVoidElementToCurrentMayFoster(kNameSpaceID_XHTML, elementName, nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES);
|
||||
NS_HTML5_BREAK(endtagloop);
|
||||
}
|
||||
case NS_HTML5TREE_BUILDER_AREA_OR_BASEFONT_OR_BGSOUND_OR_SPACER_OR_WBR:
|
||||
case NS_HTML5TREE_BUILDER_AREA_OR_SPACER_OR_WBR:
|
||||
case NS_HTML5TREE_BUILDER_PARAM_OR_SOURCE:
|
||||
case NS_HTML5TREE_BUILDER_EMBED_OR_IMG:
|
||||
case NS_HTML5TREE_BUILDER_IMAGE:
|
||||
|
@ -70,6 +70,7 @@ class nsHtml5Portability;
|
||||
class nsHtml5TreeBuilder : public nsAHtml5TreeBuilderState
|
||||
{
|
||||
private:
|
||||
static PRUnichar REPLACEMENT_CHARACTER[];
|
||||
static jArray<const char*,PRInt32> QUIRKY_PUBLIC_IDS;
|
||||
PRInt32 mode;
|
||||
PRInt32 originalMode;
|
||||
@ -100,6 +101,7 @@ class nsHtml5TreeBuilder : public nsAHtml5TreeBuilderState
|
||||
void doctype(nsIAtom* name, nsString* publicIdentifier, nsString* systemIdentifier, PRBool forceQuirks);
|
||||
void comment(PRUnichar* buf, PRInt32 start, PRInt32 length);
|
||||
void characters(const PRUnichar* buf, PRInt32 start, PRInt32 length);
|
||||
void zeroOriginatingReplacementCharacter();
|
||||
void eof();
|
||||
void endTokenization();
|
||||
void startTag(nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes, PRBool selfClosing);
|
||||
@ -239,6 +241,7 @@ class nsHtml5TreeBuilder : public nsAHtml5TreeBuilderState
|
||||
};
|
||||
|
||||
#ifdef nsHtml5TreeBuilder_cpp__
|
||||
PRUnichar nsHtml5TreeBuilder::REPLACEMENT_CHARACTER[] = { 0xfffd };
|
||||
jArray<const char*,PRInt32> nsHtml5TreeBuilder::QUIRKY_PUBLIC_IDS = nsnull;
|
||||
#endif
|
||||
|
||||
@ -258,7 +261,7 @@ jArray<const char*,PRInt32> nsHtml5TreeBuilder::QUIRKY_PUBLIC_IDS = nsnull;
|
||||
#define NS_HTML5TREE_BUILDER_INPUT 13
|
||||
#define NS_HTML5TREE_BUILDER_ISINDEX 14
|
||||
#define NS_HTML5TREE_BUILDER_LI 15
|
||||
#define NS_HTML5TREE_BUILDER_LINK 16
|
||||
#define NS_HTML5TREE_BUILDER_LINK_OR_BASEFONT_OR_BGSOUND 16
|
||||
#define NS_HTML5TREE_BUILDER_MATH 17
|
||||
#define NS_HTML5TREE_BUILDER_META 18
|
||||
#define NS_HTML5TREE_BUILDER_SVG 19
|
||||
@ -290,7 +293,7 @@ jArray<const char*,PRInt32> nsHtml5TreeBuilder::QUIRKY_PUBLIC_IDS = nsnull;
|
||||
#define NS_HTML5TREE_BUILDER_UL_OR_OL_OR_DL 46
|
||||
#define NS_HTML5TREE_BUILDER_IFRAME 47
|
||||
#define NS_HTML5TREE_BUILDER_EMBED_OR_IMG 48
|
||||
#define NS_HTML5TREE_BUILDER_AREA_OR_BASEFONT_OR_BGSOUND_OR_SPACER_OR_WBR 49
|
||||
#define NS_HTML5TREE_BUILDER_AREA_OR_SPACER_OR_WBR 49
|
||||
#define NS_HTML5TREE_BUILDER_DIV_OR_BLOCKQUOTE_OR_CENTER_OR_MENU 50
|
||||
#define NS_HTML5TREE_BUILDER_ADDRESS_OR_DIR_OR_ARTICLE_OR_ASIDE_OR_DATAGRID_OR_DETAILS_OR_HGROUP_OR_FIGURE_OR_FOOTER_OR_HEADER_OR_NAV_OR_SECTION 51
|
||||
#define NS_HTML5TREE_BUILDER_RUBY_OR_SPAN_OR_SUB_OR_SUP_OR_VAR 52
|
||||
|
@ -64,5 +64,10 @@ _TEST_FILES = parser_datreader.js \
|
||||
invalidchar.xml \
|
||||
$(NULL)
|
||||
|
||||
# Disabled test due to orange on Linux
|
||||
# test_bug568470.html \
|
||||
# file_bug568470.sjs \
|
||||
# file_bug568470-script.sjs \
|
||||
|
||||
libs:: $(_TEST_FILES)
|
||||
$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/tests/$(relativesrcdir)
|
||||
|
14
parser/htmlparser/tests/mochitest/file_bug568470-script.sjs
Normal file
14
parser/htmlparser/tests/mochitest/file_bug568470-script.sjs
Normal file
@ -0,0 +1,14 @@
|
||||
function handleRequest(request, response)
|
||||
{
|
||||
response.setHeader("Cache-Control", "no-cache", false);
|
||||
response.setHeader("Content-Type", "text/javascript", false);
|
||||
response.write("var i = 0;");
|
||||
response.bodyOutputStream.flush();
|
||||
response.processAsync();
|
||||
var timer = Components.classes["@mozilla.org/timer;1"]
|
||||
.createInstance(Components.interfaces.nsITimer);
|
||||
timer.initWithCallback(function() {
|
||||
response.finish();
|
||||
}, 500, Components.interfaces.nsITimer.TYPE_ONE_SHOT);
|
||||
}
|
||||
|
19
parser/htmlparser/tests/mochitest/file_bug568470.sjs
Normal file
19
parser/htmlparser/tests/mochitest/file_bug568470.sjs
Normal file
@ -0,0 +1,19 @@
|
||||
function handleRequest(request, response)
|
||||
{
|
||||
response.setHeader("Cache-Control", "no-cache", false);
|
||||
response.setHeader("Content-Type", "text/html", false);
|
||||
response.write("<script src='file_bug568470-script.sjs'></script>");
|
||||
response.write("<div id='flushable'>");
|
||||
for (var i = 0; i < 2000; i++) {
|
||||
response.write("Lorem ipsum dolor sit amet. ");
|
||||
}
|
||||
response.write("</div>");
|
||||
response.bodyOutputStream.flush();
|
||||
response.processAsync();
|
||||
var timer = Components.classes["@mozilla.org/timer;1"]
|
||||
.createInstance(Components.interfaces.nsITimer);
|
||||
timer.initWithCallback(function() {
|
||||
response.finish();
|
||||
}, 1200, Components.interfaces.nsITimer.TYPE_ONE_SHOT);
|
||||
}
|
||||
|
51
parser/htmlparser/tests/mochitest/test_bug568470.html
Normal file
51
parser/htmlparser/tests/mochitest/test_bug568470.html
Normal file
@ -0,0 +1,51 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=568470
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 568470</title>
|
||||
<script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
|
||||
<script type="text/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=568470">Mozilla Bug 568470</a>
|
||||
<p id="display"></p>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
/** Test for Bug 568470 **/
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
// assuming the test runs in less than a year...
|
||||
var time = new Date().getTime() + 1000*60*60*24*365;
|
||||
|
||||
var interval = setInterval(function() {
|
||||
var iframe = document.getElementsByTagName("iframe")[0];
|
||||
if (iframe) {
|
||||
var doc = iframe.contentDocument;
|
||||
if (doc) {
|
||||
if (doc.getElementById("flushable")) {
|
||||
time = new Date();
|
||||
clearInterval(interval);
|
||||
}
|
||||
}
|
||||
}
|
||||
}, 25);
|
||||
|
||||
function finish() {
|
||||
clearInterval(interval);
|
||||
var elapsed = new Date().getTime() - time;
|
||||
ok(elapsed > 350,
|
||||
"Content flush time and parse end time not enough apart.");
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
<div id="content" style="display: none">
|
||||
<iframe onload="finish();" src="file_bug568470.sjs"></iframe>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -1,2 +1,2 @@
|
||||
<body>�hello world
|
||||
<body>hello world
|
||||
|
||||
|
@ -60,7 +60,7 @@ AsyncStatementCallback::HandleError(mozIStorageError *aError)
|
||||
|
||||
nsCAutoString warnMsg;
|
||||
warnMsg.Append("An error occurred while executing an async statement: ");
|
||||
warnMsg.Append(result);
|
||||
warnMsg.AppendInt(result);
|
||||
warnMsg.Append(" ");
|
||||
warnMsg.Append(message);
|
||||
NS_WARNING(warnMsg.get());
|
||||
@ -180,6 +180,33 @@ URIBinder::Bind(mozIStorageBindingParams* aParams,
|
||||
|
||||
#undef URI_TO_URLCSTRING
|
||||
|
||||
nsresult
|
||||
GetReversedHostname(nsIURI* aURI, nsString& aRevHost)
|
||||
{
|
||||
nsCAutoString forward8;
|
||||
nsresult rv = aURI->GetHost(forward8);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// can't do reversing in UTF8, better use 16-bit chars
|
||||
GetReversedHostname(NS_ConvertUTF8toUTF16(forward8), aRevHost);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
GetReversedHostname(const nsString& aForward, nsString& aRevHost)
|
||||
{
|
||||
ReverseString(aForward, aRevHost);
|
||||
aRevHost.Append(PRUnichar('.'));
|
||||
}
|
||||
|
||||
void
|
||||
ReverseString(const nsString& aInput, nsString& aReversed)
|
||||
{
|
||||
aReversed.Truncate(0);
|
||||
for (PRInt32 i = aInput.Length() - 1; i >= 0; i--) {
|
||||
aReversed.Append(aInput[i]);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace places
|
||||
} // namespace mozilla
|
||||
|
@ -136,6 +136,44 @@ public:
|
||||
const nsACString& aURLString);
|
||||
};
|
||||
|
||||
/**
|
||||
* This extracts the hostname from the URI and reverses it in the
|
||||
* form that we use (always ending with a "."). So
|
||||
* "http://microsoft.com/" becomes "moc.tfosorcim."
|
||||
*
|
||||
* The idea behind this is that we can create an index over the items in
|
||||
* the reversed host name column, and then query for as much or as little
|
||||
* of the host name as we feel like.
|
||||
*
|
||||
* For example, the query "host >= 'gro.allizom.' AND host < 'gro.allizom/'
|
||||
* Matches all host names ending in '.mozilla.org', including
|
||||
* 'developer.mozilla.org' and just 'mozilla.org' (since we define all
|
||||
* reversed host names to end in a period, even 'mozilla.org' matches).
|
||||
* The important thing is that this operation uses the index. Any substring
|
||||
* calls in a select statement (even if it's for the beginning of a string)
|
||||
* will bypass any indices and will be slow).
|
||||
*
|
||||
* @param aURI
|
||||
* URI that contains spec to reverse
|
||||
* @param aRevHost
|
||||
* Out parameter
|
||||
*/
|
||||
nsresult GetReversedHostname(nsIURI* aURI, nsString& aRevHost);
|
||||
|
||||
/**
|
||||
* Similar method to GetReversedHostName but for strings
|
||||
*/
|
||||
void GetReversedHostname(const nsString& aForward, nsString& aRevHost);
|
||||
|
||||
/**
|
||||
* Reverses a string.
|
||||
*
|
||||
* @param aInput
|
||||
* The string to be reversed
|
||||
* @param aReversed
|
||||
* Ouput parameter will contain the reversed string
|
||||
*/
|
||||
void ReverseString(const nsString& aInput, nsString& aReversed);
|
||||
|
||||
} // namespace places
|
||||
} // namespace mozilla
|
||||
|
@ -39,6 +39,7 @@
|
||||
|
||||
#include "History.h"
|
||||
#include "nsNavHistory.h"
|
||||
#include "nsNavBookmarks.h"
|
||||
#include "Helpers.h"
|
||||
|
||||
#include "mozilla/storage.h"
|
||||
@ -58,6 +59,87 @@ namespace places {
|
||||
#define URI_VISITED "visited"
|
||||
#define URI_NOT_VISITED "not visited"
|
||||
#define URI_VISITED_RESOLUTION_TOPIC "visited-status-resolution"
|
||||
// Observer event fired after a visit has been registered in the DB.
|
||||
#define URI_VISIT_SAVED "uri-visit-saved"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//// Step
|
||||
|
||||
class Step : public AsyncStatementCallback
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Executes statement asynchronously using this as a callback.
|
||||
*
|
||||
* @param aStmt
|
||||
* Statement to execute asynchronously
|
||||
*/
|
||||
NS_IMETHOD ExecuteAsync(mozIStorageStatement* aStmt);
|
||||
|
||||
/**
|
||||
* Called once after query is completed. If your query has more than one
|
||||
* result set to process, you will want to override HandleResult to process
|
||||
* each one.
|
||||
*
|
||||
* @param aResultSet
|
||||
* Results from ExecuteAsync
|
||||
* Unlike HandleResult, this *can be NULL* if there were no results.
|
||||
*/
|
||||
NS_IMETHOD Callback(mozIStorageResultSet* aResultSet);
|
||||
|
||||
/**
|
||||
* By default, stores the last result set received in mResultSet.
|
||||
* For queries with only one result set, you don't need to override.
|
||||
*
|
||||
* @param aResultSet
|
||||
* Results from ExecuteAsync
|
||||
*/
|
||||
NS_IMETHOD HandleResult(mozIStorageResultSet* aResultSet);
|
||||
|
||||
/**
|
||||
* By default, this calls Callback with any saved results from HandleResult.
|
||||
* For queries with only one result set, you don't need to override.
|
||||
*
|
||||
* @param aReason
|
||||
* SQL status code
|
||||
*/
|
||||
NS_IMETHOD HandleCompletion(PRUint16 aReason);
|
||||
|
||||
private:
|
||||
// Used by HandleResult to cache results until HandleCompletion is called.
|
||||
nsCOMPtr<mozIStorageResultSet> mResultSet;
|
||||
};
|
||||
|
||||
NS_IMETHODIMP
|
||||
Step::ExecuteAsync(mozIStorageStatement* aStmt)
|
||||
{
|
||||
nsCOMPtr<mozIStoragePendingStatement> handle;
|
||||
nsresult rv = aStmt->ExecuteAsync(this, getter_AddRefs(handle));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
Step::Callback(mozIStorageResultSet* aResultSet)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
Step::HandleResult(mozIStorageResultSet* aResultSet)
|
||||
{
|
||||
mResultSet = aResultSet;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
Step::HandleCompletion(PRUint16 aReason)
|
||||
{
|
||||
nsCOMPtr<mozIStorageResultSet> resultSet = mResultSet;
|
||||
mResultSet = NULL;
|
||||
Callback(resultSet);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//// Anonymous Helpers
|
||||
@ -71,7 +153,7 @@ public:
|
||||
|
||||
static nsresult Start(nsIURI* aURI)
|
||||
{
|
||||
NS_ASSERTION(aURI, "Don't pass a null URI!");
|
||||
NS_PRECONDITION(aURI, "Null URI");
|
||||
|
||||
nsNavHistory* navHist = nsNavHistory::GetHistoryService();
|
||||
NS_ENSURE_TRUE(navHist, NS_ERROR_FAILURE);
|
||||
@ -144,6 +226,626 @@ NS_IMPL_ISUPPORTS1(
|
||||
mozIStorageStatementCallback
|
||||
)
|
||||
|
||||
/**
|
||||
* Fail-safe mechanism for ensuring that your task completes, no matter what.
|
||||
* Pass this around as an nsAutoPtr in your steps to guarantee that when all
|
||||
* your steps are finished, your task is finished.
|
||||
*/
|
||||
class FailSafeFinishTask
|
||||
{
|
||||
public:
|
||||
~FailSafeFinishTask() {
|
||||
History::GetService()->CurrentTaskFinished();
|
||||
}
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//// Steps for VisitURI
|
||||
|
||||
struct VisitURIData : public FailSafeFinishTask
|
||||
{
|
||||
PRInt64 placeId;
|
||||
PRInt32 hidden;
|
||||
PRInt32 typed;
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
|
||||
// Url of last added visit in chain.
|
||||
nsCString lastSpec;
|
||||
PRInt64 lastVisitId;
|
||||
PRInt32 transitionType;
|
||||
PRInt64 sessionId;
|
||||
PRTime dateTime;
|
||||
};
|
||||
|
||||
/**
|
||||
* Step 6: Update frecency of URI and notify observers.
|
||||
*/
|
||||
class UpdateFrecencyAndNotifyStep : public Step
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
UpdateFrecencyAndNotifyStep(nsAutoPtr<VisitURIData> aData)
|
||||
: mData(aData)
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMETHOD Callback(mozIStorageResultSet* aResultSet)
|
||||
{
|
||||
// Result set contains new visit created in earlier step
|
||||
NS_ENSURE_STATE(aResultSet);
|
||||
|
||||
nsCOMPtr<mozIStorageRow> row;
|
||||
nsresult rv = aResultSet->GetNextRow(getter_AddRefs(row));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
PRInt64 visitId;
|
||||
rv = row->GetInt64(0, &visitId);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// TODO need to figure out story for not synchronous frecency updating
|
||||
// (bug 556631)
|
||||
|
||||
// Swallow errors here, since if we've gotten this far, it's more
|
||||
// important to notify the observers below.
|
||||
nsNavHistory* history = nsNavHistory::GetHistoryService();
|
||||
NS_WARN_IF_FALSE(history, "Could not get history service");
|
||||
nsNavBookmarks* bookmarks = nsNavBookmarks::GetBookmarksService();
|
||||
NS_WARN_IF_FALSE(bookmarks, "Could not get bookmarks service");
|
||||
if (history && bookmarks) {
|
||||
// Update frecency *after* the visit info is in the db
|
||||
nsresult rv = history->UpdateFrecency(
|
||||
mData->placeId,
|
||||
bookmarks->IsRealBookmark(mData->placeId)
|
||||
);
|
||||
NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "Could not update frecency");
|
||||
|
||||
// Notify nsNavHistory observers of visit, but only for certain types of
|
||||
// visits to maintain consistency with nsNavHistory::GetQueryResults.
|
||||
if (!mData->hidden &&
|
||||
mData->transitionType != nsINavHistoryService::TRANSITION_EMBED &&
|
||||
mData->transitionType != nsINavHistoryService::TRANSITION_FRAMED_LINK) {
|
||||
history->NotifyOnVisit(mData->uri, visitId, mData->dateTime,
|
||||
mData->sessionId, mData->lastVisitId,
|
||||
mData->transitionType);
|
||||
}
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIObserverService> obsService =
|
||||
mozilla::services::GetObserverService();
|
||||
if (obsService) {
|
||||
nsresult rv = obsService->NotifyObservers(mData->uri, URI_VISIT_SAVED, nsnull);
|
||||
NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "Could not notify observers");
|
||||
}
|
||||
|
||||
History::GetService()->NotifyVisited(mData->uri);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
protected:
|
||||
nsAutoPtr<VisitURIData> mData;
|
||||
};
|
||||
NS_IMPL_ISUPPORTS1(
|
||||
UpdateFrecencyAndNotifyStep
|
||||
, mozIStorageStatementCallback
|
||||
)
|
||||
|
||||
/**
|
||||
* Step 5: Get newly created visit ID from moz_history_visits table.
|
||||
*/
|
||||
class GetVisitIDStep : public Step
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
GetVisitIDStep(nsAutoPtr<VisitURIData> aData)
|
||||
: mData(aData)
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMETHOD Callback(mozIStorageResultSet* aResultSet)
|
||||
{
|
||||
// Find visit ID, needed for notifying observers in next step.
|
||||
nsNavHistory* history = nsNavHistory::GetHistoryService();
|
||||
NS_ENSURE_TRUE(history, NS_ERROR_OUT_OF_MEMORY);
|
||||
nsCOMPtr<mozIStorageStatement> stmt =
|
||||
history->GetStatementById(DB_RECENT_VISIT_OF_URL);
|
||||
NS_ENSURE_STATE(stmt);
|
||||
|
||||
nsresult rv = URIBinder::Bind(stmt, NS_LITERAL_CSTRING("page_url"), mData->uri);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<Step> step = new UpdateFrecencyAndNotifyStep(mData);
|
||||
rv = step->ExecuteAsync(stmt);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
protected:
|
||||
nsAutoPtr<VisitURIData> mData;
|
||||
};
|
||||
NS_IMPL_ISUPPORTS1(
|
||||
GetVisitIDStep
|
||||
, mozIStorageStatementCallback
|
||||
)
|
||||
|
||||
/**
|
||||
* Step 4: Add visit to moz_history_visits table.
|
||||
*/
|
||||
class AddVisitStep : public Step
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
AddVisitStep(nsAutoPtr<VisitURIData> aData)
|
||||
: mData(aData)
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMETHOD Callback(mozIStorageResultSet* aResultSet)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
nsNavHistory* history = nsNavHistory::GetHistoryService();
|
||||
NS_ENSURE_TRUE(history, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
// TODO need to figure out story for new session IDs that isn't synchronous
|
||||
// (bug 561450)
|
||||
|
||||
if (aResultSet) {
|
||||
// Result set contains last visit information for this session
|
||||
nsCOMPtr<mozIStorageRow> row;
|
||||
rv = aResultSet->GetNextRow(getter_AddRefs(row));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
PRInt64 possibleSessionId;
|
||||
PRTime lastVisitOfSession;
|
||||
|
||||
rv = row->GetInt64(0, &mData->lastVisitId);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = row->GetInt64(1, &possibleSessionId);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = row->GetInt64(2, &lastVisitOfSession);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (mData->dateTime - lastVisitOfSession <= RECENT_EVENT_THRESHOLD) {
|
||||
mData->sessionId = possibleSessionId;
|
||||
}
|
||||
else {
|
||||
// Session is too old. Start a new one.
|
||||
mData->sessionId = history->GetNewSessionID();
|
||||
mData->lastVisitId = 0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// No previous saved visit entry could be found, so start a new session.
|
||||
mData->sessionId = history->GetNewSessionID();
|
||||
mData->lastVisitId = 0;
|
||||
}
|
||||
|
||||
nsCOMPtr<mozIStorageStatement> stmt =
|
||||
history->GetStatementById(DB_INSERT_VISIT);
|
||||
NS_ENSURE_STATE(stmt);
|
||||
|
||||
rv = stmt->BindInt64ByName(NS_LITERAL_CSTRING("from_visit"),
|
||||
mData->lastVisitId);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = stmt->BindInt64ByName(NS_LITERAL_CSTRING("page_id"),
|
||||
mData->placeId);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = stmt->BindInt64ByName(NS_LITERAL_CSTRING("visit_date"),
|
||||
mData->dateTime);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = stmt->BindInt32ByName(NS_LITERAL_CSTRING("visit_type"),
|
||||
mData->transitionType);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = stmt->BindInt64ByName(NS_LITERAL_CSTRING("session"),
|
||||
mData->sessionId);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<Step> step = new GetVisitIDStep(mData);
|
||||
rv = step->ExecuteAsync(stmt);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
protected:
|
||||
nsAutoPtr<VisitURIData> mData;
|
||||
};
|
||||
NS_IMPL_ISUPPORTS1(
|
||||
AddVisitStep
|
||||
, mozIStorageStatementCallback
|
||||
)
|
||||
|
||||
/**
|
||||
* Step 3: Callback for inserting or updating a moz_places entry.
|
||||
* This step checks database for the last visit in session.
|
||||
*/
|
||||
class CheckLastVisitStep : public Step
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
CheckLastVisitStep(nsAutoPtr<VisitURIData> aData)
|
||||
: mData(aData)
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMETHOD Callback(mozIStorageResultSet* aResultSet)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
if (aResultSet) {
|
||||
// Last step inserted a new URL. This query contains the id.
|
||||
nsCOMPtr<mozIStorageRow> row;
|
||||
rv = aResultSet->GetNextRow(getter_AddRefs(row));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = row->GetInt64(0, &mData->placeId);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
if (!mData->lastSpec.IsEmpty()) {
|
||||
// Find last visit ID and session ID using lastSpec so we can add them
|
||||
// to a browsing session if the visit was recent.
|
||||
nsNavHistory* history = nsNavHistory::GetHistoryService();
|
||||
NS_ENSURE_TRUE(history, NS_ERROR_OUT_OF_MEMORY);
|
||||
nsCOMPtr<mozIStorageStatement> stmt =
|
||||
history->GetStatementById(DB_RECENT_VISIT_OF_URL);
|
||||
NS_ENSURE_STATE(stmt);
|
||||
|
||||
rv = URIBinder::Bind(stmt, NS_LITERAL_CSTRING("page_url"), mData->lastSpec);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<Step> step = new AddVisitStep(mData);
|
||||
rv = step->ExecuteAsync(stmt);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
else {
|
||||
// Empty lastSpec.
|
||||
// Not part of a session. Just run next step's callback with no results.
|
||||
nsCOMPtr<Step> step = new AddVisitStep(mData);
|
||||
rv = step->Callback(NULL);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
protected:
|
||||
nsAutoPtr<VisitURIData> mData;
|
||||
};
|
||||
NS_IMPL_ISUPPORTS1(
|
||||
CheckLastVisitStep
|
||||
, mozIStorageStatementCallback
|
||||
)
|
||||
|
||||
/**
|
||||
* Step 2a: Called only when a new entry is put into moz_places.
|
||||
* Finds the ID of a recently inserted place.
|
||||
*/
|
||||
class FindNewIdStep : public Step
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
FindNewIdStep(nsAutoPtr<VisitURIData> aData)
|
||||
: mData(aData)
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMETHOD Callback(mozIStorageResultSet* aResultSet)
|
||||
{
|
||||
nsNavHistory* history = nsNavHistory::GetHistoryService();
|
||||
NS_ENSURE_TRUE(history, NS_ERROR_OUT_OF_MEMORY);
|
||||
nsCOMPtr<mozIStorageStatement> stmt =
|
||||
history->GetStatementById(DB_GET_PAGE_VISIT_STATS);
|
||||
NS_ENSURE_STATE(stmt);
|
||||
|
||||
nsresult rv = URIBinder::Bind(stmt, NS_LITERAL_CSTRING("page_url"), mData->uri);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<Step> step = new CheckLastVisitStep(mData);
|
||||
rv = step->ExecuteAsync(stmt);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
protected:
|
||||
nsAutoPtr<VisitURIData> mData;
|
||||
};
|
||||
NS_IMPL_ISUPPORTS1(
|
||||
FindNewIdStep
|
||||
, mozIStorageStatementCallback
|
||||
)
|
||||
|
||||
/**
|
||||
* Step 2: Callback for checking for an existing URI in moz_places.
|
||||
* This step inserts or updates the URI accordingly.
|
||||
*/
|
||||
class CheckExistingStep : public Step
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
CheckExistingStep(nsAutoPtr<VisitURIData> aData)
|
||||
: mData(aData)
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMETHOD Callback(mozIStorageResultSet* aResultSet)
|
||||
{
|
||||
nsresult rv;
|
||||
nsCOMPtr<mozIStorageStatement> stmt;
|
||||
|
||||
nsNavHistory* history = nsNavHistory::GetHistoryService();
|
||||
NS_ENSURE_TRUE(history, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
if (aResultSet) {
|
||||
nsCOMPtr<mozIStorageRow> row;
|
||||
rv = aResultSet->GetNextRow(getter_AddRefs(row));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = row->GetInt64(0, &mData->placeId);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (!mData->typed) {
|
||||
// If this transition wasn't typed, others might have been. If database
|
||||
// has location as typed, reflect that in our data structure.
|
||||
rv = row->GetInt32(2, &mData->typed);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
if (mData->hidden) {
|
||||
// If this transition was hidden, it is possible that others were not.
|
||||
// Any one visible transition makes this location visible. If database
|
||||
// has location as visible, reflect that in our data structure.
|
||||
rv = row->GetInt32(3, &mData->hidden);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
// Note: trigger will update visit_count.
|
||||
stmt = history->GetStatementById(DB_UPDATE_PAGE_VISIT_STATS);
|
||||
NS_ENSURE_STATE(stmt);
|
||||
|
||||
rv = stmt->BindInt32ByName(NS_LITERAL_CSTRING("typed"), mData->typed);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = stmt->BindInt32ByName(NS_LITERAL_CSTRING("hidden"), mData->hidden);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = stmt->BindInt64ByName(NS_LITERAL_CSTRING("page_id"), mData->placeId);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<Step> step = new CheckLastVisitStep(mData);
|
||||
rv = step->ExecuteAsync(stmt);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
else {
|
||||
// No entry exists, so create one.
|
||||
stmt = history->GetStatementById(DB_ADD_NEW_PAGE);
|
||||
NS_ENSURE_STATE(stmt);
|
||||
|
||||
nsAutoString revHost;
|
||||
rv = GetReversedHostname(mData->uri, revHost);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = URIBinder::Bind(stmt, NS_LITERAL_CSTRING("page_url"), mData->uri);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = stmt->BindStringByName(NS_LITERAL_CSTRING("rev_host"), revHost);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = stmt->BindInt32ByName(NS_LITERAL_CSTRING("typed"), mData->typed);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = stmt->BindInt32ByName(NS_LITERAL_CSTRING("hidden"), mData->hidden);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = stmt->BindInt32ByName(NS_LITERAL_CSTRING("frecency"), -1);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<Step> step = new FindNewIdStep(mData);
|
||||
rv = step->ExecuteAsync(stmt);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
protected:
|
||||
nsAutoPtr<VisitURIData> mData;
|
||||
};
|
||||
NS_IMPL_ISUPPORTS1(
|
||||
CheckExistingStep
|
||||
, mozIStorageStatementCallback
|
||||
)
|
||||
|
||||
/**
|
||||
* Step 1: See if there is an existing URI.
|
||||
*/
|
||||
class StartVisitURIStep : public Step
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
StartVisitURIStep(nsAutoPtr<VisitURIData> aData)
|
||||
: mData(aData)
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMETHOD Callback(mozIStorageResultSet* aResultSet)
|
||||
{
|
||||
nsNavHistory* history = nsNavHistory::GetHistoryService();
|
||||
|
||||
// Find existing entry in moz_places table, if any.
|
||||
nsCOMPtr<mozIStorageStatement> stmt =
|
||||
history->GetStatementById(DB_GET_PAGE_VISIT_STATS);
|
||||
NS_ENSURE_STATE(stmt);
|
||||
|
||||
nsresult rv = URIBinder::Bind(stmt, NS_LITERAL_CSTRING("page_url"), mData->uri);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<Step> step = new CheckExistingStep(mData);
|
||||
rv = step->ExecuteAsync(stmt);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
protected:
|
||||
nsAutoPtr<VisitURIData> mData;
|
||||
};
|
||||
NS_IMPL_ISUPPORTS1(
|
||||
StartVisitURIStep
|
||||
, Step
|
||||
)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//// Steps for SetURITitle
|
||||
|
||||
struct SetTitleData : public FailSafeFinishTask
|
||||
{
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
nsString title;
|
||||
};
|
||||
|
||||
/**
|
||||
* Step 3: Notify that title has been updated.
|
||||
*/
|
||||
class TitleNotifyStep: public Step
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
TitleNotifyStep(nsAutoPtr<SetTitleData> aData)
|
||||
: mData(aData)
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMETHOD Callback(mozIStorageResultSet* aResultSet)
|
||||
{
|
||||
nsNavHistory* history = nsNavHistory::GetHistoryService();
|
||||
history->NotifyTitleChange(mData->uri, mData->title);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
protected:
|
||||
nsAutoPtr<SetTitleData> mData;
|
||||
};
|
||||
NS_IMPL_ISUPPORTS1(
|
||||
TitleNotifyStep
|
||||
, mozIStorageStatementCallback
|
||||
)
|
||||
|
||||
/**
|
||||
* Step 2: Set title.
|
||||
*/
|
||||
class SetTitleStep : public Step
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
SetTitleStep(nsAutoPtr<SetTitleData> aData)
|
||||
: mData(aData)
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMETHOD Callback(mozIStorageResultSet* aResultSet)
|
||||
{
|
||||
if (!aResultSet) {
|
||||
// URI record was not found.
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCOMPtr<mozIStorageRow> row;
|
||||
nsresult rv = aResultSet->GetNextRow(getter_AddRefs(row));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsAutoString title;
|
||||
rv = row->GetString(2, title);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// It is actually common to set the title to be the same thing it used to
|
||||
// be. For example, going to any web page will always cause a title to be set,
|
||||
// even though it will often be unchanged since the last visit. In these
|
||||
// cases, we can avoid DB writing and observer overhead.
|
||||
if (mData->title.Equals(title) || (mData->title.IsVoid() && title.IsVoid()))
|
||||
return NS_OK;
|
||||
|
||||
nsNavHistory* history = nsNavHistory::GetHistoryService();
|
||||
|
||||
nsCOMPtr<mozIStorageStatement> stmt =
|
||||
history->GetStatementById(DB_SET_PLACE_TITLE);
|
||||
NS_ENSURE_STATE(stmt);
|
||||
|
||||
if (mData->title.IsVoid()) {
|
||||
rv = stmt->BindNullByName(NS_LITERAL_CSTRING("page_title"));
|
||||
}
|
||||
else {
|
||||
rv = stmt->BindStringByName(
|
||||
NS_LITERAL_CSTRING("page_title"),
|
||||
StringHead(mData->title, TITLE_LENGTH_MAX)
|
||||
);
|
||||
}
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = URIBinder::Bind(stmt, NS_LITERAL_CSTRING("page_url"), mData->uri);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<Step> step = new TitleNotifyStep(mData);
|
||||
rv = step->ExecuteAsync(stmt);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
protected:
|
||||
nsAutoPtr<SetTitleData> mData;
|
||||
};
|
||||
NS_IMPL_ISUPPORTS1(
|
||||
SetTitleStep
|
||||
, mozIStorageStatementCallback
|
||||
)
|
||||
|
||||
/**
|
||||
* Step 1: See if there is an existing URI.
|
||||
*/
|
||||
class StartSetURITitleStep : public Step
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
StartSetURITitleStep(nsAutoPtr<SetTitleData> aData)
|
||||
: mData(aData)
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMETHOD Callback(mozIStorageResultSet* aResultSet)
|
||||
{
|
||||
nsNavHistory* history = nsNavHistory::GetHistoryService();
|
||||
|
||||
// Find existing entry in moz_places table, if any.
|
||||
nsCOMPtr<mozIStorageStatement> stmt =
|
||||
history->GetStatementById(DB_GET_URL_PAGE_INFO);
|
||||
NS_ENSURE_STATE(stmt);
|
||||
|
||||
nsresult rv = URIBinder::Bind(stmt, NS_LITERAL_CSTRING("page_url"), mData->uri);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<Step> step = new SetTitleStep(mData);
|
||||
rv = step->ExecuteAsync(stmt);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
protected:
|
||||
nsAutoPtr<SetTitleData> mData;
|
||||
};
|
||||
NS_IMPL_ISUPPORTS1(
|
||||
StartSetURITitleStep
|
||||
, Step
|
||||
)
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@ -160,6 +862,7 @@ History::History()
|
||||
History::~History()
|
||||
{
|
||||
gService = NULL;
|
||||
|
||||
#ifdef DEBUG
|
||||
if (mObservers.IsInitialized()) {
|
||||
NS_ASSERTION(mObservers.Count() == 0,
|
||||
@ -168,6 +871,28 @@ History::~History()
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
History::AppendTask(Step* aTask)
|
||||
{
|
||||
NS_PRECONDITION(aTask, "Got NULL task.");
|
||||
|
||||
NS_ADDREF(aTask);
|
||||
mPendingVisits.Push(aTask);
|
||||
|
||||
if (mPendingVisits.GetSize() == 1) {
|
||||
// There are no other pending tasks.
|
||||
StartNextTask();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
History::CurrentTaskFinished()
|
||||
{
|
||||
nsCOMPtr<Step> deadTaskWalking =
|
||||
dont_AddRef(static_cast<Step*>(mPendingVisits.PopFront()));
|
||||
StartNextTask();
|
||||
}
|
||||
|
||||
void
|
||||
History::NotifyVisited(nsIURI* aURI)
|
||||
{
|
||||
@ -228,9 +953,107 @@ History::GetSingleton()
|
||||
return gService;
|
||||
}
|
||||
|
||||
void
|
||||
History::StartNextTask()
|
||||
{
|
||||
nsCOMPtr<Step> nextTask =
|
||||
static_cast<Step*>(mPendingVisits.PeekFront());
|
||||
if (!nextTask) {
|
||||
// No more pending visits left to process.
|
||||
return;
|
||||
}
|
||||
nsresult rv = nextTask->Callback(NULL);
|
||||
NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "Beginning a task failed.");
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//// IHistory
|
||||
|
||||
NS_IMETHODIMP
|
||||
History::VisitURI(nsIURI* aURI,
|
||||
nsIURI* aLastVisitedURI,
|
||||
PRUint32 aFlags)
|
||||
{
|
||||
NS_PRECONDITION(aURI, "URI should not be NULL.");
|
||||
|
||||
nsNavHistory* history = nsNavHistory::GetHistoryService();
|
||||
NS_ENSURE_TRUE(history, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
// Silently return if URI is something we shouldn't add to DB.
|
||||
PRBool canAdd;
|
||||
nsresult rv = history->CanAddURI(aURI, &canAdd);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (!canAdd) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Populate data structure that will be used in our async SQL steps.
|
||||
nsAutoPtr<VisitURIData> data(new VisitURIData());
|
||||
|
||||
nsCAutoString spec;
|
||||
rv = aURI->GetSpec(spec);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (aLastVisitedURI) {
|
||||
rv = aLastVisitedURI->GetSpec(data->lastSpec);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
if (spec.Equals(data->lastSpec)) {
|
||||
// Do not save refresh-page visits.
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Assigns a type to the edge in the visit linked list. Each type will be
|
||||
// considered differently when weighting the frecency of a location.
|
||||
PRUint32 recentFlags = history->GetRecentFlags(aURI);
|
||||
bool redirected = false;
|
||||
if (aFlags & IHistory::REDIRECT_TEMPORARY) {
|
||||
data->transitionType = nsINavHistoryService::TRANSITION_REDIRECT_TEMPORARY;
|
||||
redirected = true;
|
||||
}
|
||||
else if (aFlags & IHistory::REDIRECT_PERMANENT) {
|
||||
data->transitionType = nsINavHistoryService::TRANSITION_REDIRECT_PERMANENT;
|
||||
redirected = true;
|
||||
}
|
||||
else if (recentFlags & nsNavHistory::RECENT_TYPED) {
|
||||
data->transitionType = nsINavHistoryService::TRANSITION_TYPED;
|
||||
}
|
||||
else if (recentFlags & nsNavHistory::RECENT_BOOKMARKED) {
|
||||
data->transitionType = nsINavHistoryService::TRANSITION_BOOKMARK;
|
||||
}
|
||||
else if (aFlags & IHistory::TOP_LEVEL) {
|
||||
// User was redirected or link was clicked in the main window.
|
||||
data->transitionType = nsINavHistoryService::TRANSITION_LINK;
|
||||
}
|
||||
else if (recentFlags & nsNavHistory::RECENT_ACTIVATED) {
|
||||
// User activated a link in a frame.
|
||||
data->transitionType = nsINavHistoryService::TRANSITION_FRAMED_LINK;
|
||||
}
|
||||
else {
|
||||
// A frame redirected to a new site without user interaction.
|
||||
data->transitionType = nsINavHistoryService::TRANSITION_EMBED;
|
||||
}
|
||||
|
||||
data->typed = (data->transitionType == nsINavHistoryService::TRANSITION_TYPED) ? 1 : 0;
|
||||
data->hidden =
|
||||
(data->transitionType == nsINavHistoryService::TRANSITION_FRAMED_LINK ||
|
||||
data->transitionType == nsINavHistoryService::TRANSITION_EMBED ||
|
||||
redirected) ? 1 : 0;
|
||||
data->dateTime = PR_Now();
|
||||
data->uri = aURI;
|
||||
|
||||
nsCOMPtr<Step> task(new StartVisitURIStep(data));
|
||||
AppendTask(task);
|
||||
|
||||
nsCOMPtr<nsIObserverService> obsService =
|
||||
mozilla::services::GetObserverService();
|
||||
if (obsService) {
|
||||
obsService->NotifyObservers(aURI, NS_LINK_VISITED_EVENT_TOPIC, nsnull);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
History::RegisterVisitedCallback(nsIURI* aURI,
|
||||
Link* aLink)
|
||||
@ -308,12 +1131,42 @@ History::UnregisterVisitedCallback(nsIURI* aURI,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
History::SetURITitle(nsIURI* aURI, const nsAString& aTitle)
|
||||
{
|
||||
NS_PRECONDITION(aURI, "Must pass a non-null URI!");
|
||||
|
||||
nsNavHistory* history = nsNavHistory::GetHistoryService();
|
||||
PRBool canAdd;
|
||||
nsresult rv = history->CanAddURI(aURI, &canAdd);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (!canAdd) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsAutoPtr<SetTitleData> data(new SetTitleData());
|
||||
data->uri = aURI;
|
||||
|
||||
if (aTitle.IsEmpty()) {
|
||||
data->title.SetIsVoid(PR_TRUE);
|
||||
}
|
||||
else {
|
||||
data->title.Assign(aTitle);
|
||||
}
|
||||
|
||||
nsCOMPtr<Step> task(new StartSetURITitleStep(data));
|
||||
AppendTask(task);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//// nsISupports
|
||||
|
||||
NS_IMPL_ISUPPORTS1(
|
||||
History,
|
||||
IHistory
|
||||
History
|
||||
, IHistory
|
||||
)
|
||||
|
||||
} // namespace places
|
||||
|
@ -46,12 +46,13 @@
|
||||
#include "nsString.h"
|
||||
#include "nsURIHashKey.h"
|
||||
#include "nsTArray.h"
|
||||
#include "nsDeque.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace places {
|
||||
|
||||
#define NS_HISTORYSERVICE_CID \
|
||||
{0x9fc91e65, 0x1475, 0x4353, {0x9b, 0x9a, 0x93, 0xd7, 0x6f, 0x5b, 0xd9, 0xb7}}
|
||||
{0x0937a705, 0x91a6, 0x417a, {0x82, 0x92, 0xb2, 0x2e, 0xb1, 0x0d, 0xa8, 0x6c}}
|
||||
|
||||
class History : public IHistory
|
||||
{
|
||||
@ -69,6 +70,26 @@ public:
|
||||
*/
|
||||
void NotifyVisited(nsIURI *aURI);
|
||||
|
||||
/**
|
||||
* Append a task to the queue for SQL queries that need to happen
|
||||
* atomically.
|
||||
*
|
||||
* @pre aTask is not null
|
||||
*
|
||||
* @param aTask
|
||||
* Task that needs to be completed atomically
|
||||
*/
|
||||
void AppendTask(class Step* aTask);
|
||||
|
||||
/**
|
||||
* Call when all steps of the current running task are finished. Each task
|
||||
* should be responsible for calling this when it is finished (even if there
|
||||
* are errors).
|
||||
*
|
||||
* Do not call this twice for the same visit.
|
||||
*/
|
||||
void CurrentTaskFinished();
|
||||
|
||||
/**
|
||||
* Obtains a pointer to this service.
|
||||
*/
|
||||
@ -83,6 +104,26 @@ public:
|
||||
private:
|
||||
~History();
|
||||
|
||||
/**
|
||||
* Since visits rapidly fire at once, it's very likely to have race
|
||||
* conditions for SQL queries. We often need to see if a row exists
|
||||
* or peek at values, and by the time we have retrieved them they could
|
||||
* be different.
|
||||
*
|
||||
* We guarantee an ordering of our SQL statements so that a set of
|
||||
* callbacks for one visit are guaranteed to be atomic. Each visit consists
|
||||
* of a data structure that sits in this queue.
|
||||
*
|
||||
* The front of the queue always has the current visit we are processing.
|
||||
*/
|
||||
nsDeque mPendingVisits;
|
||||
|
||||
/**
|
||||
* Begins next task at the front of the queue. The task remains in the queue
|
||||
* until it is done and calls CurrentTaskFinished.
|
||||
*/
|
||||
void StartNextTask();
|
||||
|
||||
static History *gService;
|
||||
|
||||
typedef nsTArray<mozilla::dom::Link *> ObserverArray;
|
||||
|
@ -88,11 +88,6 @@
|
||||
|
||||
using namespace mozilla::places;
|
||||
|
||||
// Microsecond timeout for "recent" events such as typed and bookmark following.
|
||||
// If you typed it more than this time ago, it's not recent.
|
||||
// This is 15 minutes m s/m us/s
|
||||
#define RECENT_EVENT_THRESHOLD PRTime((PRInt64)15 * 60 * PR_USEC_PER_SEC)
|
||||
|
||||
// The maximum number of things that we will store in the recent events list
|
||||
// before calling ExpireNonrecentEvents. This number should be big enough so it
|
||||
// is very difficult to get that many unconsumed events (for example, typed but
|
||||
@ -237,21 +232,12 @@ NS_IMPL_CI_INTERFACE_GETTER5(
|
||||
|
||||
namespace {
|
||||
|
||||
static nsresult GetReversedHostname(nsIURI* aURI, nsAString& host);
|
||||
static void GetReversedHostname(const nsString& aForward, nsAString& aReversed);
|
||||
static PRInt64 GetSimpleBookmarksQueryFolder(
|
||||
const nsCOMArray<nsNavHistoryQuery>& aQueries,
|
||||
nsNavHistoryQueryOptions* aOptions);
|
||||
static void ParseSearchTermsFromQueries(const nsCOMArray<nsNavHistoryQuery>& aQueries,
|
||||
nsTArray<nsTArray<nsString>*>* aTerms);
|
||||
|
||||
inline void ReverseString(const nsString& aInput, nsAString& aReversed)
|
||||
{
|
||||
aReversed.Truncate(0);
|
||||
for (PRInt32 i = aInput.Length() - 1; i >= 0; i --)
|
||||
aReversed.Append(aInput[i]);
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
namespace mozilla {
|
||||
@ -909,6 +895,27 @@ nsNavHistory::UpdateSchemaVersion()
|
||||
}
|
||||
|
||||
|
||||
PRUint32
|
||||
nsNavHistory::GetRecentFlags(nsIURI *aURI)
|
||||
{
|
||||
PRUint32 result = 0;
|
||||
nsCAutoString spec;
|
||||
nsresult rv = aURI->GetSpec(spec);
|
||||
NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "Unable to get aURI's spec");
|
||||
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
if (CheckIsRecentEvent(&mRecentTyped, spec))
|
||||
result |= RECENT_TYPED;
|
||||
if (CheckIsRecentEvent(&mRecentLink, spec))
|
||||
result |= RECENT_ACTIVATED;
|
||||
if (CheckIsRecentEvent(&mRecentBookmark, spec))
|
||||
result |= RECENT_BOOKMARKED;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Called after InitDB, this creates our own functions
|
||||
*/
|
||||
@ -1865,6 +1872,9 @@ nsNavHistory::GetUrlIdFor(nsIURI* aURI, PRInt64* aEntryID,
|
||||
// THIS SHOULD BE THE ONLY PLACE NEW moz_places ROWS ARE
|
||||
// CREATED. This allows us to maintain better consistency.
|
||||
//
|
||||
// XXX this functionality is being moved to History.cpp, so
|
||||
// in fact there *are* two places where new pages are added.
|
||||
//
|
||||
// If non-null, the new page ID will be placed into aPageID.
|
||||
|
||||
nsresult
|
||||
@ -2162,6 +2172,29 @@ nsNavHistory::GetNewSessionID()
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
nsNavHistory::NotifyOnVisit(nsIURI* aURI,
|
||||
PRInt64 aVisitID,
|
||||
PRTime aTime,
|
||||
PRInt64 aSessionID,
|
||||
PRInt64 referringVisitID,
|
||||
PRInt32 aTransitionType)
|
||||
{
|
||||
PRUint32 added = 0;
|
||||
NOTIFY_OBSERVERS(mCanNotify, mCacheObservers, mObservers,
|
||||
nsINavHistoryObserver,
|
||||
OnVisit(aURI, aVisitID, aTime, aSessionID,
|
||||
referringVisitID, aTransitionType, &added));
|
||||
}
|
||||
|
||||
void
|
||||
nsNavHistory::NotifyTitleChange(nsIURI* aURI, const nsString& aTitle)
|
||||
{
|
||||
NOTIFY_OBSERVERS(mCanNotify, mCacheObservers, mObservers,
|
||||
nsINavHistoryObserver, OnTitleChanged(aURI, aTitle));
|
||||
}
|
||||
|
||||
|
||||
PRInt32
|
||||
nsNavHistory::GetDaysOfHistory() {
|
||||
PRInt32 daysOfHistory = 0;
|
||||
@ -2866,12 +2899,9 @@ nsNavHistory::AddVisit(nsIURI* aURI, PRTime aTime, nsIURI* aReferringURI,
|
||||
// Notify observers: The hidden detection code must match that in
|
||||
// GetQueryResults to maintain consistency.
|
||||
// FIXME bug 325241: make a way to observe hidden URLs
|
||||
PRUint32 added = 0;
|
||||
if (!hidden) {
|
||||
NOTIFY_OBSERVERS(mCanNotify, mCacheObservers, mObservers,
|
||||
nsINavHistoryObserver,
|
||||
OnVisit(aURI, *aVisitID, aTime, aSessionID,
|
||||
referringVisitID, aTransitionType, &added));
|
||||
NotifyOnVisit(aURI, *aVisitID, aTime, aSessionID, referringVisitID,
|
||||
aTransitionType);
|
||||
}
|
||||
|
||||
// Normally docshell sends the link visited observer notification for us (this
|
||||
@ -7335,7 +7365,6 @@ nsNavHistory::SetPageTitleInternal(nsIURI* aURI, const nsAString& aTitle)
|
||||
rv = mDBSetPlaceTitle->Execute();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// observers (have to check first if it's bookmarked)
|
||||
NOTIFY_OBSERVERS(mCanNotify, mCacheObservers, mObservers,
|
||||
nsINavHistoryObserver, OnTitleChanged(aURI, aTitle));
|
||||
|
||||
@ -7547,52 +7576,6 @@ nsNavHistory::RemoveDuplicateURIs()
|
||||
|
||||
namespace {
|
||||
|
||||
// GetReversedHostname
|
||||
//
|
||||
// This extracts the hostname from the URI and reverses it in the
|
||||
// form that we use (always ending with a "."). So
|
||||
// "http://microsoft.com/" becomes "moc.tfosorcim."
|
||||
//
|
||||
// The idea behind this is that we can create an index over the items in
|
||||
// the reversed host name column, and then query for as much or as little
|
||||
// of the host name as we feel like.
|
||||
//
|
||||
// For example, the query "host >= 'gro.allizom.' AND host < 'gro.allizom/'
|
||||
// Matches all host names ending in '.mozilla.org', including
|
||||
// 'developer.mozilla.org' and just 'mozilla.org' (since we define all
|
||||
// reversed host names to end in a period, even 'mozilla.org' matches).
|
||||
// The important thing is that this operation uses the index. Any substring
|
||||
// calls in a select statement (even if it's for the beginning of a string)
|
||||
// will bypass any indices and will be slow).
|
||||
|
||||
nsresult
|
||||
GetReversedHostname(nsIURI* aURI, nsAString& aRevHost)
|
||||
{
|
||||
nsCString forward8;
|
||||
nsresult rv = aURI->GetHost(forward8);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
// can't do reversing in UTF8, better use 16-bit chars
|
||||
NS_ConvertUTF8toUTF16 forward(forward8);
|
||||
GetReversedHostname(forward, aRevHost);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
// GetReversedHostname
|
||||
//
|
||||
// Same as previous but for strings
|
||||
|
||||
void
|
||||
GetReversedHostname(const nsString& aForward, nsAString& aRevHost)
|
||||
{
|
||||
ReverseString(aForward, aRevHost);
|
||||
aRevHost.Append(PRUnichar('.'));
|
||||
}
|
||||
|
||||
|
||||
// GetSimpleBookmarksQueryFolder
|
||||
//
|
||||
// Determines if this set of queries is a simple bookmarks query for a
|
||||
|
@ -88,6 +88,10 @@
|
||||
#define URI_LENGTH_MAX 65536
|
||||
#define TITLE_LENGTH_MAX 4096
|
||||
|
||||
// Microsecond timeout for "recent" events such as typed and bookmark following.
|
||||
// If you typed it more than this time ago, it's not recent.
|
||||
#define RECENT_EVENT_THRESHOLD PRTime((PRInt64)15 * 60 * PR_USEC_PER_SEC)
|
||||
|
||||
#ifdef MOZ_XUL
|
||||
// Fired after autocomplete feedback has been updated.
|
||||
#define TOPIC_AUTOCOMPLETE_FEEDBACK_UPDATED "places-autocomplete-feedback-updated"
|
||||
@ -112,6 +116,13 @@ namespace places {
|
||||
DB_GET_PAGE_INFO_BY_URL = 0
|
||||
, DB_GET_TAGS = 1
|
||||
, DB_IS_PAGE_VISITED = 2
|
||||
, DB_INSERT_VISIT = 3
|
||||
, DB_RECENT_VISIT_OF_URL = 4
|
||||
, DB_GET_PAGE_VISIT_STATS = 5
|
||||
, DB_UPDATE_PAGE_VISIT_STATS = 6
|
||||
, DB_ADD_NEW_PAGE = 7
|
||||
, DB_GET_URL_PAGE_INFO = 8
|
||||
, DB_SET_PLACE_TITLE = 9
|
||||
};
|
||||
|
||||
} // namespace places
|
||||
@ -394,6 +405,19 @@ public:
|
||||
*/
|
||||
bool canNotify() { return mCanNotify; }
|
||||
|
||||
enum RecentEventFlags {
|
||||
RECENT_TYPED = 1 << 0, // User typed in URL recently
|
||||
RECENT_ACTIVATED = 1 << 1, // User tapped URL link recently
|
||||
RECENT_BOOKMARKED = 1 << 2 // User bookmarked URL recently
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns any recent activity done with a URL.
|
||||
* @return Any recent events associated with this URI. Each bit is set
|
||||
* according to RecentEventFlags enum values.
|
||||
*/
|
||||
PRUint32 GetRecentFlags(nsIURI *aURI);
|
||||
|
||||
mozIStorageStatement* GetStatementById(
|
||||
enum mozilla::places::HistoryStatementId aStatementId
|
||||
)
|
||||
@ -406,10 +430,41 @@ public:
|
||||
return mDBGetTags;
|
||||
case DB_IS_PAGE_VISITED:
|
||||
return mDBIsPageVisited;
|
||||
case DB_INSERT_VISIT:
|
||||
return mDBInsertVisit;
|
||||
case DB_RECENT_VISIT_OF_URL:
|
||||
return mDBRecentVisitOfURL;
|
||||
case DB_GET_PAGE_VISIT_STATS:
|
||||
return mDBGetPageVisitStats;
|
||||
case DB_UPDATE_PAGE_VISIT_STATS:
|
||||
return mDBUpdatePageVisitStats;
|
||||
case DB_ADD_NEW_PAGE:
|
||||
return mDBAddNewPage;
|
||||
case DB_GET_URL_PAGE_INFO:
|
||||
return mDBGetURLPageInfo;
|
||||
case DB_SET_PLACE_TITLE:
|
||||
return mDBSetPlaceTitle;
|
||||
}
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
PRInt64 GetNewSessionID();
|
||||
|
||||
/**
|
||||
* Fires onVisit event to nsINavHistoryService observers
|
||||
*/
|
||||
void NotifyOnVisit(nsIURI* aURI,
|
||||
PRInt64 aVisitID,
|
||||
PRTime aTime,
|
||||
PRInt64 aSessionID,
|
||||
PRInt64 referringVisitID,
|
||||
PRInt32 aTransitionType);
|
||||
|
||||
/**
|
||||
* Fires onTitleChanged event to nsINavHistoryService observers
|
||||
*/
|
||||
void NotifyTitleChange(nsIURI* aURI, const nsString& title);
|
||||
|
||||
private:
|
||||
~nsNavHistory();
|
||||
|
||||
@ -687,7 +742,6 @@ protected:
|
||||
|
||||
// Sessions tracking.
|
||||
PRInt64 mLastSessionID;
|
||||
PRInt64 GetNewSessionID();
|
||||
|
||||
#ifdef MOZ_XUL
|
||||
// AutoComplete stuff
|
||||
|
@ -47,6 +47,8 @@ include $(topsrcdir)/config/rules.mk
|
||||
|
||||
_BROWSER_FILES = \
|
||||
browser_bug399606.js \
|
||||
browser_visituri.js \
|
||||
browser_settitle.js \
|
||||
$(NULL)
|
||||
|
||||
# These are files that need to be loaded via the HTTP proxy server
|
||||
@ -58,6 +60,12 @@ _HTTP_FILES = \
|
||||
bug_399606/399606-window.location.href.html \
|
||||
bug_399606/399606-window.location.html \
|
||||
bug_399606/399606-history.go-0.html \
|
||||
visituri/begin.html \
|
||||
visituri/redirect_twice.sjs \
|
||||
visituri/redirect_once.sjs \
|
||||
visituri/final.html \
|
||||
settitle/title1.html \
|
||||
settitle/title2.html \
|
||||
$(NULL)
|
||||
|
||||
libs:: $(_BROWSER_FILES)
|
||||
|
@ -47,6 +47,9 @@
|
||||
#include "nsINavHistoryService.h"
|
||||
#include "nsIObserverService.h"
|
||||
#include "mozilla/IHistory.h"
|
||||
#include "mozIStorageConnection.h"
|
||||
#include "mozIStorageStatement.h"
|
||||
#include "nsPIPlacesDatabase.h"
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
@ -117,6 +120,21 @@ addURI(nsIURI* aURI)
|
||||
do_check_success(rv);
|
||||
}
|
||||
|
||||
struct PlaceRecord
|
||||
{
|
||||
PRInt64 id;
|
||||
PRInt32 hidden;
|
||||
PRInt32 typed;
|
||||
PRInt32 visitCount;
|
||||
};
|
||||
|
||||
struct VisitRecord
|
||||
{
|
||||
PRInt64 id;
|
||||
PRInt64 lastVisitId;
|
||||
PRInt32 transitionType;
|
||||
};
|
||||
|
||||
already_AddRefed<IHistory>
|
||||
do_get_IHistory()
|
||||
{
|
||||
@ -124,3 +142,107 @@ do_get_IHistory()
|
||||
do_check_true(history);
|
||||
return history.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<nsINavHistoryService>
|
||||
do_get_NavHistory()
|
||||
{
|
||||
nsCOMPtr<nsINavHistoryService> serv =
|
||||
do_GetService(NS_NAVHISTORYSERVICE_CONTRACTID);
|
||||
do_check_true(serv);
|
||||
return serv.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<mozIStorageConnection>
|
||||
do_get_db()
|
||||
{
|
||||
nsCOMPtr<nsINavHistoryService> history = do_get_NavHistory();
|
||||
nsCOMPtr<nsPIPlacesDatabase> database = do_QueryInterface(history);
|
||||
do_check_true(database);
|
||||
|
||||
mozIStorageConnection* dbConn;
|
||||
nsresult rv = database->GetDBConnection(&dbConn);
|
||||
do_check_success(rv);
|
||||
return dbConn;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the place record from the database.
|
||||
*
|
||||
* @param aURI The unique URI of the place we are looking up
|
||||
* @param result Out parameter where the result is stored
|
||||
*/
|
||||
void
|
||||
do_get_place(nsIURI* aURI, PlaceRecord& result)
|
||||
{
|
||||
nsCOMPtr<mozIStorageConnection> dbConn = do_get_db();
|
||||
nsCOMPtr<mozIStorageStatement> stmt;
|
||||
|
||||
nsCString spec;
|
||||
nsresult rv = aURI->GetSpec(spec);
|
||||
do_check_success(rv);
|
||||
|
||||
rv = dbConn->CreateStatement(NS_LITERAL_CSTRING(
|
||||
"SELECT id, hidden, typed, visit_count FROM moz_places_temp "
|
||||
"WHERE url=?1 "
|
||||
"UNION ALL "
|
||||
"SELECT id, hidden, typed, visit_count FROM moz_places "
|
||||
"WHERE url=?1 "
|
||||
"LIMIT 1"
|
||||
), getter_AddRefs(stmt));
|
||||
do_check_success(rv);
|
||||
|
||||
rv = stmt->BindUTF8StringParameter(0, spec);
|
||||
do_check_success(rv);
|
||||
|
||||
PRBool hasResults;
|
||||
rv = stmt->ExecuteStep(&hasResults);
|
||||
do_check_true(hasResults);
|
||||
do_check_success(rv);
|
||||
|
||||
rv = stmt->GetInt64(0, &result.id);
|
||||
do_check_success(rv);
|
||||
rv = stmt->GetInt32(1, &result.hidden);
|
||||
do_check_success(rv);
|
||||
rv = stmt->GetInt32(2, &result.typed);
|
||||
do_check_success(rv);
|
||||
rv = stmt->GetInt32(3, &result.visitCount);
|
||||
do_check_success(rv);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the most recent visit to a place.
|
||||
*
|
||||
* @param placeID ID from the moz_places table
|
||||
* @param result Out parameter where visit is stored
|
||||
*/
|
||||
void
|
||||
do_get_lastVisit(PRInt64 placeId, VisitRecord& result)
|
||||
{
|
||||
nsCOMPtr<mozIStorageConnection> dbConn = do_get_db();
|
||||
nsCOMPtr<mozIStorageStatement> stmt;
|
||||
|
||||
nsresult rv = dbConn->CreateStatement(NS_LITERAL_CSTRING(
|
||||
"SELECT id, from_visit, visit_type FROM moz_historyvisits_temp "
|
||||
"WHERE place_id=?1 "
|
||||
"UNION ALL "
|
||||
"SELECT id, from_visit, visit_type FROM moz_historyvisits "
|
||||
"WHERE place_id=?1 "
|
||||
"LIMIT 1"
|
||||
), getter_AddRefs(stmt));
|
||||
do_check_success(rv);
|
||||
|
||||
rv = stmt->BindInt64Parameter(0, placeId);
|
||||
do_check_success(rv);
|
||||
|
||||
PRBool hasResults;
|
||||
rv = stmt->ExecuteStep(&hasResults);
|
||||
do_check_true(hasResults);
|
||||
do_check_success(rv);
|
||||
|
||||
rv = stmt->GetInt64(0, &result.id);
|
||||
do_check_success(rv);
|
||||
rv = stmt->GetInt64(1, &result.lastVisitId);
|
||||
do_check_success(rv);
|
||||
rv = stmt->GetInt32(2, &result.transitionType);
|
||||
do_check_success(rv);
|
||||
}
|
||||
|
@ -38,6 +38,7 @@
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "places_test_harness.h"
|
||||
#include "nsIBrowserHistory.h"
|
||||
|
||||
#include "mock_Link.h"
|
||||
using namespace mozilla::dom;
|
||||
@ -76,6 +77,53 @@ new_test_uri()
|
||||
return testURI.forget();
|
||||
}
|
||||
|
||||
class VisitURIObserver : public nsIObserver
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
VisitURIObserver(int aExpectedVisits = 1) :
|
||||
mVisits(0),
|
||||
mExpectedVisits(aExpectedVisits)
|
||||
{
|
||||
nsCOMPtr<nsIObserverService> observerService =
|
||||
do_GetService(NS_OBSERVERSERVICE_CONTRACTID);
|
||||
do_check_true(observerService);
|
||||
(void)observerService->AddObserver(this,
|
||||
"uri-visit-saved",
|
||||
PR_FALSE);
|
||||
}
|
||||
|
||||
void WaitForNotification()
|
||||
{
|
||||
while (mVisits < mExpectedVisits) {
|
||||
(void)NS_ProcessNextEvent();
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHOD Observe(nsISupports* aSubject,
|
||||
const char* aTopic,
|
||||
const PRUnichar* aData)
|
||||
{
|
||||
mVisits++;
|
||||
|
||||
if (mVisits == mExpectedVisits) {
|
||||
nsCOMPtr<nsIObserverService> observerService =
|
||||
do_GetService(NS_OBSERVERSERVICE_CONTRACTID);
|
||||
(void)observerService->RemoveObserver(this, "uri-visit-saved");
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
private:
|
||||
int mVisits;
|
||||
int mExpectedVisits;
|
||||
};
|
||||
NS_IMPL_ISUPPORTS1(
|
||||
VisitURIObserver,
|
||||
nsIObserver
|
||||
)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//// Test Functions
|
||||
|
||||
@ -363,6 +411,145 @@ test_observer_topic_dispatched()
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
void
|
||||
test_visituri_inserts()
|
||||
{
|
||||
nsCOMPtr<IHistory> history(do_get_IHistory());
|
||||
nsCOMPtr<nsIURI> lastURI(new_test_uri());
|
||||
nsCOMPtr<nsIURI> visitedURI(new_test_uri());
|
||||
|
||||
history->VisitURI(visitedURI, lastURI, mozilla::IHistory::TOP_LEVEL);
|
||||
|
||||
nsCOMPtr<VisitURIObserver> finisher = new VisitURIObserver();
|
||||
finisher->WaitForNotification();
|
||||
|
||||
PlaceRecord place;
|
||||
do_get_place(visitedURI, place);
|
||||
|
||||
do_check_true(place.id > 0);
|
||||
do_check_false(place.hidden);
|
||||
do_check_false(place.typed);
|
||||
do_check_true(place.visitCount == 1);
|
||||
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
void
|
||||
test_visituri_updates()
|
||||
{
|
||||
nsCOMPtr<IHistory> history(do_get_IHistory());
|
||||
nsCOMPtr<nsIURI> lastURI(new_test_uri());
|
||||
nsCOMPtr<nsIURI> visitedURI(new_test_uri());
|
||||
nsCOMPtr<VisitURIObserver> finisher;
|
||||
|
||||
history->VisitURI(visitedURI, lastURI, mozilla::IHistory::TOP_LEVEL);
|
||||
finisher = new VisitURIObserver();
|
||||
finisher->WaitForNotification();
|
||||
|
||||
history->VisitURI(visitedURI, lastURI, mozilla::IHistory::TOP_LEVEL);
|
||||
finisher = new VisitURIObserver();
|
||||
finisher->WaitForNotification();
|
||||
|
||||
PlaceRecord place;
|
||||
do_get_place(visitedURI, place);
|
||||
|
||||
do_check_true(place.visitCount == 2);
|
||||
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
void
|
||||
test_visituri_preserves_shown_and_typed()
|
||||
{
|
||||
nsCOMPtr<IHistory> history(do_get_IHistory());
|
||||
nsCOMPtr<nsIURI> lastURI(new_test_uri());
|
||||
nsCOMPtr<nsIURI> visitedURI(new_test_uri());
|
||||
|
||||
history->VisitURI(visitedURI, lastURI, mozilla::IHistory::TOP_LEVEL);
|
||||
// this simulates the uri visit happening in a frame. Normally frame
|
||||
// transitions would be hidden unless it was previously loaded top-level
|
||||
history->VisitURI(visitedURI, lastURI, 0);
|
||||
|
||||
nsCOMPtr<VisitURIObserver> finisher = new VisitURIObserver(2);
|
||||
finisher->WaitForNotification();
|
||||
|
||||
PlaceRecord place;
|
||||
do_get_place(visitedURI, place);
|
||||
do_check_false(place.hidden);
|
||||
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
void
|
||||
test_visituri_creates_visit()
|
||||
{
|
||||
nsCOMPtr<IHistory> history(do_get_IHistory());
|
||||
nsCOMPtr<nsIURI> lastURI(new_test_uri());
|
||||
nsCOMPtr<nsIURI> visitedURI(new_test_uri());
|
||||
|
||||
history->VisitURI(visitedURI, lastURI, mozilla::IHistory::TOP_LEVEL);
|
||||
nsCOMPtr<VisitURIObserver> finisher = new VisitURIObserver();
|
||||
finisher->WaitForNotification();
|
||||
|
||||
PlaceRecord place;
|
||||
VisitRecord visit;
|
||||
do_get_place(visitedURI, place);
|
||||
do_get_lastVisit(place.id, visit);
|
||||
|
||||
do_check_true(visit.id > 0);
|
||||
do_check_true(visit.lastVisitId == 0);
|
||||
do_check_true(visit.transitionType == nsINavHistoryService::TRANSITION_LINK);
|
||||
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
void
|
||||
test_visituri_transition_typed()
|
||||
{
|
||||
nsCOMPtr<nsINavHistoryService> navHistory = do_get_NavHistory();
|
||||
nsCOMPtr<nsIBrowserHistory> browserHistory = do_QueryInterface(navHistory);
|
||||
nsCOMPtr<IHistory> history(do_get_IHistory());
|
||||
nsCOMPtr<nsIURI> lastURI(new_test_uri());
|
||||
nsCOMPtr<nsIURI> visitedURI(new_test_uri());
|
||||
|
||||
browserHistory->MarkPageAsTyped(visitedURI);
|
||||
history->VisitURI(visitedURI, lastURI, mozilla::IHistory::TOP_LEVEL);
|
||||
nsCOMPtr<VisitURIObserver> finisher = new VisitURIObserver();
|
||||
finisher->WaitForNotification();
|
||||
|
||||
PlaceRecord place;
|
||||
VisitRecord visit;
|
||||
do_get_place(visitedURI, place);
|
||||
do_get_lastVisit(place.id, visit);
|
||||
|
||||
do_check_true(visit.transitionType == nsINavHistoryService::TRANSITION_TYPED);
|
||||
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
void
|
||||
test_visituri_transition_embed()
|
||||
{
|
||||
nsCOMPtr<nsINavHistoryService> navHistory = do_get_NavHistory();
|
||||
nsCOMPtr<nsIBrowserHistory> browserHistory = do_QueryInterface(navHistory);
|
||||
nsCOMPtr<IHistory> history(do_get_IHistory());
|
||||
nsCOMPtr<nsIURI> lastURI(new_test_uri());
|
||||
nsCOMPtr<nsIURI> visitedURI(new_test_uri());
|
||||
|
||||
history->VisitURI(visitedURI, lastURI, 0);
|
||||
nsCOMPtr<VisitURIObserver> finisher = new VisitURIObserver();
|
||||
finisher->WaitForNotification();
|
||||
|
||||
PlaceRecord place;
|
||||
VisitRecord visit;
|
||||
do_get_place(visitedURI, place);
|
||||
do_get_lastVisit(place.id, visit);
|
||||
|
||||
do_check_true(visit.transitionType == nsINavHistoryService::TRANSITION_EMBED);
|
||||
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//// Test Harness
|
||||
|
||||
@ -378,6 +565,12 @@ Test gTests[] = {
|
||||
TEST(test_new_visit_notifies_waiting_Link),
|
||||
TEST(test_RegisterVisitedCallback_returns_before_notifying),
|
||||
TEST(test_observer_topic_dispatched),
|
||||
TEST(test_visituri_inserts),
|
||||
TEST(test_visituri_updates),
|
||||
TEST(test_visituri_preserves_shown_and_typed),
|
||||
TEST(test_visituri_creates_visit),
|
||||
TEST(test_visituri_transition_typed),
|
||||
TEST(test_visituri_transition_embed),
|
||||
};
|
||||
|
||||
const char* file = __FILE__;
|
||||
|
@ -53,10 +53,10 @@ WindowDraggingElement.prototype = {
|
||||
"radiogroup", "deck", "scrollbox", "arrowscrollbox", "tabs"],
|
||||
shouldDrag: function(aEvent) {
|
||||
if (aEvent.button != 0 ||
|
||||
this._window.fullScreen ||
|
||||
!this.mouseDownCheck.call(this._elem, aEvent) ||
|
||||
aEvent.getPreventDefault())
|
||||
return false;
|
||||
this._window.fullScreen ||
|
||||
!this.mouseDownCheck.call(this._elem, aEvent) ||
|
||||
aEvent.getPreventDefault())
|
||||
return false;
|
||||
|
||||
// Maybe we have been removed from the document
|
||||
if (!this._elem._alive)
|
||||
@ -80,9 +80,8 @@ WindowDraggingElement.prototype = {
|
||||
},
|
||||
handleEvent: function(aEvent) {
|
||||
#ifdef XP_WIN
|
||||
if (this.shouldDrag(aEvent)) {
|
||||
aEvent.preventDefault();
|
||||
}
|
||||
if (this.shouldDrag(aEvent))
|
||||
aEvent.preventDefault();
|
||||
#else
|
||||
switch (aEvent.type) {
|
||||
case "mousedown":
|
||||
|
@ -165,8 +165,9 @@
|
||||
if (!this._draggableStarted) {
|
||||
this._draggableStarted = true;
|
||||
try {
|
||||
Components.utils.import("resource://gre/modules/WindowDraggingUtils.jsm");
|
||||
new WindowDraggingElement(this, window);
|
||||
let tmp = {};
|
||||
Components.utils.import("resource://gre/modules/WindowDraggingUtils.jsm", tmp);
|
||||
new tmp.WindowDraggingElement(this, window);
|
||||
} catch (e) {}
|
||||
}
|
||||
</constructor>
|
||||
@ -270,8 +271,9 @@
|
||||
if (!this._draggableStarted) {
|
||||
this._draggableStarted = true;
|
||||
try {
|
||||
Components.utils.import("resource://gre/modules/WindowDraggingUtils.jsm");
|
||||
new WindowDraggingElement(this, window);
|
||||
let tmp = {};
|
||||
Components.utils.import("resource://gre/modules/WindowDraggingUtils.jsm", tmp);
|
||||
new tmp.WindowDraggingElement(this, window);
|
||||
} catch (e) {}
|
||||
}
|
||||
</constructor>
|
||||
|
@ -445,8 +445,9 @@
|
||||
if (!this._draggableStarted) {
|
||||
this._draggableStarted = true;
|
||||
try {
|
||||
Components.utils.import("resource://gre/modules/WindowDraggingUtils.jsm");
|
||||
let draggableThis = new WindowDraggingElement(this, window);
|
||||
let tmp = {};
|
||||
Components.utils.import("resource://gre/modules/WindowDraggingUtils.jsm", tmp);
|
||||
let draggableThis = new tmp.WindowDraggingElement(this, window);
|
||||
draggableThis.mouseDownCheck = function(e) {
|
||||
// Don't move while customizing.
|
||||
return !this.parentNode.customizing;
|
||||
|
@ -1,58 +1,68 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
/**
|
||||
* Tests the Preferences button for addons in list view
|
||||
*/
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
var addonPrefsURI = TESTROOT + "addon_prefs.xul";
|
||||
|
||||
var gProvider = new MockProvider();
|
||||
gProvider.createAddons([{
|
||||
id: "test1@tests.mozilla.org",
|
||||
name: "Test add-on 1",
|
||||
description: "foo"
|
||||
},
|
||||
{
|
||||
id: "test2@tests.mozilla.org",
|
||||
name: "Test add-on 2",
|
||||
description: "bar",
|
||||
optionsURL: addonPrefsURI
|
||||
}]);
|
||||
|
||||
open_manager(null, function(aWindow) {
|
||||
var addonList = aWindow.document.getElementById("addon-list");
|
||||
var addonItem = addonList.childNodes[0];
|
||||
var prefsBtn = aWindow.document.getAnonymousElementByAttribute(addonItem,
|
||||
"anonid",
|
||||
"preferences-btn");
|
||||
is(prefsBtn.hidden, true, "Prefs button should be hidden for addon with no optionsURL set")
|
||||
|
||||
addonItem = addonList.childNodes[1];
|
||||
prefsBtn = aWindow.document.getAnonymousElementByAttribute(addonItem,
|
||||
"anonid",
|
||||
"preferences-btn");
|
||||
is(prefsBtn.hidden, false, "Prefs button should be shown for addon with a optionsURL set")
|
||||
|
||||
Services.ww.registerNotification(function(aSubject, aTopic, aData) {
|
||||
if (aTopic == "domwindowclosed") {
|
||||
Services.ww.unregisterNotification(arguments.callee);
|
||||
} else if (aTopic == "domwindowopened") {
|
||||
let win = aSubject.QueryInterface(Ci.nsIDOMEventTarget);
|
||||
win.documentURI, addonPrefsURI, "The correct addon pref window should open"
|
||||
waitForFocus(function() {
|
||||
win.close();
|
||||
aWindow.close();
|
||||
finish();
|
||||
}, win);
|
||||
}
|
||||
});
|
||||
|
||||
EventUtils.synthesizeMouse(prefsBtn, 2, 2, { }, aWindow);
|
||||
});
|
||||
|
||||
}
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
/**
|
||||
* Tests the Preferences button for addons in list view
|
||||
*/
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
var addonPrefsURI = TESTROOT + "addon_prefs.xul";
|
||||
|
||||
var gProvider = new MockProvider();
|
||||
gProvider.createAddons([{
|
||||
id: "test1@tests.mozilla.org",
|
||||
name: "Test add-on 1",
|
||||
description: "foo"
|
||||
},
|
||||
{
|
||||
id: "test2@tests.mozilla.org",
|
||||
name: "Test add-on 2",
|
||||
description: "bar",
|
||||
optionsURL: addonPrefsURI
|
||||
}]);
|
||||
|
||||
open_manager(null, function(aWindow) {
|
||||
var addonList = aWindow.document.getElementById("addon-list");
|
||||
for (var i = 0; i < addonList.childNodes.length; i++) {
|
||||
var addonItem = addonList.childNodes[i];
|
||||
if (addonItem.hasAttribute("name") &&
|
||||
addonItem.getAttribute("name") == "Test add-on 1")
|
||||
break;
|
||||
}
|
||||
var prefsBtn = aWindow.document.getAnonymousElementByAttribute(addonItem,
|
||||
"anonid",
|
||||
"preferences-btn");
|
||||
is(prefsBtn.hidden, true, "Prefs button should be hidden for addon with no optionsURL set")
|
||||
|
||||
for (i = 0; i < addonList.childNodes.length; i++) {
|
||||
addonItem = addonList.childNodes[i];
|
||||
if (addonItem.hasAttribute("name") &&
|
||||
addonItem.getAttribute("name") == "Test add-on 2")
|
||||
break;
|
||||
}
|
||||
prefsBtn = aWindow.document.getAnonymousElementByAttribute(addonItem,
|
||||
"anonid",
|
||||
"preferences-btn");
|
||||
is(prefsBtn.hidden, false, "Prefs button should be shown for addon with a optionsURL set")
|
||||
|
||||
Services.ww.registerNotification(function(aSubject, aTopic, aData) {
|
||||
if (aTopic == "domwindowclosed") {
|
||||
Services.ww.unregisterNotification(arguments.callee);
|
||||
} else if (aTopic == "domwindowopened") {
|
||||
let win = aSubject.QueryInterface(Ci.nsIDOMEventTarget);
|
||||
win.documentURI, addonPrefsURI, "The correct addon pref window should open"
|
||||
waitForFocus(function() {
|
||||
win.close();
|
||||
aWindow.close();
|
||||
finish();
|
||||
}, win);
|
||||
}
|
||||
});
|
||||
|
||||
EventUtils.synthesizeMouse(prefsBtn, 2, 2, { }, aWindow);
|
||||
});
|
||||
|
||||
}
|
||||
|
@ -83,6 +83,7 @@ jmethodID AndroidLocation::jGetTimeMethod = 0;
|
||||
jclass AndroidGeckoSurfaceView::jGeckoSurfaceViewClass = 0;
|
||||
jmethodID AndroidGeckoSurfaceView::jBeginDrawingMethod = 0;
|
||||
jmethodID AndroidGeckoSurfaceView::jEndDrawingMethod = 0;
|
||||
jmethodID AndroidGeckoSurfaceView::jDraw2DMethod = 0;
|
||||
jmethodID AndroidGeckoSurfaceView::jGetSoftwareDrawBufferMethod = 0;
|
||||
jmethodID AndroidGeckoSurfaceView::jGetHolderMethod = 0;
|
||||
|
||||
@ -147,6 +148,7 @@ AndroidGeckoSurfaceView::InitGeckoSurfaceViewClass(JNIEnv *jEnv)
|
||||
jBeginDrawingMethod = getMethod("beginDrawing", "()I");
|
||||
jGetSoftwareDrawBufferMethod = getMethod("getSoftwareDrawBuffer", "()Ljava/nio/ByteBuffer;");
|
||||
jEndDrawingMethod = getMethod("endDrawing", "()V");
|
||||
jDraw2DMethod = getMethod("draw2D", "(Ljava/nio/ByteBuffer;)V");
|
||||
jGetHolderMethod = getMethod("getHolder", "()Landroid/view/SurfaceHolder;");
|
||||
}
|
||||
|
||||
@ -361,23 +363,16 @@ AndroidGeckoSurfaceView::EndDrawing()
|
||||
JNI()->CallVoidMethod(wrapped_obj, jEndDrawingMethod);
|
||||
}
|
||||
|
||||
unsigned char *
|
||||
AndroidGeckoSurfaceView::GetSoftwareDrawBuffer(int *cap)
|
||||
void
|
||||
AndroidGeckoSurfaceView::Draw2D(jobject buffer)
|
||||
{
|
||||
jobject buf = JNI()->CallObjectMethod(wrapped_obj, jGetSoftwareDrawBufferMethod);
|
||||
if (!buf)
|
||||
return nsnull;
|
||||
JNI()->CallVoidMethod(wrapped_obj, jDraw2DMethod, buffer);
|
||||
}
|
||||
|
||||
void *bp = JNI()->GetDirectBufferAddress(buf);
|
||||
jlong blen = JNI()->GetDirectBufferCapacity(buf);
|
||||
|
||||
if (!bp || blen == -1)
|
||||
return nsnull;
|
||||
|
||||
if (cap)
|
||||
*cap = blen;
|
||||
|
||||
return (unsigned char*) bp;
|
||||
jobject
|
||||
AndroidGeckoSurfaceView::GetSoftwareDrawBuffer()
|
||||
{
|
||||
return JNI()->CallObjectMethod(wrapped_obj, jGetSoftwareDrawBufferMethod);
|
||||
}
|
||||
|
||||
jobject
|
||||
|
@ -163,13 +163,13 @@ public:
|
||||
|
||||
enum {
|
||||
DRAW_ERROR = 0,
|
||||
DRAW_GLES_2 = 1,
|
||||
DRAW_SOFTWARE = 2
|
||||
DRAW_GLES_2 = 1
|
||||
};
|
||||
|
||||
int BeginDrawing();
|
||||
unsigned char *GetSoftwareDrawBuffer(int *cap);
|
||||
jobject GetSoftwareDrawBuffer();
|
||||
void EndDrawing();
|
||||
void Draw2D(jobject buffer);
|
||||
|
||||
// must have a JNI local frame when calling this,
|
||||
// and you'd better know what you're doing
|
||||
@ -179,6 +179,7 @@ protected:
|
||||
static jclass jGeckoSurfaceViewClass;
|
||||
static jmethodID jBeginDrawingMethod;
|
||||
static jmethodID jEndDrawingMethod;
|
||||
static jmethodID jDraw2DMethod;
|
||||
static jmethodID jGetSoftwareDrawBufferMethod;
|
||||
static jmethodID jGetHolderMethod;
|
||||
};
|
||||
|
@ -584,8 +584,7 @@ nsWindow::OnGlobalAndroidEvent(AndroidGeckoEvent *ae)
|
||||
int nh = ae->P0().y;
|
||||
|
||||
if (nw == gAndroidBounds.width &&
|
||||
nh == gAndroidBounds.height)
|
||||
{
|
||||
nh == gAndroidBounds.height) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -687,12 +686,12 @@ nsWindow::DrawTo(gfxASurface *targetSurface)
|
||||
if (coveringChildIndex == -1) {
|
||||
ALOG("nsWindow[%p]::DrawTo no covering child, drawing this", (void*) this);
|
||||
|
||||
nsPaintEvent event(PR_TRUE, NS_PAINT, this);
|
||||
event.region = boundsRect;
|
||||
switch (GetLayerManager()->GetBackendType()) {
|
||||
case LayerManager::LAYERS_BASIC: {
|
||||
nsRefPtr<gfxContext> ctx = new gfxContext(targetSurface);
|
||||
|
||||
nsPaintEvent event(PR_TRUE, NS_PAINT, this);
|
||||
event.region = boundsRect;
|
||||
{
|
||||
AutoLayerManagerSetup setupLayerManager(this, ctx);
|
||||
status = DispatchEvent(&event);
|
||||
@ -707,19 +706,16 @@ nsWindow::DrawTo(gfxASurface *targetSurface)
|
||||
|
||||
// XXX if we got an ignore for the parent, do we still want to draw the children?
|
||||
// We don't really have a good way not to...
|
||||
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case LayerManager::LAYERS_OPENGL: {
|
||||
static_cast<mozilla::layers::LayerManagerOGL*>(GetLayerManager())->
|
||||
SetClippingRegion(nsIntRegion(boundsRect));
|
||||
|
||||
nsPaintEvent event(PR_TRUE, NS_PAINT, this);
|
||||
event.region = boundsRect;
|
||||
status = DispatchEvent(&event);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
NS_ERROR("Invalid layer manager");
|
||||
@ -737,8 +733,7 @@ nsWindow::DrawTo(gfxASurface *targetSurface)
|
||||
|
||||
for (PRUint32 i = coveringChildIndex; i < mChildren.Length(); ++i) {
|
||||
if (mChildren[i]->mBounds.IsEmpty() ||
|
||||
!mChildren[i]->mBounds.Intersects(boundsRect))
|
||||
{
|
||||
!mChildren[i]->mBounds.Intersects(boundsRect)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -759,20 +754,6 @@ nsWindow::DrawTo(gfxASurface *targetSurface)
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
static int
|
||||
next_power_of_two(int v)
|
||||
{
|
||||
v--;
|
||||
v |= v >> 1;
|
||||
v |= v >> 2;
|
||||
v |= v >> 4;
|
||||
v |= v >> 8;
|
||||
v |= v >> 16;
|
||||
v++;
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
void
|
||||
nsWindow::OnDraw(AndroidGeckoEvent *ae)
|
||||
{
|
||||
@ -798,43 +779,36 @@ nsWindow::OnDraw(AndroidGeckoEvent *ae)
|
||||
return;
|
||||
}
|
||||
|
||||
int drawType = sview.BeginDrawing();
|
||||
|
||||
if (drawType == AndroidGeckoSurfaceView::DRAW_ERROR) {
|
||||
ALOG("##### BeginDrawing failed!");
|
||||
return;
|
||||
}
|
||||
|
||||
if (GetLayerManager()->GetBackendType() == LayerManager::LAYERS_BASIC) {
|
||||
drawType = AndroidGeckoSurfaceView::DRAW_SOFTWARE;
|
||||
} else {
|
||||
drawType = AndroidGeckoSurfaceView::DRAW_GLES_2;
|
||||
}
|
||||
jobject bytebuf = sview.GetSoftwareDrawBuffer();
|
||||
if (!bytebuf) {
|
||||
ALOG("no buffer to draw into - skipping draw");
|
||||
return;
|
||||
}
|
||||
|
||||
if (drawType == AndroidGeckoSurfaceView::DRAW_SOFTWARE) {
|
||||
int bufCap;
|
||||
unsigned char *buf = sview.GetSoftwareDrawBuffer(&bufCap);
|
||||
if (!buf || bufCap != mBounds.width * mBounds.height * 4) {
|
||||
ALOG("### Software drawing, but too small a buffer %d expected %d (or no buffer %p)!", bufCap, mBounds.width * mBounds.height * 4, (void*)buf);
|
||||
sview.EndDrawing();
|
||||
void *buf = AndroidBridge::JNI()->GetDirectBufferAddress(bytebuf);
|
||||
int cap = AndroidBridge::JNI()->GetDirectBufferCapacity(bytebuf);
|
||||
if (!buf || cap < (mBounds.width * mBounds.height * 2)) {
|
||||
ALOG("### Software drawing, but too small a buffer %d expected %d (or no buffer %p)!", cap, mBounds.width * mBounds.height * 2, buf);
|
||||
return;
|
||||
}
|
||||
|
||||
nsRefPtr<gfxImageSurface> targetSurface =
|
||||
new gfxImageSurface(buf,
|
||||
new gfxImageSurface((unsigned char *)buf,
|
||||
gfxIntSize(mBounds.width, mBounds.height),
|
||||
mBounds.width * 4,
|
||||
gfxASurface::ImageFormatARGB32);
|
||||
mBounds.width * 2,
|
||||
gfxASurface::ImageFormatRGB16_565);
|
||||
|
||||
DrawTo(targetSurface);
|
||||
sview.Draw2D(bytebuf);
|
||||
} else {
|
||||
int drawType = sview.BeginDrawing();
|
||||
|
||||
// need to swap B and R channels, to get ABGR instead of ARGB
|
||||
unsigned int *ibuf = (unsigned int*) buf;
|
||||
unsigned int *ibufMax = ibuf + mBounds.width * mBounds.height;
|
||||
while (ibuf < ibufMax) {
|
||||
*ibuf++ = (*ibuf & 0xff00ff00) | ((*ibuf & 0x00ff0000) >> 16) | ((*ibuf & 0x000000ff) << 16);
|
||||
if (drawType == AndroidGeckoSurfaceView::DRAW_ERROR) {
|
||||
ALOG("##### BeginDrawing failed!");
|
||||
return;
|
||||
}
|
||||
} else if (drawType == AndroidGeckoSurfaceView::DRAW_GLES_2) {
|
||||
|
||||
NS_ASSERTION(sGLContext, "Drawing with GLES without a GL context?");
|
||||
|
||||
sGLContext->fClear(LOCAL_GL_COLOR_BUFFER_BIT | LOCAL_GL_DEPTH_BUFFER_BIT);
|
||||
@ -843,9 +817,8 @@ nsWindow::OnDraw(AndroidGeckoEvent *ae)
|
||||
|
||||
if (sGLContext)
|
||||
sGLContext->SwapBuffers();
|
||||
sview.EndDrawing();
|
||||
}
|
||||
|
||||
sview.EndDrawing();
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -113,6 +113,7 @@ LOCAL_INCLUDES = \
|
||||
-I$(srcdir)/../threads/_xpidlgen \
|
||||
-I$(srcdir)/../proxy/src \
|
||||
-I$(srcdir)/../reflect/xptinfo/src \
|
||||
-I$(srcdir)/../../docshell/base \
|
||||
$(NULL)
|
||||
|
||||
EXPORTS_NAMESPACES = mozilla
|
||||
|
@ -5,3 +5,14 @@ MOZ_SERVICE(XULOverlayProviderService, nsIXULOverlayProvider, "@mozilla.org/chro
|
||||
MOZ_SERVICE(IOService, nsIIOService, "@mozilla.org/network/io-service;1")
|
||||
MOZ_SERVICE(ObserverService, nsIObserverService, "@mozilla.org/observer-service;1")
|
||||
MOZ_SERVICE(StringBundleService, nsIStringBundleService, "@mozilla.org/intl/stringbundle;1")
|
||||
|
||||
#ifdef MOZ_USE_NAMESPACE
|
||||
namespace mozilla
|
||||
{
|
||||
#endif
|
||||
|
||||
MOZ_SERVICE(HistoryService, IHistory, "@mozilla.org/browser/history;1")
|
||||
|
||||
#ifdef MOZ_USE_NAMESPACE
|
||||
}
|
||||
#endif
|
||||
|
@ -48,7 +48,9 @@
|
||||
#include "nsIStringBundle.h"
|
||||
#include "nsIToolkitChromeRegistry.h"
|
||||
#include "nsIXULOverlayProvider.h"
|
||||
#include "IHistory.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::services;
|
||||
|
||||
/*
|
||||
|
@ -42,9 +42,12 @@
|
||||
#include "nscore.h"
|
||||
#include "nsCOMPtr.h"
|
||||
|
||||
#define MOZ_USE_NAMESPACE
|
||||
#define MOZ_SERVICE(NAME, TYPE, SERVICE_CID) class TYPE;
|
||||
|
||||
#include "ServiceList.h"
|
||||
#undef MOZ_SERVICE
|
||||
#undef MOZ_USE_NAMESPACE
|
||||
|
||||
namespace mozilla {
|
||||
namespace services {
|
||||
|
Loading…
Reference in New Issue
Block a user