Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
extensions: add webAuthenticationProxy.onRemoteSessionStateChange event
CRD's webAuthenticationProxy extension needs to be kept informed by the native host app whenever a remote session is attached or detached. To accomplish this, the extension ServiceWorker communicates via the native messaging host with the CRD host process. But the CRD host needs to be able to signal session state changes even when the ServiceWorker and NMH have been terminated. This change introduces an event that the CRD host process can trigger in response to a session attachment change by writing to a file at `WebAuthenticationRemoteSessionStateChange/<extension id>` inside the default user data directory. (*Default* UDD because we don't want the extension/NMH/app having to discover the correct location.) Writing to that file raises the event to the extension with that ID. The contents of the file are ignored, and the event has no parameters. This is simply a mechanism to wake up the extension and instruct it to fetch the current session attachment state from the CRD host. (This change also restricts the API to Win, Mac and Linux, because those are the only platforms we're targeting for this API. So we don't need to pick file paths for other OSes.) Bug: 1231802 Change-Id: I23409d6f23fd76c1a27ea96ad96ee7699bdeaa8c Cq-Do-Not-Cancel-Tryjobs: true Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3514116 Reviewed-by: Devlin Cronin <rdevlin.cronin@chromium.org> Commit-Queue: Martin Kreichgauer <martinkr@google.com> Cr-Commit-Position: refs/heads/main@{#989094}
- Loading branch information
1 parent
ace8322
commit cdbdd06
Showing
19 changed files
with
392 additions
and
45 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
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
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
110 changes: 110 additions & 0 deletions
110
chrome/browser/extensions/api/web_authentication_proxy/remote_session_state_change.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,110 @@ | ||
// Copyright 2022 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/extensions/api/web_authentication_proxy/remote_session_state_change.h" | ||
|
||
#include <memory> | ||
|
||
#include "base/base_paths.h" | ||
#include "base/bind.h" | ||
#include "base/files/file_path.h" | ||
#include "base/files/file_util.h" | ||
#include "base/location.h" | ||
#include "base/logging.h" | ||
#include "base/path_service.h" | ||
#include "base/task/bind_post_task.h" | ||
#include "chrome/common/chrome_paths_internal.h" | ||
#include "chrome/common/extensions/api/web_authentication_proxy.h" | ||
|
||
namespace extensions { | ||
|
||
namespace { | ||
|
||
void OnSessionStateChangeFileUpdate( | ||
const base::FilePath& watched_path, | ||
const base::RepeatingCallback<void()>& update_callback, | ||
const base::FilePath& path, | ||
bool is_error) { | ||
DCHECK_EQ(path, watched_path); | ||
if (is_error) { | ||
DLOG(ERROR) << "OnRemoteSessionStateFileUpdate() error"; | ||
return; | ||
} | ||
update_callback.Run(); | ||
} | ||
|
||
void WatchSessionStateChangeFile( | ||
base::FilePathWatcher* watcher, | ||
const ExtensionId& extension_id, | ||
base::RepeatingCallback<void()> update_callback) { | ||
base::FilePath dir; | ||
if (!WebAuthenticationProxyRemoteSessionStateChangeNotifier:: | ||
GetSessionStateChangeDir(&dir)) { | ||
DLOG(ERROR) << "GetSessionStateChangeDir failed"; | ||
return; | ||
} | ||
|
||
if (!base::PathExists(dir)) { | ||
base::CreateDirectory(dir); | ||
} | ||
const base::FilePath path = dir.AppendASCII(extension_id); | ||
if (!watcher->Watch(path, base::FilePathWatcher::Type::kNonRecursive, | ||
base::BindRepeating(&OnSessionStateChangeFileUpdate, path, | ||
update_callback))) { | ||
DLOG(ERROR) << "FilePathWatcher::Watch() failed"; | ||
} | ||
DVLOG(1) << "WebAuthenticationProxyRemoteSessionStateChangeNotifier at " | ||
<< path; | ||
} | ||
} // namespace | ||
|
||
bool WebAuthenticationProxyRemoteSessionStateChangeNotifier:: | ||
GetSessionStateChangeDir(base::FilePath* out) { | ||
// The path must be stable, i.e. the remote desktop app should not need to do | ||
// any sort of discovery, which rules out the User Data Directory. It also has | ||
// to be user-writable, because the app isn't expected to run as root. | ||
base::FilePath default_udd; | ||
if (!chrome::GetDefaultUserDataDirectory(&default_udd)) { | ||
return false; | ||
} | ||
*out = default_udd.Append( | ||
FILE_PATH_LITERAL("WebAuthenticationProxyRemoteSessionStateChange")); | ||
return true; | ||
} | ||
|
||
WebAuthenticationProxyRemoteSessionStateChangeNotifier:: | ||
WebAuthenticationProxyRemoteSessionStateChangeNotifier( | ||
EventRouter* event_router, | ||
ExtensionId extension_id) | ||
: event_router_(event_router), extension_id_(std::move(extension_id)) { | ||
DCHECK(event_router_); | ||
auto broadcast_event_on_change = base::BindPostTask( | ||
base::SequencedTaskRunnerHandle::Get(), | ||
base::BindRepeating( | ||
&WebAuthenticationProxyRemoteSessionStateChangeNotifier:: | ||
BroadcastRemoteSessionStateChangeEvent, | ||
weak_ptr_factory_.GetWeakPtr())); | ||
// This task could run after `this` has been deleted. But `watcher_` is | ||
// getting destroyed on `io_runner_`, so it will still be alive. | ||
io_runner_->PostTask( | ||
FROM_HERE, | ||
base::BindOnce(&WatchSessionStateChangeFile, watcher_.get(), | ||
extension_id_, std::move(broadcast_event_on_change))); | ||
} | ||
|
||
WebAuthenticationProxyRemoteSessionStateChangeNotifier:: | ||
~WebAuthenticationProxyRemoteSessionStateChangeNotifier() = default; | ||
|
||
void WebAuthenticationProxyRemoteSessionStateChangeNotifier:: | ||
BroadcastRemoteSessionStateChangeEvent() { | ||
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); | ||
event_router_->DispatchEventToExtension( | ||
extension_id_, | ||
std::make_unique<Event>( | ||
events::WEB_AUTHENTICATION_PROXY_ON_REMOTE_SESSION_STATE_CHANGE, | ||
api::web_authentication_proxy::OnRemoteSessionStateChange::kEventName, | ||
api::web_authentication_proxy::OnRemoteSessionStateChange::Create())); | ||
} | ||
|
||
} // namespace extensions |
67 changes: 67 additions & 0 deletions
67
chrome/browser/extensions/api/web_authentication_proxy/remote_session_state_change.h
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,67 @@ | ||
// Copyright 2022 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 CHROME_BROWSER_EXTENSIONS_API_WEB_AUTHENTICATION_PROXY_REMOTE_SESSION_STATE_CHANGE_H_ | ||
#define CHROME_BROWSER_EXTENSIONS_API_WEB_AUTHENTICATION_PROXY_REMOTE_SESSION_STATE_CHANGE_H_ | ||
|
||
#include <memory> | ||
|
||
#include "base/callback.h" | ||
#include "base/files/file_path.h" | ||
#include "base/files/file_path_watcher.h" | ||
#include "base/memory/weak_ptr.h" | ||
#include "base/sequence_checker.h" | ||
#include "base/task/task_traits.h" | ||
#include "base/task/thread_pool.h" | ||
#include "content/public/browser/browser_task_traits.h" | ||
#include "content/public/browser/browser_thread.h" | ||
#include "extensions/browser/event_router.h" | ||
|
||
namespace extensions { | ||
|
||
// WebAuthenticationProxyRemoteSessionStateChangeNotifier watches for changes to | ||
// a per-extension file in the well-known directory path returned by | ||
// `GetSessionStateChangeDir()`, and raises | ||
// `webAuthentcationProxy.onRemoteSessionStateChange` events in response. | ||
class WebAuthenticationProxyRemoteSessionStateChangeNotifier { | ||
public: | ||
// Returns the directory in which the extension is expected to write its file. | ||
static bool GetSessionStateChangeDir(base::FilePath* out); | ||
|
||
WebAuthenticationProxyRemoteSessionStateChangeNotifier( | ||
EventRouter* event_router, | ||
ExtensionId extension_id); | ||
WebAuthenticationProxyRemoteSessionStateChangeNotifier( | ||
const WebAuthenticationProxyRemoteSessionStateChangeNotifier&) = delete; | ||
WebAuthenticationProxyRemoteSessionStateChangeNotifier& operator=( | ||
WebAuthenticationProxyRemoteSessionStateChangeNotifier&) = delete; | ||
virtual ~WebAuthenticationProxyRemoteSessionStateChangeNotifier(); | ||
|
||
private: | ||
void OnRemoteSessionStateFileUpdate( | ||
base::RepeatingCallback<void()> on_file_change, | ||
const base::FilePath& path, | ||
bool error); | ||
void BroadcastRemoteSessionStateChangeEvent(); | ||
|
||
const raw_ptr<EventRouter> event_router_; | ||
const ExtensionId extension_id_; | ||
|
||
// FilePathWatcher::Watch() may block, and must be called on the same sequence | ||
// as the destructor. | ||
scoped_refptr<base::SequencedTaskRunner> io_runner_ = | ||
base::ThreadPool::CreateSequencedTaskRunner({base::MayBlock()}); | ||
|
||
std::unique_ptr<base::FilePathWatcher, base::OnTaskRunnerDeleter> watcher_{ | ||
new base::FilePathWatcher(), base::OnTaskRunnerDeleter(io_runner_)}; | ||
|
||
SEQUENCE_CHECKER(sequence_checker_); | ||
|
||
base::WeakPtrFactory<WebAuthenticationProxyRemoteSessionStateChangeNotifier> | ||
weak_ptr_factory_{this}; | ||
}; | ||
|
||
} // namespace extensions | ||
|
||
#endif // CHROME_BROWSER_EXTENSIONS_API_WEB_AUTHENTICATION_PROXY_REMOTE_SESSION_STATE_CHANGE_H_ |
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
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
Oops, something went wrong.