зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1538056 Part 1 - Notify devtools about HTML file contents, r=hsivonen.
Differential Revision: https://phabricator.services.mozilla.com/D33178 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
b24faa1675
Коммит
eb95b88a4d
|
@ -0,0 +1,15 @@
|
|||
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
// Interfaces and structures for use by the debugger and other devtools.
|
||||
|
||||
// Data sent to the devtools when new data has been received in an HTML parse.
|
||||
dictionary HTMLContent {
|
||||
DOMString parserID;
|
||||
DOMString uri;
|
||||
DOMString contents;
|
||||
boolean complete;
|
||||
};
|
|
@ -37,6 +37,7 @@ WEBIDL_FILES = [
|
|||
'ChannelWrapper.webidl',
|
||||
'DebuggerNotification.webidl',
|
||||
'DebuggerNotificationObserver.webidl',
|
||||
'DebuggerUtils.webidl',
|
||||
'DocumentL10n.webidl',
|
||||
'DominatorTree.webidl',
|
||||
'DOMLocalization.webidl',
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
#include "mozilla/SchedulerGroup.h"
|
||||
#include "nsJSEnvironment.h"
|
||||
#include "mozilla/dom/Document.h"
|
||||
#include "mozilla/dom/DebuggerUtilsBinding.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::dom;
|
||||
|
@ -230,9 +231,6 @@ nsHtml5StreamParser::nsHtml5StreamParser(nsHtml5TreeOpExecutor* aExecutor,
|
|||
nsHtml5StreamParser::~nsHtml5StreamParser() {
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
mTokenizer->end();
|
||||
if (recordreplay::IsRecordingOrReplaying()) {
|
||||
recordreplay::EndContentParse(this);
|
||||
}
|
||||
#ifdef DEBUG
|
||||
{
|
||||
mozilla::MutexAutoLock flushTimerLock(mFlushTimerMutex);
|
||||
|
@ -349,10 +347,19 @@ void nsHtml5StreamParser::FeedDetector(Span<const uint8_t> aBuffer,
|
|||
}
|
||||
|
||||
void nsHtml5StreamParser::SetViewSourceTitle(nsIURI* aURL) {
|
||||
if (recordreplay::IsRecordingOrReplaying()) {
|
||||
nsAutoCString spec;
|
||||
aURL->GetSpec(spec);
|
||||
recordreplay::BeginContentParse(this, spec.get(), "text/html");
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
nsIDocShell* docshell = mExecutor->GetDocument()->GetDocShell();
|
||||
if (docshell && docshell->GetWatchedByDevtools()) {
|
||||
mURIToSendToDevtools = aURL;
|
||||
|
||||
nsID uuid;
|
||||
nsresult rv = nsContentUtils::GenerateUUIDInPlace(uuid);
|
||||
if (!NS_FAILED(rv)) {
|
||||
char buffer[NSID_LENGTH];
|
||||
uuid.ToProvidedString(buffer);
|
||||
mUUIDForDevtools = NS_ConvertASCIItoUTF16(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
if (aURL) {
|
||||
|
@ -836,6 +843,56 @@ nsresult nsHtml5StreamParser::SniffStreamBytes(
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
class AddContentRunnable : public Runnable {
|
||||
public:
|
||||
AddContentRunnable(const nsAString& aParserID, nsIURI* aURI,
|
||||
Span<const char16_t> aData, bool aComplete)
|
||||
: Runnable("AddContent") {
|
||||
nsAutoCString spec;
|
||||
aURI->GetSpec(spec);
|
||||
mData.mUri.Construct(NS_ConvertUTF8toUTF16(spec));
|
||||
mData.mParserID.Construct(aParserID);
|
||||
mData.mContents.Construct(aData.Elements(), aData.Length());
|
||||
mData.mComplete.Construct(aComplete);
|
||||
}
|
||||
|
||||
NS_IMETHOD Run() override {
|
||||
nsAutoString json;
|
||||
if (!mData.ToJSON(json)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIObserverService> obsService = services::GetObserverService();
|
||||
if (obsService) {
|
||||
obsService->NotifyObservers(nullptr, "devtools-html-content",
|
||||
PromiseFlatString(json).get());
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
HTMLContent mData;
|
||||
};
|
||||
|
||||
inline void nsHtml5StreamParser::OnNewContent(Span<const char16_t> aData) {
|
||||
if (mURIToSendToDevtools) {
|
||||
NS_DispatchToMainThread(new AddContentRunnable(mUUIDForDevtools,
|
||||
mURIToSendToDevtools,
|
||||
aData,
|
||||
/* aComplete */ false));
|
||||
}
|
||||
}
|
||||
|
||||
inline void nsHtml5StreamParser::OnContentComplete() {
|
||||
if (mURIToSendToDevtools) {
|
||||
NS_DispatchToMainThread(new AddContentRunnable(mUUIDForDevtools,
|
||||
mURIToSendToDevtools,
|
||||
Span<const char16_t>(),
|
||||
/* aComplete */ true));
|
||||
mURIToSendToDevtools = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
nsresult nsHtml5StreamParser::WriteStreamBytes(
|
||||
Span<const uint8_t> aFromSegment) {
|
||||
NS_ASSERTION(IsParserThread(), "Wrong thread!");
|
||||
|
@ -856,8 +913,8 @@ nsresult nsHtml5StreamParser::WriteStreamBytes(
|
|||
bool hadErrors;
|
||||
Tie(result, read, written, hadErrors) =
|
||||
mUnicodeDecoder->DecodeToUTF16(src, dst, false);
|
||||
if (!mDecodingLocalFileAsUTF8 && recordreplay::IsRecordingOrReplaying()) {
|
||||
recordreplay::AddContentParseData16(this, dst.data(), written);
|
||||
if (!mDecodingLocalFileAsUTF8) {
|
||||
OnNewContent(dst.To(written));
|
||||
}
|
||||
if (hadErrors && !mHasHadErrors) {
|
||||
if (mDecodingLocalFileAsUTF8) {
|
||||
|
@ -924,13 +981,12 @@ void nsHtml5StreamParser::CommitLocalFileToUTF8() {
|
|||
mCharsetSource = kCharsetFromFileURLGuess;
|
||||
mTreeBuilder->SetDocumentCharset(mEncoding, mCharsetSource);
|
||||
|
||||
if (recordreplay::IsRecordingOrReplaying()) {
|
||||
nsHtml5OwningUTF16Buffer* buffer = mLastBuffer;
|
||||
while (buffer) {
|
||||
recordreplay::AddContentParseData16(
|
||||
this, buffer->getBuffer() + buffer->getStart(), buffer->getLength());
|
||||
buffer = buffer->next;
|
||||
}
|
||||
nsHtml5OwningUTF16Buffer* buffer = mFirstBuffer;
|
||||
while (buffer) {
|
||||
Span<const char16_t> data(buffer->getBuffer() + buffer->getStart(),
|
||||
buffer->getLength());
|
||||
OnNewContent(data);
|
||||
buffer = buffer->next;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1145,6 +1201,10 @@ void nsHtml5StreamParser::DoStopRequest() {
|
|||
"Stream ended without being open.");
|
||||
mTokenizerMutex.AssertCurrentThreadOwns();
|
||||
|
||||
auto guard = MakeScopeExit([&] {
|
||||
OnContentComplete();
|
||||
});
|
||||
|
||||
if (IsTerminated()) {
|
||||
return;
|
||||
}
|
||||
|
@ -1182,8 +1242,8 @@ void nsHtml5StreamParser::DoStopRequest() {
|
|||
bool hadErrors;
|
||||
Tie(result, read, written, hadErrors) =
|
||||
mUnicodeDecoder->DecodeToUTF16(src, dst, true);
|
||||
if (!mDecodingLocalFileAsUTF8 && recordreplay::IsRecordingOrReplaying()) {
|
||||
recordreplay::AddContentParseData16(this, dst.data(), written);
|
||||
if (!mDecodingLocalFileAsUTF8) {
|
||||
OnNewContent(dst.To(written));
|
||||
}
|
||||
if (hadErrors && !mHasHadErrors) {
|
||||
if (mDecodingLocalFileAsUTF8) {
|
||||
|
|
|
@ -383,6 +383,16 @@ class nsHtml5StreamParser final : public nsICharsetDetectionObserver {
|
|||
*/
|
||||
nsresult DispatchToMain(already_AddRefed<nsIRunnable>&& aRunnable);
|
||||
|
||||
/**
|
||||
* Notify any devtools listeners about content newly received for parsing.
|
||||
*/
|
||||
inline void OnNewContent(mozilla::Span<const char16_t> aData);
|
||||
|
||||
/**
|
||||
* Notify any devtools listeners after all parse content has been received.
|
||||
*/
|
||||
inline void OnContentComplete();
|
||||
|
||||
nsCOMPtr<nsIRequest> mRequest;
|
||||
nsCOMPtr<nsIRequestObserver> mObserver;
|
||||
|
||||
|
@ -599,6 +609,19 @@ class nsHtml5StreamParser final : public nsICharsetDetectionObserver {
|
|||
* Whether the parser should not sniff the content type.
|
||||
*/
|
||||
bool mSkipContentSniffing;
|
||||
|
||||
/**
|
||||
* If the associated docshell is being watched by the devtools, this is
|
||||
* set to the URI associated with the parse. All parse data is sent to the
|
||||
* devtools, along with this URI. This URI is cleared out after the parse has
|
||||
* been marked as completed.
|
||||
*/
|
||||
nsCOMPtr<nsIURI> mURIToSendToDevtools;
|
||||
|
||||
/**
|
||||
* If content is being sent to the devtools, an encoded UUID for the parser.
|
||||
*/
|
||||
nsString mUUIDForDevtools;
|
||||
};
|
||||
|
||||
#endif // nsHtml5StreamParser_h
|
||||
|
|
Загрузка…
Ссылка в новой задаче