Compare commits

...

20 Commits
7204 ... 3865

Author SHA1 Message Date
Marshall Greenblatt
8e8d6022fa cefclient: Fix crash when removing extension resource path prefix.
To test: Run `cefclient.exe --use-views --load-extension=set_page_color`
2019-10-18 15:00:27 +02:00
Maksim Sisov
8819106865 Remove NOTREACHED that triggers on ozone platforms.
Native frames are not guaranteed to be supported on Ozone/Wayland.
2019-10-18 14:53:28 +02:00
Marshall Greenblatt
50c951edee Don't set "always on top" style for child CefWindows.
As of https://crrev.com/9e653328e3 the Views framework will apply the "always
on top" (WS_EX_TOPMOST) style by default to widgets created with TYPE_MENU. CEF
uses this type in CefWindowView::CreateWidget to support child windows that are
not clipped to the parent window bounds (currently indicated by returning a
parent window from CefWindowDelegate::GetParentWindow and setting |is_menu| to
true).

Not setting "always on top" shouldn't be a problem except in cases where some
other window is already "always on top" and the child CefWindow is expected to
overlay that window. For this reason any menus created using ShowMenu will
continue to have the "always on top" style.
2019-10-18 14:47:43 +02:00
Marshall Greenblatt
986b8c128c Remove incorrect DCHECK
There are valid cases where |frame_tree_node_id| may not match the node ID
reported by the selected RenderFrameHost.
2019-10-18 14:05:55 +02:00
Marshall Greenblatt
4fb61d2b79 Update to Chromium version 77.0.3865.120 2019-10-14 15:39:40 +02:00
Marshall Greenblatt
676b14705f cefsimple: Use data URI instead of LoadString for error messages (see issue #2586) 2019-10-10 11:13:16 +03:00
Marshall Greenblatt
c63c001142 Fix crashes with --disable-extensions (fixes issue #2777) 2019-10-07 11:59:16 +03:00
Marshall Greenblatt
1687a637a8 Remove WebUITest.credits because it always times out 2019-10-04 18:01:10 +03:00
Marshall Greenblatt
d6a872bc86 Windows: Fix ViewsWindowTest failures due to incorrect client area size (fixes issue #2775)
These tests expect the window's client area size to be (kWSize, kWSize). Use
::AdjustWindowRect to offset TestWindowDelegate's preferred size so that the
client area size is correct after the OS internally applies frame insets during
::CreateWindow.

To test: Run `ceftests.exe --gtest_filter=ViewsWindowTest.Window*`.
All tests should pass.
2019-10-04 17:32:54 +03:00
Marshall Greenblatt
2148d3de57 Increase URLRequestTest CloseBrowser timeout to reduce flakes (fixes issue #2756)
Tests for incomplete request behavior use a timeout to trigger CloseBrowser
and terminate the test case. Recent architectural changes in Chromium have
likely increased the minimum delay required to spin up a working browser
instance and initiate the request. Consequently we need to wait longer before
closing the browser.

To test:
Run `ceftests --gtest_filter=URLRequestTest.*Incomplete* --gtest_repeat=5`.
All test runs should succeed.
2019-10-04 15:50:28 +03:00
Marshall Greenblatt
41b180dc3f macOS: cmake: Prevent Xcode 11 from doing automatic codesigning. 2019-10-03 11:29:47 +03:00
Marshall Greenblatt
c7dbc2febf Add missing services strings to pak (fixes issue #2764) 2019-10-02 13:57:22 +03:00
Marshall Greenblatt
a0ea7e64bc Remove cef_sandbox dependency on boringssl MD5/SHA1 functions (fixes issue #2743) 2019-10-01 14:30:07 +03:00
Marshall Greenblatt
d277892b92 Windows: Restore missing resources to binary distribution (fixes issue #2771) 2019-10-01 12:17:34 +03:00
Marshall Greenblatt
f3890bec3b Windows: cmake: Add newer VS versions 2019-09-30 15:16:53 +03:00
Marshall Greenblatt
f0a1c440ee Update to Chromium version 77.0.3865.90 2019-09-30 13:18:22 +03:00
Marshall Greenblatt
be3096ba33 Add Google SafeSearch support with NetworkService (see issue #1917) 2019-09-25 16:59:51 +03:00
Marshall Greenblatt
d2cc8d5015 Remove audio_output_unittest.cc which no longer exists (see issue #2755, see issue #2381) 2019-09-23 18:50:39 +03:00
Marshall Greenblatt
1f893c76a9 Revert "Add ability to capture audio output to buffer (see issue #2381)"
This reverts commit 9f41a27e58.

This needs to be reimplemented to support out of process audio (see issue #2755).
2019-09-20 17:34:54 +03:00
Marshall Greenblatt
cc9f616038 Update to Chromium version 77.0.3865.56 2019-09-04 14:54:20 -04:00
71 changed files with 401 additions and 2208 deletions

View File

@@ -364,10 +364,6 @@ if (is_win) {
static_library("libcef_static") {
sources = gypi_paths2.includes_common +
gypi_paths.autogen_cpp_includes + [
"libcef/browser/audio_mirror_destination.cc",
"libcef/browser/audio_mirror_destination.h",
"libcef/browser/audio_push_sink.cc",
"libcef/browser/audio_push_sink.h",
"libcef/browser/browser_context.cc",
"libcef/browser/browser_context.h",
"libcef/browser/browser_context_keyed_service_factories.cc",
@@ -1539,6 +1535,7 @@ make_pack_header("strings") {
"$root_gen_dir/components/strings/grit/components_strings.h",
"$root_gen_dir/content/app/strings/grit/content_strings.h",
"$root_gen_dir/extensions/strings/grit/extensions_strings.h",
"$root_gen_dir/services/strings/grit/services_strings.h",
"$root_gen_dir/ui/strings/grit/ui_strings.h",
]
}

View File

@@ -7,5 +7,5 @@
# https://bitbucket.org/chromiumembedded/cef/wiki/BranchesAndBuilding
{
'chromium_checkout': 'refs/tags/77.0.3865.0'
'chromium_checkout': 'refs/tags/77.0.3865.120'
}

View File

@@ -8,7 +8,7 @@
# by hand. See the translator.README.txt file in the tools directory for
# more information.
#
# $hash=a8e80ae73a0d30776c2e6aaceaf9dbd4031f6c74$
# $hash=9e6f93e99114085f9251881661e562357608b75a$
#
{
@@ -16,7 +16,6 @@
'autogen_cpp_includes': [
'include/cef_accessibility_handler.h',
'include/cef_app.h',
'include/cef_audio_handler.h',
'include/cef_auth_callback.h',
'include/cef_browser.h',
'include/cef_browser_process_handler.h',
@@ -110,7 +109,6 @@
'autogen_capi_includes': [
'include/capi/cef_accessibility_handler_capi.h',
'include/capi/cef_app_capi.h',
'include/capi/cef_audio_handler_capi.h',
'include/capi/cef_auth_callback_capi.h',
'include/capi/cef_browser_capi.h',
'include/capi/cef_browser_process_handler_capi.h',
@@ -206,8 +204,6 @@
'libcef_dll/ctocpp/accessibility_handler_ctocpp.h',
'libcef_dll/ctocpp/app_ctocpp.cc',
'libcef_dll/ctocpp/app_ctocpp.h',
'libcef_dll/ctocpp/audio_handler_ctocpp.cc',
'libcef_dll/ctocpp/audio_handler_ctocpp.h',
'libcef_dll/cpptoc/auth_callback_cpptoc.cc',
'libcef_dll/cpptoc/auth_callback_cpptoc.h',
'libcef_dll/cpptoc/before_download_callback_cpptoc.cc',
@@ -498,8 +494,6 @@
'libcef_dll/cpptoc/accessibility_handler_cpptoc.h',
'libcef_dll/cpptoc/app_cpptoc.cc',
'libcef_dll/cpptoc/app_cpptoc.h',
'libcef_dll/cpptoc/audio_handler_cpptoc.cc',
'libcef_dll/cpptoc/audio_handler_cpptoc.h',
'libcef_dll/ctocpp/auth_callback_ctocpp.cc',
'libcef_dll/ctocpp/auth_callback_ctocpp.h',
'libcef_dll/ctocpp/before_download_callback_ctocpp.cc',

View File

@@ -354,6 +354,11 @@
'tests/cefclient/cefclient_win.cc',
'tests/cefclient/resources/win/cefclient.rc',
],
'cefclient_sources_resources_win': [
'tests/cefclient/resources/win/cefclient.exe.manifest',
'tests/cefclient/resources/win/cefclient.ico',
'tests/cefclient/resources/win/small.ico',
],
'cefclient_sources_mac': [
'tests/cefclient/browser/browser_window_osr_mac.h',
'tests/cefclient/browser/browser_window_osr_mac.mm',
@@ -426,6 +431,11 @@
'tests/cefsimple/simple_handler_win.cc',
'tests/cefsimple/resource.h',
],
'cefsimple_sources_resources_win': [
'tests/cefsimple/cefsimple.exe.manifest',
'tests/cefsimple/res/cefsimple.ico',
'tests/cefsimple/res/small.ico',
],
'cefsimple_sources_mac': [
'tests/cefsimple/cefsimple_mac.mm',
'tests/cefsimple/simple_handler_mac.mm',
@@ -444,7 +454,6 @@
'tests/cefsimple/simple_handler_linux.cc',
],
'ceftests_sources_common': [
'tests/ceftests/audio_output_unittest.cc',
'tests/ceftests/browser_info_map_unittest.cc',
'tests/ceftests/command_line_unittest.cc',
'tests/ceftests/cookie_unittest.cc',
@@ -527,6 +536,11 @@
'tests/ceftests/resource_util_win_idmap.cc',
'tests/ceftests/resources/win/ceftests.rc',
],
'ceftests_sources_resources_win': [
'tests/ceftests/resources/win/ceftests.exe.manifest',
'tests/ceftests/resources/win/ceftests.ico',
'tests/ceftests/resources/win/small.ico',
],
'ceftests_sources_mac': [
'tests/ceftests/os_rendering_unittest_mac.h',
'tests/ceftests/os_rendering_unittest_mac.mm',
@@ -538,7 +552,6 @@
'tests/shared/browser/resource_util.h',
'tests/shared/browser/resource_util_mac.mm',
'tests/shared/browser/resource_util_posix.cc',
'tests/ceftests/audio_output_unittest.cc',
'tests/ceftests/client_app_delegates.cc',
'tests/ceftests/cookie_unittest.cc',
'tests/ceftests/dom_unittest.cc',

View File

@@ -38,6 +38,7 @@ template("_repack_one_locale") {
"${root_gen_dir}/components/strings/components_strings_${locale}.pak",
"${root_gen_dir}/content/app/strings/content_strings_${locale}.pak",
"${root_gen_dir}/extensions/strings/extensions_strings_${locale}.pak",
"${root_gen_dir}/services/strings/services_strings_${locale}.pak",
"${root_gen_dir}/ui/strings/app_locale_settings_${locale}.pak",
"${root_gen_dir}/ui/strings/ui_strings_${locale}.pak",
]
@@ -55,6 +56,7 @@ template("_repack_one_locale") {
"//components/strings:components_strings",
"//content/app/strings",
"//extensions/strings",
"//services/strings",
"//ui/strings:app_locale_settings",
"//ui/strings:ui_strings",
]

View File

@@ -332,6 +332,9 @@ if(OS_MACOSX)
set(CMAKE_OSX_ARCHITECTURES "i386")
endif()
# Prevent Xcode 11 from doing automatic codesigning.
set(CMAKE_XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY "")
# CEF directory paths.
set(CEF_BINARY_DIR "${_CEF_ROOT}/$<CONFIGURATION>")
set(CEF_BINARY_DIR_DEBUG "${_CEF_ROOT}/Debug")
@@ -385,7 +388,9 @@ if(OS_WINDOWS)
1915 # VS2017 version 15.8
1916 # VS2017 version 15.9
1920 # VS2019 version 16.0
1921 # VS2018 version 16.1
1921 # VS2019 version 16.1
1922 # VS2019 version 16.2
1923 # VS2019 version 16.3
)
list(FIND supported_msvc_versions ${MSVC_VERSION} _index)
if (${_index} EQUAL -1)

View File

@@ -1,110 +0,0 @@
// Copyright (c) 2019 Marshall A. Greenblatt. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the name Chromium Embedded
// Framework nor the names of its contributors may be used to endorse
// or promote products derived from this software without specific prior
// written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// ---------------------------------------------------------------------------
//
// This file was generated by the CEF translator tool and should not edited
// by hand. See the translator.README.txt file in the tools directory for
// more information.
//
// $hash=0385a38b6761c5dec07bb89a95a007ad3c11bea6$
//
#ifndef CEF_INCLUDE_CAPI_CEF_AUDIO_HANDLER_CAPI_H_
#define CEF_INCLUDE_CAPI_CEF_AUDIO_HANDLER_CAPI_H_
#pragma once
#include "include/capi/cef_base_capi.h"
#include "include/capi/cef_browser_capi.h"
#ifdef __cplusplus
extern "C" {
#endif
///
// Implement this structure to handle audio events All functions will be called
// on the UI thread
///
typedef struct _cef_audio_handler_t {
///
// Base structure.
///
cef_base_ref_counted_t base;
///
// Called when the stream identified by |audio_stream_id| has started.
// |audio_stream_id| will uniquely identify the stream across all future
// cef_audio_handler_t callbacks. OnAudioSteamStopped will always be called
// after OnAudioStreamStarted; both functions may be called multiple times for
// the same stream. |channels| is the number of channels, |channel_layout| is
// the layout of the channels and |sample_rate| is the stream sample rate.
// |frames_per_buffer| is the maximum number of frames that will occur in the
// PCM packet passed to OnAudioStreamPacket.
///
void(CEF_CALLBACK* on_audio_stream_started)(
struct _cef_audio_handler_t* self,
struct _cef_browser_t* browser,
int audio_stream_id,
int channels,
cef_channel_layout_t channel_layout,
int sample_rate,
int frames_per_buffer);
///
// Called when a PCM packet is received for the stream identified by
// |audio_stream_id|. |data| is an array representing the raw PCM data as a
// floating point type, i.e. 4-byte value(s). |frames| is the number of frames
// in the PCM packet. |pts| is the presentation timestamp (in milliseconds
// since the Unix Epoch) and represents the time at which the decompressed
// packet should be presented to the user. Based on |frames| and the
// |channel_layout| value passed to OnAudioStreamStarted you can calculate the
// size of the |data| array in bytes.
///
void(CEF_CALLBACK* on_audio_stream_packet)(struct _cef_audio_handler_t* self,
struct _cef_browser_t* browser,
int audio_stream_id,
const float** data,
int frames,
int64 pts);
///
// Called when the stream identified by |audio_stream_id| has stopped.
// OnAudioSteamStopped will always be called after OnAudioStreamStarted; both
// functions may be called multiple times for the same stream.
///
void(CEF_CALLBACK* on_audio_stream_stopped)(struct _cef_audio_handler_t* self,
struct _cef_browser_t* browser,
int audio_stream_id);
} cef_audio_handler_t;
#ifdef __cplusplus
}
#endif
#endif // CEF_INCLUDE_CAPI_CEF_AUDIO_HANDLER_CAPI_H_

View File

@@ -33,14 +33,13 @@
// by hand. See the translator.README.txt file in the tools directory for
// more information.
//
// $hash=c8b6ce6786bb8369c3d9bb9e932a115fb379b145$
// $hash=f7ae1e9818919482e8eb526badb9013b039f0558$
//
#ifndef CEF_INCLUDE_CAPI_CEF_CLIENT_CAPI_H_
#define CEF_INCLUDE_CAPI_CEF_CLIENT_CAPI_H_
#pragma once
#include "include/capi/cef_audio_handler_capi.h"
#include "include/capi/cef_base_capi.h"
#include "include/capi/cef_context_menu_handler_capi.h"
#include "include/capi/cef_dialog_handler_capi.h"
@@ -70,12 +69,6 @@ typedef struct _cef_client_t {
///
cef_base_ref_counted_t base;
///
// Return the handler for audio rendering events.
///
struct _cef_audio_handler_t*(CEF_CALLBACK* get_audio_handler)(
struct _cef_client_t* self);
///
// Return the handler for context menus. If no handler is provided the default
// implementation will be used.

View File

@@ -34,7 +34,7 @@
// implementations. See the translator.README.txt file in the tools directory
// for more information.
//
// $hash=23774ff0da7e40bab8244ff4b661b1d9fed24107$
// $hash=420dfefdb6497faaa2c0280ad70e66e0b7d37dfc$
//
#ifndef CEF_INCLUDE_API_HASH_H_
@@ -47,13 +47,13 @@
// way that may cause binary incompatibility with other builds. The universal
// hash value will change if any platform is affected whereas the platform hash
// values will change only if that particular platform is affected.
#define CEF_API_HASH_UNIVERSAL "d04fc15ff27c5a8ee71fee4a88383e5c4bbb7b10"
#define CEF_API_HASH_UNIVERSAL "440be38b46f14493a9981a1d9282742a83b9070e"
#if defined(OS_WIN)
#define CEF_API_HASH_PLATFORM "031426ad8eb80ee32fcf3605837cff8d3bbae3a4"
#define CEF_API_HASH_PLATFORM "e5386095f03ffc204bdeacac7a13275918c66eb1"
#elif defined(OS_MACOSX)
#define CEF_API_HASH_PLATFORM "47422c9703f7c32013642707b976d299c72f42cb"
#define CEF_API_HASH_PLATFORM "1c87ca78fce1bd15cd78f33f8f4e1763d616556a"
#elif defined(OS_LINUX)
#define CEF_API_HASH_PLATFORM "d333fdd7eee13c06f58e586513061ce121121e0b"
#define CEF_API_HASH_PLATFORM "0050dbeab6fe92dd6b954241224cb67c9d9ac23e"
#endif
#ifdef __cplusplus

View File

@@ -1,98 +0,0 @@
// Copyright (c) 2018 Marshall A. Greenblatt. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the name Chromium Embedded
// Framework nor the names of its contributors may be used to endorse
// or promote products derived from this software without specific prior
// written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// ---------------------------------------------------------------------------
//
// The contents of this file must follow a specific format in order to
// support the CEF translator tool. See the translator.README.txt file in the
// tools directory for more information.
//
#ifndef CEF_INCLUDE_CEF_AUDIO_HANDLER_H_
#define CEF_INCLUDE_CEF_AUDIO_HANDLER_H_
#pragma once
#include "include/cef_base.h"
#include "include/cef_browser.h"
///
// Implement this interface to handle audio events
// All methods will be called on the UI thread
///
/*--cef(source=client)--*/
class CefAudioHandler : public virtual CefBaseRefCounted {
public:
typedef cef_channel_layout_t ChannelLayout;
///
// Called when the stream identified by |audio_stream_id| has started.
// |audio_stream_id| will uniquely identify the stream across all future
// CefAudioHandler callbacks. OnAudioSteamStopped will always be called after
// OnAudioStreamStarted; both methods may be called multiple times for the
// same stream. |channels| is the number of channels, |channel_layout| is the
// layout of the channels and |sample_rate| is the stream sample rate.
// |frames_per_buffer| is the maximum number of frames that will occur in the
// PCM packet passed to OnAudioStreamPacket.
///
/*--cef()--*/
virtual void OnAudioStreamStarted(CefRefPtr<CefBrowser> browser,
int audio_stream_id,
int channels,
ChannelLayout channel_layout,
int sample_rate,
int frames_per_buffer) = 0;
///
// Called when a PCM packet is received for the stream identified by
// |audio_stream_id|. |data| is an array representing the raw PCM data as a
// floating point type, i.e. 4-byte value(s). |frames| is the number of frames
// in the PCM packet. |pts| is the presentation timestamp (in milliseconds
// since the Unix Epoch) and represents the time at which the decompressed
// packet should be presented to the user. Based on |frames| and the
// |channel_layout| value passed to OnAudioStreamStarted you can calculate the
// size of the |data| array in bytes.
///
/*--cef()--*/
virtual void OnAudioStreamPacket(CefRefPtr<CefBrowser> browser,
int audio_stream_id,
const float** data,
int frames,
int64 pts) = 0;
///
// Called when the stream identified by |audio_stream_id| has stopped.
// OnAudioSteamStopped will always be called after OnAudioStreamStarted; both
// methods may be called multiple times for the same stream.
///
/*--cef()--*/
virtual void OnAudioStreamStopped(CefRefPtr<CefBrowser> browser,
int audio_stream_id) = 0;
};
#endif // CEF_INCLUDE_CEF_AUDIO_HANDLER_H_

View File

@@ -38,7 +38,6 @@
#define CEF_INCLUDE_CEF_CLIENT_H_
#pragma once
#include "include/cef_audio_handler.h"
#include "include/cef_base.h"
#include "include/cef_context_menu_handler.h"
#include "include/cef_dialog_handler.h"
@@ -61,12 +60,6 @@
/*--cef(source=client,no_debugct_check)--*/
class CefClient : public virtual CefBaseRefCounted {
public:
///
// Return the handler for audio rendering events.
///
/*--cef()--*/
virtual CefRefPtr<CefAudioHandler> GetAudioHandler() { return NULL; }
///
// Return the handler for context menus. If no handler is provided the default
// implementation will be used.

View File

@@ -2972,117 +2972,6 @@ typedef struct _cef_composition_underline_t {
int thick;
} cef_composition_underline_t;
///
// Enumerates the various representations of the ordering of audio channels.
// Logged to UMA, so never reuse a value, always add new/greater ones!
// See media\base\channel_layout.h
///
typedef enum {
CEF_CHANNEL_LAYOUT_NONE = 0,
CEF_CHANNEL_LAYOUT_UNSUPPORTED = 1,
// Front C
CEF_CHANNEL_LAYOUT_MONO = 2,
// Front L, Front R
CEF_CHANNEL_LAYOUT_STEREO = 3,
// Front L, Front R, Back C
CEF_CHANNEL_LAYOUT_2_1 = 4,
// Front L, Front R, Front C
CEF_CHANNEL_LAYOUT_SURROUND = 5,
// Front L, Front R, Front C, Back C
CEF_CHANNEL_LAYOUT_4_0 = 6,
// Front L, Front R, Side L, Side R
CEF_CHANNEL_LAYOUT_2_2 = 7,
// Front L, Front R, Back L, Back R
CEF_CHANNEL_LAYOUT_QUAD = 8,
// Front L, Front R, Front C, Side L, Side R
CEF_CHANNEL_LAYOUT_5_0 = 9,
// Front L, Front R, Front C, LFE, Side L, Side R
CEF_CHANNEL_LAYOUT_5_1 = 10,
// Front L, Front R, Front C, Back L, Back R
CEF_CHANNEL_LAYOUT_5_0_BACK = 11,
// Front L, Front R, Front C, LFE, Back L, Back R
CEF_CHANNEL_LAYOUT_5_1_BACK = 12,
// Front L, Front R, Front C, Side L, Side R, Back L, Back R
CEF_CHANNEL_LAYOUT_7_0 = 13,
// Front L, Front R, Front C, LFE, Side L, Side R, Back L, Back R
CEF_CHANNEL_LAYOUT_7_1 = 14,
// Front L, Front R, Front C, LFE, Side L, Side R, Front LofC, Front RofC
CEF_CHANNEL_LAYOUT_7_1_WIDE = 15,
// Stereo L, Stereo R
CEF_CHANNEL_LAYOUT_STEREO_DOWNMIX = 16,
// Stereo L, Stereo R, LFE
CEF_CHANNEL_LAYOUT_2POINT1 = 17,
// Stereo L, Stereo R, Front C, LFE
CEF_CHANNEL_LAYOUT_3_1 = 18,
// Stereo L, Stereo R, Front C, Rear C, LFE
CEF_CHANNEL_LAYOUT_4_1 = 19,
// Stereo L, Stereo R, Front C, Side L, Side R, Back C
CEF_CHANNEL_LAYOUT_6_0 = 20,
// Stereo L, Stereo R, Side L, Side R, Front LofC, Front RofC
CEF_CHANNEL_LAYOUT_6_0_FRONT = 21,
// Stereo L, Stereo R, Front C, Rear L, Rear R, Rear C
CEF_CHANNEL_LAYOUT_HEXAGONAL = 22,
// Stereo L, Stereo R, Front C, LFE, Side L, Side R, Rear Center
CEF_CHANNEL_LAYOUT_6_1 = 23,
// Stereo L, Stereo R, Front C, LFE, Back L, Back R, Rear Center
CEF_CHANNEL_LAYOUT_6_1_BACK = 24,
// Stereo L, Stereo R, Side L, Side R, Front LofC, Front RofC, LFE
CEF_CHANNEL_LAYOUT_6_1_FRONT = 25,
// Front L, Front R, Front C, Side L, Side R, Front LofC, Front RofC
CEF_CHANNEL_LAYOUT_7_0_FRONT = 26,
// Front L, Front R, Front C, LFE, Back L, Back R, Front LofC, Front RofC
CEF_CHANNEL_LAYOUT_7_1_WIDE_BACK = 27,
// Front L, Front R, Front C, Side L, Side R, Rear L, Back R, Back C.
CEF_CHANNEL_LAYOUT_OCTAGONAL = 28,
// Channels are not explicitly mapped to speakers.
CEF_CHANNEL_LAYOUT_DISCRETE = 29,
// Front L, Front R, Front C. Front C contains the keyboard mic audio. This
// layout is only intended for input for WebRTC. The Front C channel
// is stripped away in the WebRTC audio input pipeline and never seen outside
// of that.
CEF_CHANNEL_LAYOUT_STEREO_AND_KEYBOARD_MIC = 30,
// Front L, Front R, Side L, Side R, LFE
CEF_CHANNEL_LAYOUT_4_1_QUAD_SIDE = 31,
// Actual channel layout is specified in the bitstream and the actual channel
// count is unknown at Chromium media pipeline level (useful for audio
// pass-through mode).
CEF_CHANNEL_LAYOUT_BITSTREAM = 32,
// Max value, must always equal the largest entry ever logged.
CEF_CHANNEL_LAYOUT_MAX = CEF_CHANNEL_LAYOUT_BITSTREAM
} cef_channel_layout_t;
#ifdef __cplusplus
}
#endif

View File

@@ -1,107 +0,0 @@
// Copyright (c) 2018 The Chromium Embedded Framework Authors.
// Portions copyright (c) 2011 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 "libcef/browser/audio_mirror_destination.h"
#include "libcef/browser/audio_push_sink.h"
#include "base/task/post_task.h"
#include "content/public/browser/browser_task_traits.h"
#include "media/base/bind_to_current_loop.h"
CefAudioMirrorDestination::CefAudioMirrorDestination(
CefRefPtr<CefBrowserHostImpl> browser,
CefRefPtr<CefAudioHandler> cef_audio_handler,
content::AudioMirroringManager* mirroring_manager)
: browser_(browser),
cef_audio_handler_(cef_audio_handler),
mirroring_manager_(mirroring_manager) {
DCHECK(mirroring_manager_);
thread_checker_.DetachFromThread();
}
void CefAudioMirrorDestination::Start() {
DCHECK(thread_checker_.CalledOnValidThread());
base::PostTaskWithTraits(
FROM_HERE, {content::BrowserThread::IO},
base::BindOnce(&content::AudioMirroringManager::StartMirroring,
base::Unretained(mirroring_manager_),
base::RetainedRef(this)));
}
void CefAudioMirrorDestination::Stop() {
DCHECK(thread_checker_.CalledOnValidThread());
base::PostTaskWithTraits(
FROM_HERE, {content::BrowserThread::IO},
base::BindOnce(&content::AudioMirroringManager::StopMirroring,
base::Unretained(mirroring_manager_),
base::RetainedRef(this)));
}
// Asynchronously query whether this MirroringDestination wants to consume
// audio sourced from each of the |candidates|. |results_callback| is run
// to indicate which of them (or none) should have audio routed to this
// MirroringDestination. The second parameter of |results_callback|
// indicates whether the MirroringDestination wants either: 1) exclusive
// access to a diverted audio flow versus 2) a duplicate copy of the audio
// flow. |results_callback| must be run on the same thread as the one that
// called QueryForMatches().
void CefAudioMirrorDestination::QueryForMatches(
const std::set<content::GlobalFrameRoutingId>& candidates,
MatchesCallback results_callback) {
base::PostTaskWithTraits(
FROM_HERE, {content::BrowserThread::UI},
base::BindOnce(&CefAudioMirrorDestination::QueryForMatchesOnUIThread,
base::RetainedRef(this), candidates,
media::BindToCurrentLoop(std::move(results_callback))));
}
void CefAudioMirrorDestination::QueryForMatchesOnUIThread(
const std::set<content::GlobalFrameRoutingId>& candidates,
MatchesCallback results_callback) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
std::set<content::GlobalFrameRoutingId> matches;
for (auto& candidate : candidates) {
CefRefPtr<CefBrowserHostImpl> browser =
CefBrowserHostImpl::GetBrowserForFrameRoute(candidate.child_id,
candidate.frame_routing_id);
if (browser == browser_) {
matches.insert(candidate);
}
}
std::move(results_callback).Run(matches, true);
}
// Create a consumer of audio data in the format specified by |params|, and
// connect it as an input to mirroring. This is used to provide
// MirroringDestination with exclusive access to pull the audio flow from
// the source. When Close() is called on the returned AudioOutputStream, the
// input is disconnected and the object becomes invalid.
media::AudioOutputStream* CefAudioMirrorDestination::AddInput(
const media::AudioParameters& params) {
// TODO Check and add usage on CEF
return nullptr;
}
// Create a consumer of audio data in the format specified by |params|, and
// connect it as an input to mirroring. This is used to provide
// MirroringDestination with duplicate audio data, which is pushed from the
// main audio flow. When Close() is called on the returned AudioPushSink,
// the input is disconnected and the object becomes invalid.
media::AudioPushSink* CefAudioMirrorDestination::AddPushInput(
const media::AudioParameters& params) {
return new CefAudioPushSink(
params, browser_, cef_audio_handler_,
base::Bind(&CefAudioMirrorDestination::ReleasePushInput,
base::RetainedRef(this)));
}
void CefAudioMirrorDestination::ReleasePushInput(CefAudioPushSink* sink) {
delete sink;
}

View File

@@ -1,83 +0,0 @@
// Copyright (c) 2018 The Chromium Embedded Framework Authors.
// Portions copyright (c) 2011 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 CEF_LIBCEF_BROWSER_AUDIO_MIRROR_DESTINATION_H_
#define CEF_LIBCEF_BROWSER_AUDIO_MIRROR_DESTINATION_H_
#pragma once
#include "include/cef_audio_handler.h"
#include "include/cef_base.h"
#include "libcef/browser/browser_host_impl.h"
#include "base/callback.h"
#include "base/threading/thread_checker.h"
#include "content/browser/media/capture/audio_mirroring_manager.h"
#include "media/audio/audio_io.h"
#include "media/base/audio_converter.h"
#include "media/base/audio_parameters.h"
class CefAudioPushSink;
class CefBrowserHostImpl;
class CefAudioMirrorDestination
: public base::RefCountedThreadSafe<CefAudioMirrorDestination>,
public content::AudioMirroringManager::MirroringDestination {
public:
CefAudioMirrorDestination(CefRefPtr<CefBrowserHostImpl> browser,
CefRefPtr<CefAudioHandler> cef_audio_handler,
content::AudioMirroringManager* mirroring_manager);
// Start mirroring. This needs to be triggered on the IO thread.
void Start();
// Stop mirroring. This needs to be triggered on the IO thread.
void Stop();
// Asynchronously query whether this MirroringDestination wants to consume
// audio sourced from each of the |candidates|. |results_callback| is run
// to indicate which of them (or none) should have audio routed to this
// MirroringDestination. The second parameter of |results_callback|
// indicates whether the MirroringDestination wants either: 1) exclusive
// access to a diverted audio flow versus 2) a duplicate copy of the audio
// flow. |results_callback| must be run on the same thread as the one that
// called QueryForMatches().
void QueryForMatches(
const std::set<content::GlobalFrameRoutingId>& candidates,
MatchesCallback results_callback) override;
// Create a consumer of audio data in the format specified by |params|, and
// connect it as an input to mirroring. This is used to provide
// MirroringDestination with exclusive access to pull the audio flow from
// the source. When Close() is called on the returned AudioOutputStream, the
// input is disconnected and the object becomes invalid.
media::AudioOutputStream* AddInput(
const media::AudioParameters& params) override;
// Create a consumer of audio data in the format specified by |params|, and
// connect it as an input to mirroring. This is used to provide
// MirroringDestination with duplicate audio data, which is pushed from the
// main audio flow. When Close() is called on the returned AudioPushSink,
// the input is disconnected and the object becomes invalid.
media::AudioPushSink* AddPushInput(
const media::AudioParameters& params) override;
private:
friend class base::RefCountedThreadSafe<CefAudioMirrorDestination>;
~CefAudioMirrorDestination() override = default;
void QueryForMatchesOnUIThread(
const std::set<content::GlobalFrameRoutingId>& candidates,
MatchesCallback results_callback);
void ReleasePushInput(CefAudioPushSink* sink);
CefRefPtr<CefBrowserHostImpl> browser_;
CefRefPtr<CefAudioHandler> cef_audio_handler_;
content::AudioMirroringManager* mirroring_manager_;
base::ThreadChecker thread_checker_;
};
#endif // CEF_LIBCEF_BROWSER_AUDIO_MIRROR_DESTINATION_H_

View File

@@ -1,172 +0,0 @@
// Copyright (c) 2018 The Chromium Embedded Framework Authors.
// Portions copyright (c) 2011 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 "libcef/browser/audio_push_sink.h"
#include "libcef/browser/thread_util.h"
#include "base/bind.h"
#include "base/logging.h"
#include "media/base/audio_sample_types.h"
#include "media/base/data_buffer.h"
using namespace media;
namespace {
cef_channel_layout_t TranslateChannelLayout(ChannelLayout channel) {
switch (channel) {
case CHANNEL_LAYOUT_UNSUPPORTED:
return CEF_CHANNEL_LAYOUT_UNSUPPORTED;
case CHANNEL_LAYOUT_MONO:
return CEF_CHANNEL_LAYOUT_MONO;
case CHANNEL_LAYOUT_STEREO:
return CEF_CHANNEL_LAYOUT_STEREO;
case CHANNEL_LAYOUT_2_1:
return CEF_CHANNEL_LAYOUT_2_1;
case CHANNEL_LAYOUT_SURROUND:
return CEF_CHANNEL_LAYOUT_SURROUND;
case CHANNEL_LAYOUT_4_0:
return CEF_CHANNEL_LAYOUT_4_0;
case CHANNEL_LAYOUT_2_2:
return CEF_CHANNEL_LAYOUT_2_2;
case CHANNEL_LAYOUT_QUAD:
return CEF_CHANNEL_LAYOUT_QUAD;
case CHANNEL_LAYOUT_5_0:
return CEF_CHANNEL_LAYOUT_5_0;
case CHANNEL_LAYOUT_5_1:
return CEF_CHANNEL_LAYOUT_5_1;
case CHANNEL_LAYOUT_5_0_BACK:
return CEF_CHANNEL_LAYOUT_5_0_BACK;
case CHANNEL_LAYOUT_5_1_BACK:
return CEF_CHANNEL_LAYOUT_5_1_BACK;
case CHANNEL_LAYOUT_7_0:
return CEF_CHANNEL_LAYOUT_7_0;
case CHANNEL_LAYOUT_7_1:
return CEF_CHANNEL_LAYOUT_7_1;
case CHANNEL_LAYOUT_7_1_WIDE:
return CEF_CHANNEL_LAYOUT_7_1_WIDE;
case CHANNEL_LAYOUT_STEREO_DOWNMIX:
return CEF_CHANNEL_LAYOUT_STEREO_DOWNMIX;
case CHANNEL_LAYOUT_2POINT1:
return CEF_CHANNEL_LAYOUT_2POINT1;
case CHANNEL_LAYOUT_3_1:
return CEF_CHANNEL_LAYOUT_3_1;
case CHANNEL_LAYOUT_4_1:
return CEF_CHANNEL_LAYOUT_4_1;
case CHANNEL_LAYOUT_6_0:
return CEF_CHANNEL_LAYOUT_6_0;
case CHANNEL_LAYOUT_6_0_FRONT:
return CEF_CHANNEL_LAYOUT_6_0_FRONT;
case CHANNEL_LAYOUT_HEXAGONAL:
return CEF_CHANNEL_LAYOUT_HEXAGONAL;
case CHANNEL_LAYOUT_6_1:
return CEF_CHANNEL_LAYOUT_6_1;
case CHANNEL_LAYOUT_6_1_BACK:
return CEF_CHANNEL_LAYOUT_6_1_BACK;
case CHANNEL_LAYOUT_6_1_FRONT:
return CEF_CHANNEL_LAYOUT_6_1_FRONT;
case CHANNEL_LAYOUT_7_0_FRONT:
return CEF_CHANNEL_LAYOUT_7_0_FRONT;
case CHANNEL_LAYOUT_7_1_WIDE_BACK:
return CEF_CHANNEL_LAYOUT_7_1_WIDE_BACK;
case CHANNEL_LAYOUT_OCTAGONAL:
return CEF_CHANNEL_LAYOUT_OCTAGONAL;
case CHANNEL_LAYOUT_DISCRETE:
return CEF_CHANNEL_LAYOUT_DISCRETE;
case CHANNEL_LAYOUT_STEREO_AND_KEYBOARD_MIC:
return CEF_CHANNEL_LAYOUT_STEREO_AND_KEYBOARD_MIC;
case CHANNEL_LAYOUT_4_1_QUAD_SIDE:
return CEF_CHANNEL_LAYOUT_4_1_QUAD_SIDE;
case CHANNEL_LAYOUT_BITSTREAM:
return CEF_CHANNEL_LAYOUT_BITSTREAM;
case CHANNEL_LAYOUT_NONE:
return CEF_CHANNEL_LAYOUT_NONE;
}
return CEF_CHANNEL_LAYOUT_NONE;
}
} // namespace
int CefAudioPushSink::audio_stream_id = 0;
CefAudioPushSink::CefAudioPushSink(const AudioParameters& params,
CefRefPtr<CefBrowserHostImpl> browser,
CefRefPtr<CefAudioHandler> cef_audio_handler,
const CloseCallback& callback)
: params_(params),
browser_(browser),
cef_audio_handler_(cef_audio_handler),
close_callback_(callback),
stop_stream_(false),
audio_stream_id_(++audio_stream_id) {
// Verify that our enum matches Chromium's values.
static_assert(
static_cast<int>(CEF_CHANNEL_LAYOUT_MAX) ==
static_cast<int>(CHANNEL_LAYOUT_MAX),
"cef_channel_layout_t must match the ChannelLayout enum in Chromium");
DCHECK(params_.IsValid());
DCHECK(browser);
DCHECK(cef_audio_handler);
// VAOS can be constructed on any thread, but will DCHECK that all
// AudioOutputStream methods are called from the same thread.
thread_checker_.DetachFromThread();
base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::UI},
base::BindOnce(&CefAudioPushSink::InitOnUIThread,
base::Unretained(this)));
}
CefAudioPushSink::~CefAudioPushSink() = default;
void CefAudioPushSink::InitOnUIThread() {
DCHECK(thread_checker_.CalledOnValidThread());
cef_audio_handler_->OnAudioStreamStarted(
browser_.get(), audio_stream_id_, params_.channels(),
TranslateChannelLayout(params_.channel_layout()), params_.sample_rate(),
params_.frames_per_buffer());
}
void CefAudioPushSink::OnData(std::unique_ptr<media::AudioBus> source,
base::TimeTicks reference_time) {
// early exit if stream already stopped
if (stop_stream_)
return;
if (!CEF_CURRENTLY_ON_UIT()) {
CEF_POST_TASK(CEF_UIT, base::BindOnce(&CefAudioPushSink::OnData,
base::Unretained(this),
std::move(source), reference_time));
return;
}
const int channels = source->channels();
std::vector<const float*> data(channels);
for (int c = 0; c < channels; ++c) {
data[c] = source->channel(c);
}
// Add the packet to the buffer.
base::TimeDelta pts = reference_time - base::TimeTicks::UnixEpoch();
cef_audio_handler_->OnAudioStreamPacket(browser_.get(), audio_stream_id_,
data.data(), source->frames(),
pts.InMilliseconds());
}
void CefAudioPushSink::Close() {
if (!CEF_CURRENTLY_ON_UIT()) {
CEF_POST_TASK(CEF_UIT, base::BindOnce(&CefAudioPushSink::Close,
base::Unretained(this)));
return;
}
if (!stop_stream_) {
stop_stream_ = true;
cef_audio_handler_->OnAudioStreamStopped(browser_.get(), audio_stream_id_);
if (!close_callback_.is_null()) {
std::move(close_callback_).Run(this);
}
}
}

View File

@@ -1,54 +0,0 @@
// Copyright (c) 2018 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 CEF_LIBCEF_BROWSER_AUDIO_PUSH_SINK_H_
#define CEF_LIBCEF_BROWSER_AUDIO_PUSH_SINK_H_
#pragma once
#include "include/cef_audio_handler.h"
#include "include/cef_base.h"
#include "libcef/browser/browser_host_impl.h"
#include "base/callback.h"
#include "base/memory/weak_ptr.h"
#include "base/message_loop/message_loop.h"
#include "base/threading/thread_checker.h"
#include "media/audio/audio_io.h"
#include "media/base/audio_converter.h"
#include "media/base/audio_parameters.h"
#include "media/base/channel_layout.h"
class CefAudioPushSink : public media::AudioPushSink {
public:
typedef base::Callback<void(CefAudioPushSink* sink)> CloseCallback;
CefAudioPushSink(const media::AudioParameters& params,
CefRefPtr<CefBrowserHostImpl> browser,
CefRefPtr<CefAudioHandler> cef_audio_handler,
const CloseCallback& callback);
virtual ~CefAudioPushSink();
void OnData(std::unique_ptr<media::AudioBus> source,
base::TimeTicks reference_time) override;
void Close() override;
private:
void InitOnUIThread();
const media::AudioParameters params_;
CefRefPtr<CefBrowserHostImpl> browser_;
CefRefPtr<CefAudioHandler> cef_audio_handler_;
CloseCallback close_callback_;
base::ThreadChecker thread_checker_;
bool stop_stream_;
int audio_stream_id_;
static int audio_stream_id;
DISALLOW_COPY_AND_ASSIGN(CefAudioPushSink);
};
#endif // CEF_LIBCEF_BROWSER_AUDIO_PUSH_SINK_H_

View File

@@ -7,6 +7,7 @@
#include "chrome/browser/content_settings/cookie_settings_factory.h"
#include "chrome/browser/plugins/plugin_prefs_factory.h"
#include "chrome/browser/profiles/renderer_updater_factory.h"
#include "chrome/browser/spellchecker/spellcheck_factory.h"
#include "chrome/browser/themes/theme_service_factory.h"
#include "chrome/browser/ui/prefs/prefs_tab_helper.h"
@@ -20,6 +21,7 @@ void EnsureBrowserContextKeyedServiceFactoriesBuilt() {
CookieSettingsFactory::GetInstance();
PluginPrefsFactory::GetInstance();
PrefsTabHelper::GetServiceInstance();
RendererUpdaterFactory::GetInstance();
SpellcheckServiceFactory::GetInstance();
ThemeServiceFactory::GetInstance();

View File

@@ -8,7 +8,6 @@
#include <string>
#include <utility>
#include "libcef/browser/audio_mirror_destination.h"
#include "libcef/browser/browser_context.h"
#include "libcef/browser/browser_info.h"
#include "libcef/browser/browser_info_manager.h"
@@ -49,7 +48,6 @@
#include "chrome/browser/ui/prefs/prefs_tab_helper.h"
#include "components/zoom/zoom_controller.h"
#include "content/browser/gpu/compositor_util.h"
#include "content/browser/media/capture/audio_mirroring_manager.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/common/widget_messages.h"
#include "content/public/browser/desktop_media_id.h"
@@ -1543,8 +1541,6 @@ void CefBrowserHostImpl::DestroyBrowser() {
menu_manager_->Destroy();
DestroyExtensionHost();
StopAudioMirroring();
// Notify any observers that may have state associated with this browser.
for (auto& observer : observers_)
observer.OnBrowserDestroyed(this);
@@ -2768,28 +2764,6 @@ bool CefBrowserHostImpl::HasObserver(Observer* observer) const {
return observers_.HasObserver(observer);
}
bool CefBrowserHostImpl::StartAudioMirroring() {
if (client_.get()) {
CefRefPtr<CefAudioHandler> audio_handler = client_->GetAudioHandler();
if (audio_handler.get()) {
audio_mirror_destination_ = new CefAudioMirrorDestination(
this, audio_handler, content::AudioMirroringManager::GetInstance());
audio_mirror_destination_->Start();
return true;
}
}
return false;
}
bool CefBrowserHostImpl::StopAudioMirroring() {
if (audio_mirror_destination_.get()) {
audio_mirror_destination_->Stop();
audio_mirror_destination_.reset();
return true;
}
return false;
}
CefBrowserHostImpl::NavigationLock::NavigationLock(
CefRefPtr<CefBrowserHostImpl> browser)
: browser_(browser) {
@@ -2913,8 +2887,6 @@ CefBrowserHostImpl::CefBrowserHostImpl(
// Make sure RenderViewCreated is called at least one time.
RenderViewCreated(web_contents->GetRenderViewHost());
StartAudioMirroring();
// Associate the platform delegate with this browser.
platform_delegate_->BrowserCreated(this);
}

View File

@@ -15,7 +15,6 @@
#include "include/cef_client.h"
#include "include/cef_frame.h"
#include "include/views/cef_browser_view.h"
#include "libcef/browser/audio_mirror_destination.h"
#include "libcef/browser/browser_info.h"
#include "libcef/browser/file_dialog_manager.h"
#include "libcef/browser/frame_host_impl.h"
@@ -49,7 +48,6 @@ class Widget;
}
#endif // defined(USE_AURA)
class CefAudioMirrorDestination;
class CefBrowserInfo;
class CefBrowserPlatformDelegate;
class CefDevToolsFrontend;
@@ -502,10 +500,6 @@ class CefBrowserHostImpl : public CefBrowserHost,
void AddObserver(Observer* observer);
void RemoveObserver(Observer* observer);
bool HasObserver(Observer* observer) const;
bool StartAudioMirroring();
bool StopAudioMirroring();
class NavigationLock final {
private:
friend class CefBrowserHostImpl;
@@ -668,9 +662,6 @@ class CefBrowserHostImpl : public CefBrowserHost,
CefRefPtr<CefExtension> extension_;
bool is_background_host_ = false;
// Used to mirror audio streams
scoped_refptr<CefAudioMirrorDestination> audio_mirror_destination_;
// Used with auto-resize.
bool auto_resize_enabled_ = false;
gfx::Size auto_resize_min_;

View File

@@ -61,10 +61,14 @@
#include "chrome/browser/plugins/plugin_response_interceptor_url_loader_throttle.h"
#include "chrome/browser/plugins/plugin_utils.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/renderer_updater.h"
#include "chrome/browser/profiles/renderer_updater_factory.h"
#include "chrome/browser/renderer_host/pepper/chrome_browser_pepper_host_factory.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/constants.mojom.h"
#include "chrome/common/google_url_loader_throttle.h"
#include "chrome/common/pref_names.h"
#include "chrome/common/webui_url_constants.h"
#include "chrome/grit/browser_resources.h"
#include "chrome/grit/generated_resources.h"
@@ -76,6 +80,7 @@
#include "components/services/heap_profiling/public/mojom/constants.mojom.h"
#include "components/services/pdf_compositor/public/cpp/pdf_compositor_service_factory.h"
#include "components/services/pdf_compositor/public/mojom/pdf_compositor.mojom.h"
#include "components/variations/variations_http_header_provider.h"
#include "components/version_info/version_info.h"
#include "content/browser/frame_host/navigation_handle_impl.h"
#include "content/browser/frame_host/render_frame_host_impl.h"
@@ -557,8 +562,10 @@ void CefContentBrowserClient::RenderProcessWillLaunch(
host->RemoveObserver(CefBrowserInfoManager::GetInstance());
host->AddObserver(CefBrowserInfoManager::GetInstance());
host->Send(
new CefProcessMsg_SetIsIncognitoProcess(profile->IsOffTheRecord()));
// Forwards dynamic parameters to CefRenderThreadObserver.
Profile* original_profile = profile->GetOriginalProfile();
RendererUpdaterFactory::GetForProfile(original_profile)
->InitializeRenderer(host);
service_manager::mojom::ServicePtrInfo service;
*service_request = mojo::MakeRequest(&service);
@@ -1147,7 +1154,7 @@ CefContentBrowserClient::CreateThrottlesForNavigation(
std::vector<std::unique_ptr<content::URLLoaderThrottle>>
CefContentBrowserClient::CreateURLLoaderThrottles(
const network::ResourceRequest& request,
content::BrowserContext* resource_context,
content::BrowserContext* browser_context,
const base::RepeatingCallback<content::WebContents*()>& wc_getter,
content::NavigationUIData* navigation_ui_data,
int frame_tree_node_id) {
@@ -1155,7 +1162,19 @@ CefContentBrowserClient::CreateURLLoaderThrottles(
// Used to substitute View ID for PDF contents when using the PDF plugin.
result.push_back(std::make_unique<PluginResponseInterceptorURLLoaderThrottle>(
resource_context, request.resource_type, frame_tree_node_id));
browser_context, request.resource_type, frame_tree_node_id));
Profile* profile = Profile::FromBrowserContext(browser_context);
bool is_off_the_record = profile->IsOffTheRecord();
chrome::mojom::DynamicParams dynamic_params = {
profile->GetPrefs()->GetBoolean(prefs::kForceGoogleSafeSearch),
profile->GetPrefs()->GetInteger(prefs::kForceYouTubeRestrict),
profile->GetPrefs()->GetString(prefs::kAllowedDomainsForApps),
variations::VariationsHttpHeaderProvider::GetInstance()
->GetClientDataHeader(false /* is_signed_in */)};
result.push_back(std::make_unique<GoogleURLLoaderThrottle>(
is_off_the_record, std::move(dynamic_params)));
return result;
}

View File

@@ -131,7 +131,7 @@ class CefContentBrowserClient : public content::ContentBrowserClient {
std::vector<std::unique_ptr<content::URLLoaderThrottle>>
CreateURLLoaderThrottles(
const network::ResourceRequest& request,
content::BrowserContext* resource_context,
content::BrowserContext* browser_context,
const base::RepeatingCallback<content::WebContents*()>& wc_getter,
content::NavigationUIData* navigation_ui_data,
int frame_tree_node_id) override;

View File

@@ -1224,13 +1224,6 @@ void InitOnUIThread(
// |frame| may be null for service worker requests.
if (frame) {
#if DCHECK_IS_ON()
if (frame_tree_node_id >= 0) {
// Sanity check that we ended up with the expected frame.
DCHECK_EQ(frame_tree_node_id, frame->GetFrameTreeNodeId());
}
#endif
// May return nullptr for requests originating from guest views.
browserPtr = CefBrowserHostImpl::GetBrowserForHost(frame);
if (browserPtr) {

View File

@@ -259,7 +259,8 @@ CefRenderWidgetHostViewOSR::~CefRenderWidgetHostViewOSR() {
// Marking the DelegatedFrameHost as removed from the window hierarchy is
// necessary to remove all connections to its old ui::Compositor.
if (is_showing_)
delegated_frame_host_->WasHidden();
delegated_frame_host_->WasHidden(
content::DelegatedFrameHost::HiddenCause::kOther);
delegated_frame_host_->DetachFromCompositor();
delegated_frame_host_.reset(nullptr);
@@ -347,7 +348,8 @@ void CefRenderWidgetHostViewOSR::Hide() {
if (render_widget_host_)
render_widget_host_->WasHidden();
GetDelegatedFrameHost()->WasHidden();
GetDelegatedFrameHost()->WasHidden(
content::DelegatedFrameHost::HiddenCause::kOther);
GetDelegatedFrameHost()->DetachFromCompositor();
}

View File

@@ -31,6 +31,7 @@
#include "chrome/browser/themes/theme_service.h"
#include "chrome/browser/ui/webui/print_preview/sticky_settings.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/net/safe_search_util.h"
#include "chrome/common/pref_names.h"
#include "chrome/grit/locale_settings.h"
#include "components/certificate_transparency/pref_names.h"
@@ -227,6 +228,10 @@ std::unique_ptr<PrefService> CreatePrefService(Profile* profile,
// Print preferences.
// Based on ProfileImpl::RegisterProfilePrefs.
registry->RegisterBooleanPref(prefs::kForceGoogleSafeSearch, false);
registry->RegisterIntegerPref(prefs::kForceYouTubeRestrict,
safe_search_util::YOUTUBE_RESTRICT_OFF);
registry->RegisterStringPref(prefs::kAllowedDomainsForApps, std::string());
registry->RegisterBooleanPref(prefs::kPrintingEnabled, true);
registry->RegisterBooleanPref(prefs::kPrintPreviewDisabled,
!extensions::PrintPreviewEnabled());

View File

@@ -268,6 +268,10 @@ void CefWindowView::CreateWidget() {
if (is_menu) {
// Don't clip the window to parent bounds.
params.type = views::Widget::InitParams::TYPE_MENU;
// Don't set "always on top" for the window.
params.z_order = ui::ZOrderLevel::kNormal;
can_activate = can_activate_menu;
if (can_activate_menu)
params.activatable = views::Widget::InitParams::ACTIVATABLE_YES;
@@ -409,12 +413,10 @@ views::NonClientFrameView* CefWindowView::CreateNonClientFrameView(
// DesktopNativeWidgetAura::CreateNonClientFrameView() returns
// NativeFrameView by default. Extend that type.
return new NativeFrameViewEx(widget, this);
} else {
// Widget::CreateNonClientFrameView() returns CustomFrameView by default.
// Need to extend CustomFrameView on this platform.
NOTREACHED() << "Platform does not use NativeFrameView";
}
// Use Chromium provided CustomFrameView. In case if we would like to
// customize the frame, provide own implementation.
return nullptr;
}

View File

@@ -147,11 +147,6 @@ IPC_MESSAGE_ROUTED0(CefMsg_DidStopLoading)
// Based on ChromeViewMsg_LoadBlockedPlugins.
IPC_MESSAGE_ROUTED1(CefViewMsg_LoadBlockedPlugins, std::string /* identifier */)
// Sent on process startup to indicate whether this process is running in
// incognito mode. Based on ChromeViewMsg_SetIsIncognitoProcess.
IPC_MESSAGE_CONTROL1(CefProcessMsg_SetIsIncognitoProcess,
bool /* is_incognito_processs */)
// Sent to child processes to add or remove a cross-origin whitelist entry.
IPC_MESSAGE_CONTROL2(CefProcessMsg_ModifyCrossOriginWhitelistEntry,
bool /* add */,

View File

@@ -599,13 +599,6 @@ bool CefMainDelegate::BasicStartupComplete(int* exit_code) {
features::kMimeHandlerViewInCrossProcessFrame.name);
}
if (features::kAudioServiceAudioStreams.default_state ==
base::FEATURE_ENABLED_BY_DEFAULT) {
// TODO: Add support for audio service (see issue #2755)
disable_features.push_back(
features::kAudioServiceAudioStreams.name);
}
if (!disable_features.empty()) {
DCHECK(!base::FeatureList::GetInstance());
std::string disable_features_str =

View File

@@ -81,6 +81,7 @@ buildflag_header("features") {
flags = [
"ENABLE_CEF=$enable_cef",
"IS_CEF_SANDBOX_BUILD=$is_cef_sandbox_build",
]
}

View File

@@ -4,4 +4,11 @@
declare_args() {
enable_cef = true
# Enables base target customizations necessary for distribution of the
# cef_sandbox static library. This value will be set via gn_args.py for the
# official sandbox build configurations only. DO NOT SET THIS VALUE MANUALLY
# FOR OTHER CHROMIUM/CEF BUILD CONFIGURATIONS AS ITS USE MAY HAVE SIGNIFICANT
# PERFORMANCE AND/OR SECURITY IMPLICATIONS.
is_cef_sandbox_build = false
}

View File

@@ -15,12 +15,24 @@
#include "content/public/common/service_manager_connection.h"
#include "content/public/common/simple_connection_filter.h"
#include "content/public/renderer/render_thread.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
#include "net/base/net_module.h"
#include "services/service_manager/public/cpp/binder_registry.h"
#include "services/service_manager/public/cpp/connector.h"
#include "third_party/blink/public/common/associated_interfaces/associated_interface_registry.h"
#include "third_party/blink/public/platform/web_string.h"
#include "third_party/blink/public/platform/web_url.h"
#include "third_party/blink/public/web/web_security_policy.h"
namespace {
chrome::mojom::DynamicParams* GetDynamicConfigParams() {
static base::NoDestructor<chrome::mojom::DynamicParams> dynamic_params;
return dynamic_params.get();
}
} // namespace
bool CefRenderThreadObserver::is_incognito_process_ = false;
CefRenderThreadObserver::CefRenderThreadObserver()
@@ -40,12 +52,16 @@ CefRenderThreadObserver::CefRenderThreadObserver()
CefRenderThreadObserver::~CefRenderThreadObserver() {}
// static
const chrome::mojom::DynamicParams&
CefRenderThreadObserver::GetDynamicParams() {
return *GetDynamicConfigParams();
}
bool CefRenderThreadObserver::OnControlMessageReceived(
const IPC::Message& message) {
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(CefRenderThreadObserver, message)
IPC_MESSAGE_HANDLER(CefProcessMsg_SetIsIncognitoProcess,
OnSetIsIncognitoProcess)
IPC_MESSAGE_HANDLER(CefProcessMsg_ModifyCrossOriginWhitelistEntry,
OnModifyCrossOriginWhitelistEntry)
IPC_MESSAGE_HANDLER(CefProcessMsg_ClearCrossOriginWhitelist,
@@ -55,11 +71,44 @@ bool CefRenderThreadObserver::OnControlMessageReceived(
return handled;
}
void CefRenderThreadObserver::OnSetIsIncognitoProcess(
bool is_incognito_process) {
void CefRenderThreadObserver::RegisterMojoInterfaces(
blink::AssociatedInterfaceRegistry* associated_interfaces) {
associated_interfaces->AddInterface(base::Bind(
&CefRenderThreadObserver::OnRendererConfigurationAssociatedRequest,
base::Unretained(this)));
}
void CefRenderThreadObserver::UnregisterMojoInterfaces(
blink::AssociatedInterfaceRegistry* associated_interfaces) {
associated_interfaces->RemoveInterface(
chrome::mojom::RendererConfiguration::Name_);
}
void CefRenderThreadObserver::SetInitialConfiguration(
bool is_incognito_process,
chrome::mojom::ChromeOSListenerRequest chromeos_listener_request) {
is_incognito_process_ = is_incognito_process;
}
void CefRenderThreadObserver::SetConfiguration(
chrome::mojom::DynamicParamsPtr params) {
*GetDynamicConfigParams() = std::move(*params);
}
void CefRenderThreadObserver::SetContentSettingRules(
const RendererContentSettingRules& rules) {}
void CefRenderThreadObserver::SetFieldTrialGroup(
const std::string& trial_name,
const std::string& group_name) {
content::RenderThread::Get()->SetFieldTrialGroup(trial_name, group_name);
}
void CefRenderThreadObserver::OnRendererConfigurationAssociatedRequest(
chrome::mojom::RendererConfigurationAssociatedRequest request) {
renderer_configuration_bindings_.AddBinding(this, std::move(request));
}
void CefRenderThreadObserver::OnModifyCrossOriginWhitelistEntry(
bool add,
const Cef_CrossOriginWhiteListEntry_Params& params) {

View File

@@ -9,7 +9,10 @@
#include <memory>
#include "base/compiler_specific.h"
#include "chrome/common/renderer_configuration.mojom.h"
#include "components/content_settings/core/common/content_settings.h"
#include "content/public/renderer/render_thread_observer.h"
#include "mojo/public/cpp/bindings/associated_binding_set.h"
namespace visitedlink {
class VisitedLinkSlave;
@@ -17,24 +20,45 @@ class VisitedLinkSlave;
struct Cef_CrossOriginWhiteListEntry_Params;
// This class sends and receives control messages on the renderer process.
class CefRenderThreadObserver : public content::RenderThreadObserver {
// This class sends and receives control messages in the renderer process.
class CefRenderThreadObserver : public content::RenderThreadObserver,
public chrome::mojom::RendererConfiguration {
public:
CefRenderThreadObserver();
~CefRenderThreadObserver() override;
static bool is_incognito_process() { return is_incognito_process_; }
// RenderThreadObserver implementation.
bool OnControlMessageReceived(const IPC::Message& message) override;
// Return the dynamic parameters - those that may change while the
// render process is running.
static const chrome::mojom::DynamicParams& GetDynamicParams();
visitedlink::VisitedLinkSlave* visited_link_slave() {
return visited_link_slave_.get();
}
private:
// content::RenderThreadObserver:
bool OnControlMessageReceived(const IPC::Message& message) override;
void RegisterMojoInterfaces(
blink::AssociatedInterfaceRegistry* associated_interfaces) override;
void UnregisterMojoInterfaces(
blink::AssociatedInterfaceRegistry* associated_interfaces) override;
// chrome::mojom::RendererConfiguration:
void SetInitialConfiguration(bool is_incognito_process,
chrome::mojom::ChromeOSListenerRequest
chromeos_listener_request) override;
void SetConfiguration(chrome::mojom::DynamicParamsPtr params) override;
void SetContentSettingRules(
const RendererContentSettingRules& rules) override;
void SetFieldTrialGroup(const std::string& trial_name,
const std::string& group_name) override;
void OnRendererConfigurationAssociatedRequest(
chrome::mojom::RendererConfigurationAssociatedRequest request);
// Message handlers called on the render thread.
void OnSetIsIncognitoProcess(bool is_incognito_process);
void OnModifyCrossOriginWhitelistEntry(
bool add,
const Cef_CrossOriginWhiteListEntry_Params& params);
@@ -44,6 +68,9 @@ class CefRenderThreadObserver : public content::RenderThreadObserver {
std::unique_ptr<visitedlink::VisitedLinkSlave> visited_link_slave_;
mojo::AssociatedBindingSet<chrome::mojom::RendererConfiguration>
renderer_configuration_bindings_;
DISALLOW_COPY_AND_ASSIGN(CefRenderThreadObserver);
};

View File

@@ -5,10 +5,12 @@
#include "libcef/renderer/url_loader_throttle_provider_impl.h"
#include "libcef/common/extensions/extensions_util.h"
#include "libcef/renderer/render_thread_observer.h"
#include <utility>
#include "base/feature_list.h"
#include "chrome/common/google_url_loader_throttle.h"
#include "content/public/common/content_features.h"
#include "content/public/renderer/render_frame.h"
#include "extensions/renderer/guest_view/mime_handler_view/mime_handler_view_container.h"
@@ -70,6 +72,10 @@ CefURLLoaderThrottleProviderImpl::CreateThrottles(
}
}
throttles.push_back(std::make_unique<GoogleURLLoaderThrottle>(
CefRenderThreadObserver::is_incognito_process(),
CefRenderThreadObserver::GetDynamicParams()));
return throttles;
}

View File

@@ -1,128 +0,0 @@
// Copyright (c) 2019 The Chromium Embedded Framework Authors. All rights
// reserved. Use of this source code is governed by a BSD-style license that
// can be found in the LICENSE file.
//
// ---------------------------------------------------------------------------
//
// This file was generated by the CEF translator tool. If making changes by
// hand only do so within the body of existing method and function
// implementations. See the translator.README.txt file in the tools directory
// for more information.
//
// $hash=7c55cffaa1094ff7aa49e7efbe8b4780867f6538$
//
#include "libcef_dll/cpptoc/audio_handler_cpptoc.h"
#include "libcef_dll/ctocpp/browser_ctocpp.h"
#include "libcef_dll/shutdown_checker.h"
namespace {
// MEMBER FUNCTIONS - Body may be edited by hand.
void CEF_CALLBACK
audio_handler_on_audio_stream_started(struct _cef_audio_handler_t* self,
struct _cef_browser_t* browser,
int audio_stream_id,
int channels,
cef_channel_layout_t channel_layout,
int sample_rate,
int frames_per_buffer) {
shutdown_checker::AssertNotShutdown();
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
DCHECK(self);
if (!self)
return;
// Verify param: browser; type: refptr_diff
DCHECK(browser);
if (!browser)
return;
// Execute
CefAudioHandlerCppToC::Get(self)->OnAudioStreamStarted(
CefBrowserCToCpp::Wrap(browser), audio_stream_id, channels,
channel_layout, sample_rate, frames_per_buffer);
}
void CEF_CALLBACK
audio_handler_on_audio_stream_packet(struct _cef_audio_handler_t* self,
struct _cef_browser_t* browser,
int audio_stream_id,
const float** data,
int frames,
int64 pts) {
shutdown_checker::AssertNotShutdown();
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
DCHECK(self);
if (!self)
return;
// Verify param: browser; type: refptr_diff
DCHECK(browser);
if (!browser)
return;
// Verify param: data; type: simple_byaddr
DCHECK(data);
if (!data)
return;
// Execute
CefAudioHandlerCppToC::Get(self)->OnAudioStreamPacket(
CefBrowserCToCpp::Wrap(browser), audio_stream_id, data, frames, pts);
}
void CEF_CALLBACK
audio_handler_on_audio_stream_stopped(struct _cef_audio_handler_t* self,
struct _cef_browser_t* browser,
int audio_stream_id) {
shutdown_checker::AssertNotShutdown();
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
DCHECK(self);
if (!self)
return;
// Verify param: browser; type: refptr_diff
DCHECK(browser);
if (!browser)
return;
// Execute
CefAudioHandlerCppToC::Get(self)->OnAudioStreamStopped(
CefBrowserCToCpp::Wrap(browser), audio_stream_id);
}
} // namespace
// CONSTRUCTOR - Do not edit by hand.
CefAudioHandlerCppToC::CefAudioHandlerCppToC() {
GetStruct()->on_audio_stream_started = audio_handler_on_audio_stream_started;
GetStruct()->on_audio_stream_packet = audio_handler_on_audio_stream_packet;
GetStruct()->on_audio_stream_stopped = audio_handler_on_audio_stream_stopped;
}
// DESTRUCTOR - Do not edit by hand.
CefAudioHandlerCppToC::~CefAudioHandlerCppToC() {
shutdown_checker::AssertNotShutdown();
}
template <>
CefRefPtr<CefAudioHandler> CefCppToCRefCounted<
CefAudioHandlerCppToC,
CefAudioHandler,
cef_audio_handler_t>::UnwrapDerived(CefWrapperType type,
cef_audio_handler_t* s) {
NOTREACHED() << "Unexpected class type: " << type;
return NULL;
}
template <>
CefWrapperType CefCppToCRefCounted<CefAudioHandlerCppToC,
CefAudioHandler,
cef_audio_handler_t>::kWrapperType =
WT_AUDIO_HANDLER;

View File

@@ -1,37 +0,0 @@
// Copyright (c) 2019 The Chromium Embedded Framework Authors. All rights
// reserved. Use of this source code is governed by a BSD-style license that
// can be found in the LICENSE file.
//
// ---------------------------------------------------------------------------
//
// This file was generated by the CEF translator tool. If making changes by
// hand only do so within the body of existing method and function
// implementations. See the translator.README.txt file in the tools directory
// for more information.
//
// $hash=7158e06e5c71ed020f193c698a2fdfd6d0b170c8$
//
#ifndef CEF_LIBCEF_DLL_CPPTOC_AUDIO_HANDLER_CPPTOC_H_
#define CEF_LIBCEF_DLL_CPPTOC_AUDIO_HANDLER_CPPTOC_H_
#pragma once
#if !defined(WRAPPING_CEF_SHARED)
#error This file can be included wrapper-side only
#endif
#include "include/capi/cef_audio_handler_capi.h"
#include "include/cef_audio_handler.h"
#include "libcef_dll/cpptoc/cpptoc_ref_counted.h"
// Wrap a C++ class with a C structure.
// This class may be instantiated and accessed wrapper-side only.
class CefAudioHandlerCppToC : public CefCppToCRefCounted<CefAudioHandlerCppToC,
CefAudioHandler,
cef_audio_handler_t> {
public:
CefAudioHandlerCppToC();
virtual ~CefAudioHandlerCppToC();
};
#endif // CEF_LIBCEF_DLL_CPPTOC_AUDIO_HANDLER_CPPTOC_H_

View File

@@ -9,11 +9,10 @@
// implementations. See the translator.README.txt file in the tools directory
// for more information.
//
// $hash=64b2576447d3776b829e06007036acf579b2c47c$
// $hash=376e1cc8d7296348282ac0e9f74a1149bbb97780$
//
#include "libcef_dll/cpptoc/client_cpptoc.h"
#include "libcef_dll/cpptoc/audio_handler_cpptoc.h"
#include "libcef_dll/cpptoc/context_menu_handler_cpptoc.h"
#include "libcef_dll/cpptoc/dialog_handler_cpptoc.h"
#include "libcef_dll/cpptoc/display_handler_cpptoc.h"
@@ -35,22 +34,6 @@ namespace {
// MEMBER FUNCTIONS - Body may be edited by hand.
cef_audio_handler_t* CEF_CALLBACK
client_get_audio_handler(struct _cef_client_t* self) {
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
DCHECK(self);
if (!self)
return NULL;
// Execute
CefRefPtr<CefAudioHandler> _retval =
CefClientCppToC::Get(self)->GetAudioHandler();
// Return type: refptr_same
return CefAudioHandlerCppToC::Wrap(_retval);
}
struct _cef_context_menu_handler_t* CEF_CALLBACK
client_get_context_menu_handler(struct _cef_client_t* self) {
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
@@ -297,7 +280,6 @@ client_on_process_message_received(struct _cef_client_t* self,
// CONSTRUCTOR - Do not edit by hand.
CefClientCppToC::CefClientCppToC() {
GetStruct()->get_audio_handler = client_get_audio_handler;
GetStruct()->get_context_menu_handler = client_get_context_menu_handler;
GetStruct()->get_dialog_handler = client_get_dialog_handler;
GetStruct()->get_display_handler = client_get_display_handler;

View File

@@ -1,120 +0,0 @@
// Copyright (c) 2019 The Chromium Embedded Framework Authors. All rights
// reserved. Use of this source code is governed by a BSD-style license that
// can be found in the LICENSE file.
//
// ---------------------------------------------------------------------------
//
// This file was generated by the CEF translator tool. If making changes by
// hand only do so within the body of existing method and function
// implementations. See the translator.README.txt file in the tools directory
// for more information.
//
// $hash=c23055c6f30177626f9bf7946c6afed6c481d021$
//
#include "libcef_dll/ctocpp/audio_handler_ctocpp.h"
#include "libcef_dll/cpptoc/browser_cpptoc.h"
#include "libcef_dll/shutdown_checker.h"
// VIRTUAL METHODS - Body may be edited by hand.
NO_SANITIZE("cfi-icall")
void CefAudioHandlerCToCpp::OnAudioStreamStarted(CefRefPtr<CefBrowser> browser,
int audio_stream_id,
int channels,
ChannelLayout channel_layout,
int sample_rate,
int frames_per_buffer) {
shutdown_checker::AssertNotShutdown();
cef_audio_handler_t* _struct = GetStruct();
if (CEF_MEMBER_MISSING(_struct, on_audio_stream_started))
return;
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
// Verify param: browser; type: refptr_diff
DCHECK(browser.get());
if (!browser.get())
return;
// Execute
_struct->on_audio_stream_started(_struct, CefBrowserCppToC::Wrap(browser),
audio_stream_id, channels, channel_layout,
sample_rate, frames_per_buffer);
}
NO_SANITIZE("cfi-icall")
void CefAudioHandlerCToCpp::OnAudioStreamPacket(CefRefPtr<CefBrowser> browser,
int audio_stream_id,
const float** data,
int frames,
int64 pts) {
shutdown_checker::AssertNotShutdown();
cef_audio_handler_t* _struct = GetStruct();
if (CEF_MEMBER_MISSING(_struct, on_audio_stream_packet))
return;
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
// Verify param: browser; type: refptr_diff
DCHECK(browser.get());
if (!browser.get())
return;
// Verify param: data; type: simple_byaddr
DCHECK(data);
if (!data)
return;
// Execute
_struct->on_audio_stream_packet(_struct, CefBrowserCppToC::Wrap(browser),
audio_stream_id, data, frames, pts);
}
NO_SANITIZE("cfi-icall")
void CefAudioHandlerCToCpp::OnAudioStreamStopped(CefRefPtr<CefBrowser> browser,
int audio_stream_id) {
shutdown_checker::AssertNotShutdown();
cef_audio_handler_t* _struct = GetStruct();
if (CEF_MEMBER_MISSING(_struct, on_audio_stream_stopped))
return;
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
// Verify param: browser; type: refptr_diff
DCHECK(browser.get());
if (!browser.get())
return;
// Execute
_struct->on_audio_stream_stopped(_struct, CefBrowserCppToC::Wrap(browser),
audio_stream_id);
}
// CONSTRUCTOR - Do not edit by hand.
CefAudioHandlerCToCpp::CefAudioHandlerCToCpp() {}
// DESTRUCTOR - Do not edit by hand.
CefAudioHandlerCToCpp::~CefAudioHandlerCToCpp() {
shutdown_checker::AssertNotShutdown();
}
template <>
cef_audio_handler_t*
CefCToCppRefCounted<CefAudioHandlerCToCpp,
CefAudioHandler,
cef_audio_handler_t>::UnwrapDerived(CefWrapperType type,
CefAudioHandler* c) {
NOTREACHED() << "Unexpected class type: " << type;
return NULL;
}
template <>
CefWrapperType CefCToCppRefCounted<CefAudioHandlerCToCpp,
CefAudioHandler,
cef_audio_handler_t>::kWrapperType =
WT_AUDIO_HANDLER;

View File

@@ -1,52 +0,0 @@
// Copyright (c) 2019 The Chromium Embedded Framework Authors. All rights
// reserved. Use of this source code is governed by a BSD-style license that
// can be found in the LICENSE file.
//
// ---------------------------------------------------------------------------
//
// This file was generated by the CEF translator tool. If making changes by
// hand only do so within the body of existing method and function
// implementations. See the translator.README.txt file in the tools directory
// for more information.
//
// $hash=1ef8824abe88f3c6258ae3e9cb513c7f52b28899$
//
#ifndef CEF_LIBCEF_DLL_CTOCPP_AUDIO_HANDLER_CTOCPP_H_
#define CEF_LIBCEF_DLL_CTOCPP_AUDIO_HANDLER_CTOCPP_H_
#pragma once
#if !defined(BUILDING_CEF_SHARED)
#error This file can be included DLL-side only
#endif
#include "include/capi/cef_audio_handler_capi.h"
#include "include/cef_audio_handler.h"
#include "libcef_dll/ctocpp/ctocpp_ref_counted.h"
// Wrap a C structure with a C++ class.
// This class may be instantiated and accessed DLL-side only.
class CefAudioHandlerCToCpp : public CefCToCppRefCounted<CefAudioHandlerCToCpp,
CefAudioHandler,
cef_audio_handler_t> {
public:
CefAudioHandlerCToCpp();
virtual ~CefAudioHandlerCToCpp();
// CefAudioHandler methods.
void OnAudioStreamStarted(CefRefPtr<CefBrowser> browser,
int audio_stream_id,
int channels,
ChannelLayout channel_layout,
int sample_rate,
int frames_per_buffer) override;
void OnAudioStreamPacket(CefRefPtr<CefBrowser> browser,
int audio_stream_id,
const float** data,
int frames,
int64 pts) override;
void OnAudioStreamStopped(CefRefPtr<CefBrowser> browser,
int audio_stream_id) override;
};
#endif // CEF_LIBCEF_DLL_CTOCPP_AUDIO_HANDLER_CTOCPP_H_

View File

@@ -9,14 +9,13 @@
// implementations. See the translator.README.txt file in the tools directory
// for more information.
//
// $hash=4cf201c5e2c106fe4054cb3704114f937e763295$
// $hash=464799ae4e604aaadcf51130683e72e72ac0ea64$
//
#include "libcef_dll/ctocpp/client_ctocpp.h"
#include "libcef_dll/cpptoc/browser_cpptoc.h"
#include "libcef_dll/cpptoc/frame_cpptoc.h"
#include "libcef_dll/cpptoc/process_message_cpptoc.h"
#include "libcef_dll/ctocpp/audio_handler_ctocpp.h"
#include "libcef_dll/ctocpp/context_menu_handler_ctocpp.h"
#include "libcef_dll/ctocpp/dialog_handler_ctocpp.h"
#include "libcef_dll/ctocpp/display_handler_ctocpp.h"
@@ -33,21 +32,6 @@
// VIRTUAL METHODS - Body may be edited by hand.
NO_SANITIZE("cfi-icall")
CefRefPtr<CefAudioHandler> CefClientCToCpp::GetAudioHandler() {
cef_client_t* _struct = GetStruct();
if (CEF_MEMBER_MISSING(_struct, get_audio_handler))
return NULL;
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
// Execute
cef_audio_handler_t* _retval = _struct->get_audio_handler(_struct);
// Return type: refptr_same
return CefAudioHandlerCToCpp::Wrap(_retval);
}
NO_SANITIZE("cfi-icall")
CefRefPtr<CefContextMenuHandler> CefClientCToCpp::GetContextMenuHandler() {
cef_client_t* _struct = GetStruct();

View File

@@ -9,7 +9,7 @@
// implementations. See the translator.README.txt file in the tools directory
// for more information.
//
// $hash=bbac20a2027ea623832f37512f716092f29eef3f$
// $hash=5d6b9cf99d27d848177db25cb9953b8d9c0e2ff0$
//
#ifndef CEF_LIBCEF_DLL_CTOCPP_CLIENT_CTOCPP_H_
@@ -33,7 +33,6 @@ class CefClientCToCpp
virtual ~CefClientCToCpp();
// CefClient methods.
CefRefPtr<CefAudioHandler> GetAudioHandler() override;
CefRefPtr<CefContextMenuHandler> GetContextMenuHandler() override;
CefRefPtr<CefDialogHandler> GetDialogHandler() override;
CefRefPtr<CefDisplayHandler> GetDisplayHandler() override;

View File

@@ -9,7 +9,7 @@
// implementations. See the translator.README.txt file in the tools directory
// for more information.
//
// $hash=98cdfe3302019e8169a9db0371a64ec7b3ad419b$
// $hash=d256b13437952652b8121ea7d7e10eddfebf8552$
//
#ifndef CEF_LIBCEF_DLL_WRAPPER_TYPES_H_
@@ -21,7 +21,6 @@ enum CefWrapperType {
WT_BASE_SCOPED,
WT_ACCESSIBILITY_HANDLER,
WT_APP,
WT_AUDIO_HANDLER,
WT_AUTH_CALLBACK,
WT_BEFORE_DOWNLOAD_CALLBACK,
WT_BINARY_VALUE,

View File

@@ -201,6 +201,9 @@ patches = [
},
{
# Make some methods of ProfileManager virtual.
#
# Don't create IdentityManager in RendererUpdater.
# https://bitbucket.org/chromiumembedded/cef/issues/1917
'name': 'chrome_browser_profiles',
},
{
@@ -431,6 +434,11 @@ patches = [
# https://bitbucket.org/chromiumembedded/cef/issues/123
'name': 'print_preview_123',
},
{
# Remove cef_sandbox dependency on boringssl MD5/SHA1 functions.
# https://bitbucket.org/chromiumembedded/cef/issues/2743
'name': 'base_sandbox_2743',
},
{
# Fix execution of OnAccessibilityLocationChange by adding the following
# Chromium change:

View File

@@ -0,0 +1,40 @@
diff --git base/BUILD.gn base/BUILD.gn
index 1351225a7d5c..d84ab9e2df35 100644
--- base/BUILD.gn
+++ base/BUILD.gn
@@ -31,6 +31,7 @@ import("//build/config/sysroot.gni")
import("//build/config/ui.gni")
import("//build/nocompile.gni")
import("//build/timestamp.gni")
+import("//cef/libcef/features/features.gni")
import("//testing/libfuzzer/fuzzer_test.gni")
import("//testing/test.gni")
@@ -1595,7 +1596,11 @@ jumbo_component("base") {
"hash/md5_constexpr_internal.h",
"hash/sha1.h",
]
- if (is_nacl) {
+ deps += [ "//cef/libcef/features" ]
+ if (enable_cef) {
+ configs += [ "//cef/libcef/features:config" ]
+ }
+ if (is_nacl || is_cef_sandbox_build) {
sources += [
"hash/md5_nacl.cc",
"hash/md5_nacl.h",
diff --git base/hash/md5.h base/hash/md5.h
index 8a49f08dcb04..2f03d7a6d1b3 100644
--- base/hash/md5.h
+++ base/hash/md5.h
@@ -10,8 +10,9 @@
#include "base/base_export.h"
#include "base/strings/string_piece.h"
#include "build/build_config.h"
+#include "cef/libcef/features/features.h"
-#if defined(OS_NACL)
+#if defined(OS_NACL) || BUILDFLAG(IS_CEF_SANDBOX_BUILD)
#include "base/hash/md5_nacl.h"
#else
#include "base/hash/md5_boringssl.h"

View File

@@ -12,7 +12,7 @@ index de89d291e5cb..9ce7bf4cb250 100644
// Force a new surface id to be allocated. Returns true if the
// RenderWidgetHostImpl sent the resulting surface id to the renderer.
diff --git content/browser/renderer_host/browser_compositor_view_mac.mm content/browser/renderer_host/browser_compositor_view_mac.mm
index 4b3f3c7e97e7..0ce693402b99 100644
index 8ddd790decc4..3ffd3db8da4b 100644
--- content/browser/renderer_host/browser_compositor_view_mac.mm
+++ content/browser/renderer_host/browser_compositor_view_mac.mm
@@ -85,6 +85,12 @@ DelegatedFrameHost* BrowserCompositorMac::GetDelegatedFrameHost() {

View File

@@ -79,10 +79,10 @@ index bfb918a2cba3..a193b5a0fed8 100644
// Creates a new View that holds a non-top-level widget and receives messages
// for it.
diff --git content/browser/web_contents/web_contents_view_aura.cc content/browser/web_contents/web_contents_view_aura.cc
index ab27502c3509..282985c05c45 100644
index 965204410f9e..e55a5548a0f3 100644
--- content/browser/web_contents/web_contents_view_aura.cc
+++ content/browser/web_contents/web_contents_view_aura.cc
@@ -947,7 +947,8 @@ void WebContentsViewAura::CreateView(const gfx::Size& initial_size,
@@ -951,7 +951,8 @@ void WebContentsViewAura::CreateView(const gfx::Size& initial_size,
}
RenderWidgetHostViewBase* WebContentsViewAura::CreateViewForWidget(
@@ -92,7 +92,7 @@ index ab27502c3509..282985c05c45 100644
if (render_widget_host->GetView()) {
// During testing, the view will already be set up in most cases to the
// test view, so we don't want to clobber it with a real one. To verify that
@@ -959,6 +960,7 @@ RenderWidgetHostViewBase* WebContentsViewAura::CreateViewForWidget(
@@ -963,6 +964,7 @@ RenderWidgetHostViewBase* WebContentsViewAura::CreateViewForWidget(
render_widget_host->GetView());
}
@@ -101,10 +101,10 @@ index ab27502c3509..282985c05c45 100644
g_create_render_widget_host_view
? g_create_render_widget_host_view(render_widget_host,
diff --git content/browser/web_contents/web_contents_view_aura.h content/browser/web_contents/web_contents_view_aura.h
index 9be20d50ba4b..84c5106d15f2 100644
index 428c5afe4cd9..46e4a2b43d81 100644
--- content/browser/web_contents/web_contents_view_aura.h
+++ content/browser/web_contents/web_contents_view_aura.h
@@ -122,7 +122,7 @@ class CONTENT_EXPORT WebContentsViewAura
@@ -123,7 +123,7 @@ class CONTENT_EXPORT WebContentsViewAura
gfx::NativeView context) override;
RenderWidgetHostViewBase* CreateViewForWidget(
RenderWidgetHost* render_widget_host,

View File

@@ -1,5 +1,5 @@
diff --git chrome/browser/BUILD.gn chrome/browser/BUILD.gn
index 8ce5e842bbb2..95b0356cab27 100644
index c00a09a5ec2b..5596693cc879 100644
--- chrome/browser/BUILD.gn
+++ chrome/browser/BUILD.gn
@@ -9,6 +9,7 @@ import("//build/config/jumbo.gni")

View File

@@ -1,5 +1,5 @@
diff --git chrome/browser/ui/BUILD.gn chrome/browser/ui/BUILD.gn
index 50f7329cca40..c6cae9beda15 100644
index 3ec0ed426c79..7ffad26a95a3 100644
--- chrome/browser/ui/BUILD.gn
+++ chrome/browser/ui/BUILD.gn
@@ -10,6 +10,7 @@ import("//build/config/jumbo.gni")

View File

@@ -1,8 +1,8 @@
diff --git chrome/browser/chrome_content_browser_client.cc chrome/browser/chrome_content_browser_client.cc
index 0b29bc11f07c..9c0ffba4dc20 100644
index 84354ff218e8..c5ac79c4d3aa 100644
--- chrome/browser/chrome_content_browser_client.cc
+++ chrome/browser/chrome_content_browser_client.cc
@@ -1067,10 +1067,6 @@ void LaunchURL(
@@ -1068,10 +1068,6 @@ void LaunchURL(
}
}
@@ -13,7 +13,7 @@ index 0b29bc11f07c..9c0ffba4dc20 100644
void MaybeAppendSecureOriginsAllowlistSwitch(base::CommandLine* cmdline) {
// |allowlist| combines pref/policy + cmdline switch in the browser process.
// For renderer and utility (e.g. NetworkService) processes the switch is the
@@ -1088,6 +1084,14 @@ void MaybeAppendSecureOriginsAllowlistSwitch(base::CommandLine* cmdline) {
@@ -1089,6 +1085,14 @@ void MaybeAppendSecureOriginsAllowlistSwitch(base::CommandLine* cmdline) {
} // namespace

View File

@@ -42,3 +42,37 @@ index 985c64458bdf..f46ddbb8c05d 100644
// Get the path of the last used profile, or if that's undefined, the default
// profile.
diff --git chrome/browser/profiles/renderer_updater.cc chrome/browser/profiles/renderer_updater.cc
index 9dd42523f970..b8f5ae89ae3d 100644
--- chrome/browser/profiles/renderer_updater.cc
+++ chrome/browser/profiles/renderer_updater.cc
@@ -7,6 +7,7 @@
#include <utility>
#include "base/bind.h"
+#include "cef/libcef/features/features.h"
#include "chrome/browser/content_settings/host_content_settings_map_factory.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/signin/identity_manager_factory.h"
@@ -60,8 +61,12 @@ void GetGuestViewDefaultContentSettingRules(
RendererUpdater::RendererUpdater(Profile* profile)
: profile_(profile), identity_manager_observer_(this) {
+#if !BUILDFLAG(ENABLE_CEF)
identity_manager_ = IdentityManagerFactory::GetForProfile(profile);
identity_manager_observer_.Add(identity_manager_);
+#else
+ identity_manager_ = nullptr;
+#endif
#if defined(OS_CHROMEOS)
oauth2_login_manager_ =
chromeos::OAuth2LoginManagerFactory::GetForProfile(profile_);
@@ -228,7 +233,7 @@ void RendererUpdater::UpdateRenderer(
force_google_safesearch_.GetValue(),
force_youtube_restrict_.GetValue(),
allowed_domains_for_apps_.GetValue(),
- identity_manager_->HasPrimaryAccount()
+ identity_manager_ && identity_manager_->HasPrimaryAccount()
? cached_variation_ids_header_signed_in_
: cached_variation_ids_header_));
}

View File

@@ -125,7 +125,7 @@ index f2223e24ec7c..8374b7f0d56d 100644
// If we broke out of the loop, we have found an enabled plugin.
bool enabled = i < matching_plugins.size();
diff --git chrome/browser/plugins/plugin_utils.cc chrome/browser/plugins/plugin_utils.cc
index 73d60aa7f77c..89bff0de7186 100644
index 73d60aa7f77c..ab21e5adc28e 100644
--- chrome/browser/plugins/plugin_utils.cc
+++ chrome/browser/plugins/plugin_utils.cc
@@ -5,6 +5,7 @@
@@ -148,7 +148,19 @@ index 73d60aa7f77c..89bff0de7186 100644
#if BUILDFLAG(ENABLE_EXTENSIONS)
#include "chrome/common/pref_names.h"
#include "components/prefs/pref_service.h"
@@ -251,12 +257,29 @@ base::flat_map<std::string, std::string>
@@ -221,6 +227,11 @@ std::string PluginUtils::GetExtensionIdForMimeType(
std::string PluginUtils::GetExtensionIdForMimeType(
content::BrowserContext* browser_context,
const std::string& mime_type) {
+#if BUILDFLAG(ENABLE_CEF)
+ if (!extensions::ExtensionsEnabled())
+ return std::string();
+#endif
+
#if BUILDFLAG(ENABLE_EXTENSIONS)
Profile* profile = Profile::FromBrowserContext(browser_context);
auto map = GetMimeTypeToExtensionIdMapInternal(
@@ -251,12 +262,29 @@ base::flat_map<std::string, std::string>
PluginUtils::GetMimeTypeToExtensionIdMap(
content::ResourceContext* resource_context) {
#if BUILDFLAG(ENABLE_EXTENSIONS)
@@ -180,6 +192,37 @@ index 73d60aa7f77c..89bff0de7186 100644
base::BindRepeating(
[](const scoped_refptr<extensions::InfoMap>& info_map,
const std::string& extension_id) {
diff --git chrome/common/google_url_loader_throttle.cc chrome/common/google_url_loader_throttle.cc
index 64219ce72232..97c673d7a074 100644
--- chrome/common/google_url_loader_throttle.cc
+++ chrome/common/google_url_loader_throttle.cc
@@ -4,9 +4,14 @@
#include "chrome/common/google_url_loader_throttle.h"
+#include "cef/libcef/features/features.h"
#include "chrome/common/net/safe_search_util.h"
#include "components/variations/net/variations_http_headers.h"
+#if BUILDFLAG(ENABLE_CEF)
+#include "cef/libcef/common/extensions/extensions_util.h"
+#endif
+
#if BUILDFLAG(ENABLE_EXTENSIONS)
#include "extensions/common/extension_urls.h"
#endif
@@ -95,6 +100,11 @@ void GoogleURLLoaderThrottle::WillProcessResponse(
const GURL& response_url,
network::ResourceResponseHead* response_head,
bool* defer) {
+#if BUILDFLAG(ENABLE_CEF)
+ if (!extensions::ExtensionsEnabled())
+ return;
+#endif
+
// Built-in additional protection for the chrome web store origin.
GURL webstore_url(extension_urls::GetWebstoreLaunchURL());
if (response_url.SchemeIsHTTPOrHTTPS() &&
diff --git chrome/renderer/chrome_content_renderer_client.cc chrome/renderer/chrome_content_renderer_client.cc
index ae7e07340ea4..f193040e8bca 100644
--- chrome/renderer/chrome_content_renderer_client.cc

View File

@@ -1,8 +1,8 @@
diff --git chrome/browser/download/download_target_determiner.cc chrome/browser/download/download_target_determiner.cc
index e0d2c5c42517..0849c5bf6b7e 100644
index bf1ca3fd565b..7e758b4da15c 100644
--- chrome/browser/download/download_target_determiner.cc
+++ chrome/browser/download/download_target_determiner.cc
@@ -631,8 +631,8 @@ void IsHandledBySafePlugin(content::ResourceContext* resource_context,
@@ -630,8 +630,8 @@ void IsHandledBySafePlugin(content::ResourceContext* resource_context,
content::PluginService* plugin_service =
content::PluginService::GetInstance();
bool plugin_found = plugin_service->GetPluginInfo(
@@ -129,7 +129,7 @@ index b0458c1168d9..98f7ae7b7899 100644
if (stale) {
// Refresh the plugins asynchronously.
diff --git content/browser/loader/navigation_url_loader_impl.cc content/browser/loader/navigation_url_loader_impl.cc
index 7dafa5c27290..14d97d465f2c 100644
index 8a5502430547..689f5dbfe4a6 100644
--- content/browser/loader/navigation_url_loader_impl.cc
+++ content/browser/loader/navigation_url_loader_impl.cc
@@ -1061,6 +1061,13 @@ class NavigationURLLoaderImpl::URLLoaderRequestController
@@ -373,10 +373,10 @@ index 0e2e86e6a2af..b44e90f69263 100644
virtual void FocusedElementChanged(const blink::WebElement& element) {}
diff --git content/renderer/render_frame_impl.cc content/renderer/render_frame_impl.cc
index e2a9d4a370f3..2919772fef77 100644
index f5f11bd31f7a..031ac3d689db 100644
--- content/renderer/render_frame_impl.cc
+++ content/renderer/render_frame_impl.cc
@@ -4095,7 +4095,8 @@ blink::WebPlugin* RenderFrameImpl::CreatePlugin(
@@ -4118,7 +4118,8 @@ blink::WebPlugin* RenderFrameImpl::CreatePlugin(
std::string mime_type;
bool found = false;
Send(new FrameHostMsg_GetPluginInfo(
@@ -386,7 +386,7 @@ index e2a9d4a370f3..2919772fef77 100644
params.mime_type.Utf8(), &found, &info, &mime_type));
if (!found)
return nullptr;
@@ -4510,6 +4511,8 @@ void RenderFrameImpl::FrameDetached(DetachType type) {
@@ -4533,6 +4534,8 @@ void RenderFrameImpl::FrameDetached(DetachType type) {
void RenderFrameImpl::FrameFocused() {
Send(new FrameHostMsg_FrameFocused(routing_id_));

View File

@@ -56,10 +56,10 @@ index 982fbe8d3f0d..e757be4688f1 100644
+ "studio path")
}
diff --git build/toolchain/win/setup_toolchain.py build/toolchain/win/setup_toolchain.py
index ef8aeda56458..5b7f057311b9 100644
index 9ee69df7d210..00ad4b3be81a 100644
--- build/toolchain/win/setup_toolchain.py
+++ build/toolchain/win/setup_toolchain.py
@@ -136,22 +136,25 @@ def _LoadToolchainEnv(cpu, sdk_dir, target_store):
@@ -142,22 +142,25 @@ def _LoadToolchainEnv(cpu, sdk_dir, target_store):
# variable.
if 'VSINSTALLDIR' in os.environ:
del os.environ['VSINSTALLDIR']

View File

@@ -39,10 +39,10 @@ index 07f06ac694f5..831fd9f82dbe 100644
void ChromeBrowserMainExtraPartsViewsLinux::ToolkitInitialized() {
diff --git chrome/test/BUILD.gn chrome/test/BUILD.gn
index f60af132bcdd..626c0081b78a 100644
index 954efb536692..348043e3a82d 100644
--- chrome/test/BUILD.gn
+++ chrome/test/BUILD.gn
@@ -4457,7 +4457,7 @@ test("unit_tests") {
@@ -4462,7 +4462,7 @@ test("unit_tests") {
if (use_gio) {
configs += [ "//build/linux:gio_config" ]
}
@@ -51,7 +51,7 @@ index f60af132bcdd..626c0081b78a 100644
deps += [ "//chrome/browser/ui/libgtkui" ]
}
@@ -5471,7 +5471,7 @@ if (!is_android) {
@@ -5476,7 +5476,7 @@ if (!is_android) {
# suites, it seems like one or another starts timing out too.
"../browser/ui/views/keyboard_access_browsertest.cc",
]

View File

@@ -1,8 +1,8 @@
diff --git content/browser/renderer_host/render_widget_host_view_aura.cc content/browser/renderer_host/render_widget_host_view_aura.cc
index 7bea1b72e4d0..a0c6c00d48a7 100644
index d51ce884a964..87a029e2bf60 100644
--- content/browser/renderer_host/render_widget_host_view_aura.cc
+++ content/browser/renderer_host/render_widget_host_view_aura.cc
@@ -696,10 +696,12 @@ gfx::Rect RenderWidgetHostViewAura::GetViewBounds() {
@@ -711,10 +711,12 @@ gfx::Rect RenderWidgetHostViewAura::GetViewBounds() {
void RenderWidgetHostViewAura::UpdateBackgroundColor() {
DCHECK(GetBackgroundColor());
@@ -19,7 +19,7 @@ index 7bea1b72e4d0..a0c6c00d48a7 100644
}
void RenderWidgetHostViewAura::WindowTitleChanged() {
@@ -2024,6 +2026,15 @@ void RenderWidgetHostViewAura::CreateAuraWindow(aura::client::WindowType type) {
@@ -2039,6 +2041,15 @@ void RenderWidgetHostViewAura::CreateAuraWindow(aura::client::WindowType type) {
// Init(), because it needs to have the layer.
if (frame_sink_id_.is_valid())
window_->SetEmbedFrameSinkId(frame_sink_id_);

View File

@@ -230,7 +230,7 @@ index ce169b164bc7..743509aa6acb 100644
std::unique_ptr<SelectionController> selection_controller_;
diff --git ui/views/controls/menu/menu_controller.cc ui/views/controls/menu/menu_controller.cc
index 354216cafea8..16ec7b4c4c3f 100644
index bceec6f17210..93476578a48a 100644
--- ui/views/controls/menu/menu_controller.cc
+++ ui/views/controls/menu/menu_controller.cc
@@ -2571,8 +2571,13 @@ MenuItemView* MenuController::FindNextSelectableMenuItem(
@@ -472,7 +472,7 @@ index 4f865802a6e9..42d047bd68ad 100644
// Move the cursor because EnterNotify/LeaveNotify are generated with the
// current mouse position as a result of XGrabPointer()
diff --git ui/views/view.h ui/views/view.h
index a4f2ba254fb0..8d76cfa46fa6 100644
index 75eecfb67d0a..d93bf32ffe66 100644
--- ui/views/view.h
+++ ui/views/view.h
@@ -22,6 +22,7 @@

View File

@@ -122,7 +122,7 @@ index 07d4351d0a8a..4ad78ab76a7c 100644
// Set the view's active state (i.e., tint state of controls).
virtual void SetActive(bool active) = 0;
diff --git ui/base/x/x11_window.cc ui/base/x/x11_window.cc
index 7df0a3a8ed26..4078efb5ad10 100644
index ec9484ce33d5..52c26dcfd6df 100644
--- ui/base/x/x11_window.cc
+++ ui/base/x/x11_window.cc
@@ -190,8 +190,12 @@ void XWindow::Init(const Configuration& config) {
@@ -173,7 +173,7 @@ index 70553b153c44..ecd99bc78373 100644
return host ? host->GetAcceleratedWidget() : nullptr;
}
diff --git ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc
index 7e31a1c159af..eb0451b8913a 100644
index 0eedc2665313..53492f79fe17 100644
--- ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc
+++ ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc
@@ -95,6 +95,7 @@ DesktopWindowTreeHostWin::DesktopWindowTreeHostWin(
@@ -198,7 +198,7 @@ index 7e31a1c159af..eb0451b8913a 100644
remove_standard_frame_ = params.remove_standard_frame;
has_non_client_view_ = Widget::RequiresNonClientView(params.type);
@@ -891,11 +896,15 @@ void DesktopWindowTreeHostWin::HandleFrameChanged() {
@@ -900,11 +905,15 @@ void DesktopWindowTreeHostWin::HandleFrameChanged() {
}
void DesktopWindowTreeHostWin::HandleNativeFocus(HWND last_focused_window) {
@@ -232,7 +232,7 @@ index 335db0db49bb..7f60402ed086 100644
// a reference.
corewm::TooltipWin* tooltip_;
diff --git ui/views/widget/desktop_aura/desktop_window_tree_host_x11.cc ui/views/widget/desktop_aura/desktop_window_tree_host_x11.cc
index b03a5bc9d509..bcbf960a130e 100644
index 7c4f1e88e422..c21c8b24ba54 100644
--- ui/views/widget/desktop_aura/desktop_window_tree_host_x11.cc
+++ ui/views/widget/desktop_aura/desktop_window_tree_host_x11.cc
@@ -139,6 +139,7 @@ ui::XWindow::Configuration ConvertInitParamsToX11WindowConfig(
@@ -261,7 +261,7 @@ index b03a5bc9d509..bcbf960a130e 100644
gfx::Rect bounds_in_pixels = x11_window_->bounds();
return ToDIPRect(bounds_in_pixels);
}
@@ -954,6 +959,9 @@ void DesktopWindowTreeHostX11::SetBoundsInPixels(
@@ -955,6 +960,9 @@ void DesktopWindowTreeHostX11::SetBoundsInPixels(
}
gfx::Point DesktopWindowTreeHostX11::GetLocationOnScreenInPixels() const {
@@ -271,7 +271,7 @@ index b03a5bc9d509..bcbf960a130e 100644
return x11_window_->bounds().origin();
}
@@ -1280,6 +1288,11 @@ void DesktopWindowTreeHostX11::InitX11Window(const Widget::InitParams& params) {
@@ -1281,6 +1289,11 @@ void DesktopWindowTreeHostX11::InitX11Window(const Widget::InitParams& params) {
config.background_color = background_color;
config.prefer_dark_theme = linux_ui && linux_ui->PreferDarkTheme();
config.icon = ViewsDelegate::GetInstance()->GetDefaultWindowIcon();
@@ -407,10 +407,10 @@ index 9edfa2c00c4b..8a9217578609 100644
if (native_widget_delegate->IsDialogBox()) {
*style |= DS_MODALFRAME;
diff --git ui/views/win/hwnd_message_handler.cc ui/views/win/hwnd_message_handler.cc
index 9b683f301913..8609f61ebd0f 100644
index 4d674d15da3a..e7cb3a733823 100644
--- ui/views/win/hwnd_message_handler.cc
+++ ui/views/win/hwnd_message_handler.cc
@@ -2963,10 +2963,13 @@ LRESULT HWNDMessageHandler::HandleMouseEventInternal(UINT message,
@@ -2967,10 +2967,13 @@ LRESULT HWNDMessageHandler::HandleMouseEventInternal(UINT message,
} else if (event.type() == ui::ET_MOUSEWHEEL) {
ui::MouseWheelEvent mouse_wheel_event(msg);
// Reroute the mouse wheel to the window under the pointer if applicable.

View File

@@ -80,7 +80,7 @@ index d9a9730a78b9..d98426e9f789 100644
private:
const HWND hwnd_;
diff --git components/viz/service/BUILD.gn components/viz/service/BUILD.gn
index fdd358f741e6..57afa1d3855e 100644
index 16ef26aa4816..5986062f73b4 100644
--- components/viz/service/BUILD.gn
+++ components/viz/service/BUILD.gn
@@ -13,6 +13,8 @@ config("viz_service_implementation") {

View File

@@ -1,5 +1,5 @@
diff --git content/browser/web_contents/web_contents_impl.cc content/browser/web_contents/web_contents_impl.cc
index ae1bcfa7db7d..0ff65dcfe38f 100644
index 21cac3c4da2a..a612822d5d57 100644
--- content/browser/web_contents/web_contents_impl.cc
+++ content/browser/web_contents/web_contents_impl.cc
@@ -2131,21 +2131,30 @@ void WebContentsImpl::Init(const WebContents::CreateParams& params) {
@@ -95,7 +95,7 @@ index df508da0aef2..f6f4bf42b108 100644
WebContents::CreateParams::CreateParams(const CreateParams& other) = default;
diff --git content/public/browser/web_contents.h content/public/browser/web_contents.h
index 50236e972100..8c09c1b53d27 100644
index 367705d05ebc..7e25a0de3020 100644
--- content/public/browser/web_contents.h
+++ content/public/browser/web_contents.h
@@ -76,9 +76,11 @@ class BrowserPluginGuestDelegate;

View File

@@ -44,10 +44,10 @@ index 80a9ec9bc75b..13cbb056cdfa 100644
.Top()
.GetSecurityContext()
diff --git third_party/blink/renderer/core/frame/local_frame.cc third_party/blink/renderer/core/frame/local_frame.cc
index 60b3fe655dc8..8dedb75b8d8b 100644
index bcc0869cc2f9..50cb19a2c16f 100644
--- third_party/blink/renderer/core/frame/local_frame.cc
+++ third_party/blink/renderer/core/frame/local_frame.cc
@@ -1182,7 +1182,7 @@ WebContentSettingsClient* LocalFrame::GetContentSettingsClient() {
@@ -1188,7 +1188,7 @@ WebContentSettingsClient* LocalFrame::GetContentSettingsClient() {
PluginData* LocalFrame::GetPluginData() const {
if (!Loader().AllowPlugins(kNotAboutToInstantiatePlugin))
return nullptr;

View File

@@ -62,7 +62,7 @@ index 720ea6fcfb7f..9116fbdcf673 100644
TransformationMatrix device_emulation_transform_;
diff --git third_party/blink/renderer/core/page/chrome_client_impl.cc third_party/blink/renderer/core/page/chrome_client_impl.cc
index 2df0aefc5764..6ef2dae97acd 100644
index 97c37b0ae3ae..40f236651ced 100644
--- third_party/blink/renderer/core/page/chrome_client_impl.cc
+++ third_party/blink/renderer/core/page/chrome_client_impl.cc
@@ -848,7 +848,7 @@ bool ChromeClientImpl::HasOpenedPopup() const {

View File

@@ -1,5 +1,5 @@
diff --git chrome/app/generated_resources.grd chrome/app/generated_resources.grd
index 0f25c61d5170..201f4d1c1651 100644
index 875bf04a1a60..09990ac7115b 100644
--- chrome/app/generated_resources.grd
+++ chrome/app/generated_resources.grd
@@ -4648,7 +4648,7 @@ Keep your key file in a safe place. You will need it to create new versions of y

View File

@@ -9,6 +9,7 @@
#include "include/base/cef_bind.h"
#include "include/cef_app.h"
#include "include/cef_parser.h"
#include "include/views/cef_browser_view.h"
#include "include/views/cef_window.h"
#include "include/wrapper/cef_closure_task.h"
@@ -18,6 +19,13 @@ namespace {
SimpleHandler* g_instance = NULL;
// Returns a data: URI with the specified contents.
std::string GetDataURI(const std::string& data, const std::string& mime_type) {
return "data:" + mime_type + ";base64," +
CefURIEncode(CefBase64Encode(data.data(), data.size()), false)
.ToString();
}
} // namespace
SimpleHandler::SimpleHandler(bool use_views)
@@ -106,13 +114,14 @@ void SimpleHandler::OnLoadError(CefRefPtr<CefBrowser> browser,
if (errorCode == ERR_ABORTED)
return;
// Display a load error message.
// Display a load error message using a data: URI.
std::stringstream ss;
ss << "<html><body bgcolor=\"white\">"
"<h2>Failed to load URL "
<< std::string(failedUrl) << " with error " << std::string(errorText)
<< " (" << errorCode << ").</h2></body></html>";
frame->LoadString(ss.str(), failedUrl);
frame->LoadURL(GetDataURI(ss.str(), "text/html"));
}
void SimpleHandler::CloseAllBrowsers(bool force_close) {

View File

@@ -1,923 +0,0 @@
// Copyright (c) 2018 The Chromium Embedded Framework 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 "include/base/cef_bind.h"
#include "include/wrapper/cef_closure_task.h"
#include "tests/ceftests/test_handler.h"
#include "tests/gtest/include/gtest/gtest.h"
#include "tests/shared/browser/client_app_browser.h"
using client::ClientAppBrowser;
namespace {
const int kNumChannels = 2;
const CefAudioHandler::ChannelLayout kChannelLayout = CEF_CHANNEL_LAYOUT_STEREO;
const char kTestUrl[] = "http://tests/audiooutputtest";
// Taken from:
// http://www.iandevlin.com/blog/2012/09/html5/html5-media-and-data-uri/
const char kTestHtml[] =
"<!DOCTYPE html><html><head><meta "
"charset=\"utf-8\"/></head><body><p>TEST</p><iframe "
"id=\"audio_output_frame\" src=\"data:audio/"
"ogg;base64,T2dnUwACAAAAAAAAAAA+"
"HAAAAAAAAGyawCEBQGZpc2hlYWQAAwAAAAAAAAAAAAAA6AMAAAAAAAAAAAAAAAAAAOgDAAAAAA"
"AAAAAAAAAAAAAAAAAAAAAAAAAAAABPZ2dTAAIAAAAAAAAAAINDAAAAAAAA9LkergEeAXZvcmJp"
"cwAAAAACRKwAAAAAAAAA7gIAAAAAALgBT2dnUwAAAAAAAAAAAAA+"
"HAAAAQAAAPvOJxcBUGZpc2JvbmUALAAAAINDAAADAAAARKwAAAAAAAABAAAAAAAAAAAAAAAAAA"
"AAAgAAAAAAAABDb250ZW50LVR5cGU6IGF1ZGlvL3ZvcmJpcw0KT2dnUwAAAAAAAAAAAACDQwAA"
"AQAAAGLSAC4Qdv//////////////////"
"cQN2b3JiaXMdAAAAWGlwaC5PcmcgbGliVm9yYmlzIEkgMjAwOTA3MDkCAAAAIwAAAEVOQ09ERV"
"I9ZmZtcGVnMnRoZW9yYS0wLjI2K3N2bjE2OTI0HgAAAFNPVVJDRV9PU0hBU0g9ODExM2FhYWI5"
"YzFiNjhhNwEFdm9yYmlzK0JDVgEACAAAADFMIMWA0JBVAAAQAABgJCkOk2ZJKaWUoSh5mJRISS"
"mllMUwiZiUicUYY4wxxhhjjDHGGGOMIDRkFQAABACAKAmOo+"
"ZJas45ZxgnjnKgOWlOOKcgB4pR4DkJwvUmY26mtKZrbs4pJQgNWQUAAAIAQEghhRRSSCGFFGKI"
"IYYYYoghhxxyyCGnnHIKKqigggoyyCCDTDLppJNOOumoo4466ii00EILLbTSSkwx1VZjrr0GXX"
"xzzjnnnHPOOeecc84JQkNWAQAgAAAEQgYZZBBCCCGFFFKIKaaYcgoyyIDQkFUAACAAgAAAAABH"
"kRRJsRTLsRzN0SRP8ixREzXRM0VTVE1VVVVVdV1XdmXXdnXXdn1ZmIVbuH1ZuIVb2IVd94VhGI"
"ZhGIZhGIZh+"
"H3f933f930gNGQVACABAKAjOZbjKaIiGqLiOaIDhIasAgBkAAAEACAJkiIpkqNJpmZqrmmbtmi"
"rtm3LsizLsgyEhqwCAAABAAQAAAAAAKBpmqZpmqZpmqZpmqZpmqZpmqZpmmZZlmVZlmVZlmVZl"
"mVZlmVZlmVZlmVZlmVZlmVZlmVZlmVZlmVZQGjIKgBAAgBAx3Ecx3EkRVIkx3IsBwgNWQUAyAA"
"ACABAUizFcjRHczTHczzHczxHdETJlEzN9EwPCA1ZBQAAAgAIAAAAAABAMRzFcRzJ0SRPUi3Tc"
"jVXcz3Xc03XdV1XVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVYHQkFUAAAQAACG"
"dZpZqgAgzkGEgNGQVAIAAAAAYoQhDDAgNWQUAAAQAAIih5CCa0JrzzTkOmuWgqRSb08GJVJsnu"
"amYm3POOeecbM4Z45xzzinKmcWgmdCac85JDJqloJnQmnPOeRKbB62p0ppzzhnnnA7GGWGcc85"
"p0poHqdlYm3POWdCa5qi5FJtzzomUmye1uVSbc84555xzzjnnnHPOqV6czsE54Zxzzonam2u5C"
"V2cc875ZJzuzQnhnHPOOeecc84555xzzglCQ1YBAEAAAARh2BjGnYIgfY4GYhQhpiGTHnSPDpO"
"gMcgppB6NjkZKqYNQUhknpXSC0JBVAAAgAACEEFJIIYUUUkghhRRSSCGGGGKIIaeccgoqqKSSi"
"irKKLPMMssss8wyy6zDzjrrsMMQQwwxtNJKLDXVVmONteaec645SGultdZaK6WUUkoppSA0ZBU"
"AAAIAQCBkkEEGGYUUUkghhphyyimnoIIKCA1ZBQAAAgAIAAAA8CTPER3RER3RER3RER3RER3P8"
"RxREiVREiXRMi1TMz1VVFVXdm1Zl3Xbt4Vd2HXf133f141fF4ZlWZZlWZZlWZZlWZZlWZZlCUJ"
"DVgEAIAAAAEIIIYQUUkghhZRijDHHnINOQgmB0JBVAAAgAIAAAAAAR3EUx5EcyZEkS7IkTdIsz"
"fI0T/M00RNFUTRNUxVd0RV10xZlUzZd0zVl01Vl1XZl2bZlW7d9WbZ93/d93/d93/d93/"
"d939d1IDRkFQAgAQCgIzmSIimSIjmO40iSBISGrAIAZAAABACgKI7iOI4jSZIkWZImeZZniZqp"
"mZ7pqaIKhIasAgAAAQAEAAAAAACgaIqnmIqniIrniI4oiZZpiZqquaJsyq7ruq7ruq7ruq7ruq"
"7ruq7ruq7ruq7ruq7ruq7ruq7ruq7rukBoyCoAQAIAQEdyJEdyJEVSJEVyJAcIDVkFAMgAAAgA"
"wDEcQ1Ikx7IsTfM0T/"
"M00RM90TM9VXRFFwgNWQUAAAIACAAAAAAAwJAMS7EczdEkUVIt1VI11VItVVQ9VVVVVVVVVVVV"
"VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV1TRN0zSB0JCVAAAZAAACKcWahFCSQU5K7EVpxiAHrQ"
"blKYQYk9iL6ZhCyFFQKmQMGeRAydQxhhDzYmOnFELMi/"
"Glc4xBL8a4UkIowQhCQ1YEAFEAAAZJIkkkSfI0okj0JM0jijwRgCR6PI/"
"nSZ7I83geAEkUeR7Pk0SR5/"
"E8AQAAAQ4AAAEWQqEhKwKAOAEAiyR5HknyPJLkeTRNFCGKkqaJIs8zTZ5mikxTVaGqkqaJIs8z"
"TZonmkxTVaGqniiqKlV1XarpumTbtmHLniiqKlV1XabqumzZtiHbAAAAJE9TTZpmmjTNNImiak"
"JVJc0zVZpmmjTNNImiqUJVPVN0XabpukzTdbmuLEOWPdF0XaapukzTdbmuLEOWAQAASJ6nqjTN"
"NGmaaRJFU4VqSp6nqjTNNGmaaRJFVYWpeqbpukzTdZmm63JlWYYte6bpukzTdZmm65JdWYYsAw"
"AA0EzTlomi7BJF12WargvX1UxTtomiKxNF12WargvXFVXVlqmmLVNVWea6sgxZFlVVtpmqbFNV"
"Wea6sgxZBgAAAAAAAAAAgKiqtk1VZZlqyjLXlWXIsqiqtk1VZZmpyjLXtWXIsgAAgAEHAIAAE8"
"pAoSErAYAoAACH4liWpokix7EsTRNNjmNZmmaKJEnTPM80oVmeZ5rQNFFUVWiaKKoqAAACAAAK"
"HAAAAmzQlFgcoNCQlQBASACAw3EsS9M8z/"
"NEUTRNk+"
"NYlueJoiiapmmqKsexLM8TRVE0TdNUVZalaZ4niqJomqqqqtA0zxNFUTRNVVVVaJoomqZpqqqq"
"ui40TRRN0zRVVVVdF5rmeaJomqrquq4LPE8UTVNVXdd1AQAAAAAAAAAAAAAAAAAAAAAEAAAcOA"
"AABBhBJxlVFmGjCRcegEJDVgQAUQAAgDGIMcWYUQpCKSU0SkEJJZQKQmmppJRJSK211jIpqbXW"
"WiWltJZay6Ck1lprmYTWWmutAACwAwcAsAMLodCQlQBAHgAAgoxSjDnnHDVGKcacc44aoxRjzj"
"lHlVLKOecgpJQqxZxzDlJKGXPOOecopYw555xzlFLnnHPOOUqplM455xylVErnnHOOUiolY845"
"JwAAqMABACDARpHNCUaCCg1ZCQCkAgAYHMeyPM/"
"zTNE0LUnSNFEURdNUVUuSNE0UTVE1VZVlaZoomqaqui5N0zRRNE1VdV2q6nmmqaqu67pUV/"
"RMU1VdV5YBAAAAAAAAAAAAAQDgCQ4AQAU2rI5wUjQWWGjISgAgAwAAMQYhZAxCyBiEFEIIKaUQ"
"EgAAMOAAABBgQhkoNGQlAJAKAAAYo5RzzklJpUKIMecglNJShRBjzkEopaWoMcYglJJSa1FjjE"
"EoJaXWomshlJJSSq1F10IoJaXWWotSqlRKaq3FGKVUqZTWWosxSqlzSq3FGGOUUveUWoux1iil"
"dDLGGGOtzTnnZIwxxloLAEBocAAAO7BhdYSTorHAQkNWAgB5AAAIQkoxxhhjECGlGGPMMYeQUo"
"wxxhhUijHGHGMOQsgYY4wxByFkjDHnnIMQMsYYY85BCJ1zjjHnIITQOceYcxBC55xjzDkIoXOM"
"MeacAACgAgcAgAAbRTYnGAkqNGQlABAOAAAYw5hzjDkGnYQKIecgdA5CKqlUCDkHoXMQSkmpeA"
"46KSGUUkoqxXMQSgmhlJRaKy6GUkoopaTUUpExhFJKKSWl1ooxpoSQUkqptVaMMaGEVFJKKbZi"
"jI2lpNRaa60VY2wsJZXWWmutGGOMaym1FmOsxRhjXEuppRhrLMYY43tqLcZYYzHGGJ9baimmXA"
"sAMHlwAIBKsHGGlaSzwtHgQkNWAgC5AQAIQkoxxphjzjnnnHPOSaUYc8455yCEEEIIIZRKMeac"
"c85BByGEEEIoGXPOOQchhBBCCCGEUFLqmHMOQgghhBBCCCGl1DnnIIQQQgghhBBCSqlzzkEIIY"
"QQQgghhJRSCCGEEEIIIYQQQggppZRCCCGEEEIIIZQSUkophRBCCCWEEkoIJaSUUgohhBBCKaWE"
"UkJJKaUUQgillFBKKaGUkFJKKaUQQiillFBKKSWllFJKJZRSSikllFBKSimllEoooZRQSimllJ"
"RSSimVUkopJZRSSgkppZRSSqmUUkoppZRSUkoppZRSKaWUUkoppaSUUkoppVJKKaWUEkpJKaWU"
"UkqllFBKKaWUUlJKKaWUSgqllFJKKaUAAKADBwCAACMqLcROM648AkcUMkxAhYasBABSAQAAQi"
"illFJKKTWMUUoppZRSihyklFJKKaWUUkoppZRSSimVUkoppZRSSimllFJKKaWUUkoppZRSSiml"
"lFJKKaWUUkoppZRSSimllFJKKaWUUkoppZRSSimllFJKKaWUUkoppZRSSimllFJKAcDdFw6APh"
"M2rI5wUjQWWGjISgAgFQAAMIYxxphyzjmllHPOOQadlEgp5yB0TkopPYQQQgidhJR6ByGEEEIp"
"KfUYQyghlJRS67GGTjoIpbTUaw8hhJRaaqn3HjKoKKWSUu89tVBSainG3ntLJbPSWmu9595LKi"
"nG2nrvObeSUkwtFgBgEuEAgLhgw+"
"oIJ0VjgYWGrAIAYgAACEMMQkgppZRSSinGGGOMMcYYY4wxxhhjjDHGGGOMMQEAgAkOAAABVrAr"
"s7Rqo7ipk7zog8AndMRmZMilVMzkRNAjNdRiJdihFdzgBWChISsBADIAAMRRrDXGXitiGISSai"
"wNQYxBibllxijlJObWKaWUk1hTyJRSzFmKJXRMKUYpphJCxpSkGGOMKXTSWs49t1RKCwAAgCAA"
"wECEzAQCBVBgIAMADhASpACAwgJDx3AREJBLyCgwKBwTzkmnDQBAECIzRCJiMUhMqAaKiukAYH"
"GBIR8AMjQ20i4uoMsAF3Rx14EQghCEIBYHUEACDk644Yk3POEGJ+"
"gUlToQAAAAAAAIAHgAAEg2gIhoZuY4Ojw+"
"QEJERkhKTE5QUlQEAAAAAAAQAD4AAJIVICKamTmODo8PkBCREZISkxOUFJUAAEAAAQAAAAAQQA"
"ACAgIAAAAAAAEAAAACAk9nZ1MABAAAAAAAAAAAPhwAAAIAAADItsciAQBPZ2dTAABAKgAAAAAA"
"AINDAAACAAAAi/k29xgB/4b/av9h/0j/Wv9g/1r/UP9l/1//"
"Wv8A2jWsrb6NXUc1CJ0sSdewtPbGlo1NaJI8UVTVUGRZipC555WVlSnnZVlZWVlZljm1c+"
"zimE1lYRMrAAAAAEGChIyc4DjOGcNecpzj3e5eskWraU5OsZ1ma2tra+/"
"QoUNbkyPMXUZO1Skw1yh8+fLly+84juMURSFhhhyPx1EDqAmLBR0xchzH8XgcYYYknU5HIoc//"
"F1uAOa6rplb8brWAjo6AuBaCWnBu1yRw+9I6HTe9bomx3Ecj8eHR7jhpx2EJSwhwxKWDtHpSA/"
"hd+Q6Q/"
"XNZeIut1JxXdd1FzPAbGI6kyYm6HQcNmEJi07r6Ojo6OjQ6XQdhMWCTscBwEd2xARjIprIJiYm"
"JiYyf2KCACDkOB6Px+O3AKDQkNscN32A7tIn3tm+wPdQiK1gI2FpTbSPWkfP39+nb29vT9+3/"
"Y+8NdEAfA+OmQ6zRtfR0dHR8ahTR0fH4+PjY0dHx2ynx8dHgB8U/"
"i6fLaUnx1wT25MmJiYmJqYDACDTYdbodB2EQ+9aRwD+Nkw+"
"hfQxSPHBdvQ2TD5FpJFBCCtwtLsEMYc15nbtXNNdkgqHYiKRlIwAAABAlCZiYkIIiThNSRKhE8"
"KqUrnsJ2hxoZt4CRurX076XaZaxJetiVOHTp0a+PgINiJWq8VwfLk+"
"cITkeOQ14Y4rvOkFV5gNbxGwcVJTDea6zsoAASCExwDXWK1chON6pdVirqN3roR6RupwgcQ1uT"
"LXI+"
"HyOoth7KQkYR7fAFOJv3TclGuuX2CS60rmmwgoZRIFU8icwlwDSea3MKrOGxMM1XtqaLgmDcCL"
"YEbscM8PuoIEXYE9Qj08y62k5aQRDimNrAslDCa0CL3XGSYaTW0Q2etDMZyiS435NgHG4HACkQ"
"xzYNnYqtvRwqPLDKAT1fRDd5KIJ45cOoeyA1FHC455K8BYpAAAZ2gMqDAOQPcz9/"
"v3uTNAASBXhW/"
"+wqevLAUrnjUnS7YzOs8s+"
"bpwXYrKdoXXGjBgp10SlQ8A3jb0scTwUeAFrmtD70uMfSS4gJeZlUhIlNsKco2uXVeY2VWl6JR"
"DSAhW4jYAQCYAAJCXD9bEGgGxF1Oz2UgEAhOlC0q5pjzL3fxjlQcAAACAjx8bmMEYnbAb1U4nz"
"BE2MsOHLwGuHz8oUi2qnhqYoTAuZWUNo0sfSn2HJJcA1xVleDATYEDmjGsqfYuV1VW3dhdQ11Y"
"rko0xrJHM6qZIpxW2qPLKAiBzakFdDasdLWtAzpUaGbaUXhZzReGzLuS71zqMZIhap91418WyG"
"4stA5xvC5AWfdPC0KFnhug9EJ6h0yAGfs54rQNMjP2JYPT0RkeosWCnkZ1GGYvGLCMRrhdEj8C"
"h8OOUvsYFzIyKCO+"
"MNsuxBAyvGFnp9QwEhcblgg5xA7gRNLmyHjMwEAWu57SEt2AIXIbqDRCqICCh7QEAvBIAAACSr"
"VYG45afyShwcSuuNzIo4AUK/"
"1ZvfgUABf42jCVGeVhwqQpxQ99SBB86rGrhPqKsDImUIoPYFTmNXd0Vlks7U8FRjYAEAACYOUp"
"Uk8RSEAkCIWK0JOXukmSu2R1+iWGIWLBM+mt0Up2tqni9YR6/"
"b6aK70i+"
"IV0EAzUMs4ZAYRQJwvNSInBWKJtFAgS9MiFgEEYDmIOZMK8E4h5xAegwErEGYWbSzKJ0E5mz+"
"AozI2QYjutAsEbhzsrxtoHkIjxIZo4Ho/"
"RpMMDTvsug986rhaceoIQiQucUUCJPKaOJwDKa0Y2kiRhjDxOG6EGJEyEhATLXC0j4qKckgkeE"
"ugjRA8B1MY8D3sIBr0kOVsvFwQTfLbj3ABCIMrHSLyQ4qbOdjCEK8gghdCNG3wyjgskAAICiE8"
"D3VkkAYPyxpQAAwPXlW2HA/I/NAfx2KQA+3q4MBYDE/"
"X+cAACyJJGwfpZxAP42TMkH+"
"0AOLxIzb8MUfZQRHR7AkSHICOeGMHdG55ULc3qMjEjSBwO0SAEAAAgZYhCWUSyoKAVKKKsQL5v"
"0RJaFKF0iIp4A4u42AYA9HEIPhlrCoWNiOrlxU6OmOcVsXyAWNWWyYvEg1fLKMHi1MRcAqZ6qs"
"KKPcJIoAfWgjkIjWXkBzZLBQ2X0djWBHvsi6aIQ6rQmZ50vcrgEuGNleEwUBA1WpKJiZkbhShj"
"a5TrjZ8uHdL4p6sJpn0748t/"
"4Ky401MB4FwAw6vRWc8BMAjnySEYJoc5+"
"VpmHtCG9622e9msJozQgHQ18GB16oycX3odS6siozeCNd2g8ow/"
"jDOloAgg3GK9JhkfU4FAwCLci2kD8KNGqMLrinHR6yujhyHcCArjgYYwpicBMtEILRJRmAK8nc"
"HC0MBHPNnh8fASAue68jrwrIuG/vZnupwGA/"
"v5t2CyABGSAA942LF5E8x+"
"NWB4kPtqGxYto9scgpxdJx11V1ABBREREEsTMk6t0u1QyNV3MRCIdAgAA4C6ZGSzQBMyUmAhNp"
"RgtYEkrCYlUtqSPpYbpbf2LmAYxxcEodhZD1DDVNE1z4VabMg0MUzksaBW5vkWD45q5luFKQ4x"
"Dl6XhA0w4GGKQyRZwjQbX8Y1Q1y10x21clDHA4EPjADidlLiWSmXCUjIzk18yZHjkFeGU5hOws"
"jSXKma1g2NpIJmVsRIyHQb04fcMMljQLC4eVrUpAsBbR2P80rIFh7xkaD+"
"qQRJAhCF6amxRZzQLYCgAwGHk4tTxhp46UZ1GR01UxokEw3RgDR8aYLLBhBVWdRfXkdlKNjRIn"
"tIN5WpsAhOGYW3WNE6ychBocusS6He+3SoISm3RZ/"
"ity3SkcDrh1O3GnqUWeMII2FsBAACOXK+ZAayOaQAAAMDr9fgQAAAQpgyQURIsAD43bNUE+"
"YGaVgonZW7YqgtmBDX1FCdVPNoASzrC7pwh6GrXnSTOhZliQkJITZQjAQAAEBayiEAASkSEEhU"
"nAlqMIl4iEBUvFwr9KaKiwRKlIixCWBS0QJTtFQwxraBqER3lw4O5wsxcLRbgeBwXM5WRLq6EX"
"AII0SuonlAqIjsEkPAiYT5wvA6YhOuYQ5AkIsK4nA7DuAjJhDkrtwWLUBWrcSQhFlOglSQ3XXB"
"N6sIjyXFczCTkSo5X5hpGyJJ7MtDTHSJLkPBbpMBy2F1Er3PU7qKM5yMsFhDGeEooCKVk4zwFE"
"9pNnPoeCBgAYsJ9JsGHiYDTHHEpzKldb3scr1fvvJRLdLrQPhYwq7FljfBg/"
"R6eNRZEBhQGYVX9QEdsDeG6qA6OAGjMBADgO6AIdQEAlaUfAAAAEM/"
"wQZz6AQAoK06aAAAAAGTherz+MgAAAMAHlAX1Uy0qAL42LNpFsx8HpWdH0LVh0T4i/"
"zhIHWskPTKhHTrYuWpKV5KkjEUnpIYIJAEAAIhAIBSI0aIlSlQoChGhUKQQioEWUqJCUYeEmB9"
"8T5k2E/"
"+DL3t1UQNjJmHEFP+"
"mrQyEabFWhEmubBFIrmAMZaYgjrBwHIfFMHkdTzDRuXSQqUP1KAKoAGJv6IC8ddTpGcyxIIyMN"
"kIHYlVoMSLCOpcBXBAKSR4Z5iJSHo/"
"h+sSn1w1zcL2+t+"
"vggs6EoRb1YfQRvRtEfcwboET1ohMO0JBOF4wuclcSqndFBhgiPPWeAT6CUAZAZwylLtL7MC6Y"
"NRgRVn1YnQwIRYTuUl3EIdFbu47ru3l9uMJcud4JcxHQ6RSD7hqATRcNGv0Q6EIJPAUwANBRKP"
"xWAYAIcjoAAADwMf0lHqCej/"
"n7+"
"9sAAAsWFtSVSDhHPrjcDBlFPWb95RQZfjds3cfIH5Ae5KTOd8PeYkz2Q8BDwXYfeeK0w1i5SQT"
"t1sByrhw9LiVZHOVBEgEAAKDECjFxMWamy8tFabpcQBMlLIwymhKDW/"
"motIQ8H8rNy3MJzBhFOsIQ0gAhTIG23swQ9rJa+"
"Vo1kgrfbpgarwknpUFFUXhkAZnUyFzo9nYLTpTQKNarPtd46sfSmS7CSgl1VkzAxOFWowvyqwi"
"yQM9Io9rMVtMNIw0N6duZoR3zWRYFWWQhVKbjuF7WnVTZYY8CY4e4jCT93sfJJACJBRpY1l6NS"
"QDEmmzDBPqhSdNmLPURTE4SPg9PiIuMSJ5SGvOh8fQAYFSRR2T4XYMZETqDnihEsuKtxoSvzEQ"
"OhhXKl2oCK1LfMJe11t/NvT/"
"EuCdvlaj1JXsG+"
"sLnIEHNJtDRjXHAGhudngIATJQBHPC5X0dy8cgAwAAAnP3s8A77BoAGigofEvUvtSQzzckL3lz"
"5SgA+N2xVxqYfiG2hQDRxw5p0TP7RUFYed2WZkTJkEIIMG+"
"ax2rmxQ086qaIcOihPIgEAQAgBQniAcIAZEPPwclRAKFomKe7hVnULf3/"
"PrQ43ubI48InJ1po2TLadA0rEUDVUsVMxwBjVmBC0w250lKGkDmEFeevFhBnCXCZDGDrECQYkg"
"QebcT2OKzNKQDKHqgnDSkN6oiMCsInFdb1GjTwpqw4J2QmJpC4LKoDrLwrHbc/"
"zI95E+Ki0iHd+wOuhI5EXB7E4UwUkRwKwRFLVul6uHiATCy54aCgNFdC7/"
"pjGcUyYMJw4OrgMxutRSL3lRBFhhNE7tAhCI0BJWCOb1aJpVEbyCMmnhOosy5XrmptCmDLAOhf"
"11KO/3ahqxOhRJZwP1/"
"AEZkTAcQBMVwwAAu8E9KzWgEiZCJPhBQAAMJcCAHp1D6QSAAAAzKfbAVCHthYLAAAAlQI8macA"
"IFQ+AD43bFXEXvzAuvFRN2xdx24/"
"FOvOfNzVZYRMMqQMOWHNBpJ27Ry92YXHdDyJgHJYAAAAPxIzmSBiki6amEBSVBYqBTFapoRCod"
"BcQooSE4rQEqQLIYHXj79ceaxwo/D71/"
"JVcaMMtwDAHFyFJLmS6+"
"hmgeso9zEQShTggBx3gco4QjLABeTBMDMltQ8Brgk7g1kxLtIOwrwCEwhsUeMKC7rG5ArX5HgN"
"fDrOIsfjlFavcc2EnBx3IoaOFs0aHKEuK26Jo1oGKpcKCVPHpO3dn7yJ0X8xXC73Lnd26CXLjg"
"MtCjN5hCFThAQ2oSFtOqOVGSDuE32hhYk4jsTlovpQozGwRbDa4UortUhDwkUAGGOR6jFYw2wX"
"FJWsYBDy4MgWAXCbVTMEAABQEJ9LgCwH3xYAAIBMa6ZNaQCgAcBTJ/"
"x3AOj3+wDAcLwer2MAAAAy2ACgwXf8bXKBCjY2xMkkMx+KLi9G1SRfQ+"
"pkrPnA2nUmeyDHu80EQVKEELbtjomYPTNESOfauaokPSZJA0UIkQAAYM42+guCLGQ+ns1y+"
"KgSupXRApdXJEpi4pSLDJJKRcndw82tg0wkAgPrVMAMn+iQ3W/huqg/"
"Dn51VgoLfPn9gVTIoESUeFyxOCk/hSsDF5NZW70MrmNVrOoWZlo5bmhxTDLHOHTC3u/"
"ymKjiOlaAEIzU6EcUCYPLmDnmVK1esZjWOPXKWdXtVr01YJGhu4TiVoJMBjheB9dxCXLovTEEh"
"RLGaUp2Y+m+"
"rAscdQDonFbotozWUeP0Lop2ZioVzASyLqcOHV0lOE9nZ1MAAUBTAAAAAAAAg0MAAAMAAABNPA"
"GzHHBCSXWA/4hFeXd4eHD/Tf9a/0z/RP9T/1T/"
"VP80TOZAm1Nx5OLKuqg4gORtwnDFBzFFjQzs0XZdrDdKYSDmSjid4LQfDhKi5+"
"h240ACA0CNW3cUDABUawBGbEDXTQBrAQCVA+gxJAeAooIVRYmfpDQ/"
"ADDPAJiZPJ4CKL0VwmKNDgAAABB4wcksgAwAnP100SFYKhzvrKcPFkH6ob/"
"mUaXIRDBTcgHEGFi5xJcO3laj2nwCDrhVGxPvuosRTqeLwWlAfYSrIzNoeauADicEfPVoAlDqQ"
"aRFq+"
"snciCkfCHS4qa8or0MBDMmF1j6cY1Cm4iGhjfGaeO3aieOGe5NDbGwDjMMcczOSPXRFkE9H8+"
"2tivg+AwTAGQNEQxiLnIquGjWEMUgZgkKXsxZc5FSaqfd3Uw1z81sIB8+X5WJ4h5VVZ9m4+"
"6i1buron8SP34vySmxQ7qLMCG0QEz0/"
"dT7XwCo2VZgmg6XM5ywWqdMz5QJ8fsMtqXl9ASTOGbvISIWw86dzoFrOPK5YYp0AJQNE0WyW7g"
"QLT5gX0YMCEhLFyIFZx7T9tdYUcZB0VtJu6JumJQl5fBOSLhW37S5VXs34jK1Jk6VT/"
"x83HsZZHFaDLQov1dP9gNAMvmItMzF99N26+QM0xzGyd1NG3vx7cvGMQe2Flvf/"
"nbSajF9W32brvVMk+7b9uwetObQFh8AUjYUlVb4B2Kq5oLCGBuKhIP8byZy6k0Fy/"
"P7VLTPiCKAqKtn1I4yy4MRVYUi94hYM9q163TiXMVijoCQBlgBIAEAAGyfygLXGCzgsKJUvzv9"
"XsNFCjlU+yZdS4D2WD4dm8oyL0+5TdC9AAAAAOSQ49//"
"kCTDIgMwAI6dPc3tnLUcLWWKMTh3gAtGuRBrX8HcVR2OmbiORPgtuEJZSZiw4OIuJlOhrDgCWN"
"qTvazq8R1kGqXJdTJxtXJKFMGgpws9wcyEk9FRCbfVYK7HpfDKt6iRl2yPW3hTVjWw8HljZcsx"
"BrKd+rDCSQCAGKtxnRWOVybT4lpXTXidEUdPVgF4UL9swRV23u0ZD+"
"F0MRKXIawEFIB1ekIgDYGbwsMKU+"
"0ozKo9Z2TkC0c3gMxmkYQbJsxQOzYjDyQkIuv7bsFeisuWiRwzYCSRqHXOjQg98QZbtYEYxjGc"
"QcARkID2pQDgwPm9ngRunDrVrqxYyYraKzL4/"
"nJO3t3aACCBuWOB5ax1sNREyTiHA2wFfRZkaS4gkWMr6LMg2DOhYKapgsoCSDNCBtw9OxjKFWD"
"CykgduoxFYqpga3WXZEJdsKgHsYBJTARBmHkdFKsAQCmnXnwROSE7Hv6llTQVfDiNLyIjZBf2/"
"ksraS74cBrfqkTCRD5PUtVGNNMKXBQCXNlcVlBc3JeFFaQQFSmXY1K0woOGWAXocnERodAlpA6"
"qrJyaaTkB4Jizva1jptWWCYvjdk79BZjTT5tmqsXOxhCQCDJiPlKf74sLJSRcEWkl5I7tv9mpY"
"BrTuCLSSsgd27/"
"ZqWCapv0HIOTKyCpCDKk6j0huPhQVAAtocQIRWkiGIAYtJsnw9BAjYl4xuuSLUnHcx2tjuUQyZ"
"hTkDACHjsQhFltHamcRO8SwkekNAZhRrXYOp5uxrLd4XtEwbb8z73zWNpwRWZbbM239xM8kh+"
"uMyLLcnj0cip8LZsytqkYyyYqoriqQu5FSj1dkFaJAQSnL43E4lBKlTCgqQknRouwQXhEVEbg7"
"NHGEdOWrR9X0wRWbhOXu4rUZu3p+"
"8FtsDIsThmlnNTCMKQ4thuOOKKuNZUbFxBOPz3vyLzwRKSzpbvMJu4IBp56ICCKJx9zGrmDDqb"
"OGUiFCT7KTkUeojozcJkSBhIijQiLK54mJE4GIKAsFkCwT8yUwIelyMU2EIAJRP8Vo0dPebkqG"
"aBR4ylMQA3+cdMJiYz7r7wm1Mez8OGaorRXUNFVncCyO9y+tTnwJTwwRNQtG5BcKZh5BQ70FA/"
"IHBTPXWRUpUnQexLSqkClyVlENHAqLYQOXD15ITCgkhBDxMhE3DxaKif+"
"YkFkgIqZ4SgmQMW2qv3wdmTb2rsVGrGpx6LhDJ2wcc4TF3saBL6Gd+vhJLbZdxG7+Z25+"
"jQzaNYQuBh1BDYutlYCuIXQx6Aiq1aqVkFstWUNWFBEioowYI7tudxub1uSo3FXFSbHERiQSAg"
"IAAJAymXQJKSDADKEYiBhdQYsKPMVBM0UkxcSYEqFEpJDaskhhOmY6sBhiqCm2YmIRU7Cghi9b"
"QQwceq3qcWAxCjlmZiH6YF0HALHFRchc/"
"IWBhRpjMYxFxrA4wLQKomKVxEB1ozEEOBlBjDOceDHHXZlryEFrZOCVme9uTSOkpQbDgxAsBoQ"
"6dBjBwWrXj4MpbNqgByzqAzrwgIMhAGSRUAI4ImPoj+4YhtEJ450rTr3Te+"
"oKQ0EdEh0AuLwvoUgAWPT6ibwjn2ZyAcMQETA6C9hhQkdsorFi0RUGeqCkDB1Dd4A28ScCMQJw"
"uxH6QfQ/"
"yMCNHCVggaJ1aR0BADDzeh0BwEQEwFyvuyQAAODD7zgA4LJkAL4G9D5GmqVR02oJnHPAa0DvY6"
"RZGjUtlsA5B3Rn1hAyRSpTRUo7mDuT66pYUiZ62NwCAxIAAACNtZcoBlgINkBEZhUtSYASZ1pI"
"CE0IAehCyA7TQgCCvQOL2OG46YRjoqO964AUEUVtMdWiMpMcF3OEHHwIyRNOXSSFFzOi1+"
"tdFlz6MJEIiHfoFEGsBWqK2llRk+NFMszjmrkOYygQDQIEGAA+"
"HOSYuSZcnIoDMgcTuGgKb4MccORxwXUwMNM5NAQ+"
"jEtmJnk8GAgTGCOIAaGRvV5HqNPpDSamPgLUZYEEhXR53c0QJzo6dJE7ZC1BLTrDgLgQUV0Y1Z"
"PI8bg60YUL6iMCM8fjQ0JCwjg9wzJDSCeIN5aeRgETm7ShW7pNB2jdSQAA1YwA0I0Y3ZIcAgAA"
"76QMFAAnAgAAoe4uy6WEMgFavwv68IdhABANMmTIIwAAAAA2XwkkAD43TD0Fe0BLqzkJe6wblp"
"6CPaCl1ZSEPR4R0mKQdrfEUNXOo1NjxXQ2M5EiggQAAKgQTLsoYbmoUISmWBTJoFKcEitjFhGy"
"QCgmQigBDQjFBZ4QZYPjTsiOMNVioDY+dqjHBzjITDKZHBoZrnA6iiCYOUJgwqFq+"
"mDEu24kxORIYLjm+"
"PR65PUKYWASXsmhngAEHkhMCHx4ZAgAmbmSkb5JI4ZhgHh2YtpgAvN4XMOQmTMRjA6aHkCH+"
"jA6FVDEAWqKgjhHlD9ZS4bOogVPLEZQBj2SnvQEZxim+"
"mvvsK7dgCUswSOc9JLIBK6oCaPbNTkHBedS9YS4cPG65rQAudgwO6bHoKsJYTTAMMK4AANmHVx"
"jTJ7Q6QEdEKZ7kpuib8EQLZAqQIkrdnQAGCnS4ojg7a1FusboazG0MBFHAGiOI6/"
"H2pEcTw7goALeNkzFJ3EoxLSYAkePbcNUfBKHQk6LKVD0eNdQEYqElJIghn03CFyXqw6RHi66w"
"hQTcEMAAADsJRmSWJKEhBABRQi7i3sIRDxERcFEIE6J00wooiZWgLI6sqqoaaImA+"
"AdUsJsHFq5eAwXHDQG1CCPzECqbQSSuXI9EjRqkAnfqWtrj2u6Y38kvY8UZgIRAAA9gwTCcT0O"
"QgBi8JqZ4zokjJNENj7UEZiDVyYzBMiQObjpNXAMqKGRYaiDoaEGQAgBHUEGgBAe0gRASDCOv8"
"NijCH5HbiKapzzQjhouA6MQFLiGN2g85EoRSdULj4MpRwDF0XuDnXc2ccYPjlmjuEBMwSjdvQR"
"SBM69k4wgteORhhoAuA7ZAMAoGH0pwAAKjI5AfAMBEZERr9LRwdR/f/"
"WBm+EjcfMXDOQBGAec8FkAsD/"
"AD4HLClF2mYmMaxmckRzw5pKSIdJDqsJz0ecGC0J59zOuW5Oko7MwuxAAgAAiAgkxSBKiREWij"
"MlLi6kaAERZYoCU2IQiGH1rfZGI+Y0W78s/"
"lhtUBVDXdPJ0QA8ZxyJAOSovfLiMcBwMFwRSeciPbgYDXgEeBzcdBDURwTpIjNAHpnhYuYguTK"
"g3unQCUwgGeARIgDDzMxc4XEcTy23Ta6LzCOv15VPDK/"
"MXBnpOulLtVsXBVEAxmithYNQOPXElRBBXLggBE6XkyI0JMwyYBWGMgJ6q9BkKNxjaz1K1TsDI"
"oyDzmvPYKiekGJIEE67I4w5XhwXAANwweMUkuGCQRwqtQSNAIgJWVdWnOzt0Z73R6kl6IqhpHs"
"KQi20iNlJYKzVeep1jEBkLAHjLRq/"
"UnJQIQC0AXjipN3gQHy1Bl5P4B0CMsRhT7d3VQAEcgya72QAvgY0MUVpGiE98OhpDWiijxBNIX"
"iQwwLyXWNlLSkJRJkI5pi5UlTXSULsyMwiIgAAACAhhBASEoKFEC4uToiQFkIImoYERQpM7Jzu"
"sG7HVhTTnGaL1ZaZDDK4tqNimK5HPlyfXuGYK5lrGByZSHqmoJCghDFsJCSBHqEkssICuV7MlS"
"HDpYuwyHgD4CnRASEjTEoCBEN8gwr0npGEhhokDMcVLq6oulqoGphjJoGEXHPku2pJQZM6zuIt"
"3uC7hCC6CBCqj0U4dfoOA9BhlLln1LEUBsTodNAZpm5GSuBRjpJ+R5Ek3R4mHnEpz/"
"woPkxaVjIZVmODUztO1TAhxmg8DmYgD7CYCYOzn0EaEhI3AgAQI7XSEZoyRajTAI3kO0Dr0Emc"
"DwBtiE5koAsZFh2DbidOjEjVWTcA72J0RKGoGj76McwC3UjFxPOcEMipPa7jejAXHjcs0QdzQc"
"ovE8YYN0zJB/"
"lAyR8mjOEuq0UkyCICO4Spq9o1McwpI4rXhEUzgwAAAECCGVJIZgmWaCICIi6ghOIULUoEQhCA"
"6RKI+"
"oEC7IVD7Oysin0xzEStE6bM1rjSClwzOYtrjuHTzMxr5i7CvI6LyeQY5piDQF4Mrwk51tqiBrC"
"gMwfXNWTmOI7HXIrwWSwhShx5b+"
"Ii1xxZywAw5EiYRxgwNJIFRw6Ba3LAcaAiL64jny6u1yTMEI5h4Jh5EVCXHiZidw8ByIsUYNY6"
"nYnwnrh0YRwaCjh1jND6IoN+e8D4SOgefGSnBRCdK+KC+"
"hVLp40uMkAoHI1PHK8Mw0UgALCo07kiQpd1YEHEOLMMAxOMQM0igWcEwKcPiOP5aGVv1DEGeD0"
"41V0twoN6iyaCSnJjqzbkmg9D5s02YTJgmh1GAABAJF1E6GIVBYcAABIAPjesNQUzQkMCPHqaG"
"5aWgrnQlAyPHBnsGoyI2J1YxnYulVRiRRQPzUSSQAAAAOICIkIJxRjulBjTIqJu4hRhEeKQ9BB"
"4sCgoIikBdwJxmhIQEVERePaOrBbUFKsFq9Via8xoMdRixUQUMdH7kA4dmdBkmMnwIExawKglH"
"DM5mAcLxjNur2OQcJDU8jgezKGMoTTCSSjIcISEH/"
"DAZSzCSRGZhkZQFzWOzHzIPI55kVeyaJyOLOjDeMB4x32EThqElRiLbu4hSagB4JPVGX106CQw"
"FxlezAwL1AmnI2OgJ95FTYTXUWJCHXogYjiJ9zeAQk+"
"MMzz6qVPvGfo6OkJ3T2dnUwABQIMAAAAAAACDQwAABAAAAIrNerQYWv9V/0//Xf9p/2H/ef9p/"
"2X/Yf9Q/1b/BEzE2jK0NDQQNcgJ14gIsT+BVgws0GAgojdE9hi06B0utk6OBEYZxNa/"
"YWB1IIIaiC3o9ycQrxHPWQR2Beo57/"
"Q8dRMQZxfcCgCgLFSCVcrkbAMF1KpCqhQAnjY0MQb5gPRhjae0oYk+"
"yA9IH9Z4vmUNKSIyKUUp2G7NVa66kjgVnUUcZ1EOBAAAIIiYWLIJMjJIQolT7uJM00SMFhFj2F"
"nNqfaGWu0x7MVi8SNjYScCA2AY4ksuMpMZDi6yzpho1rAWIcMx8IKBa+"
"IZaoHVE4SPIiKyR1iEDMnFqYXM41L4r2C4C2auQrtpqFOnM5JMmHkkHMeRIeF1vOYxyafjejxe"
"jxzDF+"
"B6cEJaoEZP9HoSwUAZLvROGEM8OINxkgiqB0LJCojXQ98rMUTnbyQgCKKskRBKoYPTAI6RpU8J"
"dfOn9Bj92A+xhdANvOATJADQqojR7XLp+"
"uW0OQjWYCAD4hiDETvevXUkAjpgjECjdaxVgTpi7BgQBghIvwmmQweKgROAYQAnxdyfDyZVwGw"
"GHRx6WToDAiaKIgB0n3G26RFiNDNjZQ4AABbyfsJZF7429M5FZh8N7ZfZo6e2YfQuMhtpGJ9mT"
"56PdjGbaAfz5LpdV+"
"gcuhHFY8dAAAAAUMYUGOJgSkSCAoGAQkH7NEkIxQUUoWgBamtnqDoQx8wwzLa4VuxtRcQwxM6i"
"mGqnKQgBNWW0tiGP43gquIHMiPBMTgaPsCI8ZgZqRyCZFwfDXMfMwIthOI4QjtGYuYgAwPBipc"
"k181o4BlCAhBIGF2aOubgG8uDBHDMz4WKGPHhxVXExgRmmiiZqE1MnGAB6Z0gaGuHOQEANIaCV"
"QV8tAuHgAOBFZmI3honY1a0m+v2+"
"jzxGOAidEZ46gShAZwqN14ePmBfHCnAAAsHotmG8h8swmg5oTWjInYPwm4BSGAA0Qz8WEOK0MK"
"kB6L0BHLkmVidRw/"
"CXKQaiJhRE56mXHICVMMNHIt8dVwAAAADQYAoA9IyMjJ7oqQTSj5kFKAA+N0wtxmQPSB+"
"szA1jTSF7QPgEji6TiF1WMldVeoorFzqdKN4sa+"
"xAICQkRAIAAIZUUE6xD1SQ9LIn8SmvZ8kzWFRMVAhJmWEhSJAyL4MrQAABCCGEfYoqBwVfvvLU"
"rU/"
"4c2L1xM7OVuzTDlVwzGqjVrEI8prXcU0y88plIvltLPrw60Py4gQ40ylhApdQi5FAHcwDkosPF"
"zB9RBhi2eV9xrjA6HRKoY9s4zLPO6ZcHEoCcDGvYTLDPI/"
"PbC+uHFExMNQWcxog2GKZ5jpUTZBGGcM2sX2mQCLtBWzc9M5oBKIhr2nVZDJEvSJUA+"
"bQsEDzom5Y7CBDnBL20EigLuFgAMG9AkZhqAXooQNcJrRGBoQkwGOCCf0JQICKmBWByTq0iKlp"
"+hN3YnvaOAbIg5khYARg0RrITBhYACXbggyTaw4uJi84xkxEBhVUAAAATK6zqrqO9dNIgA+"
"4ABn+NuzexMcPq+gTqae3YYsmmn248EvZQ0C6y6xWikQZGWFyJ9ZmmaCqXU/"
"0xDlHOc08ToQAgQQAACQxCyoKXMYUlIiAeJhQKkm7OrF0BwRSl9Qzyq+naTefUI6H1/"
"G6XhfX6qqwlu8+DWR+cCiM0qKDbrp2C04LrjmuaZEHM1dUC60NP6HujMTM9SCbkDmuHEeu+"
"QETMqpjoWG7hHjqCZiQU2DmIg8qhDnIMY/"
"rSrWjQTUvLdbUWsHpYRhQmVBVRamO7zK3TKPOlFoV1xChAZB7O8K0/"
"17piAkJSr3pA5yUM91WPSEOzTCRBYmgoSE7UhOkc+j0AGASjpYbGQLWggCQDLoB/"
"EqPIhdqU3C5wu9BFhSl5AjAcPBYWnE1mQsAAADhxRjzGPI0AGACAACEOgkoEXAjXOTQg6ja2k2"
"ozdSZmEgougvGG6nOAqNiqqCGKkxTGXF9GFQdEgAQWU8AACxYFD9ZTwBcHAD+"
"NizJxdgf4BeePL0NUzTB/EAIH3jy/"
"K7MDEAicmDsIKnqdq7MQiw6UcSxCUFAYAAAAAYOS8EFAeHGuBwX8vRSBSUAMxGIOSZgEXEBYUp"
"5UkCRGU6IomKqrW8MFWPsE+"
"p4BKLiSo5cWxwy6i2aCIvGlVzkQZhhqre1vk9GIfwduyysMYfp6kqSHOQRAIWFrTlamUtRVOsC"
"i4ASxy2Xp8bxI6UeNLl0JOylIcm8KoEFTxgd0SGyjzADxwVh5p2qbG7NoLBCFj0NvaP21M25Z0"
"CihupMaGN0YHS6fEgnRjQmpm83Ol/"
"jVmSZIsJTR4674wtdQXMxTPU4YYl55a1SW+"
"nKRe3FFAlAmAhGIcmscRzzms0MoAVaoI95esuyDgBoTDDNfS8gTmABgIQQkH4R8cepiMUvv8Yx"
"DR+"
"M3lgy6zpakJmQK0dy8SHhs3CtwLJn7gACzghHACADVAAk4JUSb0tKfjb0UobsAelFTvZ4NnTSR"
"NMDygtPnu/"
"qsiIRAoGNNZ25q+PSqThXbDzNxIIAAAAihw8RwCQFFUtKRCjmFa3wFAiFFWIV5V4RB/"
"aAb4d+jW3v1Ll3hOFnwiIRzm1rGKhPc3yaHNfBNY9j4PW4UCBz3NIMKRb/"
"Yo7Zgi3mhEMIHYwD9BaCSHPCGeE1DxXXzMxpB8z1mEzRc1bhNy7PUAIsIHwGl7vCGhk6Y7wXmG"
"vO4pK+lbRF1hPoXU6dtybCUH349R7h4KmaiyFcmTA3qJCNGVzAkTN2GcUle/"
"mWDIKhu76tydqwxRWyU3KxDUNIu59GGQwRZDu7naQbpjp7QCTjgcxcM6zwF4E5Oq0eoRG0o6+"
"3hCHJ0l8UhguOJFHBYmTcfN4aYJ10jKBL7xEZRcAIaxUQw59h3ALQQJ1wU/"
"pIYPpbVNRfRiBtMpLXDDNMLDGMhsCo2hgOWsIyvao0kQAAgRgAQAPLaiUAXBzCv5fAVKXAdwUB"
"AGRZAl43LF0nmR8b+TdyHHXDNOpY+"
"2MjPvg8HhPD5OZY7Oy621URi7stBMTJI6Qoh0AkAACgRGUm4oQC7aVExEUQLBAFERX47hSBQKW"
"OqROGjZ3VoVVU7GRyl1E27YQKri81sQoR4Yeehgy4+0R0LUBtGnOVfneARcIAs/"
"bIqpLUhiHKQFpM4F0ZjIQrVgjMZLmkwEQVhFaMIWozuVYbnAauQIQXmKtKmBVApYiiqBSFL/"
"NFWWAZvstNhHESPTJXWnpxhDmszIoF0OzhMNHRotGHmZkRViFoQvXSjkfR5jgqXPNU5yPBSWjt"
"ElhAARBjYLXHXDCEqZYhx/"
"BY4WCuWQmktTxgkp+6MDxGQRE1jaGRSdjOKJxwYlrOrE1EEAA9AZV0UwB+"
"SdMZDfoRAACAUfrDY7euoerjy7nMmgTkQxIIJG8Xql1h7lLtxbdXHcFpAAAAoCZPi1BjyeQAAE"
"DcvM4MAFxwRLKT+"
"VIFAB43jMmF7EMR8yeXuGFMJjL7UIifPO6qooqQMkhEMGbu6nhjkrhYRNwsgZmQIpBIAABAGYi"
"YBZiIIJmwkGkRES5RolwhpMUBQaBgYZnA933QqL3VcVcmdTKMmboWrGdB1er50kSGFKPaMT/"
"mePHi0xWF3xwXcyQXmcAjheOaGqx0pDDw0LkYoZYZMseDyfEIrwEmF5lc5LJl1wU5dNFLCAlpT"
"HjoHAxhmLPCkIliCmIFmc6G0QZ71bSoKBgYmIjkDJu/"
"IJRR54TLhyRwMXrDIhj0YW51qHNBRYJDEdbIAPRhyDAMC2pAEZkAPkJPXKBwMl5yEWyF4QqXk8"
"JTuxwXx8XMHWeFOfpIFp36ZVZnREf7pe8jT7pIFKErIuL5806oVQGAulqAwEwAQBQFA9hKQzAA"
"wGQSGHjAXBfDHGGuDzk4nRKiUmplyvR2CNPZAwAAAIZh2idUVVUB4YAA3AXkmytQOFQO/"
"jYsSSalkUYOFznb49swJZksjcxCeZCTuryriiyFFCECllZOnTHtXBLXxtLYhCAMAAAASAgJyYI"
"lS5IshGJCQiAqFIgJxZl9j/"
"333W7fpr05MZp24cSkeH2tSnMsFKXMW9qaikylHLmuSXU4lCgLP05DdRTO3rc7GW11BpMW1kY0"
"WI0IKGm0kx5qjFZjIpiivDq3YqSMulB1Ce/"
"f4dTnLa+"
"O2IKtrKH2mnnSRpi8uE6bvx0rESWgBr6HEKpYWSJNhuqSdKnDhXeh6MSWruKu6hyZM0pIGDjEL"
"xUMwkfCygCHDg3Vha6jhITx+UIAnnjjw+oylIFs7gYnnGElegYIR8hw5Bg+"
"hDkGCCPhdlFHjUvhRwBAFvB6i3CGt80JIf/"
"eAE8RviQdBRYacEIEQRAijEDrmjDFbopMWMVTUQzf7fUeI5iGHsD8pfkrfjOnUgAAAECvF0P7e"
"aABAEBk1zsCAF43bFFH88dEXg0/"
"6oYt6oj8MQl5Nfy4a8iSSCIRDjYnzE3veOwqsYrYTG4CCQAAwCBmEEkhJQtJtBhExUVExQQCCM"
"XFxIgBTkxvbxo6xfAvFov/"
"GfBvljmtJ0T8a1m0dl0zw+"
"u6AjM55vVYFWEIA3NcMMPkw0FeCR1DdyIiyY95XI8p5C3kT3nlAJ4C16gRnoRkRBgPPa1hi+"
"xICJTmMUPITAG1mlZ7MAwbw9VO0Pp9i66wIjSy3hGB0zDC6wx5wIvhNQwBeJAwcDF0TmNRZ6Gv"
"kokIwm8hmNM4Q/"
"VY0Vk0jozLWlAXIgwjP3aag9GR3qUG9hhtuoh82CAPhrnmEwuu6yhGhILBFYlQQp0UodRTCUAL"
"sQ/"
"CRAtBEE2YuEWKMOBAZEAPCBm3AwBqSZcC4BeYmABMAMBYkACOxyMAAABUHLMaUgAA2BqfXgMAA"
"NQLHjcsSUcOI1AfPA9xw5J0TP5A7B6GHndFdRIZMqEUHLN2EIzV7ZxLLC5sinMeAUkCAAAJKUg"
"ykSBmgCgxUTBDhIlAnA6AhpAWEOJXiCahabB1mnjOpaZaDBUMg6lYBAXMAUPUdc3AECmyI4DMZ"
"F6PjbxicKPLSuf1kYQAczHD63qQXLcAVbRu4BgmeZGLgLQwDMzMHD8yoJH1HbhohKH05QjAdXE"
"cjFBH1Bs9o8d1zQOODEAgAhERxsBFJrklKxcDTyRjvJPAGLtbWAm8xRHNaEgYi05XJJ2nLjiBv"
"giHThJpY6P1o4lBLEYihlBCdQRhaHeQ1IHRGO+UHK/"
"JNZMUZdUIdTGA6OBDwhgE6ToiBgCAUADXFJLZRegIIYQoijAitBpBAYB0mAfamTgAAMkqChSAi"
"hVZmAAAoCMFMlhXBQAAQKXfX1ZIgOk/hyXbVQAAfAAuAAf+NozRRI4/NiVcwNswRhM5/"
"NgkF3DXrFYBRMiIyNOM3Vpg2lW6E2NqlUIXnUAEIQEAgJNUJSAFRcFgZqFATOApLVScEtKAmDh"
"Nu4kLKHF2l8sUdJljntIH5tPxOCSuKl7MKvh0zTFIJ4YaqsLwIONWlytkqK4B4Qay8MgE6kzDc"
"VwXgXmRRb2erGJHdpmQFiLadToZYXxknY4YSzNHOKWwiuPDI7kyc+V4C78TrkyOx+"
"T6CpOBqTS8Xj+OzDFkFmE8jajuDNSEtGiNnsEbwOkYSMDFXAFvQPQK+ohQo2XDs8hfHcVMZG+"
"cej0BjCdmMwERRMUU1CL2qFzHHA9eV9RPZ2dTAAEArQAAAAAAAINDAAAFAAAAVx6YmR9Y/2H/"
"V/9m/2H/WP9Z/3VORkpMSk58cGtuam5nZ2tqCCObwnf0LmQeXJnfa+BIPtTG5UaNjfA6/"
"XTYrl1Li5wcMDBMyyEBAF4AAABUOFPjubFDzrqMwarPAKjxugADIIHebgW63cx9egLIFsQMGgk"
"uPwwAFbhABp421M7EjP9ohbCwHc6G0piw+"
"UcKuCR0nV41SQCASbETOXdcdVVFrlJ0c4QJJCMAAADPcA5xIzxWA8M6xnl8N9fwkEppIgEPyXI"
"3oSjtWYZYTHtnDH/Z7mKZTNdfNJ74Fp3eFECMtjGQhfnA9UYpJ/"
"1YvXJYOTJjany7DRgsABTFaIsrEaAurw8LkbAxmeNrAQQr05IYJkEtMEgE9W+"
"PA3LlOF7HhKtFKadthaM1K5xauaZ9l2vmygFMF1ZJqI6V4pUBIDOBmyw6DXHrSMHFUMWvchozI"
"Gwb0TA6EO/yEQB0PhIsIBkT/"
"RZH60dad4vrPXQTKg9UoU0grXHkSLlIuGTg8ehSXBchQwkIM3VasAXXhY8n0g36Ic8XYiWlQQt"
"y6B0tXAROgEgwWAHzCgAAAPezppotW0BBAOCrZgzA9ZIAbrfLxAToYGdTAAAwJlYqgErGhYwDF"
"BfYYEPg7h84CgC+"
"BkxRJo1LIaeFgiLTBkxFJxsW5LQQKPKqSkhAwCJkbLnspE5VuyqLa7pJKULKAQAAAC+"
"VM14YjpC4cagMhwhyKWMIadCdl4iKeFaQ8umy6RmFTzy9AlpMBGJer+"
"FT8iBH5nqQyUG2wAjvysAMw1y5VtnmhHS6Iul8+"
"KkzguhJqEXqgoS8siog00U4CTajcR2vOTIhZCA9jeS0gY5a4Zr5cF2Pa5iAwadjOK4EJtfNnlw"
"gDE7zGAGAKc2R1zFpZAYgw1Dohu8LhgvVmdqchRXCFiw6zuI9hYwa0n8F1dGaMeAawS6RgGF06"
"b2OOkicjlG9t4KZHADwuI5T8ZihdnE8husDr3nwSUgmkE0oTLIEc/"
"EYZh9t0hS9h8uEpMAf6MIv/X/"
"RFyLUMrp4HJEHAG8R8B0BAABxCQBw8TB7JwdsAICKjT0CAKLW6Cx4QDLX9fp0DfnwVQDeNqzFx"
"+YHKBeePLcNWzFJ+QPKQk42xndRAYJMQSdlrrmqXSplrsvCLKUAAAAAC7COyxK+"
"gDiOLYwwEihIqTcioqJiLooSnzad5t+"
"XI0uovdXHMqONWu1trehoTigttn5GYxgHG8NkOF7XrY0L9PqG8IxsjhZYcNZ2LQ0LBYlEXYwl4"
"VWCmQCEa4WbVrf5ckEGxLIEdx5WXWHh0h7AAEdZEniGHUFCRgpmTRgSYXSOC401a4Qh87ZYdDo"
"VkcJurIvWXwpjFF2RnKYI6iwwE5UUojSIgvCdauUWic5Jik642t86i2NiZAeZEMbo9DqjFwgc3"
"dI1QlOla7G0pQzDkLlLrGqyF0BmjlzJ8XSMs77qyLUbDQ95sTx2hEVzhs7PbdbWAT2rl4TFaQE"
"I+"
"D7KBRgTjiQAMLBEOZHA5R4JAELo6Jn16Rh7Ygwshn5kljY5WKeDdAGAIQBuAlQtDFxcAIxFvZ4"
"6HQSeNozOxc1Dk9OFJw9rw+"
"RdhHkYclkNPBnDq45JAGDkEHO77q6E45qlROYgAACAd7s4eePywOcolC/"
"CqoxMsaiwAiIlUUI8iJP+svEx+2QbbYpv9TO1J7H1a6oxTcxBWgfTROPK5IqK8+"
"JhfYfXcWWOuRXMMYiwBWZnV4UXB3PClYAWAbiL+"
"fAQ4UjpD1cJok3mLICBex2oogaEeRjDHLW4YbrlB5mZYQaLg7nWTulBJnM0huPIMR/"
"mEmVyRnVK4iPTIAvdTkcuh/2BCAaHr9EOEIuk2NVw7iAl/bqH56EwAkMkSIdiBdAZvUt/"
"ddH6ZCx6Qr1BEyARBNdw0azorHiMIbngNbOAdrLwOhamZSgiIrQ3Y5i0sPQUNtb5FifoEdtmD6"
"RbgBsb6O+VlBWA0CNsBtuLG4V7IDw4UhUelkBk94g+/"
"WKK6YV11wYAoDduA4B7z1+"
"6Lr2XymIDAACQYEnIPgcsKSbSAj6YKwjQHLBEn7INhBd4fleUGQAyxJHL5NyZ0pUUOyeW6CZHA"
"gAAgMcIhByNclkurFTAJ6Ll4uoVifIQgAgrxMqn+Ip0ZFOu+mBrGr5lMid90mIxp472/"
"h0nd3h8F65wXOGlXkxIaVWNMDNXKcF+"
"XWbyxBk1dBIPP6qBiMpUAyk6MXBNBqgqicXujEyd1JGBMa6QIBSNwMwr18DcXoMrWenWtU9zHc"
"Pjw1yZBA7ChMUXOmkEwh9q0TgRBH2HUggSegw4QUI3ABdsJl62hemlSmOaFWRIAgu3MMEuD3H0"
"e3RHJA4JAy2SxQaaTjfDgFxTUa5cGWDABtb1HhdBq9pox5U1RTkOvXr73dZtaG01Ebq6Tn3EhQ"
"sAgU/"
"oNpFRIgYDVYtOrlF1qXhqryu5JjoinVEAzovr0NEmAmmijwwTu7EjrkABJFseTe0sAIC5XjcDA"
"B439CWWNo2azpJW55jpHokbuhpj7YdOX1bnmOmVuavKIgmZskwZx4plgyWamrXzBBljFucSRaQ"
"nAgEAAMDNwYGJSDxRWeEpLvBShHKoaGgrMYREkqgIXGLihBBHjIWevu8pJAQEAChnMfPpE8x1M"
"Giva5JHjszM9YJrCWbgel1jcW906QAgsipqWic7DN82mBrhoCM6AIbAkPBf6IgFn5zeMeNJWDx"
"8KEGoy5HBSoTj4WyAmmIYgqoxNSwRjA4GufTGBUd6KwcFnATQ1y4XgEOAEmix6dkdRq9bahQaI"
"N1+iK2FyY1BI+"
"sIjbZGR1zUQnK6vLHIIEHTNddrhms0TqZnCEkNSBjXzKwCciCFRabeI9qEQRQoqAc1FkAcp3A6"
"S1QoAGDryQi0GOjDGwCWhRcUABAGLhv4IIR+"
"v98HAMhIAPDppHj2hkWVUlFR2Quwt4tuJIMDuMAHFjYkhSzy/L8ZsuVnkSupZMresCEhRDEM/"
"83E+"
"rPKlVQyUfdHWVGkQIgyiCJFWYQKZWQxNdVNvQGScooeYtPZmEpKYhIAAHCFggYx8hmGFTMyw6X"
"kLgFRCEILqUX4oJUQBrvAvUjJfibTT6cOHNjFTHG87DxduU7Vh1wXTK7hOK7VXhOurRyPXMOkX"
"HD8VhbhdxsEhiGS8OKgRfGlrbZqqHavXmdA4FQYQgIwL1AO1J+"
"p9k6nmV6iJngxIQxLwwDMABxzw2++ASgxOXL8MvPI9zEAkMkcx+"
"MgE8hkAikBLf7alVlCnYIwbGfGzNqCVVuZbUbbzCE969R0OpDQkBYIQQ+"
"GOGKZBm3P5IkRZYC5kDiu65dJEtJipop3Fi9mhhkSgwpHDsAKOQpwg3FnuhicFPXBW8vpSlEFW"
"AEAd6w8ecSZhJ6bwBva91t3Avs1S7b8yQ8yYqiiowpTDXokAFBEALgsFJz7CeCaU3JRPVysbc4"
"KAPABPAV3W0MRxvdyBAX/NBUV3OUMRRi/"
"nyNEch+cSQ2VpTKTNyM0IErFMTvMa4a5MpPhQS5XZL1D6KOyvLBW74Q+/"
"LZQzerw1OCbEgBoYNcAlAULDSuNVA8UfG7aMmChYqWR+"
"gUFvxvTmmpGGXhTFQAawExCsAe1iDDHBw5GF1LvNJsxFm1CGgYLtMU4GJj5ziFCfRjzAmQBdxi"
"QcF6kggXbPLaC5Q2wuD6kggXbNPk8kQApvRGEYqj3IW7UlXAthj2gJnE5JPiQ60gy4RHM1ZBeE"
"I7wIsIAnjgESCiQYNgZpAW9nBhHsr5Ach+"
"YWgt6ODGOZP6A5H5QfwF4cwRTlAHf6yIWknkMlIDhADBRk/"
"k0pFCnwxsjESZ3GmFcMnA9Ul8YE+"
"JlBAHyP6UWANQBCyM4JH8kgZHkfsg6YGEEt8SHzERyL6ijogqQ5j1TUFErK+"
"SzxPUKcwtIRPgdgWuG11w+"
"OtTpLVDDZF4zx6knBlUAhwDICmQALCKB08VwOgaSu6apRiR0jpu3QyC5zziNs7JaCAqQZFQwMN"
"c5uY3QLbMSrgmNzxINUxl7OyYslrwoYTSW5hsgvtFBQqEPnf1YBIBj6z8BXDpDN7Ff+"
"Wx9MUF2jU5VgT/"
"1w1Es0H+1J1qEFCsX5TGX0IZvTtN9S5llTiNyVKec5rJmvh6CYjGTi9Bn4tLhaREGlmcL5nBu+"
"KDZnq2Kiol8RH9qfpfQf6ZSVK0dP/e/"
"nvvUaGuZNm3KVN++ZbvTOpOdjzawOi+O9yoXAHQ+0RXo8vzCWFyz9/lEVuAzf2EuPvO/"
"sjx0WR0hcqc5I4MaznYaOVWEsijZZpWBique7CZhMbGQZfEyWVyG0LMCYp4Oza4KUjZViMiSQg"
"/JWxerNC3JT/767BP/xVSfXYYZZ5wwxSqfPgto4LprbSdcLtEVXI/"
"fo3THu1TCFeTTKaXN2VbNrK4qg85GO2bFWkWILNyZbK/"
"KP1NAdz0CADFN8i4ltJAISgLi0X9a2ynottztoFPoZvWfneL3HKV90HsypJK7Z4GTo+"
"rlc5fjyjLaOUypO8x83scuACw2qQ7qtd7EAgV+"
"5BJXoPs91L7p3TgWRSQRmxcH564OZydzCfU0SV57KRj4ToRDUoFkPXZKTjVV3okKiaruMtXOiJ"
"vA0/zjx//HqlnfY8n74+l7HveURKJzFxWIUOel4rq+e5dTPPUjM/"
"23WFUCjErBCfplfdjiwjcqhRcQp/"
"qYYjPcVVZEYmJ2CVlVIYnssMHUPUuHciRXDLCaCJMScvjseLhRLq8nNuOopQoxmYiKv4i4lWhP"
"UcrfRaso7b1OeIiPC09dSCl4giLiB5UKKWZX6D2OAPgkAGQ+"
"qQOs25VQbOBdQtEVaCs90Di9V11URiLaIeY5Y8x+"
"s01mCsGpqjlRM0w5kbtfAbg2X7Y5ooTqyNL1iX234M3noeyJB8rDzTbe/"
"NOZnDUSdBctE3OXWHOV0Hru/"
"z8zXbkYTn+tVnNvilOx1wIAjE7FAfSov5nimu1oVZtB7Pk3U7xm/"
"4zKyoR2Zhumjfs8c1oUMI8ngKhITnHK41EyJeLu3qyMogICupCAL8aiNMUQp0VFiFBUPJj4EzN"
"25n8O7Wc6Go4cOdiN+LLFwUwc+"
"AAVvvxKAJxS4QD9dn1JxTFeKhXPoF7uDxSL2dtlecgRKUQVisiLrMpA6ggbRs0jjnKEfgOgpdr"
"GJEmCSIha0HPVlKMFk4QiE4JF1+bDDBGaRT0YxK13A0tkcaGKi4iAYFT+/"
"W2YfgarKWpoBQCMUsmKtB5iEFZcwyutkg2cSxwhWlzjv1ElEmfMLMrRNnpJm5k5p0iVFcoR4QY"
"AaqZoCY7B2Ht3D9GSj5UqYu5SuApSXjaqRFGWFWVX7g1JNJIsdMVGBnXsrEM17v79bbU6mtJ+"
"1MbHl20AAFRavZMB3cRI3ALd8C+"
"tnmHEN3GkbvHDtpvihMRpzsEZGciKmJYo5h63sigOZkVZBsqSekW2KwFcl6qEF+"
"YzIkKKQctyeZlBtNogIMHzUTQ571WEF0+a8GJSCLgRqQb+"
"Ga5LgvTOmLssAABPZ2dTAADA1wAAAAAAAINDAAAGAAAAssrB0Bhy/5H/Yv9Z/0j/Wf92/0r/"
"Vv9N/17/"
"VP9sOrUDVEK81OJAtxnVTcDvIWrbbP+qRVGJOCSJg2sRZVYUgzhr8q+"
"OySJtSwRgYVvWvMClNgVxqmmBq7XQR4pyuSiRllAhTU/"
"J80pq59H9GYf2dEFIWTNjavbxba7fe+OzU2w2vu0F347gu3zb2vq6AQBaJx0+LCWy/"
"w6fDJKL0EZwnXRoeIwP/"
"z18GjtrPSVoJb4DAJBZWQaiMiPZj7TIXiTY8nimN0md5gjdTTmENAAJAAAAoAIUURwBLHQ+"
"h8sTCIWiPLNMeQmDxdwkmdC+CLzUAdMyBAIPBUlZIkwN7fnb+"
"9uSwtRWkmuyyocmOYtBEel1HmpeTJ1EVLFOb0lEnO0AXMdjMseLD1Mp8wDCL2uEL0vATRNAZyp"
"a49olwNrQqAJwT3iAkFusfXgdw8VZCVX8WMGwTjUUFEPpfgfmOncd+"
"rHhdRSxWu3EBExD0NS2mRys5YNvKavYqwyfMhfAhNCeup1HCj7GrEZVA7mODVjh+BT+"
"9PvuptHu3jSigQFX1zBEmbaGaDb2JQaCVRhGwwoyevNdOw9O15QrnybH5LqurGVP20xayn4QQB"
"FRLNMQF1QHHcxIBM6wdmFYKUG3AQBwGjQAAAOnZf1Ub/"
"e9v37rOD2YuEfcx5PCbDSLZCYAAKCX25caq19ul9qapX61+"
"lIDABAZSVxfXy8QCQBYc3MAHjkFVsyd/TfmSw7VR2o/O0v5UYpsnz37D/Mhh+wjsZ/"
"V4v2goqyEoiJRoSzJogx4HDqDIpEqE6EqJWUi14uAo+4E4GnIM6qbRCCmFwAAAABEA+"
"qwXTLOUhBj28gygOcTCBhaGosRLslN8EpBjMajIMEsUkAQkyAGBEIBE1AQJ2AKYAGLEBqgKIqi"
"mTCID0NNSEaLLkYDnQvEN18VGb45rkw4rqOnYaV6GJ2YACioYLGzmqZFrQ7FFAciIOiIIzQAAF"
"4XqrYWe4vVBsVQUUGGOSbXcX14JZmdaYqKKIiCoa1NBDF0zSOW7AEDTIwyGBNWY8ImffuJWy/"
"n9DB6AMBHPXz4HIbqDEUEtccwTauqOKLOMMbD5ZrjmhnC9ciHmWlnscFiFSyY2IsDPPLpyHUw4"
"TpYALQIILSubgSg3+/3+/1+v98Pow83Ajh3lCBkrhyPYzJCnQIAAMgovA6uh9EJAABeKZVWTb/"
"60V7qPRw9u5P3C16lVFo1/"
"epHe+"
"nu4ejZnbxfsP4ga4RCkllZkYEAOTnnefRqj3JmH9iZ6QAhtWtTGgAAAAAAwhLwGSFHCB6XRMWU"
"R1nKslxCGD5DweeAwIEwXKCZoigIBdNuXW+"
"u6XmVQBqiHoQyTBsxHNkLpmlrZ6uG48Prxeu6Zo7jw4cPQ/"
"hDnTowOvIY5pjhOq7rypEF4vTGQlhZ3fSY2+"
"AgDOHWUYPHMMxFEsRQFDUNMVA7Hz7l4nhdwPAgwKFaUbW3qGCxcb1CZsJM8kpAaJjj9bgCwwBR"
"mPCFMYS4rlcmBwPMkWFyXJnMdXDMCz5NJvMhMGGA2ohpOCbqmDghiE8PAAAAAAAAYq9qMbFxYI"
"ppZ2M6hmNitXfwIddxvSbD9WEAo402Vgdq65jjamPrUAXEsLERAPV6TcJIAOBooXUEAADAsb5P"
"ql+mBQAAAN4J9ZZPu/wP45f1bp5ZsmuFdUK96tMu/"
"0P7Zb2bZ5bsWmEPRHV1EDUkqbKiSFFUhCiCuV06Xs1G9VyLiZQHAAAAACCClHTIhfTAEMK3JKn"
"VdmIjsNo6ZtoYYmOjIlgdM0yrKXaYNqjVDodWPB6QA8K8rpnJQcJ1zeuagzkWqKckjAW9g+"
"s14fUaOI4HUEYXITpqIkAM1Tu9jut4TciVMITJ8HodCWQ4YfQADOANoUR/"
"A6NjXnPk9SKBgymYKphqWGzAYudxQK6LGQAA3kSYCJcdDm0xTNMiiAiqqoIhYie2IoYQfkcA4C"
"lghIT+"
"Bpe3CDXtBNSRaasI9qbjmjm4Ei6OeRFM03DQo4cAiLFIunWAd11M5hWuOQ4GwhUgD8jBNXNdV3"
"jNwQDAmEBHABgTEWBCWgCgowMAAACu49OHa7GxcYQDHAQoAP74JDM9PfvDL92dfFUybqQ9Osmw"
"p2V/"
"+KW7+"
"apk3Ih7oIaKDBUQUmRZGRlRU0QRe1pQ3VN5Q1SKidQKkXuiGAAAAAAIAsFdEIKLZMmAkwlyuWH"
"BXaYIxWJioCAUsIhLfKqKWkVMwKq2Zntcx8wxuRVpwpV3EW/"
"RRyZeM2FWCsOEa3g9ZmbIMLQY5qwMc1zr0sFAGCMMTGskbXXMFAO1mmJgimGu5HYFwJLEawIzE"
"NapAwBQFsf1Vjzy3QFzHZk7BTENW7W0VRxa1Cr2zGCrPVpMAQDAIGH1DomxGKG2aoM64TDT12C"
"L4rolxwGE0UN39IchwOvxOraYx+"
"t4bwBdhE5ADTUxHNjZ22LYuD7NZF6v1e31zcx6zrEAKfTQU5eHAcLoXQwAANBiX0heAwAAoxl9"
"XQLY2gCw6koAAAAAwJi5JflldKc4cDAPu7NKAQAAANB9/7YUAAAA3vjE1hG/"
"eISH7tv5rFmwJWx8UnWPXj186Hb2SbcVu6ZUSwQ11CIzK5AZqMgQaTcwymUaDxMWgKQ8nxgowo"
"TvGRllZlE2ByJDep1kiMCIE+"
"UBAAAAgIDwJjjo5aaInToqytXNJkNBGrxRElEWdZgihGYwiJBLAiKeyfS0hGkuioJQhMoSuMzr"
"ifT3D1OQMmGwWLh5ywBRCMhQ8o93apqvqaryMorpq5x0LBQTAAEph2La2hoGlmn2FityDMLrGO"
"1k2HS4PjSsrjAd6pDRJdE1kmsZxyOv445hcjDHcb1FHbp5aFF/"
"dXoE86GG6AwGkxNWEHOQAIxqxY/AcAxnFJmGJ1YBFRcA7xhC/"
"zvtjPnm7M3up1AAMMTMAHIwn5W15st2SgAAABBHAABDVEAEI6aaXWD0AYQcpaGbD1/"
"DiJwhDDNMAgAoSgC6Edx44wDgdcETADRHRn+/9/ern6+ur+1+2d2c9XF1M/y93QAAAABz5/"
"ufBgAAAB7pNMoRs33saBnTJ2D0uEU6jXLEbB87Wsb0CRg9btdEVZFU1ZRRkYQkKjJkcBKGoBBZ"
"GYkIVLmatjWrg/II0wm7yQghJiWSBAAAABGzZJAgIkjJLOEKWVDK4/"
"AJhyEMiIBQzKJMWCBOUQxJLCQJAksWzJQIREDTIjSIOAhhATgIPCYzx2WROHU0DBGOBI6EeXDM"
"os5pMQyj8SAW9RHUMOLINUNgMpPXI59myDDAFfDEIqN3MZhqbzHEECVwRwQAAOSaDzyOJHMk4f"
"jAY2axsTPV1lAbAYAf+"
"k3sDkTFztRSiwmmIWAegetg6XowdKMwEQEAiqiomFaHtjaMkWgoBYC1NYDMdQxvCiZWB7Zib2J"
"abEdz5HVdHPPiAbwMFgyIk+giEwDAWPSOdMDoBwCgG1aLAKD3/"
"S0AsGO+VNLeqaW8tpS3+UVmUQAu3sjU/"
"B47Pgb1zr4gS7ISNzI1v8eOj0F9Zl+"
"QA1npfEjVZYYaa0rVRNRQGWrImlA4ZjEcgHY9LcA4EAkwZjAbgKO7qkiEGCWRAAAAAAvBEJJYN"
"CIpWBKxZLBkKSUTxFmEAk0LAEdKEzEhBSZCmmJCiwsYDEIAZjBFgWkBTZiIQxxCBpimCBgOM2j"
"QBG6SLpaiysW0izAYAAC5wkCGB1y5BnIM5FNmCF0k6Bn0kYBPB5kjgWuYORKO12hXCAfAvBhIg"
"CnUYicihokCqgKTSRIyk9cUTId2YkFSAwAAwGKk0vGFVPi8tTC54HhNcj1eTwVkwIi0LkXKBHX"
"gARgOrgw8hmMekwECQ2YE1OkkobwNQBYRJnlri2G1SA2AEuCMFBHhtOCQGFAAiKOBiTjV7/"
"e7fToicLYBgA8/I0JEbe2tpioigHcsJAMsiZ8AgAuwcgG2EoACIAP+6CzKkpRfTI97tbNDya/"
"RmZQ5Kb+YHvdqZ4ew/"
"zWFWguhfSWqoCpTlAWE3diQ2hvp0wIkujNXNRLCeKIYAAAAAMCBv2Zuo0sBJbg8DkTw+"
"MIwCAPKZUDoEgUWEfeCkoAQFJgmTEGUov0iCe1pGvYq9oaihtqiYo4DrjDhFcIV4IKZV2CuMEw"
"yTBheDFNs7VUEBdRUwFTAHMGBaSthCCwAXucxF9fxIddjvjsOVqc6EPc6mGLYMgmoAAiYgfC6y"
"DHXAcOiFsfUsJiqVjF9yBwEAACApje6qBEmAvI7gAkvXjmOxzsdeQKAAQBUUNbBysytJu3F1oh"
"FdRXJMVcAAGC7PGFxhSQkBPJYgAKeXkcIMqqNlemmODCwEdsIO7BcFggFgw4oIuzQE4QadIjBy"
"mC0xnhEg5BQBVsDh6JWC6oC5pYeM69hmNeBEQAAAB4JrdaYSBfbx+ys5DS/"
"SGix57TsYPvYPTnN75qozqCqOlNZERTVJUqIPCezIGsMImlqDbVXjk54G8BQMRM3y4BiAAAAAJ"
"BgiuzGvaSw2COcUPAsKgwQtVLFCAXMjE5kisGCZIk4oKgqJGEATADaK+"
"JGBBRFi1B0EFqu6zGZD5yK7w5uMW46gNdkroOZTDjINWPlOCJ8jJ7ICHT17Ywa4pepioEgZozV"
"BLVrVvUp6wihFEbP0BZBDaymyjQRIY4Wp6b5bo4ClmwhM8OlruXD5FvIACRHyKeT3e6EEYKKho"
"TgnO3b67hOKQIAAPir3b0QhhICAL2E4x1zzGxcR0ZmBTL9qCxGrjFhjGgCiH2YOhgDKmJ1YtJy"
"8xUAANWeUkgZSecbRxsRUxXt4/"
"QEAOR4cVzHpw8fzDoAAADb26LUAxeXWn2M4NKBCQDoUMcAINMAGPK2yQOAifAxxggAAAA+"
"KZ3VGs8Opl93kpyTI2xSuqg1nl9MnzetLicOuR+KTFRDGWR1VZCgOI+"
"IyqoIMjIydNfoqBUj7I2ORdytWZAAAAAAwGcIFVIOy7IChku5BIQGoDEORyB5hHg+"
"SUkMFpICMXcoMEXTghIlQiAUo4itMX/FEAJfOFaddCzcisxAVuDI5C/"
"BAaNwbWSGqmY1Wuqa6qt1FdYsDuaCmYGZFZiZH9fr0GEiFBWq4Sm2NmJVe9c1lSEBFLg52NV2T"
"DBO43HCj2fCdUyAE2rRWyCAs4Au9QQnccwQqfhskEkGAAC8ziIQui0wGgJE2NKnM8J13MkY5nx"
"qwUfou6OV0d0LMDwVwLTgyyL+Ej+GKz80AAAAoBgiiJNi6+"
"xj8W2q1alYxUCsgqc9uAg10OkoJT6yU6oYCBAAYHRFEAAAdAHQIgEUYbVPMI/"
"NmPmU6jRQDKvLdYsxZgD+"
"2FxCl2VHjIAbORGNzjnjs7IRze9PTPwQEyALiQoUlQGC2M8D6B4a2gDjkw8gOmOPvoGFmN5NSq"
"wAZwIAAAAARqNG0ysYsTgPzUCEQgGPbxDyNMKwoAJQCIViREDcKiihCO3uEyIAGJRKChwPdciT"
"pAyT6ODP5QiJiyJgGrSQVUsByq8mQcmUBD1LHlFhQrpERCgFAACgKRYpwNNkVKyGgGFYZTINPA"
"7y4rThFo4ZOKTMgxkVJwwTmEy8gKIrjtdR1fV7UYEUARIDI0fx7TONAC3kxOjfGM6YmExpYh+"
"EtSpleWO+1p6ziSjXSooCmAZA/"
"okWJjoAAAAAjsdJSrFPZ2dTAAHABwEAAAAAAINDAAAHAAAASEashxh0/2H/Tf9Q/1z/a/9J/"
"0P/Uf9f/1v/T/"
"9ThxSNkAfKZZHcwvT9bk446gQtnFQwGkw88zQxMEa6wgUAkqSiKb0lYqgtKiLTxMTADHOsbcED"
"Zm1ioq8n617fHM16LwAAGP0g1wOAGQAAAIBgyvQuAVIIB8Cnu8LjCWrwOJgd1o8nEhcDDFVkEm"
"Kq86YqAF7ZPEBJ42J7xIdyju+ubB4gpYuL6ZUfSrWo+"
"4esKqACKgURiahItg1YTZ3oE9W51Bx6RJw2sAAAAAAAh4LH03mEcIUcygFEWZbH53A5ABEh0qS"
"IuCPOvgrZEaGFspgYAAAA8apAKteLn8K1JdekzFHpUjEH8HoG8EqmugZMOSBPYoTVU4suGL2ip"
"YZOnSLCKJigBghq4LU5Mc2XyVgEBoYJxFL1LmksY7X1I6CYFsMYVG0NW8Pega4AACMRJkZG6KA"
"zYbN1aDvZDk9YDRMQJDKBcxkAAABeBJiTtSISAuEL3V2/caEUAD3l/"
"cT1UdBtEd47CaATYAAA5l8C3vtLABCAOegkFk9j6hlTdRQagUCMdE2NlwJDRyUrsY6VUHkxOWW"
"UhXnGcZ1uNPgARFboAyz0Xm8AEUyIY6K5L2MLIawsNgACDIT5kTIdGGJYLU5FRI2c7lWkCSTXh"
"ZfVygAAAAAe6dxyPkcfmstFTnVHOrecz9GL5mElJ3s/"
"kEUNkIGKskpQBEUlpuoa6ctkB+"
"iJpjI24ngAYQEAAAAAIGDBYSgFjxIenwFLkJKEFFKyEmDhiEpApsXZAcUEDAbNgJQI3URYnAaH"
"VAaDmQEAAKyObK1iUWeLTF92Dm38+"
"BTCiyuP42LIMQ8CxzFzXMwTRh8B43Q5NIQ8eAWFwMzj4G2Ti8ZFcgAEJhetHNcZCRYI9QDUtFi"
"nU7EiqhgCwKm3aABex8yDYzL7oYU4RkCNMhGxYrEaVos9FQGYAQCA4WR0qAfgdDoB6FmMw4gIZ"
"yQLFdCFYdQDGP1+H0YYQQwdpqmK2IGlTAUwFzfkYODIhw/HNddjVWCxlDDXfeBI/"
"VySEdFdiNTCAJSg6qC44iIrRUYLeidggE6tgQgAEAgXKCqLYm/"
"YCDbiC1UrkEshOoDBAB7ZvIlUHHNQXOVBqCSyeRUlS140a3sRGvlAZk0yRAnVWVGKjAxRGUzdS"
"Xmhh92Qk3iciCQAAADAY20asg7iCcEXgFCGAOpMEJBSMZtMMcUik45mOjVLZpwwcSFLOR6PB5D"
"hjluXmVVDXg9mDnjADBNpgFl4XFytJEGCT8fkejw+"
"JaNkARjcrYwzDoRHgk0Yh0RHKWW0ajhjznLYjSUxDK/"
"Md8cFM0MXKMZBXYdrsGEGRFJXrfBtHac4g2oqhNWgTPAUAABOoSKElcjjIqkQADrgzYrqMop5Y"
"Wcni7RSJtA6qrWegui9kxuENayEOC42dzyLXDABFtPO1NJABa37q0EHjB+yz5cgQ/"
"QIT4ALk0ObCELMcSJEXRGM6/ZtpQi9AOPujcpbFJfpDRH/"
"TgwthqkIhpMtGMZQUIlGULX6rZiuB/"
"B6DADAIwBpEgCSVQgA3mi8+"
"5gyE3Tt01gRGbNovLqUliao7dMwvEGNVYlItLlhmdt1UT2uMFGReNyARQjKAQAAAMQQ8GnrgM5"
"huDEOGK4nLWBIuMItWURSVFZCEUI4DQBUXybOjpw6tBF7U896yhwn2j2K0c/"
"EgAVcKxNWMI8Z3LqejHpVW1Eb5kjIA1NpqN7orXSMevC6HpNVSNFhAkmOMDnmw2sq/"
"UVhZipwcYDSb2AIQtRV7rgNoFy3SCwwA6ZDahcFYXG347lwE/"
"NVTKjELdYuy5eJm3qY4l8FBQH4JFyAGYWuKFcxn3INwMw1jBOGATpa1nunK8q03an3RC90jib0"
"w40xMEZYUetcOt3odtA6OtIxwIXEzPyZogjSHCN2uJztxPSq73YIGD0cIjJhCG2ioxVogIUJjd"
"a0ACgkxuyQamJrb7EROxsdVbUs9UwGyVu81z48Kq00ACCyiwAGQRgALGu8AwBeB+"
"w0ZdKMjF9KFMjobjjSlMWkVHwqYRG+"
"oagRRJK5xqaZ3l3eVElV6CyZESIkAAAAaDTKHTwifEIjQpuFoBBjMRFSEhWyoNz3CkWsM6Tt1A"
"krFnvfzn7sygxqu08G9nYWBQtuLSEwxwXXaya6/RhaA/"
"NiEvJ6VMqR6zoyrDbXU8UM2jHXY2vSp8w8HkcZWbTHTCYH/CZbYyBXjqpmwJbGhCGsXDPXZ/"
"geTrtyUIbRJq2maeN/"
"YnoDtYjFWuJARAXTAiscRzIzM6mUokaLBpWDa1QSA2zZdBksXOgD8CBBjihLH3ywlp4YFqqHd1"
"owTlDjlIMArNJpSxgLKzw1Xo+"
"B40U2ZqOcUSIKymQZqsdydKjwiaw40pmcRVqGTWEFlcIcGdYbQy/"
"I3e4JY7MvDI1R2IuCTRVAt2uUAWLLjEhdpgurtZEItvq6sXWj03snCRNW2g/"
"NADYxQIRnpQAp2w8sFGEJ2WP0SjsJAN43nH1J4wAW8NA3nH1JcQCLAjwcmQuCgKkyttcuKZeoi"
"SASUiMIAAAAZDERUQoolxNikjQtzhCnQIEIBJRoOaGIf3vTfgYnJqzTWWY6zUSsjYOvKuD1sXi"
"Mqslr0rhIOK7jRlgkVGcYsTos+LAwC+"
"qMAByG9kcbIojamYKhIipOY3yEt3gAxzETJvmUueY1AwDXNeSYydGCa5hDy+"
"uqvSlKG6jYmIYVcwSO48U8hmSYyZGRHhdk4y2ZYCJRIsfoaYQHAyMeiAQ9nKsI8oY4kxOIEILQ"
"lVBQY0BAAoD2m4uIbsWRIxc8gWu0myBaGsUowfXXk9BX+"
"4kLKYIBTgM4hYGO6p2WDgEkxlCnjkSve+O4tAkAABL/"
"7dSQZsbc+VZbCbmdQasaeBENAOj3GRMZALlKJByPAADUxM5qihoKQGInJgBgbHkCKAB+"
"N2wpBh7I6TIXTuZu2FIM4oEcLnOBZI7MYJGnNDFVjZWuVFwkZopbDBIAAEBETFzoQVOgaBYRCI"
"WUqDglIhCIiFIUEaXERYmIOrCooPZWbB1Xi+t6cOV6HC8CIS9mQEyhbhzjPWOooTC5Ji+"
"YmUxYh4aCBgzRGwpWmaoAouDPdxlEGEON+e4gmXBdjFoEQgIkTl1yhVpFckb2CEl0Ou/"
"IHOERyAwh1wWZDwckTKQEIKz0pgQAAhMbGQowUgZiBkm+dz0ACaxoLwLBIfVO/"
"fUyIlhWARrJjayiTyIkXIDOM8K4/"
"GFyE1ZgVqblQ11wSfg4M55AR51jYoTpcXIMUb91xI7QoQdMJPrHBGijj3C08L3YETVl0OeA/"
"F0BAGAYHAEAsxkwjwtmZgmAFo/"
"rMdasMTEBZ0xMoOi9gMjhpwBIhfUCnjccaw1yguphjce84VhrkBNUD2s87WbS2rmqq9vJ2BWHZ"
"cYNAgAAAECcmaJEaZpFxIlQTCwOsbU4YWOxmo7ZGAaO4RA7MR1XHKhptcWwE1OcUDHFVDFU8Ch"
"cXMSYTISxqEdEZFuFhLxORS4UKnBhdFFQPYWbkvl0XJnM5DrgMTArTLgCB7wyAJMJCwUiNtGFA"
"RwcBObT8ZjAXKBdOebT43Vdr8eHTy9gyAUXGeb1AgLXxKHTh791tTphShMRY6VnND8VJ6I2gWm"
"E5vXS2IRGRA7G6Pplchz9iRiatbSjQw/"
"o9RG0BOPhJt+"
"EXHNrC6QCXPMCIEOYERci0McYOkaI8f8OROg4CHSghUEXiAC1VNB7E0rHWXV0GBecjhRMgPYsP"
"Z+"
"tXz8AAORpKHpnRgT4PxUCgdaFLn1bfpig8MvGGe4AAICpXi8pT3291qQDAAAJPjeckw9mQbUYE"
"jKGueGYYpATxLywPV+"
"qRESUEBkZ01Rd7ZVLrBNmEzsAAABAMpGQzAxIFpItToiNvYkVi42TDsWBGuKEwDgMtoZjlolJG"
"9/leqTFu/"
"hYLbhrsDUFi+"
"2gE4PqNFSm66oco14twjpVYgIJx4MrJ4Jc64CLFRzHXMnA6whruS7CDNerpnTwllKYBMhkOkAf"
"HdGKQDgOXoRg3UuvCqomZ82ka2hluODUte/"
"mQC3fQSZMRKaKIioGQ2O1qNbYwNDtG3YREyAASUQxmggzACoi6IUk74JHXC4n0XlE1ofNBcawX"
"B/jNOd76rjxMMSt30R2vaduv/"
"TDcquhxZXaMUwyR3gRYoUAR0fpACapOgZjAMCCkyAl47SOQlQX9UbPrclh/"
"sCJYACWn7Vu7Pf71cnkAQDERfpnLAC3RVrsh0GH98kRxlNG/"
"F1AN2RXSareh0aDAAwvaVKAkwA+B2zFB9EghsWC5zlgKz7QQFjA87EHkLpzR+"
"7Estuuq7vCLnSOscwcAAAAQNFCSYHAJaDFaUlKICYQgxBi4mJiAC1K0SIQZZoWJQIxlEOMiNC1"
"3a7A8I+NjcWwtZRD0/HpuI5MjvCaYxg4dBhVTIVN77SlMy69/"
"gbXoF5YyVxpkRz5hYHAXCThINdxMDwSLua4huR1JJCoMxiknUEnYOUAhrXVOLi45jWTj7HFNWG"
"OPGocAzOxMrN0DWQCQxi4eB3HxQHizLNywJKAOo0nkdKAcek9a+"
"ttYcQ2wQI3wwAAxngnwSoMHDMzxytkDIWprhvO99dwNHc6vccsXRczx8wcr3VjHLH1O0rtnxB6"
"3sscGhAXHdCDtHtPCXQMhFAn0QGI7FSPk6M2dPvdgVupidB5eFdkq9M3Af3YoJt6QJKOEHCyp4"
"ABq0sII8C1Q+"
"oi6RwPj0SuwCfI9SIAHjcsqQazIHoY4SluWFILdgJe4OmYEAgOMxwGCEBXJ00nhuOkkokbJAAA"
"gLioCE3R4hRhSgChi4iIikiKijBFCcULJhCKCsWZiHCFuyjEiZAZbpQog1BgIiqkaQrPKryGa8"
"gVjrwIk4thgCRzzU1UbWxsmocJkPBccekpoJQfUUgIrCJK1yk9gMl1RXL6MHoD4hkVjHNFYYWB"
"ImpdNILVUdANYbGI+S4P2CBj5PV4MNdk5mBkIDBoTLOmTfR/"
"pze6Rpu4rWPwyMAMMFGnii7jVkOCYBUlMpGNNxPDCEx3UUfOMMzxmg6xYM4viYQWQykoCaVMMW"
"uMD+l9GL8jtYx0wEVIS4uhGUJP1gZCCIOOoEVYDRgyr5mZURKJDkIGPkPr/"
"shgABdMKPorPG8xRIFWCmF7ROs1NMAwwbswp35SMgl5wpgBw3y5frcAAO5RAZ42TC7GyEOjj5e"
"lNLKHtGF0MYgJurhaF03q8a7OShARqchMZ86cOU81OVd0V6mYjB6K5RGQAAAAgCQ0MEsI6sIFK"
"XDJkiIiQtGKifLpycL/"
"qdOjOVkOjLR3Nm3sdq2qatnFV4pTUdT00l86gWIRFNTE9QjDjIIwSbByTQ4Yrhz13GmBQxfhFA"
"RxAkVQVBW5rr8Q5mJWt0LlxBSWFpSZXMegNPNiDoChel1lNACvYZjjmgDHXA+"
"g0ooMHEamoYDxMsdMFsKnUEPH3DbR6PXRFLpI5gAqkWRQwcBwyjh4FJjjQ0NGWCyRO43sAacOQ"
"7ikYB1UbzLJKxNGI1zXdjAwsE9nZ1MAAYA1AQAAAAAAg0MAAAgAAABdaUsxHF7/aP9I/1T/"
"Zf9o/2VCaGv/Yf9P/2xFSERse/"
"9GhzM8e5fRoM+b5OAGfAv2HQqqOog9JsfCj3TjREdf7JhGeAIAhCGAs/"
"3wAwAMjwBAC7pdHQBPIwHifACATdHdiX4sBayk0G+"
"19VdyEWOOLXK8AdCFWC0f5wAAFOAfPgesvcRQqFgV4CluWGoKTKAt4Olup2ZJIMvISBlWHnO50"
"fWUcDoWmck5igUAAHBjumQpndi5qSAu+"
"2RKnKK5XMzEtEIg06kf66Tfx4ZMz1Q3nfoNprOHC5h+kTtLFaUxhFFYm89qYmLZhKF+"
"h0YQywuvFabB5JphZqURU8W0hjYqiF4fhyuXnXqXdRZMigCBCwaGzNaIAWzlgAsmxxwhU1H1uO"
"PC4qUaPWDxURWwBwS/"
"g0sFv5AE6KC6KF8Anowg3yMtWjA6qg8HygEwOinpdrtjYsJgSEGGwEiqi3IwZ4lsKElRsRDvAs"
"YKwBXmtBk2tbC0ZY1ZXUuPMGGCqMuHp1XHDX3UoC+"
"UX9zoGRB19DemuhXgYyIYihW3GykLE9z3UsNEbUEMd2aKFXC69HrP5n+"
"s3moUYlwUXA9esFLvXI+"
"v7UVde0fwAADUYjKA2KsJGswMFQ6tBX4CAIDMl1N4z1MAAAAqGQCeNvSuBCZgBU9pQ29KYAJW8"
"HTXUsoUGSgzDWbMXKnQADGacdErikwJSAAAACmYiEERUkZJEKmgIFrG8BYsrgIqQQkpiNIQgoW"
"EOCLKMNX0b2NvYzdV1M6Yzr8gIogDm9ZCTfOJmZCo5RaToSEpnI50Do0jQ4mLuCwweuqE3iPz5"
"Ua1UONIruPhDfWhHowMniJMJIs+rNc+UjRohCNPrtYiRLGxmphYta2KPYNxwqnz3BAfSR8+"
"r5vo6BH7ITRKPJgMw55pYxAjtzXdYUtYOUlsOwEPjisZOGZGwknTpdBIFnEBgxW45kCnII+"
"JFgUAnjHMZcoLGIfUpWMggzitIVayXObeOyO49pfWMeKET0sAIgghvjs5ZCDUqW+gI3QB/"
"jrBrcgBIbaerbWY0DEmnJkAACsA6Q2wJcNud1FAB+MQ2PmwhiVkBQD+NuwxBjlBVy+"
"j7elt2GIKLKj1Mm3PhwmwYs6ws1cd1+"
"biUjKOMTcBAAAAREXFKFEWEQhFaTFaBJSYQCgUF6NoAYQiFSIQMQ2xsdpYbKyG6ZitgTqy2hoD"
"ajVtNXyZExYfJhjcFq4Lo/"
"YiBlAwCmXUtWSuDFcmjxkh3iCUEHPG47pIAklUBSbXQym55pSOaBgbYtG7XNUnRN7O7SOot4ek"
"OJjHycaH45rJ9el6TUKMIRfMNa9j7UEIugkBwgdrlTEJYRh3hgQCD4C8DjJkVrjgyFqiixylBs"
"4ImGVZRFhpqC6Kl5cybwTJ9CQi4zJOajqANYToGaqJAyAMYQv4ZU64M3TrKELHDYHpidhtgTtW"
"IXgAIGtHONjqd2vVRwIAxlAAoETnLWCKxCC6BXQ6AiD0RyBIkQkCFgCEsoTQB6ByY2wrkAmgTS"
"bzumo8bcity2wT4AC+"
"NmwiBbtMOg9jeF4DFuGDaSY1Xmw7gN4VKgAiIImU2zEBU1XprrhOwmYsdiAAAAAwRvhcDpfyKB"
"VwuVyGAEIxoZtvQjdJAcTFBOI+"
"EXeVSm5lLkogpKUeVnjkuq4Xx3XMmfD6cByzWonS8RjBIqCjq7DAgCNhMoEc36xgMsRFIsLKKP"
"ABCwEADqUu0oP3cKhH+AxA7IjucHffIRFg4FKYTBgeUo5LzMp8un6P4+DDIzMcV+"
"b6njKB2nfHGmABk0G6XlgwAHYKHxFdz/"
"fSgoOFxpQsgHJPDqlT364nHBXXEhvHAVOlBMObCAfXJsNEW8VNDAHgCtVHTXsYoyNh9EQPco1I"
"16PfOos28UYwlLBMdP7qnBTAba2w25wMGRTd9jxoW/"
"0LD8AQqtcXKXDqIYsjEgAgwm+MIGhxJJ1HG0DH6KIA2l5GaCOGjt+"
"N4E7qRgZAqCsiwrsQmRFAyDNdM8DlOOZeAF4HXLwLphj0eSFne64DTjFFZSLq46XIYvB0V0RVC"
"aQoInfFkLNLOVeVuE4sZjIHEgAAgJmVkBAkHRwAgZhAjJZKQGZHjBrIgPHZFvNMi8W08cHq7to"
"oZ1/"
"bnTplsEyvk2IyOF4CJZFLDV+"
"EEnDwpfTQqs3eexZGggtd4arG4ZXxXqLMWaquTbRJGLJIb4YBdM5L6XJGxOkrcoVDLqaKnKmDH"
"FHHLfYMDEjmhCAXr1TKkXkC1Bi0F5CwRsd0gHoU2T6dggaYyJ0ALvh+"
"3QpjABFwHKuw3wDovfPSTREWXBdhIe6UxALG+62jzGeQ04qVOSgC5EyahRCl+"
"cENZIZrYG6lHFm03BczCsVIO1pS9MNEh81Dp2s3pv/"
"aE7kJo25ZBeT4pml0gTAuF5abHe19EskfAfg+TDuffRgA0NuiuNGEEfjlebmjrE5hN/"
"cBZ0I8SQ9wOket640+"
"FiaiT859USQNpVU8JMgANjZ0ySTjIuACT2NDF10wIxAe4OmuqqEylFkZFVlGWZWZu4c4t1gptZ"
"WpvK6EUyUWkdlBJAAAkMYshYwaHkcRRTlLGAIx2lOCEiyniUAgaW6iss8SZevVSrr1uvIalYvh"
"V+H6XY/"
"5I0tvxe+4vskAmWsh9R3utFYXWR+yB+"
"K9uTrjhI3Oul6dRKRkRhSxyOgsOYim6ruDEAioHRctK3dGQkYZjRPLZiPqbsZ316ha6WtSm0mL"
"82GyBnN3TMBMVDHJwJEhOWK1MnARAw4K89uYGQDEI5TonZ5SXRgAOgpG4TLE0kk9YJHApSNw9j"
"A9nTBSHL4Sa/TBpHTpQupIdUSoM3JIT6NvLJm0AteV/"
"JgrQ2wAHWGSQLgVkDAMlPbqcuQyI5oG1LsXYDxvADWwilwj7ST6RgPMyhMDFAJcSDO8Y4LuqbU"
"6XS7ekbjouHmmAwCEugMAAIy/"
"DQA89rVFBlDIcLKVgAVc+UQCDBfOqdq7+"
"gkMSOAcdf9k1ZIZEcwrIRkwtMikFa8WOYBv3mUY9FGF9KsIEDiMDnUkmd2DmqD1wTAcH/"
"LhFQCs+STkJIWbf+"
"i1noRUk8LNa4RaNStrliIy7ZmnJZ6KioqqiuB2ZkveACC5lSARpEUIHQGhRMBlROiLPgrqdPjo"
"gN2JQIRiBgD4pYZpa2+KQ78cs9rMZCZTzafreLRabNW0cYBiiMDvAXwBBb2KvZavEyjk+"
"wIKepX0LF8nqJBv1ayhrChFxNjsdKRpGaG6jIzMVEZlDWUEIA3SdddcSYkTWjQFFAsYTACQKMZ"
"O1oqYJ2Tbmf3GdFJMw960FYemjWlBDQeOY1htBFARwV4cDQTZkZIIGjYUGgX/A/"
"21UBF4jsKEUhJBf2C5eioYLxB6aqyuijIjK7I6iojILMuK6pBFBuw74jgO7aoq9BbPbaS4GiAw"
"EgAAkGBJxEzEIEkEFoIhIKWQDAh3SuiC0KHdxMTFhAIxOLJV1wQMW8PE1vTl9eEZxxxhrmMbrx"
"/MS0UeK9xSwuXSMUXQbhgycx0Mp3Tw4ZUwD2ASItldCUp1C2ktjhwrXjxkUcoMBh08CsMStQIZ"
"nQDIizFhKHXoMJJDBhc8JcQT4vVOC2F1PQgHGRYmpBsjY2hA5nER5rjCVEuuFwGYXKPfDyEIWs"
"TohzgCHVjWMyIk478QRFHTYme1mKYgFluL1dZG1c6hYczUsDHf5dN1VmsPXhcHr2EeA5ODQBYp"
"wngdgH4bQXdo3T66QMAEwshJAACEwyJ1Obi+"
"zPXg03G8clwLdelg6Z2hrgBcj5UOXvn06XHleAsAAIAMAEkAdyjABX42lE6HPoLaZ1POlTwbGi"
"dCjaD2kZwr+"
"Q4VkQA4ogN7WiemLlehh56ejBAssocIkyQAAICQb4yDR8GCoeAR0CK0UITQRETANGFRyG7sC9x"
"lSkTSjRIQERG1ADaIvxETVfXU8GMKID6iYpp4BMIlKmBQuH4TQBuSNXhFbSCTSTLkwyMQwszMg"
"o54Z0R0hpQ0AZ0OnuIiw29a8ABmGNJkDg4e4YTeqbNokeh0xmnC5y0gpJ5Bj1BvPs11ZEmzJMb"
"z0G0v3YFhwKJTTyIc6kOJq+d5GOFVDZiECVpHgA7oATQoo97QCBCXHhkmB0wy5NMxJK8Pr+"
"QKcxw1bQzDtLG3KFZMBXkNC5lkEljwgBMUGFoAAMYagAkmIqDbIQCEgF8Ljhzp0RE2AwAAbSa/"
"ZIXJfHMB83oRAAAAafi2AExM4JxtN/"
"DESd8CtKpCoqoscAA2BjReBHlA7Dr+"
"HNEY0HgZmCD2ncGXE7prqIrKSFkZkRk1tW2cs2HvdjbD0cRyrq2T6rCxiakgAQAABKQRJAlmkk"
"JAKBAVF5cKZFFxSkwoTmgxIRGAZjEKtCglJipmY2uLrWKI/"
"WiYtn7Zy+"
"tWveCVuSbHdTBz5XjNdT2GZpl8RujoCNPweHEwMGGYzMzxLEshzDGZLImB15OIsBEYhvB5gsDM"
"EeAHiGJoD07S7dBLmNetmMcpkSOvJGRmuOA1gdKPvI4jMzw+"
"HT2BsUB1ZqLRRh6A4eARZq6FAN8SsJ4ajPLrBOBC54kTicW7LXMgsZANqjM90+ucyIQE+"
"H1DFQcMemZmH4mh9q0wc7wmU+kDx5UXMQVggMzpNHovTChAe/"
"EA6feMuge9d3rJlADvHSxK6Mpo0EYgjT+"
"lN4DLlZ4t1YUZJwBdgogOevvBVmv29EsXHcYEAIb4qOJcu5TvtVOAaYiBALGE0ykWcDNs+"
"VALJFMcp9F1Fk+"
"wwJmi2BpdTNSsUUrBItgBxJ6CAOCx8ID52yQZjpnXdV0cwlCG2DCmqaY9hnRcJ6cWSr8wmTurP"
"gl89cRIzKBFcO739eUTHFGDJuXU77q8qhII6hA6APgEAp6Qo7xFV495hVEj1zVWI5KLtbUbJY/"
"jlQdd0/"
"cyGKjgGIbvhVNcCwBs+"
"VDDUEANE7nG1o6SDAnUMLFTeVERQTLhCAcQMpQPwmGZLNoaoa4IXSj0kbpjcmOkR7ggzG8dydA"
"bPgixyHjNx8yaACT9fEbDNTnZ7ZPPa0FWTGfW00NVR9TbZtbUtiluzGZGAQTQv7AkEoSmiIebh"
"zhAIABlEHq60XRvRYQoY0q0EDOtDqfMqPamA79tpsPWCccc88ehQ6ti2Nk4cGTnt8UUtbWO9j5"
"WHEdmHh+7C9wIRcbudjS9CXjM7kaocWm3CfsmIKfZpvtHUVaURZ6uy8pxxLmzR5SEHNsXspeo+"
"DDzw4x9MaFSHm6tIyWiFempO9P2dtOMiWnTObTzx19O+Msvi/htb6NqsZ/"
"O3s7eMiJWj9dTFq5AEM9w6Lh/X076mm6aA9sCSIoJAHo13PxwXzBABvcU8c/"
"u7iQHUUTgzNM0Wo1dlmJRzDKZSAAAAAAwJwLO5a/4yl+5v++H209u/"
"94v13Pn59nDcvtSL21xLUpndfvy7VA5//"
"w4f27LOL795PYo+f7974+"
"SXupFFhk591zTOL79eH98nts4eItR07Oe9axnPeuZE0CZ27tPW1u3OzOKit91rOe+"
"1K7jFmVbZRyPx0AxaDGNyYnJp/7+eXL7yaB/9H/Pku1wvejpgenJsPvz+/"
"+mrSgjkevxerzVlbPImoxrYbKeY8BJsnrRY89KMmG12IoUvs3b7eanpycFiVHdouYWg8lsNmt1"
"FS+33+9zIiFVOq5jbU9nZ1MABYA2AQAAAAAAg0MAAAkAAACfd/skAWoWAKqz3++H+/"
"T0pGA6hrVD9XUrrc4zc3Nzc/r9sOZyIGq6bDnpYwKensDQ9y/"
"K37+cAFtbW3TudhWOtwZzlstb/X5/a6vf72/"
"x5+fm5nB6slBlZ3Fcha363d5ut7u3ni1rLoPf728l3KcK\" allow=\"autoplay\" "
"style=\"display:none\"></iframe></body></html>";
class AudioOutputTest : public ClientAppBrowser::Delegate {
public:
AudioOutputTest() {}
void OnBeforeCommandLineProcessing(
CefRefPtr<ClientAppBrowser> app,
CefRefPtr<CefCommandLine> command_line) override {
// Allow media to autoplay without requiring user interaction.
command_line->AppendSwitchWithValue("autoplay-policy",
"no-user-gesture-required");
}
protected:
IMPLEMENT_REFCOUNTING(AudioOutputTest);
};
// a common base class for audio output tests
class AudioOutputTestHandler : public TestHandler, public CefAudioHandler {
public:
AudioOutputTestHandler() : audio_stream_id_(-1), frames_per_buffer_(-1) {}
void RunTest() override {
// Add the resource
AddResource(kTestUrl, kTestHtml, "text/html");
// Create the browser.
CreateBrowser(kTestUrl);
// Time out the test after a reasonable period of time.
SetTestTimeout();
}
CefRefPtr<CefAudioHandler> GetAudioHandler() override { return this; }
void OnAudioStreamStarted(CefRefPtr<CefBrowser> browser,
int audio_stream_id,
int channels,
ChannelLayout channel_layout,
int sample_rate,
int frames_per_buffer) override {
EXPECT_FALSE(got_on_audio_stream_started_);
EXPECT_TRUE(GetBrowser()->IsSame(browser));
EXPECT_TRUE(CefCurrentlyOn(TID_UI));
EXPECT_EQ(channels, kNumChannels);
EXPECT_EQ(channel_layout, kChannelLayout);
EXPECT_GE(sample_rate, 22050);
EXPECT_LE(sample_rate, 48000);
EXPECT_GE(frames_per_buffer, 441);
EXPECT_LE(frames_per_buffer, 1280);
audio_stream_id_ = audio_stream_id;
frames_per_buffer_ = frames_per_buffer;
got_on_audio_stream_started_.yes();
}
void OnAudioStreamPacket(CefRefPtr<CefBrowser> browser,
int audio_stream_id,
const float** data,
int frames,
int64 pts) override {
if (!got_on_audio_stream_packet_.isSet()) {
EXPECT_TRUE(got_on_audio_stream_started_);
EXPECT_EQ(audio_stream_id_, audio_stream_id);
EXPECT_TRUE(CefCurrentlyOn(TID_UI));
EXPECT_EQ(frames, frames_per_buffer_);
browser->GetMainFrame()->ExecuteJavaScript(
"var ifr = document.getElementById(\"audio_output_frame\"); "
"ifr.parentNode.removeChild(ifr);",
CefString(), 0);
got_on_audio_stream_packet_.yes();
}
}
void OnAudioStreamStopped(CefRefPtr<CefBrowser> browser,
int audio_stream_id) override {
EXPECT_FALSE(got_on_audio_stream_stopped_);
EXPECT_TRUE(got_on_audio_stream_started_);
EXPECT_EQ(audio_stream_id_, audio_stream_id);
EXPECT_TRUE(CefCurrentlyOn(TID_UI));
got_on_audio_stream_stopped_.yes();
DestroyTest();
}
protected:
void DestroyTest() override {
EXPECT_TRUE(got_on_audio_stream_started_);
EXPECT_TRUE(got_on_audio_stream_packet_);
EXPECT_TRUE(got_on_audio_stream_stopped_);
TestHandler::DestroyTest();
}
int audio_stream_id_;
int frames_per_buffer_;
TrackCallback got_on_audio_stream_started_;
TrackCallback got_on_audio_stream_packet_;
TrackCallback got_on_audio_stream_stopped_;
IMPLEMENT_REFCOUNTING(AudioOutputTestHandler);
};
} // namespace
// Test audio output callbacks called on valid threads
// TODO: Reimplement audio mirroring support (see issue #2755).
/*
TEST(AudioOutputTest, AudioOutputTest) {
CefRefPtr<AudioOutputTestHandler> handler = new AudioOutputTestHandler();
handler->ExecuteTest();
ReleaseAndWaitForDestructor(handler);
}
*/
// Entry point for creating audio output test objects.
// Called from client_app_delegates.cc.
void CreateAudioOutputTests(ClientAppBrowser::DelegateSet& delegates) {
delegates.insert(new AudioOutputTest);
}

View File

@@ -37,10 +37,6 @@ void CreateBrowserDelegates(ClientAppBrowser::DelegateSet& delegates) {
// Bring in the V8 tests.
extern void CreateV8BrowserTests(ClientAppBrowser::DelegateSet & delegates);
CreateV8BrowserTests(delegates);
// Bring in audio output tests.
extern void CreateAudioOutputTests(ClientAppBrowser::DelegateSet & delegates);
CreateAudioOutputTests(delegates);
}
void CreateRenderDelegates(ClientAppRenderer::DelegateSet& delegates) {

View File

@@ -2836,7 +2836,7 @@ class RequestTestHandler : public TestHandler {
SetSignalCompletionWhenAllBrowsersClose(false);
CefPostDelayedTask(
TID_UI, base::Bind(&TestHandler::CloseBrowser, GetBrowser(), false),
100);
1000);
}
// Test run is complete. It ran in either the browser or render process.

View File

@@ -11,6 +11,10 @@
#include "tests/ceftests/thread_helper.h"
#include "tests/gtest/include/gtest/gtest.h"
#if defined(OS_WIN)
#include <windows.h>
#endif
namespace {
// Test timeout in MS.
@@ -24,7 +28,21 @@ const int TestWindowDelegate::kWSize = 400;
// static
void TestWindowDelegate::RunTest(CefRefPtr<CefWaitableEvent> event,
const Config& config) {
CefWindow::CreateTopLevelWindow(new TestWindowDelegate(event, config));
#if defined(OS_WIN)
RECT rect = {0, 0, config.window_size, config.window_size};
if (!config.frameless) {
// The size value is for the client area. Calculate the whole window size
// based on the default frame window style.
AdjustWindowRect(&rect, WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN,
false /* has_menu */);
}
CefSize window_size = CefSize(rect.right - rect.left, rect.bottom - rect.top);
#else
CefSize window_size = CefSize(config.window_size, config.window_size);
#endif
CefWindow::CreateTopLevelWindow(
new TestWindowDelegate(event, config, window_size));
}
void TestWindowDelegate::OnWindowCreated(CefRefPtr<CefWindow> window) {
@@ -62,8 +80,8 @@ void TestWindowDelegate::OnWindowCreated(CefRefPtr<CefWindow> window) {
// Client area bounds calculation might have off-by-one errors on Windows
// due to non-client frame size being calculated internally in pixels and
// then converted to DIPs. See http://crbug.com/602692.
EXPECT_TRUE(abs(client_bounds.width - config_.window_size) <= 1);
EXPECT_TRUE(abs(client_bounds.height - config_.window_size) <= 1);
EXPECT_TRUE(abs(client_bounds.width - window_size_.width) <= 1);
EXPECT_TRUE(abs(client_bounds.height - window_size_.height) <= 1);
}
// Run the callback.
@@ -108,7 +126,7 @@ bool TestWindowDelegate::IsFrameless(CefRefPtr<CefWindow> window) {
CefSize TestWindowDelegate::GetPreferredSize(CefRefPtr<CefView> view) {
got_get_preferred_size_ = true;
return CefSize(config_.window_size, config_.window_size);
return window_size_;
}
bool TestWindowDelegate::OnAccelerator(CefRefPtr<CefWindow> window,
@@ -126,8 +144,12 @@ bool TestWindowDelegate::OnKeyEvent(CefRefPtr<CefWindow> window,
}
TestWindowDelegate::TestWindowDelegate(CefRefPtr<CefWaitableEvent> event,
const Config& config)
: event_(event), config_(config), weak_ptr_factory_(this) {}
const Config& config,
const CefSize& window_size)
: event_(event),
config_(config),
window_size_(window_size),
weak_ptr_factory_(this) {}
TestWindowDelegate::~TestWindowDelegate() {
// Complete the test (signal the event) asynchronously so objects on the call

View File

@@ -48,14 +48,17 @@ class TestWindowDelegate : public CefWindowDelegate {
const CefKeyEvent& event) override;
private:
TestWindowDelegate(CefRefPtr<CefWaitableEvent> event, const Config& config);
TestWindowDelegate(CefRefPtr<CefWaitableEvent> event,
const Config& config,
const CefSize& window_size);
~TestWindowDelegate() override;
void OnCloseWindow();
void OnTimeoutWindow();
CefRefPtr<CefWaitableEvent> event_;
Config config_;
const Config config_;
const CefSize window_size_;
CefRefPtr<CefWindow> window_;

View File

@@ -172,7 +172,6 @@ void RunWebUITest(const std::string& url) {
WEBUI_TEST(appcache_internals)
WEBUI_TEST(accessibility)
WEBUI_TEST(blob_internals)
WEBUI_TEST(credits)
WEBUI_TEST(extensions_support)
WEBUI_TEST(gpu)
WEBUI_TEST(histograms)

View File

@@ -40,7 +40,7 @@ std::string GetInternalPath(const std::string& extension_path) {
std::string internal_path;
if (!resources_path_lower.empty() &&
extension_path_lower.find(extension_path_lower) == 0U) {
extension_path_lower.find(resources_path_lower) == 0U) {
internal_path = extension_path.substr(resources_path_lower.size());
} else {
internal_path = extension_path;

View File

@@ -375,7 +375,6 @@ _simpletypes = {
'uint64': ['uint64', '0'],
'double': ['double', '0'],
'float': ['float', '0'],
'float*': ['float*', 'NULL'],
'long': ['long', '0'],
'unsigned long': ['unsigned long', '0'],
'long long': ['long long', '0'],

View File

@@ -445,6 +445,10 @@ def GetConfigArgsSandbox(platform, args, is_debug, cpu):
# Avoid /LTCG linker warnings and generate smaller lib files.
'is_official_build': False,
# Enable base target customizations necessary for distribution of the
# cef_sandbox static library.
'is_cef_sandbox_build': True,
}
if is_debug:

View File

@@ -941,14 +941,20 @@ if platform == 'windows':
# transfer cefclient files
transfer_gypi_files(cef_dir, cef_paths2['cefclient_sources_win'], \
'tests/cefclient/', cefclient_dir, options.quiet)
transfer_gypi_files(cef_dir, cef_paths2['cefclient_sources_resources_win'], \
'tests/cefclient/', cefclient_dir, options.quiet)
# transfer cefsimple files
transfer_gypi_files(cef_dir, cef_paths2['cefsimple_sources_win'], \
'tests/cefsimple/', cefsimple_dir, options.quiet)
transfer_gypi_files(cef_dir, cef_paths2['cefsimple_sources_resources_win'], \
'tests/cefsimple/', cefsimple_dir, options.quiet)
# transfer ceftests files
transfer_gypi_files(cef_dir, cef_paths2['ceftests_sources_win'], \
'tests/ceftests/', ceftests_dir, options.quiet)
transfer_gypi_files(cef_dir, cef_paths2['ceftests_sources_resources_win'], \
'tests/ceftests/', ceftests_dir, options.quiet)
transfer_gypi_files(cef_dir, cef_paths2['ceftests_sources_views'], \
'tests/ceftests/', ceftests_dir, options.quiet)