blob: ffb77ea721a10352f23f14cbb9952c7de74262a5 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
|
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/ui/views/base_shell_dialog_win.h"
#include <algorithm>
#include "base/threading/thread.h"
// Helpers to show certain types of Windows shell dialogs in a way that doesn't
// block the UI of the entire app.
class ShellDialogThread : public base::Thread {
public:
ShellDialogThread() : base::Thread("Chrome_ShellDialogThread") { }
~ShellDialogThread();
protected:
void Init();
void CleanUp();
private:
DISALLOW_COPY_AND_ASSIGN(ShellDialogThread);
};
ShellDialogThread::~ShellDialogThread() {
Stop();
}
void ShellDialogThread::Init() {
// Initializes the COM library on the current thread.
CoInitialize(NULL);
}
void ShellDialogThread::CleanUp() {
// Closes the COM library on the current thread. CoInitialize must
// be balanced by a corresponding call to CoUninitialize.
CoUninitialize();
}
// static
BaseShellDialogImpl::Owners BaseShellDialogImpl::owners_;
int BaseShellDialogImpl::instance_count_ = 0;
BaseShellDialogImpl::BaseShellDialogImpl() {
++instance_count_;
}
BaseShellDialogImpl::~BaseShellDialogImpl() {
// All runs should be complete by the time this is called!
if (--instance_count_ == 0)
DCHECK(owners_.empty());
}
BaseShellDialogImpl::RunState BaseShellDialogImpl::BeginRun(HWND owner) {
// Cannot run a modal shell dialog if one is already running for this owner.
DCHECK(!IsRunningDialogForOwner(owner));
// The owner must be a top level window, otherwise we could end up with two
// entries in our map for the same top level window.
DCHECK(!owner || owner == GetAncestor(owner, GA_ROOT));
RunState run_state;
run_state.dialog_thread = CreateDialogThread();
run_state.owner = owner;
if (owner) {
owners_.insert(owner);
DisableOwner(owner);
}
return run_state;
}
void BaseShellDialogImpl::EndRun(RunState run_state) {
if (run_state.owner) {
DCHECK(IsRunningDialogForOwner(run_state.owner));
EnableOwner(run_state.owner);
DCHECK(owners_.find(run_state.owner) != owners_.end());
owners_.erase(run_state.owner);
}
DCHECK(run_state.dialog_thread);
delete run_state.dialog_thread;
}
bool BaseShellDialogImpl::IsRunningDialogForOwner(HWND owner) const {
return (owner && owners_.find(owner) != owners_.end());
}
void BaseShellDialogImpl::DisableOwner(HWND owner) {
if (IsWindow(owner))
EnableWindow(owner, FALSE);
}
// static
base::Thread* BaseShellDialogImpl::CreateDialogThread() {
base::Thread* thread = new ShellDialogThread;
bool started = thread->Start();
DCHECK(started);
return thread;
}
void BaseShellDialogImpl::EnableOwner(HWND owner) {
if (IsWindow(owner))
EnableWindow(owner, TRUE);
}
|