diff --git a/browser/app/moz.build b/browser/app/moz.build
index 07f01b911f0323de87836a6b49be0e1397614e0d..ba8e780dacd5934a110bf22adba8c104e6ea5acc 100644
--- a/browser/app/moz.build
+++ b/browser/app/moz.build
@@ -117,6 +117,7 @@ if CONFIG["MOZ_SANDBOX"] and CONFIG["OS_ARCH"] == "WINNT":
     DELAYLOAD_DLLS += [
         "winmm.dll",
         "user32.dll",
+        "usp10.dll",
     ]
 
 # Control the default heap size.
diff --git a/security/sandbox/chromium-shim/patches/with_update/broker_complex_line_breaks.patch b/security/sandbox/chromium-shim/patches/with_update/broker_complex_line_breaks.patch
new file mode 100644
index 0000000000000000000000000000000000000000..4d350fa8bca0b7310e7e4472cb2751c7c37b71e0
--- /dev/null
+++ b/security/sandbox/chromium-shim/patches/with_update/broker_complex_line_breaks.patch
@@ -0,0 +1,502 @@
+# HG changeset patch
+# User Bob Owen <bobowencode@gmail.com>
+# Date 1632737723 -3600
+#      Mon Sep 27 11:15:23 2021 +0100
+# Node ID 096696bc1648dbacdfab881c4ed8fe770ebe58b1
+# Parent  254b1fc8768f67d208af199135276abae9aabc0c
+Bug 1713973 p2: Add Uniscribe Line Breaking via chromium-sandbox IPC. r=toshi!,r=jfkthame!
+
+This adds a new cross call using the chromium shared memory IPC to proxy use of
+the Uniscribe line breaker, because it cannot be used in the content process
+with win32k lockdown enabled.
+
+If the text being processed is too long to fit into the IPC params then it is
+processed in chunks.
+
+This change implements an INPTR_TYPE in the sandbox, which appears to have
+been removed at some point.
+It also fixes a bug in OpcodeFactory::MakeOpAction, so that a null param is
+passed and we can use an empty parameter set.
+
+New files are in chromium-shim as these are most likely to require changes and
+this means we will not have to update the main chromium patch.
+
+diff --git a/security/sandbox/chromium/sandbox/win/src/crosscall_client.h b/security/sandbox/chromium/sandbox/win/src/crosscall_client.h
+--- a/security/sandbox/chromium/sandbox/win/src/crosscall_client.h
++++ b/security/sandbox/chromium/sandbox/win/src/crosscall_client.h
+@@ -39,20 +39,16 @@
+ //             interpretation of the answer is private to client and server.
+ //
+ // The return value is ALL_OK if the IPC was delivered to the server, other
+ // return codes indicate that the IPC transport failed to deliver it.
+ namespace sandbox {
+ 
+ enum class IpcTag;
+ 
+-// this is the assumed channel size. This can be overridden in a given
+-// IPC implementation.
+-const uint32_t kIPCChannelSize = 1024;
+-
+ // The copy helper uses templates to deduce the appropriate copy function to
+ // copy the input parameters in the buffer that is going to be send across the
+ // IPC. These template facility can be made more sophisticated as need arises.
+ 
+ // The default copy helper. It catches the general case where no other
+ // specialized template matches better. We set the type to UINT32_TYPE, so this
+ // only works with objects whose size is 32 bits.
+ template <typename T>
+@@ -207,16 +203,42 @@ class CopyHelper<const wchar_t[n]> : pub
+ // parameters.
+ class InOutCountedBuffer : public CountedBuffer {
+  public:
+   InOutCountedBuffer(void* buffer, uint32_t size)
+       : CountedBuffer(buffer, size) {}
+ };
+ 
+ // This copy helper template specialization catches the cases where the
++// parameter is a an input buffer.
++template <>
++class CopyHelper<CountedBuffer> {
++ public:
++  CopyHelper(const CountedBuffer t) : t_(t) {}
++
++  // Returns the pointer to the start of the string.
++  const void* GetStart() const { return t_.Buffer(); }
++
++  // Update not required so just return true;
++  bool Update(void* buffer) { return true; }
++
++  // Returns the size of the string in bytes. We define a nullptr string to
++  // be of zero length.
++  uint32_t GetSize() const { return t_.Size(); }
++
++  // Returns true if the current type is used as an In or InOut parameter.
++  bool IsInOut() { return false; }
++
++  ArgType GetType() { return INPTR_TYPE; }
++
++ private:
++  const CountedBuffer t_;
++};
++
++// This copy helper template specialization catches the cases where the
+ // parameter is a an input/output buffer.
+ template <>
+ class CopyHelper<InOutCountedBuffer> {
+  public:
+   CopyHelper(const InOutCountedBuffer t) : t_(t) {}
+ 
+   // Returns the pointer to the start of the string.
+   const void* GetStart() const { return t_.Buffer(); }
+diff --git a/security/sandbox/chromium/sandbox/win/src/crosscall_params.h b/security/sandbox/chromium/sandbox/win/src/crosscall_params.h
+--- a/security/sandbox/chromium/sandbox/win/src/crosscall_params.h
++++ b/security/sandbox/chromium/sandbox/win/src/crosscall_params.h
+@@ -41,16 +41,20 @@
+ // them are not supported.
+ //
+ // Another limitation of CrossCall is that the return value and output
+ // parameters can only be uint32_t integers. Returning complex structures or
+ // strings is not supported.
+ 
+ namespace sandbox {
+ 
++// this is the assumed channel size. This can be overridden in a given
++// IPC implementation.
++const uint32_t kIPCChannelSize = 1024;
++
+ // This is the list of all imported symbols from ntdll.dll.
+ SANDBOX_INTERCEPT NtExports g_nt;
+ 
+ namespace {
+ 
+ // Increases |value| until there is no need for padding given an int64_t
+ // alignment. Returns the increased value.
+ inline uint32_t Align(uint32_t value) {
+@@ -216,16 +220,21 @@ class ActualCallParams : public CrossCal
+   // Testing-only constructor. Allows setting the |number_params| to a
+   // wrong value.
+   ActualCallParams(IpcTag tag, uint32_t number_params)
+       : CrossCallParams(tag, number_params) {
+     param_info_[0].offset_ =
+         static_cast<uint32_t>(parameters_ - reinterpret_cast<char*>(this));
+   }
+ 
++  static constexpr size_t MaxParamsSize() {
++    return sizeof(
++        ActualCallParams<NUMBER_PARAMS, kIPCChannelSize>::parameters_);
++  }
++
+   // Testing-only method. Allows setting the apparent size to a wrong value.
+   // returns the previous size.
+   uint32_t OverrideSize(uint32_t new_size) {
+     uint32_t previous_size = param_info_[NUMBER_PARAMS].offset_;
+     param_info_[NUMBER_PARAMS].offset_ = new_size;
+     return previous_size;
+   }
+ 
+diff --git a/security/sandbox/chromium/sandbox/win/src/crosscall_server.cc b/security/sandbox/chromium/sandbox/win/src/crosscall_server.cc
+--- a/security/sandbox/chromium/sandbox/win/src/crosscall_server.cc
++++ b/security/sandbox/chromium/sandbox/win/src/crosscall_server.cc
+@@ -301,17 +301,17 @@ bool CrossCallParamsEx::GetParameterStr(
+ 
+ bool CrossCallParamsEx::GetParameterPtr(uint32_t index,
+                                         uint32_t expected_size,
+                                         void** pointer) {
+   uint32_t size = 0;
+   ArgType type;
+   void* start = GetRawParameter(index, &size, &type);
+ 
+-  if ((size != expected_size) || (INOUTPTR_TYPE != type))
++  if ((size != expected_size) || (INOUTPTR_TYPE != type && INPTR_TYPE != type))
+     return false;
+ 
+   if (!start)
+     return false;
+ 
+   *pointer = start;
+   return true;
+ }
+diff --git a/security/sandbox/chromium/sandbox/win/src/ipc_args.cc b/security/sandbox/chromium/sandbox/win/src/ipc_args.cc
+--- a/security/sandbox/chromium/sandbox/win/src/ipc_args.cc
++++ b/security/sandbox/chromium/sandbox/win/src/ipc_args.cc
+@@ -15,16 +15,17 @@ namespace sandbox {
+ void ReleaseArgs(const IPCParams* ipc_params, void* args[kMaxIpcParams]) {
+   for (size_t i = 0; i < kMaxIpcParams; i++) {
+     switch (ipc_params->args[i]) {
+       case WCHAR_TYPE: {
+         delete reinterpret_cast<std::wstring*>(args[i]);
+         args[i] = nullptr;
+         break;
+       }
++      case INPTR_TYPE:
+       case INOUTPTR_TYPE: {
+         delete reinterpret_cast<CountedBuffer*>(args[i]);
+         args[i] = nullptr;
+         break;
+       }
+       default:
+         break;
+     }
+@@ -69,16 +70,17 @@ bool GetArgs(CrossCallParamsEx* params,
+           void* data;
+           if (!params->GetParameterVoidPtr(i, &data)) {
+             ReleaseArgs(ipc_params, args);
+             return false;
+           }
+           args[i] = data;
+           break;
+         }
++        case INPTR_TYPE:
+         case INOUTPTR_TYPE: {
+           if (!args[i]) {
+             ReleaseArgs(ipc_params, args);
+             return false;
+           }
+           CountedBuffer* buffer = new CountedBuffer(args[i], size);
+           args[i] = buffer;
+           break;
+diff --git a/security/sandbox/chromium/sandbox/win/src/ipc_tags.h b/security/sandbox/chromium/sandbox/win/src/ipc_tags.h
+--- a/security/sandbox/chromium/sandbox/win/src/ipc_tags.h
++++ b/security/sandbox/chromium/sandbox/win/src/ipc_tags.h
+@@ -41,16 +41,17 @@ enum class IpcTag {
+   GDI_GETCERTIFICATESIZE,
+   GDI_DESTROYOPMPROTECTEDOUTPUT,
+   GDI_CONFIGUREOPMPROTECTEDOUTPUT,
+   GDI_GETOPMINFORMATION,
+   GDI_GETOPMRANDOMNUMBER,
+   GDI_GETSUGGESTEDOPMPROTECTEDOUTPUTARRAYSIZE,
+   GDI_SETOPMSIGNINGKEYANDSEQUENCENUMBERS,
+   NTCREATESECTION,
++  GETCOMPLEXLINEBREAKS,
+   LAST
+ };
+ 
+ constexpr size_t kMaxServiceCount = 64;
+ constexpr size_t kMaxIpcTag = static_cast<size_t>(IpcTag::LAST);
+ static_assert(kMaxIpcTag <= kMaxServiceCount, "kMaxServiceCount is too low");
+ 
+ }  // namespace sandbox
+diff --git a/security/sandbox/chromium/sandbox/win/src/policy_engine_opcodes.cc b/security/sandbox/chromium/sandbox/win/src/policy_engine_opcodes.cc
+--- a/security/sandbox/chromium/sandbox/win/src/policy_engine_opcodes.cc
++++ b/security/sandbox/chromium/sandbox/win/src/policy_engine_opcodes.cc
+@@ -78,17 +78,17 @@ EvalResult OpcodeEval<OP_ALWAYS_TRUE>(Po
+ }
+ 
+ //////////////////////////////////////////////////////////////////////////////
+ // Opcode OpAction:
+ // Does not require input parameter.
+ // Argument 0 contains the actual action to return.
+ 
+ PolicyOpcode* OpcodeFactory::MakeOpAction(EvalResult action, uint32_t options) {
+-  PolicyOpcode* opcode = MakeBase(OP_ACTION, options, 0);
++  PolicyOpcode* opcode = MakeBase(OP_ACTION, options, -1);
+   if (!opcode)
+     return nullptr;
+   opcode->SetArgument(0, action);
+   return opcode;
+ }
+ 
+ template <>
+ EvalResult OpcodeEval<OP_ACTION>(PolicyOpcode* opcode,
+diff --git a/security/sandbox/chromium/sandbox/win/src/policy_params.h b/security/sandbox/chromium/sandbox/win/src/policy_params.h
+--- a/security/sandbox/chromium/sandbox/win/src/policy_params.h
++++ b/security/sandbox/chromium/sandbox/win/src/policy_params.h
+@@ -56,11 +56,15 @@ POLPARAMS_BEGIN(OpenKey)
+ POLPARAMS_END(OpenKey)
+ 
+ // Policy parameter for name-based policies.
+ POLPARAMS_BEGIN(HandleTarget)
+   POLPARAM(NAME)
+   POLPARAM(TARGET)
+ POLPARAMS_END(HandleTarget)
+ 
++// Policy parameters where no parameter based checks are done.
++POLPARAMS_BEGIN(EmptyParams)
++POLPARAMS_END(EmptyParams)
++
+ }  // namespace sandbox
+ 
+ #endif  // SANDBOX_SRC_POLICY_PARAMS_H__
+diff --git a/security/sandbox/chromium/sandbox/win/src/sandbox.h b/security/sandbox/chromium/sandbox/win/src/sandbox.h
+--- a/security/sandbox/chromium/sandbox/win/src/sandbox.h
++++ b/security/sandbox/chromium/sandbox/win/src/sandbox.h
+@@ -176,16 +176,19 @@ class TargetServices {
+   //   If the return is ERROR_GENERIC, you can call ::GetLastError() to get
+   //   more information.
+   virtual ResultCode DuplicateHandle(HANDLE source_handle,
+                                      DWORD target_process_id,
+                                      HANDLE* target_handle,
+                                      DWORD desired_access,
+                                      DWORD options) = 0;
+ 
++  virtual ResultCode GetComplexLineBreaks(const WCHAR* text, uint32_t length,
++                                          uint8_t* break_before) = 0;
++
+  protected:
+   ~TargetServices() {}
+ };
+ 
+ class PolicyInfo {
+  public:
+   // Returns a JSON representation of the policy snapshot.
+   // This pointer has the same lifetime as this PolicyInfo object.
+diff --git a/security/sandbox/chromium/sandbox/win/src/sandbox_policy.h b/security/sandbox/chromium/sandbox/win/src/sandbox_policy.h
+--- a/security/sandbox/chromium/sandbox/win/src/sandbox_policy.h
++++ b/security/sandbox/chromium/sandbox/win/src/sandbox_policy.h
+@@ -27,17 +27,18 @@ class TargetPolicy {
+   enum SubSystem {
+     SUBSYS_FILES,            // Creation and opening of files and pipes.
+     SUBSYS_NAMED_PIPES,      // Creation of named pipes.
+     SUBSYS_PROCESS,          // Creation of child processes.
+     SUBSYS_REGISTRY,         // Creation and opening of registry keys.
+     SUBSYS_SYNC,             // Creation of named sync objects.
+     SUBSYS_HANDLES,          // Duplication of handles to other processes.
+     SUBSYS_WIN32K_LOCKDOWN,  // Win32K Lockdown related policy.
+-    SUBSYS_SIGNED_BINARY     // Signed binary policy.
++    SUBSYS_SIGNED_BINARY,    // Signed binary policy.
++    SUBSYS_LINE_BREAK        // Complex line break policy.
+   };
+ 
+   // Allowable semantics when a rule is matched.
+   enum Semantics {
+     FILES_ALLOW_ANY,       // Allows open or create for any kind of access that
+                            // the file system supports.
+     FILES_ALLOW_READONLY,  // Allows open or create with read access only.
+     FILES_ALLOW_QUERY,     // Allows access to query the attributes of a file.
+@@ -60,17 +61,18 @@ class TargetPolicy {
+     REG_ALLOW_READONLY,     // Allows readonly access to a registry key.
+     REG_ALLOW_ANY,          // Allows read and write access to a registry key.
+     FAKE_USER_GDI_INIT,     // Fakes user32 and gdi32 initialization. This can
+                             // be used to allow the DLLs to load and initialize
+                             // even if the process cannot access that subsystem.
+     IMPLEMENT_OPM_APIS,     // Implements FAKE_USER_GDI_INIT and also exposes
+                             // IPC calls to handle Output Protection Manager
+                             // APIs.
+-    SIGNED_ALLOW_LOAD       // Allows loading the module when CIG is enabled.
++    SIGNED_ALLOW_LOAD,      // Allows loading the module when CIG is enabled.
++    LINE_BREAK_ALLOW        // Allow complex line break brokering.
+   };
+ 
+   // Increments the reference count of this object. The reference count must
+   // be incremented if this interface is given to another component.
+   virtual void AddRef() = 0;
+ 
+   // Decrements the reference count of this object. When the reference count
+   // is zero the object is automatically destroyed.
+diff --git a/security/sandbox/chromium/sandbox/win/src/sandbox_policy_base.cc b/security/sandbox/chromium/sandbox/win/src/sandbox_policy_base.cc
+--- a/security/sandbox/chromium/sandbox/win/src/sandbox_policy_base.cc
++++ b/security/sandbox/chromium/sandbox/win/src/sandbox_policy_base.cc
+@@ -15,16 +15,17 @@
+ #include "base/strings/stringprintf.h"
+ #include "base/win/win_util.h"
+ #include "base/win/windows_version.h"
+ #include "sandbox/win/src/acl.h"
+ #include "sandbox/win/src/filesystem_policy.h"
+ #include "sandbox/win/src/handle_policy.h"
+ #include "sandbox/win/src/interception.h"
+ #include "sandbox/win/src/job.h"
++#include "sandbox/win/src/line_break_policy.h"
+ #include "sandbox/win/src/named_pipe_policy.h"
+ #include "sandbox/win/src/policy_broker.h"
+ #include "sandbox/win/src/policy_engine_processor.h"
+ #include "sandbox/win/src/policy_low_level.h"
+ #include "sandbox/win/src/process_mitigations.h"
+ #include "sandbox/win/src/process_mitigations_win32k_policy.h"
+ #include "sandbox/win/src/process_thread_policy.h"
+ #include "sandbox/win/src/registry_policy.h"
+@@ -809,16 +810,23 @@ ResultCode PolicyBase::AddRuleInternal(S
+                "policy rules.";
+         if (!SignedPolicy::GenerateRules(pattern, semantics, policy_maker_)) {
+           NOTREACHED();
+           return SBOX_ERROR_BAD_PARAMS;
+         }
+       }
+       break;
+     }
++    case SUBSYS_LINE_BREAK: {
++      if (!LineBreakPolicy::GenerateRules(pattern, semantics, policy_maker_)) {
++        NOTREACHED();
++        return SBOX_ERROR_BAD_PARAMS;
++      }
++      break;
++    }
+ 
+     default: { return SBOX_ERROR_UNSUPPORTED; }
+   }
+ 
+   return SBOX_ALL_OK;
+ }
+ 
+ }  // namespace sandbox
+diff --git a/security/sandbox/chromium/sandbox/win/src/target_services.cc b/security/sandbox/chromium/sandbox/win/src/target_services.cc
+--- a/security/sandbox/chromium/sandbox/win/src/target_services.cc
++++ b/security/sandbox/chromium/sandbox/win/src/target_services.cc
+@@ -9,16 +9,17 @@
+ #include <process.h>
+ #include <stdint.h>
+ 
+ #include "base/win/windows_version.h"
+ #include "sandbox/win/src/crosscall_client.h"
+ #include "sandbox/win/src/handle_closer_agent.h"
+ #include "sandbox/win/src/handle_interception.h"
+ #include "sandbox/win/src/heap_helper.h"
++#include "sandbox/win/src/line_break_interception.h"
+ #include "sandbox/win/src/ipc_tags.h"
+ #include "sandbox/win/src/process_mitigations.h"
+ #include "sandbox/win/src/restricted_token_utils.h"
+ #include "sandbox/win/src/sandbox.h"
+ #include "sandbox/win/src/sandbox_nt_util.h"
+ #include "sandbox/win/src/sandbox_types.h"
+ #include "sandbox/win/src/sharedmem_ipc_client.h"
+ 
+@@ -240,19 +241,24 @@ void ProcessState::SetRevertedToSelf() {
+   if (process_state_ < ProcessStateInternal::REVERTED_TO_SELF)
+     process_state_ = ProcessStateInternal::REVERTED_TO_SELF;
+ }
+ 
+ void ProcessState::SetCsrssConnected(bool csrss_connected) {
+   csrss_connected_ = csrss_connected;
+ }
+ 
+-
+ ResultCode TargetServicesBase::DuplicateHandle(HANDLE source_handle,
+                                                DWORD target_process_id,
+                                                HANDLE* target_handle,
+                                                DWORD desired_access,
+                                                DWORD options) {
+   return sandbox::DuplicateHandleProxy(source_handle, target_process_id,
+                                        target_handle, desired_access, options);
+ }
+ 
++ResultCode TargetServicesBase::GetComplexLineBreaks(const WCHAR* text,
++                                                    uint32_t length,
++                                                    uint8_t* break_before) {
++  return sandbox::GetComplexLineBreaksProxy(text, length, break_before);
++}
++
+ }  // namespace sandbox
+diff --git a/security/sandbox/chromium/sandbox/win/src/target_services.h b/security/sandbox/chromium/sandbox/win/src/target_services.h
+--- a/security/sandbox/chromium/sandbox/win/src/target_services.h
++++ b/security/sandbox/chromium/sandbox/win/src/target_services.h
+@@ -45,16 +45,18 @@ class TargetServicesBase : public Target
+   ResultCode Init() override;
+   void LowerToken() override;
+   ProcessState* GetState() override;
+   ResultCode DuplicateHandle(HANDLE source_handle,
+                              DWORD target_process_id,
+                              HANDLE* target_handle,
+                              DWORD desired_access,
+                              DWORD options) override;
++  ResultCode GetComplexLineBreaks(const WCHAR* text, uint32_t length,
++                                  uint8_t* break_before) final;
+ 
+   // Factory method.
+   static TargetServicesBase* GetInstance();
+ 
+   // Sends a simple IPC Message that has a well-known answer. Returns true
+   // if the IPC was successful and false otherwise. There are 2 versions of
+   // this test: 1 and 2. The first one send a simple message while the
+   // second one send a message with an in/out param.
+diff --git a/security/sandbox/chromium/sandbox/win/src/top_level_dispatcher.cc b/security/sandbox/chromium/sandbox/win/src/top_level_dispatcher.cc
+--- a/security/sandbox/chromium/sandbox/win/src/top_level_dispatcher.cc
++++ b/security/sandbox/chromium/sandbox/win/src/top_level_dispatcher.cc
+@@ -9,16 +9,17 @@
+ 
+ #include "base/logging.h"
+ #include "sandbox/win/src/crosscall_server.h"
+ #include "sandbox/win/src/filesystem_dispatcher.h"
+ #include "sandbox/win/src/handle_dispatcher.h"
+ #include "sandbox/win/src/interception.h"
+ #include "sandbox/win/src/internal_types.h"
+ #include "sandbox/win/src/ipc_tags.h"
++#include "sandbox/win/src/line_break_dispatcher.h"
+ #include "sandbox/win/src/named_pipe_dispatcher.h"
+ #include "sandbox/win/src/process_mitigations_win32k_dispatcher.h"
+ #include "sandbox/win/src/process_thread_dispatcher.h"
+ #include "sandbox/win/src/registry_dispatcher.h"
+ #include "sandbox/win/src/sandbox_policy_base.h"
+ #include "sandbox/win/src/signed_dispatcher.h"
+ #include "sandbox/win/src/sync_dispatcher.h"
+ 
+@@ -90,16 +91,20 @@ TopLevelDispatcher::TopLevelDispatcher(P
+       IpcTag::GDI_GETSUGGESTEDOPMPROTECTEDOUTPUTARRAYSIZE)] = dispatcher;
+   ipc_targets_[static_cast<size_t>(
+       IpcTag::GDI_SETOPMSIGNINGKEYANDSEQUENCENUMBERS)] = dispatcher;
+   process_mitigations_win32k_dispatcher_.reset(dispatcher);
+ 
+   dispatcher = new SignedDispatcher(policy_);
+   ipc_targets_[static_cast<size_t>(IpcTag::NTCREATESECTION)] = dispatcher;
+   signed_dispatcher_.reset(dispatcher);
++
++  dispatcher = new LineBreakDispatcher(policy_);
++  ipc_targets_[static_cast<size_t>(IpcTag::GETCOMPLEXLINEBREAKS)] = dispatcher;
++  line_break_dispatcher_.reset(dispatcher);
+ }
+ 
+ TopLevelDispatcher::~TopLevelDispatcher() {}
+ 
+ // When an IPC is ready in any of the targets we get called. We manage an array
+ // of IPC dispatchers which are keyed on the IPC tag so we normally delegate
+ // to the appropriate dispatcher unless we can handle the IPC call ourselves.
+ Dispatcher* TopLevelDispatcher::OnMessageReady(IPCParams* ipc,
+diff --git a/security/sandbox/chromium/sandbox/win/src/top_level_dispatcher.h b/security/sandbox/chromium/sandbox/win/src/top_level_dispatcher.h
+--- a/security/sandbox/chromium/sandbox/win/src/top_level_dispatcher.h
++++ b/security/sandbox/chromium/sandbox/win/src/top_level_dispatcher.h
+@@ -38,16 +38,17 @@ class TopLevelDispatcher : public Dispat
+   std::unique_ptr<Dispatcher> filesystem_dispatcher_;
+   std::unique_ptr<Dispatcher> named_pipe_dispatcher_;
+   std::unique_ptr<Dispatcher> thread_process_dispatcher_;
+   std::unique_ptr<Dispatcher> sync_dispatcher_;
+   std::unique_ptr<Dispatcher> registry_dispatcher_;
+   std::unique_ptr<Dispatcher> handle_dispatcher_;
+   std::unique_ptr<Dispatcher> process_mitigations_win32k_dispatcher_;
+   std::unique_ptr<Dispatcher> signed_dispatcher_;
++  std::unique_ptr<Dispatcher> line_break_dispatcher_;
+   Dispatcher* ipc_targets_[kMaxIpcTag];
+ 
+   DISALLOW_COPY_AND_ASSIGN(TopLevelDispatcher);
+ };
+ 
+ }  // namespace sandbox
+ 
+ #endif  // SANDBOX_SRC_TOP_LEVEL_DISPATCHER_H__
diff --git a/security/sandbox/chromium-shim/patches/with_update/patch_order.txt b/security/sandbox/chromium-shim/patches/with_update/patch_order.txt
index 433460cb6742392fc8413442c2cf0d2b8c2a1288..736d6eef176e5acbd5aa02dea5cc87883bf9bd5d 100755
--- a/security/sandbox/chromium-shim/patches/with_update/patch_order.txt
+++ b/security/sandbox/chromium-shim/patches/with_update/patch_order.txt
@@ -27,3 +27,4 @@ remove_extraneous_backslash_introduced_by_clang_tidy.patch
 remove_include_delayimp_h_from_pe_image_cc.patch
 lower_SDK_version_requirement.patch
 add_CET_STRICT_MODE.patch
+broker_complex_line_breaks.patch
diff --git a/security/sandbox/chromium-shim/sandbox/win/src/line_break_common.h b/security/sandbox/chromium-shim/sandbox/win/src/line_break_common.h
new file mode 100644
index 0000000000000000000000000000000000000000..a6fe342262576c07777e00f5e03a24a4b0f22f51
--- /dev/null
+++ b/security/sandbox/chromium-shim/sandbox/win/src/line_break_common.h
@@ -0,0 +1,25 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef SANDBOX_SRC_LINE_BREAK_COMMON_H_
+#define SANDBOX_SRC_LINE_BREAK_COMMON_H_
+
+#include "sandbox/win/src/crosscall_params.h"
+
+namespace sandbox {
+
+// Parameters are stored aligned to sizeof(int64_t).
+// So to calculate the maximum length we can use when brokering to the parent,
+// we take the max params buffer size, take off 8 for the aligned length and 6
+// and 7 to allow for the maximum padding that can be added to the text and
+// break before buffers. We then divide by three, because the text characters
+// are wchar_t and the break before elements are uint8_t.
+static const std::ptrdiff_t kMaxBrokeredLen =
+    (ActualCallParams<3, kIPCChannelSize>::MaxParamsSize() - 8 - 6 - 7) / 3;
+
+}  // namespace sandbox
+
+#endif  // SANDBOX_SRC_LINE_BREAK_COMMON_H_
diff --git a/security/sandbox/chromium-shim/sandbox/win/src/line_break_dispatcher.cc b/security/sandbox/chromium-shim/sandbox/win/src/line_break_dispatcher.cc
new file mode 100644
index 0000000000000000000000000000000000000000..94401d18faec84fb4fa45aa300dd6bb180013c90
--- /dev/null
+++ b/security/sandbox/chromium-shim/sandbox/win/src/line_break_dispatcher.cc
@@ -0,0 +1,58 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "sandbox/win/src/line_break_dispatcher.h"
+
+#include "sandbox/win/src/line_break_common.h"
+#include "sandbox/win/src/line_break_policy.h"
+#include "sandbox/win/src/ipc_tags.h"
+#include "sandbox/win/src/policy_params.h"
+
+namespace sandbox {
+
+LineBreakDispatcher::LineBreakDispatcher(PolicyBase* policy_base)
+    : policy_base_(policy_base) {
+  static const IPCCall get_complex_line_breaks = {
+      {IpcTag::GETCOMPLEXLINEBREAKS, {INPTR_TYPE, UINT32_TYPE, INOUTPTR_TYPE}},
+      reinterpret_cast<CallbackGeneric>(
+          &LineBreakDispatcher::GetComplexLineBreaksCall)};
+
+  ipc_calls_.push_back(get_complex_line_breaks);
+}
+
+bool LineBreakDispatcher::SetupService(InterceptionManager* manager,
+                                       IpcTag service) {
+  // We perform no interceptions for line breaking right now.
+  switch (service) {
+    case IpcTag::GETCOMPLEXLINEBREAKS:
+      return true;
+
+    default:
+      return false;
+  }
+}
+
+bool LineBreakDispatcher::GetComplexLineBreaksCall(
+    IPCInfo* ipc, CountedBuffer* text_buf, uint32_t length,
+    CountedBuffer* break_before_buf) {
+  if (length > kMaxBrokeredLen ||
+      text_buf->Size() != length * sizeof(wchar_t) ||
+      break_before_buf->Size() != length) {
+    return false;
+  }
+
+  CountedParameterSet<EmptyParams> params;
+  EvalResult eval =
+      policy_base_->EvalPolicy(IpcTag::GETCOMPLEXLINEBREAKS, params.GetBase());
+  auto* text = static_cast<wchar_t*>(text_buf->Buffer());
+  auto* break_before = static_cast<uint8_t*>(break_before_buf->Buffer());
+  ipc->return_info.win32_result =
+      LineBreakPolicy::GetComplexLineBreaksProxyAction(eval, text, length,
+                                                       break_before);
+  return true;
+}
+
+}  // namespace sandbox
diff --git a/security/sandbox/chromium-shim/sandbox/win/src/line_break_dispatcher.h b/security/sandbox/chromium-shim/sandbox/win/src/line_break_dispatcher.h
new file mode 100644
index 0000000000000000000000000000000000000000..774b5c5b5689fc3238b51823b61673229b559d72
--- /dev/null
+++ b/security/sandbox/chromium-shim/sandbox/win/src/line_break_dispatcher.h
@@ -0,0 +1,38 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef SANDBOX_SRC_LINE_BREAK_DISPATCHER_H_
+#define SANDBOX_SRC_LINE_BREAK_DISPATCHER_H_
+
+#include "base/macros.h"
+#include "sandbox/win/src/crosscall_server.h"
+#include "sandbox/win/src/sandbox_policy_base.h"
+
+namespace sandbox {
+
+// This class handles line break related IPC calls.
+class LineBreakDispatcher final : public Dispatcher {
+ public:
+  explicit LineBreakDispatcher(PolicyBase* policy_base);
+  ~LineBreakDispatcher() final {}
+
+  // Dispatcher interface.
+  bool SetupService(InterceptionManager* manager, IpcTag service) final;
+
+ private:
+  // Processes IPC requests coming from calls to
+  // TargetServices::GetComplexLineBreaks() in the target.
+  bool GetComplexLineBreaksCall(IPCInfo* ipc, CountedBuffer* text_buf,
+                                uint32_t length,
+                                CountedBuffer* break_before_buf);
+
+  PolicyBase* policy_base_;
+  DISALLOW_COPY_AND_ASSIGN(LineBreakDispatcher);
+};
+
+}  // namespace sandbox
+
+#endif  // SANDBOX_SRC_LINE_BREAK_DISPATCHER_H_
diff --git a/security/sandbox/chromium-shim/sandbox/win/src/line_break_interception.cc b/security/sandbox/chromium-shim/sandbox/win/src/line_break_interception.cc
new file mode 100644
index 0000000000000000000000000000000000000000..c01aab59a50998abde278c0f7377b89c6dde786f
--- /dev/null
+++ b/security/sandbox/chromium-shim/sandbox/win/src/line_break_interception.cc
@@ -0,0 +1,90 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "sandbox/win/src/line_break_interception.h"
+
+#include <winnls.h>
+
+#include "sandbox/win/src/crosscall_client.h"
+#include "sandbox/win/src/ipc_tags.h"
+#include "sandbox/win/src/line_break_common.h"
+#include "sandbox/win/src/sandbox_nt_util.h"
+#include "sandbox/win/src/sharedmem_ipc_client.h"
+
+namespace sandbox {
+
+static const int kBreakSearchRange = 32;
+
+ResultCode GetComplexLineBreaksProxy(const wchar_t* aText, uint32_t aLength,
+                                     uint8_t* aBreakBefore) {
+  // Make sure that a test length for kMaxBrokeredLen hasn't been set too small
+  // allowing for a surrogate pair at the end of a chunk as well.
+  DCHECK(kMaxBrokeredLen > kBreakSearchRange + 1);
+
+  void* memory = GetGlobalIPCMemory();
+  if (!memory) {
+    return SBOX_ERROR_NO_SPACE;
+  }
+
+  memset(aBreakBefore, false, aLength);
+
+  SharedMemIPCClient ipc(memory);
+
+  uint8_t* breakBeforeIter = aBreakBefore;
+  const wchar_t* textIterEnd = aText + aLength;
+  do {
+    // Next chunk is either the remaining text or kMaxBrokeredLen long.
+    const wchar_t* textIter = aText + (breakBeforeIter - aBreakBefore);
+    const wchar_t* chunkEnd = textIter + kMaxBrokeredLen;
+    if (chunkEnd < textIterEnd) {
+      // Make sure we don't split a surrogate pair.
+      if (IS_HIGH_SURROGATE(*(chunkEnd - 1))) {
+        --chunkEnd;
+      }
+    } else {
+      // This chunk handles all the (remaining) text.
+      chunkEnd = textIterEnd;
+    }
+
+    uint32_t len = chunkEnd - textIter;
+    // CountedBuffer takes a wchar_t* even though it doesn't change the buffer.
+    CountedBuffer textBuf(const_cast<wchar_t*>(textIter),
+                          sizeof(wchar_t) * len);
+    InOutCountedBuffer breakBeforeBuf(breakBeforeIter, len);
+    CrossCallReturn answer = {0};
+    ResultCode code = CrossCall(ipc, IpcTag::GETCOMPLEXLINEBREAKS, textBuf, len,
+                                breakBeforeBuf, &answer);
+    if (SBOX_ALL_OK != code) {
+      return code;
+    }
+
+    if (answer.win32_result) {
+      ::SetLastError(answer.win32_result);
+      return SBOX_ERROR_GENERIC;
+    }
+
+    if (chunkEnd == textIterEnd) {
+      break;
+    }
+
+    // We couldn't process all of the text in one go, so back up by 32 chars
+    // and look for a break, then continue from that position.
+    uint8_t* processedToEnd = breakBeforeIter + len;
+    breakBeforeIter = processedToEnd - kBreakSearchRange;
+    while (!*breakBeforeIter) {
+      if (++breakBeforeIter == processedToEnd) {
+        break;
+      }
+    }
+  } while (true);
+
+  // Whether we can break before the first character is decided by our caller
+  aBreakBefore[0] = false;
+
+  return SBOX_ALL_OK;
+}
+
+}  // namespace sandbox
diff --git a/security/sandbox/chromium-shim/sandbox/win/src/line_break_interception.h b/security/sandbox/chromium-shim/sandbox/win/src/line_break_interception.h
new file mode 100644
index 0000000000000000000000000000000000000000..87681e2e90a23877671f9ae7715206d3172db969
--- /dev/null
+++ b/security/sandbox/chromium-shim/sandbox/win/src/line_break_interception.h
@@ -0,0 +1,19 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef SANDBOX_SRC_LINE_BREAK_INTERCEPTION_H_
+#define SANDBOX_SRC_LINE_BREAK_INTERCEPTION_H_
+
+#include "sandbox/win/src/sandbox_types.h"
+
+namespace sandbox {
+
+ResultCode GetComplexLineBreaksProxy(const wchar_t* text, uint32_t length,
+                                     uint8_t* break_before);
+
+}  // namespace sandbox
+
+#endif  // SANDBOX_SRC_LINE_BREAK_INTERCEPTION_H_
diff --git a/security/sandbox/chromium-shim/sandbox/win/src/line_break_policy.cc b/security/sandbox/chromium-shim/sandbox/win/src/line_break_policy.cc
new file mode 100644
index 0000000000000000000000000000000000000000..55332326438f4a9fce509a34dec1c7cc3130e674
--- /dev/null
+++ b/security/sandbox/chromium-shim/sandbox/win/src/line_break_policy.cc
@@ -0,0 +1,66 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "sandbox/win/src/line_break_policy.h"
+
+#include <algorithm>
+#include <array>
+#include <usp10.h>
+
+#include "sandbox/win/src/ipc_tags.h"
+#include "sandbox/win/src/line_break_common.h"
+#include "sandbox/win/src/policy_engine_opcodes.h"
+#include "sandbox/win/src/policy_params.h"
+
+namespace sandbox {
+
+bool LineBreakPolicy::GenerateRules(const wchar_t* null,
+                                    TargetPolicy::Semantics semantics,
+                                    LowLevelPolicy* policy) {
+  if (TargetPolicy::LINE_BREAK_ALLOW != semantics) {
+    return false;
+  }
+
+  PolicyRule line_break_rule(ASK_BROKER);
+  if (!policy->AddRule(IpcTag::GETCOMPLEXLINEBREAKS, &line_break_rule)) {
+    return false;
+  }
+  return true;
+}
+
+/* static */ DWORD LineBreakPolicy::GetComplexLineBreaksProxyAction(
+    EvalResult eval_result, const wchar_t* text, uint32_t length,
+    uint8_t* break_before) {
+  // The only action supported is ASK_BROKER which means call the line breaker.
+  if (ASK_BROKER != eval_result) {
+    return ERROR_ACCESS_DENIED;
+  }
+
+  int outItems = 0;
+  std::array<SCRIPT_ITEM, kMaxBrokeredLen + 1> items;
+  HRESULT result = ::ScriptItemize(text, length, kMaxBrokeredLen, nullptr,
+                                   nullptr, items.data(), &outItems);
+  if (result != 0) {
+    return ERROR_ACCESS_DENIED;
+  }
+
+  std::array<SCRIPT_LOGATTR, kMaxBrokeredLen> slas;
+  for (int iItem = 0; iItem < outItems; ++iItem) {
+    uint32_t endOffset = items[iItem + 1].iCharPos;
+    uint32_t startOffset = items[iItem].iCharPos;
+    if (FAILED(::ScriptBreak(text + startOffset, endOffset - startOffset,
+                             &items[iItem].a, &slas[startOffset]))) {
+      return ERROR_ACCESS_DENIED;
+    }
+  }
+
+  std::transform(slas.data(), slas.data() + length, break_before,
+                 [](const SCRIPT_LOGATTR& sla) { return sla.fSoftBreak; });
+
+  return ERROR_SUCCESS;
+}
+
+}  // namespace sandbox
diff --git a/security/sandbox/chromium-shim/sandbox/win/src/line_break_policy.h b/security/sandbox/chromium-shim/sandbox/win/src/line_break_policy.h
new file mode 100644
index 0000000000000000000000000000000000000000..89fbf9b2076c933a00052db64470ec23ae630eba
--- /dev/null
+++ b/security/sandbox/chromium-shim/sandbox/win/src/line_break_policy.h
@@ -0,0 +1,35 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef SANDBOX_SRC_LINE_BREAK_POLICY_H_
+#define SANDBOX_SRC_LINE_BREAK_POLICY_H_
+
+#include "base/win/windows_types.h"
+#include "sandbox/win/src/policy_low_level.h"
+#include "sandbox/win/src/sandbox_policy.h"
+
+namespace sandbox {
+
+enum EvalResult;
+
+class LineBreakPolicy {
+ public:
+  // Creates the required low-level policy rules to evaluate a high-level
+  // policy rule for complex line breaks.
+  static bool GenerateRules(const wchar_t* type_name,
+                            TargetPolicy::Semantics semantics,
+                            LowLevelPolicy* policy);
+
+  // Processes a TargetServices::GetComplexLineBreaks() request from the target.
+  static DWORD GetComplexLineBreaksProxyAction(EvalResult eval_result,
+                                               const wchar_t* text,
+                                               uint32_t length,
+                                               uint8_t* break_before);
+};
+
+}  // namespace sandbox
+
+#endif  // SANDBOX_SRC_LINE_BREAK_POLICY_H_
diff --git a/security/sandbox/chromium/sandbox/win/src/crosscall_client.h b/security/sandbox/chromium/sandbox/win/src/crosscall_client.h
index 84fd090a72a92d8950cef92f385613266a15cbdc..a346aeb753a726fa1d1474a055f9f9f2ed33b6f6 100644
--- a/security/sandbox/chromium/sandbox/win/src/crosscall_client.h
+++ b/security/sandbox/chromium/sandbox/win/src/crosscall_client.h
@@ -44,10 +44,6 @@ namespace sandbox {
 
 enum class IpcTag;
 
-// this is the assumed channel size. This can be overridden in a given
-// IPC implementation.
-const uint32_t kIPCChannelSize = 1024;
-
 // The copy helper uses templates to deduce the appropriate copy function to
 // copy the input parameters in the buffer that is going to be send across the
 // IPC. These template facility can be made more sophisticated as need arises.
@@ -211,6 +207,32 @@ class InOutCountedBuffer : public CountedBuffer {
       : CountedBuffer(buffer, size) {}
 };
 
+// This copy helper template specialization catches the cases where the
+// parameter is a an input buffer.
+template <>
+class CopyHelper<CountedBuffer> {
+ public:
+  CopyHelper(const CountedBuffer t) : t_(t) {}
+
+  // Returns the pointer to the start of the string.
+  const void* GetStart() const { return t_.Buffer(); }
+
+  // Update not required so just return true;
+  bool Update(void* buffer) { return true; }
+
+  // Returns the size of the string in bytes. We define a nullptr string to
+  // be of zero length.
+  uint32_t GetSize() const { return t_.Size(); }
+
+  // Returns true if the current type is used as an In or InOut parameter.
+  bool IsInOut() { return false; }
+
+  ArgType GetType() { return INPTR_TYPE; }
+
+ private:
+  const CountedBuffer t_;
+};
+
 // This copy helper template specialization catches the cases where the
 // parameter is a an input/output buffer.
 template <>
diff --git a/security/sandbox/chromium/sandbox/win/src/crosscall_params.h b/security/sandbox/chromium/sandbox/win/src/crosscall_params.h
index a4ffc05997562b51cb788c440e7312fda78afa83..6971b55cb72d175b50c0ec60da660bbed369da82 100644
--- a/security/sandbox/chromium/sandbox/win/src/crosscall_params.h
+++ b/security/sandbox/chromium/sandbox/win/src/crosscall_params.h
@@ -46,6 +46,10 @@
 
 namespace sandbox {
 
+// this is the assumed channel size. This can be overridden in a given
+// IPC implementation.
+const uint32_t kIPCChannelSize = 1024;
+
 // This is the list of all imported symbols from ntdll.dll.
 SANDBOX_INTERCEPT NtExports g_nt;
 
@@ -221,6 +225,11 @@ class ActualCallParams : public CrossCallParams {
         static_cast<uint32_t>(parameters_ - reinterpret_cast<char*>(this));
   }
 
+  static constexpr size_t MaxParamsSize() {
+    return sizeof(
+        ActualCallParams<NUMBER_PARAMS, kIPCChannelSize>::parameters_);
+  }
+
   // Testing-only method. Allows setting the apparent size to a wrong value.
   // returns the previous size.
   uint32_t OverrideSize(uint32_t new_size) {
diff --git a/security/sandbox/chromium/sandbox/win/src/crosscall_server.cc b/security/sandbox/chromium/sandbox/win/src/crosscall_server.cc
index 415ad27eac793ad24c09bde826e21214297860af..27bfdfbd65edb0e08eda9d5747629ba5bba184ac 100644
--- a/security/sandbox/chromium/sandbox/win/src/crosscall_server.cc
+++ b/security/sandbox/chromium/sandbox/win/src/crosscall_server.cc
@@ -306,7 +306,7 @@ bool CrossCallParamsEx::GetParameterPtr(uint32_t index,
   ArgType type;
   void* start = GetRawParameter(index, &size, &type);
 
-  if ((size != expected_size) || (INOUTPTR_TYPE != type))
+  if ((size != expected_size) || (INOUTPTR_TYPE != type && INPTR_TYPE != type))
     return false;
 
   if (!start)
diff --git a/security/sandbox/chromium/sandbox/win/src/ipc_args.cc b/security/sandbox/chromium/sandbox/win/src/ipc_args.cc
index c961ad809edd126274af2c11acc3ef2269e9fcbe..c0c64f1864ec951e3d22f05de57aa8ed27fcf0ec 100644
--- a/security/sandbox/chromium/sandbox/win/src/ipc_args.cc
+++ b/security/sandbox/chromium/sandbox/win/src/ipc_args.cc
@@ -20,6 +20,7 @@ void ReleaseArgs(const IPCParams* ipc_params, void* args[kMaxIpcParams]) {
         args[i] = nullptr;
         break;
       }
+      case INPTR_TYPE:
       case INOUTPTR_TYPE: {
         delete reinterpret_cast<CountedBuffer*>(args[i]);
         args[i] = nullptr;
@@ -74,6 +75,7 @@ bool GetArgs(CrossCallParamsEx* params,
           args[i] = data;
           break;
         }
+        case INPTR_TYPE:
         case INOUTPTR_TYPE: {
           if (!args[i]) {
             ReleaseArgs(ipc_params, args);
diff --git a/security/sandbox/chromium/sandbox/win/src/ipc_tags.h b/security/sandbox/chromium/sandbox/win/src/ipc_tags.h
index ad69706258b85090ee5809482b7affd7787e604e..ec6de4a66ad513ef48eaf615367463238ba21078 100644
--- a/security/sandbox/chromium/sandbox/win/src/ipc_tags.h
+++ b/security/sandbox/chromium/sandbox/win/src/ipc_tags.h
@@ -46,6 +46,7 @@ enum class IpcTag {
   GDI_GETSUGGESTEDOPMPROTECTEDOUTPUTARRAYSIZE,
   GDI_SETOPMSIGNINGKEYANDSEQUENCENUMBERS,
   NTCREATESECTION,
+  GETCOMPLEXLINEBREAKS,
   LAST
 };
 
diff --git a/security/sandbox/chromium/sandbox/win/src/policy_engine_opcodes.cc b/security/sandbox/chromium/sandbox/win/src/policy_engine_opcodes.cc
index 4bac801f9bce53b457e70f992b716d3739fb4a8e..02c636f4aa81cdd5a01829c921a2a1212c313919 100644
--- a/security/sandbox/chromium/sandbox/win/src/policy_engine_opcodes.cc
+++ b/security/sandbox/chromium/sandbox/win/src/policy_engine_opcodes.cc
@@ -83,7 +83,7 @@ EvalResult OpcodeEval<OP_ALWAYS_TRUE>(PolicyOpcode* opcode,
 // Argument 0 contains the actual action to return.
 
 PolicyOpcode* OpcodeFactory::MakeOpAction(EvalResult action, uint32_t options) {
-  PolicyOpcode* opcode = MakeBase(OP_ACTION, options, 0);
+  PolicyOpcode* opcode = MakeBase(OP_ACTION, options, -1);
   if (!opcode)
     return nullptr;
   opcode->SetArgument(0, action);
diff --git a/security/sandbox/chromium/sandbox/win/src/policy_params.h b/security/sandbox/chromium/sandbox/win/src/policy_params.h
index dbab8307d42fc617ddc74c7691b56d926f7eee19..aeec6d7edc494bb2a6e0c33170a44b4496c795c7 100644
--- a/security/sandbox/chromium/sandbox/win/src/policy_params.h
+++ b/security/sandbox/chromium/sandbox/win/src/policy_params.h
@@ -61,6 +61,10 @@ POLPARAMS_BEGIN(HandleTarget)
   POLPARAM(TARGET)
 POLPARAMS_END(HandleTarget)
 
+// Policy parameters where no parameter based checks are done.
+POLPARAMS_BEGIN(EmptyParams)
+POLPARAMS_END(EmptyParams)
+
 }  // namespace sandbox
 
 #endif  // SANDBOX_SRC_POLICY_PARAMS_H__
diff --git a/security/sandbox/chromium/sandbox/win/src/sandbox.h b/security/sandbox/chromium/sandbox/win/src/sandbox.h
index 8c1ad7aa194f02947c6943e417930c128f669e01..92d40c755c5c9b27f97c422cd775ddcf707ee346 100644
--- a/security/sandbox/chromium/sandbox/win/src/sandbox.h
+++ b/security/sandbox/chromium/sandbox/win/src/sandbox.h
@@ -181,6 +181,9 @@ class TargetServices {
                                      DWORD desired_access,
                                      DWORD options) = 0;
 
+  virtual ResultCode GetComplexLineBreaks(const WCHAR* text, uint32_t length,
+                                          uint8_t* break_before) = 0;
+
  protected:
   ~TargetServices() {}
 };
diff --git a/security/sandbox/chromium/sandbox/win/src/sandbox_policy.h b/security/sandbox/chromium/sandbox/win/src/sandbox_policy.h
index 3ed6561589e5dda456e9b66e7441fc2fb33a01e6..75514ef595d849b33ffd56d058559485add96933 100644
--- a/security/sandbox/chromium/sandbox/win/src/sandbox_policy.h
+++ b/security/sandbox/chromium/sandbox/win/src/sandbox_policy.h
@@ -32,7 +32,8 @@ class TargetPolicy {
     SUBSYS_SYNC,             // Creation of named sync objects.
     SUBSYS_HANDLES,          // Duplication of handles to other processes.
     SUBSYS_WIN32K_LOCKDOWN,  // Win32K Lockdown related policy.
-    SUBSYS_SIGNED_BINARY     // Signed binary policy.
+    SUBSYS_SIGNED_BINARY,    // Signed binary policy.
+    SUBSYS_LINE_BREAK        // Complex line break policy.
   };
 
   // Allowable semantics when a rule is matched.
@@ -65,7 +66,8 @@ class TargetPolicy {
     IMPLEMENT_OPM_APIS,     // Implements FAKE_USER_GDI_INIT and also exposes
                             // IPC calls to handle Output Protection Manager
                             // APIs.
-    SIGNED_ALLOW_LOAD       // Allows loading the module when CIG is enabled.
+    SIGNED_ALLOW_LOAD,      // Allows loading the module when CIG is enabled.
+    LINE_BREAK_ALLOW        // Allow complex line break brokering.
   };
 
   // Increments the reference count of this object. The reference count must
diff --git a/security/sandbox/chromium/sandbox/win/src/sandbox_policy_base.cc b/security/sandbox/chromium/sandbox/win/src/sandbox_policy_base.cc
index ddaea73ab36afad4d8b81ba50bc1f58437c8b592..194f4e9353a1f029bf2e3c62a4ccd6b4fdcb3b51 100644
--- a/security/sandbox/chromium/sandbox/win/src/sandbox_policy_base.cc
+++ b/security/sandbox/chromium/sandbox/win/src/sandbox_policy_base.cc
@@ -20,6 +20,7 @@
 #include "sandbox/win/src/handle_policy.h"
 #include "sandbox/win/src/interception.h"
 #include "sandbox/win/src/job.h"
+#include "sandbox/win/src/line_break_policy.h"
 #include "sandbox/win/src/named_pipe_policy.h"
 #include "sandbox/win/src/policy_broker.h"
 #include "sandbox/win/src/policy_engine_processor.h"
@@ -814,6 +815,13 @@ ResultCode PolicyBase::AddRuleInternal(SubSystem subsystem,
       }
       break;
     }
+    case SUBSYS_LINE_BREAK: {
+      if (!LineBreakPolicy::GenerateRules(pattern, semantics, policy_maker_)) {
+        NOTREACHED();
+        return SBOX_ERROR_BAD_PARAMS;
+      }
+      break;
+    }
 
     default: { return SBOX_ERROR_UNSUPPORTED; }
   }
diff --git a/security/sandbox/chromium/sandbox/win/src/target_services.cc b/security/sandbox/chromium/sandbox/win/src/target_services.cc
index 52a29e2df3ad793ad1ee8594a75b275aeee53698..a80e0106ef952dfb665835b014cda7837610409d 100644
--- a/security/sandbox/chromium/sandbox/win/src/target_services.cc
+++ b/security/sandbox/chromium/sandbox/win/src/target_services.cc
@@ -14,6 +14,7 @@
 #include "sandbox/win/src/handle_closer_agent.h"
 #include "sandbox/win/src/handle_interception.h"
 #include "sandbox/win/src/heap_helper.h"
+#include "sandbox/win/src/line_break_interception.h"
 #include "sandbox/win/src/ipc_tags.h"
 #include "sandbox/win/src/process_mitigations.h"
 #include "sandbox/win/src/restricted_token_utils.h"
@@ -245,7 +246,6 @@ void ProcessState::SetCsrssConnected(bool csrss_connected) {
   csrss_connected_ = csrss_connected;
 }
 
-
 ResultCode TargetServicesBase::DuplicateHandle(HANDLE source_handle,
                                                DWORD target_process_id,
                                                HANDLE* target_handle,
@@ -255,4 +255,10 @@ ResultCode TargetServicesBase::DuplicateHandle(HANDLE source_handle,
                                        target_handle, desired_access, options);
 }
 
+ResultCode TargetServicesBase::GetComplexLineBreaks(const WCHAR* text,
+                                                    uint32_t length,
+                                                    uint8_t* break_before) {
+  return sandbox::GetComplexLineBreaksProxy(text, length, break_before);
+}
+
 }  // namespace sandbox
diff --git a/security/sandbox/chromium/sandbox/win/src/target_services.h b/security/sandbox/chromium/sandbox/win/src/target_services.h
index 6a1d31464652e95c17e9d98dabd9ebf875c6d636..1d70d4cd34e6def3a3deab39e29730cd65c4bf46 100644
--- a/security/sandbox/chromium/sandbox/win/src/target_services.h
+++ b/security/sandbox/chromium/sandbox/win/src/target_services.h
@@ -50,6 +50,8 @@ class TargetServicesBase : public TargetServices {
                              HANDLE* target_handle,
                              DWORD desired_access,
                              DWORD options) override;
+  ResultCode GetComplexLineBreaks(const WCHAR* text, uint32_t length,
+                                  uint8_t* break_before) final;
 
   // Factory method.
   static TargetServicesBase* GetInstance();
diff --git a/security/sandbox/chromium/sandbox/win/src/top_level_dispatcher.cc b/security/sandbox/chromium/sandbox/win/src/top_level_dispatcher.cc
index 31af52e99f84ecdd1380d30902021bfe9f9085eb..3c8f8e25e5983f232faaf1ff1f5226e36524a22e 100644
--- a/security/sandbox/chromium/sandbox/win/src/top_level_dispatcher.cc
+++ b/security/sandbox/chromium/sandbox/win/src/top_level_dispatcher.cc
@@ -14,6 +14,7 @@
 #include "sandbox/win/src/interception.h"
 #include "sandbox/win/src/internal_types.h"
 #include "sandbox/win/src/ipc_tags.h"
+#include "sandbox/win/src/line_break_dispatcher.h"
 #include "sandbox/win/src/named_pipe_dispatcher.h"
 #include "sandbox/win/src/process_mitigations_win32k_dispatcher.h"
 #include "sandbox/win/src/process_thread_dispatcher.h"
@@ -95,6 +96,10 @@ TopLevelDispatcher::TopLevelDispatcher(PolicyBase* policy) : policy_(policy) {
   dispatcher = new SignedDispatcher(policy_);
   ipc_targets_[static_cast<size_t>(IpcTag::NTCREATESECTION)] = dispatcher;
   signed_dispatcher_.reset(dispatcher);
+
+  dispatcher = new LineBreakDispatcher(policy_);
+  ipc_targets_[static_cast<size_t>(IpcTag::GETCOMPLEXLINEBREAKS)] = dispatcher;
+  line_break_dispatcher_.reset(dispatcher);
 }
 
 TopLevelDispatcher::~TopLevelDispatcher() {}
diff --git a/security/sandbox/chromium/sandbox/win/src/top_level_dispatcher.h b/security/sandbox/chromium/sandbox/win/src/top_level_dispatcher.h
index b440d86f1df5be51d12041f1063c27f0ffea72a8..a80ce1ef5d3ad7ae61fccc9189e9fc0ce28974f8 100644
--- a/security/sandbox/chromium/sandbox/win/src/top_level_dispatcher.h
+++ b/security/sandbox/chromium/sandbox/win/src/top_level_dispatcher.h
@@ -43,6 +43,7 @@ class TopLevelDispatcher : public Dispatcher {
   std::unique_ptr<Dispatcher> handle_dispatcher_;
   std::unique_ptr<Dispatcher> process_mitigations_win32k_dispatcher_;
   std::unique_ptr<Dispatcher> signed_dispatcher_;
+  std::unique_ptr<Dispatcher> line_break_dispatcher_;
   Dispatcher* ipc_targets_[kMaxIpcTag];
 
   DISALLOW_COPY_AND_ASSIGN(TopLevelDispatcher);
diff --git a/security/sandbox/moz.build b/security/sandbox/moz.build
index e10f1afe91af3dfc44e98b7b5f31b96644fcfe30..27a0eb6bd83a11a874afb5a6b7b5faaee4a96f78 100755
--- a/security/sandbox/moz.build
+++ b/security/sandbox/moz.build
@@ -49,6 +49,9 @@ elif CONFIG["OS_ARCH"] == "WINNT":
         "chromium-shim/base/win/win_util.cpp",
         "chromium-shim/sandbox/win/permissionsService.cpp",
         "chromium-shim/sandbox/win/sandboxLogging.cpp",
+        "chromium-shim/sandbox/win/src/line_break_dispatcher.cc",
+        "chromium-shim/sandbox/win/src/line_break_interception.cc",
+        "chromium-shim/sandbox/win/src/line_break_policy.cc",
         "chromium/base/at_exit.cc",
         "chromium/base/base_switches.cc",
         "chromium/base/callback_internal.cc",
@@ -204,6 +207,8 @@ elif CONFIG["OS_ARCH"] == "WINNT":
     LOCAL_INCLUDES += ["/security/sandbox/chromium"]
     LOCAL_INCLUDES += ["/nsprpub"]
 
+    OS_LIBS += ["usp10"]
+
     DisableStlWrapping()
 
     # Suppress warnings in third-party code.
diff --git a/security/sandbox/win/src/sandboxbroker/sandboxBroker.cpp b/security/sandbox/win/src/sandboxbroker/sandboxBroker.cpp
index d95bc5cf3d30ccf59e1f96787b06ec42521e865d..c58888bfc35b64c7100ddfdbcb09f6bc95ac38d6 100644
--- a/security/sandbox/win/src/sandboxbroker/sandboxBroker.cpp
+++ b/security/sandbox/win/src/sandboxbroker/sandboxBroker.cpp
@@ -783,6 +783,13 @@ void SandboxBroker::SetSecurityLevelForContentProcess(int32_t aSandboxLevel,
       sandbox::SBOX_ALL_OK == result,
       "With these static arguments AddRule should never fail, what happened?");
 
+  // Allow content processes to use complex line breaking brokering.
+  result = mPolicy->AddRule(sandbox::TargetPolicy::SUBSYS_LINE_BREAK,
+                            sandbox::TargetPolicy::LINE_BREAK_ALLOW, nullptr);
+  MOZ_RELEASE_ASSERT(
+      sandbox::SBOX_ALL_OK == result,
+      "With these static arguments AddRule should never fail, what happened?");
+
   if (aSandboxLevel >= 20) {
     // Content process still needs to be able to read fonts.
     wchar_t* fontsPath;
diff --git a/security/sandbox/win/src/sandboxtarget/sandboxTarget.cpp b/security/sandbox/win/src/sandboxtarget/sandboxTarget.cpp
index b5c71e87626517728024063b4165249e9892c437..b0b0876bcaabed9830ba3416284d0d24878ee1ac 100644
--- a/security/sandbox/win/src/sandboxtarget/sandboxTarget.cpp
+++ b/security/sandbox/win/src/sandboxtarget/sandboxTarget.cpp
@@ -50,5 +50,15 @@ bool SandboxTarget::BrokerDuplicateHandle(HANDLE aSourceHandle,
       aSourceHandle, aTargetProcessId, aTargetHandle, aDesiredAccess, aOptions);
   return (sandbox::SBOX_ALL_OK == result);
 }
+bool SandboxTarget::GetComplexLineBreaks(const WCHAR* text, uint32_t length,
+                                         uint8_t* break_before) {
+  if (!mTargetServices) {
+    return false;
+  }
+
+  sandbox::ResultCode result =
+      mTargetServices->GetComplexLineBreaks(text, length, break_before);
+  return (sandbox::SBOX_ALL_OK == result);
+}
 
 }  // namespace mozilla
diff --git a/security/sandbox/win/src/sandboxtarget/sandboxTarget.h b/security/sandbox/win/src/sandboxtarget/sandboxTarget.h
index b60881dd3faadaaed5788124c164f98706e0062e..7867f0bb33a33fc944b5de0d7b66229de7f243ae 100644
--- a/security/sandbox/win/src/sandboxtarget/sandboxTarget.h
+++ b/security/sandbox/win/src/sandboxtarget/sandboxTarget.h
@@ -62,6 +62,9 @@ class SandboxTarget {
                              HANDLE* aTargetHandle, DWORD aDesiredAccess,
                              DWORD aOptions);
 
+  bool GetComplexLineBreaks(const WCHAR* text, uint32_t length,
+                            uint8_t* break_before);
+
  protected:
   SandboxTarget() : mTargetServices(nullptr) {}