[mac] Mojofy TextInputClientMsg_StringForRange
This CL replaces TextInputClientMsg_StringForRange and TextInputClientReplyMsg_StringForRange IPC messages with GetStringForRange Mojo method in the LocalFrame interface. GetStringForRange gets a range and returns the word in the range. It cleans up text_input_client_observer.{cc,h} and text_input_client_message_filter.{cc,h} and replaces TestTextInputClientMessageFilter with TextInputTestLocalFrame to support testing GetStringForRange. Bug: 1007365 Change-Id: I7ef37d71e1642cc4c05e1f942d97acc1ea1e4cd9 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2269628 Reviewed-by: John Abd-El-Malek <jam@chromium.org> Reviewed-by: Dave Tapuska <dtapuska@chromium.org> Reviewed-by: Avi Drissman <avi@chromium.org> Reviewed-by: danakj <danakj@chromium.org> Reviewed-by: Kinuko Yasuda <kinuko@chromium.org> Commit-Queue: Julie Kim <jkim@igalia.com> Cr-Commit-Position: refs/heads/master@{#785645}
This commit is contained in:

committed by
Commit Bot

parent
310dbdf821
commit
a4bc40df56
chrome/browser
apps
guest_view
site_isolation
content
browser
BUILD.gn
frame_host
renderer_host
render_process_host_impl.cctext_input_client_mac.htext_input_client_mac.mmtext_input_client_mac_unittest.mmtext_input_client_message_filter.htext_input_client_message_filter.mm
site_per_process_mac_browsertest.mmcommon
public
test
renderer
ipc
third_party/blink
public
renderer
@ -19,7 +19,6 @@
|
||||
#include "build/build_config.h"
|
||||
#include "chrome/app/chrome_command_ids.h"
|
||||
#include "chrome/browser/apps/platform_apps/app_browsertest_util.h"
|
||||
#include "chrome/browser/chrome_content_browser_client.h"
|
||||
#include "chrome/browser/profiles/profile.h"
|
||||
#include "chrome/browser/renderer_context_menu/render_view_context_menu_browsertest_util.h"
|
||||
#include "chrome/browser/renderer_context_menu/render_view_context_menu_test_util.h"
|
||||
@ -69,49 +68,6 @@ using guest_view::TestGuestViewManager;
|
||||
using guest_view::TestGuestViewManagerFactory;
|
||||
|
||||
#if defined(OS_MACOSX)
|
||||
// The original TextInputClientMessageFilter is added during the initialization
|
||||
// phase of RenderProcessHost. The only chance we have to add the test filter
|
||||
// (so that it can receive the TextInputClientMac incoming IPC messages) is
|
||||
// during the call to RenderProcessWillLaunch() on ContentBrowserClient. This
|
||||
// class provides that for testing. The class also replaces the current client
|
||||
// and will reset the client back to the original one upon destruction.
|
||||
class BrowserClientForTextInputClientMac : public ChromeContentBrowserClient {
|
||||
public:
|
||||
BrowserClientForTextInputClientMac()
|
||||
: old_client_(content::SetBrowserClientForTesting(this)) {}
|
||||
~BrowserClientForTextInputClientMac() override {
|
||||
content::SetBrowserClientForTesting(old_client_);
|
||||
}
|
||||
|
||||
// ContentBrowserClient overrides.
|
||||
void RenderProcessWillLaunch(
|
||||
content::RenderProcessHost* process_host) override {
|
||||
ChromeContentBrowserClient::RenderProcessWillLaunch(process_host);
|
||||
filters_.push_back(
|
||||
new content::TestTextInputClientMessageFilter(process_host));
|
||||
}
|
||||
|
||||
// Retrieves the registered filter for the given RenderProcessHost. It will
|
||||
// return false if the RenderProcessHost was initialized while a different
|
||||
// instance of ContentBrowserClient was in action.
|
||||
scoped_refptr<content::TestTextInputClientMessageFilter>
|
||||
GetTextInputClientMessageFilterForProcess(
|
||||
content::RenderProcessHost* process_host) const {
|
||||
for (auto filter : filters_) {
|
||||
if (filter->process() == process_host)
|
||||
return filter;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
private:
|
||||
content::ContentBrowserClient* old_client_;
|
||||
std::vector<scoped_refptr<content::TestTextInputClientMessageFilter>>
|
||||
filters_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(BrowserClientForTextInputClientMac);
|
||||
};
|
||||
|
||||
// This class observes the RenderWidgetHostViewCocoa corresponding to the outer
|
||||
// most WebContents provided for newly added subviews. The added subview
|
||||
// corresponds to a NSPopUpButtonCell which will be removed shortly after being
|
||||
@ -1518,22 +1474,15 @@ IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest, TextSelection) {
|
||||
}
|
||||
|
||||
// Verifies that asking for a word lookup from a guest will lead to a returned
|
||||
// IPC from the renderer containing the right selected word.
|
||||
// mojo callback from the renderer containing the right selected word.
|
||||
IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest, WordLookup) {
|
||||
// BrowserClientForTextInputClientMac needs to replace the
|
||||
// ChromeContentBrowserClient after most things are initialized but before the
|
||||
// WebContents is created.
|
||||
BrowserClientForTextInputClientMac browser_client;
|
||||
|
||||
SetupTest("web_view/text_selection",
|
||||
"/extensions/platform_apps/web_view/text_selection/guest.html");
|
||||
ASSERT_TRUE(guest_web_contents());
|
||||
ASSERT_TRUE(ui_test_utils::ShowAndFocusNativeWindow(GetPlatformAppWindow()));
|
||||
|
||||
auto guest_message_filter =
|
||||
browser_client.GetTextInputClientMessageFilterForProcess(
|
||||
guest_web_contents()->GetMainFrame()->GetProcess());
|
||||
ASSERT_TRUE(guest_message_filter);
|
||||
content::TextInputTestLocalFrame text_input_local_frame;
|
||||
text_input_local_frame.SetUp(guest_web_contents()->GetMainFrame());
|
||||
|
||||
// Lookup some string through context menu.
|
||||
ContextMenuNotificationObserver menu_observer(IDC_CONTENT_CONTEXT_LOOK_UP);
|
||||
@ -1542,10 +1491,10 @@ IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest, WordLookup) {
|
||||
SimulateRWHMouseClick(guest_web_contents()->GetRenderViewHost()->GetWidget(),
|
||||
blink::WebMouseEvent::Button::kRight, 20, 20);
|
||||
// Wait for the response form the guest renderer.
|
||||
guest_message_filter->WaitForStringFromRange();
|
||||
text_input_local_frame.WaitForGetStringForRange();
|
||||
|
||||
// Sanity check.
|
||||
ASSERT_EQ("AAAA", guest_message_filter->string_from_range().substr(0, 4));
|
||||
ASSERT_EQ("AAAA", text_input_local_frame.GetStringFromRange().substr(0, 4));
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -10,7 +10,6 @@
|
||||
#include "base/strings/stringprintf.h"
|
||||
#include "base/strings/utf_string_conversions.h"
|
||||
#include "build/build_config.h"
|
||||
#include "chrome/browser/chrome_content_browser_client.h"
|
||||
#include "chrome/browser/ui/browser.h"
|
||||
#include "chrome/browser/ui/browser_window.h"
|
||||
#include "chrome/browser/ui/location_bar/location_bar.h"
|
||||
@ -1354,89 +1353,12 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessTextInputManagerTest,
|
||||
}
|
||||
}
|
||||
|
||||
// The original TextInputClientMessageFilter is added during the initialization
|
||||
// phase of RenderProcessHost. The only chance we have to add the test filter
|
||||
// (so that it can receive the TextInputClientMac incoming IPC messages) is
|
||||
// during the call to RenderProcessWillLaunch() on ContentBrowserClient. This
|
||||
// class provides that for testing.
|
||||
class TestBrowserClient : public ChromeContentBrowserClient {
|
||||
public:
|
||||
TestBrowserClient() {
|
||||
old_client_ = content::SetBrowserClientForTesting(this);
|
||||
}
|
||||
|
||||
~TestBrowserClient() override {
|
||||
content::SetBrowserClientForTesting(old_client_);
|
||||
}
|
||||
|
||||
// ContentBrowserClient overrides.
|
||||
void RenderProcessWillLaunch(
|
||||
content::RenderProcessHost* process_host) override {
|
||||
ChromeContentBrowserClient::RenderProcessWillLaunch(process_host);
|
||||
filters_.push_back(
|
||||
new content::TestTextInputClientMessageFilter(process_host));
|
||||
}
|
||||
|
||||
// Retrieves the registered filter for the given RenderProcessHost. It will
|
||||
// return false if the RenderProcessHost was initialized while a different
|
||||
// instance of ContentBrowserClient was in action.
|
||||
scoped_refptr<content::TestTextInputClientMessageFilter>
|
||||
GetTextInputClientMessageFilterForProcess(
|
||||
content::RenderProcessHost* process_host) const {
|
||||
for (auto filter : filters_) {
|
||||
if (filter->process() == process_host)
|
||||
return filter;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
private:
|
||||
content::ContentBrowserClient* old_client_ = nullptr;
|
||||
std::vector<scoped_refptr<content::TestTextInputClientMessageFilter>>
|
||||
filters_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(TestBrowserClient);
|
||||
};
|
||||
|
||||
// Earlier injection of TestBrowserClient (a ContentBrowserClient) is needed to
|
||||
// make sure it is active during creation of the first spare RenderProcessHost.
|
||||
// Without this change, the tests would be surprised that they cannot find an
|
||||
// injected message filter via GetTextInputClientMessageFilterForProcess.
|
||||
class SitePerProcessCustomTextInputManagerFilteringTest
|
||||
: public SitePerProcessTextInputManagerTest {
|
||||
public:
|
||||
SitePerProcessCustomTextInputManagerFilteringTest() {}
|
||||
~SitePerProcessCustomTextInputManagerFilteringTest() override {}
|
||||
|
||||
void CreatedBrowserMainParts(content::BrowserMainParts* parts) override {
|
||||
SitePerProcessTextInputManagerTest::CreatedBrowserMainParts(parts);
|
||||
browser_client_ = std::make_unique<TestBrowserClient>();
|
||||
}
|
||||
|
||||
void TearDown() override {
|
||||
browser_client_.reset();
|
||||
SitePerProcessTextInputManagerTest::TearDown();
|
||||
}
|
||||
|
||||
scoped_refptr<content::TestTextInputClientMessageFilter>
|
||||
GetTextInputClientMessageFilterForProcess(
|
||||
content::RenderProcessHost* process_host) const {
|
||||
return browser_client_->GetTextInputClientMessageFilterForProcess(
|
||||
process_host);
|
||||
}
|
||||
|
||||
private:
|
||||
std::unique_ptr<TestBrowserClient> browser_client_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(SitePerProcessCustomTextInputManagerFilteringTest);
|
||||
};
|
||||
|
||||
// This test verifies that when a word lookup result comes from the renderer
|
||||
// after the target RenderWidgetHost has been deleted, the browser will not
|
||||
// crash. This test covers the case where the target RenderWidgetHost is that of
|
||||
// an OOPIF.
|
||||
IN_PROC_BROWSER_TEST_F(
|
||||
SitePerProcessCustomTextInputManagerFilteringTest,
|
||||
SitePerProcessTextInputManagerTest,
|
||||
DoNotCrashBrowserInWordLookUpForDestroyedWidget_ChildFrame) {
|
||||
std::unique_ptr<content::WebContents> new_contents =
|
||||
content::WebContents::Create(content::WebContents::CreateParams(
|
||||
@ -1457,25 +1379,23 @@ IN_PROC_BROWSER_TEST_F(
|
||||
"document.querySelector('input').focus();"
|
||||
"document.querySelector('input').select();"));
|
||||
|
||||
content::RenderWidgetHostView* child_view = child_frame->GetView();
|
||||
scoped_refptr<content::TestTextInputClientMessageFilter>
|
||||
child_message_filter = GetTextInputClientMessageFilterForProcess(
|
||||
child_view->GetRenderWidgetHost()->GetProcess());
|
||||
DCHECK(child_message_filter);
|
||||
content::TextInputTestLocalFrame text_input_local_frame;
|
||||
text_input_local_frame.SetUp(child_frame);
|
||||
|
||||
// We need to wait for test scenario to complete before leaving this block.
|
||||
base::RunLoop test_complete_waiter;
|
||||
|
||||
// Destroy the RenderWidgetHost from the browser side right after the
|
||||
// dictionary IPC is received. The destruction is post tasked to UI thread.
|
||||
int32_t child_process_id =
|
||||
child_view->GetRenderWidgetHost()->GetProcess()->GetID();
|
||||
// dictionary message is received. The destruction is post tasked to UI
|
||||
// thread.
|
||||
int32_t child_process_id = child_frame->GetProcess()->GetID();
|
||||
int32_t child_frame_routing_id = child_frame->GetRoutingID();
|
||||
child_message_filter->SetStringForRangeCallback(base::Bind(
|
||||
|
||||
text_input_local_frame.SetStringForRangeCallback(base::Bind(
|
||||
[](int32_t process_id, int32_t routing_id,
|
||||
const base::Closure& callback_on_io) {
|
||||
// This runs before TextInputClientMac gets to handle the IPC. Then,
|
||||
// by the time TextInputClientMac calls back into UI to show the
|
||||
// This runs before TextInputClientMac gets to handle the mojo message.
|
||||
// Then, by the time TextInputClientMac calls back into UI to show the
|
||||
// dictionary, the target RWH is already destroyed which will be a
|
||||
// close enough repro for the crash in https://crbug.com/737032.
|
||||
ASSERT_TRUE(content::DestroyRenderWidgetHost(process_id, routing_id));
|
||||
@ -1506,7 +1426,7 @@ IN_PROC_BROWSER_TEST_F(
|
||||
// crash. This test covers the case where the target RenderWidgetHost is that of
|
||||
// the main frame (no OOPIFs on page).
|
||||
IN_PROC_BROWSER_TEST_F(
|
||||
SitePerProcessCustomTextInputManagerFilteringTest,
|
||||
SitePerProcessTextInputManagerTest,
|
||||
DoNotCrashBrowserInWordLookUpForDestroyedWidget_MainFrame) {
|
||||
std::unique_ptr<content::WebContents> new_contents =
|
||||
content::WebContents::Create(content::WebContents::CreateParams(
|
||||
@ -1526,25 +1446,24 @@ IN_PROC_BROWSER_TEST_F(
|
||||
"document.querySelector('input').focus();"
|
||||
"document.querySelector('input').select();"));
|
||||
|
||||
content::TextInputTestLocalFrame text_input_local_frame;
|
||||
text_input_local_frame.SetUp(main_frame);
|
||||
|
||||
content::RenderWidgetHostView* page_rwhv = main_frame->GetView();
|
||||
scoped_refptr<content::TestTextInputClientMessageFilter> message_filter =
|
||||
GetTextInputClientMessageFilterForProcess(
|
||||
page_rwhv->GetRenderWidgetHost()->GetProcess());
|
||||
DCHECK(message_filter);
|
||||
|
||||
// We need to wait for test scenario to complete before leaving this block.
|
||||
base::RunLoop test_complete_waiter;
|
||||
|
||||
// Destroy the RenderWidgetHost from the browser side right after the
|
||||
// dictionary IPC is received. The destruction is post tasked to UI thread.
|
||||
int32_t main_frame_process_id =
|
||||
page_rwhv->GetRenderWidgetHost()->GetProcess()->GetID();
|
||||
// dictionary message is received. The destruction is post tasked to UI
|
||||
// thread.
|
||||
int32_t main_frame_process_id = main_frame->GetProcess()->GetID();
|
||||
int32_t main_frame_routing_id = main_frame->GetRoutingID();
|
||||
message_filter->SetStringForRangeCallback(base::Bind(
|
||||
text_input_local_frame.SetStringForRangeCallback(base::Bind(
|
||||
[](int32_t process_id, int32_t routing_id,
|
||||
const base::Closure& callback_on_io) {
|
||||
// This runs before TextInputClientMac gets to handle the IPC. Then,
|
||||
// by the time TextInputClientMac calls back into UI to show the
|
||||
// This runs before TextInputClientMac gets to handle the mojo message.
|
||||
// Then, by the time TextInputClientMac calls back into UI to show the
|
||||
// dictionary, the target RWH is already destroyed which will be a
|
||||
// close enough repro for the crash in https://crbug.com/737032.
|
||||
ASSERT_TRUE(content::DestroyRenderWidgetHost(process_id, routing_id));
|
||||
|
@ -1611,8 +1611,6 @@ jumbo_source_set("browser") {
|
||||
"renderer_host/render_widget_targeter.h",
|
||||
"renderer_host/text_input_client_mac.h",
|
||||
"renderer_host/text_input_client_mac.mm",
|
||||
"renderer_host/text_input_client_message_filter.h",
|
||||
"renderer_host/text_input_client_message_filter.mm",
|
||||
"renderer_host/text_input_host_impl.h",
|
||||
"renderer_host/text_input_host_impl.mm",
|
||||
"renderer_host/text_input_manager.cc",
|
||||
|
@ -1767,6 +1767,7 @@ class CONTENT_EXPORT RenderFrameHostImpl
|
||||
friend class RenderFrameHostFeaturePolicyTest;
|
||||
friend class TestRenderFrameHost;
|
||||
friend class TestRenderViewHost;
|
||||
friend class TextInputTestLocalFrame;
|
||||
friend class WebContentsSplitCacheBrowserTest;
|
||||
|
||||
FRIEND_TEST_ALL_PREFIXES(NavigatorTest, TwoNavigationsRacingCommit);
|
||||
|
@ -251,7 +251,6 @@
|
||||
|
||||
#if defined(OS_MACOSX)
|
||||
#include "content/browser/child_process_task_port_provider_mac.h"
|
||||
#include "content/browser/renderer_host/text_input_client_message_filter.h"
|
||||
#include "content/browser/sandbox_support_mac_impl.h"
|
||||
#include "content/common/sandbox_support_mac.mojom.h"
|
||||
#endif
|
||||
@ -1988,9 +1987,6 @@ void RenderProcessHostImpl::CreateMessageFilters() {
|
||||
#if BUILDFLAG(ENABLE_PLUGINS)
|
||||
AddFilter(new PepperRendererConnection(GetID()));
|
||||
#endif
|
||||
#if defined(OS_MACOSX)
|
||||
AddFilter(new TextInputClientMessageFilter());
|
||||
#endif
|
||||
|
||||
p2p_socket_dispatcher_host_ =
|
||||
std::make_unique<P2PSocketDispatcherHost>(GetID());
|
||||
|
@ -98,11 +98,6 @@ class CONTENT_EXPORT TextInputClientMac {
|
||||
const gfx::Range& range,
|
||||
GetStringCallback callback);
|
||||
|
||||
// This is called on the IO thread when we get the renderer's reply for
|
||||
// GetStringFromRange.
|
||||
void GetStringFromRangeReply(ui::mojom::AttributedStringPtr string,
|
||||
const gfx::Point& point);
|
||||
|
||||
private:
|
||||
friend struct base::DefaultSingletonTraits<TextInputClientMac>;
|
||||
TextInputClientMac();
|
||||
@ -123,9 +118,6 @@ class CONTENT_EXPORT TextInputClientMac {
|
||||
base::Lock lock_;
|
||||
base::ConditionVariable condition_;
|
||||
|
||||
// The callback when received IPC TextInputClientReplyMsg_GotStringForRange.
|
||||
GetStringCallback replyForRangeHandler_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(TextInputClientMac);
|
||||
};
|
||||
|
||||
|
@ -15,31 +15,17 @@
|
||||
#include "content/browser/frame_host/render_frame_host_impl.h"
|
||||
#include "content/browser/renderer_host/render_widget_host_delegate.h"
|
||||
#include "content/browser/renderer_host/render_widget_host_impl.h"
|
||||
#include "content/common/text_input_client_messages.h"
|
||||
#include "ui/base/mojom/attributed_string.mojom.h"
|
||||
|
||||
namespace content {
|
||||
|
||||
namespace {
|
||||
|
||||
// TODO(ekaramad): TextInputClientObserver, the renderer side of
|
||||
// TextInputClientMac for each RenderWidgetHost, expects to have a
|
||||
// WebFrameWidget to use for handling these IPCs. However, for fullscreen flash,
|
||||
// we end up with a PepperWidget. For those scenarios, do not send the IPCs. We
|
||||
// need to figure out what features are properly supported and perhaps send the
|
||||
// IPC to the parent widget of the plugin (https://crbug.com/663384).
|
||||
bool SendMessageToRenderWidget(RenderWidgetHostImpl* widget,
|
||||
IPC::Message* message) {
|
||||
if (!widget->delegate() ||
|
||||
widget == widget->delegate()->GetFullscreenRenderWidgetHost()) {
|
||||
delete message;
|
||||
return false;
|
||||
}
|
||||
|
||||
DCHECK_EQ(widget->GetRoutingID(), message->routing_id());
|
||||
return widget->Send(message);
|
||||
}
|
||||
|
||||
// TODO(ekaramad): TextInputClientMac expects to have a RenderWidgetHost to use
|
||||
// for handling mojo calls. However, for fullscreen flash, we end up with a
|
||||
// PepperWidget. For those scenarios, do not send the mojo calls. We need to
|
||||
// figure out what features are properly supported and perhaps send the
|
||||
// mojo call to the parent widget of the plugin (https://crbug.com/663384).
|
||||
bool IsFullScreenRenderWidget(RenderWidgetHost* widget) {
|
||||
RenderWidgetHostImpl* rwhi = RenderWidgetHostImpl::From(widget);
|
||||
if (!rwhi->delegate() ||
|
||||
@ -86,19 +72,14 @@ void TextInputClientMac::GetStringAtPoint(RenderWidgetHost* rwh,
|
||||
void TextInputClientMac::GetStringFromRange(RenderWidgetHost* rwh,
|
||||
const gfx::Range& range,
|
||||
GetStringCallback callback) {
|
||||
DCHECK(!replyForRangeHandler_);
|
||||
replyForRangeHandler_ = std::move(callback);
|
||||
RenderWidgetHostImpl* rwhi = RenderWidgetHostImpl::From(rwh);
|
||||
SendMessageToRenderWidget(
|
||||
rwhi, new TextInputClientMsg_StringForRange(rwhi->GetRoutingID(), range));
|
||||
}
|
||||
RenderFrameHostImpl* rfhi = GetFocusedRenderFrameHostImpl(rwh);
|
||||
// If it doesn't have a focused frame, it calls |callback| with
|
||||
// an empty string and point.
|
||||
if (!rfhi)
|
||||
return std::move(callback).Run(nullptr, gfx::Point());
|
||||
|
||||
void TextInputClientMac::GetStringFromRangeReply(
|
||||
ui::mojom::AttributedStringPtr string,
|
||||
const gfx::Point& point) {
|
||||
if (replyForRangeHandler_) {
|
||||
std::move(replyForRangeHandler_).Run(std::move(string), point);
|
||||
}
|
||||
rfhi->GetAssociatedLocalFrame()->GetStringForRange(range,
|
||||
std::move(callback));
|
||||
}
|
||||
|
||||
uint32_t TextInputClientMac::GetCharacterIndexAtPoint(RenderWidgetHost* rwh,
|
||||
|
@ -14,7 +14,6 @@
|
||||
#include "base/threading/thread.h"
|
||||
#include "content/browser/renderer_host/render_process_host_impl.h"
|
||||
#include "content/browser/renderer_host/render_view_host_impl.h"
|
||||
#include "content/common/text_input_client_messages.h"
|
||||
#include "content/public/browser/render_frame_host.h"
|
||||
#include "content/public/browser/web_contents_observer.h"
|
||||
#include "content/public/test/browser_task_environment.h"
|
||||
|
@ -1,48 +0,0 @@
|
||||
// Copyright (c) 2012 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 CONTENT_BROWSER_RENDERER_HOST_TEXT_INPUT_CLIENT_MESSAGE_FILTER_H_
|
||||
#define CONTENT_BROWSER_RENDERER_HOST_TEXT_INPUT_CLIENT_MESSAGE_FILTER_H_
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include "base/macros.h"
|
||||
#include "content/public/browser/browser_message_filter.h"
|
||||
#include "content/public/browser/browser_thread.h"
|
||||
#include "ui/base/mojom/attributed_string.mojom-forward.h"
|
||||
|
||||
namespace gfx {
|
||||
class Point;
|
||||
}
|
||||
|
||||
namespace content {
|
||||
|
||||
// This is a browser-side message filter that lives on the IO thread to handle
|
||||
// replies to messages sent by the TextInputClientMac. See
|
||||
// content/browser/renderer_host/text_input_client_mac.h for more information.
|
||||
class CONTENT_EXPORT TextInputClientMessageFilter
|
||||
: public BrowserMessageFilter {
|
||||
public:
|
||||
TextInputClientMessageFilter();
|
||||
|
||||
// BrowserMessageFilter override:
|
||||
bool OnMessageReceived(const IPC::Message& message) override;
|
||||
void OverrideThreadForMessage(const IPC::Message& message,
|
||||
BrowserThread::ID* thread) override;
|
||||
|
||||
protected:
|
||||
~TextInputClientMessageFilter() override;
|
||||
|
||||
private:
|
||||
// IPC Message handlers:
|
||||
void OnGotStringFromRange(
|
||||
const ui::mojom::AttributedString& attributed_string,
|
||||
const gfx::Point& point);
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(TextInputClientMessageFilter);
|
||||
};
|
||||
|
||||
} // namespace content
|
||||
|
||||
#endif // CONTENT_BROWSER_RENDERER_HOST_TEXT_INPUT_CLIENT_MESSAGE_FILTER_H_
|
@ -1,52 +0,0 @@
|
||||
// Copyright (c) 2012 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/renderer_host/text_input_client_message_filter.h"
|
||||
|
||||
#include "base/strings/string16.h"
|
||||
#include "content/browser/renderer_host/render_view_host_impl.h"
|
||||
#include "content/browser/renderer_host/text_input_client_mac.h"
|
||||
#include "content/common/text_input_client_messages.h"
|
||||
#include "content/public/browser/render_widget_host_view.h"
|
||||
#include "ipc/ipc_message_macros.h"
|
||||
#include "ui/base/mojom/attributed_string.mojom.h"
|
||||
#include "ui/gfx/geometry/point.h"
|
||||
#include "ui/gfx/range/range.h"
|
||||
|
||||
namespace content {
|
||||
|
||||
TextInputClientMessageFilter::TextInputClientMessageFilter()
|
||||
: BrowserMessageFilter(TextInputClientMsgStart) {}
|
||||
|
||||
bool TextInputClientMessageFilter::OnMessageReceived(
|
||||
const IPC::Message& message) {
|
||||
bool handled = true;
|
||||
IPC_BEGIN_MESSAGE_MAP(TextInputClientMessageFilter, message)
|
||||
IPC_MESSAGE_HANDLER(TextInputClientReplyMsg_GotStringForRange,
|
||||
OnGotStringFromRange)
|
||||
IPC_MESSAGE_UNHANDLED(handled = false)
|
||||
IPC_END_MESSAGE_MAP()
|
||||
return handled;
|
||||
}
|
||||
|
||||
void TextInputClientMessageFilter::OverrideThreadForMessage(
|
||||
const IPC::Message& message,
|
||||
BrowserThread::ID* thread) {
|
||||
switch (message.type()) {
|
||||
case TextInputClientReplyMsg_GotStringForRange::ID:
|
||||
*thread = BrowserThread::UI;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
TextInputClientMessageFilter::~TextInputClientMessageFilter() {}
|
||||
|
||||
void TextInputClientMessageFilter::OnGotStringFromRange(
|
||||
const ui::mojom::AttributedString& attributed_string,
|
||||
const gfx::Point& point) {
|
||||
TextInputClientMac* service = TextInputClientMac::GetInstance();
|
||||
service->GetStringFromRangeReply(attributed_string.Clone(), point);
|
||||
}
|
||||
|
||||
} // namespace content
|
@ -94,6 +94,8 @@ IN_PROC_BROWSER_TEST_P(SitePerProcessMacBrowserTest,
|
||||
FrameTreeNode* child = root->child_at(0);
|
||||
NavigateFrameToURL(child,
|
||||
embedded_test_server()->GetURL("b.com", "/title1.html"));
|
||||
web_contents()->GetFrameTree()->SetFocusedFrame(
|
||||
child, web_contents()->GetSiteInstance());
|
||||
|
||||
RenderWidgetHost* child_widget_host =
|
||||
child->current_frame_host()->GetRenderWidgetHost();
|
||||
@ -121,6 +123,8 @@ IN_PROC_BROWSER_TEST_P(SitePerProcessMacBrowserTest,
|
||||
FrameTreeNode* root = web_contents()->GetFrameTree()->root();
|
||||
RenderWidgetHost* widget_host =
|
||||
root->current_frame_host()->GetRenderWidgetHost();
|
||||
web_contents()->GetFrameTree()->SetFocusedFrame(
|
||||
root, web_contents()->GetSiteInstance());
|
||||
TextInputClientMacHelper helper;
|
||||
|
||||
// Get string from range.
|
||||
|
@ -186,7 +186,6 @@ source_set("common") {
|
||||
"skia_utils.cc",
|
||||
"skia_utils.h",
|
||||
"state_transitions.h",
|
||||
"text_input_client_messages.h",
|
||||
"thread_pool_util.cc",
|
||||
"thread_pool_util.h",
|
||||
"unfreezable_frame_messages.h",
|
||||
|
@ -41,11 +41,6 @@
|
||||
#ifndef CONTENT_COMMON_RESOURCE_MESSAGES_H_
|
||||
#error "Failed to include content/common/resource_messages.h"
|
||||
#endif
|
||||
#undef CONTENT_COMMON_TEXT_INPUT_CLIENT_MESSAGES_H_
|
||||
#include "content/common/text_input_client_messages.h"
|
||||
#ifndef CONTENT_COMMON_TEXT_INPUT_CLIENT_MESSAGES_H_
|
||||
#error "Failed to include content/common/text_input_client_messages.h"
|
||||
#endif
|
||||
#undef CONTENT_COMMON_UNFREEZABLE_FRAME_MESSAGES_H_
|
||||
#include "content/common/unfreezable_frame_messages.h"
|
||||
#ifndef CONTENT_COMMON_UNFREEZABLE_FRAME_MESSAGES_H_
|
||||
|
@ -7,7 +7,6 @@
|
||||
|
||||
#include "base/strings/string16.h"
|
||||
#include "content/common/content_export.h"
|
||||
#include "ipc/ipc_message_utils.h"
|
||||
#include "ui/base/mojom/attributed_string.mojom.h"
|
||||
#include "ui/gfx/range/range.h"
|
||||
|
||||
@ -17,11 +16,6 @@
|
||||
class NSAttributedString;
|
||||
#endif
|
||||
|
||||
namespace base {
|
||||
class Pickle;
|
||||
class PickleIterator;
|
||||
}
|
||||
|
||||
namespace mojo {
|
||||
|
||||
template <>
|
||||
@ -40,20 +34,4 @@ struct CONTENT_EXPORT
|
||||
|
||||
} // namespace mojo
|
||||
|
||||
// IPC ParamTraits specialization //////////////////////////////////////////////
|
||||
|
||||
namespace IPC {
|
||||
|
||||
template <>
|
||||
struct ParamTraits<ui::mojom::FontAttributePtr> {
|
||||
typedef ui::mojom::FontAttributePtr param_type;
|
||||
static void Write(base::Pickle* m, const param_type& p);
|
||||
static bool Read(const base::Pickle* m,
|
||||
base::PickleIterator* iter,
|
||||
param_type* r);
|
||||
static void Log(const param_type& p, std::string* l);
|
||||
};
|
||||
|
||||
} // namespace IPC
|
||||
|
||||
#endif // CONTENT_COMMON_MAC_ATTRIBUTED_STRING_TYPE_CONVERTERS_H_
|
||||
|
@ -93,41 +93,3 @@ TypeConverter<ui::mojom::AttributedStringPtr, NSAttributedString*>::Convert(
|
||||
}
|
||||
|
||||
} // namespace mojo
|
||||
|
||||
// IPC ParamTraits specialization //////////////////////////////////////////////
|
||||
|
||||
namespace IPC {
|
||||
|
||||
using ui::mojom::FontAttributePtr;
|
||||
|
||||
void ParamTraits<FontAttributePtr>::Write(base::Pickle* m,
|
||||
const param_type& p) {
|
||||
WriteParam(m, p->font_name);
|
||||
WriteParam(m, p->font_point_size);
|
||||
WriteParam(m, p->effective_range);
|
||||
}
|
||||
|
||||
bool ParamTraits<FontAttributePtr>::Read(const base::Pickle* m,
|
||||
base::PickleIterator* iter,
|
||||
param_type* p) {
|
||||
bool success = true;
|
||||
|
||||
base::string16 font_name;
|
||||
success &= ReadParam(m, iter, &font_name);
|
||||
|
||||
float font_point_size;
|
||||
success &= ReadParam(m, iter, &font_point_size);
|
||||
|
||||
gfx::Range range;
|
||||
success &= ReadParam(m, iter, &range);
|
||||
|
||||
if (success) {
|
||||
*p = ui::mojom::FontAttribute::New(std::move(font_name), font_point_size,
|
||||
range);
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
void ParamTraits<FontAttributePtr>::Log(const param_type& p, std::string* l) {}
|
||||
|
||||
} // namespace IPC
|
||||
|
@ -1,59 +0,0 @@
|
||||
// Copyright (c) 2012 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 CONTENT_COMMON_TEXT_INPUT_CLIENT_MESSAGES_H_
|
||||
#define CONTENT_COMMON_TEXT_INPUT_CLIENT_MESSAGES_H_
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include "build/build_config.h"
|
||||
#include "ipc/ipc_message_macros.h"
|
||||
#include "ui/gfx/geometry/rect.h"
|
||||
#include "ui/gfx/range/range.h"
|
||||
|
||||
#if defined(OS_MACOSX)
|
||||
#include "content/common/mac/attributed_string_type_converters.h"
|
||||
#include "ui/base/mojom/attributed_string.mojom.h"
|
||||
#endif
|
||||
|
||||
#define IPC_MESSAGE_START TextInputClientMsgStart
|
||||
#undef IPC_MESSAGE_EXPORT
|
||||
#define IPC_MESSAGE_EXPORT CONTENT_EXPORT
|
||||
|
||||
#if defined(OS_MACOSX)
|
||||
IPC_STRUCT_TRAITS_BEGIN(ui::mojom::FontAttribute)
|
||||
IPC_STRUCT_TRAITS_MEMBER(font_name)
|
||||
IPC_STRUCT_TRAITS_MEMBER(font_point_size)
|
||||
IPC_STRUCT_TRAITS_MEMBER(effective_range)
|
||||
IPC_STRUCT_TRAITS_END()
|
||||
|
||||
IPC_STRUCT_TRAITS_BEGIN(ui::mojom::AttributedString)
|
||||
IPC_STRUCT_TRAITS_MEMBER(string)
|
||||
IPC_STRUCT_TRAITS_MEMBER(attributes)
|
||||
IPC_STRUCT_TRAITS_END()
|
||||
#endif
|
||||
|
||||
// Browser -> Renderer Messages ////////////////////////////////////////////////
|
||||
// These messages are sent from the browser to the renderer. Each one has a
|
||||
// corresponding reply message.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Tells the renderer to send back the text fragment in a given range.
|
||||
IPC_MESSAGE_ROUTED1(TextInputClientMsg_StringForRange,
|
||||
gfx::Range)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Renderer -> Browser Replies /////////////////////////////////////////////////
|
||||
// These messages are sent in reply to the above messages.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#if defined(OS_MACOSX)
|
||||
// Reply message for TextInputClientMsg_StringForRange.
|
||||
IPC_MESSAGE_ROUTED2(TextInputClientReplyMsg_GotStringForRange,
|
||||
ui::mojom::AttributedString,
|
||||
gfx::Point)
|
||||
#endif // defined(OS_MACOSX)
|
||||
|
||||
#endif // CONTENT_COMMON_TEXT_INPUT_CLIENT_MESSAGES_H_
|
@ -135,15 +135,18 @@ void GetStringAtPointForRenderWidget(
|
||||
TextInputClientMac::GetInstance()->GetStringAtPoint(
|
||||
rwh, point,
|
||||
base::BindOnce(
|
||||
base::RetainBlock(
|
||||
^(base::OnceCallback<void(const std::string&, const gfx::Point&)>
|
||||
callback,
|
||||
ui::mojom::AttributedStringPtr attributed_string,
|
||||
const gfx::Point& baseline_point) {
|
||||
std::string string = base::SysNSStringToUTF8(
|
||||
[attributed_string.To<NSAttributedString*>() string]);
|
||||
std::move(callback).Run(string, baseline_point);
|
||||
}),
|
||||
base::RetainBlock(^(
|
||||
base::OnceCallback<void(const std::string&, const gfx::Point&)>
|
||||
callback,
|
||||
ui::mojom::AttributedStringPtr attributed_string,
|
||||
const gfx::Point& baseline_point) {
|
||||
std::string string =
|
||||
attributed_string
|
||||
? base::SysNSStringToUTF8(
|
||||
[attributed_string.To<NSAttributedString*>() string])
|
||||
: std::string();
|
||||
std::move(callback).Run(string, baseline_point);
|
||||
}),
|
||||
std::move(result_callback)));
|
||||
}
|
||||
|
||||
@ -155,15 +158,18 @@ void GetStringFromRangeForRenderWidget(
|
||||
TextInputClientMac::GetInstance()->GetStringFromRange(
|
||||
rwh, range,
|
||||
base::BindOnce(
|
||||
base::RetainBlock(
|
||||
^(base::OnceCallback<void(const std::string&, const gfx::Point&)>
|
||||
callback,
|
||||
ui::mojom::AttributedStringPtr attributed_string,
|
||||
const gfx::Point& baseline_point) {
|
||||
std::string string = base::SysNSStringToUTF8(
|
||||
[attributed_string.To<NSAttributedString*>() string]);
|
||||
std::move(callback).Run(string, baseline_point);
|
||||
}),
|
||||
base::RetainBlock(^(
|
||||
base::OnceCallback<void(const std::string&, const gfx::Point&)>
|
||||
callback,
|
||||
ui::mojom::AttributedStringPtr attributed_string,
|
||||
const gfx::Point& baseline_point) {
|
||||
std::string string =
|
||||
attributed_string
|
||||
? base::SysNSStringToUTF8(
|
||||
[attributed_string.To<NSAttributedString*>() string])
|
||||
: std::string();
|
||||
std::move(callback).Run(string, baseline_point);
|
||||
}),
|
||||
std::move(result_callback)));
|
||||
}
|
||||
|
||||
|
@ -105,6 +105,10 @@ void FakeLocalFrame::GetSavableResourceLinks(
|
||||
#if defined(OS_MACOSX)
|
||||
void FakeLocalFrame::GetCharacterIndexAtPoint(const gfx::Point& point) {}
|
||||
void FakeLocalFrame::GetFirstRectForRange(const gfx::Range& range) {}
|
||||
void FakeLocalFrame::GetStringForRange(const gfx::Range& range,
|
||||
GetStringForRangeCallback callback) {
|
||||
std::move(callback).Run(nullptr, gfx::Point());
|
||||
}
|
||||
#endif
|
||||
|
||||
void FakeLocalFrame::BindReportingObserver(
|
||||
|
@ -83,6 +83,8 @@ class FakeLocalFrame : public blink::mojom::LocalFrame {
|
||||
#if defined(OS_MACOSX)
|
||||
void GetCharacterIndexAtPoint(const gfx::Point& point) override;
|
||||
void GetFirstRectForRange(const gfx::Range& range) override;
|
||||
void GetStringForRange(const gfx::Range& range,
|
||||
GetStringForRangeCallback callback) override;
|
||||
#endif
|
||||
void BindReportingObserver(
|
||||
mojo::PendingReceiver<blink::mojom::ReportingObserver> receiver) override;
|
||||
|
@ -10,22 +10,20 @@
|
||||
|
||||
#include "base/callback.h"
|
||||
#include "base/strings/string16.h"
|
||||
#include "build/build_config.h"
|
||||
#include "ui/base/ime/mojom/text_input_state.mojom.h"
|
||||
#include "ui/base/ime/mojom/virtual_keyboard_types.mojom.h"
|
||||
#include "ui/base/ime/text_input_mode.h"
|
||||
#include "ui/base/ime/text_input_type.h"
|
||||
|
||||
#ifdef OS_MACOSX
|
||||
#include "content/public/browser/browser_message_filter.h"
|
||||
#endif
|
||||
|
||||
#if defined(USE_AURA)
|
||||
#include "ui/events/event_constants.h"
|
||||
#endif
|
||||
|
||||
namespace ipc {
|
||||
class Message;
|
||||
}
|
||||
#if defined(OS_MACOSX)
|
||||
#include "content/public/test/fake_local_frame.h"
|
||||
#include "mojo/public/cpp/bindings/associated_remote.h"
|
||||
#endif
|
||||
|
||||
namespace gfx {
|
||||
class Range;
|
||||
@ -37,9 +35,7 @@ struct ImeTextSpan;
|
||||
|
||||
namespace content {
|
||||
|
||||
class MessageLoopRunner;
|
||||
class RenderFrameHost;
|
||||
class RenderProcessHost;
|
||||
class RenderWidgetHost;
|
||||
class RenderWidgetHostView;
|
||||
class RenderWidgetHostViewBase;
|
||||
@ -245,40 +241,35 @@ class TestInputMethodObserver {
|
||||
TestInputMethodObserver();
|
||||
};
|
||||
|
||||
#ifdef OS_MACOSX
|
||||
// The test message filter for TextInputClientMac incoming messages from the
|
||||
// renderer.
|
||||
// NOTE: This filter should be added to the intended RenderProcessHost before
|
||||
// the actual TextInputClientMessageFilter, otherwise, the messages
|
||||
// will be handled and will never receive this filter.
|
||||
class TestTextInputClientMessageFilter : public BrowserMessageFilter {
|
||||
#if defined(OS_MACOSX)
|
||||
// Helper class to test LocalFrame::GetStringForRange.
|
||||
class TextInputTestLocalFrame : public FakeLocalFrame {
|
||||
public:
|
||||
// Creates the filter and adds itself to |host|.
|
||||
TestTextInputClientMessageFilter(RenderProcessHost* host);
|
||||
TextInputTestLocalFrame();
|
||||
~TextInputTestLocalFrame() override;
|
||||
|
||||
// Wait until the IPC TextInputClientReplyMsg_GotStringForRange arrives.
|
||||
void WaitForStringFromRange();
|
||||
|
||||
// BrowserMessageFilter overrides.
|
||||
bool OnMessageReceived(const IPC::Message& message) override;
|
||||
|
||||
// Sets a callback for the string for range IPC arriving from the renderer.
|
||||
// The callback is invoked before that of TextInputClientMac and is handled on
|
||||
// UI thread.
|
||||
void SetUp(content::RenderFrameHost* render_frame_host);
|
||||
void WaitForGetStringForRange();
|
||||
// Sets a callback for the string for range message arriving from the
|
||||
// renderer. The callback is invoked before that of TextInputClientMac.
|
||||
void SetStringForRangeCallback(base::RepeatingClosure callback);
|
||||
|
||||
RenderProcessHost* process() const { return host_; }
|
||||
std::string string_from_range() { return string_from_range_; }
|
||||
std::string GetStringFromRange() { return string_from_range_; }
|
||||
void SetStringFromRange(std::string string_from_range) {
|
||||
string_from_range_ = string_from_range;
|
||||
}
|
||||
|
||||
// blink::mojom::LocalFrame:
|
||||
void GetStringForRange(const gfx::Range& range,
|
||||
GetStringForRangeCallback callback) override;
|
||||
|
||||
private:
|
||||
~TestTextInputClientMessageFilter() override;
|
||||
RenderProcessHost* const host_;
|
||||
std::string string_from_range_;
|
||||
bool received_string_from_range_;
|
||||
base::OnceClosure quit_closure_;
|
||||
base::RepeatingClosure string_for_range_callback_;
|
||||
scoped_refptr<MessageLoopRunner> message_loop_runner_;
|
||||
std::string string_from_range_;
|
||||
mojo::AssociatedRemote<blink::mojom::LocalFrame> local_frame_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(TestTextInputClientMessageFilter);
|
||||
DISALLOW_COPY_AND_ASSIGN(TextInputTestLocalFrame);
|
||||
};
|
||||
|
||||
// Requests the |tab_view| for the definition of the word identified by the
|
||||
@ -288,9 +279,6 @@ class TestTextInputClientMessageFilter : public BrowserMessageFilter {
|
||||
void AskForLookUpDictionaryForRange(RenderWidgetHostView* tab_view,
|
||||
const gfx::Range& range);
|
||||
|
||||
// Returns the total count of NSWindows instances which belong to the currently
|
||||
// running NSApplication.
|
||||
size_t GetOpenNSWindowsCount();
|
||||
#endif
|
||||
|
||||
} // namespace content
|
||||
|
@ -6,73 +6,64 @@
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
#include "base/memory/ref_counted.h"
|
||||
#include "base/strings/sys_string_conversions.h"
|
||||
#include "base/strings/utf_string_conversions.h"
|
||||
#include "content/browser/browser_thread_impl.h"
|
||||
#include "content/browser/frame_host/render_frame_host_impl.h"
|
||||
#include "content/browser/renderer_host/render_widget_host_view_mac.h"
|
||||
#include "content/browser/site_instance_impl.h"
|
||||
#include "content/common/mac/attributed_string_type_converters.h"
|
||||
#include "content/common/text_input_client_messages.h"
|
||||
#include "content/public/browser/browser_task_traits.h"
|
||||
#include "content/public/browser/browser_thread.h"
|
||||
#include "content/public/browser/render_process_host.h"
|
||||
#include "content/public/test/test_utils.h"
|
||||
#include "ipc/ipc_message_macros.h"
|
||||
#include "ui/base/mojom/attributed_string.mojom.h"
|
||||
|
||||
namespace content {
|
||||
|
||||
TestTextInputClientMessageFilter::TestTextInputClientMessageFilter(
|
||||
RenderProcessHost* host)
|
||||
: BrowserMessageFilter(TextInputClientMsgStart),
|
||||
host_(host),
|
||||
received_string_from_range_(false) {
|
||||
host->AddFilter(this);
|
||||
TextInputTestLocalFrame::TextInputTestLocalFrame() = default;
|
||||
|
||||
TextInputTestLocalFrame::~TextInputTestLocalFrame() = default;
|
||||
|
||||
void TextInputTestLocalFrame::SetUp(
|
||||
content::RenderFrameHost* render_frame_host) {
|
||||
local_frame_ = std::move(
|
||||
static_cast<RenderFrameHostImpl*>(render_frame_host)->local_frame_);
|
||||
FakeLocalFrame::Init(render_frame_host->GetRemoteAssociatedInterfaces());
|
||||
}
|
||||
|
||||
TestTextInputClientMessageFilter::~TestTextInputClientMessageFilter() {}
|
||||
|
||||
void TestTextInputClientMessageFilter::WaitForStringFromRange() {
|
||||
if (received_string_from_range_)
|
||||
return;
|
||||
message_loop_runner_ = new MessageLoopRunner();
|
||||
message_loop_runner_->Run();
|
||||
void TextInputTestLocalFrame::WaitForGetStringForRange() {
|
||||
base::RunLoop run_loop;
|
||||
quit_closure_ = run_loop.QuitClosure();
|
||||
run_loop.Run();
|
||||
}
|
||||
|
||||
bool TestTextInputClientMessageFilter::OnMessageReceived(
|
||||
const IPC::Message& message) {
|
||||
DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
||||
if (message.type() == TextInputClientReplyMsg_GotStringForRange::ID) {
|
||||
if (!string_for_range_callback_.is_null()) {
|
||||
GetUIThreadTaskRunner({})->PostTask(FROM_HERE,
|
||||
string_for_range_callback_);
|
||||
}
|
||||
|
||||
received_string_from_range_ = true;
|
||||
|
||||
// Now decode the string to get the word.
|
||||
TextInputClientReplyMsg_GotStringForRange::Param params;
|
||||
TextInputClientReplyMsg_GotStringForRange::Read(&message, ¶ms);
|
||||
const ui::mojom::AttributedString& attributed_string = std::get<0>(params);
|
||||
ui::mojom::AttributedStringPtr string = attributed_string.Clone();
|
||||
NSAttributedString* ns_attributed_string = string.To<NSAttributedString*>();
|
||||
string_from_range_ = base::SysNSStringToUTF8([ns_attributed_string string]);
|
||||
|
||||
// Stop the message loop if it is running.
|
||||
if (message_loop_runner_) {
|
||||
GetUIThreadTaskRunner({})->PostTask(FROM_HERE,
|
||||
message_loop_runner_->QuitClosure());
|
||||
}
|
||||
}
|
||||
|
||||
// unhandled - leave it for the actual TextInputClientMessageFilter to handle.
|
||||
return false;
|
||||
}
|
||||
|
||||
void TestTextInputClientMessageFilter::SetStringForRangeCallback(
|
||||
void TextInputTestLocalFrame::SetStringForRangeCallback(
|
||||
base::RepeatingClosure callback) {
|
||||
string_for_range_callback_ = std::move(callback);
|
||||
}
|
||||
|
||||
void TextInputTestLocalFrame::GetStringForRange(
|
||||
const gfx::Range& range,
|
||||
GetStringForRangeCallback callback) {
|
||||
local_frame_->GetStringForRange(
|
||||
range,
|
||||
base::BindOnce(
|
||||
[](TextInputTestLocalFrame* frame, GetStringForRangeCallback callback,
|
||||
ui::mojom::AttributedStringPtr attributed_string,
|
||||
const gfx::Point& point) {
|
||||
// If |string_for_range_callback_| is set, it should be called
|
||||
// first.
|
||||
if (!frame->string_for_range_callback_.is_null())
|
||||
std::move(frame->string_for_range_callback_).Run();
|
||||
|
||||
// Updates the string from the range and calls |callback|.
|
||||
frame->SetStringFromRange(
|
||||
base::UTF16ToUTF8(attributed_string ? attributed_string->string
|
||||
: base::string16()));
|
||||
std::move(callback).Run(std::move(attributed_string), gfx::Point());
|
||||
|
||||
// Calls |quit_closure_|.
|
||||
if (frame->quit_closure_)
|
||||
std::move(frame->quit_closure_).Run();
|
||||
},
|
||||
base::Unretained(this), std::move(callback)));
|
||||
}
|
||||
|
||||
void AskForLookUpDictionaryForRange(RenderWidgetHostView* tab_view,
|
||||
const gfx::Range& range) {
|
||||
RenderWidgetHostViewMac* tab_view_mac =
|
||||
@ -80,8 +71,4 @@ void AskForLookUpDictionaryForRange(RenderWidgetHostView* tab_view,
|
||||
tab_view_mac->LookUpDictionaryOverlayFromRange(range);
|
||||
}
|
||||
|
||||
size_t GetOpenNSWindowsCount() {
|
||||
return [[NSApp windows] count];
|
||||
}
|
||||
|
||||
} // namespace content
|
||||
|
@ -436,13 +436,6 @@ target(link_target_type, "renderer") {
|
||||
deps += [ "//components/services/font/public/cpp" ]
|
||||
}
|
||||
|
||||
if (is_mac) {
|
||||
sources += [
|
||||
"text_input_client_observer.cc",
|
||||
"text_input_client_observer.h",
|
||||
]
|
||||
}
|
||||
|
||||
if (is_fuchsia) {
|
||||
sources += [
|
||||
"media/audio/fuchsia_audio_device_factory.cc",
|
||||
|
@ -9,7 +9,6 @@
|
||||
#include "content/common/frame_messages.h"
|
||||
#include "content/common/frame_replication_state.h"
|
||||
#include "content/common/input_messages.h"
|
||||
#include "content/common/text_input_client_messages.h"
|
||||
#include "content/common/unfreezable_frame_messages.h"
|
||||
#include "content/public/browser/native_web_keyboard_event.h"
|
||||
#include "content/public/common/web_preferences.h"
|
||||
|
@ -455,11 +455,6 @@ void RenderWidget::Initialize(ShowCallback show_callback,
|
||||
|
||||
show_callback_ = std::move(show_callback);
|
||||
|
||||
#if defined(OS_MACOSX)
|
||||
text_input_client_observer_ =
|
||||
std::make_unique<TextInputClientObserver>(for_frame() ? this : nullptr);
|
||||
#endif
|
||||
|
||||
webwidget_mouse_lock_target_.reset(new WebWidgetLockTarget(this));
|
||||
mouse_lock_dispatcher_.reset(new RenderWidgetMouseLockDispatcher(this));
|
||||
|
||||
@ -505,11 +500,6 @@ bool RenderWidget::OnMessageReceived(const IPC::Message& message) {
|
||||
if (IsForProvisionalFrame())
|
||||
return false;
|
||||
|
||||
#if defined(OS_MACOSX)
|
||||
if (IPC_MESSAGE_CLASS(message) == TextInputClientMsgStart)
|
||||
return text_input_client_observer_->OnMessageReceived(message);
|
||||
#endif
|
||||
|
||||
IPC_BEGIN_MESSAGE_MAP(RenderWidget, message)
|
||||
IPC_MESSAGE_HANDLER(WidgetMsg_DisableDeviceEmulation,
|
||||
OnDisableDeviceEmulation)
|
||||
|
@ -65,10 +65,6 @@
|
||||
#include "ui/gfx/range/range.h"
|
||||
#include "ui/surface/transport_dib.h"
|
||||
|
||||
#if defined(OS_MACOSX)
|
||||
#include "content/renderer/text_input_client_observer.h"
|
||||
#endif
|
||||
|
||||
namespace IPC {
|
||||
class SyncMessageFilter;
|
||||
}
|
||||
@ -723,12 +719,6 @@ class CONTENT_EXPORT RenderWidget
|
||||
// WebWidgetClient::Show() occurs.
|
||||
ShowCallback show_callback_;
|
||||
|
||||
#if defined(OS_MACOSX)
|
||||
// Responds to IPCs from TextInputClientMac regarding getting string at given
|
||||
// position or range as well as finding character index at a given position.
|
||||
std::unique_ptr<TextInputClientObserver> text_input_client_observer_;
|
||||
#endif
|
||||
|
||||
// This field stores drag/drop related info for the event that is currently
|
||||
// being handled. If the current event results in starting a drag/drop
|
||||
// session, this info is sent to the browser along with other drag/drop info.
|
||||
|
@ -1,76 +0,0 @@
|
||||
// Copyright (c) 2012 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/renderer/text_input_client_observer.h"
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "content/common/mac/attributed_string_type_converters.h"
|
||||
#include "content/common/text_input_client_messages.h"
|
||||
#include "content/public/renderer/render_thread.h"
|
||||
#include "content/renderer/pepper/pepper_plugin_instance_impl.h"
|
||||
#include "content/renderer/render_frame_impl.h"
|
||||
#include "content/renderer/render_view_impl.h"
|
||||
#include "content/renderer/render_widget.h"
|
||||
#include "ipc/ipc_message.h"
|
||||
#include "third_party/blink/public/web/mac/web_substring_util.h"
|
||||
#include "third_party/blink/public/web/web_frame_widget.h"
|
||||
#include "third_party/blink/public/web/web_local_frame.h"
|
||||
#include "third_party/blink/public/web/web_view.h"
|
||||
|
||||
namespace content {
|
||||
|
||||
TextInputClientObserver::TextInputClientObserver(RenderWidget* render_widget)
|
||||
: render_widget_(render_widget) {}
|
||||
|
||||
TextInputClientObserver::~TextInputClientObserver() = default;
|
||||
|
||||
bool TextInputClientObserver::OnMessageReceived(const IPC::Message& message) {
|
||||
bool handled = true;
|
||||
IPC_BEGIN_MESSAGE_MAP(TextInputClientObserver, message)
|
||||
IPC_MESSAGE_HANDLER(TextInputClientMsg_StringForRange, OnStringForRange)
|
||||
IPC_MESSAGE_UNHANDLED(handled = false)
|
||||
IPC_END_MESSAGE_MAP()
|
||||
return handled;
|
||||
}
|
||||
|
||||
bool TextInputClientObserver::Send(IPC::Message* message) {
|
||||
// This class is attached to the main frame RenderWidget, but its messages
|
||||
// are not received on RenderWidgetHostImpl, so there's no need to send
|
||||
// through RenderWidget or use its routing id.
|
||||
return RenderThread::Get()->Send(message);
|
||||
}
|
||||
|
||||
blink::WebFrameWidget* TextInputClientObserver::GetWebFrameWidget() const {
|
||||
return static_cast<blink::WebFrameWidget*>(render_widget_->GetWebWidget());
|
||||
}
|
||||
|
||||
blink::WebLocalFrame* TextInputClientObserver::GetFocusedFrame() const {
|
||||
if (auto* frame_widget = GetWebFrameWidget()) {
|
||||
blink::WebLocalFrame* local_root = frame_widget->LocalRoot();
|
||||
blink::WebLocalFrame* focused = local_root->View()->FocusedFrame();
|
||||
return focused->LocalRoot() == local_root ? focused : nullptr;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void TextInputClientObserver::OnStringForRange(gfx::Range range) {
|
||||
gfx::Point baseline_point;
|
||||
NSAttributedString* string = nil;
|
||||
blink::WebLocalFrame* frame = GetFocusedFrame();
|
||||
// TODO(yabinh): Null check should not be necessary.
|
||||
// See crbug.com/304341
|
||||
if (frame) {
|
||||
string = blink::WebSubstringUtil::AttributedSubstringInRange(
|
||||
frame, range.start(), range.length(), &baseline_point);
|
||||
}
|
||||
ui::mojom::AttributedStringPtr attributed_string =
|
||||
ui::mojom::AttributedString::From(string);
|
||||
Send(new TextInputClientReplyMsg_GotStringForRange(
|
||||
MSG_ROUTING_NONE, *attributed_string, baseline_point));
|
||||
}
|
||||
|
||||
} // namespace content
|
@ -1,68 +0,0 @@
|
||||
// Copyright (c) 2012 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 CONTENT_RENDERER_TEXT_INPUT_CLIENT_OBSERVER_H_
|
||||
#define CONTENT_RENDERER_TEXT_INPUT_CLIENT_OBSERVER_H_
|
||||
|
||||
#include "base/macros.h"
|
||||
#include "build/build_config.h"
|
||||
#include "content/public/renderer/render_view_observer.h"
|
||||
#include "ppapi/buildflags/buildflags.h"
|
||||
#include "ui/gfx/geometry/point.h"
|
||||
#include "ui/gfx/range/range.h"
|
||||
|
||||
namespace blink {
|
||||
class WebFrameWidget;
|
||||
class WebLocalFrame;
|
||||
}
|
||||
|
||||
namespace content {
|
||||
|
||||
class PepperPluginInstanceImpl;
|
||||
class RenderWidget;
|
||||
|
||||
// This is the renderer-side message filter that generates the replies for the
|
||||
// messages sent by the TextInputClientMac. See
|
||||
// content/browser/renderer_host/text_input_client_mac.h for more information.
|
||||
class TextInputClientObserver : public IPC::Listener, public IPC::Sender {
|
||||
public:
|
||||
// Pass a null RenderWidget when the TextInputClientObserver is for a
|
||||
// RenderWidget not associated with a RenderFrame. The TextInputClientObserver
|
||||
// expects that the RenderWidget's WebWidget will always be a WebFrameWidget.
|
||||
// When given a null, the TextInputClientObserver can still reply to IPC
|
||||
// messages with empty results.
|
||||
explicit TextInputClientObserver(RenderWidget* render_widget);
|
||||
~TextInputClientObserver() override;
|
||||
|
||||
// IPC::Listener override.
|
||||
bool OnMessageReceived(const IPC::Message& message) override;
|
||||
|
||||
// IPC::Sender override.
|
||||
bool Send(IPC::Message* message) override;
|
||||
|
||||
private:
|
||||
// The WebFrameWidget corresponding to this TextInputClientObserver.
|
||||
blink::WebFrameWidget* GetWebFrameWidget() const;
|
||||
|
||||
blink::WebLocalFrame* GetFocusedFrame() const;
|
||||
|
||||
#if BUILDFLAG(ENABLE_PLUGINS)
|
||||
// Returns the currently focused pepper plugin on the page. The expectation is
|
||||
// that the focused pepper plugin is inside a frame whose local root is equal
|
||||
// to GetWebFrameWidget()->localRoot().
|
||||
PepperPluginInstanceImpl* GetFocusedPepperPlugin() const;
|
||||
#endif
|
||||
|
||||
// IPC Message handlers:
|
||||
void OnStringForRange(gfx::Range range);
|
||||
|
||||
// The RenderWidget owning this instance of the observer.
|
||||
RenderWidget* render_widget_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(TextInputClientObserver);
|
||||
};
|
||||
|
||||
} // namespace content
|
||||
|
||||
#endif // CONTENT_RENDERER_TEXT_INPUT_CLIENT_OBSERVER_H_
|
@ -27,7 +27,6 @@ enum IPCMessageStart {
|
||||
DragMsgStart,
|
||||
PrintMsgStart,
|
||||
ExtensionMsgStart,
|
||||
TextInputClientMsgStart,
|
||||
ChromotingMsgStart,
|
||||
AndroidWebViewMsgStart,
|
||||
NaClHostMsgStart,
|
||||
|
@ -64,8 +64,6 @@ void WriteIpcMessageIdAsProtozero(uint32_t message_id,
|
||||
case ExtensionMsgStart:
|
||||
message_class = ChromeLegacyIpc::CLASS_EXTENSION;
|
||||
break;
|
||||
case TextInputClientMsgStart:
|
||||
message_class = ChromeLegacyIpc::CLASS_TEXT_INPUT_CLIENT;
|
||||
break;
|
||||
case ChromotingMsgStart:
|
||||
message_class = ChromeLegacyIpc::CLASS_CHROMOTING;
|
||||
|
2
third_party/blink/public/BUILD.gn
vendored
2
third_party/blink/public/BUILD.gn
vendored
@ -278,8 +278,6 @@ source_set("blink_headers") {
|
||||
"platform/webaudiosourceprovider_impl.h",
|
||||
"platform/websocket_handshake_throttle.h",
|
||||
"web/blink.h",
|
||||
"web/mac/web_substring_util.h",
|
||||
"web/mac/web_substring_util.h",
|
||||
"web/modules/autofill/web_form_element_observer.h",
|
||||
"web/modules/media/webmediaplayer_util.h",
|
||||
"web/modules/mediastream/encoded_video_frame.h",
|
||||
|
5
third_party/blink/public/mojom/BUILD.gn
vendored
5
third_party/blink/public/mojom/BUILD.gn
vendored
@ -431,7 +431,10 @@ mojom("mojom_core") {
|
||||
enable_bytecode_checks = false
|
||||
}
|
||||
if (is_mac) {
|
||||
public_deps += [ "//ui/gfx/range/mojom" ]
|
||||
public_deps += [
|
||||
"//ui/base/mojom",
|
||||
"//ui/gfx/range/mojom",
|
||||
]
|
||||
}
|
||||
|
||||
overridden_deps_blink = [
|
||||
|
@ -49,6 +49,9 @@ import "url/mojom/url.mojom";
|
||||
[EnableIf=is_mac]
|
||||
import "ui/gfx/range/mojom/range.mojom";
|
||||
|
||||
[EnableIf=is_mac]
|
||||
import "ui/base/mojom/attributed_string.mojom";
|
||||
|
||||
// Information about a subframe being saved as "complete html".
|
||||
struct SavableSubframe {
|
||||
// Original url of the subframe (i.e. based the parent's html sources).
|
||||
@ -565,6 +568,11 @@ interface LocalFrame {
|
||||
[EnableIf=is_mac]
|
||||
GetFirstRectForRange(gfx.mojom.Range range);
|
||||
|
||||
// Requests the text fragment in a given range.
|
||||
[EnableIf=is_mac]
|
||||
GetStringForRange(gfx.mojom.Range range)
|
||||
=> (ui.mojom.AttributedString? string, gfx.mojom.Point baseline_point);
|
||||
|
||||
// Binds |receiver| to the document of this frame.
|
||||
BindReportingObserver(
|
||||
pending_receiver<blink.mojom.ReportingObserver> receiver);
|
||||
|
2
third_party/blink/renderer/core/DEPS
vendored
2
third_party/blink/renderer/core/DEPS
vendored
@ -121,7 +121,7 @@ include_rules = [
|
||||
|
||||
specific_include_rules = {
|
||||
# Additional allowed includes for tests.
|
||||
".*_test(_.*)?\.(cc|h)" : [
|
||||
".*_test(_.*)?\.(cc|h|mm)" : [
|
||||
"+base/message_loop/message_loop.h",
|
||||
"+base/test/test_mock_time_task_runner.h",
|
||||
# Test harness may use cc directly instead of going through WebViewImpl etc.
|
||||
|
@ -310,6 +310,8 @@ blink_core_sources("editing") {
|
||||
"state_machines/state_machine_util.h",
|
||||
"state_machines/text_segmentation_machine_state.cc",
|
||||
"state_machines/text_segmentation_machine_state.h",
|
||||
"substring_util.h",
|
||||
"substring_util.mm",
|
||||
"suggestion/text_suggestion_backend_impl.cc",
|
||||
"suggestion/text_suggestion_backend_impl.h",
|
||||
"suggestion/text_suggestion_controller.cc",
|
||||
@ -334,7 +336,6 @@ blink_core_sources("editing") {
|
||||
"visible_units_paragraph.cc",
|
||||
"visible_units_sentence.cc",
|
||||
"visible_units_word.cc",
|
||||
"web_substring_util.mm",
|
||||
"writing_direction.h",
|
||||
]
|
||||
|
||||
@ -429,6 +430,7 @@ jumbo_source_set("unit_tests") {
|
||||
"state_machines/state_machine_test_util.cc",
|
||||
"state_machines/state_machine_test_util.h",
|
||||
"state_machines/state_machine_util_test.cc",
|
||||
"substring_util_test.mm",
|
||||
"suggestion/text_suggestion_controller_test.cc",
|
||||
"surrounding_text_test.cc",
|
||||
"testing/editing_test_base.cc",
|
||||
|
@ -28,10 +28,12 @@
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef THIRD_PARTY_BLINK_PUBLIC_WEB_MAC_WEB_SUBSTRING_UTIL_H_
|
||||
#define THIRD_PARTY_BLINK_PUBLIC_WEB_MAC_WEB_SUBSTRING_UTIL_H_
|
||||
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_SUBSTRING_UTIL_H_
|
||||
#define THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_SUBSTRING_UTIL_H_
|
||||
|
||||
#include "third_party/blink/public/platform/web_common.h"
|
||||
#include <cstddef>
|
||||
|
||||
#include "third_party/blink/renderer/core/core_export.h"
|
||||
|
||||
#if __OBJC__
|
||||
@class NSAttributedString;
|
||||
@ -44,32 +46,31 @@ class Point;
|
||||
} // namespace gfx
|
||||
|
||||
namespace blink {
|
||||
class WebFrameWidgetBase;
|
||||
class LocalFrame;
|
||||
|
||||
class WebFrameWidget;
|
||||
class WebLocalFrame;
|
||||
|
||||
class WebSubstringUtil {
|
||||
class SubstringUtil {
|
||||
public:
|
||||
// Returns an autoreleased NSAttributedString that is the word under
|
||||
// the given point inside the given WebFrameWidget or nil on error.
|
||||
// the given point inside the given WebFrameWidgetBase or nil on error.
|
||||
// Upon return, |baselinePoint| is set to the left baseline point in
|
||||
// AppKit coordinates.
|
||||
BLINK_EXPORT static NSAttributedString* AttributedWordAtPoint(
|
||||
WebFrameWidget*,
|
||||
CORE_EXPORT static NSAttributedString* AttributedWordAtPoint(
|
||||
WebFrameWidgetBase*,
|
||||
gfx::Point,
|
||||
gfx::Point& baseline_point);
|
||||
|
||||
// Returns an autoreleased NSAttributedString that is a substring of the
|
||||
// Frame at the given range, or nil on error.
|
||||
BLINK_EXPORT static NSAttributedString*
|
||||
AttributedSubstringInRange(WebLocalFrame*, size_t location, size_t length);
|
||||
CORE_EXPORT static NSAttributedString*
|
||||
AttributedSubstringInRange(LocalFrame*, size_t location, size_t length);
|
||||
|
||||
// Returns an autoreleased NSAttributedString that is a substring of the
|
||||
// Frame at the given range, or nil on error.
|
||||
// It also gets the baseline point for the given range for showing
|
||||
// dictionary lookup bubble.
|
||||
BLINK_EXPORT static NSAttributedString* AttributedSubstringInRange(
|
||||
WebLocalFrame*,
|
||||
CORE_EXPORT static NSAttributedString* AttributedSubstringInRange(
|
||||
LocalFrame*,
|
||||
size_t location,
|
||||
size_t length,
|
||||
gfx::Point* baseline_point);
|
||||
@ -77,4 +78,4 @@ class WebSubstringUtil {
|
||||
|
||||
} // namespace blink
|
||||
|
||||
#endif
|
||||
#endif // THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_SUBSTRING_UTIL_H_
|
@ -29,15 +29,11 @@
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "third_party/blink/public/web/mac/web_substring_util.h"
|
||||
#include "third_party/blink/renderer/core/editing/substring_util.h"
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
#include "base/mac/foundation_util.h"
|
||||
#include "third_party/blink/public/platform/web_rect.h"
|
||||
#include "third_party/blink/public/web/web_frame_widget.h"
|
||||
#include "third_party/blink/public/web/web_hit_test_result.h"
|
||||
#include "third_party/blink/public/web/web_local_frame.h"
|
||||
#include "third_party/blink/renderer/core/dom/document.h"
|
||||
#include "third_party/blink/renderer/core/dom/element.h"
|
||||
#include "third_party/blink/renderer/core/dom/node.h"
|
||||
@ -53,7 +49,6 @@
|
||||
#include "third_party/blink/renderer/core/frame/local_frame_view.h"
|
||||
#include "third_party/blink/renderer/core/frame/visual_viewport.h"
|
||||
#include "third_party/blink/renderer/core/frame/web_frame_widget_base.h"
|
||||
#include "third_party/blink/renderer/core/frame/web_local_frame_impl.h"
|
||||
#include "third_party/blink/renderer/core/html/html_element.h"
|
||||
#include "third_party/blink/renderer/core/layout/hit_test_result.h"
|
||||
#include "third_party/blink/renderer/core/layout/layout_object.h"
|
||||
@ -147,7 +142,8 @@ gfx::Point GetBaselinePoint(LocalFrameView* frame_view,
|
||||
|
||||
// Adjust for the font's descender. AppKit wants the baseline point.
|
||||
if ([string length]) {
|
||||
NSDictionary* attributes = [string attributesAtIndex:0 effectiveRange:NULL];
|
||||
NSDictionary* attributes = [string attributesAtIndex:0
|
||||
effectiveRange:nullptr];
|
||||
if (NSFont* font = [attributes objectForKey:NSFontAttributeName])
|
||||
string_point.Move(0, ceil([font descender]));
|
||||
}
|
||||
@ -156,12 +152,12 @@ gfx::Point GetBaselinePoint(LocalFrameView* frame_view,
|
||||
|
||||
} // namespace
|
||||
|
||||
NSAttributedString* WebSubstringUtil::AttributedWordAtPoint(
|
||||
WebFrameWidget* frame_widget,
|
||||
NSAttributedString* SubstringUtil::AttributedWordAtPoint(
|
||||
WebFrameWidgetBase* frame_widget,
|
||||
gfx::Point point,
|
||||
gfx::Point& baseline_point) {
|
||||
HitTestResult result = static_cast<WebFrameWidgetBase*>(frame_widget)
|
||||
->CoreHitTestResultAt(FloatPoint(IntPoint(point)));
|
||||
HitTestResult result =
|
||||
frame_widget->CoreHitTestResultAt(FloatPoint(IntPoint(point)));
|
||||
|
||||
if (!result.InnerNode())
|
||||
return nil;
|
||||
@ -184,20 +180,18 @@ NSAttributedString* WebSubstringUtil::AttributedWordAtPoint(
|
||||
return string;
|
||||
}
|
||||
|
||||
NSAttributedString* WebSubstringUtil::AttributedSubstringInRange(
|
||||
WebLocalFrame* web_frame,
|
||||
size_t location,
|
||||
size_t length) {
|
||||
return WebSubstringUtil::AttributedSubstringInRange(web_frame, location,
|
||||
length, nil);
|
||||
NSAttributedString* SubstringUtil::AttributedSubstringInRange(LocalFrame* frame,
|
||||
size_t location,
|
||||
size_t length) {
|
||||
return SubstringUtil::AttributedSubstringInRange(frame, location, length,
|
||||
nil);
|
||||
}
|
||||
|
||||
NSAttributedString* WebSubstringUtil::AttributedSubstringInRange(
|
||||
WebLocalFrame* web_frame,
|
||||
NSAttributedString* SubstringUtil::AttributedSubstringInRange(
|
||||
LocalFrame* frame,
|
||||
size_t location,
|
||||
size_t length,
|
||||
gfx::Point* baseline_point) {
|
||||
LocalFrame* frame = To<WebLocalFrameImpl>(web_frame)->GetFrame();
|
||||
if (frame->View()->NeedsLayout())
|
||||
frame->View()->UpdateLayout();
|
||||
|
161
third_party/blink/renderer/core/editing/substring_util_test.mm
vendored
Normal file
161
third_party/blink/renderer/core/editing/substring_util_test.mm
vendored
Normal file
@ -0,0 +1,161 @@
|
||||
// Copyright 2020 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 "third_party/blink/renderer/core/editing/substring_util.h"
|
||||
|
||||
#include "testing/gtest/include/gtest/gtest.h"
|
||||
#include "third_party/blink/public/web/web_script_source.h"
|
||||
#include "third_party/blink/public/web/web_view.h"
|
||||
#include "third_party/blink/renderer/core/editing/testing/editing_test_base.h"
|
||||
#include "third_party/blink/renderer/core/frame/frame_test_helpers.h"
|
||||
#include "third_party/blink/renderer/core/frame/local_frame.h"
|
||||
#include "third_party/blink/renderer/core/frame/web_frame_widget_base.h"
|
||||
#include "third_party/blink/renderer/core/frame/web_local_frame_impl.h"
|
||||
#include "third_party/blink/renderer/platform/testing/unit_test_helpers.h"
|
||||
#include "third_party/blink/renderer/platform/testing/url_test_helpers.h"
|
||||
|
||||
namespace blink {
|
||||
|
||||
class SubStringUtilTest : public testing::Test {
|
||||
public:
|
||||
SubStringUtilTest() : base_url_("http://www.test.com/") {}
|
||||
|
||||
void TearDown() override {
|
||||
url_test_helpers::UnregisterAllURLsAndClearMemoryCache();
|
||||
}
|
||||
|
||||
protected:
|
||||
std::string RegisterMockedHttpURLLoad(const std::string& file_name) {
|
||||
// TODO(crbug.com/751425): We should use the mock functionality
|
||||
// via |web_view_helper_|.
|
||||
return url_test_helpers::RegisterMockedURLLoadFromBase(
|
||||
WebString::FromUTF8(base_url_), test::CoreTestDataPath(),
|
||||
WebString::FromUTF8(file_name))
|
||||
.GetString()
|
||||
.Utf8();
|
||||
}
|
||||
|
||||
std::string base_url_;
|
||||
frame_test_helpers::WebViewHelper web_view_helper_;
|
||||
};
|
||||
|
||||
TEST_F(SubStringUtilTest, SubstringUtil) {
|
||||
RegisterMockedHttpURLLoad("content_editable_populated.html");
|
||||
WebView* web_view = static_cast<WebView*>(web_view_helper_.InitializeAndLoad(
|
||||
base_url_ + "content_editable_populated.html"));
|
||||
|
||||
web_view->GetSettings()->SetDefaultFontSize(12);
|
||||
web_view->Resize(WebSize(400, 400));
|
||||
WebLocalFrameImpl* frame =
|
||||
static_cast<WebLocalFrameImpl*>(web_view->MainFrame());
|
||||
|
||||
gfx::Point baseline_point;
|
||||
NSAttributedString* result = SubstringUtil::AttributedSubstringInRange(
|
||||
frame->GetFrame(), 10, 3, &baseline_point);
|
||||
ASSERT_TRUE(!!result);
|
||||
|
||||
gfx::Point point(baseline_point);
|
||||
result = SubstringUtil::AttributedWordAtPoint(frame->FrameWidgetImpl(), point,
|
||||
baseline_point);
|
||||
ASSERT_TRUE(!!result);
|
||||
|
||||
web_view->SetZoomLevel(3);
|
||||
|
||||
result = SubstringUtil::AttributedSubstringInRange(frame->GetFrame(), 5, 5,
|
||||
&baseline_point);
|
||||
ASSERT_TRUE(!!result);
|
||||
|
||||
point = baseline_point;
|
||||
result = SubstringUtil::AttributedWordAtPoint(frame->FrameWidgetImpl(), point,
|
||||
baseline_point);
|
||||
ASSERT_TRUE(!!result);
|
||||
}
|
||||
|
||||
TEST_F(SubStringUtilTest, SubstringUtilBaselinePoint) {
|
||||
RegisterMockedHttpURLLoad("content_editable_multiline.html");
|
||||
WebView* web_view = static_cast<WebView*>(web_view_helper_.InitializeAndLoad(
|
||||
base_url_ + "content_editable_multiline.html"));
|
||||
web_view->GetSettings()->SetDefaultFontSize(12);
|
||||
web_view->Resize(WebSize(400, 400));
|
||||
WebLocalFrameImpl* frame =
|
||||
static_cast<WebLocalFrameImpl*>(web_view->MainFrame());
|
||||
|
||||
gfx::Point old_point;
|
||||
SubstringUtil::AttributedSubstringInRange(frame->GetFrame(), 3, 1,
|
||||
&old_point);
|
||||
|
||||
gfx::Point new_point;
|
||||
SubstringUtil::AttributedSubstringInRange(frame->GetFrame(), 3, 20,
|
||||
&new_point);
|
||||
|
||||
EXPECT_EQ(old_point.x(), new_point.x());
|
||||
EXPECT_EQ(old_point.y(), new_point.y());
|
||||
}
|
||||
|
||||
TEST_F(SubStringUtilTest, SubstringUtilPinchZoom) {
|
||||
RegisterMockedHttpURLLoad("content_editable_populated.html");
|
||||
WebView* web_view = static_cast<WebView*>(web_view_helper_.InitializeAndLoad(
|
||||
base_url_ + "content_editable_populated.html"));
|
||||
web_view->GetSettings()->SetDefaultFontSize(12);
|
||||
web_view->Resize(WebSize(400, 400));
|
||||
WebLocalFrameImpl* frame =
|
||||
static_cast<WebLocalFrameImpl*>(web_view->MainFrame());
|
||||
NSAttributedString* result = nil;
|
||||
|
||||
gfx::Point baseline_point;
|
||||
result = SubstringUtil::AttributedSubstringInRange(frame->GetFrame(), 10, 3,
|
||||
&baseline_point);
|
||||
ASSERT_TRUE(!!result);
|
||||
|
||||
web_view->SetPageScaleFactor(3);
|
||||
|
||||
gfx::Point point_after_zoom;
|
||||
result = SubstringUtil::AttributedSubstringInRange(frame->GetFrame(), 10, 3,
|
||||
&point_after_zoom);
|
||||
ASSERT_TRUE(!!result);
|
||||
|
||||
// We won't have moved by a full factor of 3 because of the translations, but
|
||||
// we should move by a factor of >2.
|
||||
EXPECT_LT(2 * baseline_point.x(), point_after_zoom.x());
|
||||
EXPECT_LT(2 * baseline_point.y(), point_after_zoom.y());
|
||||
}
|
||||
|
||||
TEST_F(SubStringUtilTest, SubstringUtilIframe) {
|
||||
RegisterMockedHttpURLLoad("single_iframe.html");
|
||||
RegisterMockedHttpURLLoad("visible_iframe.html");
|
||||
WebView* web_view = static_cast<WebView*>(
|
||||
web_view_helper_.InitializeAndLoad(base_url_ + "single_iframe.html"));
|
||||
web_view->GetSettings()->SetDefaultFontSize(12);
|
||||
web_view->GetSettings()->SetJavaScriptEnabled(true);
|
||||
web_view->Resize(WebSize(400, 400));
|
||||
WebLocalFrameImpl* main_frame =
|
||||
static_cast<WebLocalFrameImpl*>(web_view->MainFrame());
|
||||
WebLocalFrameImpl* child_frame = WebLocalFrameImpl::FromFrame(
|
||||
To<LocalFrame>(main_frame->GetFrame()->Tree().FirstChild()));
|
||||
|
||||
gfx::Point baseline_point;
|
||||
NSAttributedString* result = SubstringUtil::AttributedSubstringInRange(
|
||||
child_frame->GetFrame(), 11, 7, &baseline_point);
|
||||
ASSERT_NE(result, nullptr);
|
||||
|
||||
gfx::Point point(baseline_point);
|
||||
result = SubstringUtil::AttributedWordAtPoint(main_frame->FrameWidgetImpl(),
|
||||
point, baseline_point);
|
||||
ASSERT_NE(result, nullptr);
|
||||
|
||||
int y_before_change = baseline_point.y();
|
||||
|
||||
// Now move the <iframe> down by 100px.
|
||||
main_frame->ExecuteScript(WebScriptSource(
|
||||
"document.querySelector('iframe').style.marginTop = '100px';"));
|
||||
|
||||
point = gfx::Point(point.x(), point.y() + 100);
|
||||
result = SubstringUtil::AttributedWordAtPoint(main_frame->FrameWidgetImpl(),
|
||||
point, baseline_point);
|
||||
ASSERT_NE(result, nullptr);
|
||||
|
||||
EXPECT_EQ(y_before_change, baseline_point.y() - 100);
|
||||
}
|
||||
|
||||
} // namespace blink
|
@ -154,10 +154,6 @@
|
||||
#include "ui/events/keycodes/dom/dom_key.h"
|
||||
#include "v8/include/v8.h"
|
||||
|
||||
#if defined(OS_MACOSX)
|
||||
#include "third_party/blink/public/web/mac/web_substring_util.h"
|
||||
#endif
|
||||
|
||||
#if BUILDFLAG(ENABLE_UNHANDLED_TAP)
|
||||
#include "third_party/blink/public/mojom/unhandled_tap_notifier/unhandled_tap_notifier.mojom-blink.h"
|
||||
#include "third_party/blink/renderer/platform/testing/testing_platform_support.h"
|
||||
@ -4833,120 +4829,6 @@ TEST_F(ShowUnhandledTapTest, ShowUnhandledTapUIIfNeededWithTextSizes) {
|
||||
|
||||
#endif // BUILDFLAG(ENABLE_UNHANDLED_TAP)
|
||||
|
||||
#if defined(OS_MACOSX)
|
||||
TEST_F(WebViewTest, WebSubstringUtil) {
|
||||
RegisterMockedHttpURLLoad("content_editable_populated.html");
|
||||
WebViewImpl* web_view = web_view_helper_.InitializeAndLoad(
|
||||
base_url_ + "content_editable_populated.html");
|
||||
web_view->GetSettings()->SetDefaultFontSize(12);
|
||||
web_view->MainFrameWidget()->Resize(WebSize(400, 400));
|
||||
WebLocalFrameImpl* frame = web_view->MainFrameImpl();
|
||||
|
||||
gfx::Point baseline_point;
|
||||
NSAttributedString* result = WebSubstringUtil::AttributedSubstringInRange(
|
||||
frame, 10, 3, &baseline_point);
|
||||
ASSERT_TRUE(!!result);
|
||||
|
||||
gfx::Point point(baseline_point);
|
||||
result = WebSubstringUtil::AttributedWordAtPoint(frame->FrameWidget(), point,
|
||||
baseline_point);
|
||||
ASSERT_TRUE(!!result);
|
||||
|
||||
web_view->SetZoomLevel(3);
|
||||
|
||||
result = WebSubstringUtil::AttributedSubstringInRange(frame, 5, 5,
|
||||
&baseline_point);
|
||||
ASSERT_TRUE(!!result);
|
||||
|
||||
point = baseline_point;
|
||||
result = WebSubstringUtil::AttributedWordAtPoint(frame->FrameWidget(), point,
|
||||
baseline_point);
|
||||
ASSERT_TRUE(!!result);
|
||||
}
|
||||
|
||||
TEST_F(WebViewTest, WebSubstringUtilBaselinePoint) {
|
||||
RegisterMockedHttpURLLoad("content_editable_multiline.html");
|
||||
WebViewImpl* web_view = web_view_helper_.InitializeAndLoad(
|
||||
base_url_ + "content_editable_multiline.html");
|
||||
web_view->GetSettings()->SetDefaultFontSize(12);
|
||||
web_view->MainFrameWidget()->Resize(WebSize(400, 400));
|
||||
WebLocalFrameImpl* frame = web_view->MainFrameImpl();
|
||||
|
||||
gfx::Point old_point;
|
||||
WebSubstringUtil::AttributedSubstringInRange(frame, 3, 1, &old_point);
|
||||
|
||||
gfx::Point new_point;
|
||||
WebSubstringUtil::AttributedSubstringInRange(frame, 3, 20, &new_point);
|
||||
|
||||
EXPECT_EQ(old_point.x(), new_point.x());
|
||||
EXPECT_EQ(old_point.y(), new_point.y());
|
||||
}
|
||||
|
||||
TEST_F(WebViewTest, WebSubstringUtilPinchZoom) {
|
||||
RegisterMockedHttpURLLoad("content_editable_populated.html");
|
||||
WebViewImpl* web_view = web_view_helper_.InitializeAndLoad(
|
||||
base_url_ + "content_editable_populated.html");
|
||||
web_view->GetSettings()->SetDefaultFontSize(12);
|
||||
web_view->MainFrameWidget()->Resize(WebSize(400, 400));
|
||||
WebLocalFrameImpl* frame = web_view->MainFrameImpl();
|
||||
NSAttributedString* result = nil;
|
||||
|
||||
gfx::Point baseline_point;
|
||||
result = WebSubstringUtil::AttributedSubstringInRange(frame, 10, 3,
|
||||
&baseline_point);
|
||||
ASSERT_TRUE(!!result);
|
||||
|
||||
web_view->SetPageScaleFactor(3);
|
||||
|
||||
gfx::Point point_after_zoom;
|
||||
result = WebSubstringUtil::AttributedSubstringInRange(frame, 10, 3,
|
||||
&point_after_zoom);
|
||||
ASSERT_TRUE(!!result);
|
||||
|
||||
// We won't have moved by a full factor of 3 because of the translations, but
|
||||
// we should move by a factor of >2.
|
||||
EXPECT_LT(2 * baseline_point.x(), point_after_zoom.x());
|
||||
EXPECT_LT(2 * baseline_point.y(), point_after_zoom.y());
|
||||
}
|
||||
|
||||
TEST_F(WebViewTest, WebSubstringUtilIframe) {
|
||||
RegisterMockedHttpURLLoad("single_iframe.html");
|
||||
RegisterMockedHttpURLLoad("visible_iframe.html");
|
||||
WebViewImpl* web_view =
|
||||
web_view_helper_.InitializeAndLoad(base_url_ + "single_iframe.html");
|
||||
web_view->GetSettings()->SetDefaultFontSize(12);
|
||||
web_view->GetSettings()->SetJavaScriptEnabled(true);
|
||||
web_view->MainFrameWidget()->Resize(WebSize(400, 400));
|
||||
WebLocalFrameImpl* main_frame = web_view->MainFrameImpl();
|
||||
WebLocalFrameImpl* child_frame = WebLocalFrameImpl::FromFrame(
|
||||
To<LocalFrame>(main_frame->GetFrame()->Tree().FirstChild()));
|
||||
|
||||
gfx::Point baseline_point;
|
||||
NSAttributedString* result = WebSubstringUtil::AttributedSubstringInRange(
|
||||
child_frame, 11, 7, &baseline_point);
|
||||
ASSERT_NE(result, nullptr);
|
||||
|
||||
gfx::Point point(baseline_point);
|
||||
result = WebSubstringUtil::AttributedWordAtPoint(main_frame->FrameWidget(),
|
||||
point, baseline_point);
|
||||
ASSERT_NE(result, nullptr);
|
||||
|
||||
int y_before_change = baseline_point.y();
|
||||
|
||||
// Now move the <iframe> down by 100px.
|
||||
main_frame->ExecuteScript(WebScriptSource(
|
||||
"document.querySelector('iframe').style.marginTop = '100px';"));
|
||||
|
||||
point = gfx::Point(point.x(), point.y() + 100);
|
||||
result = WebSubstringUtil::AttributedWordAtPoint(main_frame->FrameWidget(),
|
||||
point, baseline_point);
|
||||
ASSERT_NE(result, nullptr);
|
||||
|
||||
EXPECT_EQ(y_before_change, baseline_point.y() - 100);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
TEST_F(WebViewTest, ShouldSuppressKeyboardForPasswordField) {
|
||||
RegisterMockedHttpURLLoad("input_field_password.html");
|
||||
// Pretend client has fill data for all fields it's queried.
|
||||
|
@ -180,6 +180,9 @@
|
||||
|
||||
#if defined(OS_MACOSX)
|
||||
#include "third_party/blink/renderer/core/editing/ephemeral_range.h"
|
||||
#include "third_party/blink/renderer/core/editing/substring_util.h"
|
||||
#include "third_party/blink/renderer/platform/fonts/mac/attributed_string_type_converter.h"
|
||||
#include "ui/base/mojom/attributed_string.mojom-blink.h"
|
||||
#include "ui/gfx/range/range.h"
|
||||
#endif
|
||||
|
||||
@ -2328,6 +2331,18 @@ void LocalFrame::GetFirstRectForRange(const gfx::Range& range) {
|
||||
|
||||
GetTextInputHost().GotFirstRectForRange(rect);
|
||||
}
|
||||
|
||||
void LocalFrame::GetStringForRange(const gfx::Range& range,
|
||||
GetStringForRangeCallback callback) {
|
||||
gfx::Point baseline_point;
|
||||
ui::mojom::blink::AttributedStringPtr attributed_string = nullptr;
|
||||
NSAttributedString* string = SubstringUtil::AttributedSubstringInRange(
|
||||
this, range.start(), range.length(), &baseline_point);
|
||||
if (string)
|
||||
attributed_string = ui::mojom::blink::AttributedString::From(string);
|
||||
|
||||
std::move(callback).Run(std::move(attributed_string), baseline_point);
|
||||
}
|
||||
#endif
|
||||
|
||||
void LocalFrame::InstallCoopAccessMonitor(
|
||||
|
@ -609,6 +609,8 @@ class CORE_EXPORT LocalFrame final
|
||||
#if defined(OS_MACOSX)
|
||||
void GetCharacterIndexAtPoint(const gfx::Point& point) final;
|
||||
void GetFirstRectForRange(const gfx::Range& range) final;
|
||||
void GetStringForRange(const gfx::Range& range,
|
||||
GetStringForRangeCallback callback) final;
|
||||
#endif
|
||||
void InstallCoopAccessMonitor(
|
||||
const base::UnguessableToken& accessed_window,
|
||||
|
@ -55,7 +55,7 @@
|
||||
#include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h"
|
||||
|
||||
#if defined(OS_MACOSX)
|
||||
#include "third_party/blink/public/web/mac/web_substring_util.h"
|
||||
#include "third_party/blink/renderer/core/editing/substring_util.h"
|
||||
#include "third_party/blink/renderer/platform/fonts/mac/attributed_string_type_converter.h"
|
||||
#include "ui/base/mojom/attributed_string.mojom-blink.h"
|
||||
#include "ui/gfx/geometry/point.h"
|
||||
@ -309,7 +309,7 @@ void WebFrameWidgetBase::GetStringAtPoint(const gfx::Point& point_in_local_root,
|
||||
GetStringAtPointCallback callback) {
|
||||
gfx::Point baseline_point;
|
||||
ui::mojom::blink::AttributedStringPtr attributed_string = nullptr;
|
||||
NSAttributedString* string = blink::WebSubstringUtil::AttributedWordAtPoint(
|
||||
NSAttributedString* string = SubstringUtil::AttributedWordAtPoint(
|
||||
this, point_in_local_root, baseline_point);
|
||||
if (string)
|
||||
attributed_string = ui::mojom::blink::AttributedString::From(string);
|
||||
|
Reference in New Issue
Block a user