nsLayoutDebugCLH.cpp (6579B)
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 // vim:cindent:tabstop=4:expandtab:shiftwidth=4: 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #include "nsLayoutDebugCLH.h" 8 9 #include "mozIDOMWindow.h" 10 #include "nsArray.h" 11 #include "nsCOMPtr.h" 12 #include "nsComponentManagerUtils.h" 13 #include "nsICommandLine.h" 14 #include "nsISupportsPrimitives.h" 15 #include "nsIURI.h" 16 #include "nsIWindowWatcher.h" 17 #include "nsServiceManagerUtils.h" 18 #include "nsString.h" 19 20 nsLayoutDebugCLH::nsLayoutDebugCLH() = default; 21 22 nsLayoutDebugCLH::~nsLayoutDebugCLH() = default; 23 24 NS_IMPL_ISUPPORTS(nsLayoutDebugCLH, ICOMMANDLINEHANDLER) 25 26 static nsresult HandleFlagWithOptionalArgument(nsICommandLine* aCmdLine, 27 const nsAString& aName, 28 const nsAString& aDefaultValue, 29 nsAString& aValue, 30 bool& aFlagPresent) { 31 aValue.Truncate(); 32 aFlagPresent = false; 33 34 nsresult rv; 35 int32_t idx; 36 37 rv = aCmdLine->FindFlag(aName, false, &idx); 38 NS_ENSURE_SUCCESS(rv, rv); 39 if (idx < 0) { 40 return NS_OK; 41 } 42 43 aFlagPresent = true; 44 45 int32_t length; 46 aCmdLine->GetLength(&length); 47 48 bool argPresent = false; 49 50 if (idx + 1 < length) { 51 rv = aCmdLine->GetArgument(idx + 1, aValue); 52 NS_ENSURE_SUCCESS(rv, rv); 53 54 if (!aValue.IsEmpty() && aValue.CharAt(0) == '-') { 55 aValue.Truncate(); 56 } else { 57 argPresent = true; 58 } 59 } 60 61 if (!argPresent) { 62 aValue = aDefaultValue; 63 } 64 65 return aCmdLine->RemoveArguments(idx, idx + argPresent); 66 } 67 68 static nsresult HandleFlagWithOptionalArgument(nsICommandLine* aCmdLine, 69 const nsAString& aName, 70 double aDefaultValue, 71 double& aValue, 72 bool& aFlagPresent) { 73 nsresult rv; 74 nsString s; 75 76 rv = 77 HandleFlagWithOptionalArgument(aCmdLine, aName, u"0"_ns, s, aFlagPresent); 78 NS_ENSURE_SUCCESS(rv, rv); 79 80 if (!aFlagPresent) { 81 aValue = 0.0; 82 return NS_OK; 83 } 84 85 aValue = s.ToDouble(&rv); 86 return rv; 87 } 88 89 static nsresult AppendArg(nsIMutableArray* aArray, const nsAString& aString) { 90 nsCOMPtr<nsISupportsString> s = 91 do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID); 92 NS_ENSURE_TRUE(s, NS_ERROR_FAILURE); 93 s->SetData(aString); 94 return aArray->AppendElement(s); 95 } 96 97 NS_IMETHODIMP 98 nsLayoutDebugCLH::Handle(nsICommandLine* aCmdLine) { 99 nsresult rv; 100 bool flagPresent; 101 102 nsString url; 103 bool autoclose = false; 104 double delay = 0.0; 105 bool captureProfile = false; 106 nsString profileFilename; 107 bool paged = false; 108 bool anonymousSubtreeDumping = false; 109 bool deterministicFrameDumping = false; 110 111 rv = HandleFlagWithOptionalArgument(aCmdLine, u"layoutdebug"_ns, 112 u"about:blank"_ns, url, flagPresent); 113 NS_ENSURE_SUCCESS(rv, rv); 114 115 if (!flagPresent) { 116 return NS_OK; 117 } 118 119 rv = HandleFlagWithOptionalArgument(aCmdLine, u"autoclose"_ns, 0.0, delay, 120 autoclose); 121 NS_ENSURE_SUCCESS(rv, rv); 122 123 rv = HandleFlagWithOptionalArgument(aCmdLine, u"capture-profile"_ns, 124 u"profile.json"_ns, profileFilename, 125 captureProfile); 126 NS_ENSURE_SUCCESS(rv, rv); 127 128 rv = aCmdLine->HandleFlag(u"paged"_ns, false, &paged); 129 NS_ENSURE_SUCCESS(rv, rv); 130 131 rv = aCmdLine->HandleFlag(u"anonymous-subtree-dumping"_ns, false, 132 &anonymousSubtreeDumping); 133 NS_ENSURE_SUCCESS(rv, rv); 134 135 rv = aCmdLine->HandleFlag(u"deterministic-frame-dumping"_ns, false, 136 &deterministicFrameDumping); 137 NS_ENSURE_SUCCESS(rv, rv); 138 139 nsCOMPtr<nsIMutableArray> argsArray = nsArray::Create(); 140 141 nsCOMPtr<nsIURI> uri; 142 nsAutoCString resolvedSpec; 143 144 rv = aCmdLine->ResolveURI(url, getter_AddRefs(uri)); 145 NS_ENSURE_SUCCESS(rv, rv); 146 147 rv = uri->GetSpec(resolvedSpec); 148 NS_ENSURE_SUCCESS(rv, rv); 149 150 rv = AppendArg(argsArray, NS_ConvertUTF8toUTF16(resolvedSpec)); 151 NS_ENSURE_SUCCESS(rv, rv); 152 153 if (autoclose) { 154 nsString arg; 155 arg.AppendPrintf("autoclose=%f", delay); 156 157 rv = AppendArg(argsArray, arg); 158 NS_ENSURE_SUCCESS(rv, rv); 159 } 160 161 if (captureProfile) { 162 nsString arg; 163 arg.AppendLiteral("profile="); 164 arg.Append(profileFilename); 165 166 rv = AppendArg(argsArray, arg); 167 NS_ENSURE_SUCCESS(rv, rv); 168 } 169 170 if (paged) { 171 rv = AppendArg(argsArray, u"paged"_ns); 172 NS_ENSURE_SUCCESS(rv, rv); 173 } 174 175 if (anonymousSubtreeDumping) { 176 rv = AppendArg(argsArray, u"anonymous-subtree-dumping"_ns); 177 NS_ENSURE_SUCCESS(rv, rv); 178 } 179 180 if (deterministicFrameDumping) { 181 rv = AppendArg(argsArray, u"deterministic-frame-dumping"_ns); 182 NS_ENSURE_SUCCESS(rv, rv); 183 } 184 185 nsCOMPtr<nsIWindowWatcher> wwatch = 186 do_GetService(NS_WINDOWWATCHER_CONTRACTID); 187 NS_ENSURE_TRUE(wwatch, NS_ERROR_FAILURE); 188 189 nsCOMPtr<mozIDOMWindowProxy> opened; 190 wwatch->OpenWindow( 191 nullptr, "chrome://layoutdebug/content/layoutdebug.xhtml"_ns, "_blank"_ns, 192 "chrome,dialog=no,all"_ns, argsArray, getter_AddRefs(opened)); 193 aCmdLine->SetPreventDefault(true); 194 return NS_OK; 195 } 196 197 NS_IMETHODIMP 198 nsLayoutDebugCLH::GetHelpInfo(nsACString& aResult) { 199 aResult.AssignLiteral( 200 " --layoutdebug [<url>] Start with Layout Debugger\n" 201 " --autoclose [<seconds>] Automatically close the Layout Debugger once\n" 202 " the page has loaded, after delaying the specified\n" 203 " number of seconds (which defaults to 0).\n" 204 " --capture-profile [<filename>] Capture a profile of the Layout\n" 205 " Debugger using the Gecko Profiler, and save the\n" 206 " profile to the specified file (which defaults to\n" 207 " profile.json).\n" 208 " --paged Layout the page in paginated mode.\n" 209 " --anonymous-subtree-dumping Toggle option to include anonymous\n" 210 " subtrees in content dumps.\n" 211 " --deterministic-frame-dumping Toggle option to only include\n" 212 " deterministic information in frame\n" 213 " dumps, for ease of diffing.\n"); 214 return NS_OK; 215 }