1 // Copyright (c) 2013 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 UI_SHELL_DIALOGS_BASE_SHELL_DIALOG_WIN_H_ 6 #define UI_SHELL_DIALOGS_BASE_SHELL_DIALOG_WIN_H_ 7 8 #include <shlobj.h> 9 #include <set> 10 11 #include "ui/shell_dialogs/base_shell_dialog.h" 12 #include "ui/shell_dialogs/shell_dialogs_export.h" 13 14 namespace base { 15 class Thread; 16 } 17 18 namespace ui { 19 20 /////////////////////////////////////////////////////////////////////////////// 21 // A base class for all shell dialog implementations that handles showing a 22 // shell dialog modally on its own thread. 23 class SHELL_DIALOGS_EXPORT BaseShellDialogImpl { 24 public: 25 BaseShellDialogImpl(); 26 virtual ~BaseShellDialogImpl(); 27 28 protected: 29 // Represents a run of a dialog. 30 struct RunState { 31 // Owning HWND, may be null. 32 HWND owner; 33 34 // Thread dialog is run on. 35 base::Thread* dialog_thread; 36 }; 37 38 // Called at the beginning of a modal dialog run. Disables the owner window 39 // and tracks it. Returns the message loop of the thread that the dialog will 40 // be run on. 41 RunState BeginRun(HWND owner); 42 43 // Cleans up after a dialog run. If the run_state has a valid HWND this makes 44 // sure that the window is enabled. This is essential because BeginRun 45 // aggressively guards against multiple modal dialogs per HWND. Must be called 46 // on the UI thread after the result of the dialog has been determined. 47 // 48 // In addition this deletes the Thread in RunState. 49 void EndRun(RunState run_state); 50 51 // Returns true if a modal shell dialog is currently active for the specified 52 // owner. Must be called on the UI thread. 53 bool IsRunningDialogForOwner(HWND owner) const; 54 55 // Disables the window |owner|. Can be run from either the ui or the dialog 56 // thread. Can be called on either the UI or the dialog thread. This function 57 // is called on the dialog thread after the modal Windows Common dialog 58 // functions return because Windows automatically re-enables the owning 59 // window when those functions return, but we don't actually want them to be 60 // re-enabled until the response of the dialog propagates back to the UI 61 // thread, so we disable the owner manually after the Common dialog function 62 // returns. 63 void DisableOwner(HWND owner); 64 65 private: 66 typedef std::set<HWND> Owners; 67 68 // Creates a thread to run a shell dialog on. Each dialog requires its own 69 // thread otherwise in some situations where a singleton owns a single 70 // instance of this object we can have a situation where a modal dialog in 71 // one window blocks the appearance of a modal dialog in another. 72 static base::Thread* CreateDialogThread(); 73 74 // Enables the window |owner_|. Can only be run from the ui thread. 75 void EnableOwner(HWND owner); 76 77 // A list of windows that currently own active shell dialogs for this 78 // instance. For example, if the DownloadManager owns an instance of this 79 // object and there are two browser windows open both with Save As dialog 80 // boxes active, this list will consist of the two browser windows' HWNDs. 81 // The derived class must call EndRun once the dialog is done showing to 82 // remove the owning HWND from this list. 83 // This object is static since it is maintained for all instances of this 84 // object - i.e. you can't have two file pickers open for the 85 // same owner, even though they might be represented by different instances 86 // of this object. 87 // This set only contains non-null HWNDs. NULL hwnds are not added to this 88 // list. 89 static Owners owners_; 90 static int instance_count_; 91 92 DISALLOW_COPY_AND_ASSIGN(BaseShellDialogImpl); 93 }; 94 95 } // namespace ui 96 97 #endif // UI_SHELL_DIALOGS_BASE_SHELL_DIALOG_WIN_H_ 98 99