forked from sanyaade-mobiledev/chromium.src
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
A mechanism to set the default handler for a URL protocol on Windows 8.
This change introduces OpenWithDialogController, which provides an asynchronous as well as a synchronous interface to setting a default protocol handler on Windows 8. BUG=154081 Review URL: https://chromiumcodereview.appspot.com/11863016 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@177417 0039d316-1c4b-4281-b951-d872f2087c98
- Loading branch information
grt@chromium.org
committed
Jan 17, 2013
1 parent
d28c6b2
commit e1eeaf4
Showing
10 changed files
with
1,320 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
include_rules = [ | ||
"+ui", | ||
"+win8/test", | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
# Copyright (c) 2013 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. | ||
{ | ||
'variables': { | ||
'chromium_code': 1, | ||
}, | ||
'targets': [ | ||
{ | ||
'target_name': 'set_default_handler', | ||
'type': 'executable', | ||
'dependencies': [ | ||
'../../base/base.gyp:base', | ||
'../../win8/win8.gyp:test_support_win8', | ||
'../../ui/ui.gyp:ui', | ||
], | ||
'include_dirs': [ | ||
'../..', | ||
], | ||
'sources': [ | ||
'set_default_handler_main.cc', | ||
], | ||
}, | ||
], | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
// Copyright (c) 2013 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. | ||
|
||
// Makes a given program ("Google Chrome" by default) the default handler for | ||
// some URL protocol ("http" by default) on Windows 8. These defaults can be | ||
// overridden via the --program and --protocol command line switches. | ||
|
||
#include <windows.h> | ||
|
||
#include "base/at_exit.h" | ||
#include "base/command_line.h" | ||
#include "base/logging.h" | ||
#include "base/string16.h" | ||
#include "base/string_util.h" | ||
#include "ui/base/win/atl_module.h" | ||
#include "win8/test/open_with_dialog_controller.h" | ||
|
||
namespace { | ||
|
||
const char kSwitchProgram[] = "program"; | ||
const char kSwitchProtocol[] = "protocol"; | ||
const wchar_t kDefaultProgram[] = L"Google Chrome"; | ||
const wchar_t kDefaultProtocol[] = L"http"; | ||
|
||
} // namespace | ||
|
||
extern "C" | ||
int wmain(int argc, wchar_t* argv[]) { | ||
// Initialize the commandline singleton from the environment. | ||
CommandLine::Init(0, NULL); | ||
// The exit manager is in charge of calling the dtors of singletons. | ||
base::AtExitManager exit_manager; | ||
logging::InitLogging(NULL, logging::LOG_ONLY_TO_SYSTEM_DEBUG_LOG, | ||
logging::DONT_LOCK_LOG_FILE, | ||
logging::APPEND_TO_OLD_LOG_FILE, | ||
logging::ENABLE_DCHECK_FOR_NON_OFFICIAL_RELEASE_BUILDS); | ||
logging::SetMinLogLevel(logging::LOG_VERBOSE); | ||
|
||
ui::win::CreateATLModuleIfNeeded(); | ||
|
||
CommandLine* command_line = CommandLine::ForCurrentProcess(); | ||
string16 protocol(command_line->GetSwitchValueNative(kSwitchProtocol)); | ||
if (protocol.empty()) | ||
protocol = kDefaultProtocol; | ||
|
||
string16 program(command_line->GetSwitchValueNative(kSwitchProgram)); | ||
if (program.empty()) | ||
program = kDefaultProgram; | ||
|
||
std::vector<string16> choices; | ||
HRESULT result = S_OK; | ||
win8::OpenWithDialogController controller; | ||
result = controller.RunSynchronously(NULL, protocol, program, &choices); | ||
|
||
if (SUCCEEDED(result)) { | ||
printf("success\n"); | ||
} else if (!choices.empty()) { | ||
printf("failed to set program. possible choices: %ls\n", | ||
JoinString(choices, L", ").c_str()); | ||
} else { | ||
printf("failed with HRESULT: 0x08X\n", result); | ||
} | ||
|
||
return FAILED(result); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,121 @@ | ||
// Copyright (c) 2013 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. | ||
|
||
// Implementation for the asynchronous interface to the Windows shell | ||
// SHOpenWithDialog function. The call is made on a dedicated UI thread in a | ||
// single-threaded apartment. | ||
|
||
#include "win8/test/open_with_dialog_async.h" | ||
|
||
#include <shlobj.h> | ||
|
||
#include "base/bind.h" | ||
#include "base/callback.h" | ||
#include "base/location.h" | ||
#include "base/memory/ref_counted.h" | ||
#include "base/single_thread_task_runner.h" | ||
#include "base/thread_task_runner_handle.h" | ||
#include "base/threading/platform_thread.h" | ||
#include "base/threading/thread.h" | ||
#include "base/win/windows_version.h" | ||
|
||
namespace win8 { | ||
|
||
namespace { | ||
|
||
struct OpenWithContext { | ||
OpenWithContext( | ||
HWND parent_window_in, | ||
const string16& file_name_in, | ||
const string16& file_type_class_in, | ||
int open_as_info_flags_in, | ||
const scoped_refptr<base::SingleThreadTaskRunner>& client_runner_in, | ||
const OpenWithDialogCallback& callback_in); | ||
~OpenWithContext(); | ||
|
||
base::Thread thread; | ||
HWND parent_window; | ||
string16 file_name; | ||
string16 file_type_class; | ||
int open_as_info_flags; | ||
scoped_refptr<base::SingleThreadTaskRunner> client_runner; | ||
OpenWithDialogCallback callback; | ||
}; | ||
|
||
OpenWithContext::OpenWithContext( | ||
HWND parent_window_in, | ||
const string16& file_name_in, | ||
const string16& file_type_class_in, | ||
int open_as_info_flags_in, | ||
const scoped_refptr<base::SingleThreadTaskRunner>& client_runner_in, | ||
const OpenWithDialogCallback& callback_in) | ||
: thread("OpenWithDialog"), | ||
parent_window(parent_window_in), | ||
file_name(file_name_in), | ||
file_type_class(file_type_class_in), | ||
open_as_info_flags(open_as_info_flags_in), | ||
client_runner(client_runner_in), | ||
callback(callback_in) { | ||
thread.init_com_with_mta(false); | ||
thread.Start(); | ||
} | ||
|
||
OpenWithContext::~OpenWithContext() {} | ||
|
||
// Runs the caller-provided |callback| with the result of the call to | ||
// SHOpenWithDialog on the caller's initial thread. | ||
void OnOpenWithDialogDone(OpenWithContext* context, HRESULT result) { | ||
DCHECK(context->client_runner->BelongsToCurrentThread()); | ||
OpenWithDialogCallback callback(context->callback); | ||
|
||
// Join with the thread. | ||
delete context; | ||
|
||
// Run the client's callback. | ||
callback.Run(result); | ||
} | ||
|
||
// Calls SHOpenWithDialog (blocking), and returns the result back to the client | ||
// thread. | ||
void OpenWithDialogTask(OpenWithContext* context) { | ||
DCHECK_EQ(context->thread.thread_id(), base::PlatformThread::CurrentId()); | ||
OPENASINFO open_as_info = { | ||
context->file_name.c_str(), | ||
context->file_type_class.c_str(), | ||
context->open_as_info_flags | ||
}; | ||
|
||
HRESULT result = ::SHOpenWithDialog(context->parent_window, &open_as_info); | ||
|
||
// Bounce back to the calling thread to release resources and deliver the | ||
// callback. | ||
if (!context->client_runner->PostTask( | ||
FROM_HERE, | ||
base::Bind(&OnOpenWithDialogDone, context, result))) { | ||
// The calling thread has gone away. There's nothing to be done but leak. | ||
// In practice this is only likely to happen at shutdown, so there isn't | ||
// much of a concern that it'll happen in the real world. | ||
DLOG(ERROR) << "leaking OpenWith thread; result = " << std::hex << result; | ||
} | ||
} | ||
|
||
} // namespace | ||
|
||
void OpenWithDialogAsync( | ||
HWND parent_window, | ||
const string16& file_name, | ||
const string16& file_type_class, | ||
int open_as_info_flags, | ||
const OpenWithDialogCallback& callback) { | ||
DCHECK_GE(base::win::GetVersion(), base::win::VERSION_VISTA); | ||
OpenWithContext* context = | ||
new OpenWithContext(parent_window, file_name, file_type_class, | ||
open_as_info_flags, | ||
base::ThreadTaskRunnerHandle::Get(), callback); | ||
context->thread.message_loop()->PostTask( | ||
FROM_HERE, | ||
base::Bind(&OpenWithDialogTask, context)); | ||
} | ||
|
||
} // namespace win8 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
// Copyright (c) 2013 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. | ||
|
||
#ifndef WIN8_TEST_OPEN_WITH_DIALOG_ASYNC_H_ | ||
#define WIN8_TEST_OPEN_WITH_DIALOG_ASYNC_H_ | ||
|
||
#include <windows.h> | ||
|
||
#include "base/callback_forward.h" | ||
#include "base/string16.h" | ||
|
||
namespace win8 { | ||
|
||
// Expected HRESULTS: | ||
// S_OK - A choice was made. | ||
// HRESULT_FROM_WIN32(ERROR_CANCELLED) - The dialog was dismissed. | ||
// HRESULT_FROM_WIN32(RPC_S_CALL_FAILED) - OpenWith.exe died. | ||
typedef base::Callback<void(HRESULT)> OpenWithDialogCallback; | ||
|
||
// Calls SHOpenWithDialog on a dedicated thread, returning the result to the | ||
// caller via |callback| on the current thread. The Windows SHOpenWithDialog | ||
// function blocks until the user makes a choice or dismisses the dialog (there | ||
// is no natural timeout nor a means by which it can be cancelled). Note that | ||
// the dedicated thread will be leaked if the calling thread's message loop goes | ||
// away before the interaction completes. | ||
void OpenWithDialogAsync(HWND parent_window, | ||
const string16& file_name, | ||
const string16& file_type_class, | ||
int open_as_info_flags, | ||
const OpenWithDialogCallback& callback); | ||
|
||
} // namespace win8 | ||
|
||
#endif // WIN8_TEST_OPEN_WITH_DIALOG_ASYNC_H_ |
Oops, something went wrong.