From d6794f97f57f9c05617c7a03a9edb9e4e0f22d83 Mon Sep 17 00:00:00 2001
From: buczekp <buczekp>
Date: Thu, 5 May 2011 09:56:14 +0000
Subject: [PATCH] [LMS-2233] integrated gwt-debug-panel with openBIS

SVN: 21143
---
 openbis/.classpath                            |   1 +
 openbis/build/build.xml                       |  12 +-
 .../OpenBIS-without-entry-point.gwt.xml       |   7 +-
 .../AbstractPluginViewContext.java            |   5 +
 .../client/web/client/application/Client.java |  18 +-
 .../client/application/CommonViewContext.java |  10 +-
 .../web/client/application/IViewContext.java  |   5 +
 .../client/application/framework/AppView.java |  13 +-
 .../framework/DebugPanelManager.java          |  91 ++++++++
 .../systemsx/cisd/openbis/public/index.html   |  16 +-
 .../public/resources/css/debug-panel.css      | 209 ++++++++++++++++++
 11 files changed, 376 insertions(+), 11 deletions(-)
 create mode 100644 openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/framework/DebugPanelManager.java
 create mode 100644 openbis/source/java/ch/systemsx/cisd/openbis/public/resources/css/debug-panel.css

diff --git a/openbis/.classpath b/openbis/.classpath
index 0594ec52192..2bcc8f62493 100644
--- a/openbis/.classpath
+++ b/openbis/.classpath
@@ -55,5 +55,6 @@
 	<classpathentry kind="lib" path="/libraries/cisd-args4j/cisd-args4j.jar" sourcepath="/libraries/cisd-args4j/cisd-args4j-src.zip"/>
 	<classpathentry kind="lib" path="/libraries/commons-dbcp/commons-dbcp.jar" sourcepath="/libraries/commons-dbcp/src.zip"/>
 	<classpathentry kind="lib" path="/libraries/jline/jline.jar" sourcepath="/libraries/jline/src.zip"/>
+	<classpathentry kind="lib" path="/libraries/gwt-debug-panel/gwt-debug-panel.jar" sourcepath="/gwt-debug-panel-read-only"/>
 	<classpathentry kind="output" path="targets/www/WEB-INF/classes"/>
 </classpath>
diff --git a/openbis/build/build.xml b/openbis/build/build.xml
index 1111125e035..55141e34b30 100644
--- a/openbis/build/build.xml
+++ b/openbis/build/build.xml
@@ -8,6 +8,7 @@
 
   <property name="gwt.lib" value="${lib}/gwt2.0" />
   <property name="gwt.user.lib" value="${gwt.lib}/gwt-user.jar" />
+  <property name="gwt.debugpanel.lib" value="${lib}/gwt-debug-panel/gwt-debug-panel.jar" />
 
   <property name="original.server.dist" value="${original.dist}/server" />
   <property name="original.openbis.server.dist" value="../openbis/dist/server" />
@@ -315,7 +316,7 @@
     <delete includeEmptyDirs="true">
     	<fileset dir="${webapp.dist}" excludes="*.jar"/>
   	</delete>
-    <java classpath="${ecp}:${gwt.lib}/gwt-dev.jar:${gwt.user.lib}:../common/${sources}:../openbis/${sources}:${sources}" 
+    <java classpath="${ecp}:${gwt.lib}/gwt-dev.jar:${gwt.user.lib}:${gwt.debugpanel.lib}:../common/${sources}:../openbis/${sources}:${sources}" 
     	classname="com.google.gwt.dev.Compiler" fork="true">
       <jvmarg value="-Xmx1024M" />
       <arg value="-war" />
@@ -385,6 +386,9 @@
       <fileset dir="${gwt.lib}">
         <include name="gwt-servlet.jar" />
       </fileset>
+      <fileset dir="${lib}/gwt-debug-panel">
+        <include name="gwt-debug-panel.jar" />
+      </fileset>
       <fileset dir="${lib}/commons-fileupload">
         <include name="*.jar" />
       </fileset>
@@ -631,6 +635,9 @@
       <lib dir="${gwt.lib}">
         <include name="gwt-servlet.jar" />
       </lib>
+    	<lib dir="${lib}/gwt-debug-panel">
+    	  <include name="gwt-debug-panel.jar" />
+    	</lib>
       <lib dir="${lib}/commons-fileupload">
         <include name="*.jar" />
       </lib>
@@ -765,7 +772,7 @@
   -->
   <target name="compile-module-test" description="Compile the module test mode">
     <delete dir="${targets.www}/${module-test.path}" />
