| // Copyright 2017 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 "content/browser/keyboard_lock/keyboard_lock_service_impl.h" |
| |
| #include <memory> |
| #include <utility> |
| |
| #include "base/bind.h" |
| #include "base/callback.h" |
| #include "base/containers/flat_set.h" |
| #include "base/logging.h" |
| #include "base/metrics/histogram_macros.h" |
| #include "base/optional.h" |
| #include "content/browser/frame_host/render_frame_host_impl.h" |
| #include "content/browser/keyboard_lock/keyboard_lock_metrics.h" |
| #include "content/browser/renderer_host/render_widget_host_impl.h" |
| #include "content/public/browser/render_frame_host.h" |
| #include "content/public/browser/render_widget_host.h" |
| #include "content/public/common/console_message_level.h" |
| #include "content/public/common/content_features.h" |
| #include "ui/events/keycodes/dom/dom_code.h" |
| #include "ui/events/keycodes/dom/keycode_converter.h" |
| |
| using blink::mojom::GetKeyboardLayoutMapResult; |
| using blink::mojom::KeyboardLockRequestResult; |
| |
| namespace content { |
| |
| namespace { |
| |
| void LogKeyboardLockMethodCalled(KeyboardLockMethods method) { |
| UMA_HISTOGRAM_ENUMERATION(kKeyboardLockMethodCalledHistogramName, method, |
| KeyboardLockMethods::kCount); |
| } |
| |
| } // namespace |
| |
| KeyboardLockServiceImpl::KeyboardLockServiceImpl( |
| RenderFrameHost* render_frame_host, |
| blink::mojom::KeyboardLockServiceRequest request) |
| : FrameServiceBase(render_frame_host, std::move(request)), |
| render_frame_host_(static_cast<RenderFrameHostImpl*>(render_frame_host)) { |
| DCHECK(render_frame_host_); |
| } |
| |
| // static |
| void KeyboardLockServiceImpl::CreateMojoService( |
| RenderFrameHost* render_frame_host, |
| blink::mojom::KeyboardLockServiceRequest request) { |
| DCHECK(render_frame_host); |
| |
| // The object is bound to the lifetime of |render_frame_host| and the mojo |
| // connection. See FrameServiceBase for details. |
| new KeyboardLockServiceImpl(render_frame_host, std::move(request)); |
| } |
| |
| void KeyboardLockServiceImpl::RequestKeyboardLock( |
| const std::vector<std::string>& key_codes, |
| RequestKeyboardLockCallback callback) { |
| if (key_codes.empty()) |
| LogKeyboardLockMethodCalled(KeyboardLockMethods::kRequestAllKeys); |
| else |
| LogKeyboardLockMethodCalled(KeyboardLockMethods::kRequestSomeKeys); |
| |
| if (!base::FeatureList::IsEnabled(features::kKeyboardLockAPI)) { |
| std::move(callback).Run(KeyboardLockRequestResult::kSuccess); |
| return; |
| } |
| |
| if (!render_frame_host_->IsCurrent()) { |
| std::move(callback).Run(KeyboardLockRequestResult::kFrameDetachedError); |
| return; |
| } |
| |
| if (render_frame_host_->GetParent()) { |
| std::move(callback).Run(KeyboardLockRequestResult::kChildFrameError); |
| return; |
| } |
| |
| // Per base::flat_set usage notes, the proper way to init a flat_set is |
| // inserting into a vector and using that to init the flat_set. |
| std::vector<ui::DomCode> dom_codes; |
| bool invalid_key_code_found = false; |
| for (const std::string& code : key_codes) { |
| ui::DomCode dom_code = ui::KeycodeConverter::CodeStringToDomCode(code); |
| if (dom_code != ui::DomCode::NONE) { |
| dom_codes.push_back(dom_code); |
| } else { |
| invalid_key_code_found = true; |
| render_frame_host_->AddMessageToConsole( |
| ConsoleMessageLevel::CONSOLE_MESSAGE_LEVEL_WARNING, |
| "Invalid DOMString passed into keyboard.lock(): '" + code + "'"); |
| } |
| } |
| |
| // If we are provided with a vector containing one or more invalid key codes, |
| // then exit without enabling keyboard lock. Also cancel any previous |
| // keyboard lock request since the most recent request failed. |
| if (invalid_key_code_found) { |
| render_frame_host_->GetRenderWidgetHost()->CancelKeyboardLock(); |
| std::move(callback).Run(KeyboardLockRequestResult::kNoValidKeyCodesError); |
| return; |
| } |
| |
| base::Optional<base::flat_set<ui::DomCode>> dom_code_set; |
| if (!dom_codes.empty()) |
| dom_code_set = std::move(dom_codes); |
| |
| if (render_frame_host_->GetRenderWidgetHost()->RequestKeyboardLock( |
| std::move(dom_code_set))) { |
| std::move(callback).Run(KeyboardLockRequestResult::kSuccess); |
| } else { |
| std::move(callback).Run(KeyboardLockRequestResult::kRequestFailedError); |
| } |
| } |
| |
| void KeyboardLockServiceImpl::CancelKeyboardLock() { |
| LogKeyboardLockMethodCalled(KeyboardLockMethods::kCancelLock); |
| |
| if (base::FeatureList::IsEnabled(features::kKeyboardLockAPI)) |
| render_frame_host_->GetRenderWidgetHost()->CancelKeyboardLock(); |
| } |
| |
| void KeyboardLockServiceImpl::GetKeyboardLayoutMap( |
| GetKeyboardLayoutMapCallback callback) { |
| auto response = GetKeyboardLayoutMapResult::New(); |
| response->status = blink::mojom::GetKeyboardLayoutMapStatus::kSuccess; |
| response->layout_map = |
| render_frame_host_->GetRenderWidgetHost()->GetKeyboardLayoutMap(); |
| |
| std::move(callback).Run(std::move(response)); |
| } |
| |
| KeyboardLockServiceImpl::~KeyboardLockServiceImpl() = default; |
| |
| } // namespace content |