15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/shell_dialogs/base_shell_dialog_win.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <algorithm>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/threading/thread.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/win/scoped_com_initializer.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace ui {
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BaseShellDialogImpl::Owners BaseShellDialogImpl::owners_;
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int BaseShellDialogImpl::instance_count_ = 0;
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BaseShellDialogImpl::BaseShellDialogImpl() {
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ++instance_count_;
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BaseShellDialogImpl::~BaseShellDialogImpl() {
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // All runs should be complete by the time this is called!
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (--instance_count_ == 0)
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(owners_.empty());
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BaseShellDialogImpl::RunState BaseShellDialogImpl::BeginRun(HWND owner) {
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Cannot run a modal shell dialog if one is already running for this owner.
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!IsRunningDialogForOwner(owner));
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The owner must be a top level window, otherwise we could end up with two
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // entries in our map for the same top level window.
335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(!owner || owner == GetAncestor(owner, GA_ROOT));
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RunState run_state;
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  run_state.dialog_thread = CreateDialogThread();
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  run_state.owner = owner;
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (owner) {
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    owners_.insert(owner);
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DisableOwner(owner);
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return run_state;
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BaseShellDialogImpl::EndRun(RunState run_state) {
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (run_state.owner) {
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(IsRunningDialogForOwner(run_state.owner));
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EnableOwner(run_state.owner);
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(owners_.find(run_state.owner) != owners_.end());
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    owners_.erase(run_state.owner);
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(run_state.dialog_thread);
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delete run_state.dialog_thread;
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool BaseShellDialogImpl::IsRunningDialogForOwner(HWND owner) const {
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return (owner && owners_.find(owner) != owners_.end());
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BaseShellDialogImpl::DisableOwner(HWND owner) {
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (IsWindow(owner))
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EnableWindow(owner, FALSE);
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)base::Thread* BaseShellDialogImpl::CreateDialogThread() {
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::Thread* thread = new base::Thread("Chrome_ShellDialogThread");
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  thread->init_com_with_mta(false);
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool started = thread->Start();
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(started);
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return thread;
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BaseShellDialogImpl::EnableOwner(HWND owner) {
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (IsWindow(owner))
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EnableWindow(owner, TRUE);
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace ui
79