-    <java classpath="${ecp}:${ecp.gwt}:${gwt.lib}/gwt-dev.jar:${gwt.user.lib}:../common/${sources}:../openbis/${sources}:${sources}"
+    <java classpath="${ecp}:${ecp.gwt}:${gwt.lib}/gwt-dev.jar:${gwt.user.lib}:${gwt.debugpanel.lib}:../common/${sources}:../openbis/${sources}:${sources}"
       classname="com.google.gwt.dev.Compiler" fork="true">
       <jvmarg value="-Xmx512M" />
       <arg value="-war" />
@@ -809,7 +816,6 @@
       <arg value="${module-test.path}/index.html" />
       <arg value="-startupUrl" />
       <arg value="${module-test.module}/index.html" />
-
       <arg value="${module-test.module}" />
       <arg value="-war" />
       <arg value="targets/www" />
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/OpenBIS-without-entry-point.gwt.xml b/openbis/source/java/ch/systemsx/cisd/openbis/OpenBIS-without-entry-point.gwt.xml
index 00426830ef1..eb32dfa6f7d 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/OpenBIS-without-entry-point.gwt.xml
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/OpenBIS-without-entry-point.gwt.xml
@@ -10,12 +10,17 @@
   -->
   <inherits name='com.google.gwt.user.User' />
   <inherits name="com.google.gwt.i18n.I18N" />
-
+  
   <!--
     // Inherit the core EXT GWT stuff.
   -->
   <inherits name='com.extjs.gxt.ui.GXT' />
 
+  <!--
+    // Inherit the panel used for debugging/profiling
+  -->
+  <inherits name="com.google.gwt.debugpanel.DebugPanel" />
+
   <!--
     // The following scripts loads dictionaries which are used for all text messages.
   -->
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/AbstractPluginViewContext.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/AbstractPluginViewContext.java
index 500449cd71f..a5bd28f469e 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/AbstractPluginViewContext.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/AbstractPluginViewContext.java
@@ -129,6 +129,11 @@ public abstract class AbstractPluginViewContext<T extends IClientServiceAsync> i
         return commonViewContext.getImageBundle();
     }
 
+    public boolean isDebuggingEnabled()
+    {
+        return commonViewContext.isDebuggingEnabled();
+    }
+
     // -------- IProfilingTable delegate
 
     /** @see IProfilingTable#log */
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/Client.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/Client.java
index ee9b77ecfad..bb1fb5bd64d 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/Client.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/Client.java
@@ -68,12 +68,18 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DisplaySettings;
  */
 public class Client implements EntryPoint, ValueChangeHandler<String>
 {
-    /** name of the URL parameter which decides if looging is switched on or off */
+    /** name of the URL parameter which decides if logging is switched on or off */
     private static final String LOGGING_PARAM = "log";
 
-    /** value of the URL parameter {@link #LOGGING_PARAM} which switches looging off */
+    /** value of the URL parameter {@link #LOGGING_PARAM} which switches logging on */
     private static final String LOGGING_ON = "true";
 
+    /** name of the URL parameter which decides if debugging is switched on or off */
+    private static final String DEBUGGING_PARAM = "debug";
+
+    /** value of the URL parameter {@link #DEBUGGING_PARAM} which switches debugging on */
+    private static final String DEBUGGING_ON = "true";
+
     private IViewContext<ICommonClientServiceAsync> viewContext;
 
     private final List<Controller> controllers = new ArrayList<Controller>();
@@ -112,7 +118,7 @@ public class Client implements EntryPoint, ValueChangeHandler<String>
 
         CommonViewContext commonContext =
                 new CommonViewContext(service, imageBundle, pageController, isLoggingEnabled(),
-                        getPageTitle());
+                        isDebuggingEnabled(), getPageTitle());
         commonContext.setClientPluginFactoryProvider(createPluginFactoryProvider(commonContext));
         initializeLocatorHandlerRegistry(commonContext.getLocatorResolverRegistry(), commonContext);
         return commonContext;
@@ -134,6 +140,12 @@ public class Client implements EntryPoint, ValueChangeHandler<String>
                 && GWTUtils.getParamString().contains(LOGGING_PARAM + "=" + LOGGING_ON);
     }
 
+    private boolean isDebuggingEnabled()
+    {
+        return GWTUtils.getParamString() != null
+                && GWTUtils.getParamString().contains(DEBUGGING_PARAM + "=" + DEBUGGING_ON);
+    }
+
     /**
      * Creates the provider for client plugin factories. Can be overridden in subclasses.
      */
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/CommonViewContext.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/CommonViewContext.java
index 8264bfe9ab9..f7ca9c0b5f0 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/CommonViewContext.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/CommonViewContext.java
@@ -96,13 +96,16 @@ public final class CommonViewContext implements IViewContext<ICommonClientServic
 
     private final IProfilingTable profilingTable;
 
