My favorites | English | Sign in

Google Desktop APIs (Labs)

Event Notification Developer Guide

The Google Desktop Event Notification Framework allows plug-ins to receive notifications when new items are being indexed.

Examples:

  • EventAPI (online and in the SDK)
  • samples/search/event_framework (in the SDK)
  • Contents

    1. Overview
      1. Getting Started
      2. Development Process Overview
    2. Event Notification Developer API
      1. Registering Event Notification Plug-ins
        1. Component Registration Interface Summary
      2. Using the Event Notification Framework

    Overview

    Getting Started

    To use event notifications you will need, in addition to the information in this document:

    • Sufficient access to write a plug-in for your application and an installer for it.
    • Programming knowledge of the Microsoft Windows Component Object Model (COM).

    Development Process Overview

    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:

    • Register your application with Google Desktop (required).
    • Subscribe to receive event notifications and implement the required callbacks.
    • Unregister your application with Google Desktop when your application uninstalls.

    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.

    Back to top

    Event Notification Developer API

    Registering Event Notification Components

    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.

    Component Registration Interface Summary

    The following summarizes the interface and its methods. All method return values are of type HRESULT.

    interface IGoogleDesktopRegistrar: IDispatch
    • Note: Components are required to call this interface to register themselves with Google Desktop before they can interact with any APIs or other provided services.
    • Note: The registration process consists of a call to 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.
      • Arguments:
        • 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.
      • Returns:
        • S_OK if successful.
        • E_COMPONENT_ALREADY_REGISTERED if this component has already been registered with Google Desktop.
        • Appropriate error on failure, such as an unregistered component classID or appID, component prohibited by policy, etc.

    • GetRegistrationInterface: Provides the requested type of registration interface.
      • Arguments:
        • 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.
      • Returns:
        • S_OK if successful.
        • Appropriate error on failure.

    • FinishComponentRegistration: Must be invoked to finish the registration process.
      • Returns:
        • S_OK if successful.
        • Appropriate error on failure, such as an unregistered component classID or appID, component prohibited by policy, etc.

    • UnregisterComponent
      • Arguments:
        • BSTR component_guid_or_progid: the same GUID used when registering the component.
      • Returns:
        • S_OK if successful.
        • Appropriate error on failure.

    Component Registration Code Template

    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);
    }
    

    Back to top

    Using the Event Notification Framework

    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.

    Subscribing for Event Notifications

    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.
      • Arguments:
        • 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.
      • Returns:
        • S_OK if successful.
        • Appropriate error on failure.
    • Unsubscribe: Invoke to stop receiving notification events and free any associated resources.
      • Arguments:
        • IGoogleDesktopEventSubscription* subscription: The the subscription object.
      • Returns:
        • S_OK if successful.
        • Appropriate error on failure.

    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.
      • Arguments:
        • GoogleDesktopSubscriptionFilterOperator op: One of the and/or operators (GD_FILTER_OPERATOR_AND, GD_FILTER_OPERATOR_OR).
      • Returns:
        • S_OK if successful.
        • Appropriate error on failure.
    • negate_result: Get/Put property negates the result of filtering.
      • Arguments:
        • [out, retval] VARIANT_BOOL * not: .
      • Returns: If true, negates the result of filtering
        • S_OK if successful.
        • Appropriate error on failure.
    • AddFilter: Add a new filter for the event stream.
      • Arguments:
        • BSTR progid: The prog id of the filter to add.
        • [in, optional] VARIANT name: Optional filter name.
        • [out, retval] IDispatch** filter: The filter object.
      • Returns:
        • S_OK if successful.
        • Appropriate error on failure.
    • RemoveFilter: Remove a filter from the event stream.
      • Arguments:
        • IDispatch* filter: The filter object.
      • Returns:
        • S_OK if successful.
        • Appropriate error on failure.
    • FindFilter: Find an event filter given a name.
      • Arguments:
        • BSTR filter_name: The filter name.
        • [out, retval] IDispatch** filter: The filter object.
      • Returns:
        • S_OK if successful.
        • Appropriate error on failure.
    • RemoveAllFilters: Remove all filters from the subscription.
      • Arguments:
      • Returns:
        • S_OK if successful.
        • Appropriate error on failure.
    interface IGoogleDesktopEventSubscription: IGoogleDesktopFilterCollection
    • active: Get/Put property used to enable/disable a subscription.
      • Arguments:
        • VARIANT_BOOL event_stream_enabled: Enable/disable switch.
      • Returns:
        • S_OK if successful.
        • Appropriate error on failure.

    Filtering Event Notifications

    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.
      • Arguments:
      • Returns:
        • S_OK if successful.
        • Appropriate error on failure.
    • Allow: Add the specified schema to the array of allowed schema names.
      • Arguments:
        • BSTR schema_name: Name of the allowed schema.
      • Returns:
        • S_OK if successful.
        • Appropriate error on failure.
    • Disallow: Remove the specified schema from the array of allowed schema names.
      • Arguments:
        • BSTR schema_name: Name of the removed schema.
      • Returns:
        • S_OK if successful.
        • Appropriate error on failure.
    • GetAllowed: Retrieves the array of allowed schema names.
      • Arguments:
        • [out, retval] SAFEARRAY(VARIANT)* schema_names: Array containing the allowed schema names.
      • Returns:
        • S_OK if successful.
        • Appropriate error on failure.
    interface IGoogleDesktopSchemaPropertyFilter: IDispatch
    • AddRequiredText: Adds the specified string to the array of strings required in the property.
      • Arguments:
        • BSTR property_name: The property name to filter on.
        • BSTR required: The string required in the property.
      • Returns:
        • S_OK if successful.
        • Appropriate error on failure.
    • AddExcludedText: Adds the specified string to the array of strings excluded from the property.
      • Arguments:
        • BSTR property_name: The property name to filter on.
        • BSTR required: The string excluded from the property.
      • Returns:
        • S_OK if successful.
        • Appropriate error on failure.
    • RemoveRequiredText: Removes the specified string from the array of strings required in the property.
      • Arguments:
        • BSTR property_name: The property name to filter on.
        • BSTR required: The string to be removed.
      • Returns:
        • S_OK if successful.
        • Appropriate error on failure.
    • RemoveExcludedText: Removes the specified string from the array of strings excluded from the property.
      • Arguments:
        • BSTR property_name: The property name to filter on.
        • BSTR required: The string to be removed.
      • Returns:
        • S_OK if successful.
        • Appropriate error on failure.
    • GetRequiredText: Retrieves the array of strings required in the property.
      • Arguments:
        • BSTR property_name: The property name to filter on.
        • [out, retval] SAFEARRAY(VARIANT)* required: Array of strings.
      • Returns:
        • S_OK if successful.
        • Appropriate error on failure.
    • GetExcludedText: Retrieves the array of strings excluded from the property.
      • Arguments:
        • BSTR property_name: The property name to filter on.
        • [out, retval] SAFEARRAY(VARIANT)* excluded: Array of strings.
      • Returns:
        • S_OK if successful.
        • Appropriate error on failure.
    • match_whole_word: Put property that specifies if matching is restricted to whole words.
      • Arguments:
        • [in] VARIANT_BOOL whole: If true, match whole words.
      • Returns:
        • S_OK if successful.
        • Appropriate error on failure.

    Receiving an Event Notification

    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.
      • Arguments:
        • BSTR property_name: The property name.
        • [out, retval] VARIANT* property_value: The value of the property.
      • Returns:
        • S_OK if successful.
        • Appropriate error on failure.
    • SchemaName: Get property which holds the name of the schema that the event is derived from.
      • Arguments:
        • [out, retval] BSTR* schema_name: The schema name.
      • Returns:
        • S_OK if successful.
        • Appropriate error on failure.

    Event Notification Code Template

    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}};	

    Back to top