Home | History | Annotate | Download | only in status_icons
      1 // Copyright 2014 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #ifndef CHROME_BROWSER_UI_VIEWS_STATUS_ICONS_STATUS_TRAY_STATE_CHANGER_WIN_H_
      6 #define CHROME_BROWSER_UI_VIEWS_STATUS_ICONS_STATUS_TRAY_STATE_CHANGER_WIN_H_
      7 
      8 #include "base/memory/scoped_ptr.h"
      9 #include "base/strings/string16.h"
     10 #include "base/threading/non_thread_safe.h"
     11 #include "base/win/iunknown_impl.h"
     12 #include "base/win/scoped_comptr.h"
     13 
     14 // The known values for NOTIFYITEM's dwPreference member.
     15 enum NOTIFYITEM_PREFERENCE {
     16   // In Windows UI: "Only show notifications."
     17   PREFERENCE_SHOW_WHEN_ACTIVE = 0,
     18   // In Windows UI: "Hide icon and notifications."
     19   PREFERENCE_SHOW_NEVER = 1,
     20   // In Windows UI: "Show icon and notifications."
     21   PREFERENCE_SHOW_ALWAYS = 2
     22 };
     23 
     24 // NOTIFYITEM describes an entry in Explorer's registry of status icons.
     25 // Explorer keeps entries around for a process even after it exits.
     26 struct NOTIFYITEM {
     27   PWSTR exe_name;    // The file name of the creating executable.
     28   PWSTR tip;         // The last hover-text value associated with this status
     29                      // item.
     30   HICON icon;        // The icon associated with this status item.
     31   HWND hwnd;         // The HWND associated with the status item.
     32   DWORD preference;  // Determines the behavior of the icon with respect to
     33                      // the taskbar. Values taken from NOTIFYITEM_PREFERENCE.
     34   UINT id;           // The ID specified by the application.  (hWnd, uID) is
     35                      // unique.
     36   GUID guid;         // The GUID specified by the application, alternative to
     37                      // uID.
     38 };
     39 
     40 // INotificationCB is an interface that applications can implement in order to
     41 // receive notifications about the state of the notification area manager.
     42 class __declspec(uuid("D782CCBA-AFB0-43F1-94DB-FDA3779EACCB")) INotificationCB
     43     : public IUnknown {
     44  public:
     45   virtual HRESULT STDMETHODCALLTYPE
     46       Notify(ULONG event, NOTIFYITEM* notify_item) = 0;
     47 };
     48 
     49 // A class that is capable of reading and writing the state of the notification
     50 // area in the Windows taskbar.  It is used to promote a tray icon from the
     51 // overflow area to the taskbar, and refuses to do anything if the user has
     52 // explicitly marked an icon to be always hidden.
     53 class StatusTrayStateChangerWin : public INotificationCB,
     54                                   public base::win::IUnknownImpl,
     55                                   public base::NonThreadSafe {
     56  public:
     57   StatusTrayStateChangerWin(UINT icon_id, HWND window);
     58 
     59   // Call this method to move the icon matching |icon_id| and |window| to the
     60   // taskbar from the overflow area.  This will not make any changes if the
     61   // icon has been set to |PREFERENCE_SHOW_NEVER|, in order to comply with
     62   // the explicit wishes/configuration of the user.
     63   void EnsureTrayIconVisible();
     64 
     65   // IUnknown.
     66   virtual ULONG STDMETHODCALLTYPE AddRef() OVERRIDE;
     67   virtual ULONG STDMETHODCALLTYPE Release() OVERRIDE;
     68   virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID, PVOID*) OVERRIDE;
     69 
     70   // INotificationCB.
     71   // Notify is called in response to RegisterCallback for each current
     72   // entry in Explorer's list of notification area icons, and ever time
     73   // one of them changes, until UnregisterCallback is called or |this|
     74   // is destroyed.
     75   virtual HRESULT STDMETHODCALLTYPE Notify(ULONG, NOTIFYITEM*);
     76 
     77  protected:
     78   virtual ~StatusTrayStateChangerWin();
     79 
     80  private:
     81   friend class StatusTrayStateChangerWinTest;
     82 
     83   enum InterfaceVersion {
     84     INTERFACE_VERSION_LEGACY = 0,
     85     INTERFACE_VERSION_WIN8,
     86     INTERFACE_VERSION_UNKNOWN
     87   };
     88 
     89   // Creates an instance of TrayNotify, and ensures that it supports either
     90   // ITrayNotify or ITrayNotifyWin8.  Returns true on success.
     91   bool CreateTrayNotify();
     92 
     93   // Returns the NOTIFYITEM that corresponds to this executable and the
     94   // HWND/ID pair that were used to create the StatusTrayStateChangerWin.
     95   // Internally it calls the appropriate RegisterCallback{Win8,Legacy}.
     96   scoped_ptr<NOTIFYITEM> RegisterCallback();
     97 
     98   // Calls RegisterCallback with the appropriate interface required by
     99   // different versions of Windows.  This will result in |notify_item_| being
    100   // updated when a matching item is passed into
    101   // StatusTrayStateChangerWin::Notify.
    102   bool RegisterCallbackWin8();
    103   bool RegisterCallbackLegacy();
    104 
    105   // Sends an update to Explorer with the passed NOTIFYITEM.
    106   void SendNotifyItemUpdate(scoped_ptr<NOTIFYITEM> notify_item);
    107 
    108   // Storing IUnknown since we will need to use different interfaces
    109   // for different versions of Windows.
    110   base::win::ScopedComPtr<IUnknown> tray_notify_;
    111   InterfaceVersion interface_version_;
    112 
    113   // The ID assigned to the notification area icon that we want to manipulate.
    114   const UINT icon_id_;
    115   // The HWND associated with the notification area icon that we want to
    116   // manipulate.  This is an unretained pointer, do not dereference.
    117   const HWND window_;
    118   // Executable name of the current program.  Along with |icon_id_| and
    119   // |window_|, this uniquely identifies a notification area entry to Explorer.
    120   base::string16 file_name_;
    121 
    122   // Temporary storage for the matched NOTIFYITEM.  This is necessary because
    123   // Notify doesn't return anything.  The call flow looks like this:
    124   //   TrayNotify->RegisterCallback()
    125   //      ... other COM stack frames ..
    126   //   StatusTrayStateChangerWin->Notify(NOTIFYITEM);
    127   // so we can't just return the notifyitem we're looking for.
    128   scoped_ptr<NOTIFYITEM> notify_item_;
    129 
    130   DISALLOW_COPY_AND_ASSIGN(StatusTrayStateChangerWin);
    131 };
    132 
    133 #endif  // CHROME_BROWSER_UI_VIEWS_STATUS_ICONS_STATUS_TRAY_STATE_CHANGER_WIN_H_
    134