+    private final boolean isDebuggingEnabled;
+
     CommonViewContext(final ICommonClientServiceAsync service,
             final IGenericImageBundle imageBundle, final IPageController pageController,
-            boolean isLoggingEnabled, String basicPageTitle)
+            boolean isLoggingEnabled, boolean isDebuggingEnabled, String basicPageTitle)
     {
         this.service = service;
         this.imageBundle = imageBundle;
         this.pageController = pageController;
+        this.isDebuggingEnabled = isDebuggingEnabled;
         this.profilingTable = ProfilingTable.create(isLoggingEnabled);
         messageProvider = new CompositeMessageProvider();
         messageProvider.add(new DictonaryBasedMessageProvider(TECHNOLOGY_NAME));
@@ -255,6 +258,11 @@ public final class CommonViewContext implements IViewContext<ICommonClientServic
         return profilingTable.isLoggingEnabled();
     }
 
+    public boolean isDebuggingEnabled()
+    {
+        return isDebuggingEnabled;
+    }
+
     public boolean isSimpleOrEmbeddedMode()
     {
         return ClientStaticState.isSimpleMode();
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/IViewContext.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/IViewContext.java
index 0d301185235..9af0af0a913 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/IViewContext.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/IViewContext.java
@@ -63,4 +63,9 @@ public interface IViewContext<T extends IClientServiceAsync> extends IMessagePro
      */
     public boolean isSimpleOrEmbeddedMode();
 
+    /**
+     * @return true if the debug panel should be added to UI.
+     */
+    public boolean isDebuggingEnabled();
+
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/framework/AppView.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/framework/AppView.java
index fcb387247be..203aa30511e 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/framework/AppView.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/framework/AppView.java
@@ -17,9 +17,11 @@
 package ch.systemsx.cisd.openbis.generic.client.web.client.application.framework;
 
 import com.extjs.gxt.ui.client.Style.LayoutRegion;
+import com.extjs.gxt.ui.client.Style.Scroll;
 import com.extjs.gxt.ui.client.mvc.AppEvent;
 import com.extjs.gxt.ui.client.mvc.Controller;
 import com.extjs.gxt.ui.client.mvc.View;
+import com.extjs.gxt.ui.client.widget.ContentPanel;
 import com.extjs.gxt.ui.client.widget.LayoutContainer;
 import com.extjs.gxt.ui.client.widget.Viewport;
 import com.extjs.gxt.ui.client.widget.layout.BorderLayout;
@@ -115,7 +117,16 @@ final class AppView extends View
 
     private final void createSouth()
     {
-        if (getViewMode() != ViewMode.EMBEDDED)
+        if (viewContext.isDebuggingEnabled())
+        {
+            final BorderLayoutData data = new BorderLayoutData(LayoutRegion.SOUTH, 200);
+            data.setSplit(true);
+            final ContentPanel panel = new ContentPanel();
+            panel.setScrollMode(Scroll.AUTO);
+            panel.setHeaderVisible(false);
+            panel.add(DebugPanelManager.createDebugPanel());
+            viewport.add(panel, data);
+        } else if (getViewMode() != ViewMode.EMBEDDED)
         {
             final Footer footer = new Footer(viewContext);
             final BorderLayoutData data = new BorderLayoutData(LayoutRegion.SOUTH, 20);
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/framework/DebugPanelManager.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/framework/DebugPanelManager.java
new file mode 100644
index 00000000000..43511636617
--- /dev/null
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/framework/DebugPanelManager.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2011 ETH Zuerich, CISD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package ch.systemsx.cisd.openbis.generic.client.web.client.application.framework;
+
+import com.google.gwt.debugpanel.client.DefaultCookieDebugPanelComponent;
+import com.google.gwt.debugpanel.client.DefaultDebugStatisticsDebugPanelComponent;
+import com.google.gwt.debugpanel.client.DefaultExceptionDebugPanelComponent;
+import com.google.gwt.debugpanel.client.DefaultRawLogDebugPanelComponent;
+import com.google.gwt.debugpanel.client.DefaultStatisticsModelRpcEventHandler;
+import com.google.gwt.debugpanel.client.DefaultStatisticsModelStartupEventHandler;
+import com.google.gwt.debugpanel.client.DelayedDebugPanelComponent;
+import com.google.gwt.debugpanel.common.GwtStatisticsEventSystem;
+import com.google.gwt.debugpanel.models.GwtDebugStatisticsModel;
+import com.google.gwt.debugpanel.models.GwtExceptionModel;
+import com.google.gwt.debugpanel.widgets.DebugPanelWidget;
+import com.google.gwt.user.client.ui.Widget;
+
+public class DebugPanelManager implements DebugPanelWidget.Listener
+{
+    private GwtStatisticsEventSystem sys;
+
+    private DefaultDebugStatisticsDebugPanelComponent panelComponent;
+
+    private DelayedDebugPanelComponent xmlComponent;
+
+    private DefaultRawLogDebugPanelComponent logComponent;
+
+    private GwtDebugStatisticsModel sm;
+
+    private GwtExceptionModel em;
+
+    public static Widget createDebugPanel()
+    {
+        DebugPanelManager manager = new DebugPanelManager();
+        return manager.createWidget();
+    }
+
+    DebugPanelManager()
+    {
+        sys = new GwtStatisticsEventSystem();
+        panelComponent = new DefaultDebugStatisticsDebugPanelComponent(null);
+        xmlComponent = panelComponent.xmlComponent();
+        logComponent = new DefaultRawLogDebugPanelComponent(sys);
+        em = new GwtExceptionModel();
+    }
+
+    private Widget createWidget()
+    {
+        return new DebugPanelWidget(this, true, new DebugPanelWidget.Component[]
+            { panelComponent, new DefaultExceptionDebugPanelComponent(em),
+                    new DefaultCookieDebugPanelComponent(), logComponent, xmlComponent });
+    }
+
+    // @Override
+    public void onShow()
+    {
+        panelComponent.reset(sm =
+                new GwtDebugStatisticsModel(new DefaultStatisticsModelStartupEventHandler(),
+                        new DefaultStatisticsModelRpcEventHandler()));
+        xmlComponent.reset();
+        logComponent.reset();
+
+        sys.addListener(sm, false);
+        sys.addListener(em, false);
+        sys.enable(true);
+    }
+
+    // @Override
+    public void onReset()
+    {
+        sys.removeListener(sm);
+        sys.removeListener(em);
+
+        panelComponent.reset(null);
+        sys.clearEventHistory();
+    }
+}
\ No newline at end of file
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/public/index.html b/openbis/source/java/ch/systemsx/cisd/openbis/public/index.html
index 535663274c4..f32d925e726 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/public/index.html
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/public/index.html
@@ -9,12 +9,24 @@
 <link rel="shortcut icon" href="images/favicon.ico" />
 <link rel="icon" type="image/png" href="images/favicon.png" />
 <link rel="stylesheet" type="text/css" href="resources/css/gxt-all.css" />
+<link rel="stylesheet" type="text/css" href="resources/css/debug-panel.css" />
 
 <!--
 // This script loads your compiled module. If you add any GWT meta tags, they must be added before this line.
 -->
-<script language="javascript"
-    src="ch.systemsx.cisd.openbis.OpenBIS.nocache.js"></script>
+<script language="javascript" src="ch.systemsx.cisd.openbis.OpenBIS.nocache.js"/>
+
+<!-- This snippet should be automatically included in all the HTML that wishes to use the debug panel. -->
+<script type="text/javascript" language="javascript">
+    var stats = window.__stats = [];
+    window.__gwtStatsEvent = function(evt) {
+      stats[stats.length] = evt;
+      var listener = window.__stats_listener;
+      listener && listener(evt);
+      return true;
+    }
+</script>
+
 </head>
 <!--
 // The body can have arbitrary html, or you can leave the body empty if you want to create a completely dynamic ui.
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/public/resources/css/debug-panel.css b/openbis/source/java/ch/systemsx/cisd/openbis/public/resources/css/debug-panel.css
new file mode 100644
index 00000000000..38b0f0886e5
--- /dev/null
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/public/resources/css/debug-panel.css
@@ -0,0 +1,209 @@
+/*
+Copyright 2009 Google Inc.
+
+Licensed under the Apache License, Version 2.0 (the "License"); you may not
+use this file except in compliance with the License. You may obtain a copy
+of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+License for the specific language governing permissions and limitations
+under the License.
+*/
+
+/* This is the div containing the entire panel. */
+div.DebugPanel-panel {
+  padding: 5px;
+  margin-left: 20px;
+  margin-right: 20px;
+}
+
+/* All the action links like show this, hide that, etc... */
+.DebugPanel-link {
+  font-size: smaller;
+  color: gray;
+  padding-right: 1em;
+}
+
+/* The tree table showing the events. */
+.DebugPanel-TreeTable {
+  border: 1px solid black;
+  border-collapse: collapse;
+}
+
+.DebugPanel-TreeTable td {
+  border: 1px solid black;
+  padding: 3px;
+  vertical-align: top;
+}
+
+.DebugPanel-TreeTable-header {
+  background-color: #d3d3d3;
+  font-weight: bold;
+}
+
+/* The first column (containing the tree) of the tree table. */
+.DebugPanel-tree {
+  white-space: nowrap;
+}
+
+/* The column showing the time in the tree table. */
+.DebugPanel-time {
+  text-align: right;
+}
+
+/* The column showing the service in the tree table. */
+.DebugPanel-code {
+  font-family: courier, monospace;
+}
+
+/* The XML debug panel component. */
+.DebugPanel-xml {
+  width: 50em;
+  height: 10em;
+  margin-top: 5px;
+}
+
+/* The main debug panel filter div. */
+.DebugPanel-filters {
+  margin-bottom: 5px;
+}
+
+/* The "Currently filtering" label. */
+.DebugPanel-filterTrailLabel {
+  font-weight: bold;
+  margin-left: 5px;
+}
+
+/* Each item in the active filter trail. */
+.DebugPanel-filterTrail-item {
+  margin-left: 5px;
+  color: black;
+  text-decoration: none;
+}
+
+.DebugPanel-filterTrail-item:hover {
+  text-decoration: underline;
+}
+
+/* The popup shown when clicking the filter menu button. */
+.DebugPanel-filterPopup {
+  border: 1px solid #ddd;
+  border-color: #ddd #000 #000 #ddd;
+  background: #fff;
+  position: absolute;
+  padding: 5px;
+}
+
+/* An item in the filter popup drop down menu. */
+.DebugPanel-filterMenuItem {
+  padding: 3px;
+  cursor: pointer;
+  white-space: nowrap;
+}
+
+.DebugPanel-filterMenuItem.active {
+  font-weight: bold;
+}
+
+.DebugPanel-filterMenuItem.selected {
+  font-style: italic;
+  background-color: #e0e6f1;
+}
+
+/* The settings portion of the filter popup. */
+.DebugPanel-filterSettings {
+  background-color: #e0e6f1;
+  height: 100%;
+  padding-left: 5px;
+  padding-right: 5px;
+}
+
+.DebugPanel-filterSettingsTitle {
+  font-weight: bold;
+  font-size: larger;
+  margin-bottom: 5px;
+}
+
+.DebugPanel-filterSettingsDescription {
+  font-size: smaller;
+  font-style: italic;
+  padding-bottom: 5px;
+}
+
+.DebugPanel-filterSettingsLabel {
+  font-weight: bold;
+  padding: 5px;
+}
+
+/* The div containing the buttons shown below the settings. */
+.DebugPanel-filterSettingsButtons {
+  padding-top: 5px;
+  padding-bottom: 5px;
+}
+
+.DebugPanel-filterSettingsButtons td {
+  padding-right: 5px;
+}
+
+/* The table showing the raw event log. */
+.DebugPanel-log {
+  border: 1px solid black;
+  border-collapse: collapse;
+  margin-top: 5px;
+}
+
+.DebugPanel-log td {
+  border: 1px solid black;
+  padding: 3px;
+  vertical-align: top;
+}
+
+.DebugPanel-logHeader td {
+  background-color: #d3d3d3;
+  font-weight: bold;
+}
+
+/* The table showing the cookies. */
+.DebugPanel-cookies {
+  border: 1px solid black;
+  border-collapse: collapse;
+  margin-top: 5px;
+}
+
+.DebugPanel-cookies td {
+  border: 1px solid black;
+  padding: 3px;
+}
+
+.DebugPanel-cookiesHeader {
+  background-color: #d3d3d3;
+  font-weight: bold;
+}
+
+/* The table showing the exception log. */
+.DebugPanel-errors {
+  border: 1px solid black;
+  border-collapse: collapse;
+  margin-top: 5px;
+}
+
+.DebugPanel-errors td {
+  border: 1px solid black;
+  padding: 3px;
+  vertical-align: top;
+}
+
+.DebugPanel-errorsHeader {
+  background-color: #d3d3d3;
+  font-weight: bold;
+}
+
+/* The stack trace of an exception in the error view. */
+.DebugPanel-codePre {
+  font-family: courier, monospace;
+  white-space: pre;
+}
-- 
GitLab