15c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// Copyright 2014 The Chromium Authors. All rights reserved.
25c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// Use of this source code is governed by a BSD-style license that can be
35c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// found in the LICENSE file.
45c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
55c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#ifndef CHROME_BROWSER_UI_VIEWS_STATUS_ICONS_STATUS_TRAY_STATE_CHANGER_WIN_H_
65c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#define CHROME_BROWSER_UI_VIEWS_STATUS_ICONS_STATUS_TRAY_STATE_CHANGER_WIN_H_
75c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
85c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "base/memory/scoped_ptr.h"
95c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "base/strings/string16.h"
105c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "base/threading/non_thread_safe.h"
115c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "base/win/iunknown_impl.h"
125c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "base/win/scoped_comptr.h"
135c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
145c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// The known values for NOTIFYITEM's dwPreference member.
155c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuenum NOTIFYITEM_PREFERENCE {
165c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // In Windows UI: "Only show notifications."
175c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  PREFERENCE_SHOW_WHEN_ACTIVE = 0,
185c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // In Windows UI: "Hide icon and notifications."
195c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  PREFERENCE_SHOW_NEVER = 1,
205c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // In Windows UI: "Show icon and notifications."
215c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  PREFERENCE_SHOW_ALWAYS = 2
225c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu};
235c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
245c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// NOTIFYITEM describes an entry in Explorer's registry of status icons.
255c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// Explorer keeps entries around for a process even after it exits.
265c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liustruct NOTIFYITEM {
275c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  PWSTR exe_name;    // The file name of the creating executable.
285c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  PWSTR tip;         // The last hover-text value associated with this status
295c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                     // item.
305c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  HICON icon;        // The icon associated with this status item.
315c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  HWND hwnd;         // The HWND associated with the status item.
325c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  DWORD preference;  // Determines the behavior of the icon with respect to
335c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                     // the taskbar. Values taken from NOTIFYITEM_PREFERENCE.
345c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  UINT id;           // The ID specified by the application.  (hWnd, uID) is
355c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                     // unique.
365c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  GUID guid;         // The GUID specified by the application, alternative to
375c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                     // uID.
385c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu};
395c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
405c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// INotificationCB is an interface that applications can implement in order to
415c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// receive notifications about the state of the notification area manager.
425c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuclass __declspec(uuid("D782CCBA-AFB0-43F1-94DB-FDA3779EACCB")) INotificationCB
435c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    : public IUnknown {
445c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu public:
455c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  virtual HRESULT STDMETHODCALLTYPE
465c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      Notify(ULONG event, NOTIFYITEM* notify_item) = 0;
475c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu};
485c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
495c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// A class that is capable of reading and writing the state of the notification
505c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// area in the Windows taskbar.  It is used to promote a tray icon from the
515c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// overflow area to the taskbar, and refuses to do anything if the user has
525c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// explicitly marked an icon to be always hidden.
535c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuclass StatusTrayStateChangerWin : public INotificationCB,
545c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                  public base::win::IUnknownImpl,
555c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                  public base::NonThreadSafe {
565c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu public:
575c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  StatusTrayStateChangerWin(UINT icon_id, HWND window);
585c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
595c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // Call this method to move the icon matching |icon_id| and |window| to the
605c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // taskbar from the overflow area.  This will not make any changes if the
615c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // icon has been set to |PREFERENCE_SHOW_NEVER|, in order to comply with
625c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // the explicit wishes/configuration of the user.
635c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  void EnsureTrayIconVisible();
645c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
655c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // IUnknown.
665c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  virtual ULONG STDMETHODCALLTYPE AddRef() OVERRIDE;
675c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  virtual ULONG STDMETHODCALLTYPE Release() OVERRIDE;
685c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID, PVOID*) OVERRIDE;
695c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
705c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // INotificationCB.
715c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // Notify is called in response to RegisterCallback for each current
725c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // entry in Explorer's list of notification area icons, and ever time
735c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // one of them changes, until UnregisterCallback is called or |this|
745c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // is destroyed.
755c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  virtual HRESULT STDMETHODCALLTYPE Notify(ULONG, NOTIFYITEM*);
765c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
775c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu protected:
785c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  virtual ~StatusTrayStateChangerWin();
795c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
805c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu private:
815c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  friend class StatusTrayStateChangerWinTest;
825c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
835c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  enum InterfaceVersion {
845c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    INTERFACE_VERSION_LEGACY = 0,
855c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    INTERFACE_VERSION_WIN8,
865c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    INTERFACE_VERSION_UNKNOWN
875c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  };
885c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
895c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // Creates an instance of TrayNotify, and ensures that it supports either
905c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // ITrayNotify or ITrayNotifyWin8.  Returns true on success.
915c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  bool CreateTrayNotify();
925c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
935c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // Returns the NOTIFYITEM that corresponds to this executable and the
945c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // HWND/ID pair that were used to create the StatusTrayStateChangerWin.
955c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // Internally it calls the appropriate RegisterCallback{Win8,Legacy}.
965c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  scoped_ptr<NOTIFYITEM> RegisterCallback();
975c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
985c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // Calls RegisterCallback with the appropriate interface required by
995c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // different versions of Windows.  This will result in |notify_item_| being
1005c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // updated when a matching item is passed into
1015c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // StatusTrayStateChangerWin::Notify.
1025c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  bool RegisterCallbackWin8();
1035c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  bool RegisterCallbackLegacy();
1045c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
1055c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // Sends an update to Explorer with the passed NOTIFYITEM.
1065c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  void SendNotifyItemUpdate(scoped_ptr<NOTIFYITEM> notify_item);
1075c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
1085c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // Storing IUnknown since we will need to use different interfaces
1095c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // for different versions of Windows.
1105c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  base::win::ScopedComPtr<IUnknown> tray_notify_;
1115c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  InterfaceVersion interface_version_;
1125c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
1135c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // The ID assigned to the notification area icon that we want to manipulate.
1145c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  const UINT icon_id_;
1155c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // The HWND associated with the notification area icon that we want to
1165c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // manipulate.  This is an unretained pointer, do not dereference.
1175c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  const HWND window_;
1185c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // Executable name of the current program.  Along with |icon_id_| and
1195c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // |window_|, this uniquely identifies a notification area entry to Explorer.
1205c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  base::string16 file_name_;
1215c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
1225c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // Temporary storage for the matched NOTIFYITEM.  This is necessary because
1235c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // Notify doesn't return anything.  The call flow looks like this:
1245c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  //   TrayNotify->RegisterCallback()
1255c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  //      ... other COM stack frames ..
1265c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  //   StatusTrayStateChangerWin->Notify(NOTIFYITEM);
1275c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // so we can't just return the notifyitem we're looking for.
1285c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  scoped_ptr<NOTIFYITEM> notify_item_;
1295c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
1305c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  DISALLOW_COPY_AND_ASSIGN(StatusTrayStateChangerWin);
1315c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu};
1325c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
1335c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#endif  // CHROME_BROWSER_UI_VIEWS_STATUS_ICONS_STATUS_TRAY_STATE_CHANGER_WIN_H_
134