Bug 470455 - test_database_sync_embed_visits.js leaks, r=sdwilsh
[wine-gecko.git] / toolkit / components / url-classifier / content / moz / debug.js
blob1e202f8d605e89d2707c083cbd60f2efdb8b0438
1 # ***** BEGIN LICENSE BLOCK *****
2 # Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 # The contents of this file are subject to the Mozilla Public License Version
5 # 1.1 (the "License"); you may not use this file except in compliance with
6 # the License. You may obtain a copy of the License at
7 # http://www.mozilla.org/MPL/
9 # Software distributed under the License is distributed on an "AS IS" basis,
10 # WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11 # for the specific language governing rights and limitations under the
12 # License.
14 # The Original Code is Google Safe Browsing.
16 # The Initial Developer of the Original Code is Google Inc.
17 # Portions created by the Initial Developer are Copyright (C) 2006
18 # the Initial Developer. All Rights Reserved.
20 # Contributor(s):
21 #   Fritz Schneider <fritz@google.com> (original author)
22 #   Annie Sullivan <sullivan@google.com>
23 #   Aaron Boodman <aa@google.com>
25 # Alternatively, the contents of this file may be used under the terms of
26 # either the GNU General Public License Version 2 or later (the "GPL"), or
27 # the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
28 # in which case the provisions of the GPL or the LGPL are applicable instead
29 # of those above. If you wish to allow use of your version of this file only
30 # under the terms of either the GPL or the LGPL, and not to allow others to
31 # use your version of this file under the terms of the MPL, indicate your
32 # decision by deleting the provisions above and replace them with the notice
33 # and other provisions required by the GPL or the LGPL. If you do not delete
34 # the provisions above, a recipient may use your version of this file under
35 # the terms of any one of the MPL, the GPL or the LGPL.
37 # ***** END LICENSE BLOCK *****
39 #ifdef DEBUG
41 // Generic logging/debugging functionality that:
43 // (*) when disabled compiles to no-ops at worst (for calls to the service) 
44 //     and to nothing at best (calls to G_Debug() and similar are compiled
45 //     away when you use a jscompiler that strips dead code)
47 // (*) has dynamically configurable/creatable debugging "zones" enabling 
48 //     selective logging
49 // 
50 // (*) hides its plumbing so that all calls in different zones are uniform,
51 //     so you can drop files using this library into other apps that use it
52 //     without any configuration 
54 // (*) can be controlled programmatically or via preferences.  The
55 //     preferences that control the service and its zones are under
56 //     the preference branch "safebrowsing-debug-service."
58 // (*) outputs function call traces when the "loggifier" zone is enabled
59 // 
60 // (*) can write output to logfiles so that you can get a call trace
61 //     from someone who is having a problem
63 // Example:
65 // var G_GDEBUG = true                           // Enable this module
66 // var G_debugService = new G_DebugService();    // in global context
68 // // You can use it with arbitrary primitive first arguement
69 // G_Debug("myzone", "Yo yo yo");   // outputs: [myzone] Yo yo yo\n
71 // // But it's nice to use it with an object; it will probe for the zone name
72 // function Obj() {
73 //   this.debugZone = "someobj";
74 // }
75 // Obj.prototype.foo = function() {
76 //   G_Debug(this, "foo called");
77 // }
78 // (new Obj).foo();                        // outputs: [someobj] foo called\n
80 // G_debugService.loggifier.loggify(Obj.prototype);  // enable call tracing
82 // // En/disable specific zones programmatically (you can also use preferences)
83 // G_debugService.enableZone("somezone");
84 // G_debugService.disableZone("someotherzone");
85 // G_debugService.enableAllZones();
87 // // We also have asserts and errors:
88 // G_Error(this, "Some error occurred");                    // will throw
89 // G_Assert(this, (x > 3), "x not greater than three!");    // will throw
91 // See classes below for more methods. 
93 // TODO add code to set prefs when not found to the default value of a tristate
94 // TODO add error level support
95 // TODO add ability to turn off console output
97 // -------> TO START DEBUGGING: set G_GDEBUG to true
99 // These are the functions code will typically call. Everything is
100 // wrapped in if's so we can compile it away when G_GDEBUG is false.
103 if (typeof G_GDEBUG == "undefined") {
104   throw new Error("G_GDEBUG constant must be set before loading debug.js");
109  * Write out a debugging message.
111  * @param who The thingy to convert into a zone name corresponding to the 
112  *            zone to which this message belongs
113  * @param msg Message to output
114  */
115 function G_Debug(who, msg) {
116   if (G_GDEBUG) {
117     G_GetDebugZone(who).debug(msg);
118   }
122  * Debugs loudly
123  */
124 function G_DebugL(who, msg) {
125   if (G_GDEBUG) {
126     var zone = G_GetDebugZone(who);
128     if (zone.zoneIsEnabled()) {
129       G_debugService.dump(
130         "\n************************************************************\n");
132       G_Debug(who, msg);
134       G_debugService.dump(
135         "************************************************************\n\n");
136     }
137   }
141  * Write out a call tracing message
143  * @param who The thingy to convert into a zone name corresponding to the 
144  *            zone to which this message belongs
145  * @param msg Message to output
146  */
147 function G_TraceCall(who, msg) {
148   if (G_GDEBUG) {
149     if (G_debugService.callTracingEnabled()) {
150       G_debugService.dump(msg + "\n");
151     }
152   }
156  * Write out an error (and throw)
158  * @param who The thingy to convert into a zone name corresponding to the 
159  *            zone to which this message belongs
160  * @param msg Message to output
161  */
162 function G_Error(who, msg) {
163   if (G_GDEBUG) {
164     G_GetDebugZone(who).error(msg);
165   }
169  * Assert something as true and signal an error if it's not
171  * @param who The thingy to convert into a zone name corresponding to the 
172  *            zone to which this message belongs
173  * @param condition Boolean condition to test
174  * @param msg Message to output
175  */
176 function G_Assert(who, condition, msg) {
177   if (G_GDEBUG) {
178     G_GetDebugZone(who).assert(condition, msg);
179   }
183  * Helper function that takes input and returns the DebugZone
184  * corresponding to it.
186  * @param who Arbitrary input that will be converted into a zone name. Most
187  *            likely an object that has .debugZone property, or a string.
188  * @returns The DebugZone object corresponding to the input
189  */
190 function G_GetDebugZone(who) {
191   if (G_GDEBUG) {
192     var zone = "?";
194     if (who && who.debugZone) {
195       zone = who.debugZone;
196     } else if (typeof who == "string") {
197       zone = who;
198     }
200     return G_debugService.getZone(zone);
201   }
204 // Classes that implement the functionality.
207  * A debug "zone" is a string derived from arbitrary types (but
208  * typically derived from another string or an object). All debugging
209  * messages using a particular zone can be enabled or disabled
210  * independent of other zones. This enables you to turn on/off logging
211  * of particular objects or modules. This object implements a single
212  * zone and the methods required to use it.
214  * @constructor
215  * @param service Reference to the DebugService object we use for 
216  *                registration
217  * @param prefix String indicating the unique prefix we should use
218  *               when creating preferences to control this zone
219  * @param zone String indicating the name of the zone
220  */
221 function G_DebugZone(service, prefix, zone) {
222   if (G_GDEBUG) {
223     this.debugService_ = service;
224     this.prefix_ = prefix;
225     this.zone_ = zone;
226     this.zoneEnabledPrefName_ = prefix + ".zone." + this.zone_;
227     this.settings_ = new G_DebugSettings();
228   }
230   
232  * @returns Boolean indicating if this zone is enabled
233  */
234 G_DebugZone.prototype.zoneIsEnabled = function() {
235   if (G_GDEBUG) {
236     var explicit = this.settings_.getSetting(this.zoneEnabledPrefName_, null);
238     if (explicit !== null) {
239       return explicit;
240     } else {
241       return this.debugService_.allZonesEnabled();
242     }
243   }
247  * Enable this logging zone
248  */
249 G_DebugZone.prototype.enableZone = function() {
250   if (G_GDEBUG) {
251     this.settings_.setDefault(this.zoneEnabledPrefName_, true);
252   }
256  * Disable this logging zone
257  */
258 G_DebugZone.prototype.disableZone = function() {
259   if (G_GDEBUG) {
260     this.settings_.setDefault(this.zoneEnabledPrefName_, false);
261   }
265  * Write a debugging message to this zone
267  * @param msg String of message to write
268  */
269 G_DebugZone.prototype.debug = function(msg) {
270   if (G_GDEBUG) {
271     if (this.zoneIsEnabled()) {
272       this.debugService_.dump("[" + this.zone_ + "] " + msg + "\n");
273     }
274   }
278  * Write an error to this zone and throw
280  * @param msg String of error to write
281  */
282 G_DebugZone.prototype.error = function(msg) {
283   if (G_GDEBUG) {
284     this.debugService_.dump("[" + this.zone_ + "] " + msg + "\n");
285     throw new Error(msg);
286     debugger;
287   }
291  * Assert something as true and error if it is not
293  * @param condition Boolean condition to test
294  * @param msg String of message to write if is false
295  */
296 G_DebugZone.prototype.assert = function(condition, msg) {
297   if (G_GDEBUG) {
298     if (condition !== true) {
299       G_Error(this.zone_, "ASSERT FAILED: " + msg);
300     }
301   }
306  * The debug service handles auto-registration of zones, namespacing
307  * the zones preferences, and various global settings such as whether
308  * all zones are enabled.
310  * @constructor
311  * @param opt_prefix Optional string indicating the unique prefix we should 
312  *                   use when creating preferences
313  */
314 function G_DebugService(opt_prefix) {
315   if (G_GDEBUG) {
316     this.prefix_ = opt_prefix ? opt_prefix : "safebrowsing-debug-service";
317     this.consoleEnabledPrefName_ = this.prefix_ + ".alsologtoconsole";
318     this.allZonesEnabledPrefName_ = this.prefix_ + ".enableallzones";
319     this.callTracingEnabledPrefName_ = this.prefix_ + ".trace-function-calls";
320     this.logFileEnabledPrefName_ = this.prefix_ + ".logfileenabled";
321     this.logFileErrorLevelPrefName_ = this.prefix_ + ".logfile-errorlevel";
322     this.zones_ = {};
324     this.loggifier = new G_Loggifier();
325     this.settings_ = new G_DebugSettings();
326   }
329 // Error levels for reporting console messages to the log.
330 G_DebugService.ERROR_LEVEL_INFO = "INFO";
331 G_DebugService.ERROR_LEVEL_WARNING = "WARNING";
332 G_DebugService.ERROR_LEVEL_EXCEPTION = "EXCEPTION";
336  * @returns Boolean indicating if we should send messages to the jsconsole
337  */
338 G_DebugService.prototype.alsoDumpToConsole = function() {
339   if (G_GDEBUG) {
340     return this.settings_.getSetting(this.consoleEnabledPrefName_, false);
341   }
345  * @returns whether to log output to a file as well as the console.
346  */
347 G_DebugService.prototype.logFileIsEnabled = function() {
348   if (G_GDEBUG) {
349     return this.settings_.getSetting(this.logFileEnabledPrefName_, false);
350   }
354  * Turns on file logging. dump() output will also go to the file specified by
355  * setLogFile()
356  */
357 G_DebugService.prototype.enableLogFile = function() {
358   if (G_GDEBUG) {
359     this.settings_.setDefault(this.logFileEnabledPrefName_, true);
360   }
364  * Turns off file logging
365  */
366 G_DebugService.prototype.disableLogFile = function() {
367   if (G_GDEBUG) {
368     this.settings_.setDefault(this.logFileEnabledPrefName_, false);
369   }
373  * @returns an nsIFile instance pointing to the current log file location
374  */
375 G_DebugService.prototype.getLogFile = function() {
376   if (G_GDEBUG) {
377     return this.logFile_;
378   }
382  * Sets a new log file location
383  */
384 G_DebugService.prototype.setLogFile = function(file) {
385   if (G_GDEBUG) {
386     this.logFile_ = file;
387   }
391  * Enables sending messages to the jsconsole
392  */
393 G_DebugService.prototype.enableDumpToConsole = function() {
394   if (G_GDEBUG) {
395     this.settings_.setDefault(this.consoleEnabledPrefName_, true);
396   }
400  * Disables sending messages to the jsconsole
401  */
402 G_DebugService.prototype.disableDumpToConsole = function() {
403   if (G_GDEBUG) {
404     this.settings_.setDefault(this.consoleEnabledPrefName_, false);
405   }
409  * @param zone Name of the zone to get
410  * @returns The DebugZone object corresopnding to input. If not such
411  *          zone exists, a new one is created and returned
412  */
413 G_DebugService.prototype.getZone = function(zone) {
414   if (G_GDEBUG) {
415     if (!this.zones_[zone]) 
416       this.zones_[zone] = new G_DebugZone(this, this.prefix_, zone);
417     
418     return this.zones_[zone];
419   }
423  * @param zone Zone to enable debugging for
424  */
425 G_DebugService.prototype.enableZone = function(zone) {
426   if (G_GDEBUG) {
427     var toEnable = this.getZone(zone);
428     toEnable.enableZone();
429   }
433  * @param zone Zone to disable debugging for
434  */
435 G_DebugService.prototype.disableZone = function(zone) {
436   if (G_GDEBUG) {
437     var toDisable = this.getZone(zone);
438     toDisable.disableZone();
439   }
443  * @returns Boolean indicating whether debugging is enabled for all zones
444  */
445 G_DebugService.prototype.allZonesEnabled = function() {
446   if (G_GDEBUG) {
447     return this.settings_.getSetting(this.allZonesEnabledPrefName_, false);
448   }
452  * Enables all debugging zones
453  */
454 G_DebugService.prototype.enableAllZones = function() {
455   if (G_GDEBUG) {
456     this.settings_.setDefault(this.allZonesEnabledPrefName_, true);
457   }
461  * Disables all debugging zones
462  */
463 G_DebugService.prototype.disableAllZones = function() {
464   if (G_GDEBUG) {
465     this.settings_.setDefault(this.allZonesEnabledPrefName_, false);
466   }
470  * @returns Boolean indicating whether call tracing is enabled
471  */
472 G_DebugService.prototype.callTracingEnabled = function() {
473   if (G_GDEBUG) {
474     return this.settings_.getSetting(this.callTracingEnabledPrefName_, false);
475   }
479  * Enables call tracing
480  */
481 G_DebugService.prototype.enableCallTracing = function() {
482   if (G_GDEBUG) {
483     this.settings_.setDefault(this.callTracingEnabledPrefName_, true);
484   }
488  * Disables call tracing
489  */
490 G_DebugService.prototype.disableCallTracing = function() {
491   if (G_GDEBUG) {
492     this.settings_.setDefault(this.callTracingEnabledPrefName_, false);
493   }
497  * Gets the minimum error that will be reported to the log.
498  */
499 G_DebugService.prototype.getLogFileErrorLevel = function() {
500   if (G_GDEBUG) {
501     var level = this.settings_.getSetting(this.logFileErrorLevelPrefName_, 
502                                           G_DebugService.ERROR_LEVEL_EXCEPTION);
504     return level.toUpperCase();
505   }
509  * Sets the minimum error level that will be reported to the log.
510  */
511 G_DebugService.prototype.setLogFileErrorLevel = function(level) {
512   if (G_GDEBUG) {
513     // normalize case just to make it slightly easier to not screw up.
514     level = level.toUpperCase();
516     if (level != G_DebugService.ERROR_LEVEL_INFO &&
517         level != G_DebugService.ERROR_LEVEL_WARNING &&
518         level != G_DebugService.ERROR_LEVEL_EXCEPTION) {
519       throw new Error("Invalid error level specified: {" + level + "}");
520     }
522     this.settings_.setDefault(this.logFileErrorLevelPrefName_, level);
523   }
527  * Internal dump() method
529  * @param msg String of message to dump
530  */
531 G_DebugService.prototype.dump = function(msg) {
532   if (G_GDEBUG) {
533     dump(msg);
534     
535     if (this.alsoDumpToConsole()) {
536       try {
537         var console = Components.classes['@mozilla.org/consoleservice;1']
538                       .getService(Components.interfaces.nsIConsoleService);
539         console.logStringMessage(msg);
540       } catch(e) {
541         dump("G_DebugZone ERROR: COULD NOT DUMP TO CONSOLE\n");
542       }
543     }
545     this.maybeDumpToFile(msg);
546   }
550  * Writes the specified message to the log file, if file logging is enabled.
551  */
552 G_DebugService.prototype.maybeDumpToFile = function(msg) {
553   if (this.logFileIsEnabled() && this.logFile_) {
555     /* try to get the correct line end character for this platform */
556     if (!this._LINE_END_CHAR)
557       this._LINE_END_CHAR =
558         Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULRuntime)
559                                          .OS == "WINNT" ? "\r\n" : "\n";
560     if (this._LINE_END_CHAR != "\n")
561       msg = msg.replace(/\n/g, this._LINE_END_CHAR);
563     try {
564       var stream = Cc["@mozilla.org/network/file-output-stream;1"]
565                    .createInstance(Ci.nsIFileOutputStream);
566       stream.init(this.logFile_,
567                   0x02 | 0x08 | 0x10 /* PR_WRONLY | PR_CREATE_FILE | PR_APPEND */
568                   -1 /* default perms */, 0 /* no special behavior */);
569       stream.write(msg, msg.length);
570     } finally {
571       stream.close();
572     }
573   }
577  * Implements nsIConsoleListener.observe(). Gets called when an error message
578  * gets reported to the console and sends it to the log file as well.
579  */
580 G_DebugService.prototype.observe = function(consoleMessage) {
581   if (G_GDEBUG) {
582     var errorLevel = this.getLogFileErrorLevel();
584     // consoleMessage can be either nsIScriptError or nsIConsoleMessage. The
585     // latter does not have things like line number, etc. So we special case 
586     // it first. 
587     if (!(consoleMessage instanceof Ci.nsIScriptError)) {
588       // Only report these messages if the error level is INFO.
589       if (errorLevel == G_DebugService.ERROR_LEVEL_INFO) {
590         this.maybeDumpToFile(G_DebugService.ERROR_LEVEL_INFO + ": " + 
591                              consoleMessage.message + "\n");
592       }
594       return;
595     }
597     // We make a local copy of these fields because writing to it doesn't seem
598     // to work.
599     var flags = consoleMessage.flags;
600     var sourceName = consoleMessage.sourceName;
601     var lineNumber = consoleMessage.lineNumber;
603     // Sometimes, a scripterror instance won't have any flags set. We 
604     // default to exception.
605     if (!flags) {
606       flags = Ci.nsIScriptError.exceptionFlag;
607     }
609     // Default the filename and line number if they aren't set.
610     if (!sourceName) {
611       sourceName = "<unknown>";
612     }
614     if (!lineNumber) {
615       lineNumber = "<unknown>";
616     }
618     // Report the error in the log file.
619     if (flags & Ci.nsIScriptError.warningFlag) {
620       // Only report warnings if the error level is warning or better. 
621       if (errorLevel == G_DebugService.ERROR_LEVEL_WARNING ||
622           errorLevel == G_DebugService.ERROR_LEVEL_INFO) {
623         this.reportScriptError_(consoleMessage.message,
624                                 sourceName,
625                                 lineNumber,
626                                 G_DebugService.ERROR_LEVEL_WARNING);
627       }
628     } else if (flags & Ci.nsIScriptError.exceptionFlag) {
629       // Always report exceptions.
630       this.reportScriptError_(consoleMessage.message,
631                               sourceName,
632                               lineNumber,
633                               G_DebugService.ERROR_LEVEL_EXCEPTION);
634     }
635   }
639  * Private helper to report an nsIScriptError instance to the log/console.
640  */
641 G_DebugService.prototype.reportScriptError_ = function(message, sourceName, 
642                                                        lineNumber, label) {
643   var message = "\n------------------------------------------------------------\n" +
644                 label + ": " + message +
645                 "\nlocation: " + sourceName + ", " + "line: " + lineNumber +
646                 "\n------------------------------------------------------------\n\n";
648   dump(message);
649   this.maybeDumpToFile(message);
655  * A class that instruments methods so they output a call trace,
656  * including the values of their actual parameters and return value.
657  * This code is mostly stolen from Aaron Boodman's original
658  * implementation in clobber utils.
660  * Note that this class uses the "loggifier" debug zone, so you'll see 
661  * a complete call trace when that zone is enabled.
663  * @constructor
664  */
665 function G_Loggifier() {
666   if (G_GDEBUG) {
667     // Careful not to loggify ourselves!
668     this.mark_(this);  
669   }
673  * Marks an object as having been loggified. Loggification is not 
674  * idempotent :)
676  * @param obj Object to be marked
677  */
678 G_Loggifier.prototype.mark_ = function(obj) {
679   if (G_GDEBUG) {
680     obj.__loggified_ = true;
681   }
685  * @param obj Object to be examined
686  * @returns Boolean indicating if the object has been loggified
687  */
688 G_Loggifier.prototype.isLoggified = function(obj) {
689   if (G_GDEBUG) {
690     return !!obj.__loggified_;
691   }
695  * Attempt to extract the class name from the constructor definition.
696  * Assumes the object was created using new.
698  * @param constructor String containing the definition of a constructor,
699  *                    for example what you'd get by examining obj.constructor
700  * @returns Name of the constructor/object if it could be found, else "???"
701  */
702 G_Loggifier.prototype.getFunctionName_ = function(constructor) {
703   if (G_GDEBUG) {
704     return constructor.name || "???";
705   }
709  * Wraps all the methods in an object so that call traces are
710  * automatically outputted.
712  * @param obj Object to loggify. SHOULD BE THE PROTOTYPE OF A USER-DEFINED
713  *            object. You can get into trouble if you attempt to 
714  *            loggify something that isn't, for example the Window.
716  * Any additional parameters are considered method names which should not be
717  * loggified.
719  * Usage:
720  * G_debugService.loggifier.loggify(MyClass.prototype,
721  *                                  "firstMethodNotToLog",
722  *                                  "secondMethodNotToLog",
723  *                                  ... etc ...);
724  */
725 G_Loggifier.prototype.loggify = function(obj) {
726   if (G_GDEBUG) {
727     if (!G_debugService.callTracingEnabled()) {
728       return;
729     }
731     if (typeof window != "undefined" && obj == window || 
732         this.isLoggified(obj))   // Don't go berserk!
733       return;
735     var zone = G_GetDebugZone(obj);
736     if (!zone || !zone.zoneIsEnabled()) {
737       return;
738     }
740     this.mark_(obj);
742     // Helper function returns an instrumented version of
743     // objName.meth, with "this" bound properly. (BTW, because we're
744     // in a conditional here, functions will only be defined as
745     // they're encountered during execution, so declare this helper
746     // before using it.)
748     function wrap(meth, objName, methName) {
749       return function() {
750         
751         // First output the call along with actual parameters
752         var args = new Array(arguments.length);
753         var argsString = "";
754         for (var i = 0; i < args.length; i++) {
755           args[i] = arguments[i];
756           argsString += (i == 0 ? "" : ", ");
757           
758           if (typeof args[i] == "function") {
759             argsString += "[function]";
760           } else {
761             argsString += args[i];
762           }
763         }
765         G_TraceCall(this, "> " + objName + "." + methName + "(" + 
766                     argsString + ")");
767         
768         // Then run the function, capturing the return value and throws
769         try {
770           var retVal = meth.apply(this, arguments);
771           var reportedRetVal = retVal;
773           if (typeof reportedRetVal == "undefined")
774             reportedRetVal = "void";
775           else if (reportedRetVal === "")
776             reportedRetVal = "\"\" (empty string)";
777         } catch (e) {
778           if (e && !e.__logged) {
779             G_TraceCall(this, "Error: " + e.message + ". " + 
780                         e.fileName + ": " + e.lineNumber);
781             try {
782               e.__logged = true;
783             } catch (e2) {
784               // Sometimes we can't add the __logged flag because it's an
785               // XPC wrapper
786               throw e;
787             }
788           }
789           
790           throw e;      // Re-throw!
791         }
793         // And spit it out already
794         G_TraceCall(
795           this, 
796           "< " + objName + "." + methName + ": " + reportedRetVal);
798         return retVal;
799       };
800     };
802     var ignoreLookup = {};
804     if (arguments.length > 1) {
805       for (var i = 1; i < arguments.length; i++) {
806         ignoreLookup[arguments[i]] = true;
807       }
808     }
809     
810     // Wrap each method of obj
811     for (var p in obj) {
812       // Work around bug in Firefox. In ffox typeof RegExp is "function",
813       // so make sure this really is a function. Bug as of FFox 1.5b2.
814       if (typeof obj[p] == "function" && obj[p].call && !ignoreLookup[p]) {
815         var objName = this.getFunctionName_(obj.constructor);
816         obj[p] = wrap(obj[p], objName, p);
817       }
818     }
819   }
824  * Simple abstraction around debug settings. The thing with debug settings is
825  * that we want to be able to specify a default in the application's startup,
826  * but have that default be overridable by the user via their prefs.
828  * To generalize this, we package up a dictionary of defaults with the 
829  * preferences tree. If a setting isn't in the preferences tree, then we grab it
830  * from the defaults.
831  */
832 function G_DebugSettings() {
833   this.defaults_ = {};
834   this.prefs_ = new G_Preferences();
838  * Returns the value of a settings, optionally defaulting to a given value if it
839  * doesn't exist. If no default is specified, the default is |undefined|.
840  */
841 G_DebugSettings.prototype.getSetting = function(name, opt_default) {
842   var override = this.prefs_.getPref(name, null);
844   if (override !== null) {
845     return override;
846   } else if (typeof this.defaults_[name] != "undefined") {
847     return this.defaults_[name];
848   } else {
849     return opt_default;
850   }
854  * Sets the default value for a setting. If the user doesn't override it with a
855  * preference, this is the value which will be returned by getSetting().
856  */
857 G_DebugSettings.prototype.setDefault = function(name, val) {
858   this.defaults_[name] = val;
861 var G_debugService = new G_DebugService(); // Instantiate us!
863 if (G_GDEBUG) {
864   G_debugService.enableAllZones();
867 #else
869 // Stubs for the debugging aids scattered through this component.
870 // They will be expanded if you compile yourself a debug build.
872 function G_Debug(who, msg) { }
873 function G_Assert(who, condition, msg) { }
874 function G_Error(who, msg) { }
875 var G_debugService = { __noSuchMethod__: function() { } };
877 #endif