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:
Brian Hackett 2019-08-04 21:33:07 +00:00
Родитель b24faa1675
Коммит eb95b88a4d
4 изменённых файлов: 117 добавлений и 18 удалений

Просмотреть файл

@ -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