/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ // vim:cindent:tabstop=4:expandtab:shiftwidth=4: /* 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/. */ #include "nsLayoutDebugCLH.h" #include "mozIDOMWindow.h" #include "nsArray.h" #include "nsString.h" #include "nsComponentManagerUtils.h" #include "nsCOMPtr.h" #include "nsIWindowWatcher.h" #include "nsISupportsPrimitives.h" #include "nsICommandLine.h" #include "nsIURI.h" #include "nsServiceManagerUtils.h" nsLayoutDebugCLH::nsLayoutDebugCLH() = default; nsLayoutDebugCLH::~nsLayoutDebugCLH() = default; NS_IMPL_ISUPPORTS(nsLayoutDebugCLH, ICOMMANDLINEHANDLER) static nsresult HandleFlagWithOptionalArgument(nsICommandLine* aCmdLine, const nsAString& aName, const nsAString& aDefaultValue, nsAString& aValue, bool& aFlagPresent) { aValue.Truncate(); aFlagPresent = false; nsresult rv; int32_t idx; rv = aCmdLine->FindFlag(aName, false, &idx); NS_ENSURE_SUCCESS(rv, rv); if (idx < 0) return NS_OK; aFlagPresent = true; int32_t length; aCmdLine->GetLength(&length); bool argPresent = false; if (idx + 1 < length) { rv = aCmdLine->GetArgument(idx + 1, aValue); NS_ENSURE_SUCCESS(rv, rv); if (!aValue.IsEmpty() && aValue.CharAt(0) == '-') { aValue.Truncate(); } else { argPresent = true; } } if (!argPresent) { aValue = aDefaultValue; } return aCmdLine->RemoveArguments(idx, idx + argPresent); } static nsresult HandleFlagWithOptionalArgument(nsICommandLine* aCmdLine, const nsAString& aName, double aDefaultValue, double& aValue, bool& aFlagPresent) { nsresult rv; nsString s; rv = HandleFlagWithOptionalArgument(aCmdLine, aName, u"0"_ns, s, aFlagPresent); NS_ENSURE_SUCCESS(rv, rv); if (!aFlagPresent) { aValue = 0.0; return NS_OK; } aValue = s.ToDouble(&rv); return rv; } static nsresult AppendArg(nsIMutableArray* aArray, const nsAString& aString) { nsCOMPtr s = do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID); NS_ENSURE_TRUE(s, NS_ERROR_FAILURE); s->SetData(aString); return aArray->AppendElement(s); } NS_IMETHODIMP nsLayoutDebugCLH::Handle(nsICommandLine* aCmdLine) { nsresult rv; bool flagPresent; nsString url; bool autoclose = false; double delay = 0.0; bool captureProfile = false; nsString profileFilename; bool paged = false; rv = HandleFlagWithOptionalArgument(aCmdLine, u"layoutdebug"_ns, u"about:blank"_ns, url, flagPresent); NS_ENSURE_SUCCESS(rv, rv); if (!flagPresent) { return NS_OK; } rv = HandleFlagWithOptionalArgument(aCmdLine, u"autoclose"_ns, 0.0, delay, autoclose); NS_ENSURE_SUCCESS(rv, rv); rv = HandleFlagWithOptionalArgument(aCmdLine, u"capture-profile"_ns, u"profile.json"_ns, profileFilename, captureProfile); NS_ENSURE_SUCCESS(rv, rv); rv = aCmdLine->HandleFlag(u"paged"_ns, false, &paged); NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr argsArray = nsArray::Create(); nsCOMPtr uri; nsAutoCString resolvedSpec; rv = aCmdLine->ResolveURI(url, getter_AddRefs(uri)); NS_ENSURE_SUCCESS(rv, rv); rv = uri->GetSpec(resolvedSpec); NS_ENSURE_SUCCESS(rv, rv); rv = AppendArg(argsArray, NS_ConvertUTF8toUTF16(resolvedSpec)); NS_ENSURE_SUCCESS(rv, rv); if (autoclose) { nsString arg; arg.AppendPrintf("autoclose=%f", delay); rv = AppendArg(argsArray, arg); NS_ENSURE_SUCCESS(rv, rv); } if (captureProfile) { nsString arg; arg.AppendLiteral("profile="); arg.Append(profileFilename); rv = AppendArg(argsArray, arg); NS_ENSURE_SUCCESS(rv, rv); } if (paged) { rv = AppendArg(argsArray, u"paged"_ns); NS_ENSURE_SUCCESS(rv, rv); } nsCOMPtr wwatch = do_GetService(NS_WINDOWWATCHER_CONTRACTID); NS_ENSURE_TRUE(wwatch, NS_ERROR_FAILURE); nsCOMPtr opened; wwatch->OpenWindow( nullptr, "chrome://layoutdebug/content/layoutdebug.xhtml"_ns, "_blank"_ns, "chrome,dialog=no,all"_ns, argsArray, getter_AddRefs(opened)); aCmdLine->SetPreventDefault(true); return NS_OK; } NS_IMETHODIMP nsLayoutDebugCLH::GetHelpInfo(nsACString& aResult) { aResult.AssignLiteral( " --layoutdebug [] Start with Layout Debugger\n" " --autoclose [] Automatically close the Layout Debugger once\n" " the page has loaded, after delaying the specified\n" " number of seconds (which defaults to 0).\n" " --capture-profile [] Capture a profile of the Layout\n" " Debugger using the Gecko Profiler, and save the\n" " profile to the specified file (which defaults to\n" " profile.json).\n" " --paged Layout the page in paginated mode.\n"); return NS_OK; }