The Google Desktop Event Notification Framework allows plug-ins to receive notifications when new items are being indexed.
Examples:
samples/search/event_framework
(in the
SDK)
To use event notifications you will need, in addition to the information in this document:
To develop an Event Notification plug-in, start by downloading the
SDK, in particular the GoogleDesktopAPI.idl
file. We recommend developing your application with Microsoft Visual Studio.
You will then need to write code to:
We recommend that you look over the sample code provided with the SDK. Please note that the sample code examples have their GUIDs hardcoded, so if you choose to reuse code from there you must change the interfaceIDs, classIDs, and libIDs to ones valid for your application.
Google Desktop will not accept unregistered components. The Event
Notification component registration is a one-time process done using the
IGoogleDesktopRegistrar
interface, and should be
done during component installation. As part of the registration process, the
component must provide its GUID as well as information about itself.
As part of its uninstallation process, a component should unregister itself with Google Desktop.
The following summarizes the interface and its methods. All
method return values are of type HRESULT
.
interface IGoogleDesktopRegistrar: IDispatch
StartComponentRegistration
followed by individual
registrations for various services
obtained through GetRegistrationInterface
and finished by a call to FinishComponentRegistration.
For event components, the
registration progid is "GoogleDesktop.EventRegistration"
and the interface is IGoogleDesktopRegisterEventPlugin
.
StartComponentRegistration
: Must be invoked by any
component to initiate the registration process.
BSTR component_guid_or_progid
: The component's GUID
or ProgID.
VARIANT
component_description: A SAFEARRAY
of pairs, where the first element is a descriptive parameter name
and the second element is that parameter's value. The method expects only the
following three required parameters, which should be given in this order.
Title
": Component title that
will be displayed on the Google Desktop preferences page.
Description
": Component
description that will be displayed on the Google Desktop preferences page.
Icon
": A string pointing to
an ICON resource, of the form "c:\program files\boo\comp.dll,23
".
This icon may be used to indicate the component and its results on various Google Desktop
pages.
S_OK
if successful.
E_COMPONENT_ALREADY_REGISTERED
if this component has
already been registered with Google Desktop.
GetRegistrationInterface
: Provides the requested
type of registration interface.
BSTR registration_type
: a stringified CLSID or a
progid to the type of registration required.
[out, retval] IUnknown **registration_interface
:
provides the requested registration mechanism.
S_OK
if successful.
FinishComponentRegistration
: Must be invoked to
finish the registration process.
S_OK
if successful.
UnregisterComponent
BSTR component_guid_or_progid
: the same GUID used
when registering the component.
S_OK
if successful.
The following template demonstrates how a component can register for event notifications. Note that this registration should only be done once, not every time the plug-in starts.
To register a component:
CComPtr<IGoogleDesktopRegistrar> spRegistrar; HRESULT hr = spRegistrar.CoCreateInstance(CLSID_GoogleDesktopRegistrar); if (SUCCEEDED(hr)) { ATLASSERT(spRegistrar != NULL); // Component description is 6 strings CComSafeArray<VARIANT> arr_descr(6); arr_descr.SetAt(0, CComVariant(L"Title")); arr_descr.SetAt(1, CComVariant(L"A sample event notification plug-in")); arr_descr.SetAt(2, CComVariant(L"Description")); arr_descr.SetAt(3, CComVariant(L"Implements sample event notifications")); arr_descr.SetAt(4, CComVariant(L"Icon")); arr_descr.SetAt(5, CComVariant(L",1")); // our CLSID in string format CComBSTR our_clsid(clsid); // Wrap description array in variant CComVariant descr(arr_descr.m_psa); // and register hr = spRegistrar->StartComponentRegistration(our_clsid, descr); if (FAILED(hr)) return hr; // success, now register as an event notification component. CComPtr<IGoogleDesktopRegisterEventPlugin> spRegistration; CComBSTR event_registrar_progid("GoogleDesktop.EventRegistration"); hr = spRegistrar->GetRegistrationInterface(event_registrar_progid, reinterpret_cast<IUnknown**>(&spRegistration)); ATLASSERT(FAILED(hr) || spRegistration); if (SUCCEEDED(hr)) { // registration cookie that will be used later on // to subscribe to event notifications long cookie = 0; hr = spRegistration->RegisterPlugin(CComBSTR(PLUGIN_GUID), &cookie); if (SUCCEEDED(hr)) { hr = spRegistrar->FinishComponentRegistration(); } // store the registration cookie if (SUCCEEDED(hr)) { hr = StoreRegistrationCookie(cookie); } }
To unregister a component:
CComPtr<IGoogleDesktopRegistrar> spRegistrar; HRESULT hr = spRegistrar.CoCreateInstance(CLSID_GoogleDesktopRegistrar); if (SUCCEEDED(hr)) { // our CLSID in string format CComBSTR bstrClsid(clsid); hr = spRegistrar->UnregisterComponent(bstrClsid); }
After a successful registration with Google Desktop, a component can use the Event Notification APIs to subscribe to receive notifications about items being indexed as well as filter which events to receive based on specific criteria.
The Event Notification API consists of a set of COM interfaces which control how a subscription behaves. The entry point to the Event Notification Framework is the IGoogleDesktopEventPublisher interface.
interface IGoogleDesktopEventPublisher: IDispatch
Subscribe
: Subscribe to start receiving notification
events.
long registration_cookie
: The cookie received from
the registration procedure (see IGoogleDesktopRegisterEventPlugin).
IUnknown* subscriber
: The object that will receive
notification calls when events are received. Out-of-proc subscribers implement
IDispatch on this object and receive calls on either a method named
"OnNewEvent" or the default method that has the dispid DISPID_VALUE. OnNewEvent
accepts a single argument of type
IGoogleDesktopNotifyEvent
.
[out, retval] IGoogleDesktopEventSubscription** subscription
:
The subscription object.S_OK
if successful.
Unsubscribe
: Invoke to stop receiving notification
events and free any associated resources.
IGoogleDesktopEventSubscription* subscription
: The
the subscription object.
S_OK
if successful.
The following interfaces control a subscription. Before events are delivered to subscribers, they must pass through any filters that are active on the subscription.
interface IGoogleDesktopFilterCollection: IDispatch
filter_operator
: Get/Put property used to decide how
multiple filter results are combined.
GoogleDesktopSubscriptionFilterOperator op
: One of
the and/or operators (GD_FILTER_OPERATOR_AND, GD_FILTER_OPERATOR_OR).
S_OK
if successful.
negate_result
: Get/Put property negates the result
of filtering.
[out, retval] VARIANT_BOOL * not
: .
S_OK
if successful.
AddFilter
: Add a new filter for the event stream.
BSTR progid
: The prog id of the filter to add.
[in, optional] VARIANT name
: Optional filter name.
[out, retval] IDispatch** filter
: The filter object.
S_OK
if successful.
RemoveFilter
: Remove a filter from the event stream.
IDispatch* filter
: The filter object.
S_OK
if successful.
FindFilter
: Find an event filter given a name.
BSTR filter_name
: The filter name.
[out, retval] IDispatch** filter
: The filter object.
S_OK
if successful.
RemoveAllFilters
: Remove all filters from the
subscription.
S_OK
if successful.
interface IGoogleDesktopEventSubscription:
IGoogleDesktopFilterCollection
active
: Get/Put property used to enable/disable a
subscription.
VARIANT_BOOL event_stream_enabled
: Enable/disable
switch.
S_OK
if successful.
The following interfaces allow the plug-in to filter the event notifications based on specified schemas and the content of schema properties.
interface IGoogleDesktopSchemaFilter: IDispatch
AllowNone
: Clears all allowed values and disables
all event notifications.
S_OK
if successful.
Allow
: Add the specified schema to the array of
allowed schema names.
BSTR schema_name
: Name of the allowed schema.
S_OK
if successful.
Disallow
: Remove the specified schema from the array
of allowed schema names.
BSTR schema_name
: Name of the removed schema.
S_OK
if successful.
GetAllowed
: Retrieves the array of allowed schema
names.
[out, retval] SAFEARRAY(VARIANT)* schema_names
:
Array containing the allowed schema names.
S_OK
if successful.
interface IGoogleDesktopSchemaPropertyFilter: IDispatch
AddRequiredText
: Adds the specified string to the
array of strings required in the property.
BSTR property_name
: The property name to filter on.
BSTR required
: The string required in the property.
S_OK
if successful.
AddExcludedText
: Adds the specified string to the
array of strings excluded from the property.
BSTR property_name
: The property name to filter on.
BSTR required
: The string excluded from the
property.
S_OK
if successful.
RemoveRequiredText
: Removes the specified string
from the array of strings required in the property.
BSTR property_name
: The property name to filter on.
BSTR required
: The string to be removed.
S_OK
if successful.
RemoveExcludedText
: Removes the specified string
from the array of strings excluded from the property.
BSTR property_name
: The property name to filter on.
BSTR required
: The string to be removed.
S_OK
if successful.
GetRequiredText
: Retrieves the array of strings
required in the property.
BSTR property_name
: The property name to filter on.
[out, retval] SAFEARRAY(VARIANT)* required
: Array of
strings.
S_OK
if successful.
GetExcludedText
: Retrieves the array of strings
excluded from the property.
BSTR property_name
: The property name to filter on.
[out, retval] SAFEARRAY(VARIANT)* excluded
: Array of
strings.
S_OK
if successful.
match_whole_word
: Put property that specifies if
matching is restricted to whole words.
[in] VARIANT_BOOL whole
: If true, match whole words.
S_OK
if successful.
After successfully subscribing to the Event Notification Framework and setting filtering options, a plug-in will be called for each matching event through the subscriber object passed to the IGoogleDesktopEventPublisher.Subscribe method. Event information will be provided through the IGoogleDesktopNotifyEvent interface.
interface IGoogleDesktopNotifyEvent: IDispatch
GetProperty
: Returns the value of a named property.
BSTR property_name
: The property name.
[out, retval] VARIANT* property_value
: The value of the property.
S_OK
if successful.
SchemaName
: Get property which holds the name of the schema
that the event is derived from.
[out, retval] BSTR* schema_name
: The schema name.
S_OK
if successful.
The following template demonstrates how a plug-in subscribes to receive event notifications and how to configure the subscription.
// // Create an instance of the Google Desktop Event Publisher // and set up a subscription // CComPtr<IGoogleDesktopEventPublisher> publisher; hr = publisher.CoCreateInstance(L"GoogleDesktop.EventPublisher.1"); // A callback object that will receive notifications EventCallback callback; // The subscription that controls how events are delivered to us CComPtr<IGoogleDesktopEventSubscription> subscription; if (SUCCEEDED(hr)) { // Get the callback object CComPtr<IUnknown> callback_identity; hr = callback._LocDEQueryInterface(IID_IUnknown, reinterpret_cast<void**>(&callback_identity)); // Subscribe hr = publisher->Subscribe(cookie, callback_identity, &subscription); if (SUCCEEDED(hr)) { CComQIPtr<IGoogleDesktopSchemaFilter> schema_filter; // Add a schema filter CComPtr<IDispatch> disp; hr = sub->AddFilter(CComBSTR(L"GoogleDesktop.SchemaFilter"), CComVariant(), &disp); if (FAILED(hr)) return hr; // Filter on the Email schema schema_filter = disp; hr = schema_filter->Allow(CComBSTR(L"Google.Desktop.Email")); if (SUCCEEDED(hr)) { // Turn on the event stream and start receiving notifications subscription->put_active(VARIANT_TRUE); } } }
The code template below shows a sample callback implementation through which the plug-in receives notifications. The event information is passed in through an object implementing IGoogleDesktopNotifyEvent.
class EventCallback : public IDispEventSimpleImpl<1, EventCallback, &IID_IDispatch> { public: BEGIN_SINK_MAP(EventCallback) SINK_ENTRY_INFO(1, IID_IDispatch, DISPID_VALUE, OnNewEvent, &s_OnNewEventInfo) END_SINK_MAP() /** * This function gets called by the event framework as this is the default * method on our class (DISPID_VALUE). */ STDMETHOD_(void, OnNewEvent)(IDispatch* event) { if (event == NULL) { _tprintf(_T("Historical indexing has just been done.\n")); } else { CComQIPtr<IGoogleDesktopNotifyEvent> e(event); ATLASSERT(e != NULL); CComBSTR schema; e->get_SchemaName(&schema); CComVariant uri; e->GetProperty(CComBSTR(L"uri"), &uri); _tprintf(_T("%ls: %ls\n"), schema, uri.vt == VT_BSTR ? uri.bstrVal : L"?"); } } static _ATL_FUNC_INFO s_OnNewEventInfo; }; _ATL_FUNC_INFO EventCallback::s_OnNewEventInfo = {CC_STDCALL, VT_EMPTY, 1, {VT_DISPATCH}};