# Console module

## 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.