Console module

Copyright © 2005-2012 Opera Software ASA. All rights reserved. This file is part of the Opera web browser. It may not be distributed under any circumstances.

Introduction

The Console module provides the OpConsoleEngine interface used to store and retrieve error or informational messages to display in the interface in Opera. These messages can come from various sources, such as the EcmaScript engine or the e-mail client.

The OpConsoleLogger class is used to log messages handled by the console to a file. The default implementation supports basic filtering based on source and severity, but can be extended to provide more context-based filtering.

The OpConsoleView is the back-end for the UI console interface and works together with the user interface code, represented by the OpConsoleViewHandler API, to provide the console dialogue and its functionality. This class is enabled by importing the API_CON_UI_GLUE API.

Current information about the Console module.

Interface overview and API documentation

The API documentation is extracted automatically by Doxygen.

Use-cases

Posting messages to the general message console

To post a message to the message console, you first need to set up a OpConsoleEngine::Message structure with the proper data. The format of the context variable is not specified, but is up to the module posting the message, but since it is generally included in the console dialogue, it should be set to something meaningful, if used.

When the message has been set up, call OpConsoleEngine::PostMessageL() (g_console->PostMessageL()) with the message. In return, you will get the id number for the message just posted.

Logging messages to file

By using an instance of the OpConsoleLogger class, or an inherited version of it, messages that are posted to the console can easily be logged to a file.

The console module by defaults sets up a logger object configurable through the preferences system, and other code can instantiate other loggers as needed.

Listening to console messages

To listen to messages sent to the console, re-implement the OpConsoleListener interface and call OpConsoleEngine::RegisterConsoleListener(). NewConsoleMessage() will be called for all messages posted to the console, no matter what the source, the listener implementation will need to do any filtering, for instance using the OpConsoleFilter class.

Implementing a console dialog

To implement a console dialog, inherit the OpConsoleViewHandler class in your user interface code, and set up a OpConsolveView object with a reference to this object. The view handler object will then be signalled each time a message that corresponds to the associated filter is posted to the console.

To refresh the view using a new filter, use the OpConsoleView::SendAllComponentMessages() API.

Supported standards

None.

Implementation and design

Generalisation and re-implementation

If you need to have more advanced selection criteria when creating a log file using OpConsoleLogger than what is provided by the OpConsoleFilter class, you can inherit the class and re-implement the NewConsoleMessage() method. The actual logging to file is separated into a LogMessage() method to allow for this.

Memory management

Heap usage

OpConsoleEngine has a ring-buffer of posted messages in memory at all times, so that the console views do not need to hold copies. The size of this buffer is determined when the engine class is created, and is determined by the PrefsCollectionCore::MaxConsoleMessages preference. By calling OpConsoleMessage::Clear(), the messages (strings) stored in the ring-buffer will be cleared, but the actual buffer itself will be kept in memory.

OpConsoleLogger holds pointers to an OpConsoleFilter and an OpFileDescriptor object. The latter object is most probably instantiated as a full OpFile, although the logger object is oblivious to that fact.

OpConsoleFilter holds a simple array of severity levels for each message source. If host overrides are enabled, it will also host a linked list of host override objects, one for each host that has an overridden value.

OpConsolePrefsHelper takes care of the general console log file configured in the preferences. For that purpose it holds an OpConsoleLogger object. This object is internal to the console module.

OpConsoleView is a light-weight class used to interface with the UI.

Stack usage

There are no recursive calls, and no arrays or large objects are allocated on the stack. When OpConsoleEngine::PostMessageL() is called, the engine will post a message in the main message queue, so that it later can call all the registered listeners, in order, with information about the new message. This is done to avoid deep stacks when calling out to the listeners. If several messages are posted at once, these will be forwarded to the listeners in a burst later on.

When preferences change regarding the console log file, the OpConsolePrefsHelper object will be called, since it is registered as a preference listener. It will then post a message in the message queue and reconfigure itself.

Static memory usage

All global variables are handled through the ConsoleModule class. There is one object representing the console engine, and, if enabled, one object handling the console log file. If console logging is disabled, the object does not get created.

OOM policies

Most interfaces to functionality that can require memory to be allocated and where local out of memory handling is difficult are using the TRAP/LEAVE convention. In other cases, methods either return OP_STATUS (especially for code that collaborates with the UI), or raises errors to the global memory manager (for code that runs from the message loop).

The code for the general console logger will retry reconfiguration later if it gets an out of memory when the preferences have changed.

Performance

The message buffer is implemented as an array, so message lookups are just a matter of array indexing. The console filter lookups are also array indexing, so the filter lookup should not be very expensive.