0

[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:
Julie Jeongeun Kim
2020-07-07 10:13:15 +00:00
committed by Commit Bot
parent 310dbdf821
commit a4bc40df56
41 changed files with 368 additions and 876 deletions

@ -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, &params);
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;

@ -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",

@ -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);

@ -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();

@ -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);