Include inttypes.h unconditionally in format_macros.h - VS2103 now supplies this...
[chromium-blink-merge.git] / win8 / test / open_with_dialog_async.cc
blob2308b55235fed96462683ea5f7b799ae09d4ffc3
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.
5 // Implementation for the asynchronous interface to the Windows shell
6 // SHOpenWithDialog function. The call is made on a dedicated UI thread in a
7 // single-threaded apartment.
9 #include "win8/test/open_with_dialog_async.h"
11 #include <shlobj.h>
13 #include "base/bind.h"
14 #include "base/callback.h"
15 #include "base/location.h"
16 #include "base/memory/ref_counted.h"
17 #include "base/single_thread_task_runner.h"
18 #include "base/thread_task_runner_handle.h"
19 #include "base/threading/platform_thread.h"
20 #include "base/threading/thread.h"
21 #include "base/win/windows_version.h"
23 namespace win8 {
25 namespace {
27 struct OpenWithContext {
28 OpenWithContext(
29 HWND parent_window_in,
30 const base::string16& file_name_in,
31 const base::string16& file_type_class_in,
32 int open_as_info_flags_in,
33 const scoped_refptr<base::SingleThreadTaskRunner>& client_runner_in,
34 const OpenWithDialogCallback& callback_in);
35 ~OpenWithContext();
37 base::Thread thread;
38 HWND parent_window;
39 base::string16 file_name;
40 base::string16 file_type_class;
41 int open_as_info_flags;
42 scoped_refptr<base::SingleThreadTaskRunner> client_runner;
43 OpenWithDialogCallback callback;
46 OpenWithContext::OpenWithContext(
47 HWND parent_window_in,
48 const base::string16& file_name_in,
49 const base::string16& file_type_class_in,
50 int open_as_info_flags_in,
51 const scoped_refptr<base::SingleThreadTaskRunner>& client_runner_in,
52 const OpenWithDialogCallback& callback_in)
53 : thread("OpenWithDialog"),
54 parent_window(parent_window_in),
55 file_name(file_name_in),
56 file_type_class(file_type_class_in),
57 open_as_info_flags(open_as_info_flags_in),
58 client_runner(client_runner_in),
59 callback(callback_in) {
60 thread.init_com_with_mta(false);
61 thread.Start();
64 OpenWithContext::~OpenWithContext() {}
66 // Runs the caller-provided |callback| with the result of the call to
67 // SHOpenWithDialog on the caller's initial thread.
68 void OnOpenWithDialogDone(OpenWithContext* context, HRESULT result) {
69 DCHECK(context->client_runner->BelongsToCurrentThread());
70 OpenWithDialogCallback callback(context->callback);
72 // Join with the thread.
73 delete context;
75 // Run the client's callback.
76 callback.Run(result);
79 // Calls SHOpenWithDialog (blocking), and returns the result back to the client
80 // thread.
81 void OpenWithDialogTask(OpenWithContext* context) {
82 DCHECK_EQ(context->thread.thread_id(), base::PlatformThread::CurrentId());
83 OPENASINFO open_as_info = {
84 context->file_name.c_str(),
85 context->file_type_class.c_str(),
86 context->open_as_info_flags
89 HRESULT result = ::SHOpenWithDialog(context->parent_window, &open_as_info);
91 // Bounce back to the calling thread to release resources and deliver the
92 // callback.
93 if (!context->client_runner->PostTask(
94 FROM_HERE,
95 base::Bind(&OnOpenWithDialogDone, context, result))) {
96 // The calling thread has gone away. There's nothing to be done but leak.
97 // In practice this is only likely to happen at shutdown, so there isn't
98 // much of a concern that it'll happen in the real world.
99 DLOG(ERROR) << "leaking OpenWith thread; result = " << std::hex << result;
103 } // namespace
105 void OpenWithDialogAsync(
106 HWND parent_window,
107 const base::string16& file_name,
108 const base::string16& file_type_class,
109 int open_as_info_flags,
110 const OpenWithDialogCallback& callback) {
111 DCHECK_GE(base::win::GetVersion(), base::win::VERSION_VISTA);
112 OpenWithContext* context =
113 new OpenWithContext(parent_window, file_name, file_type_class,
114 open_as_info_flags,
115 base::ThreadTaskRunnerHandle::Get(), callback);
116 context->thread.message_loop()->PostTask(
117 FROM_HERE,
118 base::Bind(&OpenWithDialogTask, context));
121 } // namespace win8