Bug 1333333 - Label runnables in the HTML parser (again). r=billm.
MozReview-Commit-ID: 1Z89LSr46dN
This commit is contained in:
@@ -15,7 +15,7 @@
|
||||
#include "nsHtml5TreeBuilder.h"
|
||||
#include "nsHtml5AtomTable.h"
|
||||
#include "nsHtml5Module.h"
|
||||
#include "nsHtml5RefPtr.h"
|
||||
#include "nsHtml5StreamParserPtr.h"
|
||||
#include "nsIScriptError.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "mozilla/UniquePtrExtensions.h"
|
||||
@@ -29,6 +29,7 @@
|
||||
#include "nsPrintfCString.h"
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsXULAppAPI.h"
|
||||
#include "mozilla/SchedulerGroup.h"
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
@@ -52,12 +53,12 @@ nsHtml5StreamParser::InitializeStatics()
|
||||
*
|
||||
* To work around this limitation, runnables posted by the main thread to the
|
||||
* parser thread hold their reference to the stream parser in an
|
||||
* nsHtml5RefPtr. Upon creation, nsHtml5RefPtr addrefs the object it holds
|
||||
* nsHtml5StreamParserPtr. Upon creation, nsHtml5StreamParserPtr addrefs the object it holds
|
||||
* just like a regular nsRefPtr. This is OK, since the creation of the
|
||||
* runnable and the nsHtml5RefPtr happens on the main thread.
|
||||
* runnable and the nsHtml5StreamParserPtr happens on the main thread.
|
||||
*
|
||||
* When the runnable is done on the parser thread, the destructor of
|
||||
* nsHtml5RefPtr runs there. It doesn't call Release on the held object
|
||||
* nsHtml5StreamParserPtr runs there. It doesn't call Release on the held object
|
||||
* directly. Instead, it posts another runnable back to the main thread where
|
||||
* that runnable calls Release on the wrapped object.
|
||||
*
|
||||
@@ -955,8 +956,14 @@ nsHtml5StreamParser::OnStartRequest(nsIRequest* aRequest, nsISupports* aContext)
|
||||
// previous normal load in the history.
|
||||
mReparseForbidden = !(mMode == NORMAL || mMode == PLAIN_TEXT);
|
||||
|
||||
mDocGroup = mExecutor->GetDocument()->GetDocGroup();
|
||||
|
||||
nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(mRequest, &rv));
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
// Non-HTTP channels are bogus enough that we let them work with unlabeled
|
||||
// runnables for now. Asserting for HTTP channels only.
|
||||
MOZ_ASSERT(mDocGroup || mMode == LOAD_AS_DATA, "How come the doc group is still null?");
|
||||
|
||||
nsAutoCString method;
|
||||
Unused << httpChannel->GetRequestMethod(method);
|
||||
// XXX does Necko have a way to renavigate POST, etc. without hitting
|
||||
@@ -1059,7 +1066,8 @@ nsHtml5StreamParser::DoStopRequest()
|
||||
class nsHtml5RequestStopper : public Runnable
|
||||
{
|
||||
private:
|
||||
nsHtml5RefPtr<nsHtml5StreamParser> mStreamParser;
|
||||
nsHtml5StreamParserPtr mStreamParser;
|
||||
|
||||
public:
|
||||
explicit nsHtml5RequestStopper(nsHtml5StreamParser* aStreamParser)
|
||||
: Runnable("nsHtml5RequestStopper")
|
||||
@@ -1145,9 +1153,10 @@ nsHtml5StreamParser::DoDataAvailable(const uint8_t* aBuffer, uint32_t aLength)
|
||||
class nsHtml5DataAvailable : public Runnable
|
||||
{
|
||||
private:
|
||||
nsHtml5RefPtr<nsHtml5StreamParser> mStreamParser;
|
||||
UniquePtr<uint8_t[]> mData;
|
||||
uint32_t mLength;
|
||||
nsHtml5StreamParserPtr mStreamParser;
|
||||
UniquePtr<uint8_t[]> mData;
|
||||
uint32_t mLength;
|
||||
|
||||
public:
|
||||
nsHtml5DataAvailable(nsHtml5StreamParser* aStreamParser,
|
||||
UniquePtr<uint8_t[]> aData,
|
||||
@@ -1342,9 +1351,7 @@ nsHtml5StreamParser::FlushTreeOpsAndDisarmTimer()
|
||||
}
|
||||
mTreeBuilder->Flush();
|
||||
nsCOMPtr<nsIRunnable> runnable(mExecutorFlusher);
|
||||
if (NS_FAILED(mExecutor->GetDocument()->Dispatch("nsHtml5ExecutorFlusher",
|
||||
TaskCategory::Other,
|
||||
runnable.forget()))) {
|
||||
if (NS_FAILED(DispatchToMain("nsHtml5ExecutorFlusher", runnable.forget()))) {
|
||||
NS_WARNING("failed to dispatch executor flush event");
|
||||
}
|
||||
}
|
||||
@@ -1375,11 +1382,15 @@ nsHtml5StreamParser::ParseAvailableData()
|
||||
mFirstBuffer->setEnd(0);
|
||||
}
|
||||
mTreeBuilder->FlushLoads();
|
||||
// Dispatch this runnable unconditionally, because the loads
|
||||
// that need flushing may have been flushed earlier even if the
|
||||
// flush right above here did nothing.
|
||||
if (NS_FAILED(NS_DispatchToMainThread(mLoadFlusher))) {
|
||||
NS_WARNING("failed to dispatch load flush event");
|
||||
{
|
||||
// Dispatch this runnable unconditionally, because the loads
|
||||
// that need flushing may have been flushed earlier even if the
|
||||
// flush right above here did nothing.
|
||||
nsCOMPtr<nsIRunnable> runnable(mLoadFlusher);
|
||||
if (NS_FAILED(
|
||||
DispatchToMain("nsHtml5LoadFlusher", runnable.forget()))) {
|
||||
NS_WARNING("failed to dispatch load flush event");
|
||||
}
|
||||
}
|
||||
return; // no more data for now but expecting more
|
||||
case STREAM_ENDED:
|
||||
@@ -1476,7 +1487,8 @@ nsHtml5StreamParser::ParseAvailableData()
|
||||
class nsHtml5StreamParserContinuation : public Runnable
|
||||
{
|
||||
private:
|
||||
nsHtml5RefPtr<nsHtml5StreamParser> mStreamParser;
|
||||
nsHtml5StreamParserPtr mStreamParser;
|
||||
|
||||
public:
|
||||
explicit nsHtml5StreamParserContinuation(nsHtml5StreamParser* aStreamParser)
|
||||
: Runnable("nsHtml5StreamParserContinuation")
|
||||
@@ -1640,7 +1652,8 @@ nsHtml5StreamParser::ContinueAfterFailedCharsetSwitch()
|
||||
class nsHtml5TimerKungFu : public Runnable
|
||||
{
|
||||
private:
|
||||
nsHtml5RefPtr<nsHtml5StreamParser> mStreamParser;
|
||||
nsHtml5StreamParserPtr mStreamParser;
|
||||
|
||||
public:
|
||||
explicit nsHtml5TimerKungFu(nsHtml5StreamParser* aStreamParser)
|
||||
: Runnable("nsHtml5TimerKungFu")
|
||||
@@ -1673,10 +1686,10 @@ nsHtml5StreamParser::DropTimer()
|
||||
*
|
||||
* This DropTimer method addresses these issues. This method must be called
|
||||
* on the main thread before the destructor of this class is reached.
|
||||
* The nsHtml5TimerKungFu object has an nsHtml5RefPtr that addrefs this
|
||||
* The nsHtml5TimerKungFu object has an nsHtml5StreamParserPtr that addrefs this
|
||||
* stream parser object to keep it alive until the runnable is done.
|
||||
* The runnable cancels the timer on the parser thread, drops the timer
|
||||
* and lets nsHtml5RefPtr send a runnable back to the main thread to
|
||||
* and lets nsHtml5StreamParserPtr send a runnable back to the main thread to
|
||||
* release the stream parser.
|
||||
*/
|
||||
mozilla::MutexAutoLock flushTimerLock(mFlushTimerMutex);
|
||||
@@ -1717,15 +1730,19 @@ nsHtml5StreamParser::TimerFlush()
|
||||
if (mMode == VIEW_SOURCE_HTML || mMode == VIEW_SOURCE_XML) {
|
||||
mTreeBuilder->Flush(); // delete useless ops
|
||||
if (mTokenizer->FlushViewSource()) {
|
||||
if (NS_FAILED(NS_DispatchToMainThread(mExecutorFlusher))) {
|
||||
NS_WARNING("failed to dispatch executor flush event");
|
||||
}
|
||||
}
|
||||
nsCOMPtr<nsIRunnable> runnable(mExecutorFlusher);
|
||||
if (NS_FAILED(
|
||||
DispatchToMain("nsHtml5ExecutorFlusher", runnable.forget()))) {
|
||||
NS_WARNING("failed to dispatch executor flush event");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// we aren't speculating and we don't know when new data is
|
||||
// going to arrive. Send data to the main thread.
|
||||
if (mTreeBuilder->Flush(true)) {
|
||||
if (NS_FAILED(NS_DispatchToMainThread(mExecutorFlusher))) {
|
||||
nsCOMPtr<nsIRunnable> runnable(mExecutorFlusher);
|
||||
if (NS_FAILED(
|
||||
DispatchToMain("nsHtml5ExecutorFlusher", runnable.forget()))) {
|
||||
NS_WARNING("failed to dispatch executor flush event");
|
||||
}
|
||||
}
|
||||
@@ -1742,7 +1759,20 @@ nsHtml5StreamParser::MarkAsBroken(nsresult aRv)
|
||||
mTreeBuilder->MarkAsBroken(aRv);
|
||||
mozilla::DebugOnly<bool> hadOps = mTreeBuilder->Flush(false);
|
||||
NS_ASSERTION(hadOps, "Should have had the markAsBroken op!");
|
||||
if (NS_FAILED(NS_DispatchToMainThread(mExecutorFlusher))) {
|
||||
nsCOMPtr<nsIRunnable> runnable(mExecutorFlusher);
|
||||
if (NS_FAILED(DispatchToMain("nsHtml5ExecutorFlusher", runnable.forget()))) {
|
||||
NS_WARNING("failed to dispatch executor flush event");
|
||||
}
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsHtml5StreamParser::DispatchToMain(const char* aName,
|
||||
already_AddRefed<nsIRunnable>&& aRunnable)
|
||||
{
|
||||
nsCOMPtr<nsIRunnable> runnable(aRunnable);
|
||||
if (mDocGroup) {
|
||||
return mDocGroup->Dispatch(aName, TaskCategory::Network, runnable.forget());
|
||||
}
|
||||
return SchedulerGroup::UnlabeledDispatch(
|
||||
aName, TaskCategory::Network, runnable.forget());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user