diff --git a/AUTHORS b/AUTHORS index 45e7e6d..253a383a 100644 --- a/AUTHORS +++ b/AUTHORS
@@ -580,6 +580,7 @@ Tiago Vignatti <tiago.vignatti@intel.com> Tim Ansell <mithro@mithis.com> Timo Reimann <ttr314@googlemail.com> +Tom Harwood <tfh@skip.org> Torsten Kurbad <google@tk-webart.de> Tomas Popela <tomas.popela@gmail.com> Trevor Perrin <unsafe@trevp.net>
diff --git a/BUILD.gn b/BUILD.gn index 4fd53cc..3522948 100644 --- a/BUILD.gn +++ b/BUILD.gn
@@ -708,7 +708,7 @@ # these are needed only for gn to discover build files. deps += [ "//testing/libfuzzer:libfuzzer_main", - "//testing/libfuzzer/fuzzers:string_to_int_fuzzer" + "//testing/libfuzzer/fuzzers:string_to_int_fuzzer", ] } }
diff --git a/DEPS b/DEPS index f0c89569..13c545e0 100644 --- a/DEPS +++ b/DEPS
@@ -39,11 +39,11 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling Skia # and whatever else without interference from each other. - 'skia_revision': 'a37662937cb0a44b5d75a9240cfa9587b4d60e9c', + 'skia_revision': '211df380655d3fd0c76b9b7f8be399040ca0b7a5', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling V8 # and whatever else without interference from each other. - 'v8_revision': '8449739a818e50f08aa81cd21a0477cd5f97843e', + 'v8_revision': '88d3129d9b98d5cfb94655d622f6505291d87cb4', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling swarming_client # and whatever else without interference from each other. @@ -87,11 +87,11 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling NaCl # and whatever else without interference from each other. - 'nacl_revision': '546ef11ffcbedf8c33bfa12643408c1182b6839e', + 'nacl_revision': 'b6ec17db8c2958f3455043e29000f17354336fb8', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling dEQP # and whatever else without interference from each other. - 'deqp_revision': '194294e69d44eac48bc1fb063bd607189650aa5e', + 'deqp_revision': 'cc0ded6c77267bbb14d21aac358fc5d9690c07f8', 'deqp_url': 'https://android.googlesource.com/platform/external/deqp', } @@ -190,7 +190,7 @@ Var('chromium_git') + '/chromium/third_party/ffmpeg.git' + '@' + 'c21cf0893cb95476b2a902d6c06a5c2652b832cc', 'src/third_party/libjingle/source/talk': - Var('chromium_git') + '/external/webrtc/trunk/talk.git' + '@' + '3ecea8a7f856b250a0c86d26f7a7d0f284ca5afb', # commit position 10671 + Var('chromium_git') + '/external/webrtc/trunk/talk.git' + '@' + 'eddf34f4a9ddd5bdac8d85125a4ed04eff704638', # commit position 10725 'src/third_party/usrsctp/usrsctplib': Var('chromium_git') + '/external/usrsctplib.git' + '@' + '36444a999739e9e408f8f587cb4c3ffeef2e50ac', # from svn revision 9215 @@ -214,7 +214,7 @@ Var('chromium_git') + '/native_client/src/third_party/scons-2.0.1.git' + '@' + '1c1550e17fc26355d08627fbdec13d8291227067', 'src/third_party/webrtc': - Var('chromium_git') + '/external/webrtc/trunk/webrtc.git' + '@' + '82cc96fa7a18819123cc171b19ca880c48b3406f', # commit position 10685 + Var('chromium_git') + '/external/webrtc/trunk/webrtc.git' + '@' + 'dba3e4553cbe4aa286dda6074fdb004fb1eb652f', # commit position 10724 'src/third_party/openmax_dl': Var('chromium_git') + '/external/webrtc/deps/third_party/openmax.git' + '@' + Var('openmax_dl_revision'), @@ -252,7 +252,7 @@ Var('chromium_git') + '/chromium/cdm.git' + '@' + 'a4773c3cec827c3a880e8a2c22e43a287ced0d20', 'src/third_party/mesa/src': - Var('chromium_git') + '/chromium/deps/mesa.git' + '@' + 'a3dc7d623fbb83a6246adf3d363922ad3909c14c', + Var('chromium_git') + '/chromium/deps/mesa.git' + '@' + 'ef811c6bd4de74e13e7035ca882cc77f85793fef', 'src/third_party/cld_2/src': Var('chromium_git') + '/external/github.com/CLD2Owners/cld2.git' + '@' + '84b58a5d7690ebf05a91406f371ce00c3daf31c0', @@ -270,7 +270,7 @@ Var('chromium_git') + '/external/py_trace_event.git' + '@' + 'dd463ea9e2c430de2b9e53dea57a77b4c3ac9b30', 'src/third_party/dom_distiller_js/dist': - Var('chromium_git') + '/external/github.com/chromium/dom-distiller-dist.git' + '@' + '445b024cb55f367636e6da4a61796a2afecd6d3f', + Var('chromium_git') + '/external/github.com/chromium/dom-distiller-dist.git' + '@' + '7e5e3db1b6ddecee66fc5f643729fda40976fd39', 'src/third_party/catapult': Var('chromium_git') + '/external/github.com/catapult-project/catapult.git' + '@' +
diff --git a/android_webview/BUILD.gn b/android_webview/BUILD.gn index 729d4ea..381a4a1 100644 --- a/android_webview/BUILD.gn +++ b/android_webview/BUILD.gn
@@ -98,11 +98,11 @@ ] deps = [ ":generate_aw_resources", + "//content:resources", + "//content/app/resources", + "//net:net_resources", "//third_party/WebKit/public:image_resources", "//third_party/WebKit/public:resources", - "//content/app/resources", - "//content:resources", - "//net:net_resources", "//ui/resources", ] output = "$target_gen_dir/webviewchromium.pak" @@ -471,15 +471,15 @@ "//cc/surfaces", "//components/auto_login_parser:auto_login_parser", "//components/autofill/content/renderer", - "//components/crash/content/app", - "//components/crash/content/browser", "//components/cdm/browser", "//components/cdm/renderer", + "//components/crash/content/app", + "//components/crash/content/browser", "//components/data_reduction_proxy/core/browser", "//components/devtools_discovery", "//components/navigation_interception", - "//components/printing/common", "//components/printing/browser", + "//components/printing/common", "//components/printing/renderer", "//components/visitedlink/browser", "//components/visitedlink/renderer", @@ -489,11 +489,11 @@ "//content/public/browser", "//gin", "//gpu/blink", - "//gpu/command_buffer/common:gles2_utils", - "//gpu/command_buffer/service", "//gpu/command_buffer/client:gl_in_process_context", "//gpu/command_buffer/client:gles2_c_lib", "//gpu/command_buffer/client:gles2_implementation", + "//gpu/command_buffer/common:gles2_utils", + "//gpu/command_buffer/service", "//gpu/skia_bindings", "//media", "//media/midi",
diff --git a/android_webview/browser/aw_form_database_service.cc b/android_webview/browser/aw_form_database_service.cc index 95e0a02..dfdfdb5dc 100644 --- a/android_webview/browser/aw_form_database_service.cc +++ b/android_webview/browser/aw_form_database_service.cc
@@ -93,7 +93,7 @@ WaitableEvent* completion, bool* result) { WebDataServiceBase::Handle pending_query_handle = - autofill_data_->GetCountOfEntriesContainedBetween( + autofill_data_->GetCountOfValuesContainedBetween( base::Time(), base::Time::Max(), this); PendingQuery query; query.result = result;
diff --git a/android_webview/browser/net/android_stream_reader_url_request_job.cc b/android_webview/browser/net/android_stream_reader_url_request_job.cc index dc288faa5..173bdbb 100644 --- a/android_webview/browser/net/android_stream_reader_url_request_job.cc +++ b/android_webview/browser/net/android_stream_reader_url_request_job.cc
@@ -21,6 +21,7 @@ #include "content/public/browser/browser_thread.h" #include "net/base/io_buffer.h" #include "net/base/mime_util.h" +#include "net/base/net_errors.h" #include "net/base/net_util.h" #include "net/http/http_response_headers.h" #include "net/http/http_response_info.h" @@ -89,7 +90,6 @@ net::NetworkDelegate* network_delegate, scoped_ptr<Delegate> delegate) : URLRequestJob(request, network_delegate), - range_parse_result_(net::OK), delegate_(delegate.Pass()), weak_factory_(this) { DCHECK(delegate_); @@ -101,7 +101,6 @@ scoped_ptr<DelegateObtainer> delegate_obtainer, bool) : URLRequestJob(request, network_delegate), - range_parse_result_(net::OK), delegate_obtainer_(delegate_obtainer.Pass()), weak_factory_(this) { DCHECK(delegate_obtainer_); @@ -142,10 +141,7 @@ base::Bind(&AndroidStreamReaderURLRequestJob::DelegateObtained, weak_factory_.GetWeakPtr())); } else { - // Run DoStart asynchronously to avoid re-entering the delegate. - base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, base::Bind(&AndroidStreamReaderURLRequestJob::DoStart, - weak_factory_.GetWeakPtr())); + DoStart(); } } @@ -206,29 +202,45 @@ set_expected_content_size(result); HeadersComplete(kHTTPOk, kHTTPOkText); } else { - NotifyStartError( - net::URLRequestStatus(net::URLRequestStatus::FAILED, result)); + NotifyDone(net::URLRequestStatus(net::URLRequestStatus::FAILED, result)); } } void AndroidStreamReaderURLRequestJob::OnReaderReadCompleted(int result) { DCHECK(thread_checker_.CalledOnValidThread()); - - ReadRawDataComplete(result); + // The URLRequest API contract requires that: + // * NotifyDone be called once, to set the status code, indicate the job is + // finished (there will be no further IO), + // * NotifyReadComplete be called if false is returned from ReadRawData to + // indicate that the IOBuffer will not be used by the job anymore. + // There might be multiple calls to ReadRawData (and thus multiple calls to + // NotifyReadComplete), which is why NotifyDone is called only on errors + // (result < 0) and end of data (result == 0). + if (result == 0) { + NotifyDone(net::URLRequestStatus()); + } else if (result < 0) { + NotifyDone(net::URLRequestStatus(net::URLRequestStatus::FAILED, result)); + } else { + // Clear the IO_PENDING status. + SetStatus(net::URLRequestStatus()); + } + NotifyReadComplete(result); } base::TaskRunner* AndroidStreamReaderURLRequestJob::GetWorkerThreadRunner() { return static_cast<base::TaskRunner*>(BrowserThread::GetBlockingPool()); } -int AndroidStreamReaderURLRequestJob::ReadRawData(net::IOBuffer* dest, - int dest_size) { +bool AndroidStreamReaderURLRequestJob::ReadRawData(net::IOBuffer* dest, + int dest_size, + int* bytes_read) { DCHECK(thread_checker_.CalledOnValidThread()); if (!input_stream_reader_wrapper_.get()) { // This will happen if opening the InputStream fails in which case the // error is communicated by setting the HTTP response status header rather // than failing the request during the header fetch phase. - return 0; + *bytes_read = 0; + return true; } PostTaskAndReplyWithResult( @@ -239,7 +251,9 @@ base::Bind(&AndroidStreamReaderURLRequestJob::OnReaderReadCompleted, weak_factory_.GetWeakPtr())); - return net::ERR_IO_PENDING; + SetStatus(net::URLRequestStatus(net::URLRequestStatus::IO_PENDING, + net::ERR_IO_PENDING)); + return false; } bool AndroidStreamReaderURLRequestJob::GetMimeType( @@ -289,11 +303,6 @@ void AndroidStreamReaderURLRequestJob::DoStart() { DCHECK(thread_checker_.CalledOnValidThread()); - if (range_parse_result_ != net::OK) { - NotifyStartError(net::URLRequestStatus(net::URLRequestStatus::FAILED, - range_parse_result_)); - return; - } // Start reading asynchronously so that all error reporting and data // callbacks happen as they would for network requests. SetStatus(net::URLRequestStatus(net::URLRequestStatus::IO_PENDING, @@ -374,18 +383,19 @@ const net::HttpRequestHeaders& headers) { std::string range_header; if (headers.GetHeader(net::HttpRequestHeaders::kRange, &range_header)) { - // This job only cares about the Range header so that we know how many bytes - // in the stream to skip and how many to read after that. Note that - // validation is deferred to DoStart(), because NotifyStartError() is not - // legal to call since the job has not started. + // We only extract the "Range" header so that we know how many bytes in the + // stream to skip and how many to read after that. std::vector<net::HttpByteRange> ranges; if (net::HttpUtil::ParseRangeHeader(range_header, &ranges)) { - if (ranges.size() == 1) + if (ranges.size() == 1) { byte_range_ = ranges[0]; - } else { - // We don't support multiple range requests in one single URL request, - // because we need to do multipart encoding here. - range_parse_result_ = net::ERR_REQUEST_RANGE_NOT_SATISFIABLE; + } else { + // We don't support multiple range requests in one single URL request, + // because we need to do multipart encoding here. + NotifyDone( + net::URLRequestStatus(net::URLRequestStatus::FAILED, + net::ERR_REQUEST_RANGE_NOT_SATISFIABLE)); + } } } }
diff --git a/android_webview/browser/net/android_stream_reader_url_request_job.h b/android_webview/browser/net/android_stream_reader_url_request_job.h index 645be13..e21d7655 100644 --- a/android_webview/browser/net/android_stream_reader_url_request_job.h +++ b/android_webview/browser/net/android_stream_reader_url_request_job.h
@@ -15,7 +15,6 @@ #include "base/memory/scoped_ptr.h" #include "base/memory/weak_ptr.h" #include "base/threading/thread_checker.h" -#include "net/base/net_errors.h" #include "net/http/http_byte_range.h" #include "net/url_request/url_request_job.h" @@ -97,7 +96,7 @@ // URLRequestJob: void Start() override; void Kill() override; - int ReadRawData(net::IOBuffer* buf, int buf_size) override; + bool ReadRawData(net::IOBuffer* buf, int buf_size, int* bytes_read) override; void SetExtraRequestHeaders(const net::HttpRequestHeaders& headers) override; bool GetMimeType(std::string* mime_type) const override; bool GetCharset(std::string* charset) override; @@ -132,7 +131,6 @@ void OnReaderReadCompleted(int bytes_read); net::HttpByteRange byte_range_; - net::Error range_parse_result_; scoped_ptr<net::HttpResponseInfo> response_info_; scoped_ptr<Delegate> delegate_; scoped_ptr<DelegateObtainer> delegate_obtainer_;
diff --git a/android_webview/native/BUILD.gn b/android_webview/native/BUILD.gn index a76af83..320cbb31 100644 --- a/android_webview/native/BUILD.gn +++ b/android_webview/native/BUILD.gn
@@ -7,6 +7,7 @@ source_set("native") { deps = [ + ":native_jni", "//android_webview/common:version", "//base", "//base/third_party/dynamic_annotations:dynamic_annotations", @@ -21,11 +22,10 @@ "//skia", "//storage/browser", "//storage/common", + "//third_party/boringssl", "//ui/base", "//ui/gfx", "//ui/gfx/geometry:geometry", - "//third_party/boringssl", - ":native_jni", ] include_dirs = [ "//skia/config" ]
diff --git a/ash/BUILD.gn b/ash/BUILD.gn index 067e045..06bfa93 100644 --- a/ash/BUILD.gn +++ b/ash/BUILD.gn
@@ -96,15 +96,15 @@ if (is_chromeos) { deps += [ - "//device/bluetooth", - "//ui/display", - "//ui/display/util", "//chromeos", "//chromeos:power_manager_proto", + "//device/bluetooth", "//third_party/qcms", + "//ui/chromeos:ui_chromeos", "//ui/chromeos/resources", "//ui/chromeos/strings", - "//ui/chromeos:ui_chromeos", + "//ui/display", + "//ui/display/util", ] } else { sources -= [ @@ -245,7 +245,6 @@ "//ash/strings", "//base", "//base:i18n", - "//net", "//skia", "//third_party/icu", @@ -275,9 +274,9 @@ deps = [ #"//chrome:packed_resources", TODO(GYP) + ":ash_shell_lib", "//content", "//content/shell:content_shell_lib", - ":ash_shell_lib", "//skia", ] } @@ -306,14 +305,14 @@ "//ui/aura", "//ui/aura:test_support", "//ui/base", - "//ui/base/ime", "//ui/base:test_support", + "//ui/base/ime", "//ui/compositor", "//ui/compositor:test_support", "//ui/events", - "//ui/events/devices", - "//ui/events:test_support", "//ui/events:gesture_detection", + "//ui/events:test_support", + "//ui/events/devices", "//ui/gfx", "//ui/gfx/geometry", "//ui/keyboard", @@ -361,13 +360,13 @@ if (is_chromeos) { sources += [ "first_run/first_run_helper_unittest.cc" ] deps += [ + "//chromeos:power_manager_proto", + "//chromeos:test_support_without_gmock", "//device/bluetooth", "//ui/display", "//ui/display:test_support", "//ui/display:test_util", "//ui/display/types", - "//chromeos:power_manager_proto", - "//chromeos:test_support_without_gmock", ] } else { sources -= [
diff --git a/base/BUILD.gn b/base/BUILD.gn index 9e4270d2..aabfe67 100644 --- a/base/BUILD.gn +++ b/base/BUILD.gn
@@ -734,8 +734,8 @@ deps += [ ":base_jni_headers", - "//third_party/ashmem", "//third_party/android_tools:cpu_features", + "//third_party/ashmem", ] # logging.cc uses the Android logging library. @@ -1073,8 +1073,8 @@ ":base", "//base/test:test_support", "//base/test:test_support_perf", - "//testing/perf", "//testing/gtest", + "//testing/perf", ] if (is_android) { @@ -1731,6 +1731,9 @@ sources = [ "android/java/templates/ChromiumMultiDex.template", ] + if (is_debug) { + defines = [ "MULTIDEX_CONFIGURATION_Debug" ] + } package_name = "org/chromium/base/multidex" }
diff --git a/base/android/java/templates/ChromiumMultiDex.template b/base/android/java/templates/ChromiumMultiDex.template index 18b3c77..5761a45 100644 --- a/base/android/java/templates/ChromiumMultiDex.template +++ b/base/android/java/templates/ChromiumMultiDex.template
@@ -22,15 +22,21 @@ private static final String TAG = "base_multidex"; /** - * Installs secondary dexes if possible. + * Installs secondary dexes if possible/necessary. * * Isolated processes (e.g. renderer processes) can't load secondary dex files on * K and below, so we don't even try in that case. * + * In release builds, this is a no-op because: + * - multidex isn't necessary in release builds because we run proguard there and + * thus aren't threatening to hit the dex limit; and + * - calling MultiDex.install, even in the absence of secondary dexes, causes a + * significant regression in start-up time (crbug.com/525695). + * * @param context The application context. */ @VisibleForTesting -#if defined(CONFIGURATION_NAME_Debug) +#if defined(MULTIDEX_CONFIGURATION_Debug) public static void install(Context context) { try { // TODO(jbudorick): Back out this version check once support for K & below works.
diff --git a/base/base.gyp b/base/base.gyp index e8d449ff..2f8738e 100644 --- a/base/base.gyp +++ b/base/base.gyp
@@ -1470,7 +1470,7 @@ 'package_name': 'org/chromium/base/multidex', 'template_deps': [], 'additional_gcc_preprocess_options': [ - '--defines', 'CONFIGURATION_NAME_<(CONFIGURATION_NAME)', + '--defines', 'MULTIDEX_CONFIGURATION_<(CONFIGURATION_NAME)', ], }, 'includes': ['../build/android/java_cpp_template.gypi'],
diff --git a/base/message_loop/message_pump_perftest.cc b/base/message_loop/message_pump_perftest.cc index 1f6cb66..c568425 100644 --- a/base/message_loop/message_pump_perftest.cc +++ b/base/message_loop/message_pump_perftest.cc
@@ -84,14 +84,15 @@ target_->WaitUntilThreadStarted(); } - ScopedVector<Thread> scheduling_threads; + std::vector<scoped_ptr<Thread>> scheduling_threads; scheduling_times_.reset(new base::TimeDelta[num_scheduling_threads]); scheduling_thread_times_.reset(new base::TimeDelta[num_scheduling_threads]); min_batch_times_.reset(new base::TimeDelta[num_scheduling_threads]); max_batch_times_.reset(new base::TimeDelta[num_scheduling_threads]); for (int i = 0; i < num_scheduling_threads; ++i) { - scheduling_threads.push_back(new Thread("posting thread")); + scheduling_threads.push_back( + make_scoped_ptr(new Thread("posting thread"))); scheduling_threads[i]->Start(); }
diff --git a/base/test/BUILD.gn b/base/test/BUILD.gn index 75a77d22..4c9b784 100644 --- a/base/test/BUILD.gn +++ b/base/test/BUILD.gn
@@ -143,15 +143,15 @@ public_deps = [ ":test_config", "//base", - "//base:i18n", "//base:base_static", + "//base:i18n", ] deps = [ "//base/third_party/dynamic_annotations", "//testing/gmock", "//testing/gtest", - "//third_party/libxml", "//third_party/icu:icuuc", + "//third_party/libxml", ] if (!is_posix) {
diff --git a/blimp/client/BUILD.gn b/blimp/client/BUILD.gn index e630200b..d4ecbad0 100644 --- a/blimp/client/BUILD.gn +++ b/blimp/client/BUILD.gn
@@ -192,10 +192,10 @@ android_apk("blimp_apk") { deps = [ ":blimp_apk_manifest", - ":blimp_java", - ":blimp_java_resources", ":blimp_client", ":blimp_java", + ":blimp_java", + ":blimp_java_resources", "//base:base_java", google_play_services_resources, ]
diff --git a/blimp/engine/browser/BUILD.gn b/blimp/engine/browser/BUILD.gn index 3a1451b0..a4ce000d 100644 --- a/blimp/engine/browser/BUILD.gn +++ b/blimp/engine/browser/BUILD.gn
@@ -23,8 +23,8 @@ deps = [ "//base", "//blimp/common/proto", - "//blimp/net:blimp_net", "//blimp/engine/ui", + "//blimp/net:blimp_net", "//content", "//content/public/browser", "//content/public/common",
diff --git a/blimp/net/blimp_transport.h b/blimp/net/blimp_transport.h index 56d5e34..dcc68c6 100644 --- a/blimp/net/blimp_transport.h +++ b/blimp/net/blimp_transport.h
@@ -22,14 +22,12 @@ // Initiate or listen for a connection. // - // Returns net::OK if a connection is established synchronously. - // Returns an error code if a synchronous error occurred. - // Returns net::ERR_IO_PENDING if the connection is being established - // asynchronously. |callback| is later invoked with the connection outcome. - // - // If the connection is successful, the BlimpConnection can be taken by - // calling TakeConnectedSocket(). - virtual int Connect(const net::CompletionCallback& callback) = 0; + // |callback| will be invoked with the connection outcome: + // * net::OK if a connection is established successful, the BlimpConnection + // can be taken by calling TakeConnection(). + // * net::ERR_IO_PENDING will never be the outcome + // * Other error code indicates no connection was established. + virtual void Connect(const net::CompletionCallback& callback) = 0; // Returns the connection object after a successful Connect(). virtual scoped_ptr<BlimpConnection> TakeConnection() = 0;
diff --git a/blimp/net/tcp_client_transport.cc b/blimp/net/tcp_client_transport.cc index 6bdd18f..2bdf91d 100644 --- a/blimp/net/tcp_client_transport.cc +++ b/blimp/net/tcp_client_transport.cc
@@ -7,6 +7,7 @@ #include "base/callback.h" #include "base/callback_helpers.h" #include "base/memory/scoped_ptr.h" +#include "base/message_loop/message_loop.h" #include "blimp/net/stream_socket_connection.h" #include "net/socket/stream_socket.h" #include "net/socket/tcp_client_socket.h" @@ -19,7 +20,7 @@ TCPClientTransport::~TCPClientTransport() {} -int TCPClientTransport::Connect(const net::CompletionCallback& callback) { +void TCPClientTransport::Connect(const net::CompletionCallback& callback) { DCHECK(!socket_); DCHECK(!callback.is_null()); @@ -31,11 +32,15 @@ int result = socket_->Connect(completion_callback); if (result == net::ERR_IO_PENDING) { connect_callback_ = callback; - } else if (result != net::OK) { + return; + } + + if (result != net::OK) { socket_ = nullptr; } - return result; + base::MessageLoop::current()->PostTask(FROM_HERE, + base::Bind(callback, result)); } scoped_ptr<BlimpConnection> TCPClientTransport::TakeConnection() { @@ -45,6 +50,7 @@ } void TCPClientTransport::OnTCPConnectComplete(int result) { + DCHECK_NE(net::ERR_IO_PENDING, result); DCHECK(socket_); if (result != net::OK) { socket_ = nullptr;
diff --git a/blimp/net/tcp_client_transport.h b/blimp/net/tcp_client_transport.h index d5255d3..bbac1ba 100644 --- a/blimp/net/tcp_client_transport.h +++ b/blimp/net/tcp_client_transport.h
@@ -30,7 +30,7 @@ ~TCPClientTransport() override; // BlimpTransport implementation. - int Connect(const net::CompletionCallback& callback) override; + void Connect(const net::CompletionCallback& callback) override; scoped_ptr<BlimpConnection> TakeConnection() override; private:
diff --git a/blimp/net/tcp_engine_transport.cc b/blimp/net/tcp_engine_transport.cc index c2c96f97..112e350 100644 --- a/blimp/net/tcp_engine_transport.cc +++ b/blimp/net/tcp_engine_transport.cc
@@ -7,6 +7,7 @@ #include "base/callback.h" #include "base/callback_helpers.h" #include "base/memory/scoped_ptr.h" +#include "base/message_loop/message_loop.h" #include "blimp/net/stream_socket_connection.h" #include "net/socket/stream_socket.h" #include "net/socket/tcp_server_socket.h" @@ -19,7 +20,7 @@ TCPEngineTransport::~TCPEngineTransport() {} -int TCPEngineTransport::Connect(const net::CompletionCallback& callback) { +void TCPEngineTransport::Connect(const net::CompletionCallback& callback) { DCHECK(!accepted_socket_); DCHECK(!callback.is_null()); @@ -29,7 +30,9 @@ int result = server_socket_->Listen(address_, 5); if (result != net::OK) { server_socket_.reset(); - return result; + base::MessageLoop::current()->PostTask(FROM_HERE, + base::Bind(callback, result)); + return; } } @@ -37,16 +40,18 @@ &TCPEngineTransport::OnTCPConnectAccepted, base::Unretained(this)); int result = server_socket_->Accept(&accepted_socket_, accept_callback); - if (result == net::OK) { - callback.Run(result); - } else if (result == net::ERR_IO_PENDING) { + if (result == net::ERR_IO_PENDING) { connect_callback_ = callback; - } else { + return; + } + + if (result != net::OK) { // TODO(haibinlu): investigate when we can keep using this server socket. server_socket_.reset(); } - return result; + base::MessageLoop::current()->PostTask(FROM_HERE, + base::Bind(callback, result)); } scoped_ptr<BlimpConnection> TCPEngineTransport::TakeConnection() { @@ -62,6 +67,7 @@ } void TCPEngineTransport::OnTCPConnectAccepted(int result) { + DCHECK_NE(net::ERR_IO_PENDING, result); DCHECK(accepted_socket_); if (result != net::OK) { accepted_socket_.reset();
diff --git a/blimp/net/tcp_engine_transport.h b/blimp/net/tcp_engine_transport.h index 88176e99..5bb92dd4 100644 --- a/blimp/net/tcp_engine_transport.h +++ b/blimp/net/tcp_engine_transport.h
@@ -31,7 +31,7 @@ ~TCPEngineTransport() override; // BlimpTransport implementation. - int Connect(const net::CompletionCallback& callback) override; + void Connect(const net::CompletionCallback& callback) override; scoped_ptr<BlimpConnection> TakeConnection() override; int GetLocalAddressForTesting(net::IPEndPoint* address) const;
diff --git a/blimp/net/tcp_transport_unittest.cc b/blimp/net/tcp_transport_unittest.cc index 4d31326..2df4328 100644 --- a/blimp/net/tcp_transport_unittest.cc +++ b/blimp/net/tcp_transport_unittest.cc
@@ -50,11 +50,11 @@ TEST_F(TCPTransportTest, Connect) { net::TestCompletionCallback accept_callback; - ASSERT_EQ(net::ERR_IO_PENDING, server_->Connect(accept_callback.callback())); + server_->Connect(accept_callback.callback()); net::TestCompletionCallback connect_callback; TCPClientTransport client(GetLocalAddressList(), nullptr); - ASSERT_EQ(net::ERR_IO_PENDING, client.Connect(connect_callback.callback())); + client.Connect(connect_callback.callback()); EXPECT_EQ(net::OK, connect_callback.WaitForResult()); EXPECT_EQ(net::OK, accept_callback.WaitForResult()); @@ -63,22 +63,22 @@ TEST_F(TCPTransportTest, TwoClientConnections) { net::TestCompletionCallback accept_callback1; - ASSERT_EQ(net::ERR_IO_PENDING, server_->Connect(accept_callback1.callback())); + server_->Connect(accept_callback1.callback()); net::TestCompletionCallback connect_callback1; TCPClientTransport client1(GetLocalAddressList(), nullptr); - ASSERT_EQ(net::ERR_IO_PENDING, client1.Connect(connect_callback1.callback())); + client1.Connect(connect_callback1.callback()); net::TestCompletionCallback connect_callback2; TCPClientTransport client2(GetLocalAddressList(), nullptr); - ASSERT_EQ(net::ERR_IO_PENDING, client2.Connect(connect_callback2.callback())); + client2.Connect(connect_callback2.callback()); EXPECT_EQ(net::OK, connect_callback1.WaitForResult()); EXPECT_EQ(net::OK, accept_callback1.WaitForResult()); EXPECT_TRUE(server_->TakeConnection() != nullptr); net::TestCompletionCallback accept_callback2; - ASSERT_EQ(net::OK, server_->Connect(accept_callback2.callback())); + server_->Connect(accept_callback2.callback()); EXPECT_EQ(net::OK, connect_callback2.WaitForResult()); EXPECT_EQ(net::OK, accept_callback2.WaitForResult()); EXPECT_TRUE(server_->TakeConnection() != nullptr);
diff --git a/breakpad/BUILD.gn b/breakpad/BUILD.gn index 08af6c7..9dabd81 100644 --- a/breakpad/BUILD.gn +++ b/breakpad/BUILD.gn
@@ -378,9 +378,9 @@ include_dirs = [ "src/client/apple/Framework" ] deps = [ - ":utilities", ":crash_inspector", ":crash_report_sender", + ":utilities", ] } @@ -622,12 +622,12 @@ deps = [ ":client", - ":processor_support", ":linux_dumper_unittest_helper", + ":processor_support", "//build/config/sanitizers:deps", + "//testing/gmock", "//testing/gtest", "//testing/gtest:gtest_main", - "//testing/gmock", ] include_dirs = [
diff --git a/build/android/gyp/apkbuilder.py b/build/android/gyp/apkbuilder.py index f668c08..7e0ce23 100755 --- a/build/android/gyp/apkbuilder.py +++ b/build/android/gyp/apkbuilder.py
@@ -51,6 +51,8 @@ parser.add_argument('--native-lib-placeholders', help='GYP-list of native library placeholders to add.', default='[]') + parser.add_argument('--emma-device-jar', + help='Path to emma_device.jar to include.') options = parser.parse_args(args) options.assets = build_utils.ParseGypList(options.assets) options.uncompressed_assets = build_utils.ParseGypList( @@ -122,6 +124,9 @@ if options.dex_file: input_paths.append(options.dex_file) + if options.emma_device_jar: + input_paths.append(options.emma_device_jar) + input_strings = [options.android_abi, options.native_lib_placeholders] for path in itertools.chain(options.assets, options.uncompressed_assets): @@ -150,7 +155,29 @@ apk.writestr('lib/%s/%s' % (options.android_abi, name), ':)', zipfile.ZIP_STORED) if options.dex_file: - apk.write(options.dex_file, 'classes.dex') + if options.dex_file.endswith('.zip'): + with zipfile.ZipFile(options.dex_file, 'r') as dex_zip: + for dex in (d for d in dex_zip.namelist() if d.endswith('.dex')): + apk.writestr(dex, dex_zip.read(dex)) + else: + apk.write(options.dex_file, 'classes.dex') + + if options.emma_device_jar: + # Add EMMA Java resources to APK. + with zipfile.ZipFile(options.emma_device_jar, 'r') as emma_device_jar: + for emma_device_jar_entry in emma_device_jar.namelist(): + entry_name_lower = emma_device_jar_entry.lower() + if entry_name_lower.startswith('meta-inf/'): + continue + + if entry_name_lower.endswith('/'): + continue + + if entry_name_lower.endswith('.class'): + continue + + apk.writestr(emma_device_jar_entry, + emma_device_jar.read(emma_device_jar_entry)) shutil.move(tmp_apk, options.output_apk) finally:
diff --git a/build/android/gyp/create_test_runner_script.py b/build/android/gyp/create_test_runner_script.py index 22ef260..e5e56532 100755 --- a/build/android/gyp/create_test_runner_script.py +++ b/build/android/gyp/create_test_runner_script.py
@@ -44,7 +44,7 @@ sys.exit(main()) """ -def main(): +def main(args): parser = argparse.ArgumentParser() parser.add_argument('--script-output-path', help='Output path for executable script.') @@ -56,7 +56,10 @@ group = parser.add_argument_group('Test runner path arguments.') group.add_argument('--output-directory') group.add_argument('--isolate-file-path') - args, test_runner_args = parser.parse_known_args() + group.add_argument('--apk-under-test') + group.add_argument('--test-apk') + args, test_runner_args = parser.parse_known_args( + build_utils.ExpandFileArgs(args)) def RelativizePathToScript(path): """Returns the path relative to the output script directory.""" @@ -73,6 +76,12 @@ if args.isolate_file_path: test_runner_path_args['--isolate-file-path'] = RelativizePathToScript( args.isolate_file_path) + if args.apk_under_test: + test_runner_path_args['--apk-under-test'] = RelativizePathToScript( + args.apk_under_test) + if args.test_apk: + test_runner_path_args['--test-apk'] = RelativizePathToScript( + args.test_apk) with open(args.script_output_path, 'w') as script: script.write(SCRIPT_TEMPLATE.format( @@ -88,4 +97,4 @@ build_utils.GetPythonDependencies()) if __name__ == '__main__': - sys.exit(main()) + sys.exit(main(sys.argv[1:]))
diff --git a/build/android/gyp/dex.py b/build/android/gyp/dex.py index 2fef369..d9032694c 100755 --- a/build/android/gyp/dex.py +++ b/build/android/gyp/dex.py
@@ -60,13 +60,14 @@ 'include in the main dex.') parser.add_option('--multidex-configuration-path', help='A JSON file containing multidex build configuration.') + parser.add_option('--multi-dex', default=False, action='store_true', + help='Generate multiple dex files.') options, paths = parser.parse_args(args) required_options = ('android_sdk_tools',) build_utils.CheckOptions(options, parser, required=required_options) - options.multi_dex = False if options.multidex_configuration_path: with open(options.multidex_configuration_path) as multidex_config_file: multidex_config = json.loads(multidex_config_file.read())
diff --git a/build/android/gyp/main_dex_list.py b/build/android/gyp/main_dex_list.py index 7f29bfb..7388f4ab 100755 --- a/build/android/gyp/main_dex_list.py +++ b/build/android/gyp/main_dex_list.py
@@ -17,8 +17,9 @@ from pylib import constants -def main(): +def main(args): parser = argparse.ArgumentParser() + build_utils.AddDepfileOption(parser) parser.add_argument('--android-sdk-tools', required=True, help='Android sdk build tools directory.') parser.add_argument('--main-dex-rules-path', action='append', default=[], @@ -36,11 +37,14 @@ parser.add_argument('--multidex-configuration-path', help='A JSON file containing multidex build ' 'configuration.') - parser.add_argument('paths', nargs='+', + parser.add_argument('--inputs', + help='JARs for which a main dex list should be ' + 'generated.') + parser.add_argument('paths', nargs='*', default=[], help='JARs for which a main dex list should be ' 'generated.') - args = parser.parse_args() + args = parser.parse_args(build_utils.ExpandFileArgs(args)) if args.multidex_configuration_path: with open(args.multidex_configuration_path) as multidex_config_file: @@ -49,52 +53,86 @@ if not multidex_config.get('enabled', False): return 0 - with open(args.main_dex_list_path, 'w') as main_dex_list_file: + if args.inputs: + args.paths.extend(build_utils.ParseGypList(args.inputs)) - shrinked_android_jar = os.path.abspath( - os.path.join(args.android_sdk_tools, 'lib', 'shrinkedAndroid.jar')) - dx_jar = os.path.abspath( - os.path.join(args.android_sdk_tools, 'lib', 'dx.jar')) - paths_arg = ':'.join(args.paths) - rules_file = os.path.abspath( - os.path.join(args.android_sdk_tools, 'mainDexClasses.rules')) + shrinked_android_jar = os.path.abspath( + os.path.join(args.android_sdk_tools, 'lib', 'shrinkedAndroid.jar')) + dx_jar = os.path.abspath( + os.path.join(args.android_sdk_tools, 'lib', 'dx.jar')) + rules_file = os.path.abspath( + os.path.join(args.android_sdk_tools, 'mainDexClasses.rules')) - with tempfile.NamedTemporaryFile(suffix='.jar') as temp_jar: - proguard_cmd = [ - constants.PROGUARD_SCRIPT_PATH, - '-forceprocessing', - '-dontwarn', '-dontoptimize', '-dontobfuscate', '-dontpreverify', - '-injars', paths_arg, - '-outjars', temp_jar.name, - '-libraryjars', shrinked_android_jar, - '-include', rules_file, - ] - for m in args.main_dex_rules_paths: - proguard_cmd.extend(['-include', m]) + proguard_cmd = [ + constants.PROGUARD_SCRIPT_PATH, + '-forceprocessing', + '-dontwarn', '-dontoptimize', '-dontobfuscate', '-dontpreverify', + '-libraryjars', shrinked_android_jar, + '-include', rules_file, + ] + for m in args.main_dex_rules_paths: + proguard_cmd.extend(['-include', m]) - main_dex_list = '' - try: - build_utils.CheckOutput(proguard_cmd, print_stderr=False) + main_dex_list_cmd = [ + 'java', '-cp', dx_jar, + 'com.android.multidex.MainDexListBuilder', + ] - java_cmd = [ - 'java', '-cp', dx_jar, - 'com.android.multidex.MainDexListBuilder', - temp_jar.name, paths_arg - ] - main_dex_list = build_utils.CheckOutput(java_cmd) - except build_utils.CalledProcessError as e: - if 'output jar is empty' in e.output: - pass - elif "input doesn't contain any classes" in e.output: - pass - else: - raise + input_paths = list(args.paths) + input_paths += [ + shrinked_android_jar, + dx_jar, + rules_file, + ] + input_paths += args.main_dex_rules_paths - main_dex_list_file.write(main_dex_list) + input_strings = [ + proguard_cmd, + main_dex_list_cmd, + ] + + output_paths = [ + args.main_dex_list_path, + ] + + build_utils.CallAndWriteDepfileIfStale( + lambda: _OnStaleMd5(proguard_cmd, main_dex_list_cmd, args.paths, + args.main_dex_list_path), + args, + input_paths=input_paths, + input_strings=input_strings, + output_paths=output_paths) return 0 +def _OnStaleMd5(proguard_cmd, main_dex_list_cmd, paths, main_dex_list_path): + paths_arg = ':'.join(paths) + main_dex_list = '' + try: + with tempfile.NamedTemporaryFile(suffix='.jar') as temp_jar: + proguard_cmd += [ + '-injars', paths_arg, + '-outjars', temp_jar.name + ] + build_utils.CheckOutput(proguard_cmd, print_stderr=False) + + main_dex_list_cmd += [ + temp_jar.name, paths_arg + ] + main_dex_list = build_utils.CheckOutput(main_dex_list_cmd) + except build_utils.CalledProcessError as e: + if 'output jar is empty' in e.output: + pass + elif "input doesn't contain any classes" in e.output: + pass + else: + raise + + with open(main_dex_list_path, 'w') as main_dex_list_file: + main_dex_list_file.write(main_dex_list) + + if __name__ == '__main__': - sys.exit(main()) + sys.exit(main(sys.argv[1:]))
diff --git a/build/android/gyp/write_build_config.py b/build/android/gyp/write_build_config.py index 541efdae..625107f 100755 --- a/build/android/gyp/write_build_config.py +++ b/build/android/gyp/write_build_config.py
@@ -189,6 +189,9 @@ parser.add_option('--native-libs', help='List of top-level native libs.') parser.add_option('--readelf-path', help='Path to toolchain\'s readelf.') + # apk options + parser.add_option('--apk-path', help='Path to the target\'s apk output.') + parser.add_option('--tested-apk-config', help='Path to the build config of the tested apk (for an instrumentation ' 'test apk).') @@ -291,6 +294,8 @@ deps_info['jar_path'] = options.jar_path if options.type == 'android_apk' or options.supports_android: deps_info['dex_path'] = options.dex_path + if options.type == 'android_apk': + deps_info['apk_path'] = options.apk_path config['javac'] = { 'classpath': javac_classpath, } @@ -384,6 +389,8 @@ ' apks if it\'s enabled for the tested apk') proguard_config['tested_apk_info'] = tested_apk_config['proguard_info'] + deps_info['tested_apk_path'] = tested_apk_config['apk_path'] + # Dependencies for the final dex file of an apk or a 'deps_dex'. if options.type in ['android_apk', 'deps_dex']: config['final_dex'] = {}
diff --git a/build/android/incremental_install/installer.py b/build/android/incremental_install/installer.py index b5ed5ce..635627b 100755 --- a/build/android/incremental_install/installer.py +++ b/build/android/incremental_install/installer.py
@@ -121,14 +121,12 @@ push_dex_timer.Stop(log=False) def check_selinux(): - # Samsung started using SELinux before Marshmallow. There may be even more - # cases where this is required... - has_selinux = (device.build_version_sdk >= version_codes.MARSHMALLOW or - device.GetProp('selinux.policy_version')) + # Marshmallow has no filesystem access whatsoever. It might be possible to + # get things working on Lollipop, but attempts so far have failed. + # http://crbug.com/558818 + has_selinux = device.build_version_sdk >= version_codes.LOLLIPOP if has_selinux and apk.HasIsolatedProcesses(): - raise Exception('Cannot use incremental installs on versions of Android ' - 'where isoloated processes cannot access the filesystem ' - '(this includes Android M+, and Samsung L+) without ' + raise Exception('Cannot use incremental installs on Android L+ without ' 'first disabling isoloated processes.\n' 'To do so, use GN arg:\n' ' disable_incremental_isolated_processes=true')
diff --git a/build/android/main_dex_action.gypi b/build/android/main_dex_action.gypi index 7316ae2..4076418 100644 --- a/build/android/main_dex_action.gypi +++ b/build/android/main_dex_action.gypi
@@ -10,8 +10,8 @@ # 'action_name': 'some name for the action' # 'actions': [ # 'variables': { -# 'jar_path': 'path to jar', -# 'output_path': 'output path' +# 'jar_paths': ['path to jar', ...], +# 'output_path': 'output path', # }, # 'includes': [ 'relative/path/to/main_dex_action.gypi' ], # ], @@ -27,7 +27,7 @@ 'main_dex_rules_path': '<(DEPTH)/build/android/main_dex_classes.flags', }, 'inputs': [ - '<(jar_path)', + '<@(jar_paths)', '<(main_dex_list_script)', '<(main_dex_rules_path)', '<(multidex_configuration_path)',
diff --git a/build/android/test_runner.gypi b/build/android/test_runner.gypi index 92f355b..f571888 100644 --- a/build/android/test_runner.gypi +++ b/build/android/test_runner.gypi
@@ -41,7 +41,10 @@ 'script_name': 'run_<(test_suite_name)', }], ['test_type == "instrumentation"', { - 'test_runner_args': ['--test-apk', '<(apk_name)'], + 'test_runner_args': [ + '--apk-under-test', '>(tested_apk_path)', + '--test-apk', '>(final_apk_path)', + ], 'script_name': 'run_<(_target_name)', }], ['isolate_file != ""', { @@ -69,4 +72,4 @@ ], }, ], -} \ No newline at end of file +}
diff --git a/build/config/android/config.gni b/build/config/android/config.gni index 9b141f90..01e1b7a 100644 --- a/build/config/android/config.gni +++ b/build/config/android/config.gni
@@ -69,6 +69,15 @@ # Set to true to enable the Errorprone compiler use_errorprone_java_compiler = false + # Enables EMMA Java code coverage. Instruments classes during build to + # produce .ec files during runtime + emma_coverage = false + + # EMMA filter string consisting of a list of inclusion/exclusion patterns + # separated with whitespace and/or comma. Only has effect if + # emma_coverage==true + emma_filter = "" + # Disables process isolation when building _incremental targets. # Required for Android M+ due to SELinux policies (stronger sandboxing). disable_incremental_isolated_processes = false
diff --git a/build/config/android/internal_rules.gni b/build/config/android/internal_rules.gni index 90867ed..3d91676 100644 --- a/build/config/android/internal_rules.gni +++ b/build/config/android/internal_rules.gni
@@ -223,6 +223,51 @@ template("dex") { set_sources_assignment_filter([]) + _enable_multidex = defined(invoker.enable_multidex) && invoker.enable_multidex + + if (_enable_multidex) { + _main_dex_list_path = invoker.output + ".main_dex_list" + _main_dex_list_target_name = "${target_name}__main_dex_list" + action(_main_dex_list_target_name) { + forward_variables_from(invoker, + [ + "deps", + "inputs", + "sources", + "testonly", + ]) + + script = "//build/android/gyp/main_dex_list.py" + depfile = "$target_gen_dir/$target_name.d" + + main_dex_rules = "//build/android/main_dex_classes.flags" + + outputs = [ + depfile, + _main_dex_list_path, + ] + + args = [ + "--depfile", + rebase_path(depfile, root_build_dir), + "--android-sdk-tools", + rebased_android_sdk_build_tools, + "--main-dex-list-path", + rebase_path(_main_dex_list_path, root_build_dir), + "--main-dex-rules-path", + rebase_path(main_dex_rules, root_build_dir), + ] + + if (defined(invoker.args)) { + args += invoker.args + } + + if (defined(invoker.sources)) { + args += rebase_path(invoker.sources, root_build_dir) + } + } + } + assert(defined(invoker.output)) action(target_name) { forward_variables_from(invoker, @@ -258,6 +303,16 @@ args += [ "--no-locals=1" ] } + if (_enable_multidex) { + args += [ + "--multi-dex", + "--main-dex-list-path", + rebase_path(_main_dex_list_path, root_build_dir), + ] + deps += [ ":${_main_dex_list_target_name}" ] + inputs += [ _main_dex_list_path ] + } + if (defined(invoker.args)) { args += invoker.args } @@ -452,6 +507,11 @@ rebase_path(invoker.proguard_info, root_build_dir), ] } + + if (defined(invoker.apk_path)) { + _rebased_apk_path = rebase_path(invoker.apk_path, root_build_dir) + args += [ "--apk-path=$_rebased_apk_path" ] + } } if (defined(invoker.srcjar)) { @@ -469,8 +529,6 @@ _input_jar_path = invoker.input_jar_path _output_jar_path = invoker.output_jar_path - _output_ijar_path = get_path_info(_output_jar_path, "dir") + "/" + - get_path_info(_output_jar_path, "name") + ".interface.jar" assert(invoker.build_config != "") @@ -519,18 +577,79 @@ } } - generate_interface_jar("${target_name}__ijar") { - input_jar = _output_jar_path - output_jar = _output_ijar_path - deps = [ + group(target_name) { + forward_variables_from(invoker, [ "visibility" ]) + public_deps = [ ":$_output_jar_target", ] } +} + +template("emma_instr") { + set_sources_assignment_filter([]) + forward_variables_from(invoker, [ "testonly" ]) + + assert(invoker.source_files != [] || true) # Mark as used + + if (invoker.emma_instrument) { + _output_jar_target = "${target_name}__process" + _coverage_file = "$target_out_dir/${target_name}.em" + _source_dirs_listing_file = "$target_out_dir/${target_name}_sources.txt" + _emma_jar = "${android_sdk_root}/tools/lib/emma.jar" + _rebased_source_files = rebase_path(invoker.source_files, root_build_dir) + action(_output_jar_target) { + forward_variables_from(invoker, [ "deps" ]) + + script = "//build/android/gyp/emma_instr.py" + depfile = "${target_gen_dir}/${target_name}.d" + inputs = [ + _emma_jar, + invoker.input_jar_path, + ] + outputs = [ + depfile, + _coverage_file, + _source_dirs_listing_file, + invoker.output_jar_path, + ] + args = [ + "instrument_jar", + "--input-path", + rebase_path(invoker.input_jar_path, root_build_dir), + "--output-path", + rebase_path(invoker.output_jar_path, root_build_dir), + "--depfile", + rebase_path(depfile, root_build_dir), + "--coverage-file", + rebase_path(_coverage_file, root_build_dir), + "--sources-list-file", + rebase_path(_source_dirs_listing_file, root_build_dir), + "--source-files=$_rebased_source_files", + "--src-root", + rebase_path("//", root_build_dir), + "--emma-jar", + rebase_path(_emma_jar, root_build_dir), + "--filter-string", + emma_filter, + ] + } + } else { + _output_jar_target = "${target_name}__copy_jar" + copy(_output_jar_target) { + forward_variables_from(invoker, [ "deps" ]) + + sources = [ + invoker.input_jar_path, + ] + outputs = [ + invoker.output_jar_path, + ] + } + } group(target_name) { forward_variables_from(invoker, [ "visibility" ]) public_deps = [ - ":${target_name}__ijar", ":$_output_jar_target", ] } @@ -613,6 +732,12 @@ if (_native_lib_placeholders != []) { args += [ "--native-lib-placeholders=$_native_lib_placeholders" ] } + + if (defined(invoker.emma_instrument) && invoker.emma_instrument) { + _emma_device_jar = "$android_sdk_root/tools/lib/emma_device.jar" + _rebased_emma_device_jar = rebase_path(_emma_device_jar, root_build_dir) + args += [ "--emma-device-jar=$_rebased_emma_device_jar" ] + } } } @@ -881,6 +1006,7 @@ forward_variables_from(invoker, [ "assets_build_config", + "emma_instrument", "native_lib_placeholders", "native_libs_dir", ]) @@ -896,7 +1022,11 @@ _incremental_package_target = "${target_name}_incremental__package" package_apk(_incremental_package_target) { - forward_variables_from(invoker, [ "assets_build_config" ]) + forward_variables_from(invoker, + [ + "assets_build_config", + "emma_instrument", + ]) _dex_target = "//build/android/incremental_install:bootstrap_java__dex" deps = _incremental_deps + [ ":${_incremental_package_resources_target_name}", @@ -1003,6 +1133,8 @@ # so do not put them under gen/. _target_dir_name = get_label_info(":$target_name", "dir") _jar_path = "$root_out_dir/lib.java$_target_dir_name/$target_name.jar" + _ijar_path = + "$root_out_dir/lib.java$_target_dir_name/$target_name.interface.jar" _build_config = _base_path + ".build_config" if (_supports_android) { @@ -1021,6 +1153,7 @@ _build_config_target_name = "${_template_name}__build_config" _process_jar_target_name = "${_template_name}__process_jar" + _ijar_target_name = "${_template_name}__ijar" if (_supports_android) { _dex_target_name = "${_template_name}__dex" } @@ -1040,7 +1173,10 @@ } process_java_prebuilt(_process_jar_target_name) { - visibility = [ ":$_template_name" ] + visibility = [ + ":$_ijar_target_name", + ":$_template_name", + ] if (_supports_android) { visibility += [ ":$_dex_target_name" ] } @@ -1057,6 +1193,14 @@ deps = [ ":$_build_config_target_name" ] + _deps + _jar_deps } + generate_interface_jar(_ijar_target_name) { + input_jar = _jar_path + output_jar = _ijar_path + deps = [ + ":$_process_jar_target_name", + ] + } + if (_supports_android) { dex(_dex_target_name) { sources = [ @@ -1088,6 +1232,7 @@ group(target_name) { forward_variables_from(invoker, [ "data_deps" ]) deps = [ + ":$_ijar_target_name", ":$_process_jar_target_name", ] if (_supports_android) { @@ -1128,7 +1273,11 @@ _java_files = invoker.java_files _final_jar_path = invoker.jar_path - _intermediate_jar_path = "$target_gen_dir/$target_name.initial.jar" + _javac_jar_path = "$target_gen_dir/$target_name.javac.jar" + _process_prebuilt_jar_path = + "$target_gen_dir/$target_name.process_prebuilt.jar" + _final_ijar_path = get_path_info(_final_jar_path, "dir") + "/" + + get_path_info(_final_jar_path, "name") + ".interface.jar" _build_config = invoker.build_config @@ -1183,10 +1332,12 @@ assert(_srcjar_deps == [] || true) _rebased_build_config = rebase_path(_build_config, root_build_dir) - _rebased_jar_path = rebase_path(_intermediate_jar_path, root_build_dir) + _rebased_jar_path = rebase_path(_javac_jar_path, root_build_dir) _javac_target_name = "${target_name}__javac" - _finish_target_name = "${target_name}__finish" + _process_prebuilt_target_name = "${target_name}__process_prebuilt" + _emma_instr_target_name = "${target_name}__emma_instr" + _ijar_target_name = "${target_name}__ijar" _final_target_name = target_name action(_javac_target_name) { @@ -1199,8 +1350,8 @@ outputs = [ depfile, - _intermediate_jar_path, - _intermediate_jar_path + ".md5.stamp", + _javac_jar_path, + _javac_jar_path + ".md5.stamp", ] sources = _java_files + _java_srcjars inputs = [ @@ -1221,7 +1372,7 @@ if (_enable_incremental_javac) { args += [ "--incremental" ] deps += [ "//third_party/jmake" ] - outputs += [ "${_intermediate_jar_path}.pdb" ] + outputs += [ "${_javac_jar_path}.pdb" ] } if (_supports_android) { if (defined(invoker.alternative_android_sdk_ijar)) { @@ -1251,12 +1402,10 @@ args += rebase_path(_java_files, root_build_dir) } - process_java_prebuilt(_finish_target_name) { - visibility = [ ":$_final_target_name" ] - + process_java_prebuilt(_process_prebuilt_target_name) { build_config = _build_config - input_jar_path = _intermediate_jar_path - output_jar_path = _final_jar_path + input_jar_path = _javac_jar_path + output_jar_path = _process_prebuilt_jar_path if (defined(invoker.proguard_preprocess) && invoker.proguard_preprocess) { proguard_preprocess = invoker.proguard_preprocess proguard_config = invoker.proguard_config @@ -1266,10 +1415,36 @@ ] } + emma_instr(_emma_instr_target_name) { + visibility = [ + ":$_ijar_target_name", + ":$_final_target_name", + ] + + forward_variables_from(invoker, [ "emma_instrument" ]) + + input_jar_path = _process_prebuilt_jar_path + output_jar_path = _final_jar_path + source_files = _java_files + + deps = [ + ":$_process_prebuilt_target_name", + ] + } + + generate_interface_jar(_ijar_target_name) { + input_jar = _final_jar_path + output_jar = _final_ijar_path + deps = [ + ":$_emma_instr_target_name", + ] + } + group(_final_target_name) { forward_variables_from(invoker, [ "visibility" ]) public_deps = [ - ":$_finish_target_name", + ":$_emma_instr_target_name", + ":$_ijar_target_name", ] } } @@ -1311,6 +1486,18 @@ _run_findbugs = defined(invoker.run_findbugs) && invoker.run_findbugs assert(_run_findbugs || true) # Mark as used. + _chromium_code = true + if (defined(invoker.chromium_code)) { + _chromium_code = invoker.chromium_code + } + + _emma_never_instrument = !_chromium_code + if (defined(invoker.emma_never_instrument)) { + _emma_never_instrument = invoker.emma_never_instrument + } + assert(_emma_never_instrument || true) # Mark as used + _emma_instrument = emma_coverage && !_emma_never_instrument + if (_supports_android) { _dex_path = _base_path + ".dex.jar" if (defined(invoker.dex_path)) { @@ -1351,11 +1538,6 @@ } } - _chromium_code = true - if (defined(invoker.chromium_code)) { - _chromium_code = invoker.chromium_code - } - _srcjar_deps = [] if (defined(invoker.srcjar_deps)) { _srcjar_deps = invoker.srcjar_deps @@ -1414,6 +1596,7 @@ srcjars = _srcjars chromium_code = _chromium_code supports_android = _supports_android + emma_instrument = _emma_instrument deps = build_config_deps } @@ -1466,6 +1649,7 @@ _jar_path, ] output = _dex_path + no_locals = _emma_instrument deps = [ ":$_compile_java_target", ] @@ -1754,10 +1938,18 @@ invoker.test_suite, ] } else if (_test_type == "instrumentation") { - assert(defined(invoker.test_apk)) + deps = [ + "${invoker.apk_target}__build_config", + ] + _build_config = + get_label_info(invoker.apk_target, "target_gen_dir") + "/" + + get_label_info(invoker.apk_target, "name") + ".build_config" + _rebased_build_config = rebase_path(_build_config, root_build_dir) test_runner_args += [ "--test-apk", - invoker.test_apk, + "@FileArg($_rebased_build_config:deps_info:apk_path)", + "--apk-under-test", + "@FileArg($_rebased_build_config:deps_info:tested_apk_path)", ] } else { assert(false, "Invalid test type: $_test_type.")
diff --git a/build/config/android/rules.gni b/build/config/android/rules.gni index 6e27ce4..e6560704 100644 --- a/build/config/android/rules.gni +++ b/build/config/android/rules.gni
@@ -938,8 +938,8 @@ "//testing/android/junit:junit_test_support", "//third_party/junit", "//third_party/mockito:mockito_java", - "//third_party/robolectric:robolectric_java", "//third_party/robolectric:android-all-4.3_r2-robolectric-0", + "//third_party/robolectric:robolectric_java", ] } } @@ -1072,6 +1072,8 @@ # alternative_android_sdk_ijar, must be set if alternative_android_sdk_ijar # is used. # +# emma_never_instrument: Disables EMMA Java code coverage for this target. +# # Example # android_library("foo_java") { # java_files = [ @@ -1238,7 +1240,12 @@ _rebased_lib_dex_path = rebase_path(_lib_dex_path, root_build_dir) _template_name = target_name - final_dex_path = "$gen_dir/classes.dex" + enable_multidex = defined(invoker.enable_multidex) && invoker.enable_multidex + if (enable_multidex) { + final_dex_path = "$gen_dir/classes.dex.zip" + } else { + final_dex_path = "$gen_dir/classes.dex" + } final_dex_target_name = "${_template_name}__final_dex" _final_apk_path = "" @@ -1365,12 +1372,15 @@ _proguard_jar_path = "$base_path.proguard.jar" } + _emma_never_instrument = defined(invoker.testonly) && invoker.testonly + build_config_target = "${_template_name}__build_config" write_build_config(build_config_target) { forward_variables_from(invoker, [ "apk_under_test" ]) type = "android_apk" jar_path = _jar_path dex_path = final_dex_path + apk_path = _final_apk_path resources_zip = resources_zip_path build_config = _build_config android_manifest = _android_manifest @@ -1478,6 +1488,7 @@ srcjar_deps = _srcjar_deps jar_path = _jar_path dex_path = _lib_dex_path + emma_never_instrument = _emma_never_instrument if (defined(invoker.deps)) { deps += invoker.deps @@ -1527,8 +1538,8 @@ proguard(_proguard_target) { deps = [ ":$build_config_target", - ":$process_resources_target", ":$java_target", + ":$process_resources_target", ] inputs = [ _build_config, @@ -1546,19 +1557,33 @@ _dex_sources = [ _proguard_jar_path ] _dex_deps = [ ":$_proguard_target" ] } else { - _dex_sources = [ _lib_dex_path ] + if (enable_multidex) { + _dex_sources = [ _jar_path ] + } else { + _dex_sources = [ _lib_dex_path ] + } _dex_deps = [ ":$java_target" ] } dex("$final_dex_target_name") { + forward_variables_from(invoker, [ "enable_multidex" ]) deps = _dex_deps + [ ":$build_config_target" ] inputs = [ _build_config, ] sources = _dex_sources output = final_dex_path - _dex_arg_key = "${_rebased_build_config}:final_dex:dependency_dex_files" + if (enable_multidex) { + _dex_arg_key = "${_rebased_build_config}:dist_jar:dependency_jars" + } else { + _dex_arg_key = "${_rebased_build_config}:final_dex:dependency_dex_files" + } args = [ "--inputs=@FileArg($_dex_arg_key)" ] + + if (emma_coverage && !_emma_never_instrument) { + no_locals = true + sources += [ "$android_sdk_root/tools/lib/emma_device.jar" ] + } } if (_native_libs != []) { @@ -1638,6 +1663,7 @@ dex_path = final_dex_path load_library_from_apk = _load_library_from_apk create_density_splits = _create_density_splits + emma_instrument = emma_coverage && !_emma_never_instrument if (!defined(extensions_to_not_compress)) { # Allow icu data, v8 snapshots, and pak files to be loaded directly from @@ -1669,8 +1695,7 @@ if (_native_libs != [] && !_create_abi_split) { native_libs_dir = _native_libs_dir - # Placeholders are not necessary for L+, so add them here, but don't - # bother to create them in the case of splits. + # Placeholders necessary for some older devices. # http://crbug.com/395038 forward_variables_from(invoker, [ "native_lib_placeholders" ]) @@ -1707,9 +1732,14 @@ keystore_password = _keystore_password native_libs_dir = _native_libs_dir + + # Placeholders necessary for some older devices. + # http://crbug.com/395038 + forward_variables_from(invoker, [ "native_lib_placeholders" ]) + deps = [ - ":${_prepare_native_target_name}", ":${_manifest_rule}", + ":${_prepare_native_target_name}", ] incremental_deps = deps } @@ -1770,8 +1800,8 @@ # actual target, but instead loads them at runtime, we need to explicitly # depend on them here. public_deps = [ - ":${_template_name}__create_incremental", ":${_create_incremental_script_rule_name}", + ":${_template_name}__create_incremental", ":${java_target}", ] if (_native_libs != []) { @@ -1824,35 +1854,36 @@ # ] # } template("instrumentation_test_apk") { - set_sources_assignment_filter([]) testonly = true - _template_name = target_name + _apk_target_name = "${target_name}__apk" + _test_runner_target_name = "${target_name}__test_runner_script" - if (defined(invoker.apk_name)) { - test_runner_data_dep = [ ":${_template_name}__test_runner_script" ] - test_runner_script("${_template_name}__test_runner_script") { - forward_variables_from(invoker, [ "isolate_file" ]) - test_name = invoker.target_name - test_type = "instrumentation" - test_apk = invoker.apk_name - } + test_runner_script(_test_runner_target_name) { + forward_variables_from(invoker, [ "isolate_file" ]) + test_name = invoker.target_name + test_type = "instrumentation" + apk_target = ":$_apk_target_name" } - android_apk(target_name) { + android_apk(_apk_target_name) { deps = [] data_deps = [] forward_variables_from(invoker, "*") + deps += [ "//testing/android/broker:broker_java" ] data_deps += [ "//testing/android/driver:driver_apk", "//tools/android/forwarder2", "//tools/android/md5sum", ] - if (defined(test_runner_data_dep)) { - data_deps += test_runner_data_dep - } - deps += [ "//testing/android/broker:broker_java" ] run_findbugs = false } + + group(target_name) { + public_deps = [ + ":$_apk_target_name", + ":$_test_runner_target_name", + ] + } } # Declare an Android gtest apk
diff --git a/build/config/compiler/BUILD.gn b/build/config/compiler/BUILD.gn index 2e44b85..bd1067f 100644 --- a/build/config/compiler/BUILD.gn +++ b/build/config/compiler/BUILD.gn
@@ -613,6 +613,11 @@ cflags += [ # Warnings permanently disabled: + # C4091: 'typedef ': ignored on left of 'X' when no variable is + # declared. + # This happens in a number of Windows headers. Dumb. + "/wd4091", + # C4127: conditional expression is constant # This warning can in theory catch dead code and other problems, but # triggers in far too many desirable cases where the conditional @@ -677,8 +682,17 @@ "/wd4510", # Default constructor could not be generated. "/wd4512", # Assignment operator could not be generated. "/wd4610", # Class can never be instantiated, constructor required. + "/wd4838", # Narrowing conversion. Doesn't seem to be very useful. "/wd4995", # 'X': name was marked as #pragma deprecated "/wd4996", # Deprecated function warning. + + # These are variable shadowing warnings that are new in VS2015. We + # should work through these at some point -- they may be removed from + # the RTM release in the /W4 set. + "/wd4456", + "/wd4457", + "/wd4458", + "/wd4459", ] # VS xtree header file needs to be patched or 4702 (unreachable code
diff --git a/build/config/ios/rules.gni b/build/config/ios/rules.gni index 4370393..c18c065 100644 --- a/build/config/ios/rules.gni +++ b/build/config/ios/rules.gni
@@ -169,8 +169,8 @@ identity = invoker.code_signing_identity application_path = "$root_build_dir/$app_name.app" deps = [ - ":$plist_gen_target_name", ":$bin_gen_target_name", + ":$plist_gen_target_name", ] } } else { @@ -181,8 +181,8 @@ # Top level group group(target_name) { deps = [ - ":$plist_gen_target_name", ":$bin_gen_target_name", + ":$plist_gen_target_name", ] if (invoker.code_signing_identity != "") { deps += [ ":$code_sign_gen_target_name" ]
diff --git a/build/config/mac/rules.gni b/build/config/mac/rules.gni index 8baad60..32f3d99 100644 --- a/build/config/mac/rules.gni +++ b/build/config/mac/rules.gni
@@ -195,10 +195,10 @@ group(copy_all_target_name) { visibility = [ ":$group_gen_target_name" ] deps = [ - ":$struct_gen_target_name", - ":$copy_plist_gen_target_name", ":$copy_bin_target_name", + ":$copy_plist_gen_target_name", ":$copy_xib_target_name", + ":$struct_gen_target_name", ] }
diff --git a/build/config/win/BUILD.gn b/build/config/win/BUILD.gn index daa07741..dec7a5a 100644 --- a/build/config/win/BUILD.gn +++ b/build/config/win/BUILD.gn
@@ -13,11 +13,12 @@ # Windows-only. config("compiler") { asmflags = [ - # When /SAFESEH is specified, the linker will only produce an image if it + # When /safeseh is specified, the linker will only produce an image if it # can also produce a table of the image's safe exception handlers. This # table specifies for the operating system which exception handlers are - # valid for the image. - "/SAFESEH", + # valid for the image. Note that /SAFESEH isn't accepted on the command + # line, only /safeseh. + "/safeseh", ] cflags = [
diff --git a/build/java_apk.gypi b/build/java_apk.gypi index 44a25f3..2a62d972 100644 --- a/build/java_apk.gypi +++ b/build/java_apk.gypi
@@ -155,7 +155,6 @@ 'resource_zip_path': '<(intermediate_dir)/<(_target_name).resources.zip', 'shared_resources%': 0, 'app_as_shared_library%': 0, - 'final_apk_path%': '<(PRODUCT_DIR)/apks/<(apk_name).apk', 'final_apk_path_no_extension%': '<(PRODUCT_DIR)/apks/<(apk_name)', 'final_abi_split_apk_path%': '<(PRODUCT_DIR)/apks/<(apk_name)-abi-<(android_app_abi).apk', 'incomplete_apk_path': '<(intermediate_dir)/<(apk_name)-incomplete.apk', @@ -181,6 +180,7 @@ 'unsigned_apk_path': '<(unsigned_apk_path)', 'unsigned_abi_split_apk_path': '<(unsigned_abi_split_apk_path)', 'create_abi_split%': '<(create_abi_split)', + 'final_apk_path%': '<(PRODUCT_DIR)/apks/<(apk_name).apk', 'conditions': [ ['gyp_managed_install == 1 and native_lib_target != ""', { 'conditions': [ @@ -243,6 +243,7 @@ ], 'enable_errorprone%': 0, 'errorprone_exe_path': '<(PRODUCT_DIR)/bin.java/chromium_errorprone', + 'final_apk_path%': '<(final_apk_path)', }, # Pass the jar path to the apk's "fake" jar target. This would be better as # direct_dependent_settings, but a variable set by a direct_dependent_settings @@ -259,12 +260,17 @@ 'debug_build_proguard_enabled': 'true', } }], + ['is_test_apk == 0', { + 'variables': { + 'tested_apk_path': '<(final_apk_path)', + 'tested_apk_obfuscated_jar_path': '<(obfuscated_jar_path)', + 'tested_apk_dex_path': '<(dex_path)', + 'tested_apk_is_multidex': '<(enable_multidex)', + } + }] ], 'variables': { 'apk_output_jar_path': '<(jar_path)', - 'tested_apk_obfuscated_jar_path': '<(obfuscated_jar_path)', - 'tested_apk_dex_path': '<(dex_path)', - 'tested_apk_is_multidex': '<(enable_multidex)', }, }, 'conditions': [
diff --git a/build/secondary/third_party/android_tools/BUILD.gn b/build/secondary/third_party/android_tools/BUILD.gn index c849d035..fa2f67ab 100644 --- a/build/secondary/third_party/android_tools/BUILD.gn +++ b/build/secondary/third_party/android_tools/BUILD.gn
@@ -68,8 +68,8 @@ android_java_prebuilt("android_support_v7_mediarouter_java") { deps = [ - ":android_support_v7_mediarouter_resources", ":android_support_v7_appcompat_java", + ":android_support_v7_mediarouter_resources", ] jar_path = "$android_sdk_root/extras/android/support/v7/mediarouter/libs/android-support-v7-mediarouter.jar" }
diff --git a/build/toolchain/win/BUILD.gn b/build/toolchain/win/BUILD.gn index e3100399..777c6e9e 100644 --- a/build/toolchain/win/BUILD.gn +++ b/build/toolchain/win/BUILD.gn
@@ -26,8 +26,8 @@ # This value will be inherited in the toolchain below. concurrent_links = exec_script("../get_concurrent_links.py", [], "value") -# Copy the VS runtime DLL for the default toolchain the root build directory so -# things will run. +# Copy the VS runtime DLL for the default toolchain to the root build directory +# so things will run. if (current_toolchain == default_toolchain) { if (is_debug) { configuration_name = "Debug"
diff --git a/build/vs_toolchain.py b/build/vs_toolchain.py index 648c7e6..723106b 100755 --- a/build/vs_toolchain.py +++ b/build/vs_toolchain.py
@@ -26,7 +26,7 @@ returns the location of the VS runtime DLLs so they can be copied into the output directory after gyp generation. """ - vs2013_runtime_dll_dirs = None + vs_runtime_dll_dirs = None depot_tools_win_toolchain = \ bool(int(os.environ.get('DEPOT_TOOLS_WIN_TOOLCHAIN', '1'))) # When running on a non-Windows host, only do this if the SDK has explicitly @@ -47,7 +47,7 @@ # TODO(scottmg): The order unfortunately matters in these. They should be # split into separate keys for x86 and x64. (See CopyVsRuntimeDlls call # below). http://crbug.com/345992 - vs2013_runtime_dll_dirs = toolchain_data['runtime_dirs'] + vs_runtime_dll_dirs = toolchain_data['runtime_dirs'] os.environ['GYP_MSVS_OVERRIDE_PATH'] = toolchain os.environ['GYP_MSVS_VERSION'] = version @@ -62,9 +62,9 @@ os.environ['WINDOWSSDKDIR'] = win_sdk os.environ['WDK_DIR'] = wdk # Include the VS runtime in the PATH in case it's not machine-installed. - runtime_path = ';'.join(vs2013_runtime_dll_dirs) + runtime_path = ';'.join(vs_runtime_dll_dirs) os.environ['PATH'] = runtime_path + ';' + os.environ['PATH'] - return vs2013_runtime_dll_dirs + return vs_runtime_dll_dirs def _VersionNumber(): @@ -111,6 +111,34 @@ _CopyRuntimeImpl(target, source) +def _CopyRuntime(target_dir, source_dir, target_cpu, debug): + """Copy the VS runtime DLLs, only if the target doesn't exist, but the target + directory does exist. Handles VS 2013 and VS 2015.""" + suffix = "d.dll" if debug else ".dll" + if os.environ.get('GYP_MSVS_VERSION') == '2015': + _CopyRuntime2015(target_dir, source_dir, '%s140' + suffix) + else: + _CopyRuntime2013(target_dir, source_dir, 'msvc%s120' + suffix) + + # Copy the PGO runtime library to the release directories. + if not debug and os.environ.get('GYP_MSVS_OVERRIDE_PATH'): + pgo_x86_runtime_dir = os.path.join(os.environ.get('GYP_MSVS_OVERRIDE_PATH'), + 'VC', 'bin') + pgo_x64_runtime_dir = os.path.join(pgo_x86_runtime_dir, 'amd64') + pgo_runtime_dll = 'pgort' + _VersionNumber() + '.dll' + if target_cpu == "x86": + source_x86 = os.path.join(pgo_x86_runtime_dir, pgo_runtime_dll) + if os.path.exists(source_x86): + _CopyRuntimeImpl(os.path.join(target_dir, pgo_runtime_dll), source_x86) + elif target_cpu == "x64": + source_x64 = os.path.join(pgo_x64_runtime_dir, pgo_runtime_dll) + if os.path.exists(source_x64): + _CopyRuntimeImpl(os.path.join(target_dir, pgo_runtime_dll), + source_x64) + else: + raise NotImplementedError("Unexpected target_cpu value:" + target_cpu) + + def CopyVsRuntimeDlls(output_dir, runtime_dirs): """Copies the VS runtime DLLs from the given |runtime_dirs| to the output directory so that even if not system-installed, built binaries are likely to @@ -118,6 +146,8 @@ This needs to be run after gyp has been run so that the expected target output directories are already created. + + This is used for the GYP build and gclient runhooks. """ x86, x64 = runtime_dirs out_debug = os.path.join(output_dir, 'Debug') @@ -131,35 +161,12 @@ os.makedirs(out_debug_nacl64) if os.path.exists(out_release) and not os.path.exists(out_release_nacl64): os.makedirs(out_release_nacl64) - if os.environ.get('GYP_MSVS_VERSION') == '2015': - _CopyRuntime2015(out_debug, x86, '%s140d.dll') - _CopyRuntime2015(out_release, x86, '%s140.dll') - _CopyRuntime2015(out_debug_x64, x64, '%s140d.dll') - _CopyRuntime2015(out_release_x64, x64, '%s140.dll') - _CopyRuntime2015(out_debug_nacl64, x64, '%s140d.dll') - _CopyRuntime2015(out_release_nacl64, x64, '%s140.dll') - else: - # VS2013 is the default. - _CopyRuntime2013(out_debug, x86, 'msvc%s120d.dll') - _CopyRuntime2013(out_release, x86, 'msvc%s120.dll') - _CopyRuntime2013(out_debug_x64, x64, 'msvc%s120d.dll') - _CopyRuntime2013(out_release_x64, x64, 'msvc%s120.dll') - _CopyRuntime2013(out_debug_nacl64, x64, 'msvc%s120d.dll') - _CopyRuntime2013(out_release_nacl64, x64, 'msvc%s120.dll') - - # Copy the PGO runtime library to the release directories. - if os.environ.get('GYP_MSVS_OVERRIDE_PATH'): - pgo_x86_runtime_dir = os.path.join(os.environ.get('GYP_MSVS_OVERRIDE_PATH'), - 'VC', 'bin') - pgo_x64_runtime_dir = os.path.join(pgo_x86_runtime_dir, 'amd64') - pgo_runtime_dll = 'pgort' + _VersionNumber() + '.dll' - source_x86 = os.path.join(pgo_x86_runtime_dir, pgo_runtime_dll) - if os.path.exists(source_x86): - _CopyRuntimeImpl(os.path.join(out_release, pgo_runtime_dll), source_x86) - source_x64 = os.path.join(pgo_x64_runtime_dir, pgo_runtime_dll) - if os.path.exists(source_x64): - _CopyRuntimeImpl(os.path.join(out_release_x64, pgo_runtime_dll), - source_x64) + _CopyRuntime(out_debug, x86, "x86", debug=True) + _CopyRuntime(out_release, x86, "x86", debug=False) + _CopyRuntime(out_debug_x64, x64, "x64", debug=True) + _CopyRuntime(out_release_x64, x64, "x64", debug=False) + _CopyRuntime(out_debug_nacl64, x64, "x64", debug=True) + _CopyRuntime(out_release_nacl64, x64, "x64", debug=False) def CopyDlls(target_dir, configuration, target_cpu): @@ -170,18 +177,18 @@ The debug configuration gets both the debug and release DLLs; the release config only the latter. + + This is used for the GN build. """ - vs2013_runtime_dll_dirs = SetEnvironmentAndGetRuntimeDllDirs() - if not vs2013_runtime_dll_dirs: + vs_runtime_dll_dirs = SetEnvironmentAndGetRuntimeDllDirs() + if not vs_runtime_dll_dirs: return - x64_runtime, x86_runtime = vs2013_runtime_dll_dirs + x64_runtime, x86_runtime = vs_runtime_dll_dirs runtime_dir = x64_runtime if target_cpu == 'x64' else x86_runtime - _CopyRuntime2013( - target_dir, runtime_dir, 'msvc%s' + _VersionNumber() + '.dll') + _CopyRuntime(target_dir, runtime_dir, target_cpu, debug=False) if configuration == 'Debug': - _CopyRuntime2013( - target_dir, runtime_dir, 'msvc%s' + _VersionNumber() + 'd.dll') + _CopyRuntime(target_dir, runtime_dir, target_cpu, debug=True) def _GetDesiredVsToolchainHashes():
diff --git a/cc/BUILD.gn b/cc/BUILD.gn index c3b9b8a..8fd1828 100644 --- a/cc/BUILD.gn +++ b/cc/BUILD.gn
@@ -686,9 +686,9 @@ "//base/third_party/dynamic_annotations", "//cc/surfaces", "//cc/surfaces:surface_id", + "//gpu/command_buffer/client:gl_in_process_context", "//gpu/command_buffer/client:gles2_c_lib", "//gpu/command_buffer/client:gles2_implementation", - "//gpu/command_buffer/client:gl_in_process_context", "//gpu/command_buffer/common:gles2_utils", "//gpu/skia_bindings", "//media", @@ -696,8 +696,8 @@ "//testing/gmock", "//testing/gtest", "//ui/gfx", - "//ui/gfx/geometry", "//ui/gfx:test_support", + "//ui/gfx/geometry", "//ui/gl", "//ui/gl:test_support", ] @@ -888,8 +888,8 @@ "//testing/gtest", "//ui/events:events_base", "//ui/gfx", - "//ui/gfx/geometry", "//ui/gfx:test_support", + "//ui/gfx/geometry", "//ui/gl", "//ui/gl:test_support", ]
diff --git a/cc/animation/keyframed_animation_curve_unittest.cc b/cc/animation/keyframed_animation_curve_unittest.cc index dc4e8173f..718872b8 100644 --- a/cc/animation/keyframed_animation_curve_unittest.cc +++ b/cc/animation/keyframed_animation_curve_unittest.cc
@@ -732,7 +732,7 @@ curve->AddKeyframe( FloatKeyframe::Create(base::TimeDelta::FromSecondsD(1.f), 1.f, nullptr)); curve->SetTimingFunction( - CubicBezierTimingFunction::Create(0.75f, 0.f, 0.25f, 1.f).Pass()); + CubicBezierTimingFunction::Create(0.75f, 0.f, 0.25f, 1.f)); EXPECT_FLOAT_EQ(0.f, curve->GetValue(base::TimeDelta::FromSecondsD(-1.f))); EXPECT_FLOAT_EQ(0.f, curve->GetValue(base::TimeDelta::FromSecondsD(0.f))); EXPECT_NEAR(0.05f, curve->GetValue(base::TimeDelta::FromSecondsD(0.25f)), @@ -751,12 +751,12 @@ KeyframedFloatAnimationCurve::Create()); curve->AddKeyframe(FloatKeyframe::Create( base::TimeDelta(), 0.f, - CubicBezierTimingFunction::Create(0.35f, 0.f, 0.65f, 1.f).Pass())); + CubicBezierTimingFunction::Create(0.35f, 0.f, 0.65f, 1.f))); curve->AddKeyframe( FloatKeyframe::Create(base::TimeDelta::FromSecondsD(1.f), 1.f, nullptr)); // Curve timing function producing outputs outside of range [0,1]. curve->SetTimingFunction( - CubicBezierTimingFunction::Create(0.5f, -0.5f, 0.5f, 1.5f).Pass()); + CubicBezierTimingFunction::Create(0.5f, -0.5f, 0.5f, 1.5f)); EXPECT_FLOAT_EQ(0.f, curve->GetValue(base::TimeDelta::FromSecondsD(-1.f))); EXPECT_FLOAT_EQ(0.f, curve->GetValue(base::TimeDelta::FromSecondsD(0.f))); EXPECT_FLOAT_EQ(0.f, curve->GetValue(base::TimeDelta::FromSecondsD( @@ -782,7 +782,7 @@ FloatKeyframe::Create(base::TimeDelta::FromSecondsD(1.0), 2.f, nullptr)); // Curve timing function producing timing outputs outside of range [0,1]. curve->SetTimingFunction( - CubicBezierTimingFunction::Create(0.5f, -0.5f, 0.5f, 1.5f).Pass()); + CubicBezierTimingFunction::Create(0.5f, -0.5f, 0.5f, 1.5f)); EXPECT_NEAR(-0.076f, curve->GetValue(base::TimeDelta::FromSecondsD(0.25f)), 0.001f); @@ -799,12 +799,12 @@ // Keyframe timing function with 0.5 gradients at each end. curve->AddKeyframe(FloatKeyframe::Create( base::TimeDelta(), 0.f, - CubicBezierTimingFunction::Create(0.5f, 0.25f, 0.5f, 0.75f).Pass())); + CubicBezierTimingFunction::Create(0.5f, 0.25f, 0.5f, 0.75f))); curve->AddKeyframe( FloatKeyframe::Create(base::TimeDelta::FromSecondsD(1.f), 1.f, nullptr)); // Curve timing function producing timing outputs outside of range [0,1]. curve->SetTimingFunction( - CubicBezierTimingFunction::Create(0.5f, -0.5f, 0.5f, 1.5f).Pass()); + CubicBezierTimingFunction::Create(0.5f, -0.5f, 0.5f, 1.5f)); EXPECT_NEAR(-0.02f, curve->GetValue(base::TimeDelta::FromSecondsD(0.25f)), 0.002f); // c(.25)=-.04, -.04*0.5=-0.02 @@ -828,7 +828,7 @@ FloatKeyframe::Create(base::TimeDelta::FromSecondsD(1.0), 2.f, nullptr)); // Curve timing function producing timing outputs outside of range [0,1]. curve->SetTimingFunction( - CubicBezierTimingFunction::Create(0.5f, -0.5f, 0.5f, 1.5f).Pass()); + CubicBezierTimingFunction::Create(0.5f, -0.5f, 0.5f, 1.5f)); EXPECT_FLOAT_EQ(0.f, curve->GetValue(base::TimeDelta::FromSecondsD(0.25f))); EXPECT_FLOAT_EQ(2.f, curve->GetValue(base::TimeDelta::FromSecondsD(0.75f))); @@ -849,7 +849,7 @@ curve->AddKeyframe( FloatKeyframe::Create(base::TimeDelta::FromSecondsD(4.f), 9.f, nullptr)); curve->SetTimingFunction( - CubicBezierTimingFunction::Create(0.5f, 0.f, 0.5f, 1.f).Pass()); + CubicBezierTimingFunction::Create(0.5f, 0.f, 0.5f, 1.f)); EXPECT_FLOAT_EQ(0.f, curve->GetValue(base::TimeDelta::FromSecondsD(-1.f))); EXPECT_FLOAT_EQ(0.f, curve->GetValue(base::TimeDelta::FromSecondsD(0.f))); EXPECT_NEAR(0.42f, curve->GetValue(base::TimeDelta::FromSecondsD(1.f)), @@ -879,7 +879,7 @@ FloatKeyframe::Create(base::TimeDelta::FromSecondsD(4.0), 9.f, nullptr)); // Curve timing function producing outputs outside of range [0,1]. curve->SetTimingFunction( - CubicBezierTimingFunction::Create(0.5f, -0.5f, 0.5f, 1.5f).Pass()); + CubicBezierTimingFunction::Create(0.5f, -0.5f, 0.5f, 1.5f)); EXPECT_LE(curve->GetValue(base::TimeDelta::FromSecondsD(1.f)), 0.f); // c(.25) < 0 EXPECT_GE(curve->GetValue(base::TimeDelta::FromSecondsD(3.f)),
diff --git a/cc/animation/layer_animation_controller_unittest.cc b/cc/animation/layer_animation_controller_unittest.cc index 45b2633..2128f27 100644 --- a/cc/animation/layer_animation_controller_unittest.cc +++ b/cc/animation/layer_animation_controller_unittest.cc
@@ -455,8 +455,8 @@ controller->AddValueObserver(&dummy); scoped_ptr<Animation> to_add(CreateAnimation( - scoped_ptr<AnimationCurve>(new FakeFloatTransition(1.0, 0.f, 1.f)).Pass(), - 1, Animation::OPACITY)); + scoped_ptr<AnimationCurve>(new FakeFloatTransition(1.0, 0.f, 1.f)), 1, + Animation::OPACITY)); EXPECT_FALSE(controller->needs_to_start_animations_for_testing()); controller->AddAnimation(std::move(to_add)); @@ -486,8 +486,8 @@ controller_impl->AddValueObserver(&dummy_impl); scoped_ptr<Animation> to_add(CreateAnimation( - scoped_ptr<AnimationCurve>(new FakeFloatTransition(1.0, 0.f, 1.f)).Pass(), - 1, Animation::OPACITY)); + scoped_ptr<AnimationCurve>(new FakeFloatTransition(1.0, 0.f, 1.f)), 1, + Animation::OPACITY)); to_add->set_is_impl_only(true); controller_impl->AddAnimation(std::move(to_add)); @@ -685,9 +685,8 @@ gfx::ScrollOffset initial_value(100.f, 300.f); gfx::ScrollOffset target_value(300.f, 200.f); scoped_ptr<ScrollOffsetAnimationCurve> curve( - ScrollOffsetAnimationCurve::Create( - target_value, - EaseInOutTimingFunction::Create().Pass())); + ScrollOffsetAnimationCurve::Create(target_value, + EaseInOutTimingFunction::Create())); scoped_ptr<Animation> animation( Animation::Create(std::move(curve), 1, 0, Animation::SCROLL_OFFSET)); @@ -764,9 +763,8 @@ gfx::ScrollOffset initial_value(500.f, 100.f); gfx::ScrollOffset target_value(300.f, 200.f); scoped_ptr<ScrollOffsetAnimationCurve> curve( - ScrollOffsetAnimationCurve::Create( - target_value, - EaseInOutTimingFunction::Create().Pass())); + ScrollOffsetAnimationCurve::Create(target_value, + EaseInOutTimingFunction::Create())); scoped_ptr<Animation> animation( Animation::Create(std::move(curve), 1, 0, Animation::SCROLL_OFFSET)); @@ -835,9 +833,8 @@ gfx::ScrollOffset initial_value(100.f, 300.f); gfx::ScrollOffset target_value(300.f, 200.f); scoped_ptr<ScrollOffsetAnimationCurve> curve( - ScrollOffsetAnimationCurve::Create( - target_value, - EaseInOutTimingFunction::Create().Pass())); + ScrollOffsetAnimationCurve::Create(target_value, + EaseInOutTimingFunction::Create())); curve->SetInitialValue(initial_value); double duration_in_seconds = curve->Duration().InSecondsF(); @@ -891,8 +888,8 @@ // First test the 1-argument version of RemoveAnimation. gfx::ScrollOffset target_value(300.f, 200.f); scoped_ptr<ScrollOffsetAnimationCurve> curve( - ScrollOffsetAnimationCurve::Create( - target_value, EaseInOutTimingFunction::Create().Pass())); + ScrollOffsetAnimationCurve::Create(target_value, + EaseInOutTimingFunction::Create())); int animation_id = 1; scoped_ptr<Animation> animation(Animation::Create( @@ -915,8 +912,8 @@ EXPECT_FALSE(controller_impl->scroll_offset_animation_was_interrupted()); // Now, test the 2-argument version of RemoveAnimation. - curve = ScrollOffsetAnimationCurve::Create( - target_value, EaseInOutTimingFunction::Create().Pass()); + curve = ScrollOffsetAnimationCurve::Create(target_value, + EaseInOutTimingFunction::Create()); animation = Animation::Create(std::move(curve), animation_id, 0, Animation::SCROLL_OFFSET); animation->set_needs_synchronized_start_time(true); @@ -1016,8 +1013,8 @@ controller_impl->set_layer_animation_delegate(&delegate); scoped_ptr<Animation> to_add(CreateAnimation( - scoped_ptr<AnimationCurve>(new FakeFloatTransition(1.0, 0.f, 1.f)).Pass(), - 1, Animation::OPACITY)); + scoped_ptr<AnimationCurve>(new FakeFloatTransition(1.0, 0.f, 1.f)), 1, + Animation::OPACITY)); to_add->set_is_impl_only(true); controller_impl->AddAnimation(std::move(to_add)); @@ -1142,8 +1139,8 @@ controller->AddValueObserver(&dummy); scoped_ptr<Animation> to_add(CreateAnimation( - scoped_ptr<AnimationCurve>(new FakeFloatTransition(1.0, 0.f, 1.f)).Pass(), - 1, Animation::OPACITY)); + scoped_ptr<AnimationCurve>(new FakeFloatTransition(1.0, 0.f, 1.f)), 1, + Animation::OPACITY)); to_add->set_needs_synchronized_start_time(true); // We should pause at the first keyframe indefinitely waiting for that @@ -1184,12 +1181,11 @@ EXPECT_FALSE(controller->needs_to_start_animations_for_testing()); controller->AddAnimation(CreateAnimation( - scoped_ptr<AnimationCurve>(new FakeFloatTransition(1.0, 0.f, 1.f)).Pass(), - 1, Animation::OPACITY)); + scoped_ptr<AnimationCurve>(new FakeFloatTransition(1.0, 0.f, 1.f)), 1, + Animation::OPACITY)); controller->AddAnimation(CreateAnimation( - scoped_ptr<AnimationCurve>(new FakeFloatTransition(1.0, 1.f, 0.5f)) - .Pass(), - 2, Animation::OPACITY)); + scoped_ptr<AnimationCurve>(new FakeFloatTransition(1.0, 1.f, 0.5f)), 2, + Animation::OPACITY)); EXPECT_TRUE(controller->needs_to_start_animations_for_testing()); @@ -1224,17 +1220,16 @@ LayerAnimationController::Create(0)); controller->AddValueObserver(&dummy); controller->AddAnimation(CreateAnimation( - scoped_ptr<AnimationCurve>(new FakeFloatTransition(1.0, 0.f, 1.f)).Pass(), - 1, Animation::OPACITY)); + scoped_ptr<AnimationCurve>(new FakeFloatTransition(1.0, 0.f, 1.f)), 1, + Animation::OPACITY)); controller->Animate(kInitialTickTime); controller->UpdateState(true, events.get()); EXPECT_TRUE(controller->HasActiveAnimation()); EXPECT_EQ(0.f, dummy.opacity()); scoped_ptr<Animation> to_add(CreateAnimation( - scoped_ptr<AnimationCurve>(new FakeFloatTransition(1.0, 1.f, 0.5f)) - .Pass(), - 2, Animation::OPACITY)); + scoped_ptr<AnimationCurve>(new FakeFloatTransition(1.0, 1.f, 0.5f)), 2, + Animation::OPACITY)); controller->AbortAnimations(Animation::OPACITY); controller->AddAnimation(std::move(to_add)); @@ -1261,14 +1256,14 @@ controller->AddValueObserver(&dummy); controller->AddAnimation(CreateAnimation( - scoped_ptr<AnimationCurve>(new FakeTransformTransition(1)).Pass(), 1, + scoped_ptr<AnimationCurve>(new FakeTransformTransition(1)), 1, Animation::TRANSFORM)); controller->AddAnimation(CreateAnimation( - scoped_ptr<AnimationCurve>(new FakeTransformTransition(1)).Pass(), 2, + scoped_ptr<AnimationCurve>(new FakeTransformTransition(1)), 2, Animation::TRANSFORM)); controller->AddAnimation(CreateAnimation( - scoped_ptr<AnimationCurve>(new FakeFloatTransition(1.0, 0.f, 1.f)).Pass(), - 2, Animation::OPACITY)); + scoped_ptr<AnimationCurve>(new FakeFloatTransition(1.0, 0.f, 1.f)), 2, + Animation::OPACITY)); controller->Animate(kInitialTickTime); controller->UpdateState(true, events.get()); @@ -1298,15 +1293,14 @@ controller->AddValueObserver(&dummy); controller->AddAnimation(CreateAnimation( - scoped_ptr<AnimationCurve>(new FakeTransformTransition(2)).Pass(), 1, + scoped_ptr<AnimationCurve>(new FakeTransformTransition(2)), 1, Animation::TRANSFORM)); controller->AddAnimation(CreateAnimation( - scoped_ptr<AnimationCurve>(new FakeFloatTransition(1.0, 0.f, 1.f)).Pass(), - 1, Animation::OPACITY)); + scoped_ptr<AnimationCurve>(new FakeFloatTransition(1.0, 0.f, 1.f)), 1, + Animation::OPACITY)); controller->AddAnimation(CreateAnimation( - scoped_ptr<AnimationCurve>(new FakeFloatTransition(1.0, 1.f, 0.5f)) - .Pass(), - 2, Animation::OPACITY)); + scoped_ptr<AnimationCurve>(new FakeFloatTransition(1.0, 1.f, 0.5f)), 2, + Animation::OPACITY)); // Animations with id 1 should both start now. controller->Animate(kInitialTickTime); @@ -1340,8 +1334,8 @@ controller->AddValueObserver(&dummy); scoped_ptr<Animation> to_add(CreateAnimation( - scoped_ptr<AnimationCurve>(new FakeFloatTransition(1.0, 0.f, 1.f)).Pass(), - 1, Animation::OPACITY)); + scoped_ptr<AnimationCurve>(new FakeFloatTransition(1.0, 0.f, 1.f)), 1, + Animation::OPACITY)); to_add->set_iterations(3); controller->AddAnimation(std::move(to_add)); @@ -1386,8 +1380,8 @@ controller->AddValueObserver(&dummy); scoped_ptr<Animation> to_add(CreateAnimation( - scoped_ptr<AnimationCurve>(new FakeFloatTransition(1.0, 0.f, 1.f)).Pass(), - 1, Animation::OPACITY)); + scoped_ptr<AnimationCurve>(new FakeFloatTransition(1.0, 0.f, 1.f)), 1, + Animation::OPACITY)); to_add->set_iterations(-1); controller->AddAnimation(std::move(to_add)); @@ -1433,8 +1427,8 @@ controller->AddValueObserver(&dummy); controller->AddAnimation(CreateAnimation( - scoped_ptr<AnimationCurve>(new FakeFloatTransition(1.0, 0.f, 1.f)).Pass(), - 1, Animation::OPACITY)); + scoped_ptr<AnimationCurve>(new FakeFloatTransition(1.0, 0.f, 1.f)), 1, + Animation::OPACITY)); controller->Animate(kInitialTickTime); controller->UpdateState(true, events.get()); @@ -1480,15 +1474,14 @@ const int animation_id = 2; controller->AddAnimation(Animation::Create( - scoped_ptr<AnimationCurve>(new FakeTransformTransition(1)).Pass(), 1, 1, + scoped_ptr<AnimationCurve>(new FakeTransformTransition(1)), 1, 1, Animation::TRANSFORM)); controller->AddAnimation(Animation::Create( - scoped_ptr<AnimationCurve>(new FakeFloatTransition(2.0, 0.f, 1.f)).Pass(), + scoped_ptr<AnimationCurve>(new FakeFloatTransition(2.0, 0.f, 1.f)), animation_id, 1, Animation::OPACITY)); controller->AddAnimation(Animation::Create( - scoped_ptr<AnimationCurve>(new FakeFloatTransition(1.0, 1.f, 0.75f)) - .Pass(), - 3, 2, Animation::OPACITY)); + scoped_ptr<AnimationCurve>(new FakeFloatTransition(1.0, 1.f, 0.75f)), 3, + 2, Animation::OPACITY)); controller->Animate(kInitialTickTime); controller->UpdateState(true, events.get()); @@ -1526,8 +1519,8 @@ controller->AddValueObserver(&dummy); scoped_ptr<Animation> to_add(CreateAnimation( - scoped_ptr<AnimationCurve>(new FakeFloatTransition(2.0, 0.f, 1.f)).Pass(), - 0, Animation::OPACITY)); + scoped_ptr<AnimationCurve>(new FakeFloatTransition(2.0, 0.f, 1.f)), 0, + Animation::OPACITY)); to_add->set_needs_synchronized_start_time(true); controller->AddAnimation(std::move(to_add)); @@ -1557,7 +1550,7 @@ controller->AddValueObserver(&dummy); scoped_ptr<Animation> first_animation(CreateAnimation( - scoped_ptr<AnimationCurve>(new FakeTransformTransition(1)).Pass(), 1, + scoped_ptr<AnimationCurve>(new FakeTransformTransition(1)), 1, Animation::TRANSFORM)); first_animation->set_is_controlling_instance_for_test(true); controller->AddAnimation(std::move(first_animation)); @@ -1566,8 +1559,8 @@ controller->UpdateState(true, events.get()); scoped_ptr<Animation> second_animation(CreateAnimation( - scoped_ptr<AnimationCurve>(new FakeFloatTransition(1.0, 0.f, 1.f)).Pass(), - 2, Animation::OPACITY)); + scoped_ptr<AnimationCurve>(new FakeFloatTransition(1.0, 0.f, 1.f)), 2, + Animation::OPACITY)); second_animation->set_is_controlling_instance_for_test(true); controller->AddAnimation(std::move(second_animation)); @@ -1736,20 +1729,20 @@ // Start with several animations, and allow some of them to reach the finished // state. controller->AddAnimation(Animation::Create( - scoped_ptr<AnimationCurve>(new FakeTransformTransition(1.0)).Pass(), 1, 1, + scoped_ptr<AnimationCurve>(new FakeTransformTransition(1.0)), 1, 1, Animation::TRANSFORM)); controller->AddAnimation(Animation::Create( - scoped_ptr<AnimationCurve>(new FakeFloatTransition(1.0, 0.f, 1.f)).Pass(), - 2, 2, Animation::OPACITY)); + scoped_ptr<AnimationCurve>(new FakeFloatTransition(1.0, 0.f, 1.f)), 2, 2, + Animation::OPACITY)); controller->AddAnimation(Animation::Create( - scoped_ptr<AnimationCurve>(new FakeTransformTransition(1.0)).Pass(), 3, 3, + scoped_ptr<AnimationCurve>(new FakeTransformTransition(1.0)), 3, 3, Animation::TRANSFORM)); controller->AddAnimation(Animation::Create( - scoped_ptr<AnimationCurve>(new FakeTransformTransition(2.0)).Pass(), 4, 4, + scoped_ptr<AnimationCurve>(new FakeTransformTransition(2.0)), 4, 4, Animation::TRANSFORM)); controller->AddAnimation(Animation::Create( - scoped_ptr<AnimationCurve>(new FakeFloatTransition(1.0, 0.f, 1.f)).Pass(), - 5, 5, Animation::OPACITY)); + scoped_ptr<AnimationCurve>(new FakeFloatTransition(1.0, 0.f, 1.f)), 5, 5, + Animation::OPACITY)); controller->Animate(kInitialTickTime); controller->UpdateState(true, nullptr); @@ -1872,14 +1865,14 @@ // Add two animations with the same group id but different durations. scoped_ptr<Animation> first_animation(Animation::Create( - scoped_ptr<AnimationCurve>(new FakeTransformTransition(2.0)).Pass(), 1, - group_id, Animation::TRANSFORM)); + scoped_ptr<AnimationCurve>(new FakeTransformTransition(2.0)), 1, group_id, + Animation::TRANSFORM)); first_animation->set_is_controlling_instance_for_test(true); controller_impl->AddAnimation(std::move(first_animation)); scoped_ptr<Animation> second_animation(Animation::Create( - scoped_ptr<AnimationCurve>(new FakeFloatTransition(1.0, 0.f, 1.f)).Pass(), - 2, group_id, Animation::OPACITY)); + scoped_ptr<AnimationCurve>(new FakeFloatTransition(1.0, 0.f, 1.f)), 2, + group_id, Animation::OPACITY)); second_animation->set_is_controlling_instance_for_test(true); controller_impl->AddAnimation(std::move(second_animation)); @@ -1927,14 +1920,14 @@ // Add two animations with the same group id. scoped_ptr<Animation> first_animation(CreateAnimation( - scoped_ptr<AnimationCurve>(new FakeTransformTransition(1.0)).Pass(), 1, + scoped_ptr<AnimationCurve>(new FakeTransformTransition(1.0)), 1, Animation::TRANSFORM)); first_animation->set_is_controlling_instance_for_test(true); controller_impl->AddAnimation(std::move(first_animation)); scoped_ptr<Animation> second_animation(CreateAnimation( - scoped_ptr<AnimationCurve>(new FakeFloatTransition(1.0, 0.f, 1.f)).Pass(), - 1, Animation::OPACITY)); + scoped_ptr<AnimationCurve>(new FakeFloatTransition(1.0, 0.f, 1.f)), 1, + Animation::OPACITY)); second_animation->set_is_controlling_instance_for_test(true); controller_impl->AddAnimation(std::move(second_animation)); @@ -1969,8 +1962,8 @@ EXPECT_FALSE(controller_impl->HasAnimationThatAffectsScale()); controller_impl->AddAnimation(CreateAnimation( - scoped_ptr<AnimationCurve>(new FakeFloatTransition(1.0, 0.f, 1.f)).Pass(), - 1, Animation::OPACITY)); + scoped_ptr<AnimationCurve>(new FakeFloatTransition(1.0, 0.f, 1.f)), 1, + Animation::OPACITY)); // Opacity animations don't affect scale. EXPECT_FALSE(controller_impl->HasAnimationThatAffectsScale()); @@ -2025,8 +2018,8 @@ LayerAnimationController::ObserverType::PENDING)); controller_impl->AddAnimation(CreateAnimation( - scoped_ptr<AnimationCurve>(new FakeFloatTransition(1.0, 0.f, 1.f)).Pass(), - 1, Animation::OPACITY)); + scoped_ptr<AnimationCurve>(new FakeFloatTransition(1.0, 0.f, 1.f)), 1, + Animation::OPACITY)); // Opacity animations aren't non-translation transforms. EXPECT_TRUE(controller_impl->HasOnlyTranslationTransforms( @@ -2815,8 +2808,8 @@ // Create an animation that initially affects only pending observers. scoped_ptr<Animation> animation(CreateAnimation( - scoped_ptr<AnimationCurve>(new FakeFloatTransition(1.0, 0.f, 1.f)).Pass(), - 1, Animation::OPACITY)); + scoped_ptr<AnimationCurve>(new FakeFloatTransition(1.0, 0.f, 1.f)), 1, + Animation::OPACITY)); animation->set_affects_active_observers(false); controller->AddAnimation(std::move(animation)); @@ -2887,8 +2880,8 @@ // Create an animation that initially affects only pending observers, and has // a start delay of 2 seconds. scoped_ptr<Animation> animation(CreateAnimation( - scoped_ptr<AnimationCurve>(new FakeFloatTransition(1.0, 0.f, 1.f)).Pass(), - 1, Animation::OPACITY)); + scoped_ptr<AnimationCurve>(new FakeFloatTransition(1.0, 0.f, 1.f)), 1, + Animation::OPACITY)); animation->set_fill_mode(Animation::FILL_MODE_NONE); animation->set_time_offset(TimeDelta::FromMilliseconds(-2000)); animation->set_affects_active_observers(false);
diff --git a/cc/animation/scroll_offset_animation_curve_unittest.cc b/cc/animation/scroll_offset_animation_curve_unittest.cc index fd34db0..4638ecf 100644 --- a/cc/animation/scroll_offset_animation_curve_unittest.cc +++ b/cc/animation/scroll_offset_animation_curve_unittest.cc
@@ -15,9 +15,8 @@ TEST(ScrollOffsetAnimationCurveTest, Duration) { gfx::ScrollOffset target_value(100.f, 200.f); scoped_ptr<ScrollOffsetAnimationCurve> curve( - ScrollOffsetAnimationCurve::Create( - target_value, - EaseInOutTimingFunction::Create().Pass())); + ScrollOffsetAnimationCurve::Create(target_value, + EaseInOutTimingFunction::Create())); curve->SetInitialValue(target_value); EXPECT_DOUBLE_EQ(0.0, curve->Duration().InSecondsF()); @@ -59,9 +58,8 @@ gfx::ScrollOffset initial_value(2.f, 40.f); gfx::ScrollOffset target_value(10.f, 20.f); scoped_ptr<ScrollOffsetAnimationCurve> curve( - ScrollOffsetAnimationCurve::Create( - target_value, - EaseInOutTimingFunction::Create().Pass())); + ScrollOffsetAnimationCurve::Create(target_value, + EaseInOutTimingFunction::Create())); curve->SetInitialValue(initial_value); base::TimeDelta duration = curve->Duration(); @@ -93,13 +91,12 @@ gfx::ScrollOffset initial_value(2.f, 40.f); gfx::ScrollOffset target_value(10.f, 20.f); scoped_ptr<ScrollOffsetAnimationCurve> curve( - ScrollOffsetAnimationCurve::Create( - target_value, - EaseInOutTimingFunction::Create().Pass())); + ScrollOffsetAnimationCurve::Create(target_value, + EaseInOutTimingFunction::Create())); curve->SetInitialValue(initial_value); base::TimeDelta duration = curve->Duration(); - scoped_ptr<AnimationCurve> clone(curve->Clone().Pass()); + scoped_ptr<AnimationCurve> clone(curve->Clone()); EXPECT_EQ(AnimationCurve::SCROLL_OFFSET, clone->Type()); EXPECT_EQ(duration, clone->Duration()); @@ -131,8 +128,8 @@ gfx::ScrollOffset initial_value(0.f, 0.f); gfx::ScrollOffset target_value(0.f, 3600.f); scoped_ptr<ScrollOffsetAnimationCurve> curve( - ScrollOffsetAnimationCurve::Create( - target_value, EaseInOutTimingFunction::Create().Pass())); + ScrollOffsetAnimationCurve::Create(target_value, + EaseInOutTimingFunction::Create())); curve->SetInitialValue(initial_value); EXPECT_EQ(1.0, curve->Duration().InSecondsF()); EXPECT_EQ(1800.0, curve->GetValue(base::TimeDelta::FromSecondsD(0.5)).y()); @@ -158,8 +155,8 @@ gfx::ScrollOffset initial_value(0.f, 0.f); gfx::ScrollOffset target_value(0.f, 900.f); scoped_ptr<ScrollOffsetAnimationCurve> curve( - ScrollOffsetAnimationCurve::Create( - target_value, EaseInOutTimingFunction::Create().Pass())); + ScrollOffsetAnimationCurve::Create(target_value, + EaseInOutTimingFunction::Create())); curve->SetInitialValue(initial_value); EXPECT_EQ(0.5, curve->Duration().InSecondsF()); @@ -182,7 +179,7 @@ gfx::ScrollOffset target_value(0.f, 3600.f); scoped_ptr<ScrollOffsetAnimationCurve> curve( ScrollOffsetAnimationCurve::Create( - target_value, EaseInOutTimingFunction::Create().Pass(), + target_value, EaseInOutTimingFunction::Create(), ScrollOffsetAnimationCurve::DurationBehavior::CONSTANT)); curve->SetInitialValue(initial_value); EXPECT_EQ(0.2, curve->Duration().InSecondsF());
diff --git a/cc/base/container_util.h b/cc/base/container_util.h index 2f0da6c..65a9d31 100644 --- a/cc/base/container_util.h +++ b/cc/base/container_util.h
@@ -9,22 +9,18 @@ namespace cc { -// Removes the front element from the container and returns it. Note that this -// currently only works with types that implement Pass(). -// TODO(vmpstr): Use std::move instead of Pass when allowed. +// Removes the front element from the container and returns it. template <typename Container> typename Container::value_type PopFront(Container* container) { - typename Container::value_type element = container->front().Pass(); + typename Container::value_type element = std::move(container->front()); container->pop_front(); return element; } -// Removes the back element from the container and returns it. Note that this -// currently only works with types that implement Pass(). -// TODO(vmpstr): Use std::move instead of Pass when allowed. +// Removes the back element from the container and returns it. template <typename Container> typename Container::value_type PopBack(Container* container) { - typename Container::value_type element = container->back().Pass(); + typename Container::value_type element = std::move(container->back()); container->pop_back(); return element; }
diff --git a/cc/blink/BUILD.gn b/cc/blink/BUILD.gn index 4ee8862..a501f5e 100644 --- a/cc/blink/BUILD.gn +++ b/cc/blink/BUILD.gn
@@ -90,13 +90,13 @@ ":blink", "//base/test:test_support", "//base/third_party/dynamic_annotations", + "//cc", + "//cc:test_support", "//skia", "//testing/gtest", "//third_party/WebKit/public:blink", - "//ui/gfx/geometry", "//ui/gfx:test_support", - "//cc", - "//cc:test_support", + "//ui/gfx/geometry", ] } }
diff --git a/cc/blink/web_filter_animation_curve_impl.cc b/cc/blink/web_filter_animation_curve_impl.cc index 79ffdfa..3733dab 100644 --- a/cc/blink/web_filter_animation_curve_impl.cc +++ b/cc/blink/web_filter_animation_curve_impl.cc
@@ -74,14 +74,14 @@ double x2, double y2) { curve_->SetTimingFunction( - cc::CubicBezierTimingFunction::Create(x1, y1, x2, y2).Pass()); + cc::CubicBezierTimingFunction::Create(x1, y1, x2, y2)); } void WebFilterAnimationCurveImpl::setStepsTimingFunction( int number_of_steps, float steps_start_offset) { - curve_->SetTimingFunction(cc::StepsTimingFunction::Create( - number_of_steps, steps_start_offset).Pass()); + curve_->SetTimingFunction( + cc::StepsTimingFunction::Create(number_of_steps, steps_start_offset)); } scoped_ptr<cc::AnimationCurve>
diff --git a/cc/blink/web_float_animation_curve_impl.cc b/cc/blink/web_float_animation_curve_impl.cc index 4340ae8..ae57858a 100644 --- a/cc/blink/web_float_animation_curve_impl.cc +++ b/cc/blink/web_float_animation_curve_impl.cc
@@ -68,14 +68,14 @@ double x2, double y2) { curve_->SetTimingFunction( - cc::CubicBezierTimingFunction::Create(x1, y1, x2, y2).Pass()); + cc::CubicBezierTimingFunction::Create(x1, y1, x2, y2)); } void WebFloatAnimationCurveImpl::setStepsTimingFunction( int number_of_steps, float steps_start_offset) { - curve_->SetTimingFunction(cc::StepsTimingFunction::Create( - number_of_steps, steps_start_offset).Pass()); + curve_->SetTimingFunction( + cc::StepsTimingFunction::Create(number_of_steps, steps_start_offset)); } float WebFloatAnimationCurveImpl::getValue(double time) const {
diff --git a/cc/blink/web_scrollbar_layer_impl.cc b/cc/blink/web_scrollbar_layer_impl.cc index 8248149..f96cf89f 100644 --- a/cc/blink/web_scrollbar_layer_impl.cc +++ b/cc/blink/web_scrollbar_layer_impl.cc
@@ -35,9 +35,8 @@ scoped_ptr<cc::Scrollbar>( new ScrollbarImpl(make_scoped_ptr(scrollbar), painter, - make_scoped_ptr(geometry))).Pass(), - 0))) { -} + make_scoped_ptr(geometry))), + 0))) {} WebScrollbarLayerImpl::WebScrollbarLayerImpl( blink::WebScrollbar::Orientation orientation,
diff --git a/cc/blink/web_transform_animation_curve_impl.cc b/cc/blink/web_transform_animation_curve_impl.cc index 4dafd10..9b67184 100644 --- a/cc/blink/web_transform_animation_curve_impl.cc +++ b/cc/blink/web_transform_animation_curve_impl.cc
@@ -78,14 +78,14 @@ double x2, double y2) { curve_->SetTimingFunction( - cc::CubicBezierTimingFunction::Create(x1, y1, x2, y2).Pass()); + cc::CubicBezierTimingFunction::Create(x1, y1, x2, y2)); } void WebTransformAnimationCurveImpl::setStepsTimingFunction( int number_of_steps, float steps_start_offset) { - curve_->SetTimingFunction(cc::StepsTimingFunction::Create( - number_of_steps, steps_start_offset).Pass()); + curve_->SetTimingFunction( + cc::StepsTimingFunction::Create(number_of_steps, steps_start_offset)); } scoped_ptr<cc::AnimationCurve>
diff --git a/cc/cc.gyp b/cc/cc.gyp index 709bfc1e..cf12888 100644 --- a/cc/cc.gyp +++ b/cc/cc.gyp
@@ -588,16 +588,20 @@ 'proto/compositor_message.proto', 'proto/display_item.proto', 'proto/layer.proto', + 'proto/layer_position_constraint.proto', 'proto/point.proto', + 'proto/point3f.proto', 'proto/pointf.proto', 'proto/rect.proto', 'proto/rectf.proto', + 'proto/scroll_offset.proto', 'proto/size.proto', 'proto/sizef.proto', 'proto/skregion.proto', 'proto/skrrect.proto', 'proto/skxfermode.proto', 'proto/transform.proto', + 'proto/vector2df.proto', ], 'defines': [ 'CC_PROTO_IMPLEMENTATION=1',
diff --git a/cc/layers/layer_position_constraint.cc b/cc/layers/layer_position_constraint.cc index 183b6b5..5d8824e24 100644 --- a/cc/layers/layer_position_constraint.cc +++ b/cc/layers/layer_position_constraint.cc
@@ -3,6 +3,7 @@ // found in the LICENSE file. #include "cc/layers/layer_position_constraint.h" +#include "cc/proto/layer_position_constraint.pb.h" namespace cc { @@ -12,6 +13,20 @@ is_fixed_to_bottom_edge_(false) { } +void LayerPositionConstraint::ToProtobuf( + proto::LayerPositionConstraint* proto) const { + proto->set_is_fixed_position(is_fixed_position_); + proto->set_is_fixed_to_right_edge(is_fixed_to_right_edge_); + proto->set_is_fixed_to_bottom_edge(is_fixed_to_bottom_edge_); +} + +void LayerPositionConstraint::FromProtobuf( + const proto::LayerPositionConstraint& proto) { + is_fixed_position_ = proto.is_fixed_position(); + is_fixed_to_right_edge_ = proto.is_fixed_to_right_edge(); + is_fixed_to_bottom_edge_ = proto.is_fixed_to_bottom_edge(); +} + bool LayerPositionConstraint::operator==( const LayerPositionConstraint& other) const { if (!is_fixed_position_ && !other.is_fixed_position_)
diff --git a/cc/layers/layer_position_constraint.h b/cc/layers/layer_position_constraint.h index 9a575137..1ee4bc72 100644 --- a/cc/layers/layer_position_constraint.h +++ b/cc/layers/layer_position_constraint.h
@@ -9,6 +9,10 @@ namespace cc { +namespace proto { +class LayerPositionConstraint; +} + class CC_EXPORT LayerPositionConstraint { public: LayerPositionConstraint(); @@ -24,6 +28,9 @@ } bool is_fixed_to_bottom_edge() const { return is_fixed_to_bottom_edge_; } + void ToProtobuf(proto::LayerPositionConstraint* proto) const; + void FromProtobuf(const proto::LayerPositionConstraint& proto); + bool operator==(const LayerPositionConstraint&) const; bool operator!=(const LayerPositionConstraint&) const;
diff --git a/cc/layers/layer_position_constraint_unittest.cc b/cc/layers/layer_position_constraint_unittest.cc index 5d61c01a..c137203 100644 --- a/cc/layers/layer_position_constraint_unittest.cc +++ b/cc/layers/layer_position_constraint_unittest.cc
@@ -9,6 +9,7 @@ #include "cc/layers/layer.h" #include "cc/layers/layer_impl.h" #include "cc/layers/layer_settings.h" +#include "cc/proto/layer_position_constraint.pb.h" #include "cc/test/fake_layer_tree_host.h" #include "cc/test/fake_proxy.h" #include "cc/test/geometry_test_utils.h" @@ -1131,5 +1132,31 @@ fixed_child_impl->draw_transform()); } +void VerifySerializeAndDeserializeProto(bool is_fixed_position, + bool is_fixed_to_right_edge, + bool is_fixed_to_bottom_edge) { + LayerPositionConstraint constraint; + constraint.set_is_fixed_position(is_fixed_position); + constraint.set_is_fixed_to_right_edge(is_fixed_to_right_edge); + constraint.set_is_fixed_to_bottom_edge(is_fixed_to_bottom_edge); + proto::LayerPositionConstraint proto; + constraint.ToProtobuf(&proto); + + LayerPositionConstraint constraint2; + constraint2.FromProtobuf(proto); + EXPECT_EQ(constraint, constraint2); +} + +TEST(LayerPositionConstraintSerializationTest, SerializeAndDeserializeProto) { + VerifySerializeAndDeserializeProto(true, true, true); + VerifySerializeAndDeserializeProto(true, true, false); + VerifySerializeAndDeserializeProto(true, false, true); + VerifySerializeAndDeserializeProto(true, false, false); + VerifySerializeAndDeserializeProto(false, true, true); + VerifySerializeAndDeserializeProto(false, true, false); + VerifySerializeAndDeserializeProto(false, false, true); + VerifySerializeAndDeserializeProto(false, false, false); +} + } // namespace } // namespace cc
diff --git a/cc/layers/surface_layer_impl.cc b/cc/layers/surface_layer_impl.cc index 546af40..e0dcadf0 100644 --- a/cc/layers/surface_layer_impl.cc +++ b/cc/layers/surface_layer_impl.cc
@@ -8,15 +8,19 @@ #include "cc/debug/debug_colors.h" #include "cc/quads/solid_color_draw_quad.h" #include "cc/quads/surface_draw_quad.h" +#include "cc/trees/layer_tree_impl.h" #include "cc/trees/occlusion.h" namespace cc { SurfaceLayerImpl::SurfaceLayerImpl(LayerTreeImpl* tree_impl, int id) : LayerImpl(tree_impl, id), surface_scale_(0.f) { + layer_tree_impl()->AddSurfaceLayer(this); } -SurfaceLayerImpl::~SurfaceLayerImpl() {} +SurfaceLayerImpl::~SurfaceLayerImpl() { + layer_tree_impl()->RemoveSurfaceLayer(this); +} scoped_ptr<LayerImpl> SurfaceLayerImpl::CreateLayerImpl( LayerTreeImpl* tree_impl) { @@ -76,7 +80,6 @@ SurfaceDrawQuad* quad = render_pass->CreateAndAppendDrawQuad<SurfaceDrawQuad>(); quad->SetNew(shared_quad_state, quad_rect, visible_quad_rect, surface_id_); - render_pass->referenced_surfaces.push_back(surface_id_); } void SurfaceLayerImpl::GetDebugBorderProperties(SkColor* color,
diff --git a/cc/layers/surface_layer_impl.h b/cc/layers/surface_layer_impl.h index 2bf6a9a0..4d2c48b4 100644 --- a/cc/layers/surface_layer_impl.h +++ b/cc/layers/surface_layer_impl.h
@@ -22,6 +22,7 @@ void SetSurfaceId(SurfaceId surface_id); void SetSurfaceScale(float scale); void SetSurfaceSize(const gfx::Size& size); + SurfaceId surface_id() const { return surface_id_; } // LayerImpl overrides. scoped_ptr<LayerImpl> CreateLayerImpl(LayerTreeImpl* tree_impl) override;
diff --git a/cc/layers/texture_layer_unittest.cc b/cc/layers/texture_layer_unittest.cc index 84ee9d2a..7c982c81 100644 --- a/cc/layers/texture_layer_unittest.cc +++ b/cc/layers/texture_layer_unittest.cc
@@ -368,7 +368,7 @@ void CreateMainRef() { main_ref_ = TestMailboxHolder::Create( test_data_.mailbox1_, - SingleReleaseCallback::Create(test_data_.release_mailbox1_)).Pass(); + SingleReleaseCallback::Create(test_data_.release_mailbox1_)); } void ReleaseMainRef() { main_ref_ = nullptr; }
diff --git a/cc/output/compositor_frame_metadata.h b/cc/output/compositor_frame_metadata.h index 72035e3..392c6b0d 100644 --- a/cc/output/compositor_frame_metadata.h +++ b/cc/output/compositor_frame_metadata.h
@@ -9,6 +9,7 @@ #include "cc/base/cc_export.h" #include "cc/output/viewport_selection_bound.h" +#include "cc/surfaces/surface_id.h" #include "third_party/skia/include/core/SkColor.h" #include "ui/events/latency_info.h" #include "ui/gfx/geometry/size_f.h" @@ -57,6 +58,9 @@ // A set of SurfaceSequences that this frame satisfies (always in the same // namespace as the current Surface). std::vector<uint32_t> satisfies_sequences; + + // This is the set of Surfaces that are referenced by this frame. + std::vector<SurfaceId> referenced_surfaces; }; } // namespace cc
diff --git a/cc/output/copy_output_request.cc b/cc/output/copy_output_request.cc index 7077457..0018edd 100644 --- a/cc/output/copy_output_request.cc +++ b/cc/output/copy_output_request.cc
@@ -47,7 +47,7 @@ CopyOutputRequest::~CopyOutputRequest() { if (!result_callback_.is_null()) - SendResult(CopyOutputResult::CreateEmptyResult().Pass()); + SendResult(CopyOutputResult::CreateEmptyResult()); } void CopyOutputRequest::SendResult(scoped_ptr<CopyOutputResult> result) { @@ -57,11 +57,11 @@ } void CopyOutputRequest::SendEmptyResult() { - SendResult(CopyOutputResult::CreateEmptyResult().Pass()); + SendResult(CopyOutputResult::CreateEmptyResult()); } void CopyOutputRequest::SendBitmapResult(scoped_ptr<SkBitmap> bitmap) { - SendResult(CopyOutputResult::CreateBitmapResult(std::move(bitmap)).Pass()); + SendResult(CopyOutputResult::CreateBitmapResult(std::move(bitmap))); } void CopyOutputRequest::SendTextureResult(
diff --git a/cc/output/gl_renderer_unittest.cc b/cc/output/gl_renderer_unittest.cc index d90e3e8..f50653ec 100644 --- a/cc/output/gl_renderer_unittest.cc +++ b/cc/output/gl_renderer_unittest.cc
@@ -338,7 +338,7 @@ protected: GLRendererWithDefaultHarnessTest() { output_surface_ = - FakeOutputSurface::Create3d(TestWebGraphicsContext3D::Create()).Pass(); + FakeOutputSurface::Create3d(TestWebGraphicsContext3D::Create()); CHECK(output_surface_->BindToClient(&output_surface_client_)); shared_bitmap_manager_.reset(new TestSharedBitmapManager()); @@ -369,7 +369,7 @@ class GLRendererShaderTest : public GLRendererTest { protected: GLRendererShaderTest() { - output_surface_ = FakeOutputSurface::Create3d().Pass(); + output_surface_ = FakeOutputSurface::Create3d(); CHECK(output_surface_->BindToClient(&output_surface_client_)); shared_bitmap_manager_.reset(new TestSharedBitmapManager()); @@ -1426,7 +1426,7 @@ // has finished. FakeOutputSurfaceClient output_surface_client; scoped_ptr<FakeOutputSurface> output_surface( - FakeOutputSurface::Create3d(TestWebGraphicsContext3D::Create().Pass())); + FakeOutputSurface::Create3d(TestWebGraphicsContext3D::Create())); CHECK(output_surface->BindToClient(&output_surface_client)); scoped_ptr<SharedBitmapManager> shared_bitmap_manager(
diff --git a/cc/output/texture_mailbox_deleter_unittest.cc b/cc/output/texture_mailbox_deleter_unittest.cc index 84e7d46..d17e9c36 100644 --- a/cc/output/texture_mailbox_deleter_unittest.cc +++ b/cc/output/texture_mailbox_deleter_unittest.cc
@@ -29,7 +29,7 @@ EXPECT_EQ(1u, context_provider->TestContext3d()->NumTextures()); scoped_ptr<SingleReleaseCallback> cb = - deleter->GetReleaseCallback(context_provider, texture_id).Pass(); + deleter->GetReleaseCallback(context_provider, texture_id); EXPECT_FALSE(context_provider->HasOneRef()); EXPECT_EQ(1u, context_provider->TestContext3d()->NumTextures());
diff --git a/cc/proto/BUILD.gn b/cc/proto/BUILD.gn index 2465cfa5..33e3e58 100644 --- a/cc/proto/BUILD.gn +++ b/cc/proto/BUILD.gn
@@ -32,16 +32,20 @@ "compositor_message.proto", "display_item.proto", "layer.proto", + "layer_position_constraint.proto", "point.proto", + "point3f.proto", "pointf.proto", "rect.proto", "rectf.proto", + "scroll_offset.proto", "size.proto", "sizef.proto", "skregion.proto", "skrrect.proto", "skxfermode.proto", "transform.proto", + "vector2df.proto", ] deps = [
diff --git a/cc/proto/gfx_conversions.cc b/cc/proto/gfx_conversions.cc index cf85fbf..8dac00c 100644 --- a/cc/proto/gfx_conversions.cc +++ b/cc/proto/gfx_conversions.cc
@@ -5,16 +5,21 @@ #include "cc/proto/gfx_conversions.h" #include "cc/proto/point.pb.h" +#include "cc/proto/point3f.pb.h" #include "cc/proto/pointf.pb.h" #include "cc/proto/rect.pb.h" #include "cc/proto/rectf.pb.h" +#include "cc/proto/scroll_offset.pb.h" #include "cc/proto/size.pb.h" #include "cc/proto/sizef.pb.h" #include "cc/proto/transform.pb.h" +#include "cc/proto/vector2df.pb.h" #include "ui/gfx/geometry/point.h" +#include "ui/gfx/geometry/point3_f.h" #include "ui/gfx/geometry/point_f.h" #include "ui/gfx/geometry/rect.h" #include "ui/gfx/geometry/rect_f.h" +#include "ui/gfx/geometry/scroll_offset.h" #include "ui/gfx/geometry/size.h" #include "ui/gfx/geometry/size_f.h" #include "ui/gfx/transform.h" @@ -39,6 +44,16 @@ return gfx::PointF(proto.x(), proto.y()); } +void Point3FToProto(const gfx::Point3F& point, proto::Point3F* proto) { + proto->set_x(point.x()); + proto->set_y(point.y()); + proto->set_z(point.z()); +} + +gfx::Point3F ProtoToPoint3F(const proto::Point3F& proto) { + return gfx::Point3F(proto.x(), proto.y(), proto.z()); +} + void RectToProto(const gfx::Rect& rect, proto::Rect* proto) { proto->mutable_origin()->set_x(rect.x()); proto->mutable_origin()->set_y(rect.y()); @@ -91,7 +106,9 @@ } gfx::Transform ProtoToTransform(const proto::Transform& proto) { - gfx::Transform transform; + if (proto.matrix_size() == 0) + return gfx::Transform(); + gfx::Transform transform(gfx::Transform::kSkipInitialization); DCHECK_EQ(16, proto.matrix_size()); for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { @@ -101,4 +118,23 @@ return transform; } +void Vector2dFToProto(const gfx::Vector2dF& vector, proto::Vector2dF* proto) { + proto->set_x(vector.x()); + proto->set_y(vector.y()); +} + +gfx::Vector2dF ProtoToVector2dF(const proto::Vector2dF& proto) { + return gfx::Vector2dF(proto.x(), proto.y()); +} + +void ScrollOffsetToProto(const gfx::ScrollOffset& scroll_offset, + proto::ScrollOffset* proto) { + proto->set_x(scroll_offset.x()); + proto->set_y(scroll_offset.y()); +} + +gfx::ScrollOffset ProtoToScrollOffset(const proto::ScrollOffset& proto) { + return gfx::ScrollOffset(proto.x(), proto.y()); +} + } // namespace cc
diff --git a/cc/proto/gfx_conversions.h b/cc/proto/gfx_conversions.h index 5b5c315..b5caa3a3 100644 --- a/cc/proto/gfx_conversions.h +++ b/cc/proto/gfx_conversions.h
@@ -9,31 +9,40 @@ namespace gfx { class Point; +class Point3F; class PointF; class Rect; class RectF; +class ScrollOffset; class Size; class SizeF; class Transform; -} +class Vector2dF; +} // namespace gfx namespace cc { namespace proto { class Point; +class Point3F; class PointF; class Rect; class RectF; +class ScrollOffset; class Size; class SizeF; class Transform; -} +class Vector2dF; +} // namespace proto // TODO(dtrainor): Move these to a class and make them static // (crbug.com/548432). CC_EXPORT void PointToProto(const gfx::Point& point, proto::Point* proto); CC_EXPORT gfx::Point ProtoToPoint(const proto::Point& proto); +CC_EXPORT void Point3FToProto(const gfx::Point3F& point, proto::Point3F* proto); +CC_EXPORT gfx::Point3F ProtoToPoint3F(const proto::Point3F& proto); + CC_EXPORT void PointFToProto(const gfx::PointF& point, proto::PointF* proto); CC_EXPORT gfx::PointF ProtoToPointF(const proto::PointF& proto); @@ -53,6 +62,15 @@ proto::Transform* proto); CC_EXPORT gfx::Transform ProtoToTransform(const proto::Transform& proto); +CC_EXPORT void Vector2dFToProto(const gfx::Vector2dF& vector, + proto::Vector2dF* proto); +CC_EXPORT gfx::Vector2dF ProtoToVector2dF(const proto::Vector2dF& proto); + +CC_EXPORT void ScrollOffsetToProto(const gfx::ScrollOffset& scroll_offset, + proto::ScrollOffset* proto); +CC_EXPORT gfx::ScrollOffset ProtoToScrollOffset( + const proto::ScrollOffset& proto); + } // namespace cc #endif // CC_PROTO_GFX_CONVERSIONS_H_
diff --git a/cc/proto/gfx_conversions_unittest.cc b/cc/proto/gfx_conversions_unittest.cc index 6ffdb96..6affc1c 100644 --- a/cc/proto/gfx_conversions_unittest.cc +++ b/cc/proto/gfx_conversions_unittest.cc
@@ -5,19 +5,25 @@ #include "cc/proto/gfx_conversions.h" #include "cc/proto/point.pb.h" +#include "cc/proto/point3f.pb.h" #include "cc/proto/pointf.pb.h" #include "cc/proto/rect.pb.h" #include "cc/proto/rectf.pb.h" +#include "cc/proto/scroll_offset.pb.h" #include "cc/proto/size.pb.h" #include "cc/proto/sizef.pb.h" #include "cc/proto/transform.pb.h" +#include "cc/proto/vector2df.pb.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/gfx/geometry/point.h" +#include "ui/gfx/geometry/point3_f.h" #include "ui/gfx/geometry/point_f.h" #include "ui/gfx/geometry/rect.h" #include "ui/gfx/geometry/rect_f.h" +#include "ui/gfx/geometry/scroll_offset.h" #include "ui/gfx/geometry/size.h" #include "ui/gfx/geometry/size_f.h" +#include "ui/gfx/geometry/vector2d_f.h" #include "ui/gfx/transform.h" namespace cc { @@ -87,6 +93,20 @@ EXPECT_EQ(point, ProtoToPointF(proto)); } +TEST(GfxProtoConversionsTest, SerializeDeserializePoint3F) { + const gfx::Point3F point(5.1f, 10.2f, 13.4f); + + // Test PointFToProto + proto::Point3F proto; + Point3FToProto(point, &proto); + EXPECT_EQ(point.x(), proto.x()); + EXPECT_EQ(point.y(), proto.y()); + EXPECT_EQ(point.z(), proto.z()); + + // Test ProtoToPoint3F + EXPECT_EQ(point, ProtoToPoint3F(proto)); +} + TEST(GfxProtoConversionsTest, SerializeDeserializeSize) { const gfx::Size size(5, 10); @@ -173,5 +193,31 @@ EXPECT_EQ(transform, ProtoToTransform(proto)); } +TEST(GfxProtoConversionsTest, SerializeDeserializeVector2dF) { + const gfx::Vector2dF vector(5.1f, 10.2f); + + // Test Vector2dFToProto + proto::Vector2dF proto; + Vector2dFToProto(vector, &proto); + EXPECT_EQ(vector.x(), proto.x()); + EXPECT_EQ(vector.y(), proto.y()); + + // Test ProtoToVector2dF + EXPECT_EQ(vector, ProtoToVector2dF(proto)); +} + +TEST(GfxProtoConversionsTest, SerializeDeserializeScrollOffset) { + const gfx::ScrollOffset scroll_offset(5.1f, 10.2f); + + // Test ScrollOffsetToProto + proto::ScrollOffset proto; + ScrollOffsetToProto(scroll_offset, &proto); + EXPECT_EQ(scroll_offset.x(), proto.x()); + EXPECT_EQ(scroll_offset.y(), proto.y()); + + // Test ProtoToScrollOffset + EXPECT_EQ(scroll_offset, ProtoToScrollOffset(proto)); +} + } // namespace } // namespace cc
diff --git a/cc/proto/layer_position_constraint.proto b/cc/proto/layer_position_constraint.proto new file mode 100644 index 0000000..f84ebf08 --- /dev/null +++ b/cc/proto/layer_position_constraint.proto
@@ -0,0 +1,15 @@ +// Copyright 2015 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. + +syntax = "proto2"; + +option optimize_for = LITE_RUNTIME; + +package cc.proto; + +message LayerPositionConstraint { + optional bool is_fixed_position = 1; + optional bool is_fixed_to_right_edge = 2; + optional bool is_fixed_to_bottom_edge = 3; +};
diff --git a/cc/proto/point3f.proto b/cc/proto/point3f.proto new file mode 100644 index 0000000..89b0235d --- /dev/null +++ b/cc/proto/point3f.proto
@@ -0,0 +1,15 @@ +// Copyright 2015 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. + +syntax = "proto2"; + +option optimize_for = LITE_RUNTIME; + +package cc.proto; + +message Point3F { + optional float x = 1; + optional float y = 2; + optional float z = 3; +}
diff --git a/cc/proto/scroll_offset.proto b/cc/proto/scroll_offset.proto new file mode 100644 index 0000000..b89b181 --- /dev/null +++ b/cc/proto/scroll_offset.proto
@@ -0,0 +1,14 @@ +// Copyright 2015 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. + +syntax = "proto2"; + +option optimize_for = LITE_RUNTIME; + +package cc.proto; + +message ScrollOffset { + optional double x = 1; + optional double y = 2; +}
diff --git a/cc/proto/vector2df.proto b/cc/proto/vector2df.proto new file mode 100644 index 0000000..1651b074 --- /dev/null +++ b/cc/proto/vector2df.proto
@@ -0,0 +1,14 @@ +// Copyright 2015 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. + +syntax = "proto2"; + +option optimize_for = LITE_RUNTIME; + +package cc.proto; + +message Vector2dF { + optional float x = 1; + optional float y = 2; +}
diff --git a/cc/quads/render_pass.h b/cc/quads/render_pass.h index bc64d74..e6cc67a6 100644 --- a/cc/quads/render_pass.h +++ b/cc/quads/render_pass.h
@@ -117,10 +117,6 @@ QuadList quad_list; SharedQuadStateList shared_quad_state_list; - // This vector contains the complete set of SurfaceIds referenced by - // DrawQuads in quad_list. - std::vector<SurfaceId> referenced_surfaces; - protected: explicit RenderPass(size_t num_layers); RenderPass();
diff --git a/cc/quads/render_pass_id.h b/cc/quads/render_pass_id.h index 9c36f32..f6ab9ce 100644 --- a/cc/quads/render_pass_id.h +++ b/cc/quads/render_pass_id.h
@@ -5,6 +5,8 @@ #ifndef CC_QUADS_RENDER_PASS_ID_H_ #define CC_QUADS_RENDER_PASS_ID_H_ +#include <tuple> + #include "base/basictypes.h" #include "base/containers/hash_tables.h" #include "cc/base/cc_export.h" @@ -27,8 +29,7 @@ } bool operator!=(const RenderPassId& other) const { return !(*this == other); } bool operator<(const RenderPassId& other) const { - return layer_id < other.layer_id || - (layer_id == other.layer_id && index < other.index); + return std::tie(layer_id, index) < std::tie(other.layer_id, other.index); } };
diff --git a/cc/quads/render_pass_unittest.cc b/cc/quads/render_pass_unittest.cc index f00c006..140b7e1 100644 --- a/cc/quads/render_pass_unittest.cc +++ b/cc/quads/render_pass_unittest.cc
@@ -26,7 +26,6 @@ gfx::Rect output_rect; gfx::Rect damage_rect; bool has_transparent_background; - std::vector<SurfaceId> referenced_surfaces; std::vector<scoped_ptr<CopyOutputRequest>> copy_callbacks; }; @@ -48,7 +47,6 @@ EXPECT_EQ(expected->shared_quad_state_list.size(), actual->shared_quad_state_list.size()); EXPECT_EQ(expected->quad_list.size(), actual->quad_list.size()); - EXPECT_EQ(expected->referenced_surfaces, actual->referenced_surfaces); for (auto exp_iter = expected->quad_list.cbegin(), act_iter = actual->quad_list.cbegin(); @@ -102,7 +100,6 @@ EXPECT_EQ(pass->damage_rect, copy->damage_rect); EXPECT_EQ(pass->has_transparent_background, copy->has_transparent_background); EXPECT_EQ(0u, copy->quad_list.size()); - EXPECT_EQ(0u, copy->referenced_surfaces.size()); // The copy request should not be copied/duplicated. EXPECT_EQ(1u, pass->copy_requests.size());
diff --git a/cc/raster/tile_task_worker_pool.cc b/cc/raster/tile_task_worker_pool.cc index 34c84cb..e1e6ac3 100644 --- a/cc/raster/tile_task_worker_pool.cc +++ b/cc/raster/tile_task_worker_pool.cc
@@ -225,13 +225,8 @@ SkImageInfo dst_info = SkImageInfo::Make(info.width(), info.height(), buffer_color_type, info.alphaType(), info.profileType()); - // TODO(kaanb): The GL pipeline assumes a 4-byte alignment for the - // bitmap data. There will be no need to call SkAlign4 once crbug.com/293728 - // is fixed. - const size_t dst_row_bytes = SkAlign4(dst_info.minRowBytes()); - DCHECK_EQ(0u, dst_row_bytes % 4); - bool success = canvas->readPixels(dst_info, memory, dst_row_bytes, 0, 0); - DCHECK_EQ(true, success); + bool rv = canvas->readPixels(dst_info, memory, stride, 0, 0); + DCHECK(rv); } }
diff --git a/cc/raster/tile_task_worker_pool_perftest.cc b/cc/raster/tile_task_worker_pool_perftest.cc index 7d6706d..258afc4 100644 --- a/cc/raster/tile_task_worker_pool_perftest.cc +++ b/cc/raster/tile_task_worker_pool_perftest.cc
@@ -381,7 +381,7 @@ private: void Create3dOutputSurfaceAndResourceProvider() { - output_surface_ = FakeOutputSurface::Create3d(context_provider_).Pass(); + output_surface_ = FakeOutputSurface::Create3d(context_provider_); CHECK(output_surface_->BindToClient(&output_surface_client_)); resource_provider_ = FakeResourceProvider::Create( output_surface_.get(), nullptr, &gpu_memory_buffer_manager_); @@ -454,7 +454,7 @@ public: // Overridden from testing::Test: void SetUp() override { - output_surface_ = FakeOutputSurface::Create3d(context_provider_).Pass(); + output_surface_ = FakeOutputSurface::Create3d(context_provider_); CHECK(output_surface_->BindToClient(&output_surface_client_)); resource_provider_ = FakeResourceProvider::Create(output_surface_.get(), nullptr);
diff --git a/cc/scheduler/scheduler_unittest.cc b/cc/scheduler/scheduler_unittest.cc index 1392c30..f8f2e8e 100644 --- a/cc/scheduler/scheduler_unittest.cc +++ b/cc/scheduler/scheduler_unittest.cc
@@ -420,7 +420,7 @@ void CheckMainFrameSkippedAfterLateCommit(bool expect_send_begin_main_frame); void ImplFrameSkippedAfterLateSwapAck(bool swap_ack_before_deadline); - void ImplFrameIsNotSkippedAfterLateSwapAck(); + void ImplFrameNotSkippedAfterLateSwapAck(); void BeginFramesNotFromClient(bool use_external_begin_frame_source, bool throttle_frame_production); void BeginFramesNotFromClient_SwapThrottled( @@ -779,7 +779,7 @@ SchedulerClientThatsetNeedsDrawInsideDraw* client = new SchedulerClientThatsetNeedsDrawInsideDraw; scheduler_settings_.use_external_begin_frame_source = true; - SetUpScheduler(make_scoped_ptr(client).Pass(), true); + SetUpScheduler(make_scoped_ptr(client), true); client->SetRequestRedrawsInsideDraw(true); scheduler_->SetNeedsRedraw(); @@ -815,7 +815,7 @@ SchedulerClientThatsetNeedsDrawInsideDraw* client = new SchedulerClientThatsetNeedsDrawInsideDraw; scheduler_settings_.use_external_begin_frame_source = true; - SetUpScheduler(make_scoped_ptr(client).Pass(), true); + SetUpScheduler(make_scoped_ptr(client), true); client->SetRequestRedrawsInsideDraw(true); client->SetDrawWillHappen(false); @@ -891,7 +891,7 @@ new SchedulerClientThatSetNeedsBeginMainFrameInsideDraw; scheduler_settings_.use_external_begin_frame_source = true; - SetUpScheduler(make_scoped_ptr(client).Pass(), true); + SetUpScheduler(make_scoped_ptr(client), true); EXPECT_FALSE(client->needs_begin_frames()); scheduler_->SetNeedsRedraw(); @@ -933,7 +933,7 @@ SchedulerClientThatsetNeedsDrawInsideDraw* client = new SchedulerClientThatsetNeedsDrawInsideDraw; scheduler_settings_.use_external_begin_frame_source = true; - SetUpScheduler(make_scoped_ptr(client).Pass(), true); + SetUpScheduler(make_scoped_ptr(client), true); client->SetDrawWillHappen(false); @@ -976,7 +976,7 @@ SchedulerClientThatSetNeedsBeginMainFrameInsideDraw* client = new SchedulerClientThatSetNeedsBeginMainFrameInsideDraw; scheduler_settings_.use_external_begin_frame_source = true; - SetUpScheduler(make_scoped_ptr(client).Pass(), true); + SetUpScheduler(make_scoped_ptr(client), true); scheduler_->SetNeedsRedraw(); EXPECT_TRUE(scheduler_->RedrawPending()); @@ -1014,7 +1014,7 @@ SchedulerClientNeedsPrepareTilesInDraw* client = new SchedulerClientNeedsPrepareTilesInDraw; scheduler_settings_.use_external_begin_frame_source = true; - SetUpScheduler(make_scoped_ptr(client).Pass(), true); + SetUpScheduler(make_scoped_ptr(client), true); // Request both draw and prepare tiles. PrepareTiles shouldn't // be trigged until BeginImplFrame. @@ -1268,7 +1268,7 @@ SchedulerClientNeedsPrepareTilesInDraw* client = new SchedulerClientNeedsPrepareTilesInDraw; scheduler_settings_.use_external_begin_frame_source = true; - SetUpScheduler(make_scoped_ptr(client).Pass(), true); + SetUpScheduler(make_scoped_ptr(client), true); scheduler_->SetNeedsRedraw(); EXPECT_SCOPED(AdvanceFrame()); @@ -1283,7 +1283,7 @@ new SchedulerClientNeedsPrepareTilesInDraw; scheduler_settings_.use_external_begin_frame_source = true; scheduler_settings_.commit_to_active_tree = true; - SetUpScheduler(make_scoped_ptr(client).Pass(), true); + SetUpScheduler(make_scoped_ptr(client), true); // SetNeedsBeginMainFrame should begin the frame on the next BeginImplFrame. scheduler_->SetNeedsBeginMainFrame(); @@ -1323,7 +1323,7 @@ new SchedulerClientNeedsPrepareTilesInDraw; scheduler_settings_.use_external_begin_frame_source = true; scheduler_settings_.commit_to_active_tree = true; - SetUpScheduler(make_scoped_ptr(client).Pass(), true); + SetUpScheduler(make_scoped_ptr(client), true); // SetNeedsBeginMainFrame should begin the frame on the next BeginImplFrame. scheduler_->SetNeedsBeginMainFrame(); @@ -1404,9 +1404,8 @@ // Response times of BeginMainFrame's without the critical path flag set // should not affect whether we recover latency or not. -TEST_F( - SchedulerTest, - MainFrameSkippedAfterLateCommit_LongBeginMainFrameQueueDurationNotCritical) { +TEST_F(SchedulerTest, + MainFrameSkippedAfterLateCommit_LongMainFrameQueueDurationNotCritical) { scheduler_settings_.use_external_begin_frame_source = true; SetUpScheduler(true); fake_compositor_timing_history_->SetAllEstimatesTo(kFastDuration); @@ -1420,9 +1419,8 @@ // Response times of BeginMainFrame's with the critical path flag set // should affect whether we recover latency or not. -TEST_F( - SchedulerTest, - MainFrameNotSkippedAfterLateCommit_LongBeginMainFrameQueueDurationCritical) { +TEST_F(SchedulerTest, + MainFrameNotSkippedAfterLateCommit_LongMainFrameQueueDurationCritical) { scheduler_settings_.use_external_begin_frame_source = true; SetUpScheduler(true); fake_compositor_timing_history_->SetAllEstimatesTo(kFastDuration); @@ -1596,9 +1594,8 @@ EXPECT_SCOPED(ImplFrameSkippedAfterLateSwapAck(swap_ack_before_deadline)); } -TEST_F( - SchedulerTest, - ImplFrameSkippedAfterLateSwapAck_LongBeginMainFrameQueueDurationNotCritical) { +TEST_F(SchedulerTest, + ImplFrameSkippedAfterLateSwapAck_LongMainFrameQueueDurationNotCritical) { scheduler_settings_.use_external_begin_frame_source = true; SetUpScheduler(true); fake_compositor_timing_history_->SetAllEstimatesTo(kFastDuration); @@ -1693,7 +1690,7 @@ } } -void SchedulerTest::ImplFrameIsNotSkippedAfterLateSwapAck() { +void SchedulerTest::ImplFrameNotSkippedAfterLateSwapAck() { // To get into a high latency state, this test disables automatic swap acks. client_->SetAutomaticSwapAck(false); @@ -1748,7 +1745,7 @@ TEST_F( SchedulerTest, - ImplFrameIsNotSkippedAfterLateSwapAck_BeginMainFrameQueueDurationCriticalTooLong) { + ImplFrameNotSkippedAfterLateSwapAck_MainFrameQueueDurationCriticalTooLong) { scheduler_settings_.use_external_begin_frame_source = true; SetUpScheduler(true); fake_compositor_timing_history_->SetAllEstimatesTo(kFastDuration); @@ -1756,45 +1753,44 @@ ->SetBeginMainFrameQueueDurationCriticalEstimate(kSlowDuration); fake_compositor_timing_history_ ->SetBeginMainFrameQueueDurationNotCriticalEstimate(kSlowDuration); - EXPECT_SCOPED(ImplFrameIsNotSkippedAfterLateSwapAck()); + EXPECT_SCOPED(ImplFrameNotSkippedAfterLateSwapAck()); } TEST_F(SchedulerTest, - ImplFrameIsNotSkippedAfterLateSwapAck_CommitEstimateTooLong) { + ImplFrameNotSkippedAfterLateSwapAck_CommitEstimateTooLong) { scheduler_settings_.use_external_begin_frame_source = true; SetUpScheduler(true); fake_compositor_timing_history_->SetAllEstimatesTo(kFastDuration); fake_compositor_timing_history_ ->SetBeginMainFrameStartToCommitDurationEstimate(kSlowDuration); - EXPECT_SCOPED(ImplFrameIsNotSkippedAfterLateSwapAck()); + EXPECT_SCOPED(ImplFrameNotSkippedAfterLateSwapAck()); } TEST_F(SchedulerTest, - ImplFrameIsNotSkippedAfterLateSwapAck_ReadyToActivateEstimateTooLong) { + ImplFrameNotSkippedAfterLateSwapAck_ReadyToActivateEstimateTooLong) { scheduler_settings_.use_external_begin_frame_source = true; SetUpScheduler(true); fake_compositor_timing_history_->SetAllEstimatesTo(kFastDuration); fake_compositor_timing_history_->SetCommitToReadyToActivateDurationEstimate( kSlowDuration); - EXPECT_SCOPED(ImplFrameIsNotSkippedAfterLateSwapAck()); + EXPECT_SCOPED(ImplFrameNotSkippedAfterLateSwapAck()); } TEST_F(SchedulerTest, - ImplFrameIsNotSkippedAfterLateSwapAck_ActivateEstimateTooLong) { + ImplFrameNotSkippedAfterLateSwapAck_ActivateEstimateTooLong) { scheduler_settings_.use_external_begin_frame_source = true; SetUpScheduler(true); fake_compositor_timing_history_->SetAllEstimatesTo(kFastDuration); fake_compositor_timing_history_->SetActivateDurationEstimate(kSlowDuration); - EXPECT_SCOPED(ImplFrameIsNotSkippedAfterLateSwapAck()); + EXPECT_SCOPED(ImplFrameNotSkippedAfterLateSwapAck()); } -TEST_F(SchedulerTest, - ImplFrameIsNotSkippedAfterLateSwapAck_DrawEstimateTooLong) { +TEST_F(SchedulerTest, ImplFrameNotSkippedAfterLateSwapAck_DrawEstimateTooLong) { scheduler_settings_.use_external_begin_frame_source = true; SetUpScheduler(true); fake_compositor_timing_history_->SetAllEstimatesTo(kFastDuration); fake_compositor_timing_history_->SetDrawDurationEstimate(kSlowDuration); - EXPECT_SCOPED(ImplFrameIsNotSkippedAfterLateSwapAck()); + EXPECT_SCOPED(ImplFrameNotSkippedAfterLateSwapAck()); } TEST_F(SchedulerTest,
diff --git a/cc/surfaces/surface.cc b/cc/surfaces/surface.cc index 8faff98..563415c2 100644 --- a/cc/surfaces/surface.cc +++ b/cc/surfaces/surface.cc
@@ -66,12 +66,7 @@ std::vector<SurfaceId> new_referenced_surfaces; if (current_frame_) { - for (auto& render_pass : - current_frame_->delegated_frame_data->render_pass_list) { - new_referenced_surfaces.insert(new_referenced_surfaces.end(), - render_pass->referenced_surfaces.begin(), - render_pass->referenced_surfaces.end()); - } + new_referenced_surfaces = current_frame_->metadata.referenced_surfaces; } if (previous_frame) {
diff --git a/cc/surfaces/surface_aggregator.cc b/cc/surfaces/surface_aggregator.cc index 4c1441a..181b07f 100644 --- a/cc/surfaces/surface_aggregator.cc +++ b/cc/surfaces/surface_aggregator.cc
@@ -58,6 +58,10 @@ ProcessAddedAndRemovedSurfaces(); } +SurfaceAggregator::PrewalkResult::PrewalkResult() {} + +SurfaceAggregator::PrewalkResult::~PrewalkResult() {} + // Create a clip rect for an aggregated quad from the original clip rect and // the clip rect from the surface it's on. SurfaceAggregator::ClipData SurfaceAggregator::CalculateClipRect( @@ -491,7 +495,8 @@ // Walk the Surface tree from surface_id. Validate the resources of the current // surface and its descendants, check if there are any copy requests, and // return the combined damage rect. -gfx::Rect SurfaceAggregator::PrewalkTree(SurfaceId surface_id) { +gfx::Rect SurfaceAggregator::PrewalkTree(SurfaceId surface_id, + PrewalkResult* result) { if (referenced_surfaces_.count(surface_id)) return gfx::Rect(); Surface* surface = manager_->GetSurfaceForId(surface_id); @@ -569,7 +574,7 @@ provider_->DeclareUsedResourcesFromChild(child_id, referenced_resources); for (const auto& render_pass : frame_data->render_pass_list) - has_copy_requests_ |= !render_pass->copy_requests.empty(); + result->has_copy_requests |= !render_pass->copy_requests.empty(); gfx::Rect damage_rect; if (!frame_data->render_pass_list.empty()) { @@ -583,14 +588,63 @@ SurfaceSet::iterator it = referenced_surfaces_.insert(surface->surface_id()).first; for (const auto& surface_info : child_surfaces) { - gfx::Rect surface_damage = PrewalkTree(surface_info.first); + gfx::Rect surface_damage = PrewalkTree(surface_info.first, result); damage_rect.Union( MathUtil::MapEnclosingClippedRect(surface_info.second, surface_damage)); } + + for (const auto& surface_id : surface_frame->metadata.referenced_surfaces) { + if (!contained_surfaces_.count(surface_id)) { + result->undrawn_surfaces.insert(surface_id); + PrewalkTree(surface_id, result); + } + } + referenced_surfaces_.erase(it); return damage_rect; } +void SurfaceAggregator::CopyUndrawnSurfaces(PrewalkResult* prewalk_result) { + // undrawn_surfaces are Surfaces that were identified by prewalk as being + // referenced by a drawn Surface, but aren't contained in a SurfaceDrawQuad. + // They need to be iterated over to ensure that any copy requests on them + // (or on Surfaces they reference) are executed. + std::vector<SurfaceId> surfaces_to_copy( + prewalk_result->undrawn_surfaces.begin(), + prewalk_result->undrawn_surfaces.end()); + + for (size_t i = 0; i < surfaces_to_copy.size(); i++) { + SurfaceId surface_id = surfaces_to_copy[i]; + Surface* surface = manager_->GetSurfaceForId(surface_id); + const CompositorFrame* surface_frame = surface->GetEligibleFrame(); + if (!surface_frame) + continue; + bool surface_has_copy_requests = false; + for (const auto& render_pass : + surface_frame->delegated_frame_data->render_pass_list) { + surface_has_copy_requests |= !render_pass->copy_requests.empty(); + } + if (!surface_has_copy_requests) { + // Children are not necessarily included in undrawn_surfaces (because + // they weren't referenced directly from a drawn surface), but may have + // copy requests, so make sure to check them as well. + for (const auto& child_id : surface_frame->metadata.referenced_surfaces) { + // Don't iterate over the child Surface if it was already listed as a + // child of a different Surface, or in the case where there's infinite + // recursion. + if (!prewalk_result->undrawn_surfaces.count(child_id)) { + surfaces_to_copy.push_back(child_id); + prewalk_result->undrawn_surfaces.insert(child_id); + } + } + } else { + SurfaceSet::iterator it = referenced_surfaces_.insert(surface_id).first; + CopyPasses(surface_frame->delegated_frame_data.get(), surface); + referenced_surfaces_.erase(it); + } + } +} + scoped_ptr<CompositorFrame> SurfaceAggregator::Aggregate(SurfaceId surface_id) { Surface* surface = manager_->GetSurfaceForId(surface_id); DCHECK(surface); @@ -609,9 +663,11 @@ dest_pass_list_ = &frame->delegated_frame_data->render_pass_list; valid_surfaces_.clear(); - has_copy_requests_ = false; - root_damage_rect_ = PrewalkTree(surface_id); + PrewalkResult prewalk_result; + root_damage_rect_ = PrewalkTree(surface_id, &prewalk_result); + has_copy_requests_ = prewalk_result.has_copy_requests; + CopyUndrawnSurfaces(&prewalk_result); SurfaceSet::iterator it = referenced_surfaces_.insert(surface_id).first; CopyPasses(root_surface_frame->delegated_frame_data.get(), surface); referenced_surfaces_.erase(it);
diff --git a/cc/surfaces/surface_aggregator.h b/cc/surfaces/surface_aggregator.h index 738aeec..6df7e6ba 100644 --- a/cc/surfaces/surface_aggregator.h +++ b/cc/surfaces/surface_aggregator.h
@@ -60,6 +60,15 @@ gfx::Rect rect; }; + struct PrewalkResult { + PrewalkResult(); + ~PrewalkResult(); + bool has_copy_requests = false; + // This is the set of Surfaces that were referenced by another Surface, but + // not included in a SurfaceDrawQuad. + std::set<SurfaceId> undrawn_surfaces; + }; + ClipData CalculateClipRect(const ClipData& surface_clip, const ClipData& quad_clip, const gfx::Transform& target_transform); @@ -83,7 +92,8 @@ const ClipData& clip_rect, RenderPass* dest_pass, SurfaceId surface_id); - gfx::Rect PrewalkTree(SurfaceId surface_id); + gfx::Rect PrewalkTree(SurfaceId surface_id, PrewalkResult* result); + void CopyUndrawnSurfaces(PrewalkResult* prewalk); void CopyPasses(const DelegatedFrameData* frame_data, Surface* surface); // Remove Surfaces that were referenced before but aren't currently
diff --git a/cc/surfaces/surface_aggregator_unittest.cc b/cc/surfaces/surface_aggregator_unittest.cc index 53b01e04..86eedf69 100644 --- a/cc/surfaces/surface_aggregator_unittest.cc +++ b/cc/surfaces/surface_aggregator_unittest.cc
@@ -477,6 +477,108 @@ factory_.Destroy(embedded_surface_id); } +TEST_F(SurfaceAggregatorValidSurfaceTest, UnreferencedSurface) { + SurfaceId embedded_surface_id = allocator_.GenerateId(); + factory_.Create(embedded_surface_id); + Surface* embedded_surface = manager_.GetSurfaceForId(embedded_surface_id); + EXPECT_FALSE(surface_aggregator_client_.HasSurface(embedded_surface)); + + test::Quad embedded_quads[] = {test::Quad::SolidColorQuad(SK_ColorGREEN)}; + test::Pass embedded_passes[] = { + test::Pass(embedded_quads, arraysize(embedded_quads))}; + + SubmitCompositorFrame(embedded_passes, arraysize(embedded_passes), + embedded_surface_id); + scoped_ptr<CopyOutputRequest> copy_request( + CopyOutputRequest::CreateEmptyRequest()); + CopyOutputRequest* copy_request_ptr = copy_request.get(); + factory_.RequestCopyOfSurface(embedded_surface_id, copy_request.Pass()); + + SurfaceId parent_surface_id = allocator_.GenerateId(); + factory_.Create(parent_surface_id); + Surface* parent_surface = manager_.GetSurfaceForId(parent_surface_id); + + test::Quad parent_quads[] = { + test::Quad::SolidColorQuad(SK_ColorWHITE), + test::Quad::SurfaceQuad(embedded_surface_id, 1.f), + test::Quad::SolidColorQuad(SK_ColorBLACK)}; + test::Pass parent_passes[] = { + test::Pass(parent_quads, arraysize(parent_quads))}; + + { + scoped_ptr<DelegatedFrameData> frame_data(new DelegatedFrameData); + AddPasses(&frame_data->render_pass_list, gfx::Rect(SurfaceSize()), + parent_passes, arraysize(parent_passes)); + + scoped_ptr<CompositorFrame> frame(new CompositorFrame); + frame->delegated_frame_data = frame_data.Pass(); + frame->metadata.referenced_surfaces.push_back(embedded_surface_id); + + factory_.SubmitCompositorFrame(parent_surface_id, frame.Pass(), + SurfaceFactory::DrawCallback()); + } + + test::Quad root_quads[] = {test::Quad::SolidColorQuad(SK_ColorWHITE), + test::Quad::SolidColorQuad(SK_ColorBLACK)}; + test::Pass root_passes[] = {test::Pass(root_quads, arraysize(root_quads))}; + + { + scoped_ptr<DelegatedFrameData> frame_data(new DelegatedFrameData); + AddPasses(&frame_data->render_pass_list, gfx::Rect(SurfaceSize()), + root_passes, arraysize(root_passes)); + + scoped_ptr<CompositorFrame> frame(new CompositorFrame); + frame->delegated_frame_data = frame_data.Pass(); + frame->metadata.referenced_surfaces.push_back(parent_surface_id); + + factory_.SubmitCompositorFrame(root_surface_id_, frame.Pass(), + SurfaceFactory::DrawCallback()); + } + + EXPECT_FALSE(surface_aggregator_client_.HasSurface(root_surface_)); + EXPECT_FALSE(surface_aggregator_client_.HasSurface(parent_surface)); + EXPECT_FALSE(surface_aggregator_client_.HasSurface(embedded_surface)); + + scoped_ptr<CompositorFrame> aggregated_frame = + aggregator_.Aggregate(root_surface_id_); + + EXPECT_TRUE(surface_aggregator_client_.HasSurface(root_surface_)); + EXPECT_TRUE(surface_aggregator_client_.HasSurface(parent_surface)); + EXPECT_TRUE(surface_aggregator_client_.HasSurface(embedded_surface)); + + ASSERT_TRUE(aggregated_frame); + ASSERT_TRUE(aggregated_frame->delegated_frame_data); + + DelegatedFrameData* frame_data = aggregated_frame->delegated_frame_data.get(); + + // First pass should come from surface that had a copy request but was not + // referenced directly. The second pass comes from the root surface. + // parent_quad should be ignored because it is neither referenced through a + // SurfaceDrawQuad nor has a copy request on it. + test::Pass expected_passes[] = { + test::Pass(embedded_quads, arraysize(embedded_quads)), + test::Pass(root_quads, arraysize(root_quads))}; + TestPassesMatchExpectations(expected_passes, arraysize(expected_passes), + &frame_data->render_pass_list); + ASSERT_EQ(2u, frame_data->render_pass_list.size()); + ASSERT_EQ(1u, frame_data->render_pass_list[0]->copy_requests.size()); + DCHECK_EQ(copy_request_ptr, + frame_data->render_pass_list[0]->copy_requests[0].get()); + + SurfaceId surface_ids[] = {root_surface_id_, parent_surface_id, + embedded_surface_id}; + EXPECT_EQ(arraysize(surface_ids), + aggregator_.previous_contained_surfaces().size()); + for (size_t i = 0; i < arraysize(surface_ids); i++) { + EXPECT_TRUE( + aggregator_.previous_contained_surfaces().find(surface_ids[i]) != + aggregator_.previous_contained_surfaces().end()); + } + + factory_.Destroy(parent_surface_id); + factory_.Destroy(embedded_surface_id); +} + // This tests referencing a surface that has multiple render passes. TEST_F(SurfaceAggregatorValidSurfaceTest, MultiPassSurfaceReference) { SurfaceId embedded_surface_id = child_allocator_.GenerateId();
diff --git a/cc/surfaces/surface_factory_unittest.cc b/cc/surfaces/surface_factory_unittest.cc index fa05c2e..749d7c59 100644 --- a/cc/surfaces/surface_factory_unittest.cc +++ b/cc/surfaces/surface_factory_unittest.cc
@@ -490,10 +490,10 @@ // Give id2 a frame that references surface_id_. { scoped_ptr<RenderPass> render_pass(RenderPass::Create()); - render_pass->referenced_surfaces.push_back(surface_id_); scoped_ptr<DelegatedFrameData> frame_data(new DelegatedFrameData); frame_data->render_pass_list.push_back(std::move(render_pass)); scoped_ptr<CompositorFrame> frame(new CompositorFrame); + frame->metadata.referenced_surfaces.push_back(surface_id_); frame->delegated_frame_data = std::move(frame_data); factory_->SubmitCompositorFrame(id2, std::move(frame), SurfaceFactory::DrawCallback()); @@ -503,10 +503,10 @@ // Give surface_id_ a frame that references id2. { scoped_ptr<RenderPass> render_pass(RenderPass::Create()); - render_pass->referenced_surfaces.push_back(id2); scoped_ptr<DelegatedFrameData> frame_data(new DelegatedFrameData); frame_data->render_pass_list.push_back(std::move(render_pass)); scoped_ptr<CompositorFrame> frame(new CompositorFrame); + frame->metadata.referenced_surfaces.push_back(id2); frame->delegated_frame_data = std::move(frame_data); factory_->SubmitCompositorFrame(surface_id_, std::move(frame), SurfaceFactory::DrawCallback());
diff --git a/cc/surfaces/surface_sequence.h b/cc/surfaces/surface_sequence.h index 72f4bc9..b579296 100644 --- a/cc/surfaces/surface_sequence.h +++ b/cc/surfaces/surface_sequence.h
@@ -5,6 +5,8 @@ #ifndef CC_SURFACES_SURFACE_SEQUENCE_H_ #define CC_SURFACES_SURFACE_SEQUENCE_H_ +#include <tuple> + #include "base/containers/hash_tables.h" namespace cc { @@ -31,9 +33,8 @@ } inline bool operator<(const SurfaceSequence& a, const SurfaceSequence& b) { - if (a.id_namespace != b.id_namespace) - return a.id_namespace < b.id_namespace; - return a.sequence < b.sequence; + return std::tie(a.id_namespace, a.sequence) < + std::tie(b.id_namespace, b.sequence); } } // namespace cc
diff --git a/cc/test/fake_painted_scrollbar_layer.cc b/cc/test/fake_painted_scrollbar_layer.cc index 889e7e8..8e14ff3 100644 --- a/cc/test/fake_painted_scrollbar_layer.cc +++ b/cc/test/fake_painted_scrollbar_layer.cc
@@ -25,7 +25,7 @@ FakeScrollbar* fake_scrollbar, int scrolling_layer_id) : PaintedScrollbarLayer(settings, - scoped_ptr<Scrollbar>(fake_scrollbar).Pass(), + scoped_ptr<Scrollbar>(fake_scrollbar), scrolling_layer_id), update_count_(0), push_properties_count_(0),
diff --git a/cc/test/layer_tree_pixel_test.cc b/cc/test/layer_tree_pixel_test.cc index c48b8c0..f5e5460 100644 --- a/cc/test/layer_tree_pixel_test.cc +++ b/cc/test/layer_tree_pixel_test.cc
@@ -92,14 +92,14 @@ void LayerTreePixelTest::ReadbackResult(scoped_ptr<CopyOutputResult> result) { ASSERT_TRUE(result->HasBitmap()); - result_bitmap_ = result->TakeBitmap().Pass(); + result_bitmap_ = result->TakeBitmap(); EndTest(); } void LayerTreePixelTest::BeginTest() { Layer* target = readback_target_ ? readback_target_ : layer_tree_host()->root_layer(); - target->RequestCopyOfOutput(CreateCopyOutputRequest().Pass()); + target->RequestCopyOfOutput(CreateCopyOutputRequest()); PostSetNeedsCommitToMainThread(); }
diff --git a/cc/test/pixel_test.cc b/cc/test/pixel_test.cc index 93f6341..58e5564 100644 --- a/cc/test/pixel_test.cc +++ b/cc/test/pixel_test.cc
@@ -98,7 +98,7 @@ void PixelTest::ReadbackResult(base::Closure quit_run_loop, scoped_ptr<CopyOutputResult> result) { ASSERT_TRUE(result->HasBitmap()); - result_bitmap_ = result->TakeBitmap().Pass(); + result_bitmap_ = result->TakeBitmap(); quit_run_loop.Run(); }
diff --git a/cc/test/test_web_graphics_context_3d.cc b/cc/test/test_web_graphics_context_3d.cc index d974ca9..72ac8ad 100644 --- a/cc/test/test_web_graphics_context_3d.cc +++ b/cc/test/test_web_graphics_context_3d.cc
@@ -526,7 +526,7 @@ base::ScopedPtrHashMap<unsigned, scoped_ptr<Buffer>>& buffers = namespace_->buffers; if (buffers.count(bound_buffer_) == 0) - buffers.set(bound_buffer_, make_scoped_ptr(new Buffer).Pass()); + buffers.set(bound_buffer_, make_scoped_ptr(new Buffer)); buffers.get(bound_buffer_)->target = target; }
diff --git a/cc/tiles/picture_layer_tiling_perftest.cc b/cc/tiles/picture_layer_tiling_perftest.cc index f996edc..8a169bc2 100644 --- a/cc/tiles/picture_layer_tiling_perftest.cc +++ b/cc/tiles/picture_layer_tiling_perftest.cc
@@ -33,7 +33,7 @@ base::TimeDelta::FromMilliseconds(kTimeLimitMillis), kTimeCheckInterval), context_provider_(TestContextProvider::Create()) { - output_surface_ = FakeOutputSurface::Create3d(context_provider_).Pass(); + output_surface_ = FakeOutputSurface::Create3d(context_provider_); CHECK(output_surface_->BindToClient(&output_surface_client_)); shared_bitmap_manager_.reset(new TestSharedBitmapManager());
diff --git a/cc/trees/layer_tree_host_common_unittest.cc b/cc/trees/layer_tree_host_common_unittest.cc index 1392bf6..bc3ffd5 100644 --- a/cc/trees/layer_tree_host_common_unittest.cc +++ b/cc/trees/layer_tree_host_common_unittest.cc
@@ -2406,7 +2406,7 @@ // Add a transform animation with a start delay to |grand_child|. scoped_ptr<Animation> animation = Animation::Create( - scoped_ptr<AnimationCurve>(new FakeTransformTransition(1.0)).Pass(), 0, 1, + scoped_ptr<AnimationCurve>(new FakeTransformTransition(1.0)), 0, 1, Animation::TRANSFORM); animation->set_fill_mode(Animation::FILL_MODE_NONE); animation->set_time_offset(base::TimeDelta::FromMilliseconds(-1000)); @@ -7347,7 +7347,7 @@ EXPECT_EQ(expected, actual); // Add a mask layer to child. - child_raw->SetMaskLayer(LayerImpl::Create(host_impl.active_tree(), 6).Pass()); + child_raw->SetMaskLayer(LayerImpl::Create(host_impl.active_tree(), 6)); child_raw->layer_tree_impl()->property_trees()->needs_rebuild = true; ExecuteCalculateDrawProperties(grand_parent_raw); @@ -7504,8 +7504,7 @@ gfx::Point3F(), gfx::PointF(), gfx::Size(1, 1), true, false, false); - child1_layer->SetMaskLayer( - LayerImpl::Create(host_impl.active_tree(), 4).Pass()); + child1_layer->SetMaskLayer(LayerImpl::Create(host_impl.active_tree(), 4)); child1_layer->SetDrawsContent(true); scoped_ptr<LayerImpl> replica_layer = @@ -8414,7 +8413,7 @@ // a singular transform, the subtree should still get processed. int animation_id = 0; scoped_ptr<Animation> animation = Animation::Create( - scoped_ptr<AnimationCurve>(new FakeTransformTransition(1.0)).Pass(), + scoped_ptr<AnimationCurve>(new FakeTransformTransition(1.0)), animation_id, 1, Animation::TRANSFORM); animation->set_fill_mode(Animation::FILL_MODE_NONE); animation->set_time_offset(base::TimeDelta::FromMilliseconds(-1000)); @@ -8441,7 +8440,7 @@ // Add an opacity animation with a start delay. animation_id = 1; animation = Animation::Create( - scoped_ptr<AnimationCurve>(new FakeFloatTransition(1.0, 0.f, 1.f)).Pass(), + scoped_ptr<AnimationCurve>(new FakeFloatTransition(1.0, 0.f, 1.f)), animation_id, 1, Animation::OPACITY); animation->set_fill_mode(Animation::FILL_MODE_NONE); animation->set_time_offset(base::TimeDelta::FromMilliseconds(-1000));
diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc index 43b8018..8643dbc 100644 --- a/cc/trees/layer_tree_host_impl.cc +++ b/cc/trees/layer_tree_host_impl.cc
@@ -43,6 +43,7 @@ #include "cc/layers/painted_scrollbar_layer_impl.h" #include "cc/layers/render_surface_impl.h" #include "cc/layers/scrollbar_layer_impl_base.h" +#include "cc/layers/surface_layer_impl.h" #include "cc/layers/viewport.h" #include "cc/output/compositor_frame_metadata.h" #include "cc/output/copy_output_request.h" @@ -1562,6 +1563,10 @@ !OuterViewportScrollLayer()->user_scrollable_vertical(); } + for (LayerImpl* surface_layer : active_tree_->SurfaceLayers()) { + metadata.referenced_surfaces.push_back( + static_cast<SurfaceLayerImpl*>(surface_layer)->surface_id()); + } if (!InnerViewportScrollLayer()) return metadata;
diff --git a/cc/trees/layer_tree_host_pixeltest_readback.cc b/cc/trees/layer_tree_host_pixeltest_readback.cc index da04d42..34eba0e0 100644 --- a/cc/trees/layer_tree_host_pixeltest_readback.cc +++ b/cc/trees/layer_tree_host_pixeltest_readback.cc
@@ -90,7 +90,7 @@ if (insert_copy_request_after_frame_count_ == 0) { Layer* const target = readback_target_ ? readback_target_ : layer_tree_host()->root_layer(); - target->RequestCopyOfOutput(CreateCopyOutputRequest().Pass()); + target->RequestCopyOfOutput(CreateCopyOutputRequest()); } PostSetNeedsCommitToMainThread(); } @@ -100,14 +100,14 @@ layer_tree_host()->source_frame_number()) { Layer* const target = readback_target_ ? readback_target_ : layer_tree_host()->root_layer(); - target->RequestCopyOfOutput(CreateCopyOutputRequest().Pass()); + target->RequestCopyOfOutput(CreateCopyOutputRequest()); } } void ReadbackResultAsBitmap(scoped_ptr<CopyOutputResult> result) { EXPECT_TRUE(task_runner_provider()->IsMainThread()); EXPECT_TRUE(result->HasBitmap()); - result_bitmap_ = result->TakeBitmap().Pass(); + result_bitmap_ = result->TakeBitmap(); EndTest(); }
diff --git a/cc/trees/layer_tree_host_unittest_context.cc b/cc/trees/layer_tree_host_unittest_context.cc index 86d9992..174af321 100644 --- a/cc/trees/layer_tree_host_unittest_context.cc +++ b/cc/trees/layer_tree_host_unittest_context.cc
@@ -1039,9 +1039,9 @@ layer_tree_host()->SetDebugState(debug_state); scoped_refptr<PaintedScrollbarLayer> scrollbar = - PaintedScrollbarLayer::Create( - layer_settings_, scoped_ptr<Scrollbar>(new FakeScrollbar).Pass(), - layer->id()); + PaintedScrollbarLayer::Create(layer_settings_, + scoped_ptr<Scrollbar>(new FakeScrollbar), + layer->id()); scrollbar->SetBounds(gfx::Size(10, 10)); scrollbar->SetIsDrawable(true); root->AddChild(scrollbar);
diff --git a/cc/trees/layer_tree_host_unittest_copyrequest.cc b/cc/trees/layer_tree_host_unittest_copyrequest.cc index a11ad95..f6bd32a 100644 --- a/cc/trees/layer_tree_host_unittest_copyrequest.cc +++ b/cc/trees/layer_tree_host_unittest_copyrequest.cc
@@ -105,7 +105,7 @@ void CopyOutputCallback(size_t id, scoped_ptr<CopyOutputResult> result) { EXPECT_TRUE(layer_tree_host()->task_runner_provider()->IsMainThread()); EXPECT_TRUE(result->HasBitmap()); - scoped_ptr<SkBitmap> bitmap = result->TakeBitmap().Pass(); + scoped_ptr<SkBitmap> bitmap = result->TakeBitmap(); EXPECT_EQ(result->size().ToString(), gfx::Size(bitmap->width(), bitmap->height()).ToString()); callbacks_[id] = result->size();
diff --git a/cc/trees/layer_tree_impl.cc b/cc/trees/layer_tree_impl.cc index 5964760..06635e5 100644 --- a/cc/trees/layer_tree_impl.cc +++ b/cc/trees/layer_tree_impl.cc
@@ -1319,6 +1319,19 @@ } } +void LayerTreeImpl::AddSurfaceLayer(LayerImpl* layer) { + DCHECK(std::find(surface_layers_.begin(), surface_layers_.end(), layer) == + surface_layers_.end()); + surface_layers_.push_back(layer); +} + +void LayerTreeImpl::RemoveSurfaceLayer(LayerImpl* layer) { + std::vector<LayerImpl*>::iterator it = + std::find(surface_layers_.begin(), surface_layers_.end(), layer); + DCHECK(it != surface_layers_.end()); + surface_layers_.erase(it); +} + const std::vector<LayerImpl*>& LayerTreeImpl::LayersWithCopyOutputRequest() const { // Only the active tree needs to know about layers with copy requests, as
diff --git a/cc/trees/layer_tree_impl.h b/cc/trees/layer_tree_impl.h index 2f8fbfc7..bbea5d79 100644 --- a/cc/trees/layer_tree_impl.h +++ b/cc/trees/layer_tree_impl.h
@@ -333,6 +333,12 @@ void RemoveLayerWithCopyOutputRequest(LayerImpl* layer); const std::vector<LayerImpl*>& LayersWithCopyOutputRequest() const; + void AddSurfaceLayer(LayerImpl* layer); + void RemoveSurfaceLayer(LayerImpl* layer); + const std::vector<LayerImpl*>& SurfaceLayers() const { + return surface_layers_; + } + int current_render_surface_list_id() const { return render_surface_layer_list_id_; } @@ -463,6 +469,7 @@ std::vector<PictureLayerImpl*> picture_layers_; std::vector<LayerImpl*> layers_with_copy_output_request_; + std::vector<LayerImpl*> surface_layers_; // List of visible layers for the most recently prepared frame. LayerImplList render_surface_layer_list_;
diff --git a/chrome/BUILD.gn b/chrome/BUILD.gn index ed18e51..0a09f8e 100644 --- a/chrome/BUILD.gn +++ b/chrome/BUILD.gn
@@ -620,9 +620,9 @@ group("packed_resources") { public_deps = [ + ":repack_chrome_100_percent", ":repack_locales_pack", ":repack_pseudo_locales_pack", - ":repack_chrome_100_percent", ] if (is_chrome_branded) { @@ -659,15 +659,15 @@ "$root_gen_dir/ui/resources/webui_resources.pak", ] deps = [ - "//chrome/browser:resources", "//chrome/app/theme:chrome_unscaled_resources", - "//chrome/common:resources", + "//chrome/browser:resources", "//chrome/browser/resources:invalidations_resources", "//chrome/browser/resources:memory_internals_resources", "//chrome/browser/resources:net_internals_resources", "//chrome/browser/resources:password_manager_internals_resources", "//chrome/browser/resources:signin_internals_resources", "//chrome/browser/resources:translate_internals_resources", + "//chrome/common:resources", "//components/resources", "//net:net_resources", "//ui/resources", @@ -688,8 +688,8 @@ "//chrome/browser/devtools:webrtc_device_provider_resources", "//chrome/browser/resources:component_extension_resources", "//chrome/browser/resources:options_resources", - "//chrome/browser/resources:settings_resources", "//chrome/browser/resources:quota_internals_resources", + "//chrome/browser/resources:settings_resources", "//chrome/browser/resources:sync_file_system_internals_resources", "//content/browser/devtools:devtools_resources", ]
diff --git a/chrome/VERSION b/chrome/VERSION index 45fd9ad..d4b72b1 100644 --- a/chrome/VERSION +++ b/chrome/VERSION
@@ -1,4 +1,4 @@ MAJOR=49 MINOR=0 -BUILD=2570 +BUILD=2571 PATCH=0
diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn index 8379c7a4..9cef154 100644 --- a/chrome/android/BUILD.gn +++ b/chrome/android/BUILD.gn
@@ -51,9 +51,9 @@ deps = [ ":chrome_locale_paks", ":chrome_strings_grd", + "//chrome/app:java_strings_grd", "//components/policy:app_restrictions_resources", "//content/public/android:content_java_resources", - "//chrome/app:java_strings_grd", "//third_party/android_data_chart:android_data_chart_java_resources", "//third_party/android_media:android_media_resources", ] @@ -120,7 +120,6 @@ ":chrome_java_resources", ":document_tab_model_info_proto_java", "//base:base_java", - "//net/android:net_java", "//components/bookmarks/common/android:bookmarks_java", "//components/dom_distiller/android:dom_distiller_content_java", "//components/dom_distiller/android:dom_distiller_core_java", @@ -136,8 +135,12 @@ "//components/web_contents_delegate_android:web_contents_delegate_android_java", "//content/public/android:content_java", "//media/base/android:media_java", + "//media/base/android:media_java", + "//media/midi:midi_java", + "//net/android:net_java", "//printing:printing_java", "//sync/android:sync_java", + "//third_party/WebKit/public:blink_headers_java", "//third_party/android_data_chart:android_data_chart_java", "//third_party/android_media:android_media_java", "//third_party/android_protobuf:protobuf_nano_javalib", @@ -152,9 +155,6 @@ "//third_party/cacheinvalidation:cacheinvalidation_proto_java", "//third_party/gif_player:gif_player_java", "//third_party/jsr-305:jsr_305_javalib", - "//third_party/WebKit/public:blink_headers_java", - "//media/base/android:media_java", - "//media/midi:midi_java", "//ui/android:ui_java", "//ui/android:ui_java_resources", google_play_services_library, @@ -257,9 +257,9 @@ "//components/invalidation/impl:java", "//sync:sync_java_test_support", "//sync/android:sync_java", + "//third_party/android_tools:android_support_v7_mediarouter_java", "//third_party/cacheinvalidation:cacheinvalidation_javalib", "//third_party/junit:hamcrest", - "//third_party/android_tools:android_support_v7_mediarouter_java", google_play_services_library, ] } @@ -322,12 +322,12 @@ "//net/android:net_java", "//net/android:net_java_test_support", "//printing:printing_java", + "//sync:sync_java_test_support", "//sync/android:sync_java", "//sync/android:sync_javatests", - "//sync:sync_java_test_support", + "//third_party/android_tools:android_support_v13_java", "//third_party/android_tools:android_support_v7_appcompat_java", "//third_party/android_tools:android_support_v7_recyclerview_java", - "//third_party/android_tools:android_support_v13_java", "//third_party/android_tools:legacy_http_javalib", "//third_party/cacheinvalidation:cacheinvalidation_javalib", "//third_party/jsr-305:jsr_305_javalib",
diff --git a/chrome/android/chrome_public_apk_tmpl.gni b/chrome/android/chrome_public_apk_tmpl.gni index 5a6296c8..26ae9fc 100644 --- a/chrome/android/chrome_public_apk_tmpl.gni +++ b/chrome/android/chrome_public_apk_tmpl.gni
@@ -23,7 +23,9 @@ rebase_path("$root_gen_dir/CHROME_VERSION.json", root_out_dir) native_lib_version_arg = "@FileArg($_native_lib_file:full-quoted)" - if (!is_debug) { + if (is_debug) { + enable_multidex = true + } else { proguard_enabled = true _prev_proguard_configs = [] if (defined(proguard_configs)) {
diff --git a/chrome/android/java/res/layout/fre_choose_account.xml b/chrome/android/java/res/layout/fre_choose_account.xml index 023e36e..de5e94e 100644 --- a/chrome/android/java/res/layout/fre_choose_account.xml +++ b/chrome/android/java/res/layout/fre_choose_account.xml
@@ -64,7 +64,6 @@ android:layout_height="wrap_content" android:layout_marginBottom="@dimen/fre_margin" android:padding="0dp" - android:contentDescription="@string/accessibility_fre_account_spinner" android:textColor="@color/fre_text_color" /> <TextView
diff --git a/chrome/android/java/res/values/colors.xml b/chrome/android/java/res/values/colors.xml index c1ecf5f..51f22e7 100644 --- a/chrome/android/java/res/values/colors.xml +++ b/chrome/android/java/res/values/colors.xml
@@ -19,7 +19,6 @@ <color name="infobar_background">#fff</color> <color name="infobar_background_separator">#afafaf</color> <color name="infobar_accent_blue">#4285f4</color> - <color name="infobar_tertiary_button_text">#969696</color> <color name="infobar_descriptive_text_color">#646464</color> <!-- Snackbar colors -->
diff --git a/chrome/android/java/res/values/ids.xml b/chrome/android/java/res/values/ids.xml index 29190ba..26f3b4b 100644 --- a/chrome/android/java/res/values/ids.xml +++ b/chrome/android/java/res/values/ids.xml
@@ -21,7 +21,6 @@ <!-- InfoBar constants --> <item type="id" name="button_primary" /> <item type="id" name="button_secondary" /> - <item type="id" name="button_tertiary" /> <item type="id" name="infobar_close_button" /> <item type="id" name="infobar_extra_check" /> <item type="id" name="infobar_message" />
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchPanelBase.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchPanelBase.java index 8d6ffc6..3c80f13a 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchPanelBase.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchPanelBase.java
@@ -56,11 +56,6 @@ private static final float SMALL_PANEL_WIDTH_THRESHOLD_DP = 680.f; /** - * The height of the Contextual Search Panel's Shadow in dps. - */ - private static final float PANEL_SHADOW_HEIGHT_DP = 16.f; - - /** * The brightness of the base page when the Panel is peeking. */ private static final float BASE_PAGE_BRIGHTNESS_STATE_PEEKED = 1.f; @@ -136,11 +131,6 @@ private float mToolbarHeight; /** - * The padding top of the Search Bar. - */ - private float mSearchBarPaddingTop; - - /** * The height of the Search Bar when the Panel is peeking, in dps. */ private float mSearchBarHeightPeeking; @@ -322,21 +312,6 @@ } /** - * @return The current X-position of the Contextual Search Panel. - */ - protected float calculateSearchPanelX() { - return isFullscreenSizePanel() ? 0.f - : Math.round((getFullscreenWidth() - calculateSearchPanelWidth()) / 2.f); - } - - /** - * @return The current Y-position of the Contextual Search Panel. - */ - protected float calculateSearchPanelY() { - return getFullscreenHeight() - mHeight; - } - - /** * @return The current width of the Contextual Search Panel. */ protected float calculateSearchPanelWidth() { @@ -822,8 +797,6 @@ mToolbarHeight = mContext.getResources().getDimension( getControlContainerHeightResource()) * mPxToDp; - mSearchBarPaddingTop = PANEL_SHADOW_HEIGHT_DP; - mSearchBarHeightPeeking = mContext.getResources().getDimension( R.dimen.contextual_search_bar_height) * mPxToDp; mSearchBarHeightMaximized = mContext.getResources().getDimension( @@ -971,9 +944,10 @@ * @param percentage The completion percentage of the transition. */ private void updatePanelSize(float height, PanelState endState, float percentage) { - mOffsetX = calculateSearchPanelX(); - mOffsetY = calculateSearchPanelY(); mHeight = height; + mOffsetX = isFullscreenSizePanel() ? 0.f + : Math.round((getFullscreenWidth() - calculateSearchPanelWidth()) / 2.f); + mOffsetY = getFullscreenHeight() - mHeight; mIsMaximized = height == getPanelHeightFromState(PanelState.MAXIMIZED); } @@ -1274,8 +1248,7 @@ // consideration the height of the shadow (what is returned by the // getPanelFromHeight method). We need the measurement of the portion // of the Panel that occludes the page. - final float expandedHeight = getPanelHeightFromState(expandedState) - - mSearchBarPaddingTop; + final float expandedHeight = getPanelHeightFromState(expandedState); // Calculate the offset to center the selection on the available area. final float fullscreenHeight = getFullscreenHeight();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/readermode/ReaderModePanel.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/readermode/ReaderModePanel.java index f0fa3933..3183df2 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/readermode/ReaderModePanel.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/readermode/ReaderModePanel.java
@@ -18,8 +18,12 @@ import org.chromium.chrome.browser.compositor.layouts.LayoutUpdateHost; import org.chromium.chrome.browser.compositor.scene_layer.ContextualSearchSceneLayer; import org.chromium.chrome.browser.compositor.scene_layer.SceneLayer; +import org.chromium.chrome.browser.dom_distiller.DomDistillerTabUtils; import org.chromium.chrome.browser.dom_distiller.ReaderModeManagerDelegate; +import org.chromium.chrome.browser.externalnav.ExternalNavigationHandler; +import org.chromium.components.navigation_interception.NavigationParams; import org.chromium.content.browser.ContentViewCore; +import org.chromium.content_public.browser.WebContents; import org.chromium.ui.resources.ResourceManager; /** @@ -74,22 +78,45 @@ @Override public OverlayPanelContent createNewOverlayPanelContent() { OverlayContentDelegate delegate = new OverlayContentDelegate() { + /** + * Track if a navigation/load is the first one for this content. + */ + private boolean mIsInitialLoad = true; + @Override public void onContentViewCreated(ContentViewCore contentView) { mContentViewDelegate.setOverlayPanelContentViewCore(contentView); + + WebContents distilledWebContents = contentView.getWebContents(); + if (distilledWebContents == null) return; + + WebContents sourceWebContents = mManagerDelegate.getBasePageWebContents(); + if (sourceWebContents == null) return; + + DomDistillerTabUtils.distillAndView(sourceWebContents, distilledWebContents); } @Override public void onContentViewDestroyed() { mContentViewDelegate.releaseOverlayPanelContentViewCore(); + mIsInitialLoad = true; } @Override - public void onMainFrameNavigation(String url, boolean isExternalUrl, - boolean isFailure) { - if (isExternalUrl) { - mManagerDelegate.createNewTab(url); + public boolean shouldInterceptNavigation(ExternalNavigationHandler externalNavHandler, + NavigationParams navigationParams) { + // The initial load will be the distilled content; don't try to open a new tab if + // this is the case. All other navigations on distilled pages will come from link + // clicks. + if (mIsInitialLoad) { + mIsInitialLoad = false; + return true; } + if (!navigationParams.isExternalProtocol) { + mManagerDelegate.createNewTab(navigationParams.url); + return false; + } + return true; } }; @@ -183,12 +210,6 @@ } @Override - public void peekPanel(StateChangeReason reason) { - super.peekPanel(reason); - mManagerDelegate.onPanelPeek(); - } - - @Override protected void updatePanelForCloseOrPeek(float percent) { super.updatePanelForCloseOrPeek(percent); getReaderModeBarControl().setBarText(R.string.reader_view_text);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManager.java b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManager.java index beaff0f..a8f3a97 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManager.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManager.java
@@ -6,6 +6,7 @@ import android.app.Activity; import android.content.Context; +import android.text.TextUtils; import android.view.View; import android.view.ViewGroup; import android.view.ViewTreeObserver; @@ -731,7 +732,7 @@ alternateTerm = null; doPreventPreload = true; } - if (!searchTerm.isEmpty()) { + if (!TextUtils.isEmpty(searchTerm)) { // TODO(donnd): Instead of preloading, we should prefetch (ie the URL should not // appear in the user's history until the user views it). See crbug.com/406446. boolean shouldPreload = !doPreventPreload && mPolicy.shouldPrefetchSearchResult(true);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchStaticEventFilter.java b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchStaticEventFilter.java index 6daf40f..bedd8440f 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchStaticEventFilter.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchStaticEventFilter.java
@@ -77,13 +77,16 @@ @Override protected boolean onTouchEventInternal(MotionEvent event) { + OverlayPanel activePanel = mPanelManager.getActivePanel(); + if (activePanel == null) return false; + if (event.getActionMasked() == MotionEvent.ACTION_DOWN) { // To avoid a gray flash of empty content, show the search content // view immediately on tap rather than waiting for panel expansion. // TODO(pedrosimonetti): Once we implement "side-swipe to dismiss" // we'll have to revisit this because we don't want to set the // Content View visibility to true when the side-swipe is detected. - mPanelManager.getActivePanel().notifyPanelTouched(); + activePanel.notifyPanelTouched(); } mSwipeRecognizer.onTouchEvent(event);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/dom_distiller/ReaderModeManager.java b/chrome/android/java/src/org/chromium/chrome/browser/dom_distiller/ReaderModeManager.java index 734f3cd..e00460f 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/dom_distiller/ReaderModeManager.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/dom_distiller/ReaderModeManager.java
@@ -44,11 +44,6 @@ implements InfoBarContainerObserver, ReaderModeManagerDelegate { /** - * URL scheme for dom-distiller. - */ - public static final String DOM_DISTILLER_SCHEME = "chrome-distiller"; - - /** * POSSIBLE means reader mode can be entered. */ public static final int POSSIBLE = 0; @@ -161,7 +156,7 @@ @Override public void onHidden(Tab tab) { - mReaderModePanel.closePanel(StateChangeReason.UNKNOWN, false); + closeReaderPanel(StateChangeReason.UNKNOWN, false); } @Override @@ -206,7 +201,7 @@ if (DomDistillerUrlUtils.isDistilledPage(tab.getUrl())) { tabInfo.setStatus(STARTED); mReaderModePageUrl = tab.getUrl(); - mReaderModePanel.closePanel(StateChangeReason.CONTENT_CHANGED, true); + closeReaderPanel(StateChangeReason.CONTENT_CHANGED, true); } // Make sure there is a distillability delegate set on the WebContents. setDistillabilityCallback(); @@ -217,12 +212,10 @@ @Override public void onToggleFullscreenMode(Tab tab, boolean enable) { - if (mReaderModePanel == null) return; - // Temporarily hide the reader mode panel while fullscreen is enabled. if (enable) { mIsFullscreenModeEntered = true; - mReaderModePanel.closePanel(StateChangeReason.FULLSCREEN_ENTERED, false); + closeReaderPanel(StateChangeReason.FULLSCREEN_ENTERED, false); } else { mIsFullscreenModeEntered = false; requestReaderPanelShow(StateChangeReason.FULLSCREEN_EXITED); @@ -234,16 +227,16 @@ @Override public void onAddInfoBar(InfoBarContainer container, InfoBar infoBar, boolean isFirst) { // Temporarily hides the reader mode button while the infobars are shown. - if (isFirst && mReaderModePanel != null) { + if (isFirst) { mIsInfobarContainerShown = true; - mReaderModePanel.closePanel(StateChangeReason.INFOBAR_SHOWN, false); + closeReaderPanel(StateChangeReason.INFOBAR_SHOWN, false); } } @Override public void onRemoveInfoBar(InfoBarContainer container, InfoBar infoBar, boolean isLast) { // Re-shows the reader mode button if necessary once the infobars are dismissed. - if (isLast && mReaderModePanel != null) { + if (isLast) { mIsInfobarContainerShown = false; requestReaderPanelShow(StateChangeReason.INFOBAR_HIDDEN); } @@ -289,11 +282,11 @@ } @Override - public void onPanelPeek() { - String distillerUrl = DomDistillerUrlUtils.getDistillerViewUrlFromUrl( - DOM_DISTILLER_SCHEME, mTabModelSelector.getCurrentTab().getUrl()); - // Load the distilled page URL when the visibility of the panel changes. - mReaderModePanel.loadUrlInPanel(distillerUrl, false); + public WebContents getBasePageWebContents() { + Tab tab = mTabModelSelector.getCurrentTab(); + if (tab == null) return null; + + return tab.getWebContents(); } private WebContentsObserver createWebContentsObserver(WebContents webContents) { @@ -309,7 +302,7 @@ mTabStatusMap.get(readerTabId).setUrl(validatedUrl); if (DomDistillerUrlUtils.isDistilledPage(validatedUrl)) { mTabStatusMap.get(readerTabId).setStatus(STARTED); - mReaderModePanel.closePanel(StateChangeReason.UNKNOWN, true); + closeReaderPanel(StateChangeReason.UNKNOWN, true); mReaderModePageUrl = validatedUrl; } } @@ -333,7 +326,7 @@ mReaderModePageUrl = null; if (mTabStatusMap.containsKey(readerTabId) && mTabStatusMap.get(readerTabId).getStatus() != POSSIBLE) { - mReaderModePanel.closePanel(StateChangeReason.UNKNOWN, false); + closeReaderPanel(StateChangeReason.UNKNOWN, false); } else { requestReaderPanelShow(StateChangeReason.UNKNOWN); } @@ -361,12 +354,22 @@ } /** + * A wrapper for the close method of the Reader Mode panel that checks for null and can be + * overridden for testing. + * @param reason The reason the panel is closing. + * @param animate True if the panel should animate closed. + */ + private void closeReaderPanel(StateChangeReason reason, boolean animate) { + if (mReaderModePanel == null) return; + mReaderModePanel.closePanel(reason, animate); + } + + /** * Orientation change event handler. Simply close the panel. */ public void onOrientationChange() { - if (mReaderModePanel == null) return; // Close to reset the panel then immediately show again. - mReaderModePanel.closePanel(StateChangeReason.UNKNOWN, false); + closeReaderPanel(StateChangeReason.UNKNOWN, false); requestReaderPanelShow(StateChangeReason.UNKNOWN); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/dom_distiller/ReaderModeManagerDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/dom_distiller/ReaderModeManagerDelegate.java index 2fb87d2..c006597 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/dom_distiller/ReaderModeManagerDelegate.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/dom_distiller/ReaderModeManagerDelegate.java
@@ -6,6 +6,7 @@ import org.chromium.chrome.browser.ChromeActivity; import org.chromium.chrome.browser.compositor.bottombar.readermode.ReaderModePanel; +import org.chromium.content_public.browser.WebContents; /** * Delegate for the panel to call into the manager. @@ -38,9 +39,10 @@ void onCloseButtonPressed(); /** - * Notify the manager that the panel is starting to peek. + * Get the WebContents of the page that is being distilled. + * @return The WebContents for the currently visible tab. */ - void onPanelPeek(); + WebContents getBasePageWebContents(); /** * @return The ChromeActivity that owns the manager.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/AccountFirstRunView.java b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/AccountFirstRunView.java index c25c45d9..002cd2e 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/AccountFirstRunView.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/AccountFirstRunView.java
@@ -7,6 +7,7 @@ import android.content.Context; import android.graphics.Bitmap; import android.graphics.Color; +import android.os.Bundle; import android.text.TextUtils; import android.util.AttributeSet; import android.view.Gravity; @@ -183,6 +184,23 @@ mArrayAdapter.setDropDownViewResource(R.layout.fre_spinner_dropdown); mSpinner.setAdapter(mArrayAdapter); mSpinner.setOnItemSelectedListener(new SpinnerOnItemSelectedListener()); + + // Only set the spinner's content description right before the accessibility action is going + // to be performed. Otherwise, the the content description is read when the + // AccountFirstRunView is created because setting the spinner's adapter causes a + // TYPE_VIEW_SELECTED event. ViewPager loads the next and previous pages according to + // it's off-screen page limit, which is one by default, so without this the content + // description ends up being read when the card before this one shown. + mSpinner.setAccessibilityDelegate(new AccessibilityDelegate() { + @Override + public boolean performAccessibilityAction(View host, int action, Bundle args) { + if (mSpinner.getContentDescription() == null) { + mSpinner.setContentDescription(getResources().getString( + R.string.accessibility_fre_account_spinner)); + } + return super.performAccessibilityAction(host, action, args); + } + }); } @Override
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/infobar/ConfirmInfoBar.java b/chrome/android/java/src/org/chromium/chrome/browser/infobar/ConfirmInfoBar.java index 8810c2b..cbdbba1 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/infobar/ConfirmInfoBar.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/infobar/ConfirmInfoBar.java
@@ -33,8 +33,8 @@ /** Text shown on the secondary button, e.g. "Cancel".*/ private final String mSecondaryButtonText; - /** Text shown on the extra button, e.g. "More info". */ - private final String mTertiaryButtonText; + /** Text shown on the link, e.g. "Learn more". */ + private final String mLinkText; /** Notified when one of the buttons is clicked. */ private final InfoBarListeners.Confirm mConfirmListener; @@ -54,7 +54,7 @@ super(confirmListener, iconDrawableId, iconBitmap, message); mPrimaryButtonText = primaryButtonText; mSecondaryButtonText = secondaryButtonText; - mTertiaryButtonText = linkText; + mLinkText = linkText; mConfirmListener = confirmListener; } @@ -77,7 +77,8 @@ @Override public void createContent(InfoBarLayout layout) { - layout.setButtons(mPrimaryButtonText, mSecondaryButtonText, mTertiaryButtonText); + layout.setButtons(mPrimaryButtonText, mSecondaryButtonText); + if (mLinkText != null) layout.setMessageLinkText(mLinkText); } private static boolean hasPermission(Context context, String permission) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/infobar/InfoBar.java b/chrome/android/java/src/org/chromium/chrome/browser/infobar/InfoBar.java index b923ba7d..682debf 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/infobar/InfoBar.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/infobar/InfoBar.java
@@ -186,11 +186,9 @@ View closeButton = mContentView.findViewById(R.id.infobar_close_button); View primaryButton = mContentView.findViewById(R.id.button_primary); View secondaryButton = mContentView.findViewById(R.id.button_secondary); - View tertiaryButton = mContentView.findViewById(R.id.button_tertiary); if (closeButton != null) closeButton.setEnabled(state); if (primaryButton != null) primaryButton.setEnabled(state); if (secondaryButton != null) secondaryButton.setEnabled(state); - if (tertiaryButton != null) tertiaryButton.setEnabled(state); } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/infobar/InfoBarLayout.java b/chrome/android/java/src/org/chromium/chrome/browser/infobar/InfoBarLayout.java index c307576..bb6548e8 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/infobar/InfoBarLayout.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/infobar/InfoBarLayout.java
@@ -11,7 +11,10 @@ import android.graphics.Color; import android.graphics.Typeface; import android.graphics.drawable.Drawable; +import android.text.SpannableStringBuilder; +import android.text.Spanned; import android.text.TextUtils; +import android.text.style.ClickableSpan; import android.util.TypedValue; import android.view.Gravity; import android.view.View; @@ -134,13 +137,14 @@ private ImageView mIconView; private ButtonCompat mPrimaryButton; private Button mSecondaryButton; - private Button mTertiaryButton; private View mCustomButton; private Group mMainGroup; private Group mButtonGroup; private boolean mIsUsingBigIcon; + private CharSequence mMessageMainText; + private String mMessageLinkText; /** * These values are used during onMeasure() to track where the next view will be placed. @@ -219,8 +223,9 @@ } // Set up the message view. + mMessageMainText = message; mMessageLayout = new InfoBarControlLayout(context); - mMessageTextView = mMessageLayout.addMainMessage(message); + mMessageTextView = mMessageLayout.addMainMessage(prepareMainMessageString()); } /** @@ -245,7 +250,17 @@ * KK and L: https://crbug.com/543205 */ public void setMessage(CharSequence message) { - mMessageTextView.setText(message, TextView.BufferType.SPANNABLE); + mMessageMainText = message; + mMessageTextView.setText(prepareMainMessageString()); + } + + /** + * Sets the message to show for a link in the message, if an InfoBar requires a link + * (e.g. "Learn more"). + */ + public void setMessageLinkText(String linkText) { + mMessageLinkText = linkText; + mMessageTextView.setText(prepareMainMessageString()); } /** @@ -259,20 +274,12 @@ } /** - * Calls setButtons(primaryText, secondaryText, null). - */ - public void setButtons(String primaryText, String secondaryText) { - setButtons(primaryText, secondaryText, null); - } - - /** - * Adds one, two, or three buttons to the layout. + * Adds one or two buttons to the layout. * * @param primaryText Text for the primary button. * @param secondaryText Text for the secondary button, or null if there isn't a second button. - * @param tertiaryText Text for the tertiary button, or null if there isn't a third button. */ - public void setButtons(String primaryText, String secondaryText, String tertiaryText) { + public void setButtons(String primaryText, String secondaryText) { if (TextUtils.isEmpty(primaryText)) return; mPrimaryButton = new ButtonCompat(getContext(), mAccentColor); @@ -288,22 +295,9 @@ mSecondaryButton.setOnClickListener(this); mSecondaryButton.setText(secondaryText); mSecondaryButton.setTextColor(mAccentColor); - - if (TextUtils.isEmpty(tertiaryText)) return; - - mTertiaryButton = ButtonCompat.createBorderlessButton(getContext()); - mTertiaryButton.setId(R.id.button_tertiary); - mTertiaryButton.setOnClickListener(this); - mTertiaryButton.setText(tertiaryText); - mTertiaryButton.setPadding(mMargin / 2, mTertiaryButton.getPaddingTop(), mMargin / 2, - mTertiaryButton.getPaddingBottom()); - mTertiaryButton.setTextColor(ApiCompatibilityUtils.getColor(getContext().getResources(), - R.color.infobar_tertiary_button_text)); } - /** - * Adds a custom view to show in the button row in place of the tertiary button. - */ + /** Adds a custom view to show in the button row. */ public void setCustomViewInButtonRow(View view) { mCustomButton = view; } @@ -349,8 +343,7 @@ void onContentCreated() { mMainGroup = new Group(mMessageLayout); - View[] buttons = Group.filterNullViews(mCustomButton, mTertiaryButton, - mSecondaryButton, mPrimaryButton); + View[] buttons = Group.filterNullViews(mCustomButton, mSecondaryButton, mPrimaryButton); if (buttons.length != 0) mButtonGroup = new Group(buttons); // Add the child views in the desired focus order. @@ -597,9 +590,6 @@ // Group is too wide to fit on a single row, so stack the group items vertically. mButtonGroup.setVerticalMode(mMargin / 2, 0); mButtonGroup.gravity = Gravity.FILL_HORIZONTAL; - } else if (mTertiaryButton != null) { - // Align tertiary or custom button at the start and the other buttons at the end. - ((LayoutParams) mTertiaryButton.getLayoutParams()).endMargin += extraWidth; } } } @@ -611,11 +601,7 @@ */ @Override public void onClick(View view) { - // Disable the infobar controls unless the user clicked the tertiary button, which by - // convention is the "learn more" link. - if (view.getId() != R.id.button_tertiary) { - mInfoBarView.setControlsEnabled(false); - } + mInfoBarView.setControlsEnabled(false); if (view.getId() == R.id.infobar_close_button) { mInfoBarView.onCloseButtonClicked(); @@ -623,8 +609,32 @@ mInfoBarView.onButtonClicked(true); } else if (view.getId() == R.id.button_secondary) { mInfoBarView.onButtonClicked(false); - } else if (view.getId() == R.id.button_tertiary) { - mInfoBarView.onLinkClicked(); } } + + /** + * Prepares text to be displayed as the InfoBar's main message, including setting up a + * clickable link if the InfoBar requires it. + */ + private CharSequence prepareMainMessageString() { + SpannableStringBuilder fullString = new SpannableStringBuilder(); + + if (mMessageMainText != null) fullString.append(mMessageMainText); + + // Concatenate the text to display for the link and make it clickable. + if (mMessageLinkText != null) { + if (fullString.length() > 0) fullString.append(" "); + int spanStart = fullString.length(); + + fullString.append(mMessageLinkText); + fullString.setSpan(new ClickableSpan() { + @Override + public void onClick(View view) { + mInfoBarView.onLinkClicked(); + } + }, spanStart, fullString.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + } + + return fullString; + } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageToolbar.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageToolbar.java index 95dad06..4774642 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageToolbar.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageToolbar.java
@@ -43,8 +43,12 @@ protected void onFinishInflate() { mBookmarksButton = initButton(R.id.bookmarks_button, R.drawable.btn_star); mRecentTabsButton = initButton(R.id.recent_tabs_button, R.drawable.btn_recents); - ((TextView) mBookmarksButton.getChildAt(0)).setText(OfflinePageBridge.isEnabled() - ? R.string.offline_pages_ntp_button_name : R.string.ntp_bookmarks); + if (OfflinePageBridge.isEnabled()) { + ((TextView) mBookmarksButton.getChildAt(0)).setText( + R.string.offline_pages_ntp_button_name); + ((TextView) mBookmarksButton.getChildAt(0)).setContentDescription( + getResources().getString(R.string.offline_pages_ntp_button_accessibility)); + } } private ViewGroup initButton(int buttonId, int drawableId) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/signin/OAuth2TokenService.java b/chrome/android/java/src/org/chromium/chrome/browser/signin/OAuth2TokenService.java index 5cdc845..f6a5f73c1 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/signin/OAuth2TokenService.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/signin/OAuth2TokenService.java
@@ -275,10 +275,28 @@ Context context, boolean forceNotifications) { String currentlySignedInAccount = ChromeSigninController.get(context).getSignedInAccountName(); + if (currentlySignedInAccount != null + && isSignedInAccountChanged(context, currentlySignedInAccount)) { + // Set currentlySignedInAccount to null for validation if signed-in account was changed + // (renamed or removed from the device), this will cause all credentials in token + // service be revoked. + // Could only get here during Chrome cold startup. + // After chrome started, SigninHelper and AccountsChangedReceiver will handle account + // change (re-signin or sign out signed-in account). + currentlySignedInAccount = null; + } nativeValidateAccounts(mNativeOAuth2TokenServiceDelegateAndroid, currentlySignedInAccount, forceNotifications); } + private boolean isSignedInAccountChanged(Context context, String signedInAccountName) { + String[] accountNames = getSystemAccountNames(context); + for (String accountName : accountNames) { + if (accountName.equals(signedInAccountName)) return false; + } + return true; + } + /** * Triggers a notification to all observers of the native and Java instance of the * OAuth2TokenService that a refresh token is now available. This may cause observers to retry
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninHelper.java b/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninHelper.java index b00537b..18276cb9 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninHelper.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninHelper.java
@@ -181,7 +181,7 @@ } // Always check for account deleted. - if (!accountExists(syncAccount)) { + if (!accountExists(mContext, syncAccount)) { // It is possible that Chrome got to this point without account // rename notification. Let us signout before doing a rename. // updateAccountRenameData(mContext, new SystemAccountChangeEventChecker()); @@ -284,8 +284,8 @@ }); } - private boolean accountExists(Account account) { - Account[] accounts = AccountManagerHelper.get(mContext).getGoogleAccounts(); + private static boolean accountExists(Context context, Account account) { + Account[] accounts = AccountManagerHelper.get(context).getGoogleAccounts(); for (Account a : accounts) { if (a.equals(account)) { return true; @@ -352,7 +352,8 @@ int newIndex = eventIndex; try { - outerLoop: while (true) { + outerLoop: + while (true) { List<String> nameChanges = checker.getAccountChangeEvents(context, newIndex, newName); @@ -361,8 +362,12 @@ // We have found a rename event of the current account. // We need to check if that account is further renamed. newName = name; - newIndex = 0; // Start from the beginning of the new account. - continue outerLoop; + if (!accountExists(context, AccountManagerHelper.get(context) + .createAccountFromName(newName))) { + newIndex = 0; // Start from the beginning of the new account. + continue outerLoop; + } + break; } }
diff --git a/chrome/android/java/strings/android_chrome_strings.grd b/chrome/android/java/strings/android_chrome_strings.grd index 7790bf3..f1ace95d 100644 --- a/chrome/android/java/strings/android_chrome_strings.grd +++ b/chrome/android/java/strings/android_chrome_strings.grd
@@ -1932,6 +1932,9 @@ <message name="IDS_OFFLINE_PAGES_NTP_BUTTON_NAME" desc="Text for saved pages button on the new tab page [CHAR-LIMIT=20]"> Saved pages </message> + <message name="IDS_OFFLINE_PAGES_NTP_BUTTON_ACCESSIBILITY" desc="Content description for saved pages button on the new tab page."> + Saved pages + </message> <message name="IDS_OFFLINE_PAGES_OPEN_STORAGE_SETTINGS_DIALOG_TEXT" desc="Text of the dialog asking if the user wants to open storage settings to remove files to make space."> Your device storage is full. Please remove other media to make space. </message>
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/BindingManagerIntegrationTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/BindingManagerIntegrationTest.java index e8c11ec..078f8d9 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/BindingManagerIntegrationTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/BindingManagerIntegrationTest.java
@@ -5,6 +5,7 @@ package org.chromium.chrome.browser; import android.content.Context; +import android.test.MoreAsserts; import android.test.suitebuilder.annotation.LargeTest; import android.util.SparseArray; import android.util.SparseBooleanArray; @@ -29,6 +30,7 @@ import org.chromium.content.browser.test.util.CriteriaHelper; import org.chromium.content_public.browser.LoadUrlParams; import org.chromium.ui.base.DeviceFormFactor; +import org.chromium.ui.base.PageTransition; import java.util.concurrent.Callable; @@ -414,6 +416,15 @@ }); } + private int getRenderProcessId(final Tab tab) { + return ThreadUtils.runOnUiThreadBlockingNoException(new Callable<Integer>() { + @Override + public Integer call() throws Exception { + return tab.getContentViewCore().getCurrentRenderProcessId(); + } + }); + } + /** * Ensures correctness of the visibilityDetermined() calls, that would be generally preceded by * setInForeground(), but it can't be guaranteed because they are triggered from different @@ -433,22 +444,16 @@ TabLaunchType.FROM_KEYBOARD, null); }}); ChromeTabUtils.waitForTabPageLoaded(fgTab, TestHttpServerClient.getUrl(FILE_PATH)); - int initialNavigationPid = fgTab.getContentViewCore().getCurrentRenderProcessId(); + int initialNavigationPid = getRenderProcessId(fgTab); // Ensure the following calls happened: // - FG - setInForeground(true) - when the tab is created in the foreground // - DETERMINED - visibilityDetermined() - after the initial navigation is committed assertEquals("FG;DETERMINED;", mBindingManager.getVisibilityCalls(initialNavigationPid)); // Navigate to about:version which requires a different renderer. - getInstrumentation().runOnMainSync(new Runnable() { - @Override - public void run() { - fgTab.loadUrl(new LoadUrlParams(ABOUT_VERSION_PATH)); - } - }); - ChromeTabUtils.waitForTabPageLoaded(fgTab, ABOUT_VERSION_PATH); - int secondNavigationPid = fgTab.getContentViewCore().getCurrentRenderProcessId(); - assertTrue(secondNavigationPid != initialNavigationPid); + loadUrlInTab(ABOUT_VERSION_PATH, PageTransition.LINK, fgTab); + int secondNavigationPid = getRenderProcessId(fgTab); + MoreAsserts.assertNotEqual(secondNavigationPid, initialNavigationPid); // Ensure the following calls happened: // - BG - setInForeground(false) - when the renderer is created for uncommited frame // - FG - setInForeground(true) - when the frame is swapped in on commit @@ -458,7 +463,7 @@ mBindingManager.assertIsInForeground(secondNavigationPid); String visibilityCalls = mBindingManager.getVisibilityCalls(secondNavigationPid); assertTrue(visibilityCalls, "BG;FG;DETERMINED;".equals(visibilityCalls) - || "BG;DETERMINED;FG;".equals(visibilityCalls)); + || "BG;DETERMINED;FG;".equals(visibilityCalls)); // Open a tab in the background and load it. final Tab bgTab = ThreadUtils.runOnUiThreadBlockingNoException( @@ -476,7 +481,7 @@ return tab; }}); ChromeTabUtils.waitForTabPageLoaded(bgTab, TestHttpServerClient.getUrl(FILE_PATH)); - int bgNavigationPid = bgTab.getContentViewCore().getCurrentRenderProcessId(); + int bgNavigationPid = getRenderProcessId(bgTab); // Ensure the following calls happened: // - BG - setInForeground(false) - when tab is created in the background // - DETERMINED - visibilityDetermined() - after the navigation is committed
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanelManagerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanelManagerTest.java index 5fbbdc8..237c2ea 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanelManagerTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanelManagerTest.java
@@ -7,14 +7,18 @@ import android.content.Context; import android.test.InstrumentationTestCase; import android.test.suitebuilder.annotation.SmallTest; +import android.view.ViewGroup; +import android.widget.LinearLayout; import org.chromium.base.test.util.Feature; import org.chromium.chrome.browser.compositor.bottombar.OverlayPanel; import org.chromium.chrome.browser.compositor.bottombar.OverlayPanel.StateChangeReason; import org.chromium.chrome.browser.compositor.bottombar.OverlayPanelContent; +import org.chromium.chrome.browser.compositor.bottombar.OverlayPanelHost; import org.chromium.chrome.browser.compositor.bottombar.OverlayPanelManager; import org.chromium.chrome.browser.compositor.bottombar.OverlayPanelManager.PanelPriority; import org.chromium.chrome.browser.compositor.layouts.LayoutUpdateHost; +import org.chromium.ui.resources.dynamics.DynamicResourceLoader; /** * Class responsible for testing the OverlayPanelManager. @@ -32,6 +36,9 @@ private PanelPriority mPriority; private boolean mCanBeSuppressed; + private OverlayPanelHost mHost; + private ViewGroup mContainerView; + private DynamicResourceLoader mResourceLoader; public MockOverlayPanel(Context context, LayoutUpdateHost updateHost, OverlayPanelManager panelManager, PanelPriority priority, @@ -42,6 +49,36 @@ } @Override + public void setHost(OverlayPanelHost host) { + super.setHost(host); + mHost = host; + } + + public OverlayPanelHost getHost() { + return mHost; + } + + @Override + public void setContainerView(ViewGroup container) { + super.setContainerView(container); + mContainerView = container; + } + + public ViewGroup getContainerView() { + return mContainerView; + } + + @Override + public void setDynamicResourceLoader(DynamicResourceLoader loader) { + super.setDynamicResourceLoader(loader); + mResourceLoader = loader; + } + + public DynamicResourceLoader getDynamicResourceLoader() { + return mResourceLoader; + } + + @Override public OverlayPanelContent createNewOverlayPanelContent() { return new MockOverlayPanelContent(); } @@ -185,4 +222,33 @@ assertTrue(panelManager.getActivePanel() == null); } + + @SmallTest + @Feature({"OverlayPanel"}) + public void testLatePanelGetsNecessaryVars() { + Context context = getInstrumentation().getTargetContext(); + + OverlayPanelManager panelManager = new OverlayPanelManager(); + MockOverlayPanel earlyPanel = + new MockOverlayPanel(context, null, panelManager, PanelPriority.MEDIUM, true); + + OverlayPanelHost host = new OverlayPanelHost() { + @Override + public void hideLayout(boolean immediately) { + // Intentionally do nothing. + } + }; + + // Set necessary vars before any other panels are registered in the manager. + panelManager.setPanelHost(host); + panelManager.setContainerView(new LinearLayout(getInstrumentation().getTargetContext())); + panelManager.setDynamicResourceLoader(new DynamicResourceLoader(0, null)); + + MockOverlayPanel latePanel = + new MockOverlayPanel(context, null, panelManager, PanelPriority.MEDIUM, true); + + assertTrue(earlyPanel.getHost() == latePanel.getHost()); + assertTrue(earlyPanel.getContainerView() == latePanel.getContainerView()); + assertTrue(earlyPanel.getDynamicResourceLoader() == latePanel.getDynamicResourceLoader()); + } }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/signin/SigninHelperTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/signin/SigninHelperTest.java index 7664a38..a3ec759a 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/signin/SigninHelperTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/signin/SigninHelperTest.java
@@ -4,12 +4,16 @@ package org.chromium.chrome.browser.signin; +import android.accounts.Account; import android.content.Context; import android.test.InstrumentationTestCase; import android.test.suitebuilder.annotation.SmallTest; import org.chromium.base.test.util.AdvancedMockContext; +import org.chromium.sync.signin.AccountManagerHelper; import org.chromium.sync.signin.ChromeSigninController; +import org.chromium.sync.test.util.AccountHolder; +import org.chromium.sync.test.util.MockAccountManager; import java.util.ArrayList; import java.util.HashMap; @@ -20,6 +24,7 @@ * Instrumentation tests for {@link SigninHelper}. */ public class SigninHelperTest extends InstrumentationTestCase { + private MockAccountManager mAccountManager; private AdvancedMockContext mContext; private MockChangeEventChecker mEventChecker; @@ -27,6 +32,10 @@ public void setUp() { mContext = new AdvancedMockContext(getInstrumentation().getTargetContext()); mEventChecker = new MockChangeEventChecker(); + + // Mock out the account manager on the device. + mAccountManager = new MockAccountManager(mContext, getInstrumentation().getContext()); + AccountManagerHelper.overrideAccountManagerHelperForTests(mContext, mAccountManager); } @SmallTest @@ -105,6 +114,22 @@ assertEquals("D", getNewSignedInAccountName()); } + @SmallTest + public void testLoopedAccountRename() { + setSignedInAccountName("A"); + mEventChecker.insertRenameEvent("Z", "Y"); // Unrelated. + mEventChecker.insertRenameEvent("A", "B"); + mEventChecker.insertRenameEvent("Y", "X"); // Unrelated. + mEventChecker.insertRenameEvent("B", "C"); + mEventChecker.insertRenameEvent("C", "D"); + mEventChecker.insertRenameEvent("D", "A"); // Looped. + Account account = AccountManagerHelper.createAccountFromName("D"); + AccountHolder accountHolder = AccountHolder.create().account(account).build(); + mAccountManager.addAccountHolderExplicitly(accountHolder); + SigninHelper.updateAccountRenameData(mContext, mEventChecker); + assertEquals("D", getNewSignedInAccountName()); + } + private void setSignedInAccountName(String account) { ChromeSigninController.get(mContext).setSignedInAccountName(account); }
diff --git a/chrome/app/chromeos_strings.grdp b/chrome/app/chromeos_strings.grdp index dc60b6f9..9fe452b 100644 --- a/chrome/app/chromeos_strings.grdp +++ b/chrome/app/chromeos_strings.grdp
@@ -4851,6 +4851,12 @@ <message name="IDS_STATUSBAR_LAYOUT_USA_INTERNATIONAL" desc="In the language menu button, this shows the input mode [US international keyboard]."> US international </message> + <message name="IDS_STATUSBAR_LAYOUT_USA_WORKMAN" desc="In the language menu button, this shows the input mode [US Workman keyboard]."> + US Workman + </message> + <message name="IDS_STATUSBAR_LAYOUT_USA_WORKMAN_INTERNATIONAL" desc="In the language menu button, this shows the input mode [US Workman international keyboard]."> + US Workman international + </message> <message name="IDS_STATUSBAR_LAYOUT_LITHUANIA" desc="In the language menu button, this shows the input mode [Lithuanian keyboard]."> Lithuanian </message> @@ -5155,6 +5161,12 @@ <message name="IDS_IME_NAME_KEYBOARD_US_INTERNATIONAL" desc="The input method name shows in system tray menu, this shows [US International keyboard]."> US International keyboard </message> + <message name="IDS_IME_NAME_KEYBOARD_US_WORKMAN" desc="The input method name shows in system tray menu, this shows [US Workman keyboard]."> + US Workman keyboard + </message> + <message name="IDS_IME_NAME_KEYBOARD_US_WORKMAN_INTERNATIONAL" desc="The input method name shows in system tray menu, this shows [US Workman international keyboard]."> + US Workman international keyboard + </message> <message name="IDS_IME_NAME_KEYBOARD_US" desc="The input method name shows in system tray menu, this shows [US keyboard]."> US keyboard </message>
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd index 759aaf40a..58b6106 100644 --- a/chrome/app/generated_resources.grd +++ b/chrome/app/generated_resources.grd
@@ -9658,9 +9658,6 @@ <message name="IDS_SAFE_BROWSING_PRIVACY_POLICY_PAGE" desc="Label for the link to SafeBrowsing Privacy policy page"> Privacy policy </message> - <message name="IDS_SAFE_BROWSING_PRIVACY_POLICY_URL" translateable="false"> - https://www.google.com/chrome/browser/privacy/whitepaper.html#malware - </message> <message name="IDS_SAFE_BROWSING_MALWARE_REPORTING_AGREE" desc="SafeBrowsing Malware v2 Details label next to checkbox"> Automatically report details of possible security incidents to Google. <ph name="PRIVACY_PAGE_LINK">$1</ph> </message>
diff --git a/chrome/app_shim/BUILD.gn b/chrome/app_shim/BUILD.gn index c4c164b..74bca93 100644 --- a/chrome/app_shim/BUILD.gn +++ b/chrome/app_shim/BUILD.gn
@@ -11,7 +11,7 @@ ] deps = [ - "//chrome/common:app_mode_app_support", "//chrome:strings", + "//chrome/common:app_mode_app_support", ] }
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn index e1d05f9..f93e73b 100644 --- a/chrome/browser/BUILD.gn +++ b/chrome/browser/BUILD.gn
@@ -137,13 +137,13 @@ "//components/metrics:net", "//components/metrics:profiler", "//components/metrics:profiler_content", - "//components/metrics/proto:proto", "//components/metrics:ui", + "//components/metrics/proto:proto", "//components/metrics_services_manager", "//components/mime_util", "//components/navigation_metrics", - "//components/ntp_snippets", "//components/network_time", + "//components/ntp_snippets", "//components/offline_pages", "//components/omnibox/browser", "//components/os_crypt", @@ -180,9 +180,9 @@ "//components/variations", "//components/variations/net", "//components/variations/service", + "//components/web_resource", "//components/webdata/common", "//components/webdata_services", - "//components/web_resource", "//content/public/browser", "//content/public/common", "//courgette:courgette_lib", @@ -194,8 +194,8 @@ "//sync", "//third_party/cacheinvalidation", "//third_party/icu", - "//third_party/libxml", "//third_party/libjingle", + "//third_party/libxml", "//third_party/widevine/cdm:version_h", "//third_party/zlib", "//third_party/zlib:minizip", @@ -205,9 +205,9 @@ "//ui/gfx", "//ui/gfx/geometry", "//ui/message_center", + "//ui/resources", "//ui/shell_dialogs", "//ui/strings", - "//ui/resources", ] data_deps = [] @@ -657,8 +657,8 @@ ".", "//chrome") deps += [ - "//printing", "//components/printing/browser", + "//printing", ] if (is_win) { @@ -738,9 +738,9 @@ "//third_party/libaddressinput:util", ] deps -= [ - "//third_party/libaddressinput", "//components/storage_monitor", "//components/web_modal", + "//third_party/libaddressinput", ] defines += [ "ENABLE_DATA_REDUCTION_PROXY_DEBUGGING" ] @@ -1079,6 +1079,7 @@ ] deps = [ "//base:prefs_test_support", + "//chrome/app/theme:theme_resources", "//chrome/browser", "//chrome/common", "//chrome/common/safe_browsing:proto", @@ -1089,7 +1090,6 @@ "//components/syncable_prefs:test_support", "//components/user_prefs/tracked:user_prefs_tracked_test_support", "//content/test:test_support", - "//chrome/app/theme:theme_resources", "//net:test_support", "//skia", "//testing/gmock",
diff --git a/chrome/browser/android/cookies/cookies_fetcher.cc b/chrome/browser/android/cookies/cookies_fetcher.cc index 29a6a64..1db0944 100644 --- a/chrome/browser/android/cookies/cookies_fetcher.cc +++ b/chrome/browser/android/cookies/cookies_fetcher.cc
@@ -159,12 +159,14 @@ // TODO(estark): Remove kEnableExperimentalWebPlatformFeatures check // when we decide whether to ship cookie // prefixes. https://crbug.com/541511 + bool experimental_features_enabled = + base::CommandLine::ForCurrentProcess()->HasSwitch( + switches::kEnableExperimentalWebPlatformFeatures); monster->SetCookieWithDetailsAsync( cookie.Source(), cookie.Name(), cookie.Value(), cookie.Domain(), cookie.Path(), cookie.ExpiryDate(), cookie.IsSecure(), cookie.IsHttpOnly(), cookie.IsFirstPartyOnly(), - base::CommandLine::ForCurrentProcess()->HasSwitch( - switches::kEnableExperimentalWebPlatformFeatures), + experimental_features_enabled, experimental_features_enabled, cookie.Priority(), cb); }
diff --git a/chrome/browser/android/data_usage/data_use_tab_model.cc b/chrome/browser/android/data_usage/data_use_tab_model.cc index bfbebad..dea0659f 100644 --- a/chrome/browser/android/data_usage/data_use_tab_model.cc +++ b/chrome/browser/android/data_usage/data_use_tab_model.cc
@@ -73,11 +73,11 @@ DCHECK(thread_checker_.CalledOnValidThread()); DCHECK(IsValidTabID(tab_id)); - // TODO(rajendrant): implementation to use package. switch (transition) { case TRANSITION_OMNIBOX_SEARCH: case TRANSITION_FROM_EXTERNAL_APP: { // Enter events. + bool start_tracking = false; std::string label; TabEntryMap::const_iterator tab_entry_iterator = active_tabs_.find(tab_id); @@ -85,13 +85,21 @@ tab_entry_iterator->second.IsTrackingDataUse()) { break; } - if (data_use_observer_->Matches(url, &label)) { - // TODO(rajendrant): Need to handle scenarios where these labels change - // in the middle of a tab session. Should |data_use_observer_| notify us - // about a cleanup. What happens to currently active tab sessions. - DCHECK(!label.empty()); - StartTrackingDataUse(tab_id, label); + if (transition == TRANSITION_FROM_EXTERNAL_APP) { + // Package name should match, for transitions from external app. + if (!package.empty() && + data_use_observer_->MatchesAppPackageName(package, &label)) { + DCHECK(!label.empty()); + start_tracking = true; + } } + if (!start_tracking && !url.is_empty() && + data_use_observer_->Matches(url, &label)) { + DCHECK(!label.empty()); + start_tracking = true; + } + if (start_tracking) + StartTrackingDataUse(tab_id, label); break; }
diff --git a/chrome/browser/android/data_usage/data_use_tab_model_unittest.cc b/chrome/browser/android/data_usage/data_use_tab_model_unittest.cc index baef615..70777f6 100644 --- a/chrome/browser/android/data_usage/data_use_tab_model_unittest.cc +++ b/chrome/browser/android/data_usage/data_use_tab_model_unittest.cc
@@ -15,6 +15,10 @@ #include "base/time/time.h" #include "chrome/browser/android/data_usage/external_data_use_observer.h" #include "chrome/browser/android/data_usage/tab_data_use_entry.h" +#include "components/data_usage/core/data_use.h" +#include "components/data_usage/core/data_use_aggregator.h" +#include "components/data_usage/core/data_use_amortizer.h" +#include "components/data_usage/core/data_use_annotator.h" #include "net/base/network_change_notifier.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -73,13 +77,18 @@ protected: void SetUp() override { - // TODO(rajendrant): Create a mock class for ExternalDataUseObserver to - // spoof the Matches call and test the OnNavigationEvent. - data_use_tab_model_.reset( - new DataUseTabModelNowTest(nullptr, task_runner_.get())); - } + data_use_aggregator_.reset(new data_usage::DataUseAggregator( + scoped_ptr<data_usage::DataUseAnnotator>(), + scoped_ptr<data_usage::DataUseAmortizer>())); + data_use_observer_.reset(new ExternalDataUseObserver( + data_use_aggregator_.get(), message_loop_.task_runner().get(), + message_loop_.task_runner().get())); + data_use_tab_model_ = new DataUseTabModelNowTest( + data_use_observer_.get(), message_loop_.task_runner().get()); - base::SingleThreadTaskRunner* task_runner() { return task_runner_.get(); } + // |data_use_tab_model_| will be owned by |data_use_observer_|. + data_use_observer_->data_use_tab_model_.reset(data_use_tab_model_); + } // Returns true if tab entry for |tab_id| exists in |active_tabs_|. bool IsTabEntryExists(int32_t tab_id) const { @@ -151,8 +160,20 @@ data_use_tab_model_->EndTrackingDataUse(tab_id); } - scoped_refptr<base::SingleThreadTaskRunner> task_runner_; - scoped_ptr<DataUseTabModelNowTest> data_use_tab_model_; + void RegisterURLRegexesInDataUseObserver( + const std::vector<std::string>& app_package_names, + const std::vector<std::string>& domain_regexes, + const std::vector<std::string>& labels) { + data_use_observer_->RegisterURLRegexes(app_package_names, domain_regexes, + labels); + } + + scoped_ptr<data_usage::DataUseAggregator> data_use_aggregator_; + scoped_ptr<ExternalDataUseObserver> data_use_observer_; + + // Pointer to the tab model within and owned by ExternalDataUseObserver. + DataUseTabModelNowTest* data_use_tab_model_; + base::MessageLoop message_loop_; }; @@ -465,6 +486,163 @@ base::TimeDelta::FromMinutes(10).InMilliseconds(), 1); } +// Tests that Enter navigation events start tracking the tab entry. +TEST_F(DataUseTabModelTest, NavigationEnterEvent) { + std::vector<std::string> app_package_names, domain_regexes, labels; + + // Matching rule with app package name. + app_package_names.push_back("com.google.package.foo"); + domain_regexes.push_back(std::string()); + labels.push_back(kTestLabel1); + + // Matching rule with regex. + app_package_names.push_back(std::string()); + domain_regexes.push_back("http://foo.com/"); + labels.push_back(kTestLabel2); + + RegisterURLRegexesInDataUseObserver(app_package_names, domain_regexes, + labels); + + ExpectTabEntrySize(TabEntrySize::ZERO); + + data_use_tab_model_->OnNavigationEvent( + kTabID1, DataUseTabModel::TRANSITION_FROM_EXTERNAL_APP, GURL(), + "com.google.package.foo"); + ExpectTabEntrySize(TabEntrySize::ONE); + EXPECT_TRUE(IsTrackingDataUse(kTabID1)); + ExpectDataUseLabel(kTabID1, kTestLabel1); + + data_use_tab_model_->OnNavigationEvent( + kTabID2, DataUseTabModel::TRANSITION_OMNIBOX_SEARCH, + GURL("http://foo.com"), std::string()); + ExpectTabEntrySize(TabEntrySize::TWO); + EXPECT_TRUE(IsTrackingDataUse(kTabID2)); + ExpectDataUseLabel(kTabID2, kTestLabel2); +} + +// Tests that a navigation event with empty url and empty package name does not +// start tracking. +TEST_F(DataUseTabModelTest, EmptyNavigationEvent) { + ExpectTabEntrySize(TabEntrySize::ZERO); + + RegisterURLRegexesInDataUseObserver( + std::vector<std::string>(1, std::string()), + std::vector<std::string>(1, "http://foo.com/"), + std::vector<std::string>(1, kTestLabel1)); + + data_use_tab_model_->OnNavigationEvent( + kTabID1, DataUseTabModel::TRANSITION_FROM_EXTERNAL_APP, GURL(), + std::string()); + EXPECT_FALSE(IsTrackingDataUse(kTabID1)); + + data_use_tab_model_->OnNavigationEvent( + kTabID1, DataUseTabModel::TRANSITION_OMNIBOX_SEARCH, GURL(), + std::string()); + EXPECT_FALSE(IsTrackingDataUse(kTabID1)); + ExpectTabEntrySize(TabEntrySize::ZERO); +} + +// Tests that Exit navigation event ends the tracking. +TEST_F(DataUseTabModelTest, NavigationEnterAndExitEvent) { + std::vector<std::string> app_package_names, domain_regexes, labels; + + app_package_names.push_back(std::string()); + domain_regexes.push_back("http://foo.com/"); + labels.push_back(kTestLabel2); + + RegisterURLRegexesInDataUseObserver(app_package_names, domain_regexes, + labels); + + data_use_tab_model_->OnNavigationEvent( + kTabID1, DataUseTabModel::TRANSITION_OMNIBOX_SEARCH, + GURL("http://foo.com/"), std::string()); + ExpectTabEntrySize(TabEntrySize::ONE); + EXPECT_TRUE(IsTrackingDataUse(kTabID1)); + + data_use_tab_model_->OnNavigationEvent( + kTabID1, DataUseTabModel::TRANSITION_FROM_NAVSUGGEST, GURL(), + std::string()); + EXPECT_FALSE(IsTrackingDataUse(kTabID1)); +} + +// Tests that any of the Enter transition events start the tracking. +TEST_F(DataUseTabModelTest, AllNavigationEnterEvents) { + const struct { + DataUseTabModel::TransitionType transition; + std::string url; + std::string package; + std::string expect_label; + } all_enter_transition_tests[] = { + {DataUseTabModel::TRANSITION_FROM_EXTERNAL_APP, std::string(), + "com.google.package.foo", kTestLabel1}, + {DataUseTabModel::TRANSITION_FROM_EXTERNAL_APP, "http://foo.com", + "com.google.package.nomatch", kTestLabel2}, + {DataUseTabModel::TRANSITION_OMNIBOX_SEARCH, "http://foo.com", + std::string(), kTestLabel2}, + }; + std::vector<std::string> app_package_names, domain_regexes, labels; + int32_t tab_id = 1; + + app_package_names.push_back("com.google.package.foo"); + domain_regexes.push_back(std::string()); + labels.push_back(kTestLabel1); + app_package_names.push_back(std::string()); + domain_regexes.push_back("http://foo.com/"); + labels.push_back(kTestLabel2); + + RegisterURLRegexesInDataUseObserver(app_package_names, domain_regexes, + labels); + + for (auto test : all_enter_transition_tests) { + EXPECT_FALSE(IsTrackingDataUse(tab_id)); + ExpectEmptyDataUseLabel(tab_id); + + // Tracking should start. + data_use_tab_model_->OnNavigationEvent(tab_id, test.transition, + GURL(test.url), test.package); + + EXPECT_TRUE(IsTrackingDataUse(tab_id)); + ExpectDataUseLabel(tab_id, test.expect_label); + ExpectTabEntrySize(tab_id); + ++tab_id; + } +} + +// Tests that any of the Exit transition events end the tracking. +TEST_F(DataUseTabModelTest, AllNavigationExitEvents) { + DataUseTabModel::TransitionType all_exit_transitions[] = { + DataUseTabModel::TRANSITION_TO_EXTERNAL_APP, + DataUseTabModel::TRANSITION_FROM_NAVSUGGEST, + DataUseTabModel::TRANSITION_OMNIBOX_NAVIGATION, + DataUseTabModel::TRANSITION_BOOKMARK, + DataUseTabModel::TRANSITION_HISTORY_ITEM}; + std::vector<std::string> app_package_names, domain_regexes, labels; + int32_t tab_id = 1; + + app_package_names.push_back(std::string()); + domain_regexes.push_back("http://foo.com/"); + labels.push_back(kTestLabel1); + + RegisterURLRegexesInDataUseObserver(app_package_names, domain_regexes, + labels); + + for (auto exit_transition : all_exit_transitions) { + EXPECT_FALSE(IsTrackingDataUse(tab_id)); + data_use_tab_model_->OnNavigationEvent( + tab_id, DataUseTabModel::TRANSITION_OMNIBOX_SEARCH, + GURL("http://foo.com"), std::string()); + EXPECT_TRUE(IsTrackingDataUse(tab_id)); + + // Tracking should end. + data_use_tab_model_->OnNavigationEvent(tab_id, exit_transition, GURL(), + std::string()); + + EXPECT_FALSE(IsTrackingDataUse(tab_id)); + ExpectTabEntrySize(tab_id); + ++tab_id; + } +} + } // namespace android } // namespace chrome
diff --git a/chrome/browser/android/data_usage/external_data_use_observer.cc b/chrome/browser/android/data_usage/external_data_use_observer.cc index 65283e0..aeaee32 100644 --- a/chrome/browser/android/data_usage/external_data_use_observer.cc +++ b/chrome/browser/android/data_usage/external_data_use_observer.cc
@@ -351,14 +351,14 @@ for (size_t i = 0; i < domain_path_regex.size(); ++i) { const std::string& url_regex = domain_path_regex[i]; - if (url_regex.empty()) + if (url_regex.empty() && app_package_name[i].empty()) continue; scoped_ptr<re2::RE2> pattern(new re2::RE2(url_regex, options)); if (!pattern->ok()) continue; DCHECK(!label[i].empty()); - matching_rules_.push_back( - new MatchingRule(app_package_name[i], pattern.Pass(), label[i])); + matching_rules_.push_back(make_scoped_ptr( + new MatchingRule(app_package_name[i], pattern.Pass(), label[i]))); removed_matching_rule_labels.erase(label[i]); } @@ -385,7 +385,7 @@ if (!gurl.is_valid() || gurl.is_empty()) return false; - for (const auto* matching_rule : matching_rules_) { + for (const auto& matching_rule : matching_rules_) { const re2::RE2* pattern = matching_rule->pattern(); if (re2::RE2::FullMatch(gurl.spec(), *pattern)) { *label = matching_rule->label(); @@ -405,7 +405,7 @@ if (app_package_name.empty()) return false; - for (const auto* matching_rule : matching_rules_) { + for (const auto& matching_rule : matching_rules_) { if (app_package_name == matching_rule->app_package_name()) { *label = matching_rule->label(); return true;
diff --git a/chrome/browser/android/data_usage/external_data_use_observer.h b/chrome/browser/android/data_usage/external_data_use_observer.h index deecd5da..1a2b5b2 100644 --- a/chrome/browser/android/data_usage/external_data_use_observer.h +++ b/chrome/browser/android/data_usage/external_data_use_observer.h
@@ -18,7 +18,6 @@ #include "base/macros.h" #include "base/memory/ref_counted.h" #include "base/memory/scoped_ptr.h" -#include "base/memory/scoped_vector.h" #include "base/memory/weak_ptr.h" #include "base/single_thread_task_runner.h" #include "base/thread_task_runner_handle.h" @@ -102,6 +101,7 @@ } private: + friend class DataUseTabModelTest; friend class ExternalDataUseObserverTest; FRIEND_TEST_ALL_PREFIXES(ExternalDataUseObserverTest, SingleRegex); FRIEND_TEST_ALL_PREFIXES(ExternalDataUseObserverTest, TwoRegex); @@ -285,7 +285,7 @@ bool submit_data_report_pending_; // Contains matching rules. - ScopedVector<MatchingRule> matching_rules_; + std::vector<scoped_ptr<MatchingRule>> matching_rules_; // Buffered data reports that need to be submitted to the Java data use // observer.
diff --git a/chrome/browser/android/data_usage/external_data_use_observer_unittest.cc b/chrome/browser/android/data_usage/external_data_use_observer_unittest.cc index 36d58732..6e34d45 100644 --- a/chrome/browser/android/data_usage/external_data_use_observer_unittest.cc +++ b/chrome/browser/android/data_usage/external_data_use_observer_unittest.cc
@@ -8,7 +8,6 @@ #include <vector> #include "base/memory/scoped_ptr.h" -#include "base/memory/scoped_vector.h" #include "base/metrics/field_trial.h" #include "base/run_loop.h" #include "base/strings/string_number_conversions.h" @@ -26,6 +25,19 @@ #include "testing/gtest/include/gtest/gtest.h" #include "url/gurl.h" +namespace { + +std::vector<const data_usage::DataUse*> ToConstDataUseVector( + std::vector<scoped_ptr<data_usage::DataUse>>& data_use_vector) { + std::vector<const data_usage::DataUse*> const_vector; + const_vector.reserve(data_use_vector.size()); + for (auto& data_use : data_use_vector) + const_vector.push_back(data_use.get()); + return const_vector; +} + +} // namespace + namespace chrome { namespace android { @@ -343,7 +355,7 @@ const int bytes_downloaded = 1000; const int bytes_uploaded = 100; - ScopedVector<data_usage::DataUse> data_use_vector; + std::vector<scoped_ptr<data_usage::DataUse>> data_use_vector; // Push more entries than the buffer size. Buffer size should not be exceeded. for (size_t i = 0; i < max_buffer_size * 5; ++i) { scoped_ptr<data_usage::DataUse> data_use(new data_usage::DataUse( @@ -353,10 +365,8 @@ data_use_vector.push_back(data_use.Pass()); } - std::vector<const data_usage::DataUse*> const_sequence( - data_use_vector.begin(), data_use_vector.end()); - - external_data_use_observer()->OnDataUse(const_sequence); + external_data_use_observer()->OnDataUse( + ToConstDataUseVector(data_use_vector)); EXPECT_LE(0, external_data_use_observer()->total_bytes_buffered_); // One report will be consumed. Verify that total buffered bytes is computed @@ -386,7 +396,7 @@ const size_t num_iterations = ExternalDataUseObserver::kMaxBufferSize * 5; - ScopedVector<data_usage::DataUse> data_use_vector; + std::vector<scoped_ptr<data_usage::DataUse>> data_use_vector; for (size_t i = 0; i < num_iterations; ++i) { scoped_ptr<data_usage::DataUse> data_use_foo(new data_usage::DataUse( GURL("http://www.google.com/#q=abc"), base::TimeTicks::Now(), GURL(), 0, @@ -407,10 +417,8 @@ data_use_vector.push_back(data_use_baz.Pass()); } - std::vector<const data_usage::DataUse*> const_sequence( - data_use_vector.begin(), data_use_vector.end()); - - external_data_use_observer()->OnDataUse(const_sequence); + external_data_use_observer()->OnDataUse( + ToConstDataUseVector(data_use_vector)); EXPECT_EQ(2U, external_data_use_observer()->buffered_data_reports_.size()); EXPECT_EQ(static_cast<int64_t>(num_iterations * 1), @@ -454,7 +462,7 @@ const size_t num_iterations = ExternalDataUseObserver::kMaxBufferSize * 5; - ScopedVector<data_usage::DataUse> data_use_vector; + std::vector<scoped_ptr<data_usage::DataUse>> data_use_vector; for (size_t i = 0; i < num_iterations; ++i) { scoped_ptr<data_usage::DataUse> data_use_foo(new data_usage::DataUse( GURL("http://www.google.com/#q=abc"), base::TimeTicks::Now(), GURL(), 0, @@ -462,15 +470,12 @@ data_use_vector.push_back(data_use_foo.Pass()); } - std::vector<const data_usage::DataUse*> const_sequence( - data_use_vector.begin(), data_use_vector.end()); - int64_t start_timestamp = 0; int64_t end_timestamp = 1; - for (auto it : const_sequence) { - const data_usage::DataUse* data_usage(it); + for (const auto& data_usage : data_use_vector) { external_data_use_observer()->BufferDataUseReport( - data_usage, "foo_label", base::Time::FromDoubleT(start_timestamp++), + data_usage.get(), "foo_label", + base::Time::FromDoubleT(start_timestamp++), base::Time::FromDoubleT(end_timestamp++)); } EXPECT_EQ(1U, external_data_use_observer()->buffered_data_reports_.size()); @@ -656,17 +661,15 @@ external_data_use_observer()->data_use_report_min_bytes_ / 1024; for (size_t i = 0; i < num_iterations; ++i) { - ScopedVector<data_usage::DataUse> data_use_vector; + std::vector<scoped_ptr<data_usage::DataUse>> data_use_vector; scoped_ptr<data_usage::DataUse> data_use_foo(new data_usage::DataUse( GURL("http://www.google.com/#q=abc"), base::TimeTicks::Now(), GURL(), 0, net::NetworkChangeNotifier::CONNECTION_UNKNOWN, "mccmnc_foo", 1024, 0)); data_use_vector.push_back(data_use_foo.Pass()); - std::vector<const data_usage::DataUse*> const_sequence( - data_use_vector.begin(), data_use_vector.end()); - - external_data_use_observer()->OnDataUse(const_sequence); + external_data_use_observer()->OnDataUse( + ToConstDataUseVector(data_use_vector)); if (i != num_iterations - 1) { // Total buffered bytes is less than the minimum threshold. Data use // report should not be send.
diff --git a/chrome/browser/browser_shutdown.cc b/chrome/browser/browser_shutdown.cc index 3e28ea2..9062d30 100644 --- a/chrome/browser/browser_shutdown.cc +++ b/chrome/browser/browser_shutdown.cc
@@ -19,7 +19,6 @@ #include "base/strings/stringprintf.h" #include "base/threading/thread.h" #include "base/time/time.h" -#include "base/trace_event/trace_event.h" #include "chrome/browser/about_flags.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/lifetime/application_lifetime.h" @@ -34,6 +33,7 @@ #include "components/tracing/tracing_switches.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/render_process_host.h" +#include "content/public/browser/tracing_controller.h" #if defined(OS_WIN) #include "chrome/browser/browser_util_win.h" @@ -354,9 +354,9 @@ if (command_line.HasSwitch(switches::kTraceShutdown)) { base::trace_event::TraceConfig trace_config( command_line.GetSwitchValueASCII(switches::kTraceShutdown), ""); - base::trace_event::TraceLog::GetInstance()->SetEnabled( + content::TracingController::GetInstance()->StartTracing( trace_config, - base::trace_event::TraceLog::RECORDING_MODE); + content::TracingController::StartTracingDoneCallback()); } TRACE_EVENT0("shutdown", "StartShutdownTracing"); }
diff --git a/chrome/browser/browsing_data/autofill_counter.cc b/chrome/browser/browsing_data/autofill_counter.cc index 0b0633cc..b22d2dc 100644 --- a/chrome/browser/browsing_data/autofill_counter.cc +++ b/chrome/browser/browsing_data/autofill_counter.cc
@@ -56,8 +56,19 @@ // and last modified time) lies within the deletion time range. Otherwise, // it only decreases the count property, but always to a nonzero value, // and the suggestion is retained. Therefore here as well, we must only count - // the entry that are entirely contained in [start, base::Time::Max()). - suggestions_query_ = web_data_service_->GetCountOfEntriesContainedBetween( + // the entries that are entirely contained in [start, base::Time::Max()). + // Further, many of these entries may contain the same values, as they are + // simply the same data point entered on different forms. For example, + // [name, value] pairs such as: + // ["mail", "example@example.com"] + // ["email", "example@example.com"] + // ["e-mail", "example@example.com"] + // are stored as three separate entries, but from the user's perspective, + // they constitute the same suggestion - "my email". Therefore, for the final + // output, we will consider all entries with the same value as one suggestion, + // and increment the counter only if all entries with the given value are + // contained in the interval [start, base::Time::Max()). + suggestions_query_ = web_data_service_->GetCountOfValuesContainedBetween( start, base::Time::Max(), this); // Count the credit cards.
diff --git a/chrome/browser/browsing_data/cache_counter.cc b/chrome/browser/browsing_data/cache_counter.cc index 06f4cd6a..31aea22 100644 --- a/chrome/browser/browsing_data/cache_counter.cc +++ b/chrome/browser/browsing_data/cache_counter.cc
@@ -8,7 +8,8 @@ #include "net/base/net_errors.h" CacheCounter::CacheCounter() : pref_name_(prefs::kDeleteCache), - pending_(false) { + pending_(false), + weak_ptr_factory_(this) { } CacheCounter::~CacheCounter() { @@ -29,7 +30,7 @@ base::Time(), base::Time::Max())->Count( base::Bind(&CacheCounter::OnCacheSizeCalculated, - base::Unretained(this))); + weak_ptr_factory_.GetWeakPtr())); pending_ = true; }
diff --git a/chrome/browser/browsing_data/cache_counter.h b/chrome/browser/browsing_data/cache_counter.h index 3bccb93..0e3a26fe 100644 --- a/chrome/browser/browsing_data/cache_counter.h +++ b/chrome/browser/browsing_data/cache_counter.h
@@ -5,6 +5,7 @@ #ifndef CHROME_BROWSER_BROWSING_DATA_CACHE_COUNTER_H_ #define CHROME_BROWSER_BROWSING_DATA_CACHE_COUNTER_H_ +#include "base/memory/weak_ptr.h" #include "chrome/browser/browsing_data/browsing_data_counter.h" class CacheCounter: public BrowsingDataCounter { @@ -22,6 +23,8 @@ const std::string pref_name_; bool pending_; + base::WeakPtrFactory<CacheCounter> weak_ptr_factory_; + void Count() override; void OnCacheSizeCalculated(int64 bytes); };
diff --git a/chrome/browser/browsing_data/history_counter.cc b/chrome/browser/browsing_data/history_counter.cc index 58ede73..00f8b51 100644 --- a/chrome/browser/browsing_data/history_counter.cc +++ b/chrome/browser/browsing_data/history_counter.cc
@@ -26,7 +26,8 @@ web_counting_finished_(false), testing_web_history_service_(nullptr), sync_service_(nullptr), - history_sync_enabled_(false) { + history_sync_enabled_(false), + weak_ptr_factory_(this) { } HistoryCounter::~HistoryCounter() { @@ -72,7 +73,7 @@ GetPeriodStart(), base::Time::Max(), base::Bind(&HistoryCounter::OnGetLocalHistoryCount, - base::Unretained(this)), + weak_ptr_factory_.GetWeakPtr()), &cancelable_task_tracker_); // If the history sync is enabled, test if there is at least one synced item. @@ -102,7 +103,7 @@ base::string16(), options, base::Bind(&HistoryCounter::OnGetWebHistoryCount, - base::Unretained(this))); + weak_ptr_factory_.GetWeakPtr())); // TODO(msramek): Include web history count when there is an API for it. }
diff --git a/chrome/browser/browsing_data/history_counter.h b/chrome/browser/browsing_data/history_counter.h index 026da3a8..3c02096 100644 --- a/chrome/browser/browsing_data/history_counter.h +++ b/chrome/browser/browsing_data/history_counter.h
@@ -5,6 +5,7 @@ #ifndef CHROME_BROWSER_BROWSING_DATA_HISTORY_COUNTER_H_ #define CHROME_BROWSER_BROWSING_DATA_HISTORY_COUNTER_H_ +#include "base/memory/weak_ptr.h" #include "base/task/cancelable_task_tracker.h" #include "base/timer/timer.h" #include "chrome/browser/browsing_data/browsing_data_counter.h" @@ -63,6 +64,8 @@ ProfileSyncService* sync_service_; bool history_sync_enabled_; + base::WeakPtrFactory<HistoryCounter> weak_ptr_factory_; + void Count() override; void OnGetLocalHistoryCount(history::HistoryCountResult result);
diff --git a/chrome/browser/chrome_browser_main.cc b/chrome/browser/chrome_browser_main.cc index da70b6e..5114e39 100644 --- a/chrome/browser/chrome_browser_main.cc +++ b/chrome/browser/chrome_browser_main.cc
@@ -1219,13 +1219,16 @@ #endif #if defined(ENABLE_EXTENSIONS) - // Try to compute this early on another thread so that we don't spend time - // during profile load initializing the extensions APIs. - BrowserThread::PostTask( - BrowserThread::FILE_USER_BLOCKING, - FROM_HERE, - base::Bind( - base::IgnoreResult(&extensions::FeatureProvider::GetAPIFeatures))); + if (!variations::GetVariationParamValue( + "LightSpeed", "EarlyInitStartup").empty()) { + // Try to compute this early on another thread so that we don't spend time + // during profile load initializing the extensions APIs. + BrowserThread::PostTask( + BrowserThread::FILE_USER_BLOCKING, + FROM_HERE, + base::Bind( + base::IgnoreResult(&extensions::FeatureProvider::GetAPIFeatures))); + } #endif // Android updates the metrics service dynamically depending on whether the
diff --git a/chrome/browser/chrome_browser_main_win.cc b/chrome/browser/chrome_browser_main_win.cc index 5c90b54..0e2e53a 100644 --- a/chrome/browser/chrome_browser_main_win.cc +++ b/chrome/browser/chrome_browser_main_win.cc
@@ -252,10 +252,11 @@ base::FilePath chrome_exe; if (PathService::Get(base::FILE_EXE, &chrome_exe)) { ShellUtil::ShortcutLocation user_shortcut_locations[] = { - ShellUtil::SHORTCUT_LOCATION_DESKTOP, - ShellUtil::SHORTCUT_LOCATION_QUICK_LAUNCH, - ShellUtil::SHORTCUT_LOCATION_START_MENU_CHROME_DIR, - ShellUtil::SHORTCUT_LOCATION_START_MENU_CHROME_APPS_DIR, + ShellUtil::SHORTCUT_LOCATION_DESKTOP, + ShellUtil::SHORTCUT_LOCATION_QUICK_LAUNCH, + ShellUtil::SHORTCUT_LOCATION_START_MENU_ROOT, + ShellUtil::SHORTCUT_LOCATION_START_MENU_CHROME_DIR_DEPRECATED, + ShellUtil::SHORTCUT_LOCATION_START_MENU_CHROME_APPS_DIR, }; BrowserDistribution* dist = BrowserDistribution::GetDistribution(); for (size_t i = 0; i < arraysize(user_shortcut_locations); ++i) {
diff --git a/chrome/browser/chromeos/BUILD.gn b/chrome/browser/chromeos/BUILD.gn index 5c5d3b8..bb24b8d 100644 --- a/chrome/browser/chromeos/BUILD.gn +++ b/chrome/browser/chromeos/BUILD.gn
@@ -21,11 +21,11 @@ public_deps = [ "//ash/resources", "//ash/strings", - "//chrome/app/resources:platform_locale_settings", - "//chrome/app/theme:theme_resources", "//chrome:extra_resources", "//chrome:resources", "//chrome:strings", + "//chrome/app/resources:platform_locale_settings", + "//chrome/app/theme:theme_resources", "//components/wallpaper", "//content/app/resources", "//ui/chromeos/resources", @@ -41,12 +41,6 @@ "//ash", "//ash:ash_with_content", "//build/linux:fontconfig", - "//components/drive", - "//components/flags_ui", - "//components/login", - "//components/session_manager/core", - "//components/user_manager", - "//components/wifi_sync", "//chrome/browser/devtools", "//chrome/browser/extensions", "//chrome/browser/safe_browsing:chunk_proto", @@ -58,17 +52,23 @@ "//chrome/common/safe_browsing:proto", "//chrome/installer/util", "//chromeos", - "//chromeos/ime:gencode", "//chromeos:cryptohome_proto", "//chromeos:cryptohome_signkey_proto", "//chromeos:power_manager_proto", + "//chromeos/ime:gencode", "//components/certificate_reporting:cert_logger_proto", "//components/certificate_reporting:encrypted_cert_logger_proto", + "//components/drive", + "//components/flags_ui", + "//components/login", "//components/onc", "//components/ownership", "//components/pairing", "//components/policy", "//components/proxy_config", + "//components/session_manager/core", + "//components/user_manager", + "//components/wifi_sync", # This depends directly on the variations target, rather than just # transitively via the common target because the proto sources need to @@ -108,9 +108,9 @@ "//ui/chromeos:ui_chromeos", "//ui/compositor", "//ui/display", + "//ui/events:dom_keycode_converter", "//ui/events/devices", "//ui/events/platform", - "//ui/events:dom_keycode_converter", "//ui/file_manager", "//ui/message_center", "//ui/surface", @@ -174,8 +174,8 @@ ":device_policy_proto", "//ash/resources", "//components/drive", - "//components/policy", "//components/invalidation/public", + "//components/policy", "//components/resources", "//crypto:platform", "//dbus",
diff --git a/chrome/browser/chromeos/attestation/platform_verification_dialog.cc b/chrome/browser/chromeos/attestation/platform_verification_dialog.cc index 9979825..f2deb6f1b 100644 --- a/chrome/browser/chromeos/attestation/platform_verification_dialog.cc +++ b/chrome/browser/chromeos/attestation/platform_verification_dialog.cc
@@ -128,8 +128,10 @@ GetHeightForWidth(kDialogMaxWidthInPixel)); } -void PlatformVerificationDialog::StyledLabelLinkClicked(const gfx::Range& range, - int event_flags) { +void PlatformVerificationDialog::StyledLabelLinkClicked( + views::StyledLabel* label, + const gfx::Range& range, + int event_flags) { Browser* browser = chrome::FindBrowserWithWebContents(web_contents()); const GURL learn_more_url(chrome::kEnhancedPlaybackNotificationLearnMoreURL);
diff --git a/chrome/browser/chromeos/attestation/platform_verification_dialog.h b/chrome/browser/chromeos/attestation/platform_verification_dialog.h index 29675061..7a13fe0 100644 --- a/chrome/browser/chromeos/attestation/platform_verification_dialog.h +++ b/chrome/browser/chromeos/attestation/platform_verification_dialog.h
@@ -61,7 +61,8 @@ gfx::Size GetPreferredSize() const override; // views::StyledLabelListener: - void StyledLabelLinkClicked(const gfx::Range& range, + void StyledLabelLinkClicked(views::StyledLabel* label, + const gfx::Range& range, int event_flags) override; // content::WebContentsObserver:
diff --git a/chrome/browser/chromeos/fileapi/external_file_url_request_job.cc b/chrome/browser/chromeos/fileapi/external_file_url_request_job.cc index 917cbcb..676e356 100644 --- a/chrome/browser/chromeos/fileapi/external_file_url_request_job.cc +++ b/chrome/browser/chromeos/fileapi/external_file_url_request_job.cc
@@ -10,7 +10,6 @@ #include "base/bind.h" #include "base/logging.h" #include "base/memory/ref_counted.h" -#include "base/thread_task_runner_handle.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/chromeos/file_manager/fileapi_util.h" #include "chrome/browser/chromeos/fileapi/external_file_url_util.h" @@ -20,6 +19,7 @@ #include "content/public/browser/browser_thread.h" #include "content/public/browser/storage_partition.h" #include "content/public/common/url_constants.h" +#include "net/base/net_errors.h" #include "net/http/http_byte_range.h" #include "net/http/http_request_headers.h" #include "net/http/http_response_info.h" @@ -163,7 +163,6 @@ net::NetworkDelegate* network_delegate) : net::URLRequestJob(request, network_delegate), profile_id_(profile_id), - range_parse_result_(net::OK), remaining_bytes_(0), weak_ptr_factory_(this) {} @@ -171,40 +170,24 @@ const net::HttpRequestHeaders& headers) { std::string range_header; if (headers.GetHeader(net::HttpRequestHeaders::kRange, &range_header)) { - // Currently this job only cares about the Range header, and only supports - // single range requests. Note that validation is deferred to Start, - // because NotifyStartError is not legal to call since the job has not - // started. + // Note: We only support single range requests. std::vector<net::HttpByteRange> ranges; if (net::HttpUtil::ParseRangeHeader(range_header, &ranges) && ranges.size() == 1) { byte_range_ = ranges[0]; } else { - range_parse_result_ = net::ERR_REQUEST_RANGE_NOT_SATISFIABLE; + // Failed to parse Range: header, so notify the error. + NotifyDone(net::URLRequestStatus(net::URLRequestStatus::FAILED, + net::ERR_REQUEST_RANGE_NOT_SATISFIABLE)); } } } void ExternalFileURLRequestJob::Start() { - // Post a task to invoke StartAsync asynchronously to avoid re-entering the - // delegate, because NotifyStartError is not legal to call synchronously in - // Start(). - base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, base::Bind(&ExternalFileURLRequestJob::StartAsync, - weak_ptr_factory_.GetWeakPtr())); -} - -void ExternalFileURLRequestJob::StartAsync() { DVLOG(1) << "Starting request"; DCHECK_CURRENTLY_ON(BrowserThread::IO); DCHECK(!stream_reader_); - if (range_parse_result_ != net::OK) { - NotifyStartError(net::URLRequestStatus(net::URLRequestStatus::FAILED, - range_parse_result_)); - return; - } - // We only support GET request. if (request()->method() != "GET") { LOG(WARNING) << "Failed to start request: " << request()->method() @@ -344,23 +327,37 @@ return true; } -int ExternalFileURLRequestJob::ReadRawData(net::IOBuffer* buf, int buf_size) { +bool ExternalFileURLRequestJob::ReadRawData(net::IOBuffer* buf, + int buf_size, + int* bytes_read) { DCHECK_CURRENTLY_ON(BrowserThread::IO); DCHECK(stream_reader_); - if (remaining_bytes_ == 0) - return 0; + if (remaining_bytes_ == 0) { + *bytes_read = 0; + return true; + } const int result = stream_reader_->Read( buf, std::min<int64>(buf_size, remaining_bytes_), base::Bind(&ExternalFileURLRequestJob::OnReadCompleted, weak_ptr_factory_.GetWeakPtr())); - if (result < 0) - return result; + if (result == net::ERR_IO_PENDING) { + // The data is not yet available. + SetStatus(net::URLRequestStatus(net::URLRequestStatus::IO_PENDING, 0)); + return false; + } + if (result < 0) { + // An error occurs. + NotifyDone(net::URLRequestStatus(net::URLRequestStatus::FAILED, result)); + return false; + } + // Reading has been finished immediately. + *bytes_read = result; remaining_bytes_ -= result; - return result; + return true; } ExternalFileURLRequestJob::~ExternalFileURLRequestJob() { @@ -369,10 +366,15 @@ void ExternalFileURLRequestJob::OnReadCompleted(int read_result) { DCHECK_CURRENTLY_ON(BrowserThread::IO); - if (read_result > 0) - remaining_bytes_ -= read_result; + if (read_result < 0) { + DCHECK_NE(read_result, net::ERR_IO_PENDING); + NotifyDone( + net::URLRequestStatus(net::URLRequestStatus::FAILED, read_result)); + } - ReadRawDataComplete(read_result); + remaining_bytes_ -= read_result; + SetStatus(net::URLRequestStatus()); // Clear the IO_PENDING status. + NotifyReadComplete(read_result); } } // namespace chromeos
diff --git a/chrome/browser/chromeos/fileapi/external_file_url_request_job.h b/chrome/browser/chromeos/fileapi/external_file_url_request_job.h index dff3379b..a026e43 100644 --- a/chrome/browser/chromeos/fileapi/external_file_url_request_job.h +++ b/chrome/browser/chromeos/fileapi/external_file_url_request_job.h
@@ -63,17 +63,12 @@ void Kill() override; bool GetMimeType(std::string* mime_type) const override; bool IsRedirectResponse(GURL* location, int* http_status_code) override; - int ReadRawData(net::IOBuffer* buf, int buf_size) override; + bool ReadRawData(net::IOBuffer* buf, int buf_size, int* bytes_read) override; protected: ~ExternalFileURLRequestJob() override; private: - // Helper method to start the job. Should be called asynchronously because - // NotifyStartError() is not legal to call synchronously in - // URLRequestJob::Start(). - void StartAsync(); - // Called from an internal helper class defined in drive_url_request_job.cc, // which is running on the UI thread. void OnHelperResultObtained( @@ -96,7 +91,6 @@ void* const profile_id_; // The range of the file to be returned. - net::Error range_parse_result_; net::HttpByteRange byte_range_; int64 remaining_bytes_;
diff --git a/chrome/browser/chromeos/input_method/input_method_manager_impl_unittest.cc b/chrome/browser/chromeos/input_method/input_method_manager_impl_unittest.cc index a91a3fe..ac9d555 100644 --- a/chrome/browser/chromeos/input_method/input_method_manager_impl_unittest.cc +++ b/chrome/browser/chromeos/input_method/input_method_manager_impl_unittest.cc
@@ -245,6 +245,20 @@ ext_xkb_engine_colemak.layouts.push_back("us(colemak)"); ext_xkb.engines.push_back(ext_xkb_engine_colemak); + ComponentExtensionEngine ext_xkb_engine_workman; + ext_xkb_engine_workman.engine_id = "xkb:us:workman:eng"; + ext_xkb_engine_workman.display_name = "xkb:us:workman:eng"; + ext_xkb_engine_workman.language_codes.push_back("en-US"); + ext_xkb_engine_workman.layouts.push_back("us(workman)"); + ext_xkb.engines.push_back(ext_xkb_engine_workman); + + ComponentExtensionEngine ext_xkb_engine_workman_intl; + ext_xkb_engine_workman_intl.engine_id = "xkb:us:workman-intl:eng"; + ext_xkb_engine_workman_intl.display_name = "xkb:us:workman-intl:eng"; + ext_xkb_engine_workman_intl.language_codes.push_back("en-US"); + ext_xkb_engine_workman_intl.layouts.push_back("us(workman-intl)"); + ext_xkb.engines.push_back(ext_xkb_engine_workman_intl); + ComponentExtensionEngine ext_xkb_engine_fr; ext_xkb_engine_fr.engine_id = "xkb:fr::fra"; ext_xkb_engine_fr.display_name = "xkb:fr::fra"; @@ -376,7 +390,7 @@ menu_manager_->AddObserver(&observer); EXPECT_EQ(0, observer.input_method_changed_count_); manager_->GetActiveIMEState()->EnableLoginLayouts("en-US", keyboard_layouts); - EXPECT_EQ(6U, manager_->GetActiveIMEState()->GetActiveInputMethods()->size()); + EXPECT_EQ(8U, manager_->GetActiveIMEState()->GetActiveInputMethods()->size()); EXPECT_EQ(1, observer.input_method_changed_count_); // Menu change is triggered only if current input method was actually changed. EXPECT_EQ(0, observer.input_method_menu_item_changed_count_); @@ -424,13 +438,13 @@ } TEST_F(InputMethodManagerImplTest, TestEnableLayouts) { - // Currently 6 keyboard layouts are supported for en-US, and 1 for ja. See + // Currently 8 keyboard layouts are supported for en-US, and 1 for ja. See // ibus_input_method.txt. std::vector<std::string> keyboard_layouts; InitComponentExtension(); manager_->GetActiveIMEState()->EnableLoginLayouts("en-US", keyboard_layouts); - EXPECT_EQ(6U, manager_->GetActiveIMEState()->GetNumActiveInputMethods()); + EXPECT_EQ(8U, manager_->GetActiveIMEState()->GetNumActiveInputMethods()); // For http://crbug.com/19655#c11 - (5) // The hardware keyboard layout "xkb:us::eng" is always active, hence 2U. @@ -460,8 +474,8 @@ "en-US", manager_->GetInputMethodUtil()->GetHardwareLoginInputMethodIds()); EXPECT_EQ( - 7U, - manager_->GetActiveIMEState()->GetNumActiveInputMethods()); // 6 + French + 9U, + manager_->GetActiveIMEState()->GetNumActiveInputMethods()); // 8 + French // The physical layout is Japanese. manager_->GetInputMethodUtil()->SetHardwareKeyboardLayoutForTesting( "xkb:jp::jpn"); @@ -489,8 +503,8 @@ manager_->GetActiveIMEState()->EnableLoginLayouts( "en-US", manager_->GetInputMethodUtil()->GetHardwareLoginInputMethodIds()); - // 6 + French + Hungarian - EXPECT_EQ(8U, manager_->GetActiveIMEState()->GetNumActiveInputMethods()); + // 8 + French + Hungarian + EXPECT_EQ(10U, manager_->GetActiveIMEState()->GetNumActiveInputMethods()); } TEST_F(InputMethodManagerImplTest, @@ -901,7 +915,7 @@ keyboard_layouts.push_back(ImeIdFromEngineId("xkb:us::eng")); // For http://crbug.com/19655#c11 - (1) manager_->GetActiveIMEState()->EnableLoginLayouts("en-US", keyboard_layouts); - EXPECT_EQ(6U, manager_->GetActiveIMEState()->GetNumActiveInputMethods()); + EXPECT_EQ(8U, manager_->GetActiveIMEState()->GetNumActiveInputMethods()); EXPECT_EQ(ImeIdFromEngineId("xkb:us::eng"), manager_->GetActiveIMEState()->GetCurrentInputMethod().id()); EXPECT_EQ("us", keyboard_->last_layout_); @@ -932,6 +946,16 @@ EXPECT_EQ("us(colemak)", keyboard_->last_layout_); manager_->GetActiveIMEState()->SwitchToNextInputMethod(); EXPECT_TRUE(observer.last_show_message_); + EXPECT_EQ(ImeIdFromEngineId("xkb:us:workman:eng"), + manager_->GetActiveIMEState()->GetCurrentInputMethod().id()); + EXPECT_EQ("us(workman)", keyboard_->last_layout_); + manager_->GetActiveIMEState()->SwitchToNextInputMethod(); + EXPECT_TRUE(observer.last_show_message_); + EXPECT_EQ(ImeIdFromEngineId("xkb:us:workman-intl:eng"), + manager_->GetActiveIMEState()->GetCurrentInputMethod().id()); + EXPECT_EQ("us(workman-intl)", keyboard_->last_layout_); + manager_->GetActiveIMEState()->SwitchToNextInputMethod(); + EXPECT_TRUE(observer.last_show_message_); EXPECT_EQ(ImeIdFromEngineId("xkb:us::eng"), manager_->GetActiveIMEState()->GetCurrentInputMethod().id()); EXPECT_EQ("us", keyboard_->last_layout_); @@ -947,7 +971,7 @@ std::vector<std::string> keyboard_layouts; keyboard_layouts.push_back(ImeIdFromEngineId("xkb:us::eng")); manager_->GetActiveIMEState()->EnableLoginLayouts("en-US", keyboard_layouts); - EXPECT_EQ(6U, manager_->GetActiveIMEState()->GetNumActiveInputMethods()); + EXPECT_EQ(8U, manager_->GetActiveIMEState()->GetNumActiveInputMethods()); EXPECT_TRUE(manager_->GetActiveIMEState()->CanCycleInputMethod()); EXPECT_EQ(ImeIdFromEngineId("xkb:us::eng"), manager_->GetActiveIMEState()->GetCurrentInputMethod().id()); @@ -1019,7 +1043,7 @@ std::vector<std::string> keyboard_layouts; keyboard_layouts.push_back(ImeIdFromEngineId("xkb:us::eng")); manager_->GetActiveIMEState()->EnableLoginLayouts("en-US", keyboard_layouts); - EXPECT_EQ(6U, manager_->GetActiveIMEState()->GetNumActiveInputMethods()); + EXPECT_EQ(8U, manager_->GetActiveIMEState()->GetNumActiveInputMethods()); // Henkan, Muhenkan, ZenkakuHankaku should be ignored when no Japanese IMEs // and keyboards are enabled.
diff --git a/chrome/browser/chromeos/input_method/input_method_util.cc b/chrome/browser/chromeos/input_method/input_method_util.cc index f463ef30..c256730 100644 --- a/chrome/browser/chromeos/input_method/input_method_util.cc +++ b/chrome/browser/chromeos/input_method/input_method_util.cc
@@ -188,6 +188,8 @@ {"xkb:us:intl:eng", IDS_STATUSBAR_LAYOUT_USA_INTERNATIONAL}, {"xkb:us:intl:nld", IDS_STATUSBAR_LAYOUT_USA_INTERNATIONAL}, {"xkb:us:intl:por", IDS_STATUSBAR_LAYOUT_USA_INTERNATIONAL}, + {"xkb:us:workman-intl:eng", IDS_STATUSBAR_LAYOUT_USA_WORKMAN_INTERNATIONAL}, + {"xkb:us:workman:eng", IDS_STATUSBAR_LAYOUT_USA_WORKMAN}, }; const size_t kEnglishToResourceIdArraySize = arraysize(kEnglishToResourceIdArray); @@ -329,6 +331,9 @@ {"__MSG_KEYBOARD_US_EXTENDED__", IDS_IME_NAME_KEYBOARD_US_EXTENDED}, {"__MSG_KEYBOARD_US_INTERNATIONAL__", IDS_IME_NAME_KEYBOARD_US_INTERNATIONAL}, + {"__MSG_KEYBOARD_US_WORKMAN_INTERNATIONAL__", + IDS_IME_NAME_KEYBOARD_US_WORKMAN_INTERNATIONAL}, + {"__MSG_KEYBOARD_US_WORKMAN__", IDS_IME_NAME_KEYBOARD_US_WORKMAN}, {"__MSG_KEYBOARD_US__", IDS_IME_NAME_KEYBOARD_US}, {"__MSG_KEYBOARD_VIETNAMESE_TCVN__", IDS_IME_NAME_KEYBOARD_VIETNAMESE_TCVN}, {"__MSG_KEYBOARD_VIETNAMESE_TELEX__",
diff --git a/chrome/browser/chromeos/login/easy_unlock/easy_unlock_create_keys_operation.cc b/chrome/browser/chromeos/login/easy_unlock/easy_unlock_create_keys_operation.cc index e3c11a8..d0ebacf 100644 --- a/chrome/browser/chromeos/login/easy_unlock/easy_unlock_create_keys_operation.cc +++ b/chrome/browser/chromeos/login/easy_unlock/easy_unlock_create_keys_operation.cc
@@ -6,6 +6,7 @@ #include <string> +#include "base/base64url.h" #include "base/bind.h" #include "base/logging.h" #include "base/memory/scoped_ptr.h" @@ -17,7 +18,6 @@ #include "chromeos/dbus/dbus_thread_manager.h" #include "chromeos/dbus/easy_unlock_client.h" #include "chromeos/login/auth/key.h" -#include "components/proximity_auth/cryptauth/base64url.h" #include "components/proximity_auth/logging/logging.h" #include "crypto/encryptor.h" #include "crypto/random.h" @@ -121,7 +121,9 @@ } std::string device_pub_key; - if (!proximity_auth::Base64UrlDecode(device_->public_key, &device_pub_key)) { + if (!base::Base64UrlDecode(device_->public_key, + base::Base64UrlDecodePolicy::REQUIRE_PADDING, + &device_pub_key)) { PA_LOG(ERROR) << "Easy unlock failed to decode device public key."; callback_.Run(false); return;
diff --git a/chrome/browser/chromeos/login/easy_unlock/secure_message_delegate_chromeos.cc b/chrome/browser/chromeos/login/easy_unlock/secure_message_delegate_chromeos.cc index 665106d3..bb95222 100644 --- a/chrome/browser/chromeos/login/easy_unlock/secure_message_delegate_chromeos.cc +++ b/chrome/browser/chromeos/login/easy_unlock/secure_message_delegate_chromeos.cc
@@ -7,7 +7,6 @@ #include "base/bind.h" #include "chromeos/dbus/dbus_thread_manager.h" #include "chromeos/dbus/easy_unlock_client.h" -#include "components/proximity_auth/cryptauth/base64url.h" #include "components/proximity_auth/logging/logging.h" #include "third_party/cros_system_api/dbus/service_constants.h"
diff --git a/chrome/browser/chromeos/login/login_ui_keyboard_browsertest.cc b/chrome/browser/chromeos/login/login_ui_keyboard_browsertest.cc index b50ba964..afbfb97 100644 --- a/chrome/browser/chromeos/login/login_ui_keyboard_browsertest.cc +++ b/chrome/browser/chromeos/login/login_ui_keyboard_browsertest.cc
@@ -31,6 +31,8 @@ out->push_back("xkb:us:dvorak:eng"); out->push_back("xkb:us:dvp:eng"); out->push_back("xkb:us:colemak:eng"); + out->push_back("xkb:us:workman:eng"); + out->push_back("xkb:us:workman-intl:eng"); chromeos::input_method::InputMethodManager::Get()->MigrateInputMethods(out); }
diff --git a/chrome/browser/chromeos/login/oobe_localization_browsertest.cc b/chrome/browser/chromeos/login/oobe_localization_browsertest.cc index 4d0efe3..17d38f2 100644 --- a/chrome/browser/chromeos/login/oobe_localization_browsertest.cc +++ b/chrome/browser/chromeos/login/oobe_localization_browsertest.cc
@@ -76,66 +76,55 @@ const char* expected_keyboard_layout; const char* expected_keyboard_select_control; } const oobe_localization_test_parameters[] = { - // ------------------ Non-Latin setup - // For a non-Latin keyboard layout like Russian, we expect to see the US - // keyboard. - {"ru", "xkb:ru::rus", "ru", kUSLayout, "xkb:us::eng"}, - {"ru", "xkb:us::eng,xkb:ru::rus", "ru", kUSLayout, "xkb:us::eng"}, + // ------------------ Non-Latin setup + // For a non-Latin keyboard layout like Russian, we expect to see the US + // keyboard. + {"ru", "xkb:ru::rus", "ru", kUSLayout, "xkb:us::eng"}, + {"ru", "xkb:us::eng,xkb:ru::rus", "ru", kUSLayout, "xkb:us::eng"}, - // IMEs do not load at OOBE, so we just expect to see the (Latin) Japanese - // keyboard. - {"ja", "xkb:jp::jpn", "ja", "xkb:jp::jpn", "xkb:jp::jpn,[xkb:us::eng]"}, + // IMEs do not load at OOBE, so we just expect to see the (Latin) Japanese + // keyboard. + {"ja", "xkb:jp::jpn", "ja", "xkb:jp::jpn", "xkb:jp::jpn,[xkb:us::eng]"}, - // We don't use the Icelandic locale but the Icelandic keyboard layout - // should still be selected when specified as the default. - {"en-US", - "xkb:is::ice", - "en-US", - "xkb:is::ice", - "xkb:is::ice,[xkb:us::eng,xkb:us:intl:eng,xkb:us:altgr-intl:eng," - "xkb:us:dvorak:eng,xkb:us:dvp:eng,xkb:us:colemak:eng]"}, - // ------------------ Full Latin setup - // French Swiss keyboard. - {"fr", - "xkb:ch:fr:fra", - "fr", - "xkb:ch:fr:fra", - "xkb:ch:fr:fra,[xkb:fr::fra,xkb:be::fra,xkb:ca::fra," - "xkb:ca:multix:fra,xkb:us::eng]"}, + // We don't use the Icelandic locale but the Icelandic keyboard layout + // should still be selected when specified as the default. + {"en-US", "xkb:is::ice", "en-US", "xkb:is::ice", + "xkb:is::ice,[xkb:us::eng,xkb:us:intl:eng,xkb:us:altgr-intl:eng," + "xkb:us:dvorak:eng,xkb:us:dvp:eng,xkb:us:colemak:eng," + "xkb:us:workman:eng,xkb:us:workman-intl:eng]"}, + // ------------------ Full Latin setup + // French Swiss keyboard. + {"fr", "xkb:ch:fr:fra", "fr", "xkb:ch:fr:fra", + "xkb:ch:fr:fra,[xkb:fr::fra,xkb:be::fra,xkb:ca::fra," + "xkb:ca:multix:fra,xkb:us::eng]"}, - // German Swiss keyboard. - {"de", - "xkb:ch::ger", - "de", - "xkb:ch::ger", - "xkb:ch::ger,[xkb:de::ger,xkb:de:neo:ger,xkb:be::ger,xkb:us::eng]"}, + // German Swiss keyboard. + {"de", "xkb:ch::ger", "de", "xkb:ch::ger", + "xkb:ch::ger,[xkb:de::ger,xkb:de:neo:ger,xkb:be::ger,xkb:us::eng]"}, - // NetworkScreenMultipleLocales - {"es,en-US,nl", - "xkb:be::nld", - "es,en-US,nl", - "xkb:be::nld", - "xkb:be::nld,[xkb:es::spa,xkb:latam::spa,xkb:us::eng]"}, + // NetworkScreenMultipleLocales + {"es,en-US,nl", "xkb:be::nld", "es,en-US,nl", "xkb:be::nld", + "xkb:be::nld,[xkb:es::spa,xkb:latam::spa,xkb:us::eng]"}, - {"ru,de", "xkb:ru::rus", "ru,de", kUSLayout, "xkb:us::eng"}, + {"ru,de", "xkb:ru::rus", "ru,de", kUSLayout, "xkb:us::eng"}, - // TODO(alemate/michaelpg): Figure out why these tests are failing - // and re-enable them. crbug.com/422702. - // ------------------ Regional Locales - // Syntetic example to test correct merging of different locales. - // {"fr-CH,it-CH,de-CH", - // "xkb:fr::fra,xkb:it::ita,xkb:de::ger", - // "fr-CH,it-CH,de-CH", - // "xkb:fr::fra", - // "xkb:fr::fra,xkb:it::ita,xkb:de::ger,[xkb:be::fra,xkb:ca::fra," - // "xkb:ch:fr:fra,xkb:ca:multix:fra,xkb:us::eng]"}, + // TODO(alemate/michaelpg): Figure out why these tests are failing + // and re-enable them. crbug.com/422702. + // ------------------ Regional Locales + // Syntetic example to test correct merging of different locales. + // {"fr-CH,it-CH,de-CH", + // "xkb:fr::fra,xkb:it::ita,xkb:de::ger", + // "fr-CH,it-CH,de-CH", + // "xkb:fr::fra", + // "xkb:fr::fra,xkb:it::ita,xkb:de::ger,[xkb:be::fra,xkb:ca::fra," + // "xkb:ch:fr:fra,xkb:ca:multix:fra,xkb:us::eng]"}, - // Another syntetic example. Check that british keyboard is available. - // {"en-AU", - // "xkb:us::eng", - // "en-AU", - // "xkb:us::eng", - // "xkb:us::eng,[xkb:gb:extd:eng,xkb:gb:dvorak:eng]"}, + // Another syntetic example. Check that british keyboard is available. + // {"en-AU", + // "xkb:us::eng", + // "en-AU", + // "xkb:us::eng", + // "xkb:us::eng,[xkb:gb:extd:eng,xkb:gb:dvorak:eng]"}, }; class OobeLocalizationTest
diff --git a/chrome/browser/chromeos/policy/device_status_collector.cc b/chrome/browser/chromeos/policy/device_status_collector.cc index fc12d3d..7a2afc89 100644 --- a/chrome/browser/chromeos/policy/device_status_collector.cc +++ b/chrome/browser/chromeos/policy/device_status_collector.cc
@@ -118,7 +118,8 @@ stat.f_frsize); result.push_back(info); } else { - LOG(ERROR) << "Unable to get volume status for " << mount_point; + LOG_IF(ERROR, !mount_point.empty()) << "Unable to get volume status for " + << mount_point; } } return result;
diff --git a/chrome/browser/chromeos/policy/heartbeat_scheduler.cc b/chrome/browser/chromeos/policy/heartbeat_scheduler.cc index a910964..c598437 100644 --- a/chrome/browser/chromeos/policy/heartbeat_scheduler.cc +++ b/chrome/browser/chromeos/policy/heartbeat_scheduler.cc
@@ -27,15 +27,27 @@ const char* kHeartbeatGCMDestinationID = "1013309121859"; const char* kHeartbeatGCMSenderSuffix = "@google.com"; -const char* kMonitoringMessageTypeKey = "type"; +// Destination of upstream notification sign up message. +const char* kUpstreamNotificationSignUpDestinationID = + "https://gcm.googleapis.com/gcm/gcm.event_tracker"; + +// A bit mask, listening events of upstream notification. +const char* kUpstreamNotificationSignUpListeningEvents = + "7"; // START | DISCONNECTED | HEARTBEAT + +const char* kGcmMessageTypeKey = "type"; const char* kHeartbeatTimestampKey = "timestamp"; const char* kHeartbeatDomainNameKey = "domain_name"; const char* kHeartbeatDeviceIDKey = "device_id"; const char* kHeartbeatTypeValue = "hb"; +const char* kUpstreamNotificationNotifyKey = "notify"; // If we get an error registering with GCM, try again in two minutes. const int64 kRegistrationRetryDelayMs = 2 * 60 * 1000; +const char* kHeartbeatSchedulerScope = + "policy.heartbeat_scheduler.upstream_notification"; + // Returns the destination ID for GCM heartbeats. std::string GetDestinationID() { std::string receiver_id = kHeartbeatGCMDestinationID; @@ -212,9 +224,13 @@ // value because CrosSettings can become untrusted at arbitrary times and we // want to use the last trusted value). int frequency; - if (settings->GetInteger(chromeos::kHeartbeatFrequency, &frequency)) + if (settings->GetInteger(chromeos::kHeartbeatFrequency, &frequency)) { heartbeat_interval_ = EnsureValidHeartbeatInterval( base::TimeDelta::FromMilliseconds(frequency)); + } + + gcm_driver_->AddHeartbeatInterval(kHeartbeatSchedulerScope, + heartbeat_interval_.InMilliseconds()); bool enabled; if (settings->GetBoolean(chromeos::kHeartbeatEnabled, &enabled)) @@ -241,7 +257,9 @@ registration_id_.clear(); if (registered_app_handler_) { registered_app_handler_ = false; + gcm_driver_->RemoveHeartbeatInterval(kHeartbeatSchedulerScope); gcm_driver_->RemoveAppHandler(kHeartbeatGCMAppID); + gcm_driver_->RemoveConnectionObserver(this); } } @@ -274,6 +292,7 @@ // a GCM connection. registered_app_handler_ = true; gcm_driver_->AddAppHandler(kHeartbeatGCMAppID, this); + gcm_driver_->AddConnectionObserver(this); registration_helper_.reset(new HeartbeatRegistrationHelper( gcm_driver_, task_runner_)); registration_helper_->Register( @@ -308,6 +327,7 @@ registration_id, base::Bind(&HeartbeatScheduler::OnGcmIdUpdateRequestSent, weak_factory_.GetWeakPtr())); + SignUpUpstreamNotification(); } // Now that GCM registration is complete, start sending heartbeats. @@ -328,7 +348,7 @@ // https://developer.chrome.com/apps/cloudMessaging#send_messages message.id = base::Int64ToString( base::Time::NowFromSystemTime().ToInternalValue()); - message.data[kMonitoringMessageTypeKey] = kHeartbeatTypeValue; + message.data[kGcmMessageTypeKey] = kHeartbeatTypeValue; message.data[kHeartbeatTimestampKey] = base::Int64ToString( base::Time::NowFromSystemTime().ToJavaTime()); message.data[kHeartbeatDomainNameKey] = enrollment_domain_; @@ -340,6 +360,24 @@ weak_factory_.GetWeakPtr())); } +void HeartbeatScheduler::SignUpUpstreamNotification() { + DCHECK(gcm_driver_); + + if (registration_id_.empty()) + return; + + gcm::OutgoingMessage message; + message.id = + base::Int64ToString(base::Time::NowFromSystemTime().ToInternalValue()); + message.data[kGcmMessageTypeKey] = kUpstreamNotificationSignUpListeningEvents; + message.data[kUpstreamNotificationNotifyKey] = + GetDestinationID() + kHeartbeatGCMSenderSuffix; + gcm_driver_->Send(kHeartbeatGCMAppID, + kUpstreamNotificationSignUpDestinationID, message, + base::Bind(&HeartbeatScheduler::OnUpstreamNotificationSent, + weak_factory_.GetWeakPtr())); +} + void HeartbeatScheduler::OnHeartbeatSent(const std::string& message_id, gcm::GCMClient::Result result) { DVLOG(1) << "Monitoring heartbeat sent - result = " << result; @@ -351,6 +389,14 @@ ScheduleNextHeartbeat(); } +void HeartbeatScheduler::OnUpstreamNotificationSent( + const std::string& message_id, + gcm::GCMClient::Result result) { + DVLOG(1) << "Upstream notification signup message sent - result = " << result; + DLOG_IF(ERROR, result != gcm::GCMClient::SUCCESS) + << "Error sending upstream notification signup message: " << result; +} + HeartbeatScheduler::~HeartbeatScheduler() { ShutdownGCM(); } @@ -385,6 +431,10 @@ DVLOG(1) << "Heartbeat sent with message_id: " << message_id; } +void HeartbeatScheduler::OnConnected(const net::IPEndPoint&) { + SignUpUpstreamNotification(); +} + void HeartbeatScheduler::OnGcmIdUpdateRequestSent(bool success) { // TODO(binjin): Handle the failure, probably by exponential backoff. LOG_IF(WARNING, !success) << "Failed to send GCM id to DM server";
diff --git a/chrome/browser/chromeos/policy/heartbeat_scheduler.h b/chrome/browser/chromeos/policy/heartbeat_scheduler.h index ab3140c..1b46709 100644 --- a/chrome/browser/chromeos/policy/heartbeat_scheduler.h +++ b/chrome/browser/chromeos/policy/heartbeat_scheduler.h
@@ -16,6 +16,7 @@ #include "chrome/browser/chromeos/settings/cros_settings.h" #include "components/gcm_driver/gcm_app_handler.h" #include "components/gcm_driver/gcm_client.h" +#include "components/gcm_driver/gcm_connection_observer.h" #include "components/policy/core/common/cloud/cloud_policy_client.h" namespace base { @@ -33,7 +34,8 @@ // Class responsible for periodically sending heartbeats to the policy service // for monitoring device connectivity. -class HeartbeatScheduler : public gcm::GCMAppHandler { +class HeartbeatScheduler : public gcm::GCMAppHandler, + gcm::GCMConnectionObserver { public: // Default interval for how often we send up a heartbeat. static const int64 kDefaultHeartbeatIntervalMs; @@ -63,6 +65,9 @@ void OnSendAcknowledged(const std::string& app_id, const std::string& message_id) override; + // GCMConnectionObserver overrides. + void OnConnected(const net::IPEndPoint&) override; + private: // Callback invoked periodically to send a heartbeat to the policy service. void SendHeartbeat(); @@ -74,6 +79,10 @@ void OnHeartbeatSent(const std::string& message_id, gcm::GCMClient::Result result); + // Invoked after a upstream notification sign up message has been sent. + void OnUpstreamNotificationSent(const std::string& message_id, + gcm::GCMClient::Result result); + // Helper method that figures out when the next heartbeat should // be scheduled. void ScheduleNextHeartbeat(); @@ -92,6 +101,9 @@ // Callback for the GCM id update request. void OnGcmIdUpdateRequestSent(bool status); + // Helper function to signup for upstream notification. + void SignUpUpstreamNotification(); + // TaskRunner used for scheduling heartbeats. const scoped_refptr<base::SequencedTaskRunner> task_runner_;
diff --git a/chrome/browser/chromeos/policy/heartbeat_scheduler_unittest.cc b/chrome/browser/chromeos/policy/heartbeat_scheduler_unittest.cc index 868c4cf..d08077a 100644 --- a/chrome/browser/chromeos/policy/heartbeat_scheduler_unittest.cc +++ b/chrome/browser/chromeos/policy/heartbeat_scheduler_unittest.cc
@@ -4,18 +4,28 @@ #include "chrome/browser/chromeos/policy/heartbeat_scheduler.h" +#include "base/macros.h" #include "base/strings/string_number_conversions.h" #include "base/test/test_simple_task_runner.h" #include "chrome/browser/chromeos/settings/scoped_cros_settings_test_helper.h" #include "chromeos/settings/cros_settings_names.h" +#include "components/gcm_driver/common/gcm_messages.h" #include "components/gcm_driver/fake_gcm_driver.h" #include "components/policy/core/common/cloud/cloud_policy_client.h" #include "components/policy/core/common/cloud/mock_cloud_policy_client.h" #include "content/public/test/test_utils.h" +#include "net/base/ip_endpoint.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" using ::testing::_; +using ::testing::AnyNumber; +using ::testing::AtLeast; +using ::testing::Contains; +using ::testing::Field; +using ::testing::Key; +using ::testing::Matches; +using ::testing::Pair; using ::testing::SaveArg; namespace { @@ -25,10 +35,19 @@ const char* const kRegistrationId = "registration_id"; const char* const kDMToken = "fake_dm_token"; +MATCHER(IsHeartbeatMsg, "") { + return Matches( + Field(&gcm::OutgoingMessage::data, Contains(Pair("type", "hb"))))(arg); +} + +MATCHER(IsUpstreamNotificationMsg, "") { + return Matches(Field(&gcm::OutgoingMessage::data, Contains(Key("notify"))))( + arg); +} + class MockGCMDriver : public testing::StrictMock<gcm::FakeGCMDriver> { public: - MockGCMDriver() { - } + MockGCMDriver() { IgnoreDefaultHeartbeatsInterval(); } ~MockGCMDriver() override { } @@ -40,6 +59,9 @@ const std::string&, const gcm::OutgoingMessage& message)); + MOCK_METHOD2(AddHeartbeatInterval, + void(const std::string& scope, int interval_ms)); + // Helper function to complete a registration previously started by // Register(). void CompleteRegistration(const std::string& app_id, @@ -54,6 +76,32 @@ gcm::GCMClient::Result result) { SendFinished(app_id, message_id, result); } + + void AddConnectionObserver(gcm::GCMConnectionObserver* observer) override { + EXPECT_FALSE(observer_); + observer_ = observer; + } + + void RemoveConnectionObserver(gcm::GCMConnectionObserver* observer) override { + EXPECT_TRUE(observer_); + observer_ = nullptr; + } + + void NotifyConnected() { + ASSERT_TRUE(observer_); + observer_->OnConnected(net::IPEndPoint()); + } + + void IgnoreDefaultHeartbeatsInterval() { + // Ignore default setting for heartbeats interval. + EXPECT_CALL(*this, AddHeartbeatInterval(_, 2 * 60 * 1000)) + .Times(AnyNumber()); + } + + private: + gcm::GCMConnectionObserver* observer_ = nullptr; + + DISALLOW_COPY_AND_ASSIGN(MockGCMDriver); }; class HeartbeatSchedulerTest : public testing::Test { @@ -96,6 +144,12 @@ EXPECT_GE(now - last_heartbeat, delta); } + void IgnoreUpstreamNotificationMsg() { + EXPECT_CALL(gcm_driver_, + SendImpl(kHeartbeatGCMAppID, _, IsUpstreamNotificationMsg())) + .Times(AnyNumber()); + } + base::MessageLoop loop_; MockGCMDriver gcm_driver_; chromeos::ScopedCrosSettingsTestHelper settings_helper_; @@ -127,26 +181,36 @@ } TEST_F(HeartbeatSchedulerTest, TemporarilyFailedGCMRegistration) { + IgnoreUpstreamNotificationMsg(); + EXPECT_CALL(gcm_driver_, RegisterImpl(kHeartbeatGCMAppID, _)); settings_helper_.SetBoolean(chromeos::kHeartbeatEnabled, true); gcm_driver_.CompleteRegistration( kHeartbeatGCMAppID, gcm::GCMClient::SERVER_ERROR); testing::Mock::VerifyAndClearExpectations(&gcm_driver_); + IgnoreUpstreamNotificationMsg(); + gcm_driver_.IgnoreDefaultHeartbeatsInterval(); + // Should have a pending task to try registering again. ASSERT_FALSE(task_runner_->GetPendingTasks().empty()); EXPECT_CALL(gcm_driver_, RegisterImpl(kHeartbeatGCMAppID, _)); task_runner_->RunPendingTasks(); testing::Mock::VerifyAndClearExpectations(&gcm_driver_); + IgnoreUpstreamNotificationMsg(); + gcm_driver_.IgnoreDefaultHeartbeatsInterval(); + // Once we have successfully registered, we should send a heartbeat. - EXPECT_CALL(gcm_driver_, SendImpl(kHeartbeatGCMAppID, _, _)); + EXPECT_CALL(gcm_driver_, SendImpl(kHeartbeatGCMAppID, _, IsHeartbeatMsg())); gcm_driver_.CompleteRegistration( kHeartbeatGCMAppID, gcm::GCMClient::SUCCESS); task_runner_->RunPendingTasks(); } TEST_F(HeartbeatSchedulerTest, ChangeHeartbeatFrequency) { + IgnoreUpstreamNotificationMsg(); + EXPECT_CALL(gcm_driver_, RegisterImpl(kHeartbeatGCMAppID, _)); settings_helper_.SetBoolean(chromeos::kHeartbeatEnabled, true); gcm_driver_.CompleteRegistration( @@ -157,11 +221,15 @@ EXPECT_EQ(base::TimeDelta(), task_runner_->NextPendingTaskDelay()); testing::Mock::VerifyAndClearExpectations(&gcm_driver_); + IgnoreUpstreamNotificationMsg(); + gcm_driver_.IgnoreDefaultHeartbeatsInterval(); + const int new_delay = 1234*1000; // 1234 seconds. + EXPECT_CALL(gcm_driver_, AddHeartbeatInterval(_, new_delay)); settings_helper_.SetInteger(chromeos::kHeartbeatFrequency, new_delay); // Now run pending heartbeat task, should send a heartbeat. gcm::OutgoingMessage message; - EXPECT_CALL(gcm_driver_, SendImpl(kHeartbeatGCMAppID, _, _)) + EXPECT_CALL(gcm_driver_, SendImpl(kHeartbeatGCMAppID, _, IsHeartbeatMsg())) .WillOnce(SaveArg<2>(&message)); task_runner_->RunPendingTasks(); EXPECT_TRUE(task_runner_->GetPendingTasks().empty()); @@ -176,11 +244,13 @@ } TEST_F(HeartbeatSchedulerTest, DisableHeartbeats) { + IgnoreUpstreamNotificationMsg(); + // Makes sure that we can disable heartbeats on the fly. EXPECT_CALL(gcm_driver_, RegisterImpl(kHeartbeatGCMAppID, _)); settings_helper_.SetBoolean(chromeos::kHeartbeatEnabled, true); gcm::OutgoingMessage message; - EXPECT_CALL(gcm_driver_, SendImpl(kHeartbeatGCMAppID, _, _)) + EXPECT_CALL(gcm_driver_, SendImpl(kHeartbeatGCMAppID, _, IsHeartbeatMsg())) .WillOnce(SaveArg<2>(&message)); gcm_driver_.CompleteRegistration( kHeartbeatGCMAppID, gcm::GCMClient::SUCCESS); @@ -200,6 +270,9 @@ policy::HeartbeatScheduler::kDefaultHeartbeatIntervalMs)); testing::Mock::VerifyAndClearExpectations(&gcm_driver_); + IgnoreUpstreamNotificationMsg(); + gcm_driver_.IgnoreDefaultHeartbeatsInterval(); + // Now disable heartbeats. Should get no more heartbeats sent. settings_helper_.SetBoolean(chromeos::kHeartbeatEnabled, false); task_runner_->RunPendingTasks(); @@ -207,9 +280,11 @@ } TEST_F(HeartbeatSchedulerTest, CheckMessageContents) { + IgnoreUpstreamNotificationMsg(); + gcm::OutgoingMessage message; EXPECT_CALL(gcm_driver_, RegisterImpl(kHeartbeatGCMAppID, _)); - EXPECT_CALL(gcm_driver_, SendImpl(kHeartbeatGCMAppID, _, _)) + EXPECT_CALL(gcm_driver_, SendImpl(kHeartbeatGCMAppID, _, IsHeartbeatMsg())) .WillOnce(SaveArg<2>(&message)); settings_helper_.SetBoolean(chromeos::kHeartbeatEnabled, true); gcm_driver_.CompleteRegistration( @@ -238,7 +313,8 @@ // Enable heartbeats. EXPECT_CALL(gcm_driver_, RegisterImpl(kHeartbeatGCMAppID, _)); - EXPECT_CALL(gcm_driver_, SendImpl(kHeartbeatGCMAppID, _, _)); + EXPECT_CALL(gcm_driver_, SendImpl(kHeartbeatGCMAppID, _, _)) + .Times(AtLeast(1)); settings_helper_.SetBoolean(chromeos::kHeartbeatEnabled, true); gcm_driver_.CompleteRegistration(kHeartbeatGCMAppID, gcm::GCMClient::SUCCESS); task_runner_->RunPendingTasks(); @@ -250,4 +326,32 @@ callback.Run(true); } +TEST_F(HeartbeatSchedulerTest, GcmUpstreamNotificationSignup) { + // Verifies that upstream notification works as expected. + cloud_policy_client_.SetDMToken(kDMToken); + EXPECT_CALL(gcm_driver_, RegisterImpl(kHeartbeatGCMAppID, _)) + .Times(AnyNumber()); + EXPECT_CALL(cloud_policy_client_, UpdateGcmId(kRegistrationId, _)); + + // GCM connected event before the registration should be ignored. + settings_helper_.SetBoolean(chromeos::kHeartbeatEnabled, true); + gcm_driver_.NotifyConnected(); + task_runner_->RunPendingTasks(); + testing::Mock::VerifyAndClearExpectations(&gcm_driver_); + + // Ignore unintested calls. + EXPECT_CALL(gcm_driver_, RegisterImpl(kHeartbeatGCMAppID, _)) + .Times(AnyNumber()); + EXPECT_CALL(gcm_driver_, SendImpl(kHeartbeatGCMAppID, _, IsHeartbeatMsg())) + .Times(AnyNumber()); + gcm_driver_.IgnoreDefaultHeartbeatsInterval(); + + EXPECT_CALL(gcm_driver_, + SendImpl(kHeartbeatGCMAppID, _, IsUpstreamNotificationMsg())) + .Times(AtLeast(1)); + gcm_driver_.CompleteRegistration(kHeartbeatGCMAppID, gcm::GCMClient::SUCCESS); + + gcm_driver_.NotifyConnected(); +} + } // namespace
diff --git a/chrome/browser/chromeos/ui/echo_dialog_view.cc b/chrome/browser/chromeos/ui/echo_dialog_view.cc index 7c3cb9b..1c373b9 100644 --- a/chrome/browser/chromeos/ui/echo_dialog_view.cc +++ b/chrome/browser/chromeos/ui/echo_dialog_view.cc
@@ -151,7 +151,8 @@ return false; } -void EchoDialogView::StyledLabelLinkClicked(const gfx::Range& range, +void EchoDialogView::StyledLabelLinkClicked(views::StyledLabel* label, + const gfx::Range& range, int event_flags) { if (!listener_) return;
diff --git a/chrome/browser/chromeos/ui/echo_dialog_view.h b/chrome/browser/chromeos/ui/echo_dialog_view.h index 85f29b1..935b4e3 100644 --- a/chrome/browser/chromeos/ui/echo_dialog_view.h +++ b/chrome/browser/chromeos/ui/echo_dialog_view.h
@@ -62,7 +62,8 @@ bool ShouldShowWindowIcon() const override; // views::LinkListener override. - void StyledLabelLinkClicked(const gfx::Range& range, + void StyledLabelLinkClicked(views::StyledLabel* label, + const gfx::Range& range, int event_flags) override; // views::View override.
diff --git a/chrome/browser/devtools/BUILD.gn b/chrome/browser/devtools/BUILD.gn index 496e553..3088e41 100644 --- a/chrome/browser/devtools/BUILD.gn +++ b/chrome/browser/devtools/BUILD.gn
@@ -67,18 +67,18 @@ if (!is_android) { deps += [ - "//chrome/app/theme:theme_resources", - "//chrome/common/extensions/api", + ":webrtc_device_provider_resources", "//chrome:extra_resources", "//chrome:resources", "//chrome:strings", + "//chrome/app/theme:theme_resources", + "//chrome/common/extensions/api", "//components/devtools_http_handler", "//net:http_server", "//skia", "//third_party/icu", "//third_party/leveldatabase", "//third_party/libusb", - ":webrtc_device_provider_resources", ] sources += [ "chrome_devtools_discovery_provider.cc",
diff --git a/chrome/browser/dom_distiller/dom_distiller_service_factory.cc b/chrome/browser/dom_distiller/dom_distiller_service_factory.cc index 497d5a1..6923b62 100644 --- a/chrome/browser/dom_distiller/dom_distiller_service_factory.cc +++ b/chrome/browser/dom_distiller/dom_distiller_service_factory.cc
@@ -76,6 +76,11 @@ options.set_debug_level(logging::GetVlogLevelHelper( FROM_HERE.file_name(), ::strlen(FROM_HERE.file_name()))); } + // Options for pagination algorithm: + // - "next": detect anchors with "next" text + // - "pagenum": detect anchors with numeric page numbers + // Default is "next". + options.set_pagination_algo("next"); scoped_ptr<DistillerFactory> distiller_factory( new DistillerFactoryImpl(distiller_url_fetcher_factory.Pass(), options)); scoped_ptr<DistilledPagePrefs> distilled_page_prefs(
diff --git a/chrome/browser/extensions/BUILD.gn b/chrome/browser/extensions/BUILD.gn index 14208a9..c093041 100644 --- a/chrome/browser/extensions/BUILD.gn +++ b/chrome/browser/extensions/BUILD.gn
@@ -55,13 +55,14 @@ "//crypto", "//device/bluetooth", "//device/hid", + "//extensions:extensions_resources", "//extensions/browser", "//extensions/common/api", "//extensions/common/api:api_registration", "//extensions/strings", - "//extensions:extensions_resources", "//net", "//skia", + "//storage/browser", "//storage/common", "//sync", "//third_party/WebKit/public:image_resources", @@ -80,7 +81,6 @@ "//ui/resources", "//ui/strings", "//url", - "//storage/browser", ] if (is_chromeos) { @@ -91,10 +91,10 @@ sources -= [ "api/music_manager_private/device_id_linux.cc" ] configs += [ "//build/config/linux:dbus" ] deps += [ - "//third_party/protobuf:protobuf_lite", "//chromeos/ime:gencode", "//components/chrome_apps", "//remoting/host/it2me:common", + "//third_party/protobuf:protobuf_lite", ] } else { sources += [
diff --git a/chrome/browser/extensions/api/cookies/cookies_api.cc b/chrome/browser/extensions/api/cookies/cookies_api.cc index 558f90d..7f00ee3 100644 --- a/chrome/browser/extensions/api/cookies/cookies_api.cc +++ b/chrome/browser/extensions/api/cookies/cookies_api.cc
@@ -381,6 +381,11 @@ base::Time::FromDoubleT(*parsed_args_->details.expiration_date); } + bool are_experimental_cookie_features_enabled = + store_browser_context_->GetURLRequestContext() + ->network_delegate() + ->AreExperimentalCookieFeaturesEnabled(); + cookie_monster->SetCookieWithDetailsAsync( url_, parsed_args_->details.name.get() ? *parsed_args_->details.name : std::string(), @@ -398,10 +403,8 @@ // TODO(mkwst): If we decide to ship First-party-only cookies, we'll need // to extend the extension API to support them. For the moment, we'll set // all cookies as non-First-party-only. - false, store_browser_context_->GetURLRequestContext() - ->network_delegate() - ->AreExperimentalCookieFeaturesEnabled(), - net::COOKIE_PRIORITY_DEFAULT, + false, are_experimental_cookie_features_enabled, + are_experimental_cookie_features_enabled, net::COOKIE_PRIORITY_DEFAULT, base::Bind(&CookiesSetFunction::PullCookie, this)); }
diff --git a/chrome/browser/extensions/api/desktop_capture/desktop_capture_base.cc b/chrome/browser/extensions/api/desktop_capture/desktop_capture_base.cc index 74e1b57..a15e8fb 100644 --- a/chrome/browser/extensions/api/desktop_capture/desktop_capture_base.cc +++ b/chrome/browser/extensions/api/desktop_capture/desktop_capture_base.cc
@@ -130,7 +130,12 @@ // DesktopMediaPicker is implemented only for Windows, OSX and // Aura Linux builds. -#if defined(TOOLKIT_VIEWS) || defined(OS_MACOSX) + // TODO(bshe): Use ANDROID_JAVA_UI flag here after it landed. +#if (defined(TOOLKIT_VIEWS) && !defined(OS_ANDROID)) || defined(OS_MACOSX) + // TODO(bshe): This is called if chrome.desktopCapture.chooseDesktopMedia + // or chrome.webrtcDesktopCapturePrivate.chooseDesktopMedia are called by + // extensions. Simply return error message on Android platform for now. + // Revisit this when necessary. See crbug.com/557424. picker_ = DesktopMediaPicker::Create(); #else error_ = "Desktop Capture API is not yet implemented for this platform.";
diff --git a/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_api.cc b/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_api.cc index 122dcffd..5e03a09 100644 --- a/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_api.cc +++ b/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_api.cc
@@ -6,6 +6,7 @@ #include <vector> +#include "base/base64url.h" #include "base/bind.h" #include "base/command_line.h" #include "base/lazy_instance.h" @@ -30,7 +31,6 @@ #include "components/proximity_auth/ble/bluetooth_low_energy_connection_finder.h" #include "components/proximity_auth/bluetooth_throttler_impl.h" #include "components/proximity_auth/bluetooth_util.h" -#include "components/proximity_auth/cryptauth/base64url.h" #include "components/proximity_auth/cryptauth/cryptauth_device_manager.h" #include "components/proximity_auth/cryptauth/cryptauth_enrollment_manager.h" #include "components/proximity_auth/cryptauth/cryptauth_enrollment_utils.h" @@ -602,10 +602,12 @@ EasyUnlockService::Get(profile) ->proximity_auth_client() ->GetCryptAuthEnrollmentManager(); - proximity_auth::Base64UrlEncode(enrollment_manager->GetUserPublicKey(), - user_public_key); - proximity_auth::Base64UrlEncode(enrollment_manager->GetUserPrivateKey(), - user_private_key); + base::Base64UrlEncode(enrollment_manager->GetUserPublicKey(), + base::Base64UrlEncodePolicy::INCLUDE_PADDING, + user_public_key); + base::Base64UrlEncode(enrollment_manager->GetUserPrivateKey(), + base::Base64UrlEncodePolicy::INCLUDE_PADDING, + user_private_key); } void EasyUnlockPrivateGetPermitAccessFunction:: @@ -781,8 +783,12 @@ const cryptauth::ExternalDeviceInfo& device, const std::string& persistent_symmetric_key) { std::string b64_public_key, b64_psk; - proximity_auth::Base64UrlEncode(device.public_key(), &b64_public_key); - proximity_auth::Base64UrlEncode(persistent_symmetric_key, &b64_psk); + base::Base64UrlEncode(device.public_key(), + base::Base64UrlEncodePolicy::INCLUDE_PADDING, + &b64_public_key); + base::Base64UrlEncode(persistent_symmetric_key, + base::Base64UrlEncodePolicy::INCLUDE_PADDING, + &b64_psk); // Fill in the JSON dictionary containing a single unlock key's data. scoped_ptr<base::DictionaryValue> device_dictionary(
diff --git a/chrome/browser/extensions/api/management/management_browsertest.cc b/chrome/browser/extensions/api/management/management_browsertest.cc index b2b35ef0..a7e0a30 100644 --- a/chrome/browser/extensions/api/management/management_browsertest.cc +++ b/chrome/browser/extensions/api/management/management_browsertest.cc
@@ -29,6 +29,7 @@ #include "extensions/browser/extension_registry.h" #include "extensions/browser/extension_system.h" #include "extensions/browser/notification_types.h" +#include "extensions/browser/test_extension_registry_observer.h" #include "extensions/browser/updater/extension_downloader.h" #include "extensions/test/extension_test_message_listener.h" #include "net/url_request/test_url_request_interceptor.h" @@ -317,8 +318,10 @@ // Run autoupdate and make sure version 2 of the extension was installed. ExtensionTestMessageListener listener2("v2 installed", false); + + extensions::TestExtensionRegistryObserver install_observer(registry); service->updater()->CheckNow(params); - ASSERT_TRUE(WaitForExtensionInstall()); + install_observer.WaitForExtensionWillBeInstalled(); listener2.WaitUntilSatisfied(); ASSERT_EQ(size_before + 1, registry->enabled_extensions().size()); extension = service->GetExtensionById( @@ -406,10 +409,11 @@ base::Unretained(¬ification_listener)); ExtensionTestMessageListener listener2("v2 installed", false); + extensions::TestExtensionRegistryObserver install_observer(registry); // Run autoupdate and make sure version 2 of the extension was installed but // is still disabled. service->updater()->CheckNow(params); - ASSERT_TRUE(WaitForExtensionInstall()); + install_observer.WaitForExtensionWillBeInstalled(); ASSERT_EQ(disabled_size_before + 1, registry->disabled_extensions().size()); ASSERT_EQ(enabled_size_before, registry->enabled_extensions().size()); extension = service->GetExtensionById( @@ -471,9 +475,10 @@ Extension::NO_FLAGS, false)); + extensions::TestExtensionRegistryObserver install_observer(registry); // Run autoupdate and make sure version 2 of the extension was installed. service->updater()->CheckNow(params); - ASSERT_TRUE(WaitForExtensionInstall()); + install_observer.WaitForExtensionWillBeInstalled(); ASSERT_EQ(size_before + 1, registry->enabled_extensions().size()); const Extension* extension = service->GetExtensionById(kExtensionId, false); ASSERT_TRUE(extension); @@ -566,10 +571,11 @@ policy::POLICY_SOURCE_CLOUD, forcelist.DeepCopy(), NULL); + extensions::TestExtensionRegistryObserver install_observer(registry); UpdateProviderPolicy(policies); + install_observer.WaitForExtensionWillBeInstalled(); // Check if the extension got installed. - ASSERT_TRUE(WaitForExtensionInstall()); ASSERT_EQ(size_before + 1, registry->enabled_extensions().size()); const Extension* extension = service->GetExtensionById(kExtensionId, false); ASSERT_TRUE(extension); @@ -656,9 +662,10 @@ policy::POLICY_SOURCE_CLOUD, forcelist.DeepCopy(), NULL); + extensions::TestExtensionRegistryObserver install_observer(registry); UpdateProviderPolicy(policies); + install_observer.WaitForExtensionWillBeInstalled(); - ASSERT_TRUE(WaitForExtensionInstall()); ASSERT_EQ(size_before + 1, registry->enabled_extensions().size()); extension = service->GetExtensionById(kExtensionId, false); ASSERT_TRUE(extension); @@ -698,9 +705,11 @@ policy::POLICY_SOURCE_CLOUD, forcelist.DeepCopy(), NULL); - UpdateProviderPolicy(policies); - ASSERT_TRUE(WaitForExtensionInstall()); + extensions::TestExtensionRegistryObserver extension_observer(registry); + UpdateProviderPolicy(policies); + extension_observer.WaitForExtensionWillBeInstalled(); + ASSERT_EQ(size_before + 1, registry->enabled_extensions().size()); extension = service->GetExtensionById(kExtensionId, false); ASSERT_TRUE(extension);
diff --git a/chrome/browser/extensions/dev_mode_bubble_delegate.cc b/chrome/browser/extensions/dev_mode_bubble_delegate.cc index 5f723de..1ac48c9 100644 --- a/chrome/browser/extensions/dev_mode_bubble_delegate.cc +++ b/chrome/browser/extensions/dev_mode_bubble_delegate.cc
@@ -19,13 +19,6 @@ namespace extensions { -namespace { - -base::LazyInstance<std::set<Profile*> > g_shown_for_profiles = - LAZY_INSTANCE_INITIALIZER; - -} // namespace - DevModeBubbleDelegate::DevModeBubbleDelegate(Profile* profile) : ExtensionMessageBubbleController::Delegate(profile) { } @@ -105,13 +98,12 @@ action, ExtensionMessageBubbleController::ACTION_BOUNDARY); } -std::set<Profile*>* DevModeBubbleDelegate::GetProfileSet() { - return g_shown_for_profiles.Pointer(); +const char* DevModeBubbleDelegate::GetKey() { + return "DevModeBubbleDelegate"; } -// static -void DevModeBubbleDelegate::ClearProfileListForTesting() { - g_shown_for_profiles.Get().clear(); +bool DevModeBubbleDelegate::ClearProfileSetAfterAction() { + return false; } } // namespace extensions
diff --git a/chrome/browser/extensions/dev_mode_bubble_delegate.h b/chrome/browser/extensions/dev_mode_bubble_delegate.h index b8bdaab..7412aa7a 100644 --- a/chrome/browser/extensions/dev_mode_bubble_delegate.h +++ b/chrome/browser/extensions/dev_mode_bubble_delegate.h
@@ -40,9 +40,8 @@ bool ShouldLimitToEnabledExtensions() const override; void LogExtensionCount(size_t count) override; void LogAction(ExtensionMessageBubbleController::BubbleAction) override; - std::set<Profile*>* GetProfileSet() override; - - static void ClearProfileListForTesting(); + const char* GetKey() override; + bool ClearProfileSetAfterAction() override; private: DISALLOW_COPY_AND_ASSIGN(DevModeBubbleDelegate);
diff --git a/chrome/browser/extensions/extension_browsertest.h b/chrome/browser/extensions/extension_browsertest.h index 0f3b1a3..65d1d92e 100644 --- a/chrome/browser/extensions/extension_browsertest.h +++ b/chrome/browser/extensions/extension_browsertest.h
@@ -243,12 +243,6 @@ return observer_->WaitForPageActionVisibilityChangeTo(count); } - // Waits until an extension is installed and loaded. Returns true if an - // install happened before timeout. - bool WaitForExtensionInstall() { - return observer_->WaitForExtensionInstall(); - } - // Wait for an extension install error to be raised. Returns true if an // error was raised. bool WaitForExtensionInstallError() {
diff --git a/chrome/browser/extensions/extension_disabled_ui_browsertest.cc b/chrome/browser/extensions/extension_disabled_ui_browsertest.cc index 59822df6..7c16a03 100644 --- a/chrome/browser/extensions/extension_disabled_ui_browsertest.cc +++ b/chrome/browser/extensions/extension_disabled_ui_browsertest.cc
@@ -24,6 +24,7 @@ #include "extensions/browser/extension_prefs.h" #include "extensions/browser/extension_registry.h" #include "extensions/browser/extension_system.h" +#include "extensions/browser/test_extension_registry_observer.h" #include "extensions/common/extension.h" #include "net/url_request/test_url_request_interceptor.h" #include "sync/protocol/extension_specifics.pb.h" @@ -208,12 +209,13 @@ extensions::ExtensionUpdater::CheckParams params; service_->updater()->set_default_check_params(params); + extensions::TestExtensionRegistryObserver install_observer(registry_); sync_service->ProcessSyncChanges( FROM_HERE, syncer::SyncChangeList( 1, sync_data.GetSyncChange(syncer::SyncChange::ACTION_ADD))); - WaitForExtensionInstall(); + install_observer.WaitForExtensionWillBeInstalled(); content::RunAllBlockingPoolTasksUntilIdle(); extension = service_->GetExtensionById(extension_id, true); @@ -261,6 +263,8 @@ base::Time::Now(), syncer::AttachmentIdList(), syncer::AttachmentServiceProxy()); + + extensions::TestExtensionRegistryObserver install_observer(registry_); ExtensionSyncService::Get(profile())->ProcessSyncChanges( FROM_HERE, syncer::SyncChangeList( @@ -268,7 +272,7 @@ syncer::SyncChange::ACTION_ADD, sync_data))); - WaitForExtensionInstall(); + install_observer.WaitForExtensionWillBeInstalled(); content::RunAllBlockingPoolTasksUntilIdle(); const Extension* extension = service_->GetExtensionById(extension_id, true);
diff --git a/chrome/browser/extensions/extension_message_bubble_controller.cc b/chrome/browser/extensions/extension_message_bubble_controller.cc index 8dd0160..7c9d2ce 100644 --- a/chrome/browser/extensions/extension_message_bubble_controller.cc +++ b/chrome/browser/extensions/extension_message_bubble_controller.cc
@@ -5,6 +5,7 @@ #include "chrome/browser/extensions/extension_message_bubble_controller.h" #include "base/bind.h" +#include "base/lazy_instance.h" #include "base/metrics/histogram.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_util.h" @@ -24,12 +25,18 @@ namespace extensions { namespace { + // How many extensions to show in the bubble (max). const int kMaxExtensionsToShow = 7; // Whether or not to ignore the learn more link navigation for testing. bool g_should_ignore_learn_more_for_testing = false; -} + +using ProfileSetMap = std::map<std::string, std::set<Profile*>>; +base::LazyInstance<ProfileSetMap> g_shown_for_profiles = + LAZY_INSTANCE_INITIALIZER; + +} // namespace //////////////////////////////////////////////////////////////////////////////// // ExtensionMessageBubbleController::Delegate @@ -48,6 +55,10 @@ return l10n_util::GetStringUTF16(IDS_LEARN_MORE); } +bool ExtensionMessageBubbleController::Delegate::ClearProfileSetAfterAction() { + return true; +} + bool ExtensionMessageBubbleController::Delegate::HasBubbleInfoBeenAcknowledged( const std::string& extension_id) { std::string pref_name = get_acknowledged_flag_pref_name(); @@ -71,11 +82,6 @@ value ? new base::FundamentalValue(value) : NULL); } -std::set<Profile*>* -ExtensionMessageBubbleController::Delegate::GetProfileSet() { - return nullptr; -} - std::string ExtensionMessageBubbleController::Delegate::get_acknowledged_flag_pref_name() const { @@ -108,8 +114,8 @@ } bool ExtensionMessageBubbleController::ShouldShow() { - std::set<Profile*>* profiles = delegate_->GetProfileSet(); - return (!profiles || !profiles->count(profile()->GetOriginalProfile())) && + std::set<Profile*>* profiles = GetProfileSet(); + return !profiles->count(profile()->GetOriginalProfile()) && !GetExtensionList().empty(); } @@ -170,9 +176,7 @@ } void ExtensionMessageBubbleController::OnShown() { - std::set<Profile*>* profiles = delegate_->GetProfileSet(); - if (profiles) - profiles->insert(profile()->GetOriginalProfile()); + GetProfileSet()->insert(profile()->GetOriginalProfile()); } void ExtensionMessageBubbleController::OnBubbleAction() { @@ -185,18 +189,21 @@ OnClose(); } -void ExtensionMessageBubbleController::OnBubbleDismiss() { +void ExtensionMessageBubbleController::OnBubbleDismiss( + bool closed_by_deactivation) { // OnBubbleDismiss() can be called twice when we receive multiple // "OnWidgetDestroying" notifications (this can at least happen when we close // a window with a notification open). Handle this gracefully. if (user_action_ != ACTION_BOUNDARY) { - DCHECK(user_action_ == ACTION_DISMISS); + DCHECK(user_action_ == ACTION_DISMISS_USER_ACTION || + user_action_ == ACTION_DISMISS_DEACTIVATION); return; } - user_action_ = ACTION_DISMISS; + user_action_ = closed_by_deactivation ? ACTION_DISMISS_DEACTIVATION + : ACTION_DISMISS_USER_ACTION; - delegate_->LogAction(ACTION_DISMISS); + delegate_->LogAction(user_action_); OnClose(); } @@ -217,6 +224,10 @@ OnClose(); } +void ExtensionMessageBubbleController::ClearProfileListForTesting() { + GetProfileSet()->clear(); +} + // static void ExtensionMessageBubbleController::set_should_ignore_learn_more_for_testing( bool should_ignore) { @@ -252,9 +263,22 @@ } void ExtensionMessageBubbleController::OnClose() { - AcknowledgeExtensions(); + DCHECK_NE(ACTION_BOUNDARY, user_action_); + // If the bubble was closed due to deactivation, don't treat it as + // acknowledgment so that the user will see the bubble again (until they + // explicitly take an action). + if (user_action_ != ACTION_DISMISS_DEACTIVATION) { + AcknowledgeExtensions(); + if (delegate_->ClearProfileSetAfterAction()) + GetProfileSet()->clear(); + } + if (did_highlight_) ToolbarActionsModel::Get(profile())->StopHighlighting(); } +std::set<Profile*>* ExtensionMessageBubbleController::GetProfileSet() { + return &g_shown_for_profiles.Get()[delegate_->GetKey()]; +} + } // namespace extensions
diff --git a/chrome/browser/extensions/extension_message_bubble_controller.h b/chrome/browser/extensions/extension_message_bubble_controller.h index 40e5b81be..c3059c5 100644 --- a/chrome/browser/extensions/extension_message_bubble_controller.h +++ b/chrome/browser/extensions/extension_message_bubble_controller.h
@@ -24,8 +24,9 @@ enum BubbleAction { ACTION_LEARN_MORE = 0, ACTION_EXECUTE, - ACTION_DISMISS, - ACTION_BOUNDARY, // Must be the last value. + ACTION_DISMISS_USER_ACTION, + ACTION_DISMISS_DEACTIVATION, + ACTION_BOUNDARY, // Must be the last value. }; class Delegate { @@ -74,14 +75,22 @@ virtual void LogExtensionCount(size_t count) = 0; virtual void LogAction(BubbleAction action) = 0; - // Has the user acknowledged info about the extension the bubble reports. - virtual bool HasBubbleInfoBeenAcknowledged(const std::string& extension_id); - virtual void SetBubbleInfoBeenAcknowledged(const std::string& extension_id, - bool value); + // Returns a key unique to the type of bubble that can be used to retrieve + // state specific to the type (e.g., shown for profiles). + virtual const char* GetKey() = 0; - // Returns the set of profiles for which this bubble has been shown. - // If profiles are not tracked, returns null (default). - virtual std::set<Profile*>* GetProfileSet(); + // Whether the "shown for profiles" set should be cleared if an action is + // taken on the bubble. This defaults to true, since once an action is + // taken, the extension will usually either be acknowledged or removed, and + // the bubble won't show for that extension. + // This should be false in cases where there is no acknowledgment option + // (as in the developer-mode extension warning). + virtual bool ClearProfileSetAfterAction(); + + // Has the user acknowledged info about the extension the bubble reports. + bool HasBubbleInfoBeenAcknowledged(const std::string& extension_id); + void SetBubbleInfoBeenAcknowledged(const std::string& extension_id, + bool value); protected: Profile* profile() { return profile_; } @@ -141,9 +150,11 @@ // Callbacks from bubble. Declared virtual for testing purposes. virtual void OnBubbleAction(); - virtual void OnBubbleDismiss(); + virtual void OnBubbleDismiss(bool dismissed_by_deactivation); virtual void OnLinkClicked(); + void ClearProfileListForTesting(); + static void set_should_ignore_learn_more_for_testing( bool should_ignore_learn_more); @@ -157,6 +168,8 @@ // Performs cleanup after the bubble closes. void OnClose(); + std::set<Profile*>* GetProfileSet(); + // A weak pointer to the Browser we are associated with. Not owned by us. Browser* browser_;
diff --git a/chrome/browser/extensions/extension_message_bubble_controller_unittest.cc b/chrome/browser/extensions/extension_message_bubble_controller_unittest.cc index 129990f..4af1301aa 100644 --- a/chrome/browser/extensions/extension_message_bubble_controller_unittest.cc +++ b/chrome/browser/extensions/extension_message_bubble_controller_unittest.cc
@@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "base/bind_helpers.h" #include "base/command_line.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_util.h" @@ -59,9 +60,9 @@ ++action_button_callback_count_; ExtensionMessageBubbleController::OnBubbleAction(); } - void OnBubbleDismiss() override { + void OnBubbleDismiss(bool by_deactivation) override { ++dismiss_button_callback_count_; - ExtensionMessageBubbleController::OnBubbleDismiss(); + ExtensionMessageBubbleController::OnBubbleDismiss(by_deactivation); } void OnLinkClicked() override { ++link_click_callback_count_; @@ -89,10 +90,12 @@ enum ExtensionBubbleAction { BUBBLE_ACTION_CLICK_ACTION_BUTTON = 0, BUBBLE_ACTION_CLICK_DISMISS_BUTTON, + BUBBLE_ACTION_DISMISS_DEACTIVATION, BUBBLE_ACTION_CLICK_LINK, }; - FakeExtensionMessageBubble() : controller_(nullptr) {} + FakeExtensionMessageBubble() + : action_(BUBBLE_ACTION_CLICK_ACTION_BUTTON), controller_(nullptr) {} void set_action_on_show(ExtensionBubbleAction action) { action_ = action; @@ -103,12 +106,20 @@ void Show() { controller_->OnShown(); - if (action_ == BUBBLE_ACTION_CLICK_ACTION_BUTTON) - controller_->OnBubbleAction(); - else if (action_ == BUBBLE_ACTION_CLICK_DISMISS_BUTTON) - controller_->OnBubbleDismiss(); - else if (action_ == BUBBLE_ACTION_CLICK_LINK) - controller_->OnLinkClicked(); + switch (action_) { + case BUBBLE_ACTION_CLICK_ACTION_BUTTON: + controller_->OnBubbleAction(); + break; + case BUBBLE_ACTION_CLICK_DISMISS_BUTTON: + controller_->OnBubbleDismiss(false); + break; + case BUBBLE_ACTION_DISMISS_DEACTIVATION: + controller_->OnBubbleDismiss(true); + break; + case BUBBLE_ACTION_CLICK_LINK: + controller_->OnLinkClicked(); + break; + } } private: @@ -305,6 +316,70 @@ DISALLOW_COPY_AND_ASSIGN(ExtensionMessageBubbleTest); }; +TEST_F(ExtensionMessageBubbleTest, BubbleReshowsOnDeactivationDismissal) { + Init(); + + ASSERT_TRUE(LoadExtensionOverridingNtp("1", kId1, Manifest::INTERNAL)); + ASSERT_TRUE(LoadExtensionOverridingNtp("2", kId2, Manifest::INTERNAL)); + scoped_ptr<TestExtensionMessageBubbleController> controller( + new TestExtensionMessageBubbleController( + new NtpOverriddenBubbleDelegate(browser()->profile()), browser())); + + // The list will contain one enabled unpacked extension (ext 2). + EXPECT_TRUE(controller->ShouldShow()); + std::vector<base::string16> override_extensions = + controller->GetExtensionList(); + ASSERT_EQ(1U, override_extensions.size()); + EXPECT_EQ(base::ASCIIToUTF16("Extension 2"), override_extensions[0]); + EXPECT_EQ(0U, controller->link_click_count()); + EXPECT_EQ(0U, controller->dismiss_click_count()); + EXPECT_EQ(0U, controller->action_click_count()); + + // Simulate showing the bubble and dismissing it due to deactivation. + FakeExtensionMessageBubble bubble; + bubble.set_action_on_show( + FakeExtensionMessageBubble::BUBBLE_ACTION_DISMISS_DEACTIVATION); + bubble.set_controller(controller.get()); + bubble.Show(); + EXPECT_EQ(0U, controller->link_click_count()); + EXPECT_EQ(0U, controller->action_click_count()); + EXPECT_EQ(1U, controller->dismiss_click_count()); + + // No extension should have become disabled. + ExtensionRegistry* registry = ExtensionRegistry::Get(profile()); + EXPECT_TRUE(registry->enabled_extensions().GetByID(kId2)); + // And since it was dismissed due to deactivation, the extension should not + // have been acknowledged. + EXPECT_FALSE(controller->delegate()->HasBubbleInfoBeenAcknowledged(kId2)); + + bubble.set_action_on_show( + FakeExtensionMessageBubble::BUBBLE_ACTION_DISMISS_DEACTIVATION); + controller.reset(new TestExtensionMessageBubbleController( + new NtpOverriddenBubbleDelegate(browser()->profile()), browser())); + // The bubble shouldn't show again for the same profile (we don't want to + // be annoying). + EXPECT_FALSE(controller->ShouldShow()); + controller->ClearProfileListForTesting(); + EXPECT_TRUE(controller->ShouldShow()); + // Explicitly click the dismiss button. The extension should be acknowledged. + bubble.set_controller(controller.get()); + bubble.set_action_on_show( + FakeExtensionMessageBubble::BUBBLE_ACTION_CLICK_DISMISS_BUTTON); + bubble.Show(); + EXPECT_TRUE(controller->delegate()->HasBubbleInfoBeenAcknowledged(kId2)); + + // Uninstall the current ntp-controlling extension, allowing the other to + // take control. + service_->UninstallExtension(kId2, UNINSTALL_REASON_FOR_TESTING, + base::Bind(&base::DoNothing), nullptr); + + // Even though we already showed for the given profile, we should show again, + // because it's a different extension. + controller.reset(new TestExtensionMessageBubbleController( + new NtpOverriddenBubbleDelegate(browser()->profile()), browser())); + EXPECT_TRUE(controller->ShouldShow()); +} + // The feature this is meant to test is only enacted on Windows, but it should // pass on all platforms. TEST_F(ExtensionMessageBubbleTest, WipeoutControllerTest) { @@ -343,7 +418,7 @@ new TestExtensionMessageBubbleController( new SuspiciousExtensionBubbleDelegate(browser()->profile()), browser())); - SuspiciousExtensionBubbleDelegate::ClearProfileListForTesting(); + controller->ClearProfileListForTesting(); EXPECT_TRUE(controller->ShouldShow()); suspicious_extensions = controller->GetExtensionList(); ASSERT_EQ(1U, suspicious_extensions.size()); @@ -368,7 +443,7 @@ new TestExtensionMessageBubbleController( new SuspiciousExtensionBubbleDelegate(browser()->profile()), browser())); - SuspiciousExtensionBubbleDelegate::ClearProfileListForTesting(); + controller->ClearProfileListForTesting(); EXPECT_TRUE(controller->ShouldShow()); suspicious_extensions = controller->GetExtensionList(); ASSERT_EQ(2U, suspicious_extensions.size()); @@ -430,7 +505,12 @@ new TestExtensionMessageBubbleController( new DevModeBubbleDelegate(browser()->profile()), browser())); - DevModeBubbleDelegate::ClearProfileListForTesting(); + // Most bubbles would want to show again as long as the extensions weren't + // acknowledged and the bubble wasn't dismissed due to deactivation. Since dev + // mode extensions can't be (persistently) acknowledged, this isn't the case + // for the dev mode bubble, and we should only show once per profile. + EXPECT_FALSE(controller->ShouldShow()); + controller->ClearProfileListForTesting(); EXPECT_TRUE(controller->ShouldShow()); dev_mode_extensions = controller->GetExtensionList(); EXPECT_EQ(2U, dev_mode_extensions.size()); @@ -453,7 +533,7 @@ new TestExtensionMessageBubbleController( new DevModeBubbleDelegate(browser()->profile()), browser())); - DevModeBubbleDelegate::ClearProfileListForTesting(); + controller->ClearProfileListForTesting(); EXPECT_TRUE(controller->ShouldShow()); dev_mode_extensions = controller->GetExtensionList(); EXPECT_EQ(2U, dev_mode_extensions.size()); @@ -473,7 +553,7 @@ new TestExtensionMessageBubbleController( new DevModeBubbleDelegate(browser()->profile()), browser())); - DevModeBubbleDelegate::ClearProfileListForTesting(); + controller->ClearProfileListForTesting(); EXPECT_FALSE(controller->ShouldShow()); dev_mode_extensions = controller->GetExtensionList(); EXPECT_EQ(0U, dev_mode_extensions.size());
diff --git a/chrome/browser/extensions/extension_service.cc b/chrome/browser/extensions/extension_service.cc index fc5a382..c5e68c7 100644 --- a/chrome/browser/extensions/extension_service.cc +++ b/chrome/browser/extensions/extension_service.cc
@@ -1936,12 +1936,6 @@ } bool from_ephemeral = was_ephemeral && !extension_prefs_->IsEphemeralApp(extension->id()); - extensions::InstalledExtensionInfo details( - extension, is_update, from_ephemeral, old_name); - content::NotificationService::current()->Notify( - extensions::NOTIFICATION_EXTENSION_WILL_BE_INSTALLED_DEPRECATED, - content::Source<Profile>(profile_), - content::Details<const extensions::InstalledExtensionInfo>(&details)); registry_->TriggerOnWillBeInstalled( extension, is_update, from_ephemeral, old_name); @@ -1989,16 +1983,6 @@ // Fire install-related events to allow observers to handle the promotion // of the ephemeral app. - extensions::InstalledExtensionInfo details( - extension, - true /* is update */, - true /* from ephemeral */, - extension->name() /* old name */); - content::NotificationService::current()->Notify( - extensions::NOTIFICATION_EXTENSION_WILL_BE_INSTALLED_DEPRECATED, - content::Source<Profile>(profile_), - content::Details<const extensions::InstalledExtensionInfo>(&details)); - registry_->TriggerOnWillBeInstalled( extension, true /* is update */,
diff --git a/chrome/browser/extensions/extension_test_notification_observer.cc b/chrome/browser/extensions/extension_test_notification_observer.cc index da99e296..62b55e6 100644 --- a/chrome/browser/extensions/extension_test_notification_observer.cc +++ b/chrome/browser/extensions/extension_test_notification_observer.cc
@@ -172,13 +172,6 @@ return true; } -bool ExtensionTestNotificationObserver::WaitForExtensionInstall() { - int before = extension_installs_observed_; - WaitForNotification( - extensions::NOTIFICATION_EXTENSION_WILL_BE_INSTALLED_DEPRECATED); - return extension_installs_observed_ == (before + 1); -} - bool ExtensionTestNotificationObserver::WaitForExtensionInstallError() { int before = extension_installs_observed_; content::WindowedNotificationObserver( @@ -262,11 +255,6 @@ ++crx_installers_done_observed_; break; - case extensions::NOTIFICATION_EXTENSION_WILL_BE_INSTALLED_DEPRECATED: - VLOG(1) << "Got EXTENSION_INSTALLED notification."; - ++extension_installs_observed_; - break; - case extensions::NOTIFICATION_EXTENSION_LOAD_ERROR: VLOG(1) << "Got EXTENSION_LOAD_ERROR notification."; ++extension_load_errors_observed_;
diff --git a/chrome/browser/extensions/extension_test_notification_observer.h b/chrome/browser/extensions/extension_test_notification_observer.h index 214c824..08dce93 100644 --- a/chrome/browser/extensions/extension_test_notification_observer.h +++ b/chrome/browser/extensions/extension_test_notification_observer.h
@@ -32,10 +32,6 @@ // Wait for the number of visible page actions to change to |count|. bool WaitForPageActionVisibilityChangeTo(int count); - // Waits until an extension is installed and loaded. Returns true if an - // install happened before timeout. - bool WaitForExtensionInstall(); - // Wait for an extension install error to be raised. Returns true if an // error was raised. bool WaitForExtensionInstallError();
diff --git a/chrome/browser/extensions/ntp_overridden_bubble_delegate.cc b/chrome/browser/extensions/ntp_overridden_bubble_delegate.cc index f76ebdc8..c2baee0f 100644 --- a/chrome/browser/extensions/ntp_overridden_bubble_delegate.cc +++ b/chrome/browser/extensions/ntp_overridden_bubble_delegate.cc
@@ -129,4 +129,8 @@ ExtensionMessageBubbleController::ACTION_BOUNDARY); } +const char* NtpOverriddenBubbleDelegate::GetKey() { + return "NtpOverriddenBubbleDelegate"; +} + } // namespace extensions
diff --git a/chrome/browser/extensions/ntp_overridden_bubble_delegate.h b/chrome/browser/extensions/ntp_overridden_bubble_delegate.h index 80026ab..357d09ce 100644 --- a/chrome/browser/extensions/ntp_overridden_bubble_delegate.h +++ b/chrome/browser/extensions/ntp_overridden_bubble_delegate.h
@@ -39,6 +39,7 @@ bool ShouldLimitToEnabledExtensions() const override; void LogExtensionCount(size_t count) override; void LogAction(ExtensionMessageBubbleController::BubbleAction) override; + const char* GetKey() override; private: // The ID of the extension we are showing the bubble for.
diff --git a/chrome/browser/extensions/proxy_overridden_bubble_delegate.cc b/chrome/browser/extensions/proxy_overridden_bubble_delegate.cc index 59c7dd43..b2b3db5b 100644 --- a/chrome/browser/extensions/proxy_overridden_bubble_delegate.cc +++ b/chrome/browser/extensions/proxy_overridden_bubble_delegate.cc
@@ -143,4 +143,8 @@ ExtensionMessageBubbleController::ACTION_BOUNDARY); } +const char* ProxyOverriddenBubbleDelegate::GetKey() { + return "ProxyOverriddenBubbleDelegate"; +} + } // namespace extensions
diff --git a/chrome/browser/extensions/proxy_overridden_bubble_delegate.h b/chrome/browser/extensions/proxy_overridden_bubble_delegate.h index cbd851d1..dedc843 100644 --- a/chrome/browser/extensions/proxy_overridden_bubble_delegate.h +++ b/chrome/browser/extensions/proxy_overridden_bubble_delegate.h
@@ -40,6 +40,7 @@ bool ShouldLimitToEnabledExtensions() const override; void LogExtensionCount(size_t count) override; void LogAction(ExtensionMessageBubbleController::BubbleAction) override; + const char* GetKey() override; private: // The ID of the extension we are showing the bubble for.
diff --git a/chrome/browser/extensions/settings_api_bubble_delegate.cc b/chrome/browser/extensions/settings_api_bubble_delegate.cc index 2641883f..26ac3da 100644 --- a/chrome/browser/extensions/settings_api_bubble_delegate.cc +++ b/chrome/browser/extensions/settings_api_bubble_delegate.cc
@@ -238,4 +238,17 @@ } } +const char* SettingsApiBubbleDelegate::GetKey() { + switch (type_) { + case BUBBLE_TYPE_HOME_PAGE: + return "SettingsApiBubbleDelegate.HomePage"; + case BUBBLE_TYPE_STARTUP_PAGES: + return "SettingsApiBubbleDelegate.StartupPages"; + case BUBBLE_TYPE_SEARCH_ENGINE: + return "SettingsApiBubbleDelegate.SearchEngine"; + } + NOTREACHED(); + return ""; +} + } // namespace extensions
diff --git a/chrome/browser/extensions/settings_api_bubble_delegate.h b/chrome/browser/extensions/settings_api_bubble_delegate.h index dde081d3..aea8350 100644 --- a/chrome/browser/extensions/settings_api_bubble_delegate.h +++ b/chrome/browser/extensions/settings_api_bubble_delegate.h
@@ -39,6 +39,7 @@ bool ShouldLimitToEnabledExtensions() const override; void LogExtensionCount(size_t count) override; void LogAction(ExtensionMessageBubbleController::BubbleAction) override; + const char* GetKey() override; private: // The type of settings override this bubble will report on. This can be, for
diff --git a/chrome/browser/extensions/suspicious_extension_bubble_delegate.cc b/chrome/browser/extensions/suspicious_extension_bubble_delegate.cc index c4b95ed..33381d71d 100644 --- a/chrome/browser/extensions/suspicious_extension_bubble_delegate.cc +++ b/chrome/browser/extensions/suspicious_extension_bubble_delegate.cc
@@ -26,9 +26,6 @@ // Whether the user has been notified about extension being wiped out. const char kWipeoutAcknowledged[] = "ack_wiped"; -base::LazyInstance<std::set<Profile*> > g_shown_for_profiles = - LAZY_INSTANCE_INITIALIZER; - } // namespace namespace extensions { @@ -132,13 +129,8 @@ action, ExtensionMessageBubbleController::ACTION_BOUNDARY); } -std::set<Profile*>* SuspiciousExtensionBubbleDelegate::GetProfileSet() { - return g_shown_for_profiles.Pointer(); -} - -// static -void SuspiciousExtensionBubbleDelegate::ClearProfileListForTesting() { - g_shown_for_profiles.Get().clear(); +const char* SuspiciousExtensionBubbleDelegate::GetKey() { + return "SuspiciousExtensionBubbleDelegate"; } } // namespace extensions
diff --git a/chrome/browser/extensions/suspicious_extension_bubble_delegate.h b/chrome/browser/extensions/suspicious_extension_bubble_delegate.h index 9ecad2668..0d1406e 100644 --- a/chrome/browser/extensions/suspicious_extension_bubble_delegate.h +++ b/chrome/browser/extensions/suspicious_extension_bubble_delegate.h
@@ -38,11 +38,7 @@ bool ShouldLimitToEnabledExtensions() const override; void LogExtensionCount(size_t count) override; void LogAction(ExtensionMessageBubbleController::BubbleAction) override; - std::set<Profile*>* GetProfileSet() override; - - // Clears the list of profiles the bubble has been shown for. Should only be - // used during testing. - static void ClearProfileListForTesting(); + const char* GetKey() override; private: DISALLOW_COPY_AND_ASSIGN(SuspiciousExtensionBubbleDelegate);
diff --git a/chrome/browser/interstitials/security_interstitial_page.cc b/chrome/browser/interstitials/security_interstitial_page.cc index 0cc658e..d476177 100644 --- a/chrome/browser/interstitials/security_interstitial_page.cc +++ b/chrome/browser/interstitials/security_interstitial_page.cc
@@ -79,46 +79,12 @@ interstitial_page_->Show(); } -void SecurityInterstitialPage::SetReportingPreference(bool report) { - Profile* profile = - Profile::FromBrowserContext(web_contents()->GetBrowserContext()); - PrefService* pref = profile->GetPrefs(); - pref->SetBoolean(prefs::kSafeBrowsingExtendedReportingEnabled, report); - metrics_helper()->RecordUserInteraction( - report ? security_interstitials::MetricsHelper:: - SET_EXTENDED_REPORTING_ENABLED - : security_interstitials::MetricsHelper:: - SET_EXTENDED_REPORTING_DISABLED); -} - bool SecurityInterstitialPage::IsPrefEnabled(const char* pref) { Profile* profile = Profile::FromBrowserContext(web_contents()->GetBrowserContext()); return profile->GetPrefs()->GetBoolean(pref); } -void SecurityInterstitialPage::OpenExtendedReportingPrivacyPolicy() { - metrics_helper()->RecordUserInteraction( - security_interstitials::MetricsHelper::SHOW_PRIVACY_POLICY); - GURL privacy_url( - l10n_util::GetStringUTF8(IDS_SAFE_BROWSING_PRIVACY_POLICY_URL)); - privacy_url = google_util::AppendGoogleLocaleParam( - privacy_url, g_browser_process->GetApplicationLocale()); - OpenURLParams params(privacy_url, Referrer(), CURRENT_TAB, - ui::PAGE_TRANSITION_LINK, false); - web_contents()->OpenURL(params); -} - -security_interstitials::MetricsHelper* -SecurityInterstitialPage::metrics_helper() const { - return metrics_helper_.get(); -} - -void SecurityInterstitialPage::set_metrics_helper( - scoped_ptr<security_interstitials::MetricsHelper> metrics_helper) { - metrics_helper_ = metrics_helper.Pass(); -} - base::string16 SecurityInterstitialPage::GetFormattedHostName() const { std::string languages; Profile* profile = @@ -143,3 +109,23 @@ webui::AppendWebUiCssTextDefaults(&html); return webui::GetI18nTemplateHtml(html, &load_time_data); } + +void SecurityInterstitialPage::OpenUrlInCurrentTab(const GURL& url) { + OpenURLParams params(url, Referrer(), CURRENT_TAB, ui::PAGE_TRANSITION_LINK, + false); + web_contents()->OpenURL(params); +} + +const std::string& SecurityInterstitialPage::GetApplicationLocale() { + return g_browser_process->GetApplicationLocale(); +} + +PrefService* SecurityInterstitialPage::GetPrefService() { + Profile* profile = + Profile::FromBrowserContext(web_contents()->GetBrowserContext()); + return profile->GetPrefs(); +} + +const std::string SecurityInterstitialPage::GetExtendedReportingPrefName() { + return prefs::kSafeBrowsingExtendedReportingEnabled; +}
diff --git a/chrome/browser/interstitials/security_interstitial_page.h b/chrome/browser/interstitials/security_interstitial_page.h index 13c547df..215253eb 100644 --- a/chrome/browser/interstitials/security_interstitial_page.h +++ b/chrome/browser/interstitials/security_interstitial_page.h
@@ -6,6 +6,7 @@ #define CHROME_BROWSER_INTERSTITIALS_SECURITY_INTERSTITIAL_PAGE_H_ #include "base/strings/string16.h" +#include "components/security_interstitials/core/controller_client.h" #include "content/public/browser/interstitial_page_delegate.h" #include "url/gurl.h" @@ -26,39 +27,10 @@ extern const char kPrivacyLinkHtml[]; } -namespace security_interstitials { -class MetricsHelper; -} - -class SecurityInterstitialPage : public content::InterstitialPageDelegate { +class SecurityInterstitialPage + : public content::InterstitialPageDelegate, + public security_interstitials::ControllerClient { public: - // These represent the commands sent from the interstitial JavaScript. - // DO NOT reorder or change these without also changing the JavaScript! - // See chrome/browser/resources/security_warnings/interstitial_v2.js - enum SecurityInterstitialCommands { - // Used by tests - CMD_ERROR = -3, - CMD_TEXT_FOUND = -2, - CMD_TEXT_NOT_FOUND = -1, - // Decisions - CMD_DONT_PROCEED = 0, - CMD_PROCEED = 1, - // Ways for user to get more information - CMD_SHOW_MORE_SECTION = 2, - CMD_OPEN_HELP_CENTER = 3, - CMD_OPEN_DIAGNOSTIC = 4, - // Primary button actions - CMD_RELOAD = 5, - CMD_OPEN_DATE_SETTINGS = 6, - CMD_OPEN_LOGIN = 7, - // Safe Browsing Extended Reporting - CMD_DO_REPORT = 8, - CMD_DONT_REPORT = 9, - CMD_OPEN_REPORTING_PRIVACY = 10, - // Report a phishing error - CMD_REPORT_PHISHING_ERROR = 11, - }; - SecurityInterstitialPage(content::WebContents* web_contents, const GURL& url); ~SecurityInterstitialPage() override; @@ -87,22 +59,18 @@ content::WebContents* web_contents() const; GURL request_url() const; - // Record the user's preference for reporting information about - // malware and SSL errors. - void SetReportingPreference(bool report); - // Returns the boolean value of the given |pref| from the PrefService of the // Profile associated with |web_contents_|. bool IsPrefEnabled(const char* pref); - void OpenExtendedReportingPrivacyPolicy(); - - security_interstitials::MetricsHelper* metrics_helper() const; - void set_metrics_helper( - scoped_ptr<security_interstitials::MetricsHelper> metrics_helper); + protected: + // security_interstitials::ControllerClient overrides + void OpenUrlInCurrentTab(const GURL& url) override; + const std::string& GetApplicationLocale() override; + PrefService* GetPrefService() override; + const std::string GetExtendedReportingPrefName() override; private: - scoped_ptr<security_interstitials::MetricsHelper> metrics_helper_; // The WebContents with which this interstitial page is // associated. Not available in ~SecurityInterstitialPage, since it // can be destroyed before this class is destroyed.
diff --git a/chrome/browser/net/chrome_extensions_network_delegate.cc b/chrome/browser/net/chrome_extensions_network_delegate.cc index 42fc490..75c6f2b9 100644 --- a/chrome/browser/net/chrome_extensions_network_delegate.cc +++ b/chrome/browser/net/chrome_extensions_network_delegate.cc
@@ -109,7 +109,6 @@ void OnResponseStarted(net::URLRequest* request) override; void OnCompleted(net::URLRequest* request, bool started) override; void OnURLRequestDestroyed(net::URLRequest* request) override; - void OnURLRequestJobOrphaned(net::URLRequest* request) override; void OnPACScriptError(int line_number, const base::string16& error) override; net::NetworkDelegate::AuthRequiredResponse OnAuthRequired( net::URLRequest* request, @@ -237,12 +236,6 @@ profile_, request); } -void ChromeExtensionsNetworkDelegateImpl::OnURLRequestJobOrphaned( - net::URLRequest* request) { - ExtensionWebRequestEventRouter::GetInstance()->OnURLRequestJobOrphaned( - profile_, request); -} - void ChromeExtensionsNetworkDelegateImpl::OnPACScriptError( int line_number, const base::string16& error) { @@ -347,10 +340,6 @@ net::URLRequest* request) { } -void ChromeExtensionsNetworkDelegate::OnURLRequestJobOrphaned( - net::URLRequest* request) { -} - void ChromeExtensionsNetworkDelegate::OnPACScriptError( int line_number, const base::string16& error) {
diff --git a/chrome/browser/net/chrome_extensions_network_delegate.h b/chrome/browser/net/chrome_extensions_network_delegate.h index 0ab2dceb..156094c 100644 --- a/chrome/browser/net/chrome_extensions_network_delegate.h +++ b/chrome/browser/net/chrome_extensions_network_delegate.h
@@ -63,7 +63,6 @@ void OnResponseStarted(net::URLRequest* request) override; void OnCompleted(net::URLRequest* request, bool started) override; void OnURLRequestDestroyed(net::URLRequest* request) override; - void OnURLRequestJobOrphaned(net::URLRequest* request) override; void OnPACScriptError(int line_number, const base::string16& error) override; net::NetworkDelegate::AuthRequiredResponse OnAuthRequired( net::URLRequest* request,
diff --git a/chrome/browser/net/chrome_network_delegate.cc b/chrome/browser/net/chrome_network_delegate.cc index 507ce90f..8fd4f9b 100644 --- a/chrome/browser/net/chrome_network_delegate.cc +++ b/chrome/browser/net/chrome_network_delegate.cc
@@ -559,10 +559,6 @@ extensions_delegate_->OnURLRequestDestroyed(request); } -void ChromeNetworkDelegate::OnURLRequestJobOrphaned(net::URLRequest* request) { - extensions_delegate_->OnURLRequestJobOrphaned(request); -} - void ChromeNetworkDelegate::OnPACScriptError(int line_number, const base::string16& error) { extensions_delegate_->OnPACScriptError(line_number, error);
diff --git a/chrome/browser/net/chrome_network_delegate.h b/chrome/browser/net/chrome_network_delegate.h index a39ba5f..e0ab87af 100644 --- a/chrome/browser/net/chrome_network_delegate.h +++ b/chrome/browser/net/chrome_network_delegate.h
@@ -166,7 +166,6 @@ int64_t bytes_sent) override; void OnCompleted(net::URLRequest* request, bool started) override; void OnURLRequestDestroyed(net::URLRequest* request) override; - void OnURLRequestJobOrphaned(net::URLRequest* request) override; void OnPACScriptError(int line_number, const base::string16& error) override; net::NetworkDelegate::AuthRequiredResponse OnAuthRequired( net::URLRequest* request,
diff --git a/chrome/browser/push_messaging/PRESUBMIT.py b/chrome/browser/push_messaging/PRESUBMIT.py new file mode 100644 index 0000000..aa4ae97d --- /dev/null +++ b/chrome/browser/push_messaging/PRESUBMIT.py
@@ -0,0 +1,12 @@ +# Copyright 2015 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. + +"""Top-level presubmit script for Push Messaging. + +See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts +for more details about the presubmit API built into depot_tools. +""" + +def CheckChangeOnUpload(input_api, output_api): + return input_api.canned_checks.CheckPatchFormatted(input_api, output_api)
diff --git a/chrome/browser/push_messaging/push_messaging_app_identifier.cc b/chrome/browser/push_messaging/push_messaging_app_identifier.cc index 2acb29df..bcafe79 100644 --- a/chrome/browser/push_messaging/push_messaging_app_identifier.cc +++ b/chrome/browser/push_messaging/push_messaging_app_identifier.cc
@@ -25,21 +25,21 @@ // sizeof is strlen + 1 since it's null-terminated. const size_t kPrefixLength = sizeof(kPushMessagingAppIdentifierPrefix) - 1; -const char kSeparator = '#'; // Ok as only the origin of the url is used. +const char kSeparator = '#'; // Ok as only the origin of the url is used. const size_t kGuidLength = 36; // "%08X-%04X-%04X-%04X-%012llX" std::string MakePrefValue(const GURL& origin, int64_t service_worker_registration_id) { - return origin.spec() + kSeparator - + base::Int64ToString(service_worker_registration_id); + return origin.spec() + kSeparator + + base::Int64ToString(service_worker_registration_id); } -bool GetOriginAndSWRFromPrefValue( - const std::string& pref_value, GURL* origin, - int64_t* service_worker_registration_id) { - std::vector<std::string> parts = base::SplitString( - pref_value, std::string(1, kSeparator), - base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); +bool GetOriginAndSWRFromPrefValue(const std::string& pref_value, + GURL* origin, + int64_t* service_worker_registration_id) { + std::vector<std::string> parts = + base::SplitString(pref_value, std::string(1, kSeparator), + base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); if (parts.size() != 2) return false; @@ -64,12 +64,12 @@ // static PushMessagingAppIdentifier PushMessagingAppIdentifier::Generate( - const GURL& origin, int64_t service_worker_registration_id) -{ + const GURL& origin, + int64_t service_worker_registration_id) { std::string guid = base::GenerateGUID(); CHECK(!guid.empty()); - std::string app_id = kPushMessagingAppIdentifierPrefix + origin.spec() - + kSeparator + guid; + std::string app_id = + kPushMessagingAppIdentifierPrefix + origin.spec() + kSeparator + guid; PushMessagingAppIdentifier app_identifier(app_id, origin, service_worker_registration_id); @@ -115,9 +115,9 @@ // static PushMessagingAppIdentifier PushMessagingAppIdentifier::FindByServiceWorker( - Profile* profile, const GURL& origin, - int64_t service_worker_registration_id) -{ + Profile* profile, + const GURL& origin, + int64_t service_worker_registration_id) { const base::StringValue pref_value = base::StringValue(MakePrefValue(origin, service_worker_registration_id)); @@ -149,13 +149,12 @@ // static size_t PushMessagingAppIdentifier::GetCount(Profile* profile) { return profile->GetPrefs() - ->GetDictionary(prefs::kPushMessagingAppIdentifierMap)->size(); + ->GetDictionary(prefs::kPushMessagingAppIdentifierMap) + ->size(); } PushMessagingAppIdentifier::PushMessagingAppIdentifier() - : origin_(GURL::EmptyGURL()), - service_worker_registration_id_(-1) { -} + : origin_(GURL::EmptyGURL()), service_worker_registration_id_(-1) {} PushMessagingAppIdentifier::PushMessagingAppIdentifier( const std::string& app_id, @@ -163,11 +162,9 @@ int64_t service_worker_registration_id) : app_id_(app_id), origin_(origin), - service_worker_registration_id_(service_worker_registration_id) { -} + service_worker_registration_id_(service_worker_registration_id) {} -PushMessagingAppIdentifier::~PushMessagingAppIdentifier() { -} +PushMessagingAppIdentifier::~PushMessagingAppIdentifier() {} void PushMessagingAppIdentifier::PersistToPrefs(Profile* profile) const { DCheckValid(); @@ -178,8 +175,8 @@ // Delete any stale entry with the same origin and Service Worker // registration id (hence we ensure there is a 1:1 not 1:many mapping). - PushMessagingAppIdentifier old = FindByServiceWorker( - profile, origin_, service_worker_registration_id_); + PushMessagingAppIdentifier old = + FindByServiceWorker(profile, origin_, service_worker_registration_id_); if (!old.is_null()) map->RemoveWithoutPathExpansion(old.app_id_, nullptr /* out_value */); @@ -210,7 +207,8 @@ const size_t suffix_length = 1 /* kSeparator */ + kGuidLength; DCHECK(app_id_.size() > kPrefixLength + suffix_length); DCHECK_EQ(origin_, GURL(app_id_.substr( - kPrefixLength, app_id_.size() - kPrefixLength - suffix_length))); + kPrefixLength, + app_id_.size() - kPrefixLength - suffix_length))); DCHECK_EQ(std::string(1, kSeparator), app_id_.substr(app_id_.size() - suffix_length, 1)); }
diff --git a/chrome/browser/push_messaging/push_messaging_app_identifier_unittest.cc b/chrome/browser/push_messaging/push_messaging_app_identifier_unittest.cc index 862c7dc..4face03 100644 --- a/chrome/browser/push_messaging/push_messaging_app_identifier_unittest.cc +++ b/chrome/browser/push_messaging/push_messaging_app_identifier_unittest.cc
@@ -28,7 +28,8 @@ // To bypass DCHECK in PushMessagingAppIdentifier::Generate, we just use it // to generate app_id, and then use private constructor. std::string app_id = PushMessagingAppIdentifier::Generate( - GURL("https://www.example.com/"), 1).app_id(); + GURL("https://www.example.com/"), 1) + .app_id(); return PushMessagingAppIdentifier(app_id, origin, service_worker_registration_id); } @@ -70,26 +71,32 @@ } TEST_F(PushMessagingAppIdentifierTest, UniqueGuids) { - EXPECT_NE(PushMessagingAppIdentifier::Generate( - GURL("https://www.example.com/"), 1).app_id(), - PushMessagingAppIdentifier::Generate( - GURL("https://www.example.com/"), 1).app_id()); + EXPECT_NE( + PushMessagingAppIdentifier::Generate(GURL("https://www.example.com/"), 1) + .app_id(), + PushMessagingAppIdentifier::Generate(GURL("https://www.example.com/"), 1) + .app_id()); } TEST_F(PushMessagingAppIdentifierTest, FindInvalidAppId) { // These calls to FindByAppId should not DCHECK. EXPECT_TRUE(PushMessagingAppIdentifier::FindByAppId(profile(), "").is_null()); EXPECT_TRUE(PushMessagingAppIdentifier::FindByAppId( - profile(), "amhfneadkjmnlefnpidcijoldiibcdnd").is_null()); + profile(), "amhfneadkjmnlefnpidcijoldiibcdnd") + .is_null()); } TEST_F(PushMessagingAppIdentifierTest, PersistAndFind) { - ASSERT_TRUE(PushMessagingAppIdentifier::FindByAppId( - profile(), original_.app_id()).is_null()); - ASSERT_TRUE(PushMessagingAppIdentifier::FindByServiceWorker( - profile(), original_.origin(), original_.service_worker_registration_id()) + ASSERT_TRUE( + PushMessagingAppIdentifier::FindByAppId(profile(), original_.app_id()) .is_null()); + const auto identifier = PushMessagingAppIdentifier::FindByServiceWorker( + profile(), original_.origin(), + original_.service_worker_registration_id()); + + ASSERT_TRUE(identifier.is_null()); + // Test basic PersistToPrefs round trips. original_.PersistToPrefs(profile()); { @@ -100,8 +107,9 @@ } { PushMessagingAppIdentifier found_by_origin_and_swr_id = - PushMessagingAppIdentifier::FindByServiceWorker(profile(), - original_.origin(), original_.service_worker_registration_id()); + PushMessagingAppIdentifier::FindByServiceWorker( + profile(), original_.origin(), + original_.service_worker_registration_id()); EXPECT_FALSE(found_by_origin_and_swr_id.is_null()); ExpectAppIdentifiersEqual(original_, found_by_origin_and_swr_id); } @@ -109,11 +117,14 @@ TEST_F(PushMessagingAppIdentifierTest, FindLegacy) { const std::string legacy_app_id("wp:9CC55CCE-B8F9-4092-A364-3B0F73A3AB5F"); - ASSERT_TRUE(PushMessagingAppIdentifier::FindByAppId(profile(), - legacy_app_id).is_null()); - ASSERT_TRUE(PushMessagingAppIdentifier::FindByServiceWorker( - profile(), original_.origin(), original_.service_worker_registration_id()) - .is_null()); + ASSERT_TRUE(PushMessagingAppIdentifier::FindByAppId(profile(), legacy_app_id) + .is_null()); + + const auto identifier = PushMessagingAppIdentifier::FindByServiceWorker( + profile(), original_.origin(), + original_.service_worker_registration_id()); + + ASSERT_TRUE(identifier.is_null()); // Create a legacy preferences entry (the test happens to use PersistToPrefs // since that currently works, but it's ok to change the behavior of @@ -130,8 +141,9 @@ } { PushMessagingAppIdentifier found_by_origin_and_swr_id = - PushMessagingAppIdentifier::FindByServiceWorker(profile(), - original_.origin(), original_.service_worker_registration_id()); + PushMessagingAppIdentifier::FindByServiceWorker( + profile(), original_.origin(), + original_.service_worker_registration_id()); EXPECT_FALSE(found_by_origin_and_swr_id.is_null()); ExpectAppIdentifiersEqual(original_, found_by_origin_and_swr_id); } @@ -160,8 +172,9 @@ } { PushMessagingAppIdentifier found_by_original_origin_and_swr_id = - PushMessagingAppIdentifier::FindByServiceWorker(profile(), - original_.origin(), original_.service_worker_registration_id()); + PushMessagingAppIdentifier::FindByServiceWorker( + profile(), original_.origin(), + original_.service_worker_registration_id()); EXPECT_FALSE(found_by_original_origin_and_swr_id.is_null()); ExpectAppIdentifiersEqual(same_origin_and_sw_, found_by_original_origin_and_swr_id); @@ -184,8 +197,9 @@ } { PushMessagingAppIdentifier found_by_original_origin_and_swr_id = - PushMessagingAppIdentifier::FindByServiceWorker(profile(), - original_.origin(), original_.service_worker_registration_id()); + PushMessagingAppIdentifier::FindByServiceWorker( + profile(), original_.origin(), + original_.service_worker_registration_id()); EXPECT_FALSE(found_by_original_origin_and_swr_id.is_null()); ExpectAppIdentifiersEqual(original_, found_by_original_origin_and_swr_id); } @@ -205,8 +219,9 @@ } { PushMessagingAppIdentifier found_by_original_origin_and_swr_id = - PushMessagingAppIdentifier::FindByServiceWorker(profile(), - original_.origin(), original_.service_worker_registration_id()); + PushMessagingAppIdentifier::FindByServiceWorker( + profile(), original_.origin(), + original_.service_worker_registration_id()); EXPECT_TRUE(found_by_original_origin_and_swr_id.is_null()); } }
diff --git a/chrome/browser/push_messaging/push_messaging_browsertest.cc b/chrome/browser/push_messaging/push_messaging_browsertest.cc index c0a05540..6e21fb0 100644 --- a/chrome/browser/push_messaging/push_messaging_browsertest.cc +++ b/chrome/browser/push_messaging/push_messaging_browsertest.cc
@@ -61,13 +61,9 @@ message_loop_runner_->Quit(); } - void WaitUntilSatisfied() { - message_loop_runner_->Run(); - } + void WaitUntilSatisfied() { message_loop_runner_->Run(); } - const std::string& app_id() { - return app_id_; - } + const std::string& app_id() { return app_id_; } private: scoped_refptr<content::MessageLoopRunner> message_loop_runner_; @@ -140,9 +136,7 @@ ui_test_utils::NavigateToURL(GetBrowser(), https_server_->GetURL(path)); } - void LoadTestPage() { - LoadTestPage(GetTestURL()); - } + void LoadTestPage() { LoadTestPage(GetTestURL()); } bool RunScript(const std::string& script, std::string* result) { return RunScript(script, result, nullptr); @@ -153,8 +147,7 @@ if (!web_contents) web_contents = GetBrowser()->tab_strip_model()->GetActiveWebContents(); return content::ExecuteScriptAndExtractString(web_contents->GetMainFrame(), - script, - result); + script, result); } gcm::GCMAppHandler* GetAppHandler() { @@ -360,8 +353,8 @@ script_result); } -// Disabled on Windows due to flakiness (http://crbug.com/554003). -#if defined(OS_WIN) +// Disabled on Windows and Linux due to flakiness (http://crbug.com/554003). +#if defined(OS_WIN) || defined(OS_LINUX) #define MAYBE_SubscribePersisted DISABLED_SubscribePersisted #else #define MAYBE_SubscribePersisted SubscribePersisted @@ -499,8 +492,8 @@ // When the push service will receive it next message, given that there is no // SW available, it should unregister |app_identifier.app_id()|. UnregistrationCallback callback; - gcm_service()->SetUnregisterCallback(base::Bind(&UnregistrationCallback::Run, - base::Unretained(&callback))); + gcm_service()->SetUnregisterCallback( + base::Bind(&UnregistrationCallback::Run, base::Unretained(&callback))); gcm::IncomingMessage message; message.sender_id = "1234567890"; @@ -656,12 +649,10 @@ { base::RunLoop run_loop; - push_service()->SetMessageCallbackForTesting( - base::Bind(&PushMessagingBrowserTest::OnDeliveryFinished, - base::Unretained(this), - &number_of_notifications_shown, - base::BarrierClosure(2 /* num_closures */, - run_loop.QuitClosure()))); + push_service()->SetMessageCallbackForTesting(base::Bind( + &PushMessagingBrowserTest::OnDeliveryFinished, base::Unretained(this), + &number_of_notifications_shown, + base::BarrierClosure(2 /* num_closures */, run_loop.QuitClosure()))); message.raw_data = "testdata"; push_service()->OnMessage(app_identifier.app_id(), message); @@ -742,8 +733,7 @@ RequestAndAcceptPermission(); ASSERT_TRUE(RunScript("subscribePush()", &script_result)); - EXPECT_EQ(GetEndpointForSubscriptionId("1-0"), - script_result); + EXPECT_EQ(GetEndpointForSubscriptionId("1-0"), script_result); ASSERT_TRUE(RunScript("permissionState()", &script_result)); EXPECT_EQ("permission status - granted", script_result); @@ -824,8 +814,8 @@ push_service()->SetContentSettingChangedCallbackForTesting( message_loop_runner->QuitClosure()); - HostContentSettingsMapFactory::GetForProfile(GetBrowser()->profile())-> - ClearSettingsForOneType(CONTENT_SETTINGS_TYPE_PUSH_MESSAGING); + HostContentSettingsMapFactory::GetForProfile(GetBrowser()->profile()) + ->ClearSettingsForOneType(CONTENT_SETTINGS_TYPE_PUSH_MESSAGING); message_loop_runner->Run(); @@ -857,8 +847,7 @@ HostContentSettingsMapFactory::GetForProfile(GetBrowser()->profile()) ->SetContentSetting(ContentSettingsPattern::FromURLNoWildcard(origin), ContentSettingsPattern::FromURLNoWildcard(origin), - CONTENT_SETTINGS_TYPE_PUSH_MESSAGING, - std::string(), + CONTENT_SETTINGS_TYPE_PUSH_MESSAGING, std::string(), CONTENT_SETTING_DEFAULT); message_loop_runner->Run(); @@ -891,8 +880,7 @@ HostContentSettingsMapFactory::GetForProfile(GetBrowser()->profile()) ->SetContentSetting(ContentSettingsPattern::FromURLNoWildcard(origin), ContentSettingsPattern::FromURLNoWildcard(origin), - CONTENT_SETTINGS_TYPE_PUSH_MESSAGING, - std::string(), + CONTENT_SETTINGS_TYPE_PUSH_MESSAGING, std::string(), CONTENT_SETTING_BLOCK); message_loop_runner->Run(); @@ -921,8 +909,8 @@ push_service()->SetContentSettingChangedCallbackForTesting( message_loop_runner->QuitClosure()); - HostContentSettingsMapFactory::GetForProfile(GetBrowser()->profile())-> - ClearSettingsForOneType(CONTENT_SETTINGS_TYPE_NOTIFICATIONS); + HostContentSettingsMapFactory::GetForProfile(GetBrowser()->profile()) + ->ClearSettingsForOneType(CONTENT_SETTINGS_TYPE_NOTIFICATIONS); message_loop_runner->Run(); @@ -954,8 +942,7 @@ HostContentSettingsMapFactory::GetForProfile(GetBrowser()->profile()) ->SetContentSetting(ContentSettingsPattern::FromURLNoWildcard(origin), ContentSettingsPattern::Wildcard(), - CONTENT_SETTINGS_TYPE_NOTIFICATIONS, - std::string(), + CONTENT_SETTINGS_TYPE_NOTIFICATIONS, std::string(), CONTENT_SETTING_DEFAULT); message_loop_runner->Run(); @@ -988,8 +975,7 @@ HostContentSettingsMapFactory::GetForProfile(GetBrowser()->profile()) ->SetContentSetting(ContentSettingsPattern::FromURLNoWildcard(origin), ContentSettingsPattern::Wildcard(), - CONTENT_SETTINGS_TYPE_NOTIFICATIONS, - std::string(), + CONTENT_SETTINGS_TYPE_NOTIFICATIONS, std::string(), CONTENT_SETTING_BLOCK); message_loop_runner->Run(); @@ -1022,14 +1008,12 @@ HostContentSettingsMapFactory::GetForProfile(GetBrowser()->profile()) ->SetContentSetting(ContentSettingsPattern::FromURLNoWildcard(origin), ContentSettingsPattern::Wildcard(), - CONTENT_SETTINGS_TYPE_NOTIFICATIONS, - std::string(), + CONTENT_SETTINGS_TYPE_NOTIFICATIONS, std::string(), CONTENT_SETTING_ALLOW); HostContentSettingsMapFactory::GetForProfile(GetBrowser()->profile()) ->SetContentSetting(ContentSettingsPattern::FromURLNoWildcard(origin), ContentSettingsPattern::FromURLNoWildcard(origin), - CONTENT_SETTINGS_TYPE_PUSH_MESSAGING, - std::string(), + CONTENT_SETTINGS_TYPE_PUSH_MESSAGING, std::string(), CONTENT_SETTING_ALLOW); message_loop_runner->Run(); @@ -1066,26 +1050,22 @@ HostContentSettingsMapFactory::GetForProfile(GetBrowser()->profile()) ->SetContentSetting(ContentSettingsPattern::Wildcard(), ContentSettingsPattern::Wildcard(), - CONTENT_SETTINGS_TYPE_NOTIFICATIONS, - std::string(), + CONTENT_SETTINGS_TYPE_NOTIFICATIONS, std::string(), CONTENT_SETTING_ALLOW); HostContentSettingsMapFactory::GetForProfile(GetBrowser()->profile()) ->SetContentSetting(ContentSettingsPattern::FromString("https://*"), ContentSettingsPattern::FromString("https://*"), - CONTENT_SETTINGS_TYPE_PUSH_MESSAGING, - std::string(), + CONTENT_SETTINGS_TYPE_PUSH_MESSAGING, std::string(), CONTENT_SETTING_ALLOW); HostContentSettingsMapFactory::GetForProfile(GetBrowser()->profile()) ->SetContentSetting(ContentSettingsPattern::FromURLNoWildcard(origin), ContentSettingsPattern::Wildcard(), - CONTENT_SETTINGS_TYPE_NOTIFICATIONS, - std::string(), + CONTENT_SETTINGS_TYPE_NOTIFICATIONS, std::string(), CONTENT_SETTING_DEFAULT); HostContentSettingsMapFactory::GetForProfile(GetBrowser()->profile()) ->SetContentSetting(ContentSettingsPattern::FromURLNoWildcard(origin), ContentSettingsPattern::FromURLNoWildcard(origin), - CONTENT_SETTINGS_TYPE_PUSH_MESSAGING, - std::string(), + CONTENT_SETTINGS_TYPE_PUSH_MESSAGING, std::string(), CONTENT_SETTING_DEFAULT); message_loop_runner->Run();
diff --git a/chrome/browser/push_messaging/push_messaging_notification_manager.cc b/chrome/browser/push_messaging/push_messaging_notification_manager.cc index 396627c..e96bb79 100644 --- a/chrome/browser/push_messaging/push_messaging_notification_manager.cc +++ b/chrome/browser/push_messaging/push_messaging_notification_manager.cc
@@ -39,12 +39,17 @@ #endif using content::BrowserThread; +using content::NotificationDatabaseData; +using content::PlatformNotificationContext; +using content::PlatformNotificationData; +using content::PushMessagingService; +using content::ServiceWorkerContext; +using content::WebContents; namespace { void RecordUserVisibleStatus(content::PushUserVisibleStatus status) { - UMA_HISTOGRAM_ENUMERATION("PushMessaging.UserVisibleStatus", - status, + UMA_HISTOGRAM_ENUMERATION("PushMessaging.UserVisibleStatus", status, content::PUSH_USER_VISIBLE_STATUS_LAST + 1); } @@ -53,12 +58,35 @@ return content::BrowserContext::GetStoragePartitionForSite(profile, origin); } +NotificationDatabaseData CreateDatabaseData( + const GURL& origin, + int64_t service_worker_registration_id, + const std::string& languages) { + PlatformNotificationData notification_data; + notification_data.title = + url_formatter::FormatUrlForSecurityDisplayOmitScheme(origin, languages); + notification_data.direction = + PlatformNotificationData::DIRECTION_LEFT_TO_RIGHT; + notification_data.body = + l10n_util::GetStringUTF16(IDS_PUSH_MESSAGING_GENERIC_NOTIFICATION_BODY); + notification_data.tag = kPushMessagingForcedNotificationTag; + notification_data.icon = GURL(); + notification_data.silent = true; + + NotificationDatabaseData database_data; + database_data.origin = origin; + database_data.service_worker_registration_id = service_worker_registration_id; + database_data.notification_data = notification_data; + return database_data; +} + +void IgnoreResult(bool unused) {} + } // namespace PushMessagingNotificationManager::PushMessagingNotificationManager( Profile* profile) - : profile_(profile), - weak_factory_(this) {} + : profile_(profile), weak_factory_(this) {} PushMessagingNotificationManager::~PushMessagingNotificationManager() {} @@ -68,12 +96,13 @@ const base::Closure& message_handled_closure) { DCHECK_CURRENTLY_ON(BrowserThread::UI); // TODO(johnme): Relax this heuristic slightly. - scoped_refptr<content::PlatformNotificationContext> notification_context = + scoped_refptr<PlatformNotificationContext> notification_context = GetStoragePartition(profile_, origin)->GetPlatformNotificationContext(); + BrowserThread::PostTask( BrowserThread::IO, FROM_HERE, base::Bind( - &content::PlatformNotificationContext:: + &PlatformNotificationContext:: ReadAllNotificationDataForServiceWorkerRegistration, notification_context, origin, service_worker_registration_id, base::Bind(&PushMessagingNotificationManager:: @@ -89,7 +118,7 @@ int64_t service_worker_registration_id, const base::Closure& message_handled_closure, bool success, - const std::vector<content::NotificationDatabaseData>& data) { + const std::vector<NotificationDatabaseData>& data) { DCHECK_CURRENTLY_ON(BrowserThread::IO); BrowserThread::PostTask( BrowserThread::UI, FROM_HERE, @@ -104,7 +133,7 @@ int64_t service_worker_registration_id, const base::Closure& message_handled_closure, bool success, - const std::vector<content::NotificationDatabaseData>& data) { + const std::vector<NotificationDatabaseData>& data) { DCHECK_CURRENTLY_ON(BrowserThread::UI); // TODO(johnme): Hiding an existing notification should also count as a useful // user-visible action done in response to a push message - but make sure that @@ -114,16 +143,17 @@ bool notification_shown = notification_count > 0; bool notification_needed = true; + // Sites with a currently visible tab don't need to show notifications. + #if defined(OS_ANDROID) for (auto it = TabModelList::begin(); it != TabModelList::end(); ++it) { Profile* profile = (*it)->GetProfile(); - content::WebContents* active_web_contents = - (*it)->GetActiveWebContents(); + WebContents* active_web_contents = (*it)->GetActiveWebContents(); #else for (chrome::BrowserIterator it; !it.done(); it.Next()) { Profile* profile = it->profile(); - content::WebContents* active_web_contents = + WebContents* active_web_contents = it->tab_strip_model()->GetActiveWebContents(); #endif if (!active_web_contents || !active_web_contents->GetMainFrame()) @@ -135,11 +165,11 @@ // Ignore minimized windows etc. switch (active_web_contents->GetMainFrame()->GetVisibilityState()) { - case blink::WebPageVisibilityStateHidden: - case blink::WebPageVisibilityStatePrerender: - continue; - case blink::WebPageVisibilityStateVisible: - break; + case blink::WebPageVisibilityStateHidden: + case blink::WebPageVisibilityStatePrerender: + continue; + case blink::WebPageVisibilityStateVisible: + break; } // Use the visible URL since that's the one the user is aware of (and it @@ -182,10 +212,10 @@ // Don't track push messages that didn't show a notification but were exempt // from needing to do so. if (notification_shown || notification_needed) { - content::ServiceWorkerContext* service_worker_context = + ServiceWorkerContext* service_worker_context = GetStoragePartition(profile_, origin)->GetServiceWorkerContext(); - content::PushMessagingService::GetNotificationsShownByLastFewPushes( + PushMessagingService::GetNotificationsShownByLastFewPushes( service_worker_context, service_worker_registration_id, base::Bind(&PushMessagingNotificationManager:: DidGetNotificationsShownAndNeeded, @@ -199,9 +229,6 @@ } } -static void IgnoreResult(bool unused) { -} - void PushMessagingNotificationManager::DidGetNotificationsShownAndNeeded( const GURL& origin, int64_t service_worker_registration_id, @@ -212,7 +239,7 @@ bool success, bool not_found) { DCHECK_CURRENTLY_ON(BrowserThread::UI); - content::ServiceWorkerContext* service_worker_context = + ServiceWorkerContext* service_worker_context = GetStoragePartition(profile_, origin)->GetServiceWorkerContext(); // We remember whether the last (up to) 10 pushes showed notifications. @@ -230,7 +257,7 @@ missed_notifications[0] = needed_but_not_shown; std::string updated_data(missed_notifications. to_string<char, std::string::traits_type, std::string::allocator_type>()); - content::PushMessagingService::SetNotificationsShownByLastFewPushes( + PushMessagingService::SetNotificationsShownByLastFewPushes( service_worker_context, service_worker_registration_id, origin, updated_data, base::Bind(&IgnoreResult)); // This is a heuristic; ignore failure. @@ -238,21 +265,20 @@ if (notification_shown) { RecordUserVisibleStatus( notification_needed - ? content::PUSH_USER_VISIBLE_STATUS_REQUIRED_AND_SHOWN - : content::PUSH_USER_VISIBLE_STATUS_NOT_REQUIRED_BUT_SHOWN); + ? content::PUSH_USER_VISIBLE_STATUS_REQUIRED_AND_SHOWN + : content::PUSH_USER_VISIBLE_STATUS_NOT_REQUIRED_BUT_SHOWN); message_handled_closure.Run(); return; } DCHECK(needed_but_not_shown); if (missed_notifications.count() <= 1) { // Apply grace. RecordUserVisibleStatus( - content::PUSH_USER_VISIBLE_STATUS_REQUIRED_BUT_NOT_SHOWN_USED_GRACE); + content::PUSH_USER_VISIBLE_STATUS_REQUIRED_BUT_NOT_SHOWN_USED_GRACE); message_handled_closure.Run(); return; } RecordUserVisibleStatus( - content:: - PUSH_USER_VISIBLE_STATUS_REQUIRED_BUT_NOT_SHOWN_GRACE_EXCEEDED); + content::PUSH_USER_VISIBLE_STATUS_REQUIRED_BUT_NOT_SHOWN_GRACE_EXCEEDED); rappor::SampleDomainAndRegistryFromGURL( g_browser_process->rappor_service(), "PushMessaging.GenericNotificationShown.Origin", origin); @@ -260,41 +286,27 @@ // The site failed to show a notification when one was needed, and they have // already failed once in the previous 10 push messages, so we will show a // generic notification. See https://crbug.com/437277. - content::PlatformNotificationData notification_data; - notification_data.title = - url_formatter::FormatUrlForSecurityDisplayOmitScheme( - origin, profile_->GetPrefs()->GetString(prefs::kAcceptLanguages)); - notification_data.direction = - content::PlatformNotificationData::DIRECTION_LEFT_TO_RIGHT; - notification_data.body = - l10n_util::GetStringUTF16(IDS_PUSH_MESSAGING_GENERIC_NOTIFICATION_BODY); - notification_data.tag = kPushMessagingForcedNotificationTag; - notification_data.icon = GURL(); - notification_data.silent = true; - - content::NotificationDatabaseData database_data; - database_data.origin = origin; - database_data.service_worker_registration_id = - service_worker_registration_id; - database_data.notification_data = notification_data; - - scoped_refptr<content::PlatformNotificationContext> notification_context = + NotificationDatabaseData database_data = CreateDatabaseData( + origin, service_worker_registration_id, + profile_->GetPrefs()->GetString(prefs::kAcceptLanguages)); + scoped_refptr<PlatformNotificationContext> notification_context = GetStoragePartition(profile_, origin)->GetPlatformNotificationContext(); BrowserThread::PostTask( BrowserThread::IO, FROM_HERE, - base::Bind(&content::PlatformNotificationContext::WriteNotificationData, + base::Bind(&PlatformNotificationContext::WriteNotificationData, notification_context, origin, database_data, base::Bind(&PushMessagingNotificationManager:: DidWriteNotificationDataIOProxy, weak_factory_.GetWeakPtr(), origin, - notification_data, message_handled_closure))); + database_data.notification_data, + message_handled_closure))); } // static void PushMessagingNotificationManager::DidWriteNotificationDataIOProxy( const base::WeakPtr<PushMessagingNotificationManager>& ui_weak_ptr, const GURL& origin, - const content::PlatformNotificationData& notification_data, + const PlatformNotificationData& notification_data, const base::Closure& message_handled_closure, bool success, int64_t persistent_notification_id) { @@ -308,7 +320,7 @@ void PushMessagingNotificationManager::DidWriteNotificationData( const GURL& origin, - const content::PlatformNotificationData& notification_data, + const PlatformNotificationData& notification_data, const base::Closure& message_handled_closure, bool success, int64_t persistent_notification_id) { @@ -318,8 +330,10 @@ message_handled_closure.Run(); return; } + PlatformNotificationServiceImpl::GetInstance()->DisplayPersistentNotification( profile_, persistent_notification_id, origin, SkBitmap() /* icon */, notification_data); + message_handled_closure.Run(); }
diff --git a/chrome/browser/push_messaging/push_messaging_permission_context.cc b/chrome/browser/push_messaging/push_messaging_permission_context.cc index 3a6d246..ab2194a 100644 --- a/chrome/browser/push_messaging/push_messaging_permission_context.cc +++ b/chrome/browser/push_messaging/push_messaging_permission_context.cc
@@ -22,11 +22,9 @@ PushMessagingPermissionContext::PushMessagingPermissionContext(Profile* profile) : PermissionContextBase(profile, CONTENT_SETTINGS_TYPE_PUSH_MESSAGING), profile_(profile), - weak_factory_ui_thread_(this) { -} + weak_factory_ui_thread_(this) {} -PushMessagingPermissionContext::~PushMessagingPermissionContext() { -} +PushMessagingPermissionContext::~PushMessagingPermissionContext() {} ContentSetting PushMessagingPermissionContext::GetPermissionStatus( const GURL& requesting_origin,
diff --git a/chrome/browser/push_messaging/push_messaging_permission_context.h b/chrome/browser/push_messaging/push_messaging_permission_context.h index 6b5e3582..5ff4533c 100644 --- a/chrome/browser/push_messaging/push_messaging_permission_context.h +++ b/chrome/browser/push_messaging/push_messaging_permission_context.h
@@ -38,8 +38,7 @@ DecidePermission); FRIEND_TEST_ALL_PREFIXES(PushMessagingPermissionContextTest, DecidePushPermission); - FRIEND_TEST_ALL_PREFIXES(PushMessagingPermissionContextTest, - InsecureOrigin); + FRIEND_TEST_ALL_PREFIXES(PushMessagingPermissionContextTest, InsecureOrigin); // Used to decide the permission for push, once the permission for // Notification has been granted/denied.
diff --git a/chrome/browser/push_messaging/push_messaging_permission_context_factory.cc b/chrome/browser/push_messaging/push_messaging_permission_context_factory.cc index 282c5e2..075793a 100644 --- a/chrome/browser/push_messaging/push_messaging_permission_context_factory.cc +++ b/chrome/browser/push_messaging/push_messaging_permission_context_factory.cc
@@ -11,8 +11,7 @@ // static PushMessagingPermissionContext* -PushMessagingPermissionContextFactory::GetForProfile( - Profile* profile) { +PushMessagingPermissionContextFactory::GetForProfile(Profile* profile) { return static_cast<PushMessagingPermissionContext*>( GetInstance()->GetServiceForBrowserContext(profile, true)); } @@ -26,12 +25,10 @@ PushMessagingPermissionContextFactory::PushMessagingPermissionContextFactory() : PermissionContextFactoryBase( "GCMPermissionContext", - BrowserContextDependencyManager::GetInstance()) { -} + BrowserContextDependencyManager::GetInstance()) {} -PushMessagingPermissionContextFactory -::~PushMessagingPermissionContextFactory() { -} +PushMessagingPermissionContextFactory:: + ~PushMessagingPermissionContextFactory() {} KeyedService* PushMessagingPermissionContextFactory::BuildServiceInstanceFor( content::BrowserContext* profile) const {
diff --git a/chrome/browser/push_messaging/push_messaging_permission_context_unittest.cc b/chrome/browser/push_messaging/push_messaging_permission_context_unittest.cc index b380fa4..d010bb7 100644 --- a/chrome/browser/push_messaging/push_messaging_permission_context_unittest.cc +++ b/chrome/browser/push_messaging/push_messaging_permission_context_unittest.cc
@@ -60,8 +60,8 @@ HostContentSettingsMapFactory::GetForProfile(profile); host_content_settings_map->SetContentSetting(pattern_a, pattern_a, setting, std::string(), value); - host_content_settings_map->SetContentSetting(insecure_pattern, - insecure_pattern, setting, std::string(), value); + host_content_settings_map->SetContentSetting( + insecure_pattern, insecure_pattern, setting, std::string(), value); } content::TestBrowserThreadBundle thread_bundle_; @@ -175,19 +175,16 @@ BrowserPermissionCallback callback; // Requesting and embedding origin are different. - context.DecidePermission(NULL, request_id, - GURL(kOriginA), GURL(kOriginB), + context.DecidePermission(NULL, request_id, GURL(kOriginA), GURL(kOriginB), true, callback); EXPECT_FALSE(context.was_persisted()); EXPECT_FALSE(context.was_granted()); // Insecure origin - context.DecidePermission(NULL, request_id, - GURL(kInsecureOrigin), GURL(kInsecureOrigin), - true, callback); + context.DecidePermission(NULL, request_id, GURL(kInsecureOrigin), + GURL(kInsecureOrigin), true, callback); EXPECT_FALSE(context.was_persisted()); EXPECT_FALSE(context.was_granted()); - } TEST_F(PushMessagingPermissionContextTest, GetPermissionStatusInsecureOrigin) { @@ -197,26 +194,26 @@ // The status should be blocked for an insecure origin, regardless of the // content setting value. EXPECT_EQ(CONTENT_SETTING_BLOCK, - context.GetPermissionStatus(GURL(kInsecureOrigin), - GURL(kInsecureOrigin))); + context.GetPermissionStatus(GURL(kInsecureOrigin), + GURL(kInsecureOrigin))); SetContentSetting(&profile, CONTENT_SETTINGS_TYPE_PUSH_MESSAGING, CONTENT_SETTING_ALLOW); SetContentSetting(&profile, CONTENT_SETTINGS_TYPE_NOTIFICATIONS, CONTENT_SETTING_ALLOW); EXPECT_EQ(CONTENT_SETTING_BLOCK, - context.GetPermissionStatus(GURL(kInsecureOrigin), - GURL(kInsecureOrigin))); + context.GetPermissionStatus(GURL(kInsecureOrigin), + GURL(kInsecureOrigin))); SetContentSetting(&profile, CONTENT_SETTINGS_TYPE_PUSH_MESSAGING, CONTENT_SETTING_BLOCK); EXPECT_EQ(CONTENT_SETTING_BLOCK, - context.GetPermissionStatus(GURL(kInsecureOrigin), - GURL(kInsecureOrigin))); + context.GetPermissionStatus(GURL(kInsecureOrigin), + GURL(kInsecureOrigin))); SetContentSetting(&profile, CONTENT_SETTINGS_TYPE_PUSH_MESSAGING, CONTENT_SETTING_ASK); EXPECT_EQ(CONTENT_SETTING_BLOCK, - context.GetPermissionStatus(GURL(kInsecureOrigin), - GURL(kInsecureOrigin))); + context.GetPermissionStatus(GURL(kInsecureOrigin), + GURL(kInsecureOrigin))); }
diff --git a/chrome/browser/push_messaging/push_messaging_service_factory.cc b/chrome/browser/push_messaging/push_messaging_service_factory.cc index 9285565..c42c3e94 100644 --- a/chrome/browser/push_messaging/push_messaging_service_factory.cc +++ b/chrome/browser/push_messaging/push_messaging_service_factory.cc
@@ -38,8 +38,7 @@ DependsOn(HostContentSettingsMapFactory::GetInstance()); } -PushMessagingServiceFactory::~PushMessagingServiceFactory() { -} +PushMessagingServiceFactory::~PushMessagingServiceFactory() {} void PushMessagingServiceFactory::RestoreFactoryForTests( content::BrowserContext* context) {
diff --git a/chrome/browser/push_messaging/push_messaging_service_impl.cc b/chrome/browser/push_messaging/push_messaging_service_impl.cc index 124f883..e8f42af7 100644 --- a/chrome/browser/push_messaging/push_messaging_service_impl.cc +++ b/chrome/browser/push_messaging/push_messaging_service_impl.cc
@@ -58,8 +58,7 @@ "https://goo.gl/yqv4Q4 for more details."; void RecordDeliveryStatus(content::PushDeliveryStatus status) { - UMA_HISTOGRAM_ENUMERATION("PushMessaging.DeliveryStatus", - status, + UMA_HISTOGRAM_ENUMERATION("PushMessaging.DeliveryStatus", status, content::PUSH_DELIVERY_STATUS_LAST + 1); } @@ -78,8 +77,8 @@ } } -void UnregisterCallbackToClosure( - const base::Closure& closure, content::PushUnregistrationStatus status) { +void UnregisterCallbackToClosure(const base::Closure& closure, + content::PushUnregistrationStatus status) { closure.Run(); } @@ -212,21 +211,18 @@ rappor::SampleDomainAndRegistryFromGURL( g_browser_process->rappor_service(), - "PushMessaging.MessageReceived.Origin", - app_identifier.origin()); + "PushMessaging.MessageReceived.Origin", app_identifier.origin()); std::string data; if (AreMessagePayloadsEnabled() && message.decrypted) data = message.raw_data; content::BrowserContext::DeliverPushMessage( - profile_, - app_identifier.origin(), - app_identifier.service_worker_registration_id(), - data, + profile_, app_identifier.origin(), + app_identifier.service_worker_registration_id(), data, base::Bind(&PushMessagingServiceImpl::DeliverMessageCallback, - weak_factory_.GetWeakPtr(), - app_identifier.app_id(), app_identifier.origin(), + weak_factory_.GetWeakPtr(), app_identifier.app_id(), + app_identifier.origin(), app_identifier.service_worker_registration_id(), message, message_handled_closure)); } @@ -287,7 +283,7 @@ } void PushMessagingServiceImpl::SetMessageCallbackForTesting( - const base::Closure& callback) { + const base::Closure& callback) { message_callback_for_testing_ = callback; } @@ -346,8 +342,7 @@ if (!user_visible) { web_contents->GetMainFrame()->AddMessageToConsole( - content::CONSOLE_MESSAGE_LEVEL_ERROR, - kSilentPushUnsupportedMessage); + content::CONSOLE_MESSAGE_LEVEL_ERROR, kSilentPushUnsupportedMessage); SubscribeEndWithError(callback, content::PUSH_REGISTRATION_STATUS_PERMISSION_DENIED); @@ -382,9 +377,8 @@ GURL embedding_origin = requesting_origin; blink::WebPushPermissionStatus permission_status = - PushMessagingServiceImpl::GetPermissionStatus(requesting_origin, - embedding_origin, - user_visible); + PushMessagingServiceImpl::GetPermissionStatus( + requesting_origin, embedding_origin, user_visible); if (permission_status != blink::WebPushPermissionStatusGranted) { SubscribeEndWithError(register_callback, content::PUSH_REGISTRATION_STATUS_PERMISSION_DENIED); @@ -419,15 +413,17 @@ const content::PushMessagingService::RegisterCallback& callback, const std::string& subscription_id, const std::vector<uint8_t>& p256dh, + const std::vector<uint8_t>& auth, content::PushRegistrationStatus status) { - callback.Run(subscription_id, p256dh, status); + callback.Run(subscription_id, p256dh, auth, status); } void PushMessagingServiceImpl::SubscribeEndWithError( const content::PushMessagingService::RegisterCallback& callback, content::PushRegistrationStatus status) { SubscribeEnd(callback, std::string() /* subscription_id */, - std::vector<uint8_t>() /* p256dh */, status); + std::vector<uint8_t>() /* p256dh */, + std::vector<uint8_t>() /* auth */, status); } void PushMessagingServiceImpl::DidSubscribe( @@ -444,9 +440,8 @@ case gcm::GCMClient::SUCCESS: // Do not get a certificate if message payloads have not been enabled. if (!AreMessagePayloadsEnabled()) { - DidSubscribeWithPublicKey( - app_identifier, callback, subscription_id, - std::string() /* public_key */); + DidSubscribeWithPublicKey(app_identifier, callback, subscription_id, + std::string() /* public_key */); return; } @@ -455,10 +450,9 @@ // order to send payloads to the user. GetGCMDriver()->GetPublicKey( app_identifier.app_id(), - base::Bind( - &PushMessagingServiceImpl::DidSubscribeWithPublicKey, - weak_factory_.GetWeakPtr(), app_identifier, callback, - subscription_id)); + base::Bind(&PushMessagingServiceImpl::DidSubscribeWithPublicKey, + weak_factory_.GetWeakPtr(), app_identifier, callback, + subscription_id)); return; case gcm::GCMClient::INVALID_PARAMETER: @@ -492,8 +486,13 @@ IncreasePushSubscriptionCount(1, false /* is_pending */); + // TODO(peter): Hook up the authentication tag in the gcm_driver. + std::string authentication; + SubscribeEnd(callback, subscription_id, std::vector<uint8_t>(public_key.begin(), public_key.end()), + std::vector<uint8_t>(authentication.begin(), + authentication.end()), content::PUSH_REGISTRATION_STATUS_SUCCESS_FROM_PUSH_SERVICE); } @@ -524,7 +523,9 @@ const PushMessagingService::PublicKeyCallback& callback) { // An empty public key will be returned if payloads are not enabled. if (!AreMessagePayloadsEnabled()) { - callback.Run(true /* success */, std::vector<uint8_t>()); + callback.Run(true /* success */, + std::vector<uint8_t>() /* public_key */, + std::vector<uint8_t>() /* auth */); return; } @@ -546,8 +547,13 @@ // I/O errors might prevent the GCM Driver from retrieving a key-pair. const bool success = !!public_key.size(); - callback.Run(success, std::vector<uint8_t>(public_key.begin(), - public_key.end())); + // TODO(peter): Hook up the authentication tag in the gcm_driver. + std::string authentication; + + callback.Run(success, + std::vector<uint8_t>(public_key.begin(), public_key.end()), + std::vector<uint8_t>(authentication.begin(), + authentication.end())); } // Unsubscribe methods --------------------------------------------------------- @@ -707,7 +713,7 @@ } void PushMessagingServiceImpl::SetContentSettingChangedCallbackForTesting( - const base::Closure& callback) { + const base::Closure& callback) { content_setting_changed_callback_for_testing_ = callback; }
diff --git a/chrome/browser/push_messaging/push_messaging_service_impl.h b/chrome/browser/push_messaging/push_messaging_service_impl.h index 8f9791b..4cd099f 100644 --- a/chrome/browser/push_messaging/push_messaging_service_impl.h +++ b/chrome/browser/push_messaging/push_messaging_service_impl.h
@@ -83,8 +83,8 @@ void GetPublicEncryptionKey( const GURL& origin, int64_t service_worker_registration_id, - const content::PushMessagingService::PublicKeyCallback& - callback) override; + const content::PushMessagingService::PublicKeyCallback& callback) + override; void Unsubscribe( const GURL& requesting_origin, int64_t service_worker_registration_id, @@ -96,7 +96,6 @@ bool user_visible) override; bool SupportNonVisibleMessages() override; - // content_settings::Observer implementation. void OnContentSettingChanged(const ContentSettingsPattern& primary_pattern, const ContentSettingsPattern& secondary_pattern, @@ -135,6 +134,7 @@ const content::PushMessagingService::RegisterCallback& callback, const std::string& subscription_id, const std::vector<uint8_t>& p256dh, + const std::vector<uint8_t>& auth, content::PushRegistrationStatus status); void SubscribeEndWithError( @@ -161,10 +161,8 @@ // GetPublicEncryptionKey method --------------------------------------------- - void DidGetPublicKey( - const PushMessagingService::PublicKeyCallback& callback, - const std::string& public_key) const; - + void DidGetPublicKey(const PushMessagingService::PublicKeyCallback& callback, + const std::string& public_key) const; // Unsubscribe methods -------------------------------------------------------
diff --git a/chrome/browser/resources/chromeos/bluetooth_pair_device.js b/chrome/browser/resources/chromeos/bluetooth_pair_device.js index 84a82796..c476037 100644 --- a/chrome/browser/resources/chromeos/bluetooth_pair_device.js +++ b/chrome/browser/resources/chromeos/bluetooth_pair_device.js
@@ -67,14 +67,15 @@ PageManager.register(pairingPage); PageManager.registerOverlay(BluetoothPairing.getInstance(), pairingPage); + // Since this UI is used to host a BluetoothPairing dialog we need to add + // an onPairing observer. (Normally that would be added in browser_options). + chrome.bluetoothPrivate.onPairing.addListener( + BluetoothPairing.onBluetoothPairingEvent); + + // Show the BluetoothPairing dialog. var args = JSON.parse(chrome.getVariableValue('dialogArguments')); - var device = /** @type {!BluetoothDevice} */ (args); - var event = /** @type {!BluetoothPairingEvent} */ ({ - pairing: BluetoothPairingEventType.STARTUP, - device: device - }); - BluetoothPairing.showDialog(event); - chrome.send('updateBluetoothDevice', [device.address, 'connect']); + var device = /** @type {!chrome.bluetooth.Device} */ (args); + BluetoothPairing.connect(device, true); } document.addEventListener('DOMContentLoaded', load);
diff --git a/chrome/browser/resources/chromeos/browser_options.js b/chrome/browser/resources/chromeos/browser_options.js index 748f2f9..dd4a1ee 100644 --- a/chrome/browser/resources/chromeos/browser_options.js +++ b/chrome/browser/resources/chromeos/browser_options.js
@@ -19,27 +19,12 @@ BrowserOptions.prototype = { __proto__: Page.prototype, - }; - BrowserOptions.showBluetoothSettings = function() { - }; - - BrowserOptions.setBluetoothState = function() { - }; - - /** - * Handles bluetoothPairingEvent call, display the Bluetooth pairing overlay - * for the pairing device. - * @param {!BluetoothPairingEvent} event - */ - BrowserOptions.bluetoothPairingEvent = function(event) { - // One device can be in the process of pairing. If found, display - // the Bluetooth pairing overlay. - if (event.pairing) - BluetoothPairing.showDialog(event); - }; - - BrowserOptions.removeBluetoothDevice = function(address) { + /** @override */ + initializePage: function() { + chrome.bluetoothPrivate.onPairing.addListener( + BluetoothPairing.onBluetoothPairingEvent); + } }; // Export
diff --git a/chrome/browser/resources/chromeos/chromevox/BUILD.gn b/chrome/browser/resources/chromeos/chromevox/BUILD.gn index c3bce7e..e2a1693 100644 --- a/chrome/browser/resources/chromeos/chromevox/BUILD.gn +++ b/chrome/browser/resources/chromeos/chromevox/BUILD.gn
@@ -26,15 +26,15 @@ #<(DEPTH)/third_party/liblouis/liblouis_nacl.gyp:liblouis_nacl_wrapper_nacl' # TODO(GYP) ":chromevox_copied_files", - ":chromevox_manifest", ":chromevox_guest_manifest", + ":chromevox_manifest", ] if (chromevox_compress_js) { deps += [ + ":chromevox_background_script", ":chromevox_content_script", ":chromevox_kbexplorer_script", ":chromevox_options_script", - ":chromevox_background_script", ":chromevox_panel_script", ] } else { @@ -314,6 +314,8 @@ sources = chromevox_tests_gypi_values.chromevox_tests_sources deps = [ + ":chromevox_extjs_tests", + ":chromevox_unitjs_tests", "//base", "//base:i18n", "//base/test:test_support", @@ -328,8 +330,6 @@ "//chrome/test:test_support_ui", "//testing/gmock", "//testing/gtest", - ":chromevox_extjs_tests", - ":chromevox_unitjs_tests", ] if (cld_version == 0 || cld_version == 2) { # Because the browser_tests use translate, they need CLD data.
diff --git a/chrome/browser/resources/chromeos/chromevox/cvox2/background/background.js b/chrome/browser/resources/chromeos/chromevox/cvox2/background/background.js index ab7447d..a9206ac 100644 --- a/chrome/browser/resources/chromeos/chromevox/cvox2/background/background.js +++ b/chrome/browser/resources/chromeos/chromevox/cvox2/background/background.js
@@ -100,13 +100,15 @@ }).bind(this) }); - Object.defineProperty(cvox.ChromeVox, 'modKeyStr', { - get: function() { - return (this.mode_ == ChromeVoxMode.CLASSIC || this.mode_ == - ChromeVoxMode.COMPAT) ? - 'Search+Shift' : 'Search'; - }.bind(this) - }); + if (cvox.ChromeVox.isChromeOS) { + Object.defineProperty(cvox.ChromeVox, 'modKeyStr', { + get: function() { + return (this.mode_ == ChromeVoxMode.CLASSIC || this.mode_ == + ChromeVoxMode.COMPAT) ? + 'Search+Shift' : 'Search'; + }.bind(this) + }); + } Object.defineProperty(cvox.ChromeVox, 'isActive', { get: function() {
diff --git a/chrome/browser/resources/chromeos/chromevox/cvox2/background/desktop_automation_handler.js b/chrome/browser/resources/chromeos/chromevox/cvox2/background/desktop_automation_handler.js index d4627775..182bbd4 100644 --- a/chrome/browser/resources/chromeos/chromevox/cvox2/background/desktop_automation_handler.js +++ b/chrome/browser/resources/chromeos/chromevox/cvox2/background/desktop_automation_handler.js
@@ -141,7 +141,7 @@ node = node.find({state: {focused: true}}) || node; } - if (evt.target.state.editable) + if (this.isEditable_(evt.target)) this.createEditableTextHandlerIfNeeded_(evt.target); this.onEventDefault({target: node, type: 'focus'}); @@ -195,7 +195,7 @@ * @param {Object} evt */ onTextOrTextSelectionChanged: function(evt) { - if (!evt.target.state.editable) + if (!this.isEditable_(evt.target)) return; // Don't process nodes inside of web content if ChromeVox Next is inactive. @@ -206,9 +206,6 @@ if (!evt.target.state.focused) return; - if (evt.target.role != RoleType.textField) - return; - if (!global.backgroundObj.currentRange) { this.onEventDefault(evt); global.backgroundObj.currentRange = cursors.Range.fromNode(evt.target); @@ -242,10 +239,8 @@ if (!evt.target.state.focused) return; - // Value change events fire on web text fields and text areas when pressing - // enter; suppress them. - if (!global.backgroundObj.currentRange || - evt.target.role != RoleType.textField) { + // Value change events fire on web editables when typing. Suppress them. + if (!global.backgroundObj.currentRange || !this.isEditable_(evt.target)) { this.onEventDefault(evt); global.backgroundObj.currentRange = cursors.Range.fromNode(evt.target); } @@ -274,6 +269,18 @@ node.state.protected, cvox.ChromeVox.tts); } + }, + + /** + * Returns true if |node| is editable. + * @param {AutomationNode} node + * @return {boolean} + * @private + */ + isEditable_: function(node) { + // Remove the check for role after m47 whereafter the editable state can be + // used to know when to create an editable text handler. + return node.role == RoleType.textField || node.state.editable; } };
diff --git a/chrome/browser/resources/chromeos/chromevox/testing/chromevox_next_e2e_test_base.js b/chrome/browser/resources/chromeos/chromevox/testing/chromevox_next_e2e_test_base.js index 5a84dc2b..bb9f1fb0 100644 --- a/chrome/browser/resources/chromeos/chromevox/testing/chromevox_next_e2e_test_base.js +++ b/chrome/browser/resources/chromeos/chromevox/testing/chromevox_next_e2e_test_base.js
@@ -39,7 +39,7 @@ evt.target.docUrl.indexOf('test') == -1) return; - r.removeEventListener(listener); + r.removeEventListener('loadComplete', listener, true); callback && callback(evt.target); callback = null; };
diff --git a/chrome/browser/resources/chromeos/input_method/google_xkb_manifest.json b/chrome/browser/resources/chromeos/input_method/google_xkb_manifest.json index d8edb7c..76ef7520 100644 --- a/chrome/browser/resources/chromeos/input_method/google_xkb_manifest.json +++ b/chrome/browser/resources/chromeos/input_method/google_xkb_manifest.json
@@ -208,6 +208,38 @@ "options_page": "hmm_options.html?code=xkb:us:colemak:eng" }, { + "name": "__MSG_keyboard_us_workman__", + "type": "ime", + "id": "xkb:us:workman:eng", + "indicator": "WM", + "description": "", + "language": [ + "en", + "en-US" + ], + "layouts": [ + "us(workman)" + ], + "input_view": "inputview.html#id=us-workman&language=en-US&passwordLayout=us-workman&name=keyboard_us_workman", + "options_page": "hmm_options.html?code=xkb:us:workman:eng" + }, + { + "name": "__MSG_keyboard_us_workman_international__", + "type": "ime", + "id": "xkb:us:workman-intl:eng", + "indicator": "WMI", + "description": "", + "language": [ + "en", + "en-US" + ], + "layouts": [ + "us(workman-intl)" + ], + "input_view": "inputview.html#id=us-workman-intl&language=en-US&passwordLayout=us-workman-intl&name=keyboard_us_workman_international", + "options_page": "hmm_options.html?code=xkb:us:workman-intl:eng" + }, + { "name": "__MSG_keyboard_belgian__", "type": "ime", "id": "xkb:be::nld",
diff --git a/chrome/browser/resources/chromeos/input_method/xkb_manifest.json b/chrome/browser/resources/chromeos/input_method/xkb_manifest.json index 8eb595f0..4a24e1d 100644 --- a/chrome/browser/resources/chromeos/input_method/xkb_manifest.json +++ b/chrome/browser/resources/chromeos/input_method/xkb_manifest.json
@@ -176,6 +176,36 @@ "input_view": "inputview.html?id=us-colemak&language=en-US&passwordLayout=us-colemak&name=keyboard_us_colemak" }, { + "name": "__MSG_keyboard_us_workman__", + "type": "ime", + "id": "xkb:us:workman:eng", + "indicator": "WM", + "description": "", + "language": [ + "en", + "en-US" + ], + "layouts": [ + "us(workman)" + ], + "input_view": "inputview.html?id=us-workman&language=en-US&passwordLayout=us-workman&name=keyboard_us_workman" + }, + { + "name": "__MSG_keyboard_us_workman_international__", + "type": "ime", + "id": "xkb:us:workman-intl:eng", + "indicator": "WMI", + "description": "", + "language": [ + "en", + "en-US" + ], + "layouts": [ + "us(workman-intl)" + ], + "input_view": "inputview.html?id=us-workman-intl&language=en-US&passwordLayout=us-workman-intl&name=keyboard_us_workman_international" + }, + { "name": "__MSG_keyboard_belgian__", "type": "ime", "id": "xkb:be::nld",
diff --git a/chrome/browser/resources/options/browser_options.js b/chrome/browser/resources/options/browser_options.js index 4af8014..ae7c092 100644 --- a/chrome/browser/resources/options/browser_options.js +++ b/chrome/browser/resources/options/browser_options.js
@@ -121,6 +121,12 @@ */ systemTimezoneIsManaged_: false, + /** + * Cached bluetooth adapter state. + * @private {?chrome.bluetooth.AdapterState} + */ + bluetoothAdapterState_: null, + /** @override */ initializePage: function() { Page.prototype.initializePage.call(this); @@ -516,6 +522,24 @@ // Bluetooth (CrOS only). if (cr.isChromeOS) { + // Request the intial bluetooth adapter state. + var adapterStateChanged = + this.onBluetoothAdapterStateChanged_.bind(this); + chrome.bluetooth.getAdapterState(adapterStateChanged); + + // Set up observers. + chrome.bluetooth.onAdapterStateChanged.addListener(adapterStateChanged); + var deviceAddedOrChanged = + this.onBluetoothDeviceAddedOrChanged_.bind(this); + chrome.bluetooth.onDeviceAdded.addListener(deviceAddedOrChanged); + chrome.bluetooth.onDeviceChanged.addListener(deviceAddedOrChanged); + chrome.bluetooth.onDeviceRemoved.addListener( + this.onBluetoothDeviceRemoved_.bind(this)); + + chrome.bluetoothPrivate.onPairing.addListener( + this.onBluetoothPrivatePairing_.bind(this)); + + // Initialize UI. options.system.bluetooth.BluetoothDeviceList.decorate( $('bluetooth-paired-devices-list')); @@ -536,9 +560,7 @@ chrome.send('coreOptionsUserMetricsAction', ['Options_BluetoothConnectPairedDevice']); var device = $('bluetooth-paired-devices-list').selectedItem; - var address = device.address; - chrome.send('updateBluetoothDevice', [address, 'connect']); - PageManager.closeOverlay(); + BluetoothPairing.connect(device); }; $('bluetooth-paired-devices-list').addEventListener('change', @@ -2022,22 +2044,6 @@ }, /** - * Activate the Bluetooth settings section on the System settings page. - * @private - */ - showBluetoothSettings_: function() { - $('bluetooth-devices').hidden = false; - }, - - /** - * Dectivates the Bluetooth settings section from the System settings page. - * @private - */ - hideBluetoothSettings_: function() { - $('bluetooth-devices').hidden = true; - }, - - /** * Sets the state of the checkbox indicating if Bluetooth is turned on. The * state of the "Find devices" button and the list of discovered devices may * also be affected by a change to the state. @@ -2049,27 +2055,88 @@ $('bluetooth-paired-devices-list').parentNode.hidden = !checked; $('bluetooth-add-device').hidden = !checked; $('bluetooth-reconnect-device').hidden = !checked; - // Flush list of previously discovered devices if bluetooth is turned off. - if (!checked) { - $('bluetooth-paired-devices-list').clear(); - $('bluetooth-unpaired-devices-list').clear(); + }, + + /** + * Process a bluetooth.onAdapterStateChanged event. + * @param {!chrome.bluetooth.AdapterState} state + * @private + */ + onBluetoothAdapterStateChanged_: function(state) { + if (!state || !state.available) { + this.bluetoothAdapterState_ = null; + $('bluetooth-devices').hidden = true; + return; + } + $('bluetooth-devices').hidden = false; + this.bluetoothAdapterState_ = state; + this.setBluetoothState_(state.powered); + + // Flush the device lists. + $('bluetooth-paired-devices-list').clear(); + $('bluetooth-unpaired-devices-list').clear(); + if (state.powered) { + options.BluetoothOptions.updateDiscoveryState(state.discovering); + // Update the device lists. + chrome.bluetooth.getDevices(function(devices) { + for (var device of devices) + this.updateBluetoothDevicesList_(device); + }.bind(this)); } else { - chrome.send('getPairedBluetoothDevices'); + options.BluetoothOptions.dismissOverlay(); } }, /** - * Process a bluetooth pairing event. event.device will be added to the list - * of available Bluetooth devices or updated if a device with a matching - * |address| property exists. If event.pairing is defined and not empty, the - * pairing dialog will be shown (if not already visible) and the event will - * be processed. - * @param {!BluetoothPairingEvent} event + * Process a bluetooth.onDeviceAdded or onDeviceChanged event and update the + * device list. + * @param {!chrome.bluetooth.Device} device * @private */ - bluetoothPairingEvent_: function(event) { - var device = event.device; - var list = $('bluetooth-unpaired-devices-list'); + onBluetoothDeviceAddedOrChanged_: function(device) { + this.updateBluetoothDevicesList_(device); + }, + + /** + * Process a bluetooth.onDeviceRemoved event and update the device list. + * @param {!chrome.bluetooth.Device} device + * @private + */ + onBluetoothDeviceRemoved_: function(device) { + this.removeBluetoothDevice_(device.address); + }, + + /** + * Process a bluetoothPrivate onPairing event and update the device list. + * @param {!chrome.bluetoothPrivate.PairingEvent} pairing_event + * @private + */ + onBluetoothPrivatePairing_: function(pairing_event) { + this.updateBluetoothDevicesList_(pairing_event.device); + BluetoothPairing.onBluetoothPairingEvent(pairing_event); + }, + + /** + * Add |device| to the appropriate list of Bluetooth devices. + * @param {!chrome.bluetooth.Device} device + * @private + */ + addBluetoothDeviceToList_: function(device) { + // Display the "connecting" (already paired or not yet paired) and the + // paired devices in the same list. + if (device.paired || device.connecting) + $('bluetooth-paired-devices-list').appendDevice(device); + else + $('bluetooth-unpaired-devices-list').appendDevice(device); + }, + + /** + * Add |device| to the appropriate list of Bluetooth devices or update the + * entry if a device with a matching |address| property exists. + * @param {!chrome.bluetooth.Device} device + * @private + */ + updateBluetoothDevicesList_: function(device) { // Display the "connecting" (already paired or not yet paired) and the // paired devices in the same list. if (device.paired || device.connecting) { @@ -2078,7 +2145,6 @@ var index = $('bluetooth-unpaired-devices-list').find(device.address); if (index != undefined) $('bluetooth-unpaired-devices-list').deleteItemAtIndex(index); - list = $('bluetooth-paired-devices-list'); } else { // Test to see if the device is currently in the paired list, in which // case it should be removed from that list. @@ -2086,12 +2152,7 @@ if (index != undefined) $('bluetooth-paired-devices-list').deleteItemAtIndex(index); } - list.appendDevice(device); - - // One device can be in the process of pairing. If found, display - // the Bluetooth pairing overlay. - if (event.pairing) - BluetoothPairing.showDialog(event); + this.addBluetoothDeviceToList_(device); }, /** @@ -2163,21 +2224,18 @@ // Forward public APIs to private implementations. cr.makePublic(BrowserOptions, [ - 'bluetoothPairingEvent', 'deleteCurrentProfile', 'enableCertificateButton', 'enableDisplaySettings', 'enableFactoryResetSection', 'getCurrentProfile', 'getStartStopSyncButton', - 'hideBluetoothSettings', 'notifyInitializationComplete', 'removeBluetoothDevice', 'scrollToSection', 'setAccountPictureManaged', 'setWallpaperManaged', 'setAutoOpenFileTypesDisplayed', - 'setBluetoothState', 'setCanSetTime', 'setFontSize', 'setHotwordRetrainLinkVisible', @@ -2196,7 +2254,6 @@ 'setupPageZoomSelector', 'setupProxySettingsButton', 'setAudioHistorySectionVisible', - 'showBluetoothSettings', 'showCreateProfileError', 'showCreateProfileSuccess', 'showCreateProfileWarning',
diff --git a/chrome/browser/resources/options/chromeos/bluetooth_add_device_overlay.js b/chrome/browser/resources/options/chromeos/bluetooth_add_device_overlay.js index f8f2ed28..323a31fb 100644 --- a/chrome/browser/resources/options/chromeos/bluetooth_add_device_overlay.js +++ b/chrome/browser/resources/options/chromeos/bluetooth_add_device_overlay.js
@@ -43,14 +43,8 @@ chrome.send('coreOptionsUserMetricsAction', ['Options_BluetoothConnectNewDevice']); var device = self.deviceList_.selectedItem; - var address = device.address; PageManager.closeOverlay(); - var pairingEvent = /** @type {!BluetoothPairingEvent} */ ({ - pairing: BluetoothPairingEventType.STARTUP, - device: device - }); - options.BluetoothPairing.showDialog(pairingEvent); - chrome.send('updateBluetoothDevice', [address, 'connect']); + options.BluetoothPairing.connect(device, true); }; $('bluetooth-unpaired-devices-list').addEventListener('change', @@ -74,13 +68,29 @@ /** @override */ didShowPage: function() { - chrome.bluetooth.startDiscovery(); + chrome.bluetooth.startDiscovery(function() { + if (chrome.runtime.lastError) { + console.error( + 'Unexpected error calling bluetooth.startDiscovery: ' + + chrome.runtime.lastError.message); + } + }); BluetoothOptions.updateDiscoveryState(true); }, /** @override */ didClosePage: function() { - chrome.bluetooth.stopDiscovery(); + chrome.bluetooth.stopDiscovery(function() { + // The page may get closed before discovery started, so ignore any + // 'Failed to stop discovery' errors. + if (chrome.runtime.lastError && + chrome.runtime.lastError.message != 'Failed to stop discovery') { + console.log( + 'Unexpected error calling bluetooth.stopDiscovery: ' + + chrome.runtime.lastError.message); + + } + }); }, /**
diff --git a/chrome/browser/resources/options/chromeos/bluetooth_device_list.js b/chrome/browser/resources/options/chromeos/bluetooth_device_list.js index 510cea30..c7fcfd9 100644 --- a/chrome/browser/resources/options/chromeos/bluetooth_device_list.js +++ b/chrome/browser/resources/options/chromeos/bluetooth_device_list.js
@@ -2,16 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -/** - * @typedef {{name: string, - * address: string, - * paired: boolean, - * connected: boolean, - * connecting: boolean, - * connectable: boolean}} - */ -var BluetoothDevice; - cr.define('options.system.bluetooth', function() { /** @const */ var ArrayDataModel = cr.ui.ArrayDataModel; /** @const */ var DeletableItem = options.DeletableItem; @@ -25,7 +15,7 @@ /** * Creates a new bluetooth list item. - * @param {BluetoothDevice} device Description of the Bluetooth device. + * @param {chrome.bluetooth.Device} device * @constructor * @extends {options.DeletableItem} */ @@ -47,7 +37,7 @@ /** * Description of the Bluetooth device. - * @type {?BluetoothDevice} + * @type {?chrome.bluetooth.Device} */ data: null, @@ -57,24 +47,28 @@ var label = this.ownerDocument.createElement('div'); label.className = 'bluetooth-device-label'; this.classList.add('bluetooth-device'); + + var connecting = !!this.data.connecting; + var connected = !!this.data.connected; + var connectable = !!this.data.connectable; + var paired = !!this.data.paired; + // There are four kinds of devices we want to distinguish: // * Connecting devices: in bold with a "connecting" label, // * Connected devices: in bold, // * Paired, not connected but connectable devices: regular and // * Paired, not connected and not connectable devices: grayed out. - this.connected = this.data.connecting || - (this.data.paired && this.data.connected); - this.notconnectable = this.data.paired && !this.data.connecting && - !this.data.connected && !this.data.connectable; + this.connected = connecting || (paired && connected); + this.notconnectable = paired && !connecting && + !connected && !connectable; // "paired" devices are those that are remembered but not connected. - this.paired = this.data.paired && !this.data.connected && - this.data.connectable; + this.paired = paired && !connected && connectable; var content = this.data.name; // Update the device's label according to its state. A "connecting" device // can be in the process of connecting and pairing, so we check connecting // first. - if (this.data.connecting) { + if (connecting) { content = loadTimeData.getStringF('bluetoothDeviceConnecting', this.data.name); } @@ -126,7 +120,7 @@ * Adds a bluetooth device to the list of available devices. A check is * made to see if the device is already in the list, in which case the * existing device is updated. - * @param {!BluetoothDevice} device + * @param {!chrome.bluetooth.Device} device * @return {boolean} True if the devies was successfully added or updated. */ appendDevice: function(device) { @@ -208,11 +202,12 @@ if (entry.address == address) return i; } + return undefined; }, /** * @override - * @param {BluetoothDevice} entry + * @param {chrome.bluetooth.Device} entry */ createItem: function(entry) { return new BluetoothListItem(entry); @@ -283,9 +278,22 @@ // Inform the bluetooth adapter that we are disconnecting or // forgetting the device. - chrome.send('updateBluetoothDevice', - [item.data.address, item.connected ? 'disconnect' : 'forget']); - + var address = item.data.address; + if (item.connected) { + chrome.bluetoothPrivate.disconnectAll(address, function() { + if (chrome.runtime.lastError) { + options.BluetoothPairing.showMessage( + {message: 'bluetoothDisconnectFailed', address: address}); + } + }); + } else { + chrome.bluetoothPrivate.forgetDevice(address, function() { + if (chrome.runtime.lastError) { + options.BluetoothPairing.showMessage( + {message: 'bluetoothForgetFailed', address: address}); + } + }); + } chrome.send('coreOptionsUserMetricsAction', ['Options_BluetoothRemoveDevice']); }
diff --git a/chrome/browser/resources/options/chromeos/bluetooth_pair_device_overlay.js b/chrome/browser/resources/options/chromeos/bluetooth_pair_device_overlay.js index 6dd3313..65f07c60 100644 --- a/chrome/browser/resources/options/chromeos/bluetooth_pair_device_overlay.js +++ b/chrome/browser/resources/options/chromeos/bluetooth_pair_device_overlay.js
@@ -9,7 +9,7 @@ * @enum {string} */ var BluetoothPairingEventType = { - STARTUP: 'bluetoothStartConnecting', + CONNECTING: 'bluetoothStartConnecting', ENTER_PIN_CODE: 'bluetoothEnterPinCode', ENTER_PASSKEY: 'bluetoothEnterPasskey', REMOTE_PIN_CODE: 'bluetoothRemotePinCode', @@ -19,17 +19,45 @@ CANCELED: 'bluetoothPairingCanceled', DISMISSED: 'bluetoothPairingDismissed', // pairing dismissed (succeeded or // canceled). + NOOP: '' // Update device but do not show or update the dialog. }; /** * @typedef {{pairing: (BluetoothPairingEventType|undefined), - * device: !BluetoothDevice, + * device: !chrome.bluetooth.Device, * pincode: (string|undefined), * passkey: (number|undefined), * enteredKey: (number|undefined)}} */ var BluetoothPairingEvent; +/** + * Returns a BluetoothPairingEventType corresponding to |event_type|. + * @param {!chrome.bluetoothPrivate.PairingEventType} event_type + * @return {BluetoothPairingEventType} + */ +function GetBluetoothPairingEvent(event_type) { + switch (event_type) { + case chrome.bluetoothPrivate.PairingEventType.REQUEST_PINCODE: + return BluetoothPairingEventType.ENTER_PIN_CODE; + case chrome.bluetoothPrivate.PairingEventType.DISPLAY_PINCODE: + return BluetoothPairingEventType.REMOTE_PIN_CODE; + case chrome.bluetoothPrivate.PairingEventType.REQUEST_PASSKEY: + return BluetoothPairingEventType.ENTER_PASSKEY; + case chrome.bluetoothPrivate.PairingEventType.DISPLAY_PASSKEY: + return BluetoothPairingEventType.REMOTE_PASSKEY; + case chrome.bluetoothPrivate.PairingEventType.KEYS_ENTERED: + return BluetoothPairingEventType.NOOP; + case chrome.bluetoothPrivate.PairingEventType.CONFIRM_PASSKEY: + return BluetoothPairingEventType.CONFIRM_PASSKEY; + case chrome.bluetoothPrivate.PairingEventType.REQUEST_AUTHORIZATION: + return BluetoothPairingEventType.NOOP; + case chrome.bluetoothPrivate.PairingEventType.COMPLETE: + return BluetoothPairingEventType.NOOP; + } + return BluetoothPairingEventType.NOOP; +} + cr.define('options', function() { /** @const */ var Page = cr.ui.pageManager.Page; /** @const */ var PageManager = cr.ui.pageManager.PageManager; @@ -85,27 +113,46 @@ PageManager.closeOverlay(); }; $('bluetooth-pair-device-reject-button').onclick = function() { - chrome.send('updateBluetoothDevice', - [self.event_.device.address, 'reject']); + var options = { + device: self.event_.device, + response: chrome.bluetoothPrivate.PairingResponse.REJECT + }; + chrome.bluetoothPrivate.setPairingResponse(options); self.event_.pairing = BluetoothPairingEventType.DISMISSED; PageManager.closeOverlay(); }; $('bluetooth-pair-device-connect-button').onclick = function() { - var args = [self.event_.device.address, 'connect']; - var passkey = self.event_.passkey; - if (passkey) - args.push(String(passkey)); - else if (!$('bluetooth-pairing-passkey-entry').hidden) - args.push($('bluetooth-passkey').value); - else if (!$('bluetooth-pairing-pincode-entry').hidden) - args.push($('bluetooth-pincode').value); - chrome.send('updateBluetoothDevice', args); // Prevent sending a 'connect' command twice. $('bluetooth-pair-device-connect-button').disabled = true; + + var options = { + device: self.event_.device, + response: chrome.bluetoothPrivate.PairingResponse.CONFIRM + }; + var passkey = self.event_.passkey; + if (passkey) { + options.passkey = passkey; + } else if (!$('bluetooth-pairing-passkey-entry').hidden) { + options.passkey = parseInt($('bluetooth-passkey').value, 10); + } else if (!$('bluetooth-pairing-pincode-entry').hidden) { + options.pincode = $('bluetooth-pincode').value; + } else { + BluetoothPairing.connect(self.event_.device); + return; + } + chrome.bluetoothPrivate.setPairingResponse(options); + var event = /** @type {!BluetoothPairingEvent} */ ({ + pairing: BluetoothPairingEventType.CONNECTING, + device: self.event_.device + }); + BluetoothPairing.showDialog(event); }; $('bluetooth-pair-device-accept-button').onclick = function() { - chrome.send('updateBluetoothDevice', - [self.event_.device.address, 'accept']); + var options = { + device: self.event_.device, + response: chrome.bluetoothPrivate.PairingResponse.CONFIRM + }; + chrome.bluetoothPrivate.setPairingResponse(options); // Prevent sending a 'accept' command twice. $('bluetooth-pair-device-accept-button').disabled = true; }; @@ -141,8 +188,11 @@ this.event_.pairing != BluetoothPairingEventType.DISMISSED && this.event_.pairing != BluetoothPairingEventType.CONNECT_FAILED) { this.event_.pairing = BluetoothPairingEventType.CANCELED; - chrome.send('updateBluetoothDevice', - [this.event_.device.address, 'cancel']); + var options = { + device: this.event_.device, + response: chrome.bluetoothPrivate.PairingResponse.CANCEL + }; + chrome.bluetoothPrivate.setPairingResponse(options); } }, @@ -170,19 +220,56 @@ /** * Configures the overlay for pairing a device. * @param {!BluetoothPairingEvent} event - * @param {boolean=} opt_dismissible + * @param {boolean=} opt_notDismissible */ - update: function(event, opt_dismissible) { + update: function(event, opt_notDismissible) { assert(event); assert(event.device); - this.event_ = - /** @type {BluetoothPairingEvent} */ (Object.assign({}, event)); - Object.assign(this.event_.device, event.device); + if (this.event_ == undefined || + this.event_.device.address != event.device.address) { + // New event or device, create a new BluetoothPairingEvent. + this.event_ = + /** @type {BluetoothPairingEvent} */ ({device: event.device}); + } else { + // Update to an existing event; just update |device| in case it changed. + this.event_.device = event.device; + } + + if (event.pairing) + this.event_.pairing = event.pairing; + + if (!this.event_.pairing) + return; + + if (this.event_.pairing == BluetoothPairingEventType.CANCELED) { + // If we receive an update after canceling a pairing (e.g. a key + // press), ignore it and clear the device so that future updates for + // the device will also be ignored. + this.event_.device.address = ''; + return; + } + + if (event.pincode != undefined) + this.event_.pincode = event.pincode; + if (event.passkey != undefined) + this.event_.passkey = event.passkey; + if (event.enteredKey != undefined) + this.event_.enteredKey = event.enteredKey; + + // Update the list model (in case, e.g. the name changed). + if (this.event_.device.name) { + var list = $('bluetooth-unpaired-devices-list'); + if (list) { // May be undefined in tests. + var index = list.find(this.event_.device.address); + if (index != undefined) + list.dataModel.splice(index, 1, this.event_.device); + } + } // Update the pairing instructions. var instructionsEl = assert($('bluetooth-pairing-instructions')); this.clearElement_(instructionsEl); - this.dismissible_ = opt_dismissible !== false; + this.dismissible_ = opt_notDismissible !== true; var message = loadTimeData.getString(this.event_.pairing); message = message.replace('%1', this.event_.device.name); instructionsEl.textContent = message; @@ -219,7 +306,7 @@ 'bluetooth-pair-device-connect-button', 'bluetooth-pair-device-cancel-button']); $('bluetooth-passkey').value = ''; - } else if (this.event_.pairing == BluetoothPairingEventType.STARTUP) { + } else if (this.event_.pairing == BluetoothPairingEventType.CONNECTING) { // Starting the pairing process. this.displayElements_(['bluetooth-pair-device-cancel-button']); } else { @@ -331,11 +418,31 @@ * Configures the device pairing instructions and displays the pairing * overlay. * @param {!BluetoothPairingEvent} event - * @param {boolean=} opt_dismissible If set to false, the dialog can not + * @param {boolean=} opt_notDismissible If set to true, the dialog can not * be dismissed. */ - BluetoothPairing.showDialog = function(event, opt_dismissible) { - BluetoothPairing.getInstance().update(event, opt_dismissible); + BluetoothPairing.showDialog = function(event, opt_notDismissible) { + BluetoothPairing.getInstance().update(event, opt_notDismissible); + PageManager.showPageByName('bluetoothPairing', false); + }; + + + /** + * Handles bluetoothPrivate onPairing events. + * @param {!chrome.bluetoothPrivate.PairingEvent} event + */ + BluetoothPairing.onBluetoothPairingEvent = function(event) { + var dialog = BluetoothPairing.getInstance(); + if (!dialog.event_ || dialog.event_.device.address != event.device.address) + return; // Ignore events not associated with an active connect or pair. + var pairingEvent = /** @type {!BluetoothPairingEvent} */ ({ + pairing: GetBluetoothPairingEvent(event.pairing), + device: event.device, + pincode: event.pincode, + passkey: event.passkey, + enteredKey: event.enteredKey + }); + dialog.update(pairingEvent); PageManager.showPageByName('bluetoothPairing', false); }; @@ -371,16 +478,79 @@ } var event = /** @type {!BluetoothPairingEvent} */ ({ pairing: /** @type {BluetoothPairingEventType} */ (data.message), - device: /** @type {!BluetoothDevice} */ ({ + device: /** @type {!chrome.bluetooth.Device} */ ({ name: name, address: data.address, - paired: false, - connected: false, - connecting: false, - connectable: false }) }); - BluetoothPairing.showDialog(event, false /* not dismissible */); + BluetoothPairing.showDialog(event, true /* not dismissible */); + }; + + /** + * Sends a connect request to the bluetoothPrivate API. If there is an error + * the pairing dialog will be shown with the error message. + * @param {!chrome.bluetooth.Device} device + * @param {boolean=} opt_showConnecting If true, show 'connecting' message in + * the pairing dialog. + */ + BluetoothPairing.connect = function(device, opt_showConnecting) { + if (opt_showConnecting) { + var event = /** @type {!BluetoothPairingEvent} */ ( + {pairing: BluetoothPairingEventType.CONNECTING, device: device}); + BluetoothPairing.showDialog(event); + } + var address = device.address; + chrome.bluetoothPrivate.connect(address, function(result) { + BluetoothPairing.connectCompleted_(address, result); + }); + }; + + /** + * Connect request completion callback. + * @param {string} address + * @param {chrome.bluetoothPrivate.ConnectResultType} result + */ + BluetoothPairing.connectCompleted_ = function(address, result) { + var message; + if (chrome.runtime.lastError) { + var errorMessage = chrome.runtime.lastError.message; + if (errorMessage != 'Connect failed') { + console.error('bluetoothPrivate.connect: Unexpected error for: ' + + address + ': ' + errorMessage); + } + } + switch (result) { + case chrome.bluetoothPrivate.ConnectResultType.SUCCESS: + case chrome.bluetoothPrivate.ConnectResultType.ALREADY_CONNECTED: + BluetoothPairing.dismissDialog(); + return; + case chrome.bluetoothPrivate.ConnectResultType.UNKNOWN_ERROR: + message = 'bluetoothConnectUnknownError'; + break; + case chrome.bluetoothPrivate.ConnectResultType.IN_PROGRESS: + message = 'bluetoothConnectInProgress'; + break; + case chrome.bluetoothPrivate.ConnectResultType.FAILED: + message = 'bluetoothConnectFailed'; + break; + case chrome.bluetoothPrivate.ConnectResultType.AUTH_FAILED: + message = 'bluetoothConnectAuthFailed'; + break; + case chrome.bluetoothPrivate.ConnectResultType.AUTH_CANCELED: + message = 'bluetoothConnectAuthCanceled'; + break; + case chrome.bluetoothPrivate.ConnectResultType.AUTH_REJECTED: + message = 'bluetoothConnectAuthRejected'; + break; + case chrome.bluetoothPrivate.ConnectResultType.AUTH_TIMEOUT: + message = 'bluetoothConnectAuthTimeout'; + break; + case chrome.bluetoothPrivate.ConnectResultType.UNSUPPORTED_DEVICE: + message = 'bluetoothConnectUnsupportedDevice'; + break; + } + if (message) + BluetoothPairing.showMessage({message: message, address: address}); }; /**
diff --git a/chrome/browser/resources/settings/appearance_page/appearance_page.html b/chrome/browser/resources/settings/appearance_page/appearance_page.html index 613b8cb..63957d4 100644 --- a/chrome/browser/resources/settings/appearance_page/appearance_page.html +++ b/chrome/browser/resources/settings/appearance_page/appearance_page.html
@@ -93,8 +93,11 @@ <neon-animatable id="appearance-fonts"> <settings-subheader i18n-values="page-title:customizeFonts"> </settings-subheader> - <settings-appearance-fonts-page prefs="{{prefs}}"> - </settings-appearance-fonts-page> + <template is="dom-if" if="[[showFontsPage_(currentRoute.subpage.*)]]" + restamp> + <settings-appearance-fonts-page prefs="{{prefs}}"> + </settings-appearance-fonts-page> + </template> </neon-animatable> </settings-animated-pages> </template>
diff --git a/chrome/browser/resources/settings/appearance_page/appearance_page.js b/chrome/browser/resources/settings/appearance_page/appearance_page.js index 09a8aad..c38b25e 100644 --- a/chrome/browser/resources/settings/appearance_page/appearance_page.js +++ b/chrome/browser/resources/settings/appearance_page/appearance_page.js
@@ -99,4 +99,9 @@ resetTheme_: function() { chrome.send('resetTheme'); }, + + /** @private */ + showFontsPage_: function() { + return this.currentRoute.subpage[0] == 'appearance-fonts'; + }, });
diff --git a/chrome/browser/resources/settings/site_settings/compiled_resources.gyp b/chrome/browser/resources/settings/site_settings/compiled_resources.gyp index 12796dd8..16fa38a 100644 --- a/chrome/browser/resources/settings/site_settings/compiled_resources.gyp +++ b/chrome/browser/resources/settings/site_settings/compiled_resources.gyp
@@ -16,7 +16,7 @@ 'site_details_permission.js', ], 'externs': [ - '../../../../../third_party/closure_compiler/externs/settings_private.js' + '../../../../../third_party/closure_compiler/externs/settings_private.js', ], }, 'includes': ['../../../../../third_party/closure_compiler/compile_js.gypi'], @@ -33,7 +33,25 @@ 'site_settings_behavior.js', ], 'externs': [ - '../../../../../third_party/closure_compiler/externs/settings_private.js' + '../../../../../third_party/closure_compiler/externs/settings_private.js', + ], + }, + 'includes': ['../../../../../third_party/closure_compiler/compile_js.gypi'], + }, + { + 'target_name': 'site_list', + 'variables': { + 'depends': [ + '../../../../../ui/webui/resources/js/compiled_resources.gyp:assert', + '../../../../../ui/webui/resources/js/compiled_resources.gyp:cr', + '../../../../../ui/webui/resources/js/compiled_resources.gyp:load_time_data', + '../prefs/prefs_behavior.js', + '../prefs/prefs_types.js', + 'constants.js', + 'site_settings_behavior.js', + ], + 'externs': [ + '../../../../../third_party/closure_compiler/externs/settings_private.js', ], }, 'includes': ['../../../../../third_party/closure_compiler/compile_js.gypi'], @@ -49,7 +67,7 @@ 'constants.js', ], 'externs': [ - '../../../../../third_party/closure_compiler/externs/settings_private.js' + '../../../../../third_party/closure_compiler/externs/settings_private.js', ], }, 'includes': ['../../../../../third_party/closure_compiler/compile_js.gypi'], @@ -68,7 +86,7 @@ 'site_settings_behavior.js', ], 'externs': [ - '../../../../../third_party/closure_compiler/externs/settings_private.js' + '../../../../../third_party/closure_compiler/externs/settings_private.js', ], }, 'includes': ['../../../../../third_party/closure_compiler/compile_js.gypi'],
diff --git a/chrome/browser/resources/settings/site_settings/site_list.html b/chrome/browser/resources/settings/site_settings/site_list.html index 82349d1..2c0ae8337 100644 --- a/chrome/browser/resources/settings/site_settings/site_list.html +++ b/chrome/browser/resources/settings/site_settings/site_list.html
@@ -25,7 +25,7 @@ <iron-icon id="icon" icon="icons:expand-more"></iron-icon> </div> </paper-item> - <paper-menu class="menu-content"> + <paper-menu class="menu-content" id="listContainer"> <template is="dom-repeat" items="{{sites_}}"> <div class="site-list horizontal layout center"> <iron-icon icon="[[computeSiteIcon_(item.url)]]"
diff --git a/chrome/browser/resources/settings/site_settings/site_list.js b/chrome/browser/resources/settings/site_settings/site_list.js index 5f0f4a7e..ee50e514 100644 --- a/chrome/browser/resources/settings/site_settings/site_list.js +++ b/chrome/browser/resources/settings/site_settings/site_list.js
@@ -107,12 +107,23 @@ ready: function() { CrSettingsPrefs.initialized.then(function() { - this.setUpActionMenu_(); - this.populateList_(); + this.initialize_(); }.bind(this)); }, /** + * One-time initialization routines for this class. + * @private + */ + initialize_: function() { + this.setUpActionMenu_(); + this.populateList_(); + + if (this.categoryEnabled) + this.$.category.opened = true; + }, + + /** * Handles the data changing, for example when the category is flipped from * ALLOW to BLOCK or sites are added to the list. * @private @@ -143,7 +154,8 @@ this.computeCategoryExceptionsPrefName(this.category)); var sites = pref.value; for (var origin in sites) { - if (sites[origin].setting == this.categorySubtype) { + var site = /** @type {{setting: number}} */(sites[origin]); + if (site.setting == this.categorySubtype) { var tokens = origin.split(','); newList.push({url: tokens[0]}); } @@ -166,6 +178,7 @@ /** * A handler for selecting a site (by clicking on the origin). + * @param {!{model: !{item: !{url: string}}}} event * @private */ onOriginTap_: function(event) { @@ -182,7 +195,7 @@ /** * Returns the appropriate header value for display. - * @param {array<string>} siteList The list of all sites to display for this + * @param {Array<string>} siteList The list of all sites to display for this * category subtype. * @param {boolean} toggleState The state of the global toggle for this * category. @@ -213,7 +226,7 @@ /** * Returns whether to show the site list. - * @param {array} siteList The list of all sites to display for this category + * @param {Array} siteList The list of all sites to display for this category * subtype. * @param {boolean} toggleState The state of the global toggle for this * category.
diff --git a/chrome/browser/resources/settings/site_settings/site_settings_category.html b/chrome/browser/resources/settings/site_settings/site_settings_category.html index a98a16f..829ba97 100644 --- a/chrome/browser/resources/settings/site_settings/site_settings_category.html +++ b/chrome/browser/resources/settings/site_settings/site_settings_category.html
@@ -6,7 +6,7 @@ <link rel="import" href="chrome://resources/polymer/v1_0/paper-item/paper-icon-item.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-item/paper-item-body.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-toggle-button/paper-toggle-button.html"> -<link rel="import" href="chrome://md-settings/prefs/prefs.html"> +<link rel="import" href="chrome://md-settings/prefs/prefs_types.html"> <link rel="import" href="chrome://md-settings/settings_page/settings_animated_pages.html"> <link rel="import" href="chrome://md-settings/settings_page/settings_subheader.html"> <link rel="import" href="chrome://md-settings/site_settings/constants.html">
diff --git a/chrome/browser/resources/settings/site_settings/site_settings_category.js b/chrome/browser/resources/settings/site_settings/site_settings_category.js index 3b58fde..5526e4f 100644 --- a/chrome/browser/resources/settings/site_settings/site_settings_category.js +++ b/chrome/browser/resources/settings/site_settings/site_settings_category.js
@@ -73,8 +73,6 @@ * @private */ onToggleChange_: function(event) { - assert(CrSettingsPrefs.isInitialized); - switch (this.category) { case settings.ContentSettingsTypes.COOKIES: case settings.ContentSettingsTypes.JAVASCRIPT:
diff --git a/chrome/browser/safe_browsing/incident_reporting/environment_data_collection_win.cc b/chrome/browser/safe_browsing/incident_reporting/environment_data_collection_win.cc index 39d065e..0d2b881 100644 --- a/chrome/browser/safe_browsing/incident_reporting/environment_data_collection_win.cc +++ b/chrome/browser/safe_browsing/incident_reporting/environment_data_collection_win.cc
@@ -14,6 +14,7 @@ #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" #include "base/win/registry.h" +#include "base/win/win_util.h" #include "chrome/browser/install_verification/win/module_info.h" #include "chrome/browser/install_verification/win/module_verification_common.h" #include "chrome/browser/net/service_providers_win.h" @@ -297,6 +298,11 @@ } } +void CollectDomainEnrollmentData( + ClientIncidentReport_EnvironmentData_OS* os_data) { + os_data->set_is_enrolled_to_domain(base::win::IsEnrolledToDomain()); +} + void CollectPlatformProcessData( ClientIncidentReport_EnvironmentData_Process* process) { CollectDlls(process); @@ -313,5 +319,6 @@ CollectRegistryData(kRegKeysToCollect, arraysize(kRegKeysToCollect), os_data->mutable_registry_key()); } + CollectDomainEnrollmentData(os_data); } } // namespace safe_browsing
diff --git a/chrome/browser/safe_browsing/incident_reporting/environment_data_collection_win.h b/chrome/browser/safe_browsing/incident_reporting/environment_data_collection_win.h index 4dacce3..4469467 100644 --- a/chrome/browser/safe_browsing/incident_reporting/environment_data_collection_win.h +++ b/chrome/browser/safe_browsing/incident_reporting/environment_data_collection_win.h
@@ -16,6 +16,7 @@ namespace safe_browsing { +class ClientIncidentReport_EnvironmentData_OS; class ClientIncidentReport_EnvironmentData_OS_RegistryKey; class ClientIncidentReport_EnvironmentData_Process; @@ -55,6 +56,11 @@ google::protobuf::RepeatedPtrField< ClientIncidentReport_EnvironmentData_OS_RegistryKey>* key_data); +// Populates |os_data| with information about the machine's domain enrollment +// status. +void CollectDomainEnrollmentData( + ClientIncidentReport_EnvironmentData_OS* os_data); + } // namespace safe_browsing #endif // CHROME_BROWSER_SAFE_BROWSING_INCIDENT_REPORTING_ENVIRONMENT_DATA_COLLECTION_WIN_H_
diff --git a/chrome/browser/safe_browsing/incident_reporting/environment_data_collection_win_unittest.cc b/chrome/browser/safe_browsing/incident_reporting/environment_data_collection_win_unittest.cc index 16eb4c0..6097649 100644 --- a/chrome/browser/safe_browsing/incident_reporting/environment_data_collection_win_unittest.cc +++ b/chrome/browser/safe_browsing/incident_reporting/environment_data_collection_win_unittest.cc
@@ -305,4 +305,13 @@ EXPECT_EQ(REG_SZ, subkey_pb.value(0).type()); } +TEST(SafeBrowsingEnvironmentDataCollectionWinTest, + CollectDomainEnrollmentData) { + // The test may or may not be running on a domain-enrolled machine, so all we + // can check is that some value is filled in. + ClientIncidentReport_EnvironmentData_OS os_data; + CollectDomainEnrollmentData(&os_data); + EXPECT_TRUE(os_data.has_is_enrolled_to_domain()); +} + } // namespace safe_browsing
diff --git a/chrome/browser/shell_integration_win.cc b/chrome/browser/shell_integration_win.cc index d23682b..5de8cf59 100644 --- a/chrome/browser/shell_integration_win.cc +++ b/chrome/browser/shell_integration_win.cc
@@ -624,19 +624,6 @@ shortcut = programs_folder.Append(shortcut_name); if (base::PathExists(shortcut)) return shortcut; - - // Check in "Start Menu\Programs\<BROWSER>" if the shortcut was not found in - // "Start Menu\Programs". This fallback check is here to handle running - // instances that are updated past the change that migrates Chrome's start - // menu shortcut from the "Google Chrome" folder up into the main "Programs" - // folder. This code will become obsolete when the migration change lands, - // and is to be removed in that change. - shortcut = - programs_folder.Append(dist->GetStartMenuShortcutSubfolder( - BrowserDistribution::SUBFOLDER_CHROME)) - .Append(shortcut_name); - if (base::PathExists(shortcut)) - return shortcut; } return base::FilePath();
diff --git a/chrome/browser/signin/easy_unlock_service_regular.cc b/chrome/browser/signin/easy_unlock_service_regular.cc index a8e0d52..90e017a 100644 --- a/chrome/browser/signin/easy_unlock_service_regular.cc +++ b/chrome/browser/signin/easy_unlock_service_regular.cc
@@ -4,6 +4,7 @@ #include "chrome/browser/signin/easy_unlock_service_regular.h" +#include "base/base64url.h" #include "base/bind.h" #include "base/command_line.h" #include "base/logging.h" @@ -24,7 +25,6 @@ #include "chromeos/login/user_names.h" #include "components/gcm_driver/gcm_profile_service.h" #include "components/pref_registry/pref_registry_syncable.h" -#include "components/proximity_auth/cryptauth/base64url.h" #include "components/proximity_auth/cryptauth/cryptauth_access_token_fetcher.h" #include "components/proximity_auth/cryptauth/cryptauth_client_impl.h" #include "components/proximity_auth/cryptauth/cryptauth_enrollment_manager.h" @@ -127,8 +127,12 @@ for (const auto& device : remote_devices) { scoped_ptr<base::DictionaryValue> dict(new base::DictionaryValue()); std::string b64_public_key, b64_psk; - proximity_auth::Base64UrlEncode(device.public_key, &b64_public_key); - proximity_auth::Base64UrlEncode(device.persistent_symmetric_key, &b64_psk); + base::Base64UrlEncode(device.public_key, + base::Base64UrlEncodePolicy::INCLUDE_PADDING, + &b64_public_key); + base::Base64UrlEncode(device.persistent_symmetric_key, + base::Base64UrlEncodePolicy::INCLUDE_PADDING, + &b64_psk); dict->SetString("name", device.name); dict->SetString("psk", b64_psk); @@ -298,7 +302,13 @@ // devices. if (GetCryptAuthDeviceManager()) { std::string public_key; - proximity_auth::Base64UrlDecode(b64_public_key, &public_key); + if (!base::Base64UrlDecode(b64_public_key, + base::Base64UrlDecodePolicy::REQUIRE_PADDING, + &public_key)) { + PA_LOG(ERROR) << "Unable to base64url decode the public key: " + << b64_public_key; + return; + } const std::vector<cryptauth::ExternalDeviceInfo> unlock_keys = GetCryptAuthDeviceManager()->unlock_keys(); auto iterator = std::find_if(
diff --git a/chrome/browser/signin/easy_unlock_service_signin_chromeos.cc b/chrome/browser/signin/easy_unlock_service_signin_chromeos.cc index a8909e89..938b3c9 100644 --- a/chrome/browser/signin/easy_unlock_service_signin_chromeos.cc +++ b/chrome/browser/signin/easy_unlock_service_signin_chromeos.cc
@@ -4,6 +4,7 @@ #include "chrome/browser/signin/easy_unlock_service_signin_chromeos.h" +#include "base/base64url.h" #include "base/basictypes.h" #include "base/bind.h" #include "base/command_line.h" @@ -22,7 +23,6 @@ #include "chrome/browser/signin/easy_unlock_metrics.h" #include "chromeos/login/auth/user_context.h" #include "chromeos/tpm/tpm_token_loader.h" -#include "components/proximity_auth/cryptauth/base64url.h" #include "components/proximity_auth/logging/logging.h" #include "components/proximity_auth/remote_device.h" #include "components/proximity_auth/switches.h" @@ -129,7 +129,9 @@ } std::string device_public_key_base64; - proximity_auth::Base64UrlEncode(device_public_key, &device_public_key_base64); + base::Base64UrlEncode(device_public_key, + base::Base64UrlEncodePolicy::INCLUDE_PADDING, + &device_public_key_base64); for (const auto& device_data : it->second->devices) { if (device_data.public_key == device_public_key_base64) { PA_LOG(INFO) << "Wrapping challenge for " << user_id << "..."; @@ -427,9 +429,19 @@ // TODO(tengs): Currently, ProximityAuthSystem only supports one device. Once // multiple devices are supported, we need to load all devices. std::string decoded_public_key, decoded_psk, decoded_challenge; - proximity_auth::Base64UrlDecode(devices[0].public_key, &decoded_public_key); - proximity_auth::Base64UrlDecode(devices[0].psk, &decoded_psk); - proximity_auth::Base64UrlDecode(devices[0].challenge, &decoded_challenge); + if (!base::Base64UrlDecode(devices[0].public_key, + base::Base64UrlDecodePolicy::REQUIRE_PADDING, + &decoded_public_key) || + !base::Base64UrlDecode(devices[0].psk, + base::Base64UrlDecodePolicy::REQUIRE_PADDING, + &decoded_psk) || + !base::Base64UrlDecode(devices[0].challenge, + base::Base64UrlDecodePolicy::REQUIRE_PADDING, + &decoded_challenge)) { + PA_LOG(ERROR) << "Unable to base64url decode the input data."; + return; + } + proximity_auth::RemoteDevice::BluetoothType bluetooth_type = devices[0].bluetooth_type == chromeos::EasyUnlockDeviceKeyData::BLUETOOTH_LE
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn index c945da10..6c1d26a8 100644 --- a/chrome/browser/ui/BUILD.gn +++ b/chrome/browser/ui/BUILD.gn
@@ -117,8 +117,8 @@ "//third_party/WebKit/public:resources", "//third_party/adobe/flash:flapper_version_h", "//third_party/leveldatabase", - "//third_party/mojo/src/mojo/edk/system", "//third_party/libjingle", + "//third_party/mojo/src/mojo/edk/system", "//third_party/re2", "//ui/base/ime", "//ui/compositor", @@ -399,9 +399,9 @@ "//chrome/installer/util:strings", "//components/search_engines", "//google_update", - "//third_party/wtl", "//third_party/iaccessible2", "//third_party/isimpledom", + "//third_party/wtl", "//ui/app_list", ] if (!is_chrome_branded) {
diff --git a/chrome/browser/ui/autofill/save_card_bubble_controller.cc b/chrome/browser/ui/autofill/save_card_bubble_controller.cc new file mode 100644 index 0000000..f7186f6 --- /dev/null +++ b/chrome/browser/ui/autofill/save_card_bubble_controller.cc
@@ -0,0 +1,13 @@ +// Copyright 2015 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 "chrome/browser/ui/autofill/save_card_bubble_controller.h" + +namespace autofill { + +SaveCardBubbleController::LegalMessageLine::LegalMessageLine() {} + +SaveCardBubbleController::LegalMessageLine::~LegalMessageLine() {} + +} // namespace autofill
diff --git a/chrome/browser/ui/autofill/save_card_bubble_controller.h b/chrome/browser/ui/autofill/save_card_bubble_controller.h index cfde68a..231c9d0 100644 --- a/chrome/browser/ui/autofill/save_card_bubble_controller.h +++ b/chrome/browser/ui/autofill/save_card_bubble_controller.h
@@ -5,8 +5,12 @@ #ifndef CHROME_BROWSER_UI_AUTOFILL_SAVE_CARD_BUBBLE_CONTROLLER_H_ #define CHROME_BROWSER_UI_AUTOFILL_SAVE_CARD_BUBBLE_CONTROLLER_H_ +#include <vector> + #include "base/macros.h" #include "base/strings/string16.h" +#include "ui/gfx/range/range.h" +#include "url/gurl.h" namespace autofill { @@ -15,6 +19,21 @@ // Interface that exposes controller functionality to SaveCardBubbleView. class SaveCardBubbleController { public: + struct LegalMessageLine { + struct Link { + gfx::Range range; + GURL url; + }; + + LegalMessageLine(); + ~LegalMessageLine(); + + base::string16 text; + std::vector<Link> links; + }; + + typedef std::vector<LegalMessageLine> LegalMessageLines; + // Returns the title that should be displayed in the bubble. virtual base::string16 GetWindowTitle() const = 0; @@ -22,11 +41,18 @@ // Returns an empty string if no message should be displayed. virtual base::string16 GetExplanatoryMessage() const = 0; + // Interaction. virtual void OnSaveButton() = 0; virtual void OnCancelButton() = 0; virtual void OnLearnMoreClicked() = 0; + virtual void OnLegalMessageLinkClicked(const GURL& url) = 0; virtual void OnBubbleClosed() = 0; + // State. + + // Returns empty vector if no legal message should be shown. + virtual const LegalMessageLines& GetLegalMessageLines() const = 0; + protected: SaveCardBubbleController() {} virtual ~SaveCardBubbleController() {}
diff --git a/chrome/browser/ui/autofill/save_card_bubble_controller_impl.cc b/chrome/browser/ui/autofill/save_card_bubble_controller_impl.cc index ceb341b5..daca87b 100644 --- a/chrome/browser/ui/autofill/save_card_bubble_controller_impl.cc +++ b/chrome/browser/ui/autofill/save_card_bubble_controller_impl.cc
@@ -4,6 +4,9 @@ #include "chrome/browser/ui/autofill/save_card_bubble_controller_impl.h" +#include "base/i18n/message_formatter.h" +#include "base/strings/string_util.h" +#include "base/strings/utf_string_conversions.h" #include "chrome/browser/ui/autofill/save_card_bubble_view.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_finder.h" @@ -16,6 +19,8 @@ DEFINE_WEB_CONTENTS_USER_DATA_KEY(autofill::SaveCardBubbleControllerImpl); +namespace autofill { + namespace { // Number of seconds the bubble and icon will survive navigations, starting @@ -23,9 +28,113 @@ // TODO(bondd): Share with ManagePasswordsUIController. const int kSurviveNavigationSeconds = 5; -} // namespace +// Replace "{0}", "{1}", ... in |template_icu| with corresponding strings +// from |display_texts|. Sets |out_message| to the resulting string, with +// start position of each replacement in |out_offsets|. +// Return false on failure. If false is returned then contents of |out_message| +// and |out_offsets| are undefined. +bool ReplaceTemplatePlaceholders( + const base::string16& template_icu, + const std::vector<base::string16>& display_texts, + base::string16* out_message, + std::vector<size_t>* out_offsets) { + // Escape "$" -> "$$" for ReplaceStringPlaceholders(). + // + // Edge cases: + // 1. Two or more consecutive $ characters will be incorrectly expanded + // ("$$" -> "$$$$", which ReplaceStringPlaceholders() then turns into + // "$$$"). + // + // 2. "${" will cause false to be returned. "${0}" will expand to "$${0}". + // FormatWithNumberedArgs() turns it into "$$$1", which + // ReplaceStringPlaceholders() then turns into "$$1" without doing the + // parameter replacement. This causes false to be returned because each + // parameter is not used exactly once. + // + // Both of these cases are noted in the header file, and are unlikely to + // occur in any actual legal message. + base::string16 template_icu_escaped; + base::ReplaceChars(template_icu, base::ASCIIToUTF16("$"), + base::ASCIIToUTF16("$$"), &template_icu_escaped); -namespace autofill { + // Replace "{0}" -> "$1", "{1}" -> "$2", ... to prepare |template_dollars| + // for ReplaceStringPlaceholders(). + base::string16 template_dollars = + base::i18n::MessageFormatter::FormatWithNumberedArgs( + template_icu_escaped, "$1", "$2", "$3", "$4", "$5", "$6", "$7"); + + // FormatWithNumberedArgs() returns an empty string on failure. + if (template_dollars.empty() && !template_icu.empty()) + return false; + + // Replace "$1", "$2", ... with the display text of each parameter. + *out_message = base::ReplaceStringPlaceholders(template_dollars, + display_texts, out_offsets); + + // Each parameter must be used exactly once. If a parameter is unused or + // used more than once then it can't be determined which |offsets| entry + // corresponds to which parameter. + return out_offsets->size() == display_texts.size(); +} + +// Parses |line| and sets |out|. +// Returns false on failure. |out| is not modified if false is returned. +bool ParseLegalMessageLine(const base::DictionaryValue& line, + SaveCardBubbleController::LegalMessageLine* out) { + SaveCardBubbleController::LegalMessageLine result; + + // |display_texts| elements are the strings that will be substituted for + // "{0}", "{1}", etc. in the template string. + std::vector<base::string16> display_texts; + + // Process all the template parameters. + const base::ListValue* template_parameters = nullptr; + if (line.GetList("template_parameter", &template_parameters)) { + display_texts.resize(template_parameters->GetSize()); + result.links.resize(template_parameters->GetSize()); + + for (size_t parameter_index = 0; + parameter_index < template_parameters->GetSize(); ++parameter_index) { + const base::DictionaryValue* single_parameter; + std::string url; + if (!template_parameters->GetDictionary(parameter_index, + &single_parameter) || + !single_parameter->GetString("display_text", + &display_texts[parameter_index]) || + !single_parameter->GetString("url", &url)) { + return false; + } + result.links[parameter_index].url = GURL(url); + } + } + + // Read the template string. It's a small subset of the ICU message format + // syntax. + base::string16 template_icu; + if (!line.GetString("template", &template_icu)) + return false; + + // Replace the placeholders in |template_icu| with strings from + // |display_texts|, and store the start position of each replacement in + // |offsets|. + std::vector<size_t> offsets; + if (!ReplaceTemplatePlaceholders(template_icu, display_texts, &result.text, + &offsets)) { + return false; + } + + // Fill in range values for all links. + for (size_t offset_index = 0; offset_index < offsets.size(); ++offset_index) { + size_t range_start = offsets[offset_index]; + result.links[offset_index].range = gfx::Range( + range_start, range_start + display_texts[offset_index].size()); + } + + *out = result; + return true; +} + +} // namespace SaveCardBubbleControllerImpl::SaveCardBubbleControllerImpl( content::WebContents* web_contents) @@ -54,6 +163,23 @@ // TODO(bondd): Store legal_message here. } +bool SaveCardBubbleControllerImpl::SetLegalMessage( + const base::ListValue& lines) { + // Process all lines of the message. See comment in header file for example + // of valid |lines| data. + legal_message_lines_.resize(lines.GetSize()); + for (size_t i = 0; i < lines.GetSize(); ++i) { + const base::DictionaryValue* single_line; + if (!lines.GetDictionary(i, &single_line) || + !ParseLegalMessageLine(*single_line, &legal_message_lines_[i])) { + legal_message_lines_.clear(); + return false; + } + } + + return true; +} + void SaveCardBubbleControllerImpl::ShowBubble(bool user_action) { DCHECK(!save_card_callback_.is_null()); @@ -104,9 +230,11 @@ } void SaveCardBubbleControllerImpl::OnLearnMoreClicked() { - web_contents()->OpenURL(content::OpenURLParams( - GURL(kHelpURL), content::Referrer(), NEW_FOREGROUND_TAB, - ui::PAGE_TRANSITION_LINK, false)); + OpenUrl(GURL(kHelpURL)); +} + +void SaveCardBubbleControllerImpl::OnLegalMessageLinkClicked(const GURL& url) { + OpenUrl(url); } void SaveCardBubbleControllerImpl::OnBubbleClosed() { @@ -114,12 +242,23 @@ UpdateIcon(); } +const SaveCardBubbleController::LegalMessageLines& +SaveCardBubbleControllerImpl::GetLegalMessageLines() const { + return legal_message_lines_; +} + void SaveCardBubbleControllerImpl::UpdateIcon() { Browser* browser = chrome::FindBrowserWithWebContents(web_contents()); LocationBar* location_bar = browser->window()->GetLocationBar(); location_bar->UpdateSaveCreditCardIcon(); } +void SaveCardBubbleControllerImpl::OpenUrl(const GURL& url) { + web_contents()->OpenURL( + content::OpenURLParams(url, content::Referrer(), NEW_FOREGROUND_TAB, + ui::PAGE_TRANSITION_LINK, false)); +} + void SaveCardBubbleControllerImpl::DidNavigateMainFrame( const content::LoadCommittedDetails& details, const content::FrameNavigateParams& params) {
diff --git a/chrome/browser/ui/autofill/save_card_bubble_controller_impl.h b/chrome/browser/ui/autofill/save_card_bubble_controller_impl.h index dfcd522..4f104fad4 100644 --- a/chrome/browser/ui/autofill/save_card_bubble_controller_impl.h +++ b/chrome/browser/ui/autofill/save_card_bubble_controller_impl.h
@@ -31,6 +31,35 @@ void InitializeForUpload(const base::Closure& save_card_callback, scoped_ptr<base::DictionaryValue> legal_message); + // TODO(bondd): Combine SetLegalMessage() with InitializeForUpload(). + // Example of valid |lines| data: + // [ { + // "template" : "The legal documents are: {0} and {1}", + // "template_parameter" : [ { + // "display_text" : "Terms of Service", + // "url": "http://www.example.com/tos" + // }, { + // "display_text" : "Privacy Policy", + // "url": "http://www.example.com/pp" + // } ], + // }, { + // "template" : "This is the second line and it has no parameters" + // } ] + // + // Caveats: + // 1. '{' and '}' may be displayed by escaping them with an apostrophe in the + // template string, e.g. "template" : "Here is a literal '{'" + // 2. Two or more consecutive dollar signs in the template string will not + // expand correctly. + // 3. "${" anywhere in the template string is invalid. + // 4. "\n" embedded anywhere in the template string, or an empty template + // string, can be used to separate paragraphs. It is not possible to create + // a completely blank line by using two consecutive newlines (they will be + // treated as a single newline by views::StyledLabel). + // + // Returns false if contents of |lines| are invalid. + bool SetLegalMessage(const base::ListValue& lines); + // InitializeForLocalSave() or InitializeForUpload() must be called first. void ShowBubble(bool user_action); @@ -46,8 +75,11 @@ void OnSaveButton() override; void OnCancelButton() override; void OnLearnMoreClicked() override; + void OnLegalMessageLinkClicked(const GURL& url) override; void OnBubbleClosed() override; + const LegalMessageLines& GetLegalMessageLines() const override; + private: friend class content::WebContentsUserData<SaveCardBubbleControllerImpl>; @@ -57,6 +89,8 @@ // Update the visibility and toggled state of the Omnibox save card icon. void UpdateIcon(); + void OpenUrl(const GURL& url); + // content::WebContentsObserver: void DidNavigateMainFrame( const content::LoadCommittedDetails& details, @@ -73,6 +107,9 @@ // Governs whether the upload or local save version of the UI should be shown. bool is_uploading_; + // If no legal message should be shown then this variable is an empty vector. + LegalMessageLines legal_message_lines_; + // Used to measure the amount of time on a page; if it's less than some // reasonable limit, then don't close the bubble upon navigation. scoped_ptr<base::ElapsedTimer> timer_;
diff --git a/chrome/browser/ui/autofill/save_card_bubble_controller_impl_unittest.cc b/chrome/browser/ui/autofill/save_card_bubble_controller_impl_unittest.cc new file mode 100644 index 0000000..f2a6274 --- /dev/null +++ b/chrome/browser/ui/autofill/save_card_bubble_controller_impl_unittest.cc
@@ -0,0 +1,349 @@ +// Copyright 2014 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 "chrome/browser/ui/autofill/save_card_bubble_controller_impl.h" + +#include "base/json/json_reader.h" +#include "base/strings/utf_string_conversions.h" +#include "base/values.h" +#include "chrome/test/base/chrome_render_view_host_test_harness.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace autofill { + +typedef SaveCardBubbleController::LegalMessageLine LegalMessageLine; +typedef SaveCardBubbleController::LegalMessageLines LegalMessageLines; + +class SaveCardBubbleControllerImplTest + : public ChromeRenderViewHostTestHarness { + public: + SaveCardBubbleControllerImplTest() {} + + void SetUp() override { + ChromeRenderViewHostTestHarness::SetUp(); + SaveCardBubbleControllerImpl::CreateForWebContents(web_contents()); + } + + void SetLegalMessageExpectSuccess(const std::string& message_json) { + scoped_ptr<base::Value> value(base::JSONReader::Read(message_json)); + const base::ListValue* lines; + ASSERT_TRUE(value->GetAsList(&lines)); + EXPECT_TRUE(controller()->SetLegalMessage(*lines)); + } + + void SetLegalMessageExpectFailure(const std::string& message_json) { + scoped_ptr<base::Value> value(base::JSONReader::Read(message_json)); + const base::ListValue* lines; + ASSERT_TRUE(value->GetAsList(&lines)); + EXPECT_FALSE(controller()->SetLegalMessage(*lines)); + } + + // Returns true if lines are the same. + bool CompareLegalMessageLines(const LegalMessageLine& a, + const LegalMessageLine& b) { + if (a.text != b.text) + return false; + if (a.links.size() != b.links.size()) + return false; + for (size_t i = 0; i < a.links.size(); ++i) { + if (a.links[i].range != b.links[i].range) + return false; + if (a.links[i].url != b.links[i].url) + return false; + } + return true; + } + + // Returns true if messages are the same. + bool CompareLegalMessages(const LegalMessageLines& a, + const LegalMessageLines& b) { + if (a.size() != b.size()) + return false; + for (size_t i = 0; i < a.size(); ++i) { + if (!CompareLegalMessageLines(a[i], b[i])) + return false; + } + return true; + } + + protected: + SaveCardBubbleControllerImpl* controller() { + return SaveCardBubbleControllerImpl::FromWebContents(web_contents()); + } + + private: + DISALLOW_COPY_AND_ASSIGN(SaveCardBubbleControllerImplTest); +}; + +TEST_F(SaveCardBubbleControllerImplTest, NoParameters) { + SetLegalMessageExpectSuccess( + "[ {" + " \"template\": \"This is the entire message.\"" + "} ]"); + + LegalMessageLine expected_line; + expected_line.text = base::ASCIIToUTF16("This is the entire message."); + LegalMessageLines expected = {expected_line}; + EXPECT_TRUE( + CompareLegalMessages(expected, controller()->GetLegalMessageLines())); +} + +TEST_F(SaveCardBubbleControllerImplTest, SingleParameter) { + SetLegalMessageExpectSuccess( + "[ {" + " \"template\": \"Panda {0}.\"," + " \"template_parameter\": [ {" + " \"display_text\": \"bears are fuzzy\"," + " \"url\": \"http://www.example.com\"" + " } ]" + "} ]"); + + LegalMessageLine expected_line; + expected_line.text = base::ASCIIToUTF16("Panda bears are fuzzy."); + expected_line.links = { + {{6, 21}, GURL("http://www.example.com")}, + }; + LegalMessageLines expected = {expected_line}; + EXPECT_TRUE( + CompareLegalMessages(expected, controller()->GetLegalMessageLines())); +} + +TEST_F(SaveCardBubbleControllerImplTest, MissingUrl) { + SetLegalMessageExpectFailure( + "[ {" + " \"template\": \"Panda {0}.\"," + " \"template_parameter\": [ {" + " \"display_text\": \"bear\"" + " } ]" + "} ]"); + EXPECT_TRUE(CompareLegalMessages(LegalMessageLines(), + controller()->GetLegalMessageLines())); +} + +TEST_F(SaveCardBubbleControllerImplTest, MissingDisplayText) { + SetLegalMessageExpectFailure( + "[ {" + " \"template\": \"Panda {0}.\"," + " \"template_parameter\": [ {" + " \"url\": \"http://www.example.com\"" + " } ]" + "} ]"); + EXPECT_TRUE(CompareLegalMessages(LegalMessageLines(), + controller()->GetLegalMessageLines())); +} + +TEST_F(SaveCardBubbleControllerImplTest, EscapeCharacters) { + SetLegalMessageExpectSuccess( + "[ {" + " \"template\": \"Panda '{'{0}'}' '{1}' don't $1.\"," + " \"template_parameter\": [ {" + " \"display_text\": \"bears\"," + " \"url\": \"http://www.example.com\"" + " } ]" + "} ]"); + + LegalMessageLine expected_line; + expected_line.text = base::ASCIIToUTF16("Panda {bears} {1} don't $1."); + expected_line.links = { + {{7, 12}, GURL("http://www.example.com")}, + }; + LegalMessageLines expected = {expected_line}; + EXPECT_TRUE( + CompareLegalMessages(expected, controller()->GetLegalMessageLines())); +} + +TEST_F(SaveCardBubbleControllerImplTest, ConsecutiveDollarSigns) { + SetLegalMessageExpectSuccess( + "[ {" + " \"template\": \"$$\"" + "} ]"); + + // Consecutive dollar signs do not expand correctly (see comment in + // ReplaceTemplatePlaceholders() in save_card_bubble_controller_impl.cc). + // If this is fixed and this test starts to fail, please update the + // "Caveats" section of the SaveCardBubbleControllerImpl::SetLegalMessage() + // header file comment. + LegalMessageLine expected_line; + expected_line.text = base::ASCIIToUTF16("$$$"); + + LegalMessageLines expected = {expected_line}; + EXPECT_TRUE( + CompareLegalMessages(expected, controller()->GetLegalMessageLines())); +} + +TEST_F(SaveCardBubbleControllerImplTest, DollarAndParenthesis) { + // "${" does not expand correctly (see comment in + // ReplaceTemplatePlaceholders() in save_card_bubble_controller_impl.cc). + // If this is fixed and this test starts to fail, please update the + // "Caveats" section of the SaveCardBubbleControllerImpl::SetLegalMessage() + // header file comment. + SetLegalMessageExpectFailure( + "[ {" + " \"template\": \"${0}\"," + " \"template_parameter\": [ {" + " \"display_text\": \"bears\"," + " \"url\": \"http://www.example.com\"" + " } ]" + "} ]"); +} + +TEST_F(SaveCardBubbleControllerImplTest, MultipleParameters) { + SetLegalMessageExpectSuccess( + "[ {" + " \"template\": \"Panda {0} like {2} eat {1}.\"," + " \"template_parameter\": [ {" + " \"display_text\": \"bears\"," + " \"url\": \"http://www.example.com/0\"" + " }, {" + " \"display_text\": \"bamboo\"," + " \"url\": \"http://www.example.com/1\"" + " }, {" + " \"display_text\": \"to\"," + " \"url\": \"http://www.example.com/2\"" + " } ]" + "} ]"); + + LegalMessageLine expected_line; + expected_line.text = base::ASCIIToUTF16("Panda bears like to eat bamboo."); + expected_line.links = { + {{6, 11}, GURL("http://www.example.com/0")}, + {{24, 30}, GURL("http://www.example.com/1")}, + {{17, 19}, GURL("http://www.example.com/2")}, + }; + LegalMessageLines expected = {expected_line}; + EXPECT_TRUE( + CompareLegalMessages(expected, controller()->GetLegalMessageLines())); +} + +TEST_F(SaveCardBubbleControllerImplTest, MultipleLineElements) { + SetLegalMessageExpectSuccess( + "[ {" + " \"template\": \"Panda {0}\"," + " \"template_parameter\": [ {" + " \"display_text\": \"bears\"," + " \"url\": \"http://www.example.com/line_0_param_0\"" + " } ]" + "}, {" + " \"template\": \"like {1} eat {0}.\"," + " \"template_parameter\": [ {" + " \"display_text\": \"bamboo\"," + " \"url\": \"http://www.example.com/line_1_param_0\"" + " }, {" + " \"display_text\": \"to\"," + " \"url\": \"http://www.example.com/line_1_param_1\"" + " } ]" + "}, {" + " \"template\": \"The {0}.\"," + " \"template_parameter\": [ {" + " \"display_text\": \"end\"," + " \"url\": \"http://www.example.com/line_2_param_0\"" + " } ]" + "} ]"); + + // Line 0. + LegalMessageLine expected_line_0; + expected_line_0.text = base::ASCIIToUTF16("Panda bears"); + expected_line_0.links = { + {{6, 11}, GURL("http://www.example.com/line_0_param_0")}, + }; + + // Line 1. + LegalMessageLine expected_line_1; + expected_line_1.text = base::ASCIIToUTF16("like to eat bamboo."); + expected_line_1.links = { + {{12, 18}, GURL("http://www.example.com/line_1_param_0")}, + {{5, 7}, GURL("http://www.example.com/line_1_param_1")}, + }; + + // Line 2. + LegalMessageLine expected_line_2; + expected_line_2.text = base::ASCIIToUTF16("The end."); + expected_line_2.links = { + {{4, 7}, GURL("http://www.example.com/line_2_param_0")}, + }; + + LegalMessageLines expected = {expected_line_0, expected_line_1, + expected_line_2}; + EXPECT_TRUE( + CompareLegalMessages(expected, controller()->GetLegalMessageLines())); +} + +TEST_F(SaveCardBubbleControllerImplTest, EmbeddedNewlines) { + SetLegalMessageExpectSuccess( + "[ {" + " \"template\": \"Panda {0}\nlike {2} eat {1}.\nThe {3}.\"," + " \"template_parameter\": [ {" + " \"display_text\": \"bears\"," + " \"url\": \"http://www.example.com/0\"" + " }, {" + " \"display_text\": \"bamboo\"," + " \"url\": \"http://www.example.com/1\"" + " }, {" + " \"display_text\": \"to\"," + " \"url\": \"http://www.example.com/2\"" + " }, {" + " \"display_text\": \"end\"," + " \"url\": \"http://www.example.com/3\"" + " } ]" + "} ]"); + + LegalMessageLine expected_line; + expected_line.text = + base::ASCIIToUTF16("Panda bears\nlike to eat bamboo.\nThe end."); + expected_line.links = { + {{6, 11}, GURL("http://www.example.com/0")}, + {{24, 30}, GURL("http://www.example.com/1")}, + {{17, 19}, GURL("http://www.example.com/2")}, + {{36, 39}, GURL("http://www.example.com/3")}, + }; + LegalMessageLines expected = {expected_line}; + EXPECT_TRUE( + CompareLegalMessages(expected, controller()->GetLegalMessageLines())); +} + +TEST_F(SaveCardBubbleControllerImplTest, MaximumPlaceholders) { + SetLegalMessageExpectSuccess( + "[ {" + " \"template\": \"a{0} b{1} c{2} d{3} e{4} f{5} g{6}\"," + " \"template_parameter\": [ {" + " \"display_text\": \"A\"," + " \"url\": \"http://www.example.com/0\"" + " }, {" + " \"display_text\": \"B\"," + " \"url\": \"http://www.example.com/1\"" + " }, {" + " \"display_text\": \"C\"," + " \"url\": \"http://www.example.com/2\"" + " }, {" + " \"display_text\": \"D\"," + " \"url\": \"http://www.example.com/3\"" + " }, {" + " \"display_text\": \"E\"," + " \"url\": \"http://www.example.com/4\"" + " }, {" + " \"display_text\": \"F\"," + " \"url\": \"http://www.example.com/5\"" + " }, {" + " \"display_text\": \"G\"," + " \"url\": \"http://www.example.com/6\"" + " } ]" + "} ]"); + + LegalMessageLine expected_line; + expected_line.text = base::ASCIIToUTF16("aA bB cC dD eE fF gG"); + expected_line.links = { + {{1, 2}, GURL("http://www.example.com/0")}, + {{4, 5}, GURL("http://www.example.com/1")}, + {{7, 8}, GURL("http://www.example.com/2")}, + {{10, 11}, GURL("http://www.example.com/3")}, + {{13, 14}, GURL("http://www.example.com/4")}, + {{16, 17}, GURL("http://www.example.com/5")}, + {{19, 20}, GURL("http://www.example.com/6")}, + }; + LegalMessageLines expected = {expected_line}; + EXPECT_TRUE( + CompareLegalMessages(expected, controller()->GetLegalMessageLines())); +} + +} // namespace autofill
diff --git a/chrome/browser/ui/cocoa/extensions/extension_message_bubble_bridge.mm b/chrome/browser/ui/cocoa/extensions/extension_message_bubble_bridge.mm index 86f1361..28b77e5e 100644 --- a/chrome/browser/ui/cocoa/extensions/extension_message_bubble_bridge.mm +++ b/chrome/browser/ui/cocoa/extensions/extension_message_bubble_bridge.mm
@@ -48,9 +48,12 @@ void ExtensionMessageBubbleBridge::OnBubbleClosed(CloseAction action) { switch(action) { - case CLOSE_DISMISS: - controller_->OnBubbleDismiss(); + case CLOSE_DISMISS_USER_ACTION: + case CLOSE_DISMISS_DEACTIVATION: { + bool close_by_deactivate = action == CLOSE_DISMISS_DEACTIVATION; + controller_->OnBubbleDismiss(close_by_deactivate); break; + } case CLOSE_EXECUTE: controller_->OnBubbleAction(); break;
diff --git a/chrome/browser/ui/cocoa/extensions/toolbar_actions_bar_bubble_mac.mm b/chrome/browser/ui/cocoa/extensions/toolbar_actions_bar_bubble_mac.mm index 5e01460..ccba1d80 100644 --- a/chrome/browser/ui/cocoa/extensions/toolbar_actions_bar_bubble_mac.mm +++ b/chrome/browser/ui/cocoa/extensions/toolbar_actions_bar_bubble_mac.mm
@@ -106,7 +106,7 @@ - (void)windowWillClose:(NSNotification*)notification { if (!acknowledged_) { delegate_->OnBubbleClosed( - ToolbarActionsBarBubbleDelegate::CLOSE_DISMISS); + ToolbarActionsBarBubbleDelegate::CLOSE_DISMISS_DEACTIVATION); acknowledged_ = YES; } [super windowWillClose:notification]; @@ -327,7 +327,7 @@ if (learnMoreButton_ && sender == learnMoreButton_) { action = ToolbarActionsBarBubbleDelegate::CLOSE_LEARN_MORE; } else if (dismissButton_ && sender == dismissButton_) { - action = ToolbarActionsBarBubbleDelegate::CLOSE_DISMISS; + action = ToolbarActionsBarBubbleDelegate::CLOSE_DISMISS_USER_ACTION; } else { DCHECK_EQ(sender, actionButton_); action = ToolbarActionsBarBubbleDelegate::CLOSE_EXECUTE;
diff --git a/chrome/browser/ui/cocoa/extensions/toolbar_actions_bar_bubble_mac_unittest.mm b/chrome/browser/ui/cocoa/extensions/toolbar_actions_bar_bubble_mac_unittest.mm index 6c266f4..4f9a443 100644 --- a/chrome/browser/ui/cocoa/extensions/toolbar_actions_bar_bubble_mac_unittest.mm +++ b/chrome/browser/ui/cocoa/extensions/toolbar_actions_bar_bubble_mac_unittest.mm
@@ -117,12 +117,15 @@ case ToolbarActionsBarBubbleDelegate::CLOSE_EXECUTE: button = [bubble actionButton]; break; - case ToolbarActionsBarBubbleDelegate::CLOSE_DISMISS: + case ToolbarActionsBarBubbleDelegate::CLOSE_DISMISS_USER_ACTION: button = [bubble dismissButton]; break; case ToolbarActionsBarBubbleDelegate::CLOSE_LEARN_MORE: button = [bubble learnMoreButton]; break; + case ToolbarActionsBarBubbleDelegate::CLOSE_DISMISS_DEACTIVATION: + NOTREACHED(); // Deactivation is tested below. + break; } ASSERT_TRUE(button); @@ -144,7 +147,7 @@ TEST_F(ToolbarActionsBarBubbleMacTest, CloseActionAndDismiss) { // Test all the possible actions. TestBubbleButton(ToolbarActionsBarBubbleDelegate::CLOSE_EXECUTE); - TestBubbleButton(ToolbarActionsBarBubbleDelegate::CLOSE_DISMISS); + TestBubbleButton(ToolbarActionsBarBubbleDelegate::CLOSE_DISMISS_USER_ACTION); TestBubbleButton(ToolbarActionsBarBubbleDelegate::CLOSE_LEARN_MORE); { @@ -160,7 +163,7 @@ [bubble close]; chrome::testing::NSRunLoopRunAllPending(); ASSERT_TRUE(delegate.close_action()); - EXPECT_EQ(ToolbarActionsBarBubbleDelegate::CLOSE_DISMISS, + EXPECT_EQ(ToolbarActionsBarBubbleDelegate::CLOSE_DISMISS_DEACTIVATION, *delegate.close_action()); EXPECT_TRUE([windowObserver windowIsClosing]); }
diff --git a/chrome/browser/ui/libgtk2ui/BUILD.gn b/chrome/browser/ui/libgtk2ui/BUILD.gn index 9be48243..9b1c927 100644 --- a/chrome/browser/ui/libgtk2ui/BUILD.gn +++ b/chrome/browser/ui/libgtk2ui/BUILD.gn
@@ -92,12 +92,12 @@ deps = [ "//base", - "//base/third_party/dynamic_annotations", "//base:i18n", - "//chrome/app/theme:theme_resources", + "//base/third_party/dynamic_annotations", "//chrome:extra_resources", "//chrome:resources", "//chrome:strings", + "//chrome/app/theme:theme_resources", "//components/resources", "//content/public/browser", "//mojo/environment:chromium",
diff --git a/chrome/browser/ui/libgtk2ui/select_file_dialog_impl_gtk2.cc b/chrome/browser/ui/libgtk2ui/select_file_dialog_impl_gtk2.cc index f3e6249b..377bbd2a 100644 --- a/chrome/browser/ui/libgtk2ui/select_file_dialog_impl_gtk2.cc +++ b/chrome/browser/ui/libgtk2ui/select_file_dialog_impl_gtk2.cc
@@ -4,6 +4,7 @@ #include "chrome/browser/ui/libgtk2ui/select_file_dialog_impl_gtk2.h" +#include <gdk/gdkx.h> #include <gtk/gtk.h> #include <sys/stat.h> #include <sys/types.h> @@ -31,6 +32,7 @@ #include "ui/base/l10n/l10n_util.h" #include "ui/shell_dialogs/select_file_dialog.h" #include "ui/strings/grit/ui_strings.h" +#include "ui/views/widget/desktop_aura/desktop_window_tree_host_x11.h" #include "ui/views/widget/desktop_aura/x11_desktop_handler.h" namespace { @@ -163,9 +165,11 @@ params_map_[dialog] = params; - // TODO(erg): Figure out how to fake GTK window-to-parent modality without - // having the parent be a real GtkWindow. - gtk_window_set_modal(GTK_WINDOW(dialog), TRUE); + // Disable input events handling in the host window to make this dialog modal. + views::DesktopWindowTreeHostX11* host = + views::DesktopWindowTreeHostX11::GetHostForXID( + owning_window->GetHost()->GetAcceleratedWidget()); + host->DisableEventListening(GDK_WINDOW_XID(gtk_widget_get_window(dialog))); gtk_widget_show_all(dialog); @@ -424,6 +428,12 @@ aura::Window* parent = GetAuraTransientParent(dialog); if (!parent) return; + + views::DesktopWindowTreeHostX11* host = + views::DesktopWindowTreeHostX11::GetHostForXID( + parent->GetHost()->GetAcceleratedWidget()); + host->EnableEventListening(); + std::set<aura::Window*>::iterator iter = parents_.find(parent); if (iter != parents_.end()) { (*iter)->RemoveObserver(this);
diff --git a/chrome/browser/ui/libgtk2ui/select_file_dialog_interactive_uitest.cc b/chrome/browser/ui/libgtk2ui/select_file_dialog_interactive_uitest.cc index 657731f..8078d4f 100644 --- a/chrome/browser/ui/libgtk2ui/select_file_dialog_interactive_uitest.cc +++ b/chrome/browser/ui/libgtk2ui/select_file_dialog_interactive_uitest.cc
@@ -100,3 +100,47 @@ }; } // namespace libgtk2ui + +// Test that the file-picker is modal. +IN_PROC_BROWSER_TEST_F(BrowserSelectFileDialogTest, ModalTest) { + // Bring the native window to the foreground. Returns true on success. + ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser())); + ASSERT_TRUE(browser()->window()->IsActive()); + + // Leaks in GtkFileChooserDialog. http://crbug.com/537468 + ANNOTATE_SCOPED_MEMORY_LEAK; + libgtk2ui::FilePicker file_picker(browser()->window()); + + gfx::NativeWindow window = browser()->window()->GetNativeWindow(); + views::Widget* widget = views::Widget::GetWidgetForNativeWindow(window); + ASSERT_NE(nullptr, widget); + + // Run a nested loop until the browser window becomes inactive + // so that the file-picker can be active. + WidgetActivationWaiter waiter_inactive(widget, false); + waiter_inactive.Wait(); + EXPECT_FALSE(browser()->window()->IsActive()); + + ui_test_utils::ClickOnView(browser(), VIEW_ID_TAB_CONTAINER); + // The window should not get focus due to modal dialog. + EXPECT_FALSE(browser()->window()->IsActive()); + + ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser())); + EXPECT_FALSE(browser()->window()->IsActive()); + + ASSERT_TRUE(ui_test_utils::ShowAndFocusNativeWindow(window)); + EXPECT_FALSE(browser()->window()->IsActive()); + + ASSERT_TRUE(ui_test_utils::SendKeyPressSync( + browser(), ui::VKEY_TAB, false, false, true, false)); + EXPECT_FALSE(browser()->window()->IsActive()); + + file_picker.Close(); + + // Run a nested loop until the browser window becomes active. + WidgetActivationWaiter wait_active(widget, true); + wait_active.Wait(); + + ui_test_utils::ClickOnView(browser(), VIEW_ID_TAB_CONTAINER); + EXPECT_TRUE(browser()->window()->IsActive()); +}
diff --git a/chrome/browser/ui/toolbar/toolbar_actions_bar_bubble_delegate.h b/chrome/browser/ui/toolbar/toolbar_actions_bar_bubble_delegate.h index 2fb9bc89..508371ea 100644 --- a/chrome/browser/ui/toolbar/toolbar_actions_bar_bubble_delegate.h +++ b/chrome/browser/ui/toolbar/toolbar_actions_bar_bubble_delegate.h
@@ -13,7 +13,8 @@ enum CloseAction { CLOSE_LEARN_MORE, CLOSE_EXECUTE, - CLOSE_DISMISS + CLOSE_DISMISS_USER_ACTION, + CLOSE_DISMISS_DEACTIVATION, }; virtual ~ToolbarActionsBarBubbleDelegate() {}
diff --git a/chrome/browser/ui/toolbar/toolbar_actions_bar_unittest.cc b/chrome/browser/ui/toolbar/toolbar_actions_bar_unittest.cc index 7e793378..b0ce77b 100644 --- a/chrome/browser/ui/toolbar/toolbar_actions_bar_unittest.cc +++ b/chrome/browser/ui/toolbar/toolbar_actions_bar_unittest.cc
@@ -424,7 +424,7 @@ new ExtensionToolbarIconSurfacingBubbleDelegate(profile())); bubble_delegate->OnBubbleShown(); bubble_delegate->OnBubbleClosed( - ToolbarActionsBarBubbleDelegate::CLOSE_DISMISS); + ToolbarActionsBarBubbleDelegate::CLOSE_DISMISS_USER_ACTION); EXPECT_FALSE( ExtensionToolbarIconSurfacingBubbleDelegate::ShouldShowForProfile( profile()));
diff --git a/chrome/browser/ui/toolbar/toolbar_actions_model_unittest.cc b/chrome/browser/ui/toolbar/toolbar_actions_model_unittest.cc index 787e5da..c0e7d26 100644 --- a/chrome/browser/ui/toolbar/toolbar_actions_model_unittest.cc +++ b/chrome/browser/ui/toolbar/toolbar_actions_model_unittest.cc
@@ -1229,7 +1229,8 @@ scoped_ptr<ToolbarActionsBarBubbleDelegate> bubble( new ExtensionToolbarIconSurfacingBubbleDelegate(profile())); - bubble->OnBubbleClosed(ToolbarActionsBarBubbleDelegate::CLOSE_DISMISS); + bubble->OnBubbleClosed( + ToolbarActionsBarBubbleDelegate::CLOSE_DISMISS_USER_ACTION); EXPECT_FALSE(toolbar_model->is_highlighting()); EXPECT_EQ(ToolbarActionsModel::HIGHLIGHT_NONE,
diff --git a/chrome/browser/ui/views/app_list/win/app_list_service_win.cc b/chrome/browser/ui/views/app_list/win/app_list_service_win.cc index dd9b7e59..6692e3f 100644 --- a/chrome/browser/ui/views/app_list/win/app_list_service_win.cc +++ b/chrome/browser/ui/views/app_list/win/app_list_service_win.cc
@@ -306,7 +306,7 @@ shortcut_locations.on_desktop = true; shortcut_locations.in_quick_launch_bar = true; shortcut_locations.applications_menu_location = - web_app::APP_MENU_LOCATION_SUBDIR_CHROME; + web_app::APP_MENU_LOCATION_SUBDIR_CHROME_DEPRECATED; base::FilePath user_data_dir( g_browser_process->profile_manager()->user_data_dir());
diff --git a/chrome/browser/ui/views/autofill/autofill_dialog_views.cc b/chrome/browser/ui/views/autofill/autofill_dialog_views.cc index 330fcf7..5ccaa1a 100644 --- a/chrome/browser/ui/views/autofill/autofill_dialog_views.cc +++ b/chrome/browser/ui/views/autofill/autofill_dialog_views.cc
@@ -311,7 +311,8 @@ } // views::StyledLabelListener implementation. - void StyledLabelLinkClicked(const gfx::Range& range, + void StyledLabelLinkClicked(views::StyledLabel* label, + const gfx::Range& range, int event_flags) override { delegate_->LinkClicked(data_.link_url()); }
diff --git a/chrome/browser/ui/views/autofill/password_generation_popup_view_views.cc b/chrome/browser/ui/views/autofill/password_generation_popup_view_views.cc index 33e4802..5f73a60 100644 --- a/chrome/browser/ui/views/autofill/password_generation_popup_view_views.cc +++ b/chrome/browser/ui/views/autofill/password_generation_popup_view_views.cc
@@ -251,7 +251,9 @@ } void PasswordGenerationPopupViewViews::StyledLabelLinkClicked( - const gfx::Range& range, int event_flags) { + views::StyledLabel* label, + const gfx::Range& range, + int event_flags) { controller_->OnSavedPasswordsLinkClicked(); }
diff --git a/chrome/browser/ui/views/autofill/password_generation_popup_view_views.h b/chrome/browser/ui/views/autofill/password_generation_popup_view_views.h index 54e3e1f..e85cba90 100644 --- a/chrome/browser/ui/views/autofill/password_generation_popup_view_views.h +++ b/chrome/browser/ui/views/autofill/password_generation_popup_view_views.h
@@ -50,7 +50,8 @@ void GetAccessibleState(ui::AXViewState* state) override; // views::StyledLabelListener implementation - void StyledLabelLinkClicked(const gfx::Range& range, + void StyledLabelLinkClicked(views::StyledLabel* label, + const gfx::Range& range, int event_flags) override; // Sub views. Used to change bounds when updating. Weak references.
diff --git a/chrome/browser/ui/views/autofill/save_card_bubble_views.cc b/chrome/browser/ui/views/autofill/save_card_bubble_views.cc index e48406e..c14e4d6e 100644 --- a/chrome/browser/ui/views/autofill/save_card_bubble_views.cc +++ b/chrome/browser/ui/views/autofill/save_card_bubble_views.cc
@@ -5,6 +5,7 @@ #include "chrome/browser/ui/views/autofill/save_card_bubble_views.h" #include "base/strings/utf_string_conversions.h" +#include "chrome/browser/ui/autofill/autofill_dialog_types.h" #include "chrome/browser/ui/autofill/save_card_bubble_controller.h" #include "grit/components_strings.h" #include "ui/base/l10n/l10n_util.h" @@ -13,11 +14,15 @@ #include "ui/views/controls/button/label_button.h" #include "ui/views/controls/label.h" #include "ui/views/controls/link.h" +#include "ui/views/controls/styled_label.h" +#include "ui/views/layout/box_layout.h" #include "ui/views/layout/grid_layout.h" #include "ui/views/layout/layout_constants.h" using views::GridLayout; +namespace autofill { + namespace { // Fixed width of the bubble. @@ -32,9 +37,20 @@ const bool kIsOkButtonOnLeftSide = false; #endif -} // namespace +scoped_ptr<views::StyledLabel> CreateLegalMessageLineLabel( + const SaveCardBubbleController::LegalMessageLine& line, + views::StyledLabelListener* listener) { + scoped_ptr<views::StyledLabel> label( + new views::StyledLabel(line.text, listener)); + for (const SaveCardBubbleController::LegalMessageLine::Link& link : + line.links) { + label->AddStyleRange(link.range, + views::StyledLabel::RangeStyleInfo::CreateForLink()); + } + return label; +} -namespace autofill { +} // namespace SaveCardBubbleViews::SaveCardBubbleViews(views::View* anchor_view, content::WebContents* web_contents, @@ -92,15 +108,40 @@ controller_->OnLearnMoreClicked(); } -void SaveCardBubbleViews::Init() { +void SaveCardBubbleViews::StyledLabelLinkClicked(views::StyledLabel* label, + const gfx::Range& range, + int event_flags) { + // Index of |label| within its parent's view hierarchy is the same as the + // legal message line index. DCHECK this assumption to guard against future + // layout changes. + DCHECK_EQ(static_cast<size_t>(label->parent()->child_count()), + controller_->GetLegalMessageLines().size()); + + const auto& links = + controller_->GetLegalMessageLines()[label->parent()->GetIndexOf(label)] + .links; + for (const SaveCardBubbleController::LegalMessageLine::Link& link : links) { + if (link.range == range) { + controller_->OnLegalMessageLinkClicked(link.url); + return; + } + } + + // |range| was not found. + NOTREACHED(); +} + +// Create view containing everything except for the footnote. +scoped_ptr<views::View> SaveCardBubbleViews::CreateMainContentView() { enum { COLUMN_SET_ID_SPACER, COLUMN_SET_ID_EXPLANATION, COLUMN_SET_ID_BUTTONS, }; - GridLayout* layout = new GridLayout(this); - SetLayoutManager(layout); + scoped_ptr<View> view(new View()); + GridLayout* layout = new GridLayout(view.get()); + view->SetLayoutManager(layout); // Add a column set with padding to establish a minimum width. views::ColumnSet* cs = layout->AddColumnSet(COLUMN_SET_ID_SPACER); @@ -144,6 +185,7 @@ // Create "learn more" link and add it to layout. learn_more_link_ = new views::Link(l10n_util::GetStringUTF16(IDS_LEARN_MORE)); + learn_more_link_->SetUnderline(false); learn_more_link_->set_listener(this); layout->StartRow(0, COLUMN_SET_ID_BUTTONS); layout->AddView(learn_more_link_); @@ -167,8 +209,38 @@ } layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing); + return view; +} + +// Create view containing the legal message text. +scoped_ptr<views::View> SaveCardBubbleViews::CreateFootnoteView() { + // Use BoxLayout to provide insets around the label. + scoped_ptr<View> view(new View()); + view->SetLayoutManager( + new views::BoxLayout(views::BoxLayout::kVertical, + GetBubbleFrameView()->GetTitleInsets().left(), + views::kRelatedControlVerticalSpacing, 0)); + view->SetBorder( + views::Border::CreateSolidSidedBorder(1, 0, 0, 0, kSubtleBorderColor)); + view->set_background( + views::Background::CreateSolidBackground(kLightShadingColor)); + + // Add a StyledLabel for each line of the legal message. + for (const SaveCardBubbleController::LegalMessageLine& line : + controller_->GetLegalMessageLines()) { + view->AddChildView(CreateLegalMessageLineLabel(line, this).release()); + } + + return view; +} + +void SaveCardBubbleViews::Init() { + SetLayoutManager(new views::BoxLayout(views::BoxLayout::kVertical, 0, 0, 0)); + AddChildView(CreateMainContentView().release()); + if (!controller_->GetLegalMessageLines().empty()) + AddChildView(CreateFootnoteView().release()); + set_margins(gfx::Insets(1, 0, 1, 0)); - Layout(); } } // namespace autofill
diff --git a/chrome/browser/ui/views/autofill/save_card_bubble_views.h b/chrome/browser/ui/views/autofill/save_card_bubble_views.h index 6f26339..62d69733 100644 --- a/chrome/browser/ui/views/autofill/save_card_bubble_views.h +++ b/chrome/browser/ui/views/autofill/save_card_bubble_views.h
@@ -6,10 +6,12 @@ #define CHROME_BROWSER_UI_VIEWS_AUTOFILL_SAVE_CARD_BUBBLE_VIEWS_H_ #include "base/macros.h" +#include "chrome/browser/ui/autofill/save_card_bubble_controller.h" #include "chrome/browser/ui/autofill/save_card_bubble_view.h" #include "chrome/browser/ui/views/location_bar/location_bar_bubble_delegate_view.h" #include "ui/views/controls/button/button.h" #include "ui/views/controls/link_listener.h" +#include "ui/views/controls/styled_label_listener.h" namespace content { class WebContents; @@ -18,19 +20,19 @@ namespace views { class LabelButton; class Link; +class StyledLabel; } namespace autofill { -class SaveCardBubbleController; - // This class displays the "Save credit card?" bubble that is shown when the // user submits a form with a credit card number that Autofill has not // previously saved. class SaveCardBubbleViews : public SaveCardBubbleView, public LocationBarBubbleDelegateView, public views::ButtonListener, - public views::LinkListener { + public views::LinkListener, + public views::StyledLabelListener { public: // Bubble will be anchored to |anchor_view|. SaveCardBubbleViews(views::View* anchor_view, @@ -54,9 +56,17 @@ // views::LinkListener void LinkClicked(views::Link* source, int event_flags) override; + // views::StyledLabelListener + void StyledLabelLinkClicked(views::StyledLabel* label, + const gfx::Range& range, + int event_flags) override; + private: ~SaveCardBubbleViews() override; + scoped_ptr<views::View> CreateMainContentView(); + scoped_ptr<views::View> CreateFootnoteView(); + // views::BubbleDelegateView void Init() override;
diff --git a/chrome/browser/ui/views/bookmarks/bookmark_sync_promo_view.cc b/chrome/browser/ui/views/bookmarks/bookmark_sync_promo_view.cc index a4a37a0e..d0fff27 100644 --- a/chrome/browser/ui/views/bookmarks/bookmark_sync_promo_view.cc +++ b/chrome/browser/ui/views/bookmarks/bookmark_sync_promo_view.cc
@@ -71,7 +71,8 @@ AddChildView(promo_label); } -void BookmarkSyncPromoView::StyledLabelLinkClicked(const gfx::Range& range, +void BookmarkSyncPromoView::StyledLabelLinkClicked(views::StyledLabel* label, + const gfx::Range& range, int event_flags) { delegate_->OnSignInLinkClicked(); }
diff --git a/chrome/browser/ui/views/bookmarks/bookmark_sync_promo_view.h b/chrome/browser/ui/views/bookmarks/bookmark_sync_promo_view.h index 63efab1..75bcb56 100644 --- a/chrome/browser/ui/views/bookmarks/bookmark_sync_promo_view.h +++ b/chrome/browser/ui/views/bookmarks/bookmark_sync_promo_view.h
@@ -21,7 +21,8 @@ private: // views::StyledLabelListener: - void StyledLabelLinkClicked(const gfx::Range& range, + void StyledLabelLinkClicked(views::StyledLabel* label, + const gfx::Range& range, int event_flags) override; // views::View:
diff --git a/chrome/browser/ui/views/bookmarks/bookmark_sync_promo_view_unittest.cc b/chrome/browser/ui/views/bookmarks/bookmark_sync_promo_view_unittest.cc index 4d08179..f7f21615 100644 --- a/chrome/browser/ui/views/bookmarks/bookmark_sync_promo_view_unittest.cc +++ b/chrome/browser/ui/views/bookmarks/bookmark_sync_promo_view_unittest.cc
@@ -7,10 +7,12 @@ #include "base/basictypes.h" #include "base/compiler_specific.h" #include "base/memory/scoped_ptr.h" +#include "base/strings/utf_string_conversions.h" #include "chrome/browser/ui/bookmarks/bookmark_bubble_delegate.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/events/event_constants.h" #include "ui/gfx/range/range.h" +#include "ui/views/controls/styled_label.h" class BookmarkSyncPromoViewTest : public BookmarkBubbleDelegate, public testing::Test { @@ -33,8 +35,9 @@ sync_promo.reset(new BookmarkSyncPromoView(this)); // Simulate clicking the "Sign in" link. + views::StyledLabel styled_label(base::ASCIIToUTF16("test"), nullptr); views::StyledLabelListener* listener = sync_promo.get(); - listener->StyledLabelLinkClicked(gfx::Range(), ui::EF_NONE); + listener->StyledLabelLinkClicked(&styled_label, gfx::Range(), ui::EF_NONE); EXPECT_EQ(1, sign_in_clicked_count_); }
diff --git a/chrome/browser/ui/views/desktop_media_picker_views.cc b/chrome/browser/ui/views/desktop_media_picker_views.cc index 7c438b2..f1741ed 100644 --- a/chrome/browser/ui/views/desktop_media_picker_views.cc +++ b/chrome/browser/ui/views/desktop_media_picker_views.cc
@@ -54,6 +54,11 @@ gfx::AcceleratedWidget accelerated_widget) { #if defined(OS_WIN) return reinterpret_cast<DesktopMediaID::Id>(accelerated_widget); +#elif defined(OS_ANDROID) + // TODO(bshe): We may need to revisit this for Android platform. See + // crbug.com/557424. + NOTIMPLEMENTED(); + return reinterpret_cast<DesktopMediaID::Id>(accelerated_widget); #else return static_cast<DesktopMediaID::Id>(accelerated_widget); #endif
diff --git a/chrome/browser/ui/views/download/download_feedback_dialog_view.cc b/chrome/browser/ui/views/download/download_feedback_dialog_view.cc index 82790e15..1d2f0b328 100644 --- a/chrome/browser/ui/views/download/download_feedback_dialog_view.cc +++ b/chrome/browser/ui/views/download/download_feedback_dialog_view.cc
@@ -14,6 +14,7 @@ #include "chrome/grit/generated_resources.h" #include "components/constrained_window/constrained_window_views.h" #include "content/public/browser/page_navigator.h" +#include "grit/components_strings.h" #include "ui/base/l10n/l10n_util.h" #include "ui/views/controls/link.h" #include "ui/views/controls/message_box_view.h"
diff --git a/chrome/browser/ui/views/extensions/extension_message_bubble_view.cc b/chrome/browser/ui/views/extensions/extension_message_bubble_view.cc index c30ba3b..fc528bc 100644 --- a/chrome/browser/ui/views/extensions/extension_message_bubble_view.cc +++ b/chrome/browser/ui/views/extensions/extension_message_bubble_view.cc
@@ -77,8 +77,10 @@ void ExtensionMessageBubbleView::OnWidgetDestroying(views::Widget* widget) { // To catch Esc, we monitor destroy message. Unless the link has been clicked, // we assume Dismiss was the action taken. - if (!link_clicked_ && !action_taken_) - controller_->OnBubbleDismiss(); + if (!link_clicked_ && !action_taken_) { + bool closed_on_deactivation = close_reason() == CloseReason::DEACTIVATION; + controller_->OnBubbleDismiss(closed_on_deactivation); + } } void ExtensionMessageBubbleView::set_bubble_appearance_wait_time_for_testing(
diff --git a/chrome/browser/ui/views/extensions/extension_toolbar_icon_surfacing_bubble_views.cc b/chrome/browser/ui/views/extensions/extension_toolbar_icon_surfacing_bubble_views.cc index c0ddf62e..24fefe36 100644 --- a/chrome/browser/ui/views/extensions/extension_toolbar_icon_surfacing_bubble_views.cc +++ b/chrome/browser/ui/views/extensions/extension_toolbar_icon_surfacing_bubble_views.cc
@@ -78,7 +78,11 @@ views::Widget* widget) { BubbleDelegateView::OnWidgetDestroying(widget); if (!acknowledged_) { - delegate_->OnBubbleClosed(ToolbarActionsBarBubbleDelegate::CLOSE_DISMISS); + ToolbarActionsBarBubbleDelegate::CloseAction close_action = + close_reason() == CloseReason::DEACTIVATION + ? ToolbarActionsBarBubbleDelegate::CLOSE_DISMISS_DEACTIVATION + : ToolbarActionsBarBubbleDelegate::CLOSE_DISMISS_USER_ACTION; + delegate_->OnBubbleClosed(close_action); acknowledged_ = true; } }
diff --git a/chrome/browser/ui/views/extensions/extension_toolbar_icon_surfacing_bubble_views_unittest.cc b/chrome/browser/ui/views/extensions/extension_toolbar_icon_surfacing_bubble_views_unittest.cc index ab7cbd2..ac8a6da6 100644 --- a/chrome/browser/ui/views/extensions/extension_toolbar_icon_surfacing_bubble_views_unittest.cc +++ b/chrome/browser/ui/views/extensions/extension_toolbar_icon_surfacing_bubble_views_unittest.cc
@@ -81,11 +81,12 @@ views::test::TestWidgetObserver bubble_observer(bubble_widget); EXPECT_FALSE(delegate.close_action()); - // Close the bubble. The delegate should be told it was dismissed. - bubble_widget->Close(); + // Close the bubble by activating another widget. The delegate should be + // told it was dismissed. + anchor_widget->Activate(); base::RunLoop().RunUntilIdle(); ASSERT_TRUE(delegate.close_action()); - EXPECT_EQ(ToolbarActionsBarBubbleDelegate::CLOSE_DISMISS, + EXPECT_EQ(ToolbarActionsBarBubbleDelegate::CLOSE_DISMISS_DEACTIVATION, *delegate.close_action()); EXPECT_TRUE(bubble_observer.widget_closed()); }
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view_factory_android.cc b/chrome/browser/ui/views/frame/browser_non_client_frame_view_factory_android.cc new file mode 100644 index 0000000..851aad6 --- /dev/null +++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view_factory_android.cc
@@ -0,0 +1,18 @@ +// Copyright 2015 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 "chrome/browser/ui/views/frame/browser_non_client_frame_view.h" + +#include "chrome/browser/ui/views/frame/browser_view.h" +#include "chrome/browser/ui/views/frame/opaque_browser_frame_view.h" + +namespace chrome { + +BrowserNonClientFrameView* CreateBrowserNonClientFrameView( + BrowserFrame* frame, + BrowserView* browser_view) { + return new OpaqueBrowserFrameView(frame, browser_view); +} + +} // namespace chrome
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view_factory_aura.cc b/chrome/browser/ui/views/frame/browser_non_client_frame_view_factory_ash.cc similarity index 80% rename from chrome/browser/ui/views/frame/browser_non_client_frame_view_factory_aura.cc rename to chrome/browser/ui/views/frame/browser_non_client_frame_view_factory_ash.cc index 5263ea9..c7ae34f0 100644 --- a/chrome/browser/ui/views/frame/browser_non_client_frame_view_factory_aura.cc +++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view_factory_ash.cc
@@ -1,11 +1,11 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Copyright 2015 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 "chrome/browser/ui/views/frame/browser_view.h" - #include "chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.h" +#include "chrome/browser/ui/views/frame/browser_view.h" + #if !defined(OS_CHROMEOS) #include "chrome/browser/ui/views/frame/opaque_browser_frame_view.h" #endif @@ -17,10 +17,11 @@ namespace chrome { BrowserNonClientFrameView* CreateBrowserNonClientFrameView( - BrowserFrame* frame, BrowserView* browser_view) { + BrowserFrame* frame, + BrowserView* browser_view) { #if !defined(OS_CHROMEOS) - if (browser_view->browser()-> - host_desktop_type() == chrome::HOST_DESKTOP_TYPE_NATIVE) { + if (browser_view->browser()->host_desktop_type() == + chrome::HOST_DESKTOP_TYPE_NATIVE) { #if defined(OS_WIN) if (frame->ShouldUseNativeFrame()) return new GlassBrowserFrameView(frame, browser_view);
diff --git a/chrome/browser/ui/views/frame/immersive_mode_controller_factory_android.cc b/chrome/browser/ui/views/frame/immersive_mode_controller_factory_android.cc new file mode 100644 index 0000000..0276b96 --- /dev/null +++ b/chrome/browser/ui/views/frame/immersive_mode_controller_factory_android.cc
@@ -0,0 +1,16 @@ +// Copyright 2015 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 "chrome/browser/ui/host_desktop.h" +#include "chrome/browser/ui/views/frame/immersive_mode_controller_stub.h" + +namespace chrome { + +ImmersiveModeController* CreateImmersiveModeController( + chrome::HostDesktopType host_desktop_type) { + // TODO(bshe): Implement for Android. See crbug.com/559179. + return new ImmersiveModeControllerStub(); +} + +} // namespace chrome
diff --git a/chrome/browser/ui/views/passwords/manage_passwords_bubble_view.cc b/chrome/browser/ui/views/passwords/manage_passwords_bubble_view.cc index 3acc33f3..3b01a8d 100644 --- a/chrome/browser/ui/views/passwords/manage_passwords_bubble_view.cc +++ b/chrome/browser/ui/views/passwords/manage_passwords_bubble_view.cc
@@ -235,7 +235,8 @@ void ButtonPressed(views::Button* sender, const ui::Event& event) override; // views::StyledLabelListener: - void StyledLabelLinkClicked(const gfx::Range& range, + void StyledLabelLinkClicked(views::StyledLabel* label, + const gfx::Range& range, int event_flags) override; // Adds |password_forms| to the layout remembering their |type|. @@ -322,6 +323,7 @@ } void ManagePasswordsBubbleView::AccountChooserView::StyledLabelLinkClicked( + views::StyledLabel* label, const gfx::Range& range, int event_flags) { DCHECK_EQ(range, parent_->model()->title_brand_link_range()); @@ -345,7 +347,8 @@ void ButtonPressed(views::Button* sender, const ui::Event& event) override; // views::StyledLabelListener: - void StyledLabelLinkClicked(const gfx::Range& range, + void StyledLabelLinkClicked(views::StyledLabel* label, + const gfx::Range& range, int event_flags) override; // views::WidgetObserver: @@ -442,7 +445,9 @@ } void ManagePasswordsBubbleView::AutoSigninView::StyledLabelLinkClicked( - const gfx::Range& range, int event_flags) { + views::StyledLabel* label, + const gfx::Range& range, + int event_flags) { DCHECK_EQ(range, parent_->model()->autosignin_welcome_link_range()); parent_->model()->OnBrandLinkClicked(); } @@ -481,7 +486,8 @@ void ButtonPressed(views::Button* sender, const ui::Event& event) override; // views::StyledLabelListener: - void StyledLabelLinkClicked(const gfx::Range& range, + void StyledLabelLinkClicked(views::StyledLabel* label, + const gfx::Range& range, int event_flags) override; ManagePasswordsBubbleView* parent_; @@ -567,6 +573,7 @@ } void ManagePasswordsBubbleView::PendingView::StyledLabelLinkClicked( + views::StyledLabel* label, const gfx::Range& range, int event_flags) { DCHECK_EQ(range, parent_->model()->title_brand_link_range()); @@ -689,7 +696,8 @@ void ButtonPressed(views::Button* sender, const ui::Event& event) override; // views::StyledLabelListener implementation - void StyledLabelLinkClicked(const gfx::Range& range, + void StyledLabelLinkClicked(views::StyledLabel* label, + const gfx::Range& range, int event_flags) override; ManagePasswordsBubbleView* parent_; @@ -734,7 +742,9 @@ } void ManagePasswordsBubbleView::SaveConfirmationView::StyledLabelLinkClicked( - const gfx::Range& range, int event_flags) { + views::StyledLabel* label, + const gfx::Range& range, + int event_flags) { DCHECK_EQ(range, parent_->model()->save_confirmation_link_range()); parent_->model()->OnManageLinkClicked(); parent_->Close(); @@ -816,7 +826,8 @@ void ButtonPressed(views::Button* sender, const ui::Event& event) override; // views::StyledLabelListener: - void StyledLabelLinkClicked(const gfx::Range& range, + void StyledLabelLinkClicked(views::StyledLabel* label, + const gfx::Range& range, int event_flags) override; ManagePasswordsBubbleView* parent_; @@ -898,6 +909,7 @@ } void ManagePasswordsBubbleView::UpdatePendingView::StyledLabelLinkClicked( + views::StyledLabel* label, const gfx::Range& range, int event_flags) { DCHECK_EQ(range, parent_->model()->title_brand_link_range());
diff --git a/chrome/browser/ui/views/profiles/profile_chooser_view.cc b/chrome/browser/ui/views/profiles/profile_chooser_view.cc index 7338cbcc..16412db0 100644 --- a/chrome/browser/ui/views/profiles/profile_chooser_view.cc +++ b/chrome/browser/ui/views/profiles/profile_chooser_view.cc
@@ -992,8 +992,9 @@ } } -void ProfileChooserView::StyledLabelLinkClicked( - const gfx::Range& range, int event_flags) { +void ProfileChooserView::StyledLabelLinkClicked(views::StyledLabel* label, + const gfx::Range& range, + int event_flags) { chrome::ShowSettings(browser_); }
diff --git a/chrome/browser/ui/views/profiles/profile_chooser_view.h b/chrome/browser/ui/views/profiles/profile_chooser_view.h index f1d7892..8000eb79 100644 --- a/chrome/browser/ui/views/profiles/profile_chooser_view.h +++ b/chrome/browser/ui/views/profiles/profile_chooser_view.h
@@ -96,7 +96,8 @@ void LinkClicked(views::Link* sender, int event_flags) override; // views::StyledLabelListener: - void StyledLabelLinkClicked(const gfx::Range& range, + void StyledLabelLinkClicked(views::StyledLabel* label, + const gfx::Range& range, int event_flags) override; // views::TextfieldController:
diff --git a/chrome/browser/ui/views/proximity_auth/proximity_auth_error_bubble_view.cc b/chrome/browser/ui/views/proximity_auth/proximity_auth_error_bubble_view.cc index 1d16f7b..49c8836 100644 --- a/chrome/browser/ui/views/proximity_auth/proximity_auth_error_bubble_view.cc +++ b/chrome/browser/ui/views/proximity_auth/proximity_auth_error_bubble_view.cc
@@ -128,6 +128,7 @@ } void ProximityAuthErrorBubbleView::StyledLabelLinkClicked( + views::StyledLabel* label, const gfx::Range& range, int event_flags) { if (!web_contents())
diff --git a/chrome/browser/ui/views/proximity_auth/proximity_auth_error_bubble_view.h b/chrome/browser/ui/views/proximity_auth/proximity_auth_error_bubble_view.h index 1a13d70..987ad18d 100644 --- a/chrome/browser/ui/views/proximity_auth/proximity_auth_error_bubble_view.h +++ b/chrome/browser/ui/views/proximity_auth/proximity_auth_error_bubble_view.h
@@ -52,7 +52,8 @@ void WebContentsDestroyed() override; // views::StyledLabelListener: - void StyledLabelLinkClicked(const gfx::Range& range, + void StyledLabelLinkClicked(views::StyledLabel* label, + const gfx::Range& range, int event_flags) override; // The message text shown in the bubble.
diff --git a/chrome/browser/ui/views/session_crashed_bubble_view.cc b/chrome/browser/ui/views/session_crashed_bubble_view.cc index 7b1060e..b95a03d 100644 --- a/chrome/browser/ui/views/session_crashed_bubble_view.cc +++ b/chrome/browser/ui/views/session_crashed_bubble_view.cc
@@ -398,7 +398,8 @@ RestorePreviousSession(sender); } -void SessionCrashedBubbleView::StyledLabelLinkClicked(const gfx::Range& range, +void SessionCrashedBubbleView::StyledLabelLinkClicked(views::StyledLabel* label, + const gfx::Range& range, int event_flags) { browser_->OpenURL(content::OpenURLParams( GURL("https://support.google.com/chrome/answer/96817"),
diff --git a/chrome/browser/ui/views/session_crashed_bubble_view.h b/chrome/browser/ui/views/session_crashed_bubble_view.h index 6e7e5c02..a6688460 100644 --- a/chrome/browser/ui/views/session_crashed_bubble_view.h +++ b/chrome/browser/ui/views/session_crashed_bubble_view.h
@@ -71,7 +71,8 @@ void ButtonPressed(views::Button* sender, const ui::Event& event) override; // views::StyledLabelListener methods. - void StyledLabelLinkClicked(const gfx::Range& range, + void StyledLabelLinkClicked(views::StyledLabel* label, + const gfx::Range& range, int event_flags) override; // content::WebContentsObserver methods.
diff --git a/chrome/browser/ui/views/sync/profile_signin_confirmation_dialog_views.cc b/chrome/browser/ui/views/sync/profile_signin_confirmation_dialog_views.cc index e01845c..f10dad6 100644 --- a/chrome/browser/ui/views/sync/profile_signin_confirmation_dialog_views.cc +++ b/chrome/browser/ui/views/sync/profile_signin_confirmation_dialog_views.cc
@@ -232,6 +232,7 @@ } void ProfileSigninConfirmationDialogViews::StyledLabelLinkClicked( + views::StyledLabel* label, const gfx::Range& range, int event_flags) { chrome::NavigateParams params(
diff --git a/chrome/browser/ui/views/sync/profile_signin_confirmation_dialog_views.h b/chrome/browser/ui/views/sync/profile_signin_confirmation_dialog_views.h index 812eddca..fcbe3a35 100644 --- a/chrome/browser/ui/views/sync/profile_signin_confirmation_dialog_views.h +++ b/chrome/browser/ui/views/sync/profile_signin_confirmation_dialog_views.h
@@ -56,7 +56,8 @@ const ViewHierarchyChangedDetails& details) override; // views::StyledLabelListener: - void StyledLabelLinkClicked(const gfx::Range& range, + void StyledLabelLinkClicked(views::StyledLabel* label, + const gfx::Range& range, int event_flags) override; // views::ButtonListener:
diff --git a/chrome/browser/ui/views/toolbar/toolbar_view.h b/chrome/browser/ui/views/toolbar/toolbar_view.h index e045788..80eef0d7 100644 --- a/chrome/browser/ui/views/toolbar/toolbar_view.h +++ b/chrome/browser/ui/views/toolbar/toolbar_view.h
@@ -152,10 +152,6 @@ // The apparent horizontal space between most items, and the vertical // padding above and below them. kStandardSpacing = 3, - - // The top of the toolbar has an edge we have to skip over in addition to - // the standard spacing. - kVertSpacing = 5, }; protected:
diff --git a/chrome/browser/ui/views/website_settings/website_settings_popup_view.cc b/chrome/browser/ui/views/website_settings/website_settings_popup_view.cc index 63b776e8..07868e0 100644 --- a/chrome/browser/ui/views/website_settings/website_settings_popup_view.cc +++ b/chrome/browser/ui/views/website_settings/website_settings_popup_view.cc
@@ -910,7 +910,8 @@ } } -void WebsiteSettingsPopupView::StyledLabelLinkClicked(const gfx::Range& range, +void WebsiteSettingsPopupView::StyledLabelLinkClicked(views::StyledLabel* label, + const gfx::Range& range, int event_flags) { presenter_->RecordWebsiteSettingsAction( WebsiteSettings::WEBSITE_SETTINGS_SECURITY_DETAILS_OPENED);
diff --git a/chrome/browser/ui/views/website_settings/website_settings_popup_view.h b/chrome/browser/ui/views/website_settings/website_settings_popup_view.h index b8e08009..4ae4f9c 100644 --- a/chrome/browser/ui/views/website_settings/website_settings_popup_view.h +++ b/chrome/browser/ui/views/website_settings/website_settings_popup_view.h
@@ -88,7 +88,8 @@ void LinkClicked(views::Link* source, int event_flags) override; // views::StyledLabelListener implementation. - void StyledLabelLinkClicked(const gfx::Range& range, + void StyledLabelLinkClicked(views::StyledLabel* label, + const gfx::Range& range, int event_flags) override; // views::TabbedPaneListener implementations.
diff --git a/chrome/browser/ui/webui/chromeos/bluetooth_pairing_ui_browsertest-inl.h b/chrome/browser/ui/webui/chromeos/bluetooth_pairing_ui_browsertest-inl.h index 01eb6f30..ac37b41 100644 --- a/chrome/browser/ui/webui/chromeos/bluetooth_pairing_ui_browsertest-inl.h +++ b/chrome/browser/ui/webui/chromeos/bluetooth_pairing_ui_browsertest-inl.h
@@ -26,6 +26,7 @@ }; BluetoothPairingUITest::BluetoothPairingUITest() {} + BluetoothPairingUITest::~BluetoothPairingUITest() {} void BluetoothPairingUITest::ShowDialog() { @@ -42,11 +43,14 @@ new testing::NiceMock<device::MockBluetoothDevice>( nullptr, 0, - "fake_bluetooth_device", - "11:12:13:14:15:16", + "Bluetooth 2.0 Mouse", + "28:CF:DA:00:00:00", kNotPaired, kNotConnected)); + EXPECT_CALL(*mock_adapter_, GetDevice(testing::_)) + .WillOnce(testing::Return(mock_device_.get())); + chromeos::BluetoothPairingDialog* dialog = new chromeos::BluetoothPairingDialog( browser()->window()->GetNativeWindow(), mock_device_.get());
diff --git a/chrome/browser/ui/webui/options/chromeos/bluetooth_options_browsertest.js b/chrome/browser/ui/webui/options/chromeos/bluetooth_options_browsertest.js index d7043e4..607484c2 100644 --- a/chrome/browser/ui/webui/options/chromeos/bluetooth_options_browsertest.js +++ b/chrome/browser/ui/webui/options/chromeos/bluetooth_options_browsertest.js
@@ -4,23 +4,50 @@ GEN('#if defined(OS_CHROMEOS)'); -function BluetoothWebUITest() {} +function BluetoothWebUITestAsync() {} -BluetoothWebUITest.prototype = { +BluetoothWebUITestAsync.prototype = { __proto__: testing.Test.prototype, + /** @override */ + isAsync: true, + /** * Start tests from the main-settings page. */ browsePreload: 'chrome://settings-frame/', - /** - * @override - */ - preLoad: function() { - this.makeAndRegisterMockHandler([ - 'updateBluetoothDevice', - ]); + // These entries match the fake entries in FakeBluetoothDeviceClient. + fakePairedDevice: { + address: '00:11:22:33:44:55', + connectable: true, + connected: false, + name: 'Fake Device', + paired: true + }, + + fakePairedDevice2: { + address: '20:7D:74:00:00:04', + connectable: false, + connected: false, + name: 'Paired Unconnectable Device', + paired: true + }, + + fakeUnpairedDevice: { + address: '28:CF:DA:00:00:00', + connectable: true, + connected: false, + name: 'Bluetooth 2.0 Mouse', + paired: false + }, + + fakeUnpairedDevice2: { + address: '00:24:BE:00:00:00', + connectable: true, + connected: false, + name: 'PIN Device', + paired: false }, /** @@ -37,15 +64,16 @@ if (name == deviceName) return candidate; } + return undefined; }, /** * Selects a bluetooth device from the list with the matching address. * @param {!Element} listElement A list of Bluetooth devices. - * @param {!BluetoothDevice} device Description of the device. + * @param {string} address Device address. */ - selectDevice: function(listElement, device) { - listElement.selectedItem = device; + selectDevice: function(listElement, address) { + listElement.setSelectedDevice_(address); cr.dispatchSimpleEvent(listElement, 'change'); }, @@ -61,288 +89,279 @@ }; -function BluetoothWebUITestAsync() {} - -BluetoothWebUITestAsync.prototype = { - __proto__: BluetoothWebUITest.prototype, - - /** @override */ - isAsync: true -}; - TEST_F('BluetoothWebUITestAsync', 'testEnableBluetooth', function() { assertEquals(this.browsePreload, document.location.href); expectFalse($('enable-bluetooth').checked); expectTrue($('bluetooth-paired-devices-list').parentNode.hidden); - chrome.bluetooth.onAdapterStateChanged.addListener(function(state) { + $('enable-bluetooth').click(); + + // The UI may not be updated until all callbacks have been handled, so + // send a new request that will get processed after any currently pending + // callbacks. + chrome.bluetooth.getAdapterState(function(state) { expectTrue(state.powered); expectFalse($('bluetooth-paired-devices-list').parentNode.hidden); - this.testDone(); - }); + testDone(); + }.bind(this)); +}); + +TEST_F('BluetoothWebUITestAsync', 'testAddDevice', function() { + assertEquals(this.browsePreload, document.location.href); + + // Enable bluetooth. $('enable-bluetooth').click(); + + // Wait for the UI to process any pending messages. + window.setTimeout(function() { + // Wait for fake bluetooth impl to send any updates. + chrome.bluetooth.getAdapterState(function(state) { + var pairedDeviceList = $('bluetooth-paired-devices-list'); + var unpairedDeviceList = $('bluetooth-unpaired-devices-list'); + + // Verify that devices are in the correct list. + var index = pairedDeviceList.find(this.fakePairedDevice.address); + expectEquals(1, index); + index = pairedDeviceList.find(this.fakePairedDevice2.address); + expectEquals(0, index); + index = pairedDeviceList.find(this.fakeUnpairedDevice.address); + expectEquals(undefined, index); + expectTrue(!!this.getElementForDevice(pairedDeviceList, + this.fakePairedDevice.name)); + expectFalse(!!this.getElementForDevice(unpairedDeviceList, + this.fakePairedDevice.name)); + + // Test clicking on the 'Add a device' button. This should send a + // startDiscovering request. + $('bluetooth-add-device').click(); + expectFalse($('bluetooth-options').hidden); + + // Wait for fake bluetooth impl to send any updates. + chrome.bluetooth.getAdapterState(function(state) { + expectTrue(state.discovering); + expectFalse(unpairedDeviceList.parentNode.hidden); + + index = unpairedDeviceList.find(this.fakeUnpairedDevice.address); + expectEquals(0, index); + + var connectButton = $('bluetooth-add-device-apply-button'); + expectTrue(connectButton.disabled); + expectFalse($('bluetooth-add-device-cancel-button').disabled); + + // Test selecting an element and clicking on the connect button. + this.selectDevice(unpairedDeviceList, this.fakeUnpairedDevice.address); + expectFalse(connectButton.disabled); + connectButton.click(); + + // Wait for fake bluetooth impl to send any updates. + chrome.bluetooth.getAdapterState(function(state) { + // Verify that the pairing UI is shown. + expectFalse($('bluetooth-pairing').hidden); + testDone(); + }.bind(this)); + }.bind(this)); + }.bind(this)); + }.bind(this)); }); -TEST_F('BluetoothWebUITest', 'testAddDevices', function() { +TEST_F('BluetoothWebUITestAsync', 'testDevicePairing', function() { assertEquals(this.browsePreload, document.location.href); - var pairedDeviceList = $('bluetooth-paired-devices-list'); - var unpairedDeviceList = $('bluetooth-unpaired-devices-list'); + // Enable bluetooth. + $('enable-bluetooth').click(); - var fakePairedDevice = { - address: '00:11:22:33:44:55', - connectable: true, - connected: false, - name: 'Fake device', - paired: true - }; + // Wait for the UI to process any pending messages. + window.setTimeout(function() { + // Wait for fake bluetooth impl to send any updates. + chrome.bluetooth.getAdapterState(function(state) { + var pairedDeviceList = $('bluetooth-paired-devices-list'); + var unpairedDeviceList = $('bluetooth-unpaired-devices-list'); - var fakeUnpairedDevice = { - address: '28:CF:DA:00:00:00', - connectable: true, - connected: false, - name: 'Apple Magic Mouse', - paired: false - }; + $('bluetooth-add-device').click(); - var fakeUnpairedDevice2 = { - address: '28:37:37:00:00:00', - connectable: true, - connected: false, - name: 'Apple Wireless Keyboard', - paired: false - }; + // Wait for fake bluetooth impl to send any updates. + chrome.bluetooth.getAdapterState(function(state) { + expectFalse(unpairedDeviceList.parentNode.hidden); - // Ensure data models for the paired and unpaired device lists are properly - // updated. - var index = pairedDeviceList.find(fakePairedDevice.address); - expectEquals(undefined, index); - options.BrowserOptions.bluetoothPairingEvent({device: fakePairedDevice}); - index = pairedDeviceList.find(fakePairedDevice.address); - expectEquals(0, index); + // Test selecting an element and clicking on the connect button. + var index = unpairedDeviceList.find(this.fakeUnpairedDevice2.address); + expectNotEquals(undefined, index); + this.selectDevice(unpairedDeviceList, this.fakeUnpairedDevice2.address); + var connectButton = $('bluetooth-add-device-apply-button'); + expectFalse(connectButton.disabled); + connectButton.click(); - // Ensure the DOM contents of the list are properly updated. The default - // layout of a list creates DOM elements only for visible elements in the - // list, which is problematic if the list is hidden at the time of layout. - // The Bluetooth device lists overcomes this problem by using fixed sized - // elements in an auto-expanding list. This test ensures the problem stays - // fixed. - expectTrue(!!this.getElementForDevice(pairedDeviceList, - fakePairedDevice.name)); - expectFalse(!!this.getElementForDevice(unpairedDeviceList, - fakePairedDevice.name)); + // Wait for fake bluetooth impl to send any updates. + chrome.bluetooth.getAdapterState(function(state) { + // Verify that the pairing UI is shown. + expectFalse($('bluetooth-pairing').hidden); + expectTrue($('bluetooth-pairing-passkey-display').hidden); + expectTrue($('bluetooth-pairing-passkey-entry').hidden); + expectFalse($('bluetooth-pairing-pincode-entry').hidden); - options.BrowserOptions.bluetoothPairingEvent({device: fakeUnpairedDevice}); - index = unpairedDeviceList.find(fakeUnpairedDevice.address); - expectEquals(0, index); - expectFalse(!!this.getElementForDevice(pairedDeviceList, - fakeUnpairedDevice.name)); - expectTrue(!!this.getElementForDevice(unpairedDeviceList, - fakeUnpairedDevice.name)); + var pincode = '123456'; + this.fakeInput($('bluetooth-pincode'), pincode); + $('bluetooth-pair-device-connect-button').click(); - // Test adding a second device to a list. - options.BrowserOptions.bluetoothPairingEvent({device: fakeUnpairedDevice2}); - index = unpairedDeviceList.find(fakeUnpairedDevice2.address); - expectEquals(1, index); - expectTrue(!!this.getElementForDevice(unpairedDeviceList, - fakeUnpairedDevice2.name)); - - // Test clicking on the 'Add a device' button. - $('bluetooth-add-device').click(); - expectFalse($('bluetooth-options').hidden); - expectTrue($('bluetooth-add-device-apply-button').disabled); - expectFalse($('bluetooth-add-device-cancel-button').disabled); - - Mock4JS.verifyAllMocks(); - Mock4JS.clearMocksToVerify(); - - // Test selecting an element and clicking on the connect button. - this.mockHandler.expects(once()).updateBluetoothDevice( - [fakeUnpairedDevice2.address, 'connect']); - this.selectDevice(unpairedDeviceList, fakeUnpairedDevice2); - var connectButton = $('bluetooth-add-device-apply-button'); - expectFalse(connectButton.disabled); - connectButton.click(); + // Wait for fake bluetooth impl to send any updates. + chrome.bluetooth.getAdapterState(function(state) { + expectTrue($('bluetooth-pairing-pincode-entry').hidden); + testDone(); + }.bind(this)); + }.bind(this)); + }.bind(this)); + }.bind(this)); + }.bind(this)); }); -TEST_F('BluetoothWebUITest', 'testDevicePairing', function() { +TEST_F('BluetoothWebUITestAsync', 'testConnect', function() { assertEquals(this.browsePreload, document.location.href); - var pairedDeviceList = $('bluetooth-paired-devices-list'); - var unpairedDeviceList = $('bluetooth-unpaired-devices-list'); + // Enable bluetooth. + $('enable-bluetooth').click(); - var fakeEvent = { - device: { - address: '00:24:BE:00:00:00', - connectable: true, - connected: false, - name: 'Sony BT-00', - paired: false - } - }; + // Wait for the UI to process any pending messages. + window.setTimeout(function() { + // Wait for fake bluetooth impl to send any updates. + chrome.bluetooth.getAdapterState(function(state) { + var pairedDeviceList = $('bluetooth-paired-devices-list'); + var element = this.getElementForDevice( + pairedDeviceList, this.fakePairedDevice.name); + assertTrue(!!element, this.fakePairedDevice.name); + expectFalse(!!element.getAttribute('connected')); - options.BrowserOptions.bluetoothPairingEvent(fakeEvent); - var index = unpairedDeviceList.find(fakeEvent.device.address); - expectEquals(0, index); - expectTrue(!!this.getElementForDevice(unpairedDeviceList, - fakeEvent.device.name)); + var connectButton = $('bluetooth-reconnect-device'); + expectTrue(connectButton.disabled); - // Simulate process of pairing a device. - fakeEvent.pairing = 'bluetoothEnterPinCode'; - options.BrowserOptions.bluetoothPairingEvent(fakeEvent); + // Simulate connecting to a previously paired device. + this.selectDevice(pairedDeviceList, this.fakePairedDevice.address); + expectFalse(connectButton.disabled); + connectButton.click(); - // Verify that the pairing dialog is displayed with the proper options. - expectFalse($('bluetooth-pairing').hidden); - expectTrue($('bluetooth-pairing-passkey-display').hidden); - expectTrue($('bluetooth-pairing-passkey-entry').hidden); - expectFalse($('bluetooth-pairing-pincode-entry').hidden); - - // Connect button should be visible but disabled until a pincode is entered. - expectFalse($('bluetooth-pair-device-connect-button').hidden); - expectFalse($('bluetooth-pair-device-cancel-button').hidden); - expectTrue($('bluetooth-pair-device-connect-button').disabled); - expectFalse($('bluetooth-pair-device-cancel-button').disabled); - - // Simulate process of entering a pincode. - var pincode = '123456'; - - this.mockHandler.expects(once()).updateBluetoothDevice( - [fakeEvent.device.address, 'connect', pincode]).will( - callFunction(function() { - fakeEvent.pairing = ''; - fakeEvent.device.paired = true; - options.BrowserOptions.bluetoothPairingEvent(fakeEvent); - })); - - this.fakeInput($('bluetooth-pincode'), pincode); - $('bluetooth-pair-device-connect-button').click(); - - // Verify that the device is removed from the unparied list and added to the - // paired device list. - expectTrue(!!this.getElementForDevice(pairedDeviceList, - fakeEvent.device.name)); - expectFalse(!!this.getElementForDevice(unpairedDeviceList, - fakeEvent.device.name)); + // Call bluetooth.getAdapterState to ensure that all state has been + // updated. + chrome.bluetooth.getAdapterState(function(state) { + element = this.getElementForDevice( + pairedDeviceList, this.fakePairedDevice.name); + expectTrue(!!element.getAttribute('connected')); + var deleteButton = element.querySelector('.row-delete-button'); + expectTrue(!!deleteButton); + testDone(); + }.bind(this)); + }.bind(this)); + }.bind(this)); }); -TEST_F('BluetoothWebUITest', 'testConnectionState', function() { +TEST_F('BluetoothWebUITestAsync', 'testDisconnect', function() { assertEquals(this.browsePreload, document.location.href); - var pairedDeviceList = $('bluetooth-paired-devices-list'); - var connectButton = $('bluetooth-reconnect-device'); + // Enable bluetooth. + $('enable-bluetooth').click(); - var fakeEvent = { - device: { - address: '00:24:BE:00:00:00', - connectable: true, - connected: false, - name: 'Sony BT-00', - paired: true - } - }; + // Wait for the UI to process any pending messages. + window.setTimeout(function() { + // Wait for fake bluetooth impl to send any updates. + chrome.bluetooth.getAdapterState(function(state) { + var pairedDeviceList = $('bluetooth-paired-devices-list'); - options.BrowserOptions.bluetoothPairingEvent(fakeEvent); - var element = this.getElementForDevice(pairedDeviceList, - fakeEvent.device.name); - assertTrue(!!element); - expectFalse(!!element.getAttribute('connected')); - expectTrue(connectButton.disabled); + // First connect to the device so that the fake implementation state is + // connected. + chrome.bluetoothPrivate.connect( + this.fakePairedDevice.address, function(result) { + assertEquals( + chrome.bluetoothPrivate.ConnectResultType.SUCCESS, result); - // Simulate connecting to a previously paired device. - this.selectDevice(pairedDeviceList, fakeEvent.device); - expectFalse(connectButton.disabled); - this.mockHandler.expects(once()).updateBluetoothDevice( - [fakeEvent.device.address, 'connect']).will( - callFunction(function() { - fakeEvent.device.connected = true; - options.BrowserOptions.bluetoothPairingEvent(fakeEvent); - })); - connectButton.click(); - element = this.getElementForDevice(pairedDeviceList, - fakeEvent.device.name); - assertTrue(!!element); - expectTrue(!!element.getAttribute('connected')); - var button = element.querySelector('.row-delete-button'); - expectTrue(!!button); + var element = this.getElementForDevice( + pairedDeviceList, this.fakePairedDevice.name); + assertTrue(!!element, this.fakePairedDevice.name); + expectTrue(!!element.getAttribute('connected')); - Mock4JS.verifyAllMocks(); - Mock4JS.clearMocksToVerify(); + // Simulate disconnecting from a connected device. + var button = element.querySelector('.row-delete-button'); + button.click(); - // Test disconnecting. - this.mockHandler.expects(once()).updateBluetoothDevice( - [fakeEvent.device.address, 'disconnect']).will( - callFunction(function() { - fakeEvent.device.connected = false; - options.BrowserOptions.bluetoothPairingEvent(fakeEvent); - })); - button.click(); - element = this.getElementForDevice(pairedDeviceList, - fakeEvent.device.name); - assertTrue(!!element); - expectFalse(!!element.getAttribute('connected')); - button = element.querySelector('.row-delete-button'); - expectTrue(!!button); + // Wait for fake bluetooth impl to send any updates. + chrome.bluetooth.getAdapterState(function(state) { + element = this.getElementForDevice( + pairedDeviceList, this.fakePairedDevice.name); + expectFalse(!!element.getAttribute('connected')); + button = element.querySelector('.row-delete-button'); + expectTrue(!!button); + testDone(); + }.bind(this)); + }.bind(this)); + }.bind(this)); + }.bind(this)); +}); - Mock4JS.verifyAllMocks(); - Mock4JS.clearMocksToVerify(); +TEST_F('BluetoothWebUITestAsync', 'testForget', function() { + assertEquals(this.browsePreload, document.location.href); - // Test forgetting a disconnected device. - this.mockHandler.expects(once()).updateBluetoothDevice( - [fakeEvent.device.address, 'forget']).will( - callFunction(function() { - options.BrowserOptions.removeBluetoothDevice(fakeEvent.device.address); - })); - button.click(); - expectFalse(!!this.getElementForDevice(pairedDeviceList, - fakeEvent.device.name)); + // Enable bluetooth. + $('enable-bluetooth').click(); + + // Wait for the UI to process any pending messages. + window.setTimeout(function() { + // Wait for fake bluetooth impl to send any updates. + chrome.bluetooth.getAdapterState(function(state) { + var pairedDeviceList = $('bluetooth-paired-devices-list'); + + var element = this.getElementForDevice(pairedDeviceList, + this.fakePairedDevice.name); + var button = element.querySelector('.row-delete-button'); + button.click(); + + // Wait for fake bluetooth impl to send any updates. + chrome.bluetooth.getAdapterState(function(state) { + expectFalse(!!this.getElementForDevice(pairedDeviceList, + this.fakePairedDevice.name)); + testDone(); + }.bind(this)); + }.bind(this)); + }.bind(this)); }); -TEST_F('BluetoothWebUITest', 'testMaliciousInput', function() { +TEST_F('BluetoothWebUITestAsync', 'testMaliciousInput', function() { assertEquals(this.browsePreload, document.location.href); - var unpairedDeviceList = $('bluetooth-unpaired-devices-list'); - var pairDeviceDialog = $('bluetooth-pairing'); - var maliciousStrings = [ - '<SCRIPT>alert(1)</SCRIPT>', - '>\'>\\"><SCRIPT>alert(1)</SCRIPT>', - '<IMG SRC=\\"javascript:alert(1)\\">', - '<A HREF=\\"data:text/html;base64,' + - 'PHNjcmlwdD5hbGVydCgxKTwvc2NyaXB0Pgo=\\">..</A>', - '<div>', - '<textarea>', - '<style>', - '[0xC0][0xBC]SCRIPT[0xC0][0xBE]alert(1)[0xC0][0xBC]/SCRIPT[0xC0][0xBE]', - '+ADw-SCRIPT+AD4-alert(1)+ADw-/SCRIPT+AD4-', - '&#<script>alert(1)</script>;', - '<!-- Hello -- world > <SCRIPT>alert(1)</SCRIPT> -->', - '<!<!-- Hello world > <SCRIPT>alert(1)</SCRIPT> -->', - '\x3CSCRIPT\x3Ealert(1)\x3C/SCRIPT\x3E', - '<IMG SRC=\\"j[0x00]avascript:alert(1)\\">', - '<BASE HREF=\\"javascript:1;/**/\\"><IMG SRC=\\"alert(1)\\">', - 'javascript:alert(1);', - ' xss_injection=\\"\\" ', - '\\" xss_injection=\\"', - '\' xss_injection=\'', - '<!--', - '\'', - '\\"' + '<SCRIPT>alert(1)</SCRIPT>', + '>\'>\\"><SCRIPT>alert(1)</SCRIPT>', + '<IMG SRC=\\"javascript:alert(1)\\">', + '<A HREF=\\"data:text/html;base64,' + + 'PHNjcmlwdD5hbGVydCgxKTwvc2NyaXB0Pgo=\\">..</A>', + '<div>', + '<textarea>', + '<style>', + '[0xC0][0xBC]SCRIPT[0xC0][0xBE]alert(1)[0xC0][0xBC]/SCRIPT[0xC0][0xBE]', + '+ADw-SCRIPT+AD4-alert(1)+ADw-/SCRIPT+AD4-', + '&#<script>alert(1)</script>;', + '<!-- Hello -- world > <SCRIPT>alert(1)</SCRIPT> -->', + '<!<!-- Hello world > <SCRIPT>alert(1)</SCRIPT> -->', + '\x3CSCRIPT\x3Ealert(1)\x3C/SCRIPT\x3E', + '<IMG SRC=\\"j[0x00]avascript:alert(1)\\">', + '<BASE HREF=\\"javascript:1;/**/\\"><IMG SRC=\\"alert(1)\\">', + 'javascript:alert(1);', + ' xss_injection=\\"\\" ', + '\\" xss_injection=\\"', + '\' xss_injection=\'', + '<!--', + '\'', + '\\"' ]; var fakeEvent = { device: { - address: '11:22:33:44:55:66', + address: '28:CF:DA:00:00:00', connectable: true, connected: false, - name: 'fake', - paired: false, + name: 'Bluetooth 2.0 Mouse', + paired: false }, pairing: 'bluetoothStartConnecting' }; - options.BrowserOptions.bluetoothPairingEvent(fakeEvent); - var nodeCount = function(node) { if (node.getAttribute) assertFalse(!!node.getAttribute('xss_injection')); @@ -354,26 +373,48 @@ return tally; }; - // Determine the expected sizes. - var unpairedDeviceListSize = nodeCount(unpairedDeviceList); - var pairDeviceDialogSize = nodeCount(pairDeviceDialog); + // Enable bluetooth. + $('enable-bluetooth').click(); - // Ensure that updating the device with a malicious name does not corrupt the - // structure of the document. Tests the unpaired device list and bluetooth - // pairing dialog. - for (var i = 0; i < maliciousStrings.length; i++) { - fakeEvent.device.name = maliciousStrings[i]; - options.BrowserOptions.bluetoothPairingEvent(fakeEvent); - assertEquals(unpairedDeviceListSize, nodeCount(unpairedDeviceList)); - var element = this.getElementForDevice(unpairedDeviceList, - fakeEvent.device.name); - assertTrue(!!element); - var label = element.querySelector('.bluetooth-device-label'); - assertTrue(!!label); - assertEquals(maliciousStrings[i], label.textContent); - assertEquals(pairDeviceDialogSize, nodeCount(pairDeviceDialog)); - } + // Wait for the UI to process any pending messages. + window.setTimeout(function() { + // Wait for fake bluetooth impl to send any updates. + chrome.bluetooth.getAdapterState(function(state) { + var unpairedDeviceList = $('bluetooth-unpaired-devices-list'); + var pairDeviceDialog = $('bluetooth-pairing'); + // Show the pairing dialog. + $('bluetooth-add-device').click(); + BluetoothPairing.showDialog(fakeEvent); + + // Wait for fake bluetooth impl to send any updates. + chrome.bluetooth.getAdapterState(function(state) { + expectFalse(unpairedDeviceList.parentNode.hidden); + + // Determine the expected sizes. + var unpairedDeviceListSize = nodeCount(unpairedDeviceList); + var pairDeviceDialogSize = nodeCount(pairDeviceDialog); + + // Ensure that updating the device with a malicious name does not + // corrupt the structure of the document. Tests the unpaired device + // list and bluetooth pairing dialog. + for (var i = 0; i < maliciousStrings.length; i++) { + fakeEvent.device.name = maliciousStrings[i]; + BluetoothPairing.showDialog(fakeEvent); + assertEquals(unpairedDeviceListSize, nodeCount(unpairedDeviceList)); + var element = this.getElementForDevice( + unpairedDeviceList, fakeEvent.device.name); + assertTrue(!!element, fakeEvent.device.name); + var label = element.querySelector('.bluetooth-device-label'); + assertTrue(!!label); + assertEquals(maliciousStrings[i], label.textContent); + assertEquals(pairDeviceDialogSize, nodeCount(pairDeviceDialog)); + } + + testDone(); + }.bind(this)); + }.bind(this)); + }.bind(this)); }); GEN('#endif');
diff --git a/chrome/browser/ui/webui/options/chromeos/bluetooth_options_handler.cc b/chrome/browser/ui/webui/options/chromeos/bluetooth_options_handler.cc index ae6af02..1defd65 100644 --- a/chrome/browser/ui/webui/options/chromeos/bluetooth_options_handler.cc +++ b/chrome/browser/ui/webui/options/chromeos/bluetooth_options_handler.cc
@@ -13,60 +13,15 @@ #include "base/values.h" #include "chrome/grit/generated_resources.h" #include "content/public/browser/web_ui.h" -#include "device/bluetooth/bluetooth_adapter.h" -#include "device/bluetooth/bluetooth_adapter_factory.h" -#include "device/bluetooth/bluetooth_device.h" #include "third_party/cros_system_api/dbus/service_constants.h" -namespace { - -// |UpdateDeviceCallback| takes a variable length list as an argument. The -// value stored in each list element is indicated by the following constants. -const int kUpdateDeviceAddressIndex = 0; -const int kUpdateDeviceCommandIndex = 1; -const int kUpdateDeviceAuthTokenIndex = 2; - -// |UpdateDeviceCallback| provides a command value of one of the following -// constants that indicates what update it is providing to us. -const char kConnectCommand[] = "connect"; -const char kCancelCommand[] = "cancel"; -const char kAcceptCommand[] = "accept"; -const char kRejectCommand[] = "reject"; -const char kDisconnectCommand[] = "disconnect"; -const char kForgetCommand[] = "forget"; - -// |SendDeviceNotification| provides BluetoothPairingEvent properties. -const char kPincode[] = "pincode"; -const char kPasskey[] = "passkey"; -const char kEnteredKey[] = "enteredKey"; - -// |SendDeviceNotification| may include a pairing parameter whose value -// is one of the following constants instructing the UI to perform a certain -// action. -const char kStartConnecting[] = "bluetoothStartConnecting"; -const char kEnterPinCode[] = "bluetoothEnterPinCode"; -const char kEnterPasskey[] = "bluetoothEnterPasskey"; -const char kRemotePinCode[] = "bluetoothRemotePinCode"; -const char kRemotePasskey[] = "bluetoothRemotePasskey"; -const char kConfirmPasskey[] = "bluetoothConfirmPasskey"; - -// An invalid |entered| value to represent the "undefined" value. -const int kInvalidEntered = 0xFFFF; - -} // namespace - namespace chromeos { namespace options { -BluetoothOptionsHandler::BluetoothOptionsHandler() - : pairing_device_passkey_(1000000), - pairing_device_entered_(kInvalidEntered), - weak_ptr_factory_(this) { +BluetoothOptionsHandler::BluetoothOptionsHandler() { } BluetoothOptionsHandler::~BluetoothOptionsHandler() { - if (adapter_.get()) - adapter_->RemoveObserver(this); } void BluetoothOptionsHandler::GetLocalizedValues( @@ -144,376 +99,5 @@ RegisterStrings(localized_strings, resources, arraysize(resources)); } -// TODO(kevers): Reorder methods to match ordering in the header file. - -void BluetoothOptionsHandler::AdapterPresentChanged( - device::BluetoothAdapter* adapter, - bool present) { - DCHECK(adapter == adapter_.get()); - if (present) { - web_ui()->CallJavascriptFunction( - "options.BrowserOptions.showBluetoothSettings"); - - // Update the checkbox and visibility based on the powered state of the - // new adapter. - AdapterPoweredChanged(adapter_.get(), adapter_->IsPowered()); - } else { - web_ui()->CallJavascriptFunction( - "options.BrowserOptions.hideBluetoothSettings"); - } -} - -void BluetoothOptionsHandler::AdapterPoweredChanged( - device::BluetoothAdapter* adapter, - bool powered) { - DCHECK(adapter == adapter_.get()); - base::FundamentalValue checked(powered); - web_ui()->CallJavascriptFunction( - "options.BrowserOptions.setBluetoothState", checked); - - // If the "Add device" overlay is visible, dismiss it. - if (!powered) { - web_ui()->CallJavascriptFunction( - "options.BluetoothOptions.dismissOverlay"); - } -} - -void BluetoothOptionsHandler::AdapterDiscoveringChanged( - device::BluetoothAdapter* adapter, - bool discovering) { - DCHECK(adapter == adapter_.get()); - base::FundamentalValue discovering_value(discovering); - web_ui()->CallJavascriptFunction( - "options.BluetoothOptions.updateDiscoveryState", discovering_value); -} - -void BluetoothOptionsHandler::RegisterMessages() { - web_ui()->RegisterMessageCallback("updateBluetoothDevice", - base::Bind(&BluetoothOptionsHandler::UpdateDeviceCallback, - base::Unretained(this))); - web_ui()->RegisterMessageCallback("getPairedBluetoothDevices", - base::Bind(&BluetoothOptionsHandler::GetPairedDevicesCallback, - base::Unretained(this))); -} - -void BluetoothOptionsHandler::InitializeHandler() { - device::BluetoothAdapterFactory::GetAdapter( - base::Bind(&BluetoothOptionsHandler::InitializeAdapter, - weak_ptr_factory_.GetWeakPtr())); -} - -void BluetoothOptionsHandler::InitializePage() { - // Show or hide the bluetooth settings and update the checkbox based - // on the current present/powered state. - AdapterPresentChanged(adapter_.get(), adapter_->IsPresent()); -} - -void BluetoothOptionsHandler::InitializeAdapter( - scoped_refptr<device::BluetoothAdapter> adapter) { - adapter_ = adapter; - CHECK(adapter_.get()); - adapter_->AddObserver(this); -} - -void BluetoothOptionsHandler::UpdateDeviceCallback( - const base::ListValue* args) { - std::string address; - args->GetString(kUpdateDeviceAddressIndex, &address); - - device::BluetoothDevice* device = adapter_->GetDevice(address); - if (!device) - return; - - std::string command; - args->GetString(kUpdateDeviceCommandIndex, &command); - - if (command == kConnectCommand) { - int size = args->GetSize(); - if (size > kUpdateDeviceAuthTokenIndex) { - // PIN code or Passkey entry during the pairing process. - std::string auth_token; - args->GetString(kUpdateDeviceAuthTokenIndex, &auth_token); - - if (device->ExpectingPinCode()) { - DeviceConnecting(device); - // PIN Code is an array of 1 to 16 8-bit bytes, the usual - // interpretation, and the one shared by BlueZ, is a UTF-8 string - // of as many characters that will fit in that space, thus we - // can use the auth token from JavaScript unmodified. - VLOG(1) << "PIN Code supplied: " << address << ": " << auth_token; - device->SetPinCode(auth_token); - } else if (device->ExpectingPasskey()) { - DeviceConnecting(device); - // Passkey is a numeric in the range 0-999999, in this case the - // JavaScript code should have ensured the auth token string only - // contains digits so a simple conversion is sufficient. In the - // failure case, just use 0 since that's the most likely Passkey - // anyway, and if it's refused the device will request a new one. - unsigned passkey = 0; - base::StringToUint(auth_token, &passkey); - - VLOG(1) << "Passkey supplied: " << address << ": " << passkey; - device->SetPasskey(passkey); - } else { - LOG(WARNING) << "Auth token supplied after pairing ended: " << address - << ": " << auth_token; - } - } else { - // Connection request. - VLOG(1) << "Connect: " << address; - device->Connect( - this, - base::Bind(&BluetoothOptionsHandler::Connected, - weak_ptr_factory_.GetWeakPtr()), - base::Bind(&BluetoothOptionsHandler::ConnectError, - weak_ptr_factory_.GetWeakPtr(), - device->GetAddress())); - } - } else if (command == kCancelCommand) { - // Cancel pairing. - VLOG(1) << "Cancel pairing: " << address; - device->CancelPairing(); - } else if (command == kAcceptCommand) { - DeviceConnecting(device); - // Confirm displayed Passkey. - VLOG(1) << "Confirm pairing: " << address; - device->ConfirmPairing(); - } else if (command == kRejectCommand) { - // Reject displayed Passkey. - VLOG(1) << "Reject pairing: " << address; - device->RejectPairing(); - } else if (command == kDisconnectCommand) { - // Disconnect from device. - VLOG(1) << "Disconnect device: " << address; - device->Disconnect( - base::Bind(&base::DoNothing), - base::Bind(&BluetoothOptionsHandler::DisconnectError, - weak_ptr_factory_.GetWeakPtr(), - device->GetAddress())); - } else if (command == kForgetCommand) { - // Disconnect from device and delete pairing information. - VLOG(1) << "Forget device: " << address; - device->Forget( - base::Bind(&base::DoNothing), - base::Bind(&BluetoothOptionsHandler::ForgetError, - weak_ptr_factory_.GetWeakPtr(), device->GetAddress())); - } else { - LOG(WARNING) << "Unknown updateBluetoothDevice command: " << command; - } -} - -void BluetoothOptionsHandler::Connected() { - // Invalidate the local cache. - pairing_device_address_.clear(); - pairing_device_entered_ = kInvalidEntered; - - web_ui()->CallJavascriptFunction( - "options.BluetoothPairing.dismissDialog"); -} - -void BluetoothOptionsHandler::ConnectError( - const std::string& address, - device::BluetoothDevice::ConnectErrorCode error_code) { - const char* error_name = nullptr; - - // Invalidate the local cache. - pairing_device_address_.clear(); - pairing_device_entered_ = kInvalidEntered; - - VLOG(1) << "Failed to connect to device: " << address; - switch (error_code) { - case device::BluetoothDevice::ERROR_UNKNOWN: - error_name = "bluetoothConnectUnknownError"; - break; - case device::BluetoothDevice::ERROR_INPROGRESS: - error_name = "bluetoothConnectInProgress"; - break; - case device::BluetoothDevice::ERROR_FAILED: - error_name = "bluetoothConnectFailed"; - break; - case device::BluetoothDevice::ERROR_AUTH_FAILED: - error_name = "bluetoothConnectAuthFailed"; - break; - case device::BluetoothDevice::ERROR_AUTH_CANCELED: - error_name = "bluetoothConnectAuthCanceled"; - break; - case device::BluetoothDevice::ERROR_AUTH_REJECTED: - error_name = "bluetoothConnectAuthRejected"; - break; - case device::BluetoothDevice::ERROR_AUTH_TIMEOUT: - error_name = "bluetoothConnectAuthTimeout"; - break; - case device::BluetoothDevice::ERROR_UNSUPPORTED_DEVICE: - error_name = "bluetoothConnectUnsupportedDevice"; - break; - } - // Report an error only if there's an error to report. - if (error_name) - ReportError(error_name, address); -} - -void BluetoothOptionsHandler::DisconnectError(const std::string& address) { - VLOG(1) << "Failed to disconnect from device: " << address; - ReportError("bluetoothDisconnectFailed", address); -} - -void BluetoothOptionsHandler::ForgetError(const std::string& address) { - VLOG(1) << "Failed to disconnect and unpair device: " << address; - ReportError("bluetoothForgetFailed", address); -} - -void BluetoothOptionsHandler::GetPairedDevicesCallback( - const base::ListValue* args) { - device::BluetoothAdapter::DeviceList devices = adapter_->GetDevices(); - - for (device::BluetoothAdapter::DeviceList::iterator iter = devices.begin(); - iter != devices.end(); ++iter) - SendDeviceNotification(*iter, nullptr, std::string()); -} - -void BluetoothOptionsHandler::SendDeviceNotification( - const device::BluetoothDevice* device, - base::DictionaryValue* params, - std::string pairing) { - scoped_ptr<base::DictionaryValue> js_device_properties( - new base::DictionaryValue); - js_device_properties->SetString("name", device->GetName()); - js_device_properties->SetString("address", device->GetAddress()); - js_device_properties->SetBoolean("paired", device->IsPaired()); - js_device_properties->SetBoolean("connected", device->IsConnected()); - js_device_properties->SetBoolean("connecting", device->IsConnecting()); - js_device_properties->SetBoolean("connectable", device->IsConnectable()); - - scoped_ptr<base::DictionaryValue> js_event_properties( - new base::DictionaryValue); - if (params) - js_event_properties->MergeDictionary(params); - js_event_properties->SetString("pairing", pairing); - js_event_properties->Set("device", js_device_properties.Pass()); - - // Use the cached values to update event properties. - if (device->GetAddress() == pairing_device_address_) { - if (pairing.empty()) { - pairing = pairing_device_pairing_; - js_event_properties->SetString("pairing", pairing); - } - if (pairing == kRemotePinCode && !js_event_properties->HasKey(kPincode)) - js_event_properties->SetString(kPincode, pairing_device_pincode_); - if (pairing == kRemotePasskey && !js_event_properties->HasKey(kPasskey)) - js_event_properties->SetInteger(kPasskey, pairing_device_passkey_); - if ((pairing == kRemotePinCode || pairing == kRemotePasskey) && - !js_event_properties->HasKey(kEnteredKey) && - pairing_device_entered_ != kInvalidEntered) { - js_event_properties->SetInteger(kEnteredKey, pairing_device_entered_); - } - } - - // Update the cache with the new information. - if (!pairing.empty()) { - pairing_device_address_ = device->GetAddress(); - pairing_device_pairing_ = pairing; - js_event_properties->GetString(kPincode, &pairing_device_pincode_); - js_event_properties->GetInteger(kPasskey, &pairing_device_passkey_); - if (!js_event_properties->GetInteger(kEnteredKey, &pairing_device_entered_)) - pairing_device_entered_ = kInvalidEntered; - } - - web_ui()->CallJavascriptFunction( - "options.BrowserOptions.bluetoothPairingEvent", - *js_event_properties); -} - -void BluetoothOptionsHandler::RequestPinCode(device::BluetoothDevice* device) { - SendDeviceNotification(device, nullptr, kEnterPinCode); -} - -void BluetoothOptionsHandler::RequestPasskey(device::BluetoothDevice* device) { - SendDeviceNotification(device, nullptr, kEnterPasskey); -} - -void BluetoothOptionsHandler::DisplayPinCode(device::BluetoothDevice* device, - const std::string& pincode) { - base::DictionaryValue params; - params.SetString(kPincode, pincode); - SendDeviceNotification(device, ¶ms, kRemotePinCode); -} - -void BluetoothOptionsHandler::DisplayPasskey(device::BluetoothDevice* device, - uint32 passkey) { - base::DictionaryValue params; - params.SetInteger(kPasskey, passkey); - SendDeviceNotification(device, ¶ms, kRemotePasskey); -} - -void BluetoothOptionsHandler::KeysEntered(device::BluetoothDevice* device, - uint32 entered) { - base::DictionaryValue params; - params.SetInteger(kEnteredKey, entered); - SendDeviceNotification(device, ¶ms, ""); -} - -void BluetoothOptionsHandler::ConfirmPasskey(device::BluetoothDevice* device, - uint32 passkey) { - base::DictionaryValue params; - params.SetInteger(kPasskey, passkey); - SendDeviceNotification(device, ¶ms, kConfirmPasskey); -} - -void BluetoothOptionsHandler::AuthorizePairing( - device::BluetoothDevice* device) { - // There is never any circumstance where this will be called, since the - // options handler will only be used for outgoing pairing requests, but - // play it safe. - device->ConfirmPairing(); -} - -void BluetoothOptionsHandler::ReportError( - const std::string& error, - const std::string& address) { - base::DictionaryValue properties; - properties.SetString("message", error); - properties.SetString("address", address); - web_ui()->CallJavascriptFunction( - "options.BluetoothPairing.showMessage", - properties); -} - -void BluetoothOptionsHandler::DeviceAdded(device::BluetoothAdapter* adapter, - device::BluetoothDevice* device) { - DCHECK(adapter == adapter_.get()); - DCHECK(device); - SendDeviceNotification(device, nullptr, std::string()); -} - -void BluetoothOptionsHandler::DeviceChanged(device::BluetoothAdapter* adapter, - device::BluetoothDevice* device) { - DCHECK(adapter == adapter_.get()); - DCHECK(device); - SendDeviceNotification(device, nullptr, std::string()); -} - -void BluetoothOptionsHandler::DeviceRemoved(device::BluetoothAdapter* adapter, - device::BluetoothDevice* device) { - DCHECK(adapter == adapter_.get()); - DCHECK(device); - - // Invalidate the local cache if the pairing device is removed. - if (pairing_device_address_ == device->GetAddress()) { - pairing_device_address_.clear(); - pairing_device_entered_ = kInvalidEntered; - } - - base::StringValue address(device->GetAddress()); - web_ui()->CallJavascriptFunction( - "options.BrowserOptions.removeBluetoothDevice", - address); -} - -void BluetoothOptionsHandler::DeviceConnecting( - device::BluetoothDevice* device) { - DCHECK(device); - SendDeviceNotification(device, nullptr, kStartConnecting); -} - } // namespace options } // namespace chromeos
diff --git a/chrome/browser/ui/webui/options/chromeos/bluetooth_options_handler.h b/chrome/browser/ui/webui/options/chromeos/bluetooth_options_handler.h index b22b4d9..cd17609 100644 --- a/chrome/browser/ui/webui/options/chromeos/bluetooth_options_handler.h +++ b/chrome/browser/ui/webui/options/chromeos/bluetooth_options_handler.h
@@ -12,8 +12,6 @@ #include "base/memory/scoped_ptr.h" #include "base/memory/weak_ptr.h" #include "chrome/browser/ui/webui/options/options_ui.h" -#include "device/bluetooth/bluetooth_adapter.h" -#include "device/bluetooth/bluetooth_device.h" namespace base { class DictionaryValue; @@ -23,181 +21,15 @@ namespace options { // Handler for Bluetooth options on the system options page. -class BluetoothOptionsHandler - : public ::options::OptionsPageUIHandler, - public device::BluetoothAdapter::Observer, - public device::BluetoothDevice::PairingDelegate { +class BluetoothOptionsHandler : public ::options::OptionsPageUIHandler { public: BluetoothOptionsHandler(); ~BluetoothOptionsHandler() override; // OptionsPageUIHandler implementation. void GetLocalizedValues(base::DictionaryValue* localized_strings) override; - void RegisterMessages() override; - void InitializeHandler() override; - void InitializePage() override; - - void InitializeAdapter(scoped_refptr<device::BluetoothAdapter> adapter); - - // Sends a notification to the Web UI of the status of a Bluetooth device. - // |device| is the Bluetooth device. - // |params| is an optional set of parameters. - // |pairing| is an optional pairing command. - void SendDeviceNotification(const device::BluetoothDevice* device, - base::DictionaryValue* params, - std::string pairing); - - // device::BluetoothDevice::PairingDelegate override. - // - // This method will be called when the Bluetooth daemon requires a - // PIN Code for authentication of the device |device|, the UI will display - // a blank entry form to obtain the PIN code from the user. - // - // PIN Codes are generally required for Bluetooth 2.0 and earlier devices - // for which there is no automatic pairing or special handling. - void RequestPinCode(device::BluetoothDevice* device) override; - - // device::BluetoothDevice::PairingDelegate override. - // - // This method will be called when the Bluetooth daemon requires a - // Passkey for authentication of the device |device|, the UI will display - // a blank entry form to obtain the passkey from the user (a numeric in the - // range 0-999999). - // - // Passkeys are generally required for Bluetooth 2.1 and later devices - // which cannot provide input or display on their own, and don't accept - // passkey-less pairing. - void RequestPasskey(device::BluetoothDevice* device) override; - - // device::BluetoothDevice::PairingDelegate override. - // - // This method will be called when the Bluetooth daemon requires that the - // user enter the PIN code |pincode| into the device |device| so that it - // may be authenticated, the UI will display the PIN code with accompanying - // instructions. - // - // This is used for Bluetooth 2.0 and earlier keyboard devices, the - // |pincode| will always be a six-digit numeric in the range 000000-999999 - // for compatibilty with later specifications. - void DisplayPinCode(device::BluetoothDevice* device, - const std::string& pincode) override; - - // device::BluetoothDevice::PairingDelegate override. - // - // This method will be called when the Bluetooth daemon requires that the - // user enter the Passkey |passkey| into the device |device| so that it - // may be authenticated, the UI will display the passkey with accompanying - // instructions. - // - // This is used for Bluetooth 2.1 and later devices that support input - // but not display, such as keyboards. The Passkey is a numeric in the - // range 0-999999 and should be always presented zero-padded to six - // digits. - void DisplayPasskey(device::BluetoothDevice* device, uint32 passkey) override; - - // device::BluetoothDevice::PairingDelegate override. - // - // This method will be called when the Bluetooth daemon gets a notification - // of a key entered on the device |device| while pairing with the device - // using a PIN code or a Passkey. - // - // The UI will show a visual indication that a given key was pressed in the - // same pairing overlay where the PIN code or Passkey is displayed. - // - // A first call with |entered| as 0 will indicate that this notification - // mechanism is supported by the device allowing the UI to display this fact. - // A last call with |entered| as the length of the key plus one will indicate - // that the [enter] key was pressed. - void KeysEntered(device::BluetoothDevice* device, uint32 entered) override; - - // device::BluetoothDevice::PairingDelegate override. - // - // This method will be called when the Bluetooth daemon requires that the - // user confirm that the Passkey |passkey| is displayed on the screen - // of the device |device| so that it may be authenticated, the UI will - // display the passkey with accompanying instructions. - // - // This is used for Bluetooth 2.1 and later devices that support display, - // such as other computers or phones. The Passkey is a numeric in the - // range 0-999999 and should be always present zero-padded to six - // digits. - void ConfirmPasskey(device::BluetoothDevice* device, uint32 passkey) override; - - // device::BluetoothDevice::PairingDelegate override. - void AuthorizePairing(device::BluetoothDevice* device) override; - - // Displays a Bluetooth error. - // |error| maps to a localized resource for the error message. - // |address| is the address of the Bluetooth device. May be an empty - // string if the error is not specific to a single device. - void ReportError(const std::string& error, const std::string& address); - - // device::BluetoothAdapter::Observer implementation. - void AdapterPresentChanged(device::BluetoothAdapter* adapter, - bool present) override; - void AdapterPoweredChanged(device::BluetoothAdapter* adapter, - bool powered) override; - void AdapterDiscoveringChanged(device::BluetoothAdapter* adapter, - bool discovering) override; - void DeviceAdded(device::BluetoothAdapter* adapter, - device::BluetoothDevice* device) override; - void DeviceChanged(device::BluetoothAdapter* adapter, - device::BluetoothDevice* device) override; - void DeviceRemoved(device::BluetoothAdapter* adapter, - device::BluetoothDevice* device) override; private: - // Displays in the UI a connecting to the device |device| message. - void DeviceConnecting(device::BluetoothDevice* device); - - // Called by device::BluetoothAdapter in response to a failure to - // change the power status of the adapter. - void EnableChangeError(); - - // Called by device::BluetoothDevice on a successful pairing and connection - // to a device. - void Connected(); - - // Called by device::BluetoothDevice in response to a failure to - // connect to the device with bluetooth address |address| due to an error - // encoded in |error_code|. - void ConnectError(const std::string& address, - device::BluetoothDevice::ConnectErrorCode error_code); - - // Called by device::BluetoothDevice in response to a failure to - // disconnect the device with bluetooth address |address|. - void DisconnectError(const std::string& address); - - // Called by device::BluetoothDevice in response to a failure to - // disconnect and unpair the device with bluetooth address |address|. - void ForgetError(const std::string& address); - - // Called when the user requests to connect to or disconnect from a Bluetooth - // device. - // |args| will be a list containing two or three arguments, the first argument - // is the device ID and the second is the requested action. If a third - // argument is present, it is the passkey for pairing confirmation. - void UpdateDeviceCallback(const base::ListValue* args); - - // Called when the list of paired devices is initialized in order to - // populate the list. - // |args| will be an empty list. - void GetPairedDevicesCallback(const base::ListValue* args); - - // Default bluetooth adapter, used for all operations. - scoped_refptr<device::BluetoothAdapter> adapter_; - - // Cached information about the current pairing device, if any. - std::string pairing_device_address_; - std::string pairing_device_pairing_; - std::string pairing_device_pincode_; - int pairing_device_passkey_; - int pairing_device_entered_; - - // Weak pointer factory for generating 'this' pointers that might live longer - // than this object does. - base::WeakPtrFactory<BluetoothOptionsHandler> weak_ptr_factory_; - DISALLOW_COPY_AND_ASSIGN(BluetoothOptionsHandler); };
diff --git a/chrome/browser/ui/webui/options/options_browsertest.js b/chrome/browser/ui/webui/options/options_browsertest.js index d2c068a..895928a 100644 --- a/chrome/browser/ui/webui/options/options_browsertest.js +++ b/chrome/browser/ui/webui/options/options_browsertest.js
@@ -194,7 +194,7 @@ window.setTimeout(function() { assertFalse(dntOverlay.visible); assertEquals(confirmInterstitial, dntCheckbox.checked); - dntOverlay.removeEventListener(visibleChangeHandler); + dntOverlay.removeEventListener('visibleChange', visibleChangeHandler); testDone(); }, 0); break; @@ -247,7 +247,7 @@ window.setTimeout(function() { assertFalse(dntOverlay.visible); assertTrue(dntCheckbox.checked); - dntOverlay.removeEventListener(visibleChangeHandler); + dntOverlay.removeEventListener('visibleChange', visibleChangeHandler); dntCheckbox.click(); }, 0); break;
diff --git a/chrome/browser/web_applications/web_app.h b/chrome/browser/web_applications/web_app.h index fee38de2..1bf4bbb 100644 --- a/chrome/browser/web_applications/web_app.h +++ b/chrome/browser/web_applications/web_app.h
@@ -78,7 +78,7 @@ enum ApplicationsMenuLocation { APP_MENU_LOCATION_NONE, APP_MENU_LOCATION_ROOT, - APP_MENU_LOCATION_SUBDIR_CHROME, + APP_MENU_LOCATION_SUBDIR_CHROME_DEPRECATED, // TODO(bcwhite) remove this APP_MENU_LOCATION_SUBDIR_CHROMEAPPS, APP_MENU_LOCATION_HIDDEN, };
diff --git a/chrome/browser/web_applications/web_app_win.cc b/chrome/browser/web_applications/web_app_win.cc index a5078b0..18772be 100644 --- a/chrome/browser/web_applications/web_app_win.cc +++ b/chrome/browser/web_applications/web_app_win.cc
@@ -573,8 +573,8 @@ ShellUtil::SHORTCUT_LOCATION_START_MENU_ROOT }, { creation_locations.applications_menu_location == - APP_MENU_LOCATION_SUBDIR_CHROME, - ShellUtil::SHORTCUT_LOCATION_START_MENU_CHROME_DIR + APP_MENU_LOCATION_SUBDIR_CHROME_DEPRECATED, + ShellUtil::SHORTCUT_LOCATION_START_MENU_CHROME_DIR_DEPRECATED }, { creation_locations.applications_menu_location == APP_MENU_LOCATION_SUBDIR_CHROMEAPPS,
diff --git a/chrome/chrome_browser_ui.gypi b/chrome/chrome_browser_ui.gypi index 74b9599..a67359c0 100644 --- a/chrome/chrome_browser_ui.gypi +++ b/chrome/chrome_browser_ui.gypi
@@ -52,6 +52,7 @@ 'browser/ui/autofill/password_generation_popup_view.h', 'browser/ui/autofill/popup_controller_common.cc', 'browser/ui/autofill/popup_controller_common.h', + 'browser/ui/autofill/save_card_bubble_controller.cc', 'browser/ui/autofill/save_card_bubble_controller.h', 'browser/ui/autofill/save_card_bubble_controller_impl.cc', 'browser/ui/autofill/save_card_bubble_controller_impl.h', @@ -642,8 +643,10 @@ 'browser/ui/views/frame/browser_header_painter_ash.h', 'browser/ui/views/frame/browser_non_client_frame_view_ash.cc', 'browser/ui/views/frame/browser_non_client_frame_view_ash.h', + 'browser/ui/views/frame/browser_non_client_frame_view_factory_ash.cc', 'browser/ui/views/frame/immersive_mode_controller_ash.cc', 'browser/ui/views/frame/immersive_mode_controller_ash.h', + 'browser/ui/views/frame/immersive_mode_controller_factory_ash.cc', 'browser/ui/views/frame/web_app_left_header_view_ash.cc', 'browser/ui/views/frame/web_app_left_header_view_ash.h', 'browser/ui/views/tabs/window_finder_ash.cc', @@ -2204,7 +2207,7 @@ 'browser/ui/views/frame/browser_frame_mac.mm', 'browser/ui/views/frame/browser_non_client_frame_view.cc', 'browser/ui/views/frame/browser_non_client_frame_view.h', - 'browser/ui/views/frame/browser_non_client_frame_view_factory_aura.cc', + 'browser/ui/views/frame/browser_non_client_frame_view_factory_android.cc', 'browser/ui/views/frame/browser_non_client_frame_view_factory_mac.mm', 'browser/ui/views/frame/browser_non_client_frame_view_mac.h', 'browser/ui/views/frame/browser_non_client_frame_view_mac.mm', @@ -2226,7 +2229,7 @@ 'browser/ui/views/frame/contents_web_view.h', 'browser/ui/views/frame/immersive_mode_controller.cc', 'browser/ui/views/frame/immersive_mode_controller.h', - 'browser/ui/views/frame/immersive_mode_controller_factory_ash.cc', + 'browser/ui/views/frame/immersive_mode_controller_factory_android.cc', 'browser/ui/views/frame/immersive_mode_controller_factory_mac.cc', 'browser/ui/views/frame/immersive_mode_controller_stub.cc', 'browser/ui/views/frame/immersive_mode_controller_stub.h',
diff --git a/chrome/chrome_repack_locales.gni b/chrome/chrome_repack_locales.gni index 47a431d6..71469b09 100644 --- a/chrome/chrome_repack_locales.gni +++ b/chrome/chrome_repack_locales.gni
@@ -66,8 +66,8 @@ deps += [ "//content/app/strings", "//device/bluetooth/strings", - "//ui/strings:ui_strings", "//ui/strings:app_locale_settings", + "//ui/strings:ui_strings", ] } if (enable_autofill_dialog) {
diff --git a/chrome/chrome_tests_unit.gypi b/chrome/chrome_tests_unit.gypi index 5f6d09a..09073989 100644 --- a/chrome/chrome_tests_unit.gypi +++ b/chrome/chrome_tests_unit.gypi
@@ -541,6 +541,7 @@ 'chrome_unit_tests_non_mobile_sources': [ 'browser/renderer_context_menu/render_view_context_menu_test_util.cc', 'browser/renderer_context_menu/render_view_context_menu_test_util.h', + 'browser/ui/autofill/save_card_bubble_controller_impl_unittest.cc', 'browser/ui/website_settings/mock_permission_bubble_view.cc', 'browser/ui/website_settings/mock_permission_bubble_view.h', ],
diff --git a/chrome/chrome_watcher/BUILD.gn b/chrome/chrome_watcher/BUILD.gn index e6398616..efd9155 100644 --- a/chrome/chrome_watcher/BUILD.gn +++ b/chrome/chrome_watcher/BUILD.gn
@@ -32,9 +32,9 @@ deps = [ ":chrome_watcher_resources", ":client", - "//chrome/installer/util", "//base", "//build/config/sanitizers:deps", + "//chrome/installer/util", "//components/browser_watcher", ] ldflags = [ "/DEF:" + rebase_path("chrome_watcher.def", root_build_dir) ]
diff --git a/chrome/common/BUILD.gn b/chrome/common/BUILD.gn index 01e134cb..21cf8d8 100644 --- a/chrome/common/BUILD.gn +++ b/chrome/common/BUILD.gn
@@ -48,9 +48,9 @@ public_deps = [ "//base:base", + "//base:base_static", "//base:i18n", "//base:prefs", - "//base:base_static", "//chrome:resources", "//chrome:strings", "//chrome/app/theme:theme_resources", @@ -112,16 +112,16 @@ public_deps += [ ":mojo_bindings", "//chrome/common/net", - "//components/visitedlink/common", "//components/autofill/content/common", "//components/autofill/core/common", "//components/password_manager/content/common", "//components/password_manager/core/common", "//components/signin/core/common", "//components/translate/content/common", + "//components/visitedlink/common", + "//ipc", "//media", "//mojo/public/cpp/bindings", - "//ipc", "//third_party/re2", "//third_party/widevine/cdm:version_h", ] @@ -132,11 +132,11 @@ ".", "//chrome") public_deps += [ - "//device/usb", "//chrome/common/extensions/api", + "//device/usb", + "//extensions:extensions_resources", "//extensions/common", "//extensions/common/api", - "//extensions:extensions_resources", "//extensions/strings", "//media/cast:net", ] @@ -238,8 +238,8 @@ if (is_mac) { sources -= [ "channel_info_posix.cc" ] public_deps += [ - "//third_party/mach_override", "//third_party/google_toolbox_for_mac", + "//third_party/mach_override", ] }
diff --git a/chrome/common/safe_browsing/csd.proto b/chrome/common/safe_browsing/csd.proto index 9c9f8de..8d5c589 100644 --- a/chrome/common/safe_browsing/csd.proto +++ b/chrome/common/safe_browsing/csd.proto
@@ -520,6 +520,8 @@ } repeated RegistryKey registry_key = 3; + + optional bool is_enrolled_to_domain = 4; } optional OS os = 1; message Machine {
diff --git a/chrome/installer/gcapi/BUILD.gn b/chrome/installer/gcapi/BUILD.gn index 611ba992..40791d65 100644 --- a/chrome/installer/gcapi/BUILD.gn +++ b/chrome/installer/gcapi/BUILD.gn
@@ -32,8 +32,8 @@ deps = [ "//base", - "//chrome/installer/util", "//chrome/installer/launcher_support", + "//chrome/installer/util", "//components/variations", "//google_update", ]
diff --git a/chrome/installer/setup/install.cc b/chrome/installer/setup/install.cc index 3bd2a05..8b83bef 100644 --- a/chrome/installer/setup/install.cc +++ b/chrome/installer/setup/install.cc
@@ -69,7 +69,10 @@ case ShellUtil::SHORTCUT_LOCATION_QUICK_LAUNCH: message.append("Quick Launch "); break; - case ShellUtil::SHORTCUT_LOCATION_START_MENU_CHROME_DIR: + case ShellUtil::SHORTCUT_LOCATION_START_MENU_ROOT: + message.append("Start menu "); + break; + case ShellUtil::SHORTCUT_LOCATION_START_MENU_CHROME_DIR_DEPRECATED: message.append("Start menu/" + base::UTF16ToUTF8(dist->GetStartMenuShortcutSubfolder( BrowserDistribution::SUBFOLDER_CHROME)) + @@ -420,8 +423,24 @@ ShellUtil::SHELL_SHORTCUT_CREATE_IF_NO_SYSTEM_LEVEL) { start_menu_properties.set_pin_to_taskbar(!do_not_create_taskbar_shortcut); } + + // The attempt below to update the stortcut will fail if it does not already + // exist at the expected location on disk. First check if it exists in the + // previous location (under a subdirectory) and, if so, move it to the new + // location. + base::FilePath old_shortcut_path; + ShellUtil::GetShortcutPath( + ShellUtil::SHORTCUT_LOCATION_START_MENU_CHROME_DIR_DEPRECATED, dist, + shortcut_level, &old_shortcut_path); + if (base::PathExists(old_shortcut_path)) { + ShellUtil::MoveExistingShortcut( + ShellUtil::SHORTCUT_LOCATION_START_MENU_CHROME_DIR_DEPRECATED, + ShellUtil::SHORTCUT_LOCATION_START_MENU_ROOT, + dist, start_menu_properties); + } + ExecuteAndLogShortcutOperation( - ShellUtil::SHORTCUT_LOCATION_START_MENU_CHROME_DIR, dist, + ShellUtil::SHORTCUT_LOCATION_START_MENU_ROOT, dist, start_menu_properties, shortcut_operation); }
diff --git a/chrome/installer/setup/install_unittest.cc b/chrome/installer/setup/install_unittest.cc index e6faeb4..cfbca40 100644 --- a/chrome/installer/setup/install_unittest.cc +++ b/chrome/installer/setup/install_unittest.cc
@@ -125,18 +125,21 @@ fake_user_desktop_.path().Append(shortcut_name); user_quick_launch_shortcut_ = fake_user_quick_launch_.path().Append(shortcut_name); - user_start_menu_shortcut_ = - fake_start_menu_.path().Append( - dist_->GetStartMenuShortcutSubfolder( + user_start_menu_shortcut_ = fake_start_menu_.path().Append(shortcut_name); + user_start_menu_subdir_shortcut_ = + fake_start_menu_.path() + .Append(dist_->GetStartMenuShortcutSubfolder( BrowserDistribution::SUBFOLDER_CHROME)) - .Append(shortcut_name); + .Append(shortcut_name); system_desktop_shortcut_ = fake_common_desktop_.path().Append(shortcut_name); system_start_menu_shortcut_ = - fake_common_start_menu_.path().Append( - dist_->GetStartMenuShortcutSubfolder( + fake_common_start_menu_.path().Append(shortcut_name); + system_start_menu_subdir_shortcut_ = + fake_common_start_menu_.path() + .Append(dist_->GetStartMenuShortcutSubfolder( BrowserDistribution::SUBFOLDER_CHROME)) - .Append(shortcut_name); + .Append(shortcut_name); user_alternate_desktop_shortcut_ = fake_user_desktop_.path().Append(alternate_shortcut_name); } @@ -145,7 +148,9 @@ // Try to unpin potentially pinned shortcuts (although pinning isn't tested, // the call itself might still have pinned the Start Menu shortcuts). base::win::UnpinShortcutFromTaskbar(user_start_menu_shortcut_); + base::win::UnpinShortcutFromTaskbar(user_start_menu_subdir_shortcut_); base::win::UnpinShortcutFromTaskbar(system_start_menu_shortcut_); + base::win::UnpinShortcutFromTaskbar(system_start_menu_subdir_shortcut_); CoUninitialize(); } @@ -200,8 +205,10 @@ base::FilePath user_desktop_shortcut_; base::FilePath user_quick_launch_shortcut_; base::FilePath user_start_menu_shortcut_; + base::FilePath user_start_menu_subdir_shortcut_; base::FilePath system_desktop_shortcut_; base::FilePath system_start_menu_shortcut_; + base::FilePath system_start_menu_subdir_shortcut_; base::FilePath user_alternate_desktop_shortcut_; }; @@ -355,6 +362,69 @@ ASSERT_FALSE(base::PathExists(user_start_menu_shortcut_)); } +class MigrateShortcutTest : public InstallShortcutTest, + public testing::WithParamInterface< + testing::tuple< + installer::InstallShortcutOperation, + installer::InstallShortcutLevel>> { + public: + MigrateShortcutTest() : shortcut_operation_(testing::get<0>(GetParam())), + shortcut_level_(testing::get<1>(GetParam())) {} + + protected: + const installer::InstallShortcutOperation shortcut_operation_; + const installer::InstallShortcutLevel shortcut_level_; + + private: + DISALLOW_COPY_AND_ASSIGN(MigrateShortcutTest); +}; + +TEST_P(MigrateShortcutTest, MigrateAwayFromDeprecatedStartMenuTest) { + base::win::ShortcutProperties dummy_properties; + base::FilePath dummy_target; + ASSERT_TRUE(base::CreateTemporaryFileInDir(temp_dir_.path(), &dummy_target)); + dummy_properties.set_target(expected_properties_.target); + dummy_properties.set_working_dir(fake_user_desktop_.path()); + dummy_properties.set_arguments(L"--dummy --args"); + dummy_properties.set_app_id(L"El.Dummiest"); + + base::FilePath start_menu_shortcut; + base::FilePath start_menu_subdir_shortcut; + if (shortcut_level_ == installer::CURRENT_USER) { + start_menu_shortcut = user_start_menu_shortcut_; + start_menu_subdir_shortcut = user_start_menu_subdir_shortcut_; + } else { + start_menu_shortcut = system_start_menu_shortcut_; + start_menu_subdir_shortcut = system_start_menu_subdir_shortcut_; + } + + ASSERT_TRUE(base::CreateDirectory(start_menu_subdir_shortcut.DirName())); + ASSERT_FALSE(base::PathExists(start_menu_subdir_shortcut)); + ASSERT_TRUE(base::win::CreateOrUpdateShortcutLink( + start_menu_subdir_shortcut, dummy_properties, + base::win::SHORTCUT_CREATE_ALWAYS)); + ASSERT_TRUE(base::PathExists(start_menu_subdir_shortcut)); + ASSERT_FALSE(base::PathExists(start_menu_shortcut)); + + installer::CreateOrUpdateShortcuts(chrome_exe_, *product_, *prefs_, + shortcut_level_, shortcut_operation_); + ASSERT_FALSE(base::PathExists(start_menu_subdir_shortcut)); + ASSERT_TRUE(base::PathExists(start_menu_shortcut)); +} + +// Verify that any installer operation for any installation level triggers +// the migration from sub-folder to root of start-menu. +INSTANTIATE_TEST_CASE_P( + MigrateShortcutTests, MigrateShortcutTest, + testing::Combine( + testing::Values( + installer::INSTALL_SHORTCUT_REPLACE_EXISTING, + installer::INSTALL_SHORTCUT_CREATE_EACH_IF_NO_SYSTEM_LEVEL, + installer::INSTALL_SHORTCUT_CREATE_ALL), + testing::Values( + installer::CURRENT_USER, + installer::ALL_USERS))); + TEST_F(InstallShortcutTest, CreateIfNoSystemLevelAllSystemShortcutsExist) { base::win::ShortcutProperties dummy_properties; base::FilePath dummy_target;
diff --git a/chrome/installer/setup/setup_main.cc b/chrome/installer/setup/setup_main.cc index 286695b..91a6cce 100644 --- a/chrome/installer/setup/setup_main.cc +++ b/chrome/installer/setup/setup_main.cc
@@ -982,7 +982,7 @@ shortcut_properties.set_dual_mode(true); shortcut_properties.set_pin_to_taskbar(true); ShellUtil::CreateOrUpdateShortcut( - ShellUtil::SHORTCUT_LOCATION_START_MENU_CHROME_DIR, chrome_dist, + ShellUtil::SHORTCUT_LOCATION_START_MENU_ROOT, chrome_dist, shortcut_properties, ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS); // Register Chrome at user-level and make it default.
diff --git a/chrome/installer/test/BUILD.gn b/chrome/installer/test/BUILD.gn index 2f5dfc2..53df9b4e 100644 --- a/chrome/installer/test/BUILD.gn +++ b/chrome/installer/test/BUILD.gn
@@ -38,8 +38,8 @@ deps = [ "//base", "//base:base_static", - "//chrome/installer/util", "//chrome/common:constants", + "//chrome/installer/util", ] }
diff --git a/chrome/installer/util/shell_util.cc b/chrome/installer/util/shell_util.cc index 4b6b74c..f867dde 100644 --- a/chrome/installer/util/shell_util.cc +++ b/chrome/installer/util/shell_util.cc
@@ -1537,7 +1537,8 @@ BrowserDistribution* dist, ShellUtil::ShellChange level) { // Explicitly whitelist locations, since accidental calls can be very harmful. - if (location != ShellUtil::SHORTCUT_LOCATION_START_MENU_CHROME_DIR && + if (location != + ShellUtil::SHORTCUT_LOCATION_START_MENU_CHROME_DIR_DEPRECATED && location != ShellUtil::SHORTCUT_LOCATION_START_MENU_CHROME_APPS_DIR && location != ShellUtil::SHORTCUT_LOCATION_APP_SHORTCUTS) { NOTREACHED(); @@ -1616,13 +1617,12 @@ CONFIRM_SHELL_REGISTRATION_IN_HKLM); } -bool ShellUtil::ShortcutLocationIsSupported( - ShellUtil::ShortcutLocation location) { +bool ShellUtil::ShortcutLocationIsSupported(ShortcutLocation location) { switch (location) { case SHORTCUT_LOCATION_DESKTOP: // Falls through. case SHORTCUT_LOCATION_QUICK_LAUNCH: // Falls through. case SHORTCUT_LOCATION_START_MENU_ROOT: // Falls through. - case SHORTCUT_LOCATION_START_MENU_CHROME_DIR: // Falls through. + case SHORTCUT_LOCATION_START_MENU_CHROME_DIR_DEPRECATED: // Falls through. case SHORTCUT_LOCATION_START_MENU_CHROME_APPS_DIR: return true; case SHORTCUT_LOCATION_TASKBAR_PINS: @@ -1635,7 +1635,7 @@ } } -bool ShellUtil::GetShortcutPath(ShellUtil::ShortcutLocation location, +bool ShellUtil::GetShortcutPath(ShortcutLocation location, BrowserDistribution* dist, ShellChange level, base::FilePath* path) { @@ -1656,7 +1656,7 @@ dir_key = (level == CURRENT_USER) ? base::DIR_START_MENU : base::DIR_COMMON_START_MENU; break; - case SHORTCUT_LOCATION_START_MENU_CHROME_DIR: + case SHORTCUT_LOCATION_START_MENU_CHROME_DIR_DEPRECATED: dir_key = (level == CURRENT_USER) ? base::DIR_START_MENU : base::DIR_COMMON_START_MENU; folder_to_append = dist->GetStartMenuShortcutSubfolder( @@ -1691,16 +1691,42 @@ return true; } +bool ShellUtil::MoveExistingShortcut(ShortcutLocation old_location, + ShortcutLocation new_location, + BrowserDistribution* dist, + const ShortcutProperties& properties) { + // Explicitly whitelist locations to which this is applicable. + if (old_location != SHORTCUT_LOCATION_START_MENU_CHROME_DIR_DEPRECATED || + new_location != SHORTCUT_LOCATION_START_MENU_ROOT) { + NOTREACHED(); + return false; + } + + base::string16 shortcut_name( + ExtractShortcutNameFromProperties(dist, properties)); + + base::FilePath old_shortcut_path; + base::FilePath new_shortcut_path; + GetShortcutPath(old_location, dist, properties.level, &old_shortcut_path); + GetShortcutPath(new_location, dist, properties.level, &new_shortcut_path); + old_shortcut_path = old_shortcut_path.Append(shortcut_name); + new_shortcut_path = new_shortcut_path.Append(shortcut_name); + + bool result = base::Move(old_shortcut_path, new_shortcut_path); + RemoveShortcutFolderIfEmpty(old_location, dist, properties.level); + return result; +} + bool ShellUtil::CreateOrUpdateShortcut( - ShellUtil::ShortcutLocation location, + ShortcutLocation location, BrowserDistribution* dist, - const ShellUtil::ShortcutProperties& properties, - ShellUtil::ShortcutOperation operation) { + const ShortcutProperties& properties, + ShortcutOperation operation) { // Explicitly whitelist locations to which this is applicable. if (location != SHORTCUT_LOCATION_DESKTOP && location != SHORTCUT_LOCATION_QUICK_LAUNCH && location != SHORTCUT_LOCATION_START_MENU_ROOT && - location != SHORTCUT_LOCATION_START_MENU_CHROME_DIR && + location != SHORTCUT_LOCATION_START_MENU_CHROME_DIR_DEPRECATED && location != SHORTCUT_LOCATION_START_MENU_CHROME_APPS_DIR) { NOTREACHED(); return false; @@ -1809,7 +1835,7 @@ DCHECK(dist); DCHECK(browsers); - const base::string16 base_key(ShellUtil::kRegStartMenuInternet); + const base::string16 base_key(kRegStartMenuInternet); base::string16 client_path; RegKey key; base::string16 name; @@ -1949,7 +1975,7 @@ base::FilePath app_path; if (!PathService::Get(base::FILE_EXE, &app_path)) { NOTREACHED(); - return ShellUtil::UNKNOWN_DEFAULT; + return UNKNOWN_DEFAULT; } return GetChromeDefaultStateFromPath(app_path); @@ -1992,7 +2018,7 @@ base::FilePath chrome_exe; if (!PathService::Get(base::FILE_EXE, &chrome_exe)) { NOTREACHED(); - return ShellUtil::UNKNOWN_DEFAULT; + return UNKNOWN_DEFAULT; } const wchar_t* const protocols[] = { protocol.c_str() }; @@ -2010,7 +2036,7 @@ int shell_change, const base::FilePath& chrome_exe, bool elevate_if_not_admin) { - DCHECK(!(shell_change & ShellUtil::SYSTEM_LEVEL) || IsUserAnAdmin()); + DCHECK(!(shell_change & SYSTEM_LEVEL) || IsUserAnAdmin()); BrowserDistribution* distribution = BrowserDistribution::GetDistribution(); if (distribution->GetDefaultBrowserControlPolicy() != @@ -2025,7 +2051,7 @@ return false; } - if (!ShellUtil::RegisterChromeBrowser( + if (!RegisterChromeBrowser( dist, chrome_exe, base::string16(), elevate_if_not_admin)) { return false; } @@ -2043,24 +2069,24 @@ HRESULT hr = pAAR.CreateInstance(CLSID_ApplicationAssociationRegistration, NULL, CLSCTX_INPROC); if (SUCCEEDED(hr)) { - for (int i = 0; ShellUtil::kBrowserProtocolAssociations[i] != NULL; i++) { + for (int i = 0; kBrowserProtocolAssociations[i] != NULL; i++) { hr = pAAR->SetAppAsDefault(app_name.c_str(), - ShellUtil::kBrowserProtocolAssociations[i], AT_URLPROTOCOL); + kBrowserProtocolAssociations[i], AT_URLPROTOCOL); if (!SUCCEEDED(hr)) { ret = false; LOG(ERROR) << "Failed to register as default for protocol " - << ShellUtil::kBrowserProtocolAssociations[i] + << kBrowserProtocolAssociations[i] << " (" << hr << ")"; } } - for (int i = 0; ShellUtil::kDefaultFileAssociations[i] != NULL; i++) { + for (int i = 0; kDefaultFileAssociations[i] != NULL; i++) { hr = pAAR->SetAppAsDefault(app_name.c_str(), - ShellUtil::kDefaultFileAssociations[i], AT_FILEEXTENSION); + kDefaultFileAssociations[i], AT_FILEEXTENSION); if (!SUCCEEDED(hr)) { ret = false; LOG(ERROR) << "Failed to register as default for file extension " - << ShellUtil::kDefaultFileAssociations[i] + << kDefaultFileAssociations[i] << " (" << hr << ")"; } } @@ -2343,11 +2369,11 @@ } // static -bool ShellUtil::RemoveShortcuts(ShellUtil::ShortcutLocation location, +bool ShellUtil::RemoveShortcuts(ShortcutLocation location, BrowserDistribution* dist, ShellChange level, const base::FilePath& target_exe) { - if (!ShellUtil::ShortcutLocationIsSupported(location)) + if (!ShortcutLocationIsSupported(location)) return true; // Vacuous success. FilterTargetEq shortcut_filter(target_exe, false); @@ -2361,7 +2387,7 @@ NULL); // Remove chrome-specific shortcut folders if they are now empty. if (success && - (location == SHORTCUT_LOCATION_START_MENU_CHROME_DIR || + (location == SHORTCUT_LOCATION_START_MENU_CHROME_DIR_DEPRECATED || location == SHORTCUT_LOCATION_START_MENU_CHROME_APPS_DIR || location == SHORTCUT_LOCATION_APP_SHORTCUTS)) { success = RemoveShortcutFolderIfEmpty(location, dist, level); @@ -2371,12 +2397,12 @@ // static bool ShellUtil::RetargetShortcutsWithArgs( - ShellUtil::ShortcutLocation location, + ShortcutLocation location, BrowserDistribution* dist, ShellChange level, const base::FilePath& old_target_exe, const base::FilePath& new_target_exe) { - if (!ShellUtil::ShortcutLocationIsSupported(location)) + if (!ShortcutLocationIsSupported(location)) return true; // Vacuous success. FilterTargetEq shortcut_filter(old_target_exe, true); @@ -2388,14 +2414,14 @@ // static bool ShellUtil::ShortcutListMaybeRemoveUnknownArgs( - ShellUtil::ShortcutLocation location, + ShortcutLocation location, BrowserDistribution* dist, ShellChange level, const base::FilePath& chrome_exe, bool do_removal, const scoped_refptr<SharedCancellationFlag>& cancel, std::vector<std::pair<base::FilePath, base::string16> >* shortcuts) { - if (!ShellUtil::ShortcutLocationIsSupported(location)) + if (!ShortcutLocationIsSupported(location)) return false; DCHECK(dist); FilterTargetEq shortcut_filter(chrome_exe, true); @@ -2517,7 +2543,7 @@ // static bool ShellUtil::DeleteFileAssociations(const base::string16& prog_id) { // Delete the key HKEY_CURRENT_USER\Software\Classes\PROGID. - base::string16 key_path(ShellUtil::kRegClasses); + base::string16 key_path(kRegClasses); key_path.push_back(base::FilePath::kSeparators[0]); key_path.append(prog_id); return InstallUtil::DeleteRegistryKey(
diff --git a/chrome/installer/util/shell_util.h b/chrome/installer/util/shell_util.h index f13e2bb..1c34c5d 100644 --- a/chrome/installer/util/shell_util.h +++ b/chrome/installer/util/shell_util.h
@@ -54,9 +54,9 @@ SHORTCUT_LOCATION_DESKTOP = SHORTCUT_LOCATION_FIRST, SHORTCUT_LOCATION_QUICK_LAUNCH, SHORTCUT_LOCATION_START_MENU_ROOT, - SHORTCUT_LOCATION_START_MENU_CHROME_DIR, + SHORTCUT_LOCATION_START_MENU_CHROME_DIR_DEPRECATED, // now placed in root SHORTCUT_LOCATION_START_MENU_CHROME_APPS_DIR, - SHORTCUT_LOCATION_TASKBAR_PINS, // base::win::VERSION_WIN7 + + SHORTCUT_LOCATION_TASKBAR_PINS, // base::win::VERSION_WIN7 + SHORTCUT_LOCATION_APP_SHORTCUTS, // base::win::VERSION_WIN8 + NUM_SHORTCUT_LOCATIONS }; @@ -311,17 +311,25 @@ // Returns true if the current Windows version supports the presence of // shortcuts at |location|. - static bool ShortcutLocationIsSupported(ShellUtil::ShortcutLocation location); + static bool ShortcutLocationIsSupported(ShortcutLocation location); // Sets |path| to the path for a shortcut at the |location| desired for the // given |level| (CURRENT_USER for per-user path and SYSTEM_LEVEL for // all-users path). // Returns false on failure. - static bool GetShortcutPath(ShellUtil::ShortcutLocation location, + static bool GetShortcutPath(ShortcutLocation location, BrowserDistribution* dist, ShellChange level, base::FilePath* path); + // Move an existing shortcut from |old_location| to |new_location| for the + // set |shortcut_level|. If the folder containing |old_location| is then + // empty, it will be removed. + static bool MoveExistingShortcut(ShortcutLocation old_location, + ShortcutLocation new_location, + BrowserDistribution* dist, + const ShortcutProperties& properties); + // Updates shortcut in |location| (or creates it if |options| specify // SHELL_SHORTCUT_CREATE_ALWAYS). // |dist| gives the type of browser distribution currently in use. @@ -332,10 +340,10 @@ // SHORTCUT_LOCATION_START_MENU_CHROME_DIR, or // SHORTCUT_LOCATION_START_MENU_CHROME_APPS_DIR. static bool CreateOrUpdateShortcut( - ShellUtil::ShortcutLocation location, + ShortcutLocation location, BrowserDistribution* dist, - const ShellUtil::ShortcutProperties& properties, - ShellUtil::ShortcutOperation operation); + const ShortcutProperties& properties, + ShortcutOperation operation); // Returns the string "|icon_path|,|icon_index|" (see, for example, // http://msdn.microsoft.com/library/windows/desktop/dd391573.aspx). @@ -543,7 +551,7 @@ // If |location| is a Chrome-specific folder, it will be deleted as well. // Returns true if all shortcuts pointing to |target_exe| are successfully // deleted, including the case where no such shortcuts are found. - static bool RemoveShortcuts(ShellUtil::ShortcutLocation location, + static bool RemoveShortcuts(ShortcutLocation location, BrowserDistribution* dist, ShellChange level, const base::FilePath& target_exe); @@ -557,7 +565,7 @@ // Returns true if all updates to matching shortcuts are successful, including // the vacuous case where no matching shortcuts are found. static bool RetargetShortcutsWithArgs( - ShellUtil::ShortcutLocation location, + ShortcutLocation location, BrowserDistribution* dist, ShellChange level, const base::FilePath& old_target_exe, @@ -570,7 +578,7 @@ // those shortcuts. This method will abort and return false if |cancel| is // non-NULL and gets set at any point during this call. static bool ShortcutListMaybeRemoveUnknownArgs( - ShellUtil::ShortcutLocation location, + ShortcutLocation location, BrowserDistribution* dist, ShellChange level, const base::FilePath& chrome_exe,
diff --git a/chrome/installer/util/shell_util_unittest.cc b/chrome/installer/util/shell_util_unittest.cc index 3b97dd0..e581064 100644 --- a/chrome/installer/util/shell_util_unittest.cc +++ b/chrome/installer/util/shell_util_unittest.cc
@@ -117,7 +117,11 @@ case ShellUtil::SHORTCUT_LOCATION_QUICK_LAUNCH: expected_path = fake_user_quick_launch_.path(); break; - case ShellUtil::SHORTCUT_LOCATION_START_MENU_CHROME_DIR: + case ShellUtil::SHORTCUT_LOCATION_START_MENU_ROOT: + expected_path = (properties.level == ShellUtil::CURRENT_USER) ? + fake_start_menu_.path() : fake_common_start_menu_.path(); + break; + case ShellUtil::SHORTCUT_LOCATION_START_MENU_CHROME_DIR_DEPRECATED: expected_path = (properties.level == ShellUtil::CURRENT_USER) ? fake_start_menu_.path() : fake_common_start_menu_.path(); expected_path = expected_path.Append( @@ -233,17 +237,50 @@ base::string16 start_menu_subfolder = dist_->GetStartMenuShortcutSubfolder( BrowserDistribution::SUBFOLDER_CHROME); - ShellUtil::GetShortcutPath(ShellUtil::SHORTCUT_LOCATION_START_MENU_CHROME_DIR, - dist_, ShellUtil::CURRENT_USER, &path); + ShellUtil::GetShortcutPath( + ShellUtil::SHORTCUT_LOCATION_START_MENU_CHROME_DIR_DEPRECATED, + dist_, ShellUtil::CURRENT_USER, &path); EXPECT_EQ(fake_start_menu_.path().Append(start_menu_subfolder), path); - ShellUtil::GetShortcutPath(ShellUtil::SHORTCUT_LOCATION_START_MENU_CHROME_DIR, - dist_, ShellUtil::SYSTEM_LEVEL, &path); + ShellUtil::GetShortcutPath( + ShellUtil::SHORTCUT_LOCATION_START_MENU_CHROME_DIR_DEPRECATED, + dist_, ShellUtil::SYSTEM_LEVEL, &path); EXPECT_EQ(fake_common_start_menu_.path().Append(start_menu_subfolder), path); } +TEST_F(ShellUtilShortcutTest, MoveExistingShortcut) { + test_properties_.set_shortcut_name(L"Bobo le shortcut"); + test_properties_.level = ShellUtil::SYSTEM_LEVEL; + base::FilePath old_shortcut_path(GetExpectedShortcutPath( + ShellUtil::SHORTCUT_LOCATION_START_MENU_CHROME_DIR_DEPRECATED, + dist_, test_properties_)); + + ASSERT_TRUE( + ShellUtil::CreateOrUpdateShortcut( + ShellUtil::SHORTCUT_LOCATION_START_MENU_CHROME_DIR_DEPRECATED, + dist_, test_properties_, + ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS)); + ValidateChromeShortcut( + ShellUtil::SHORTCUT_LOCATION_START_MENU_CHROME_DIR_DEPRECATED, + dist_, test_properties_); + ASSERT_TRUE(base::PathExists(old_shortcut_path.DirName())); + ASSERT_TRUE(base::PathExists(old_shortcut_path)); + + ASSERT_TRUE( + ShellUtil::MoveExistingShortcut( + ShellUtil::SHORTCUT_LOCATION_START_MENU_CHROME_DIR_DEPRECATED, + ShellUtil::SHORTCUT_LOCATION_START_MENU_ROOT, + dist_, test_properties_)); + + ValidateChromeShortcut( + ShellUtil::SHORTCUT_LOCATION_START_MENU_ROOT, + dist_, test_properties_); + ASSERT_FALSE(base::PathExists(old_shortcut_path)); + ASSERT_FALSE(base::PathExists(old_shortcut_path.DirName())); +} + TEST_F(ShellUtilShortcutTest, CreateChromeExeShortcutWithDefaultProperties) { ShellUtil::ShortcutProperties properties(ShellUtil::CURRENT_USER); product_->AddDefaultShortcutProperties(chrome_exe_, &properties); @@ -257,12 +294,14 @@ TEST_F(ShellUtilShortcutTest, CreateStartMenuShortcutWithAllProperties) { test_properties_.set_shortcut_name(L"Bobo le shortcut"); test_properties_.level = ShellUtil::SYSTEM_LEVEL; - ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut( - ShellUtil::SHORTCUT_LOCATION_START_MENU_CHROME_DIR, - dist_, test_properties_, - ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS)); - ValidateChromeShortcut(ShellUtil::SHORTCUT_LOCATION_START_MENU_CHROME_DIR, - dist_, test_properties_); + ASSERT_TRUE( + ShellUtil::CreateOrUpdateShortcut( + ShellUtil::SHORTCUT_LOCATION_START_MENU_CHROME_DIR_DEPRECATED, + dist_, test_properties_, + ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS)); + ValidateChromeShortcut( + ShellUtil::SHORTCUT_LOCATION_START_MENU_CHROME_DIR_DEPRECATED, + dist_, test_properties_); } TEST_F(ShellUtilShortcutTest, ReplaceSystemLevelDesktopShortcut) { @@ -317,21 +356,24 @@ TEST_F(ShellUtilShortcutTest, UpdateAddDualModeToStartMenuShortcut) { ShellUtil::ShortcutProperties properties(ShellUtil::CURRENT_USER); product_->AddDefaultShortcutProperties(chrome_exe_, &properties); - ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut( - ShellUtil::SHORTCUT_LOCATION_START_MENU_CHROME_DIR, dist_, - properties, ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS)); + ASSERT_TRUE( + ShellUtil::CreateOrUpdateShortcut( + ShellUtil::SHORTCUT_LOCATION_START_MENU_CHROME_DIR_DEPRECATED, dist_, + properties, ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS)); ShellUtil::ShortcutProperties added_properties(ShellUtil::CURRENT_USER); added_properties.set_dual_mode(true); - ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut( - ShellUtil::SHORTCUT_LOCATION_START_MENU_CHROME_DIR, dist_, - added_properties, ShellUtil::SHELL_SHORTCUT_UPDATE_EXISTING)); + ASSERT_TRUE( + ShellUtil::CreateOrUpdateShortcut( + ShellUtil::SHORTCUT_LOCATION_START_MENU_CHROME_DIR_DEPRECATED, dist_, + added_properties, ShellUtil::SHELL_SHORTCUT_UPDATE_EXISTING)); ShellUtil::ShortcutProperties expected_properties(properties); expected_properties.set_dual_mode(true); - ValidateChromeShortcut(ShellUtil::SHORTCUT_LOCATION_START_MENU_CHROME_DIR, - dist_, expected_properties); + ValidateChromeShortcut( + ShellUtil::SHORTCUT_LOCATION_START_MENU_CHROME_DIR_DEPRECATED, + dist_, expected_properties); } TEST_F(ShellUtilShortcutTest, CreateIfNoSystemLevel) { @@ -364,11 +406,12 @@ TEST_F(ShellUtilShortcutTest, CreateIfNoSystemLevelStartMenu) { ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut( - ShellUtil::SHORTCUT_LOCATION_START_MENU_CHROME_DIR, + ShellUtil::SHORTCUT_LOCATION_START_MENU_CHROME_DIR_DEPRECATED, dist_, test_properties_, ShellUtil::SHELL_SHORTCUT_CREATE_IF_NO_SYSTEM_LEVEL)); - ValidateChromeShortcut(ShellUtil::SHORTCUT_LOCATION_START_MENU_CHROME_DIR, - dist_, test_properties_); + ValidateChromeShortcut( + ShellUtil::SHORTCUT_LOCATION_START_MENU_CHROME_DIR_DEPRECATED, + dist_, test_properties_); } TEST_F(ShellUtilShortcutTest, CreateAlwaysUserWithSystemLevelPresent) { @@ -700,7 +743,7 @@ TEST_F(ShellUtilShortcutTest, CreateMultipleStartMenuShortcutsAndRemoveFolder) { ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut( - ShellUtil::SHORTCUT_LOCATION_START_MENU_CHROME_DIR, + ShellUtil::SHORTCUT_LOCATION_START_MENU_CHROME_DIR_DEPRECATED, dist_, test_properties_, ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS)); ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut( @@ -709,7 +752,7 @@ ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS)); test_properties_.set_shortcut_name(L"A second shortcut"); ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut( - ShellUtil::SHORTCUT_LOCATION_START_MENU_CHROME_DIR, + ShellUtil::SHORTCUT_LOCATION_START_MENU_CHROME_DIR_DEPRECATED, dist_, test_properties_, ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS)); ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut( @@ -743,7 +786,7 @@ ASSERT_TRUE(base::PathExists(chrome_shortcut_folder)); ASSERT_TRUE(ShellUtil::RemoveShortcuts( - ShellUtil::SHORTCUT_LOCATION_START_MENU_CHROME_DIR, dist_, + ShellUtil::SHORTCUT_LOCATION_START_MENU_CHROME_DIR_DEPRECATED, dist_, ShellUtil::CURRENT_USER, chrome_exe_)); ASSERT_FALSE(base::PathExists(chrome_shortcut_folder));
diff --git a/chrome/renderer/BUILD.gn b/chrome/renderer/BUILD.gn index 13b806d7..4ab9a7e8 100644 --- a/chrome/renderer/BUILD.gn +++ b/chrome/renderer/BUILD.gn
@@ -31,13 +31,13 @@ deps = [ "//base/allocator", - "//chrome/common", - "//chrome/common:mojo_bindings", "//chrome:resources", "//chrome:strings", + "//chrome/common", + "//chrome/common:mojo_bindings", "//components/autofill/content/renderer", - "//components/content_settings/content/common", "//components/cdm/renderer", + "//components/content_settings/content/common", "//components/data_reduction_proxy/content/common", "//components/data_reduction_proxy/core/common", "//components/dom_distiller/content:content_renderer",
diff --git a/chrome/service/BUILD.gn b/chrome/service/BUILD.gn index fa569695..bb741209 100644 --- a/chrome/service/BUILD.gn +++ b/chrome/service/BUILD.gn
@@ -51,9 +51,9 @@ configs += [ "//build/config/compiler:no_size_t_to_int_warning" ] deps = [ + "//base", "//chrome:strings", "//chrome/common", - "//base", "//components/cloud_devices/common", "//google_apis", "//jingle:notifier",
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index defc2a0b..88d7b73 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -118,10 +118,9 @@ "//components/sync_driver:test_support", "//components/sync_sessions:test_support", "//components/syncable_prefs:test_support", - "//components/update_client:test_support", "//components/ui/zoom:test_support", + "//components/update_client:test_support", "//content/public/app:both", - "//ui/gfx:test_support", "//net", "//net:test_support", "//skia", @@ -131,6 +130,7 @@ "//testing/gmock", "//testing/gtest", "//third_party/zlib", + "//ui/gfx:test_support", "//ui/message_center:test_support", ] @@ -140,11 +140,6 @@ "//chrome/plugin", "//chrome/renderer", "//chrome/utility", - "//content/public/child", - "//content/public/common", - "//content/public/plugin", - "//content/public/renderer", - "//content/public/utility", "//components/autofill/core/browser:test_support", "//components/captive_portal:test_support", "//components/guest_view/browser:test_support", @@ -152,6 +147,11 @@ "//components/sessions:test_support", "//components/user_manager:test_support", "//components/web_resource:test_support", + "//content/public/child", + "//content/public/common", + "//content/public/plugin", + "//content/public/renderer", + "//content/public/utility", "//google_apis:test_support", "//ipc:test_support", "//media:test_support", @@ -329,13 +329,13 @@ ":test_support", ":test_support_ui", "//base/allocator", + "//chrome:packed_extra_resources", + "//chrome:packed_resources", + "//chrome:resources", + "//chrome:strings", "//chrome/browser", "//chrome/browser/devtools", "//chrome/renderer", - "//chrome:resources", - "//chrome:strings", - "//chrome:packed_extra_resources", - "//chrome:packed_resources", "//components/resources", "//content/app/resources", "//crypto:platform", @@ -397,8 +397,7 @@ # suites, it seems like one or another starts timing out too. "../browser/ui/views/keyboard_access_browsertest.cc", ] - sources += - [ "../browser/ui/libgtk2ui/select_file_dialog_interactive_uitest.cc" ] + sources += [ "../browser/ui/libgtk2ui/select_file_dialog_interactive_uitest.cc" ] configs += [ "//build/config/linux/gtk2:gtk2_internal_config" ] } } @@ -588,8 +587,8 @@ "//net", "//skia", "//sync", - "//sync:test_support_sync_testserver", "//sync:test_support_sync_fake_server", + "//sync:test_support_sync_testserver", "//ui/app_list:test_support", ] @@ -1323,9 +1322,9 @@ "//sync", "//testing/gmock", "//testing/gtest", + "//third_party/WebKit/public:blink", "//third_party/icu", "//third_party/leveldatabase", - "//third_party/WebKit/public:blink", ] data_deps = [ @@ -1544,10 +1543,10 @@ ":test_support_unit", "//base/test:test_support", "//chrome/test:test_support", - "//components/resources", "//components/content_settings/core/test:test_support", - "//content/test:test_support", + "//components/resources", "//content/public/app:both", + "//content/test:test_support", "//crypto:platform", "//crypto:test_support", "//net", @@ -1589,10 +1588,10 @@ "//components/metrics/proto", "//components/safe_browsing_db", "//components/safe_json:test_support", - "//components/webdata_services:test_support", "//components/strings", - "//device/bluetooth:mocks", + "//components/webdata_services:test_support", "//content/app/resources", + "//device/bluetooth:mocks", "//gpu:test_support", "//media:test_support", @@ -1722,9 +1721,9 @@ if (use_aura) { sources += [ "//ui/views/controls/webview/webview_unittest.cc" ] deps += [ - "//ui/wm", "//ui/aura:test_support", "//ui/views:test_support", + "//ui/wm", ] } if (!is_chromeos && is_linux) { @@ -1735,8 +1734,8 @@ } if (!is_chromeos && !use_ozone && is_linux) { deps += [ - "//chrome/browser/ui/libgtk2ui", "//build/linux:gio", + "//chrome/browser/ui/libgtk2ui", ] } @@ -1942,9 +1941,9 @@ } if (!is_mac && !is_ios) { deps += [ - "//chrome/tools/convert_dict:lib", "//chrome:packed_extra_resources", "//chrome:packed_resources", + "//chrome/tools/convert_dict:lib", "//third_party/hunspell", ] } @@ -1976,8 +1975,8 @@ "//chrome") deps += [ "//chrome:other_version", - "//chrome_elf:blacklist_test_dll_1", "//chrome/installer/util:strings", + "//chrome_elf:blacklist_test_dll_1", "//third_party/iaccessible2", "//third_party/isimpledom", "//third_party/wtl", @@ -2104,12 +2103,12 @@ ] deps = [ ":test_support", + "//base/test:run_all_unittests", + "//base/test:test_support", "//breakpad:client", "//chrome/browser", "//chrome/child", "//components/crash/core/common", - "//base/test:run_all_unittests", - "//base/test:test_support", ] if (cld_version == 2) { # Use whatever CLD2 data access mode that the
diff --git a/chrome/test/android/BUILD.gn b/chrome/test/android/BUILD.gn index 1f65910..67b3f4d 100644 --- a/chrome/test/android/BUILD.gn +++ b/chrome/test/android/BUILD.gn
@@ -22,11 +22,11 @@ "//content/public/test/android:content_java_test_support", "//net/android:net_java", "//net/android:net_java_test_support", - "//sync/android:sync_java", "//sync:sync_java_test_support", + "//sync/android:sync_java", "//testing/android/reporter:reporter_java", - "//third_party/android_tools:android_support_v7_appcompat_java", "//third_party/android_tools:android_support_v13_java", + "//third_party/android_tools:android_support_v7_appcompat_java", "//third_party/android_tools:legacy_http_javalib", "//third_party/jsr-305:jsr_305_javalib", "//ui/android:ui_java",
diff --git a/chrome/test/data/webui/settings/cr_settings_browsertest.js b/chrome/test/data/webui/settings/cr_settings_browsertest.js index 557ab9d..b59ef62f 100644 --- a/chrome/test/data/webui/settings/cr_settings_browsertest.js +++ b/chrome/test/data/webui/settings/cr_settings_browsertest.js
@@ -33,6 +33,8 @@ 'pref_util_tests.js', 'prefs_test_cases.js', 'prefs_tests.js', + 'site_list_tests.js', + 'site_settings_category_tests.js', ]), }; @@ -53,6 +55,8 @@ settings_dropdown_menu.registerTests(); settings_prefUtil.registerTests(); settings_prefs.registerTests(); + site_list.registerTests(); + site_settings_category.registerTests(); // Run all registered tests. mocha.run();
diff --git a/chrome/test/data/webui/settings/site_list_tests.js b/chrome/test/data/webui/settings/site_list_tests.js new file mode 100644 index 0000000..585e497 --- /dev/null +++ b/chrome/test/data/webui/settings/site_list_tests.js
@@ -0,0 +1,175 @@ +// Copyright 2015 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. + +/** @fileoverview Suite of tests for site-list. */ +cr.define('site_list', function() { + function registerTests() { + suite('SiteList', function() { + /** + * A site list element created before each test. + * @type {SiteList} + */ + var testElement; + + /** + * An example pref with 2 blocked location items and 2 allowed. + */ + var prefs = { + 'profile': { + 'content_settings': { + 'exceptions': { + 'geolocation': { + 'value': { + 'https:\/\/foo-allow.com:443,https:\/\/foo-allow.com:443': { + 'setting': 1, + }, + 'https:\/\/bar-allow.com:443,https:\/\/bar-allow.com:443': { + 'setting': 1, + }, + 'https:\/\/foo-block.com:443,https:\/\/foo-block.com:443': { + 'setting': 2, + }, + 'https:\/\/bar-block.com:443,https:\/\/bar-block.com:443': { + 'setting': 2, + } + }, + }, + }, + }, + }, + }; + + /** + * An example empty pref. + */ + var prefsEmpty = { + 'profile': { + 'content_settings': { + 'exceptions': { + 'geolocation': {} + }, + }, + }, + }; + + // Import necessary html before running suite. + suiteSetup(function() { + return PolymerTest.importHtml( + 'chrome://md-settings/site_settings/site_list.html' + ); + }); + + // Initialize a site-list before each test. + setup(function() { + PolymerTest.clearBody(); + testElement = document.createElement('settings-site-list'); + document.body.appendChild(testElement); + }); + + /** + * Asserts if a menu action is incorrectly hidden. + * @param {!HTMLElement} parentElement The parent node to start looking + * in. + * @param {string} textForHiddenAction Text content of the only node that + * should be hidden. + */ + function assertMenuActionHidden(parentElement, textForHiddenAction) { + var actions = parentElement.$.listContainer.items; + for (var i = 0; i < actions.length; ++i) { + var content = actions[i].textContent.trim(); + if (content == textForHiddenAction) + assertTrue(actions[i].hidden); + else + assertFalse(actions[i].hidden); + } + } + + test('Empty list', function() { + testElement.category = settings.ContentSettingsTypes.GEOLOCATION; + testElement.categorySubtype = settings.PermissionValues.ALLOW; + testElement.categoryEnabled = true; + testElement.prefs = prefsEmpty; + testElement.initialize_(); + Polymer.dom.flush(); + + assertEquals(0, testElement.sites_.length); + + assertTrue(testElement.isAllowList_()); + assertFalse(testElement.showSiteList_(testElement.sites_, true)); + assertFalse(testElement.showSiteList_(testElement.sites_, false)); + assertEquals('Allow - 0', testElement.computeSiteListHeader_( + testElement.sites_, true)); + assertEquals('Exceptions - 0', testElement.computeSiteListHeader_( + testElement.sites_, false)); + }); + + test('initial ALLOW state is correct', function() { + testElement.category = settings.ContentSettingsTypes.GEOLOCATION; + testElement.categorySubtype = settings.PermissionValues.ALLOW; + testElement.categoryEnabled = true; + testElement.prefs = prefs; + testElement.initialize_(); + Polymer.dom.flush(); + + assertEquals(2, testElement.sites_.length); + assertEquals('https://foo-allow.com:443', testElement.sites_[0].url); + + assertTrue(testElement.isAllowList_()); + assertMenuActionHidden(testElement, 'Allow'); + // Site list should show, no matter what category default is set to. + assertTrue(testElement.showSiteList_(testElement.sites_, true)); + assertTrue(testElement.showSiteList_(testElement.sites_, false)); + assertEquals('Exceptions - 2', testElement.computeSiteListHeader_( + testElement.sites_, false)); + assertEquals('Allow - 2', testElement.computeSiteListHeader_( + testElement.sites_, true)); + }); + + test('initial BLOCK state is correct', function() { + testElement.category = settings.ContentSettingsTypes.GEOLOCATION; + testElement.categorySubtype = settings.PermissionValues.BLOCK; + testElement.categoryEnabled = true; + testElement.prefs = prefs; + testElement.initialize_(); + Polymer.dom.flush(); + + assertEquals(2, testElement.sites_.length); + assertEquals('https://foo-block.com:443', testElement.sites_[0].url); + + assertFalse(testElement.isAllowList_()); + assertMenuActionHidden(testElement, 'Block'); + // Site list should only show when category default is enabled. + assertFalse(testElement.showSiteList_(testElement.sites_, false)); + assertTrue(testElement.showSiteList_(testElement.sites_, true)); + assertEquals('Block - 2', testElement.computeSiteListHeader_( + testElement.sites_, true)); + }); + + test('list items shown and clickable when data is present', function() { + testElement.category = settings.ContentSettingsTypes.GEOLOCATION; + testElement.categorySubtype = settings.PermissionValues.ALLOW; + testElement.categoryEnabled = true; + testElement.prefs = prefs; + testElement.initialize_(); + // Required for firstItem to be found below. + Polymer.dom.flush(); + + // Validate that the sites_ gets populated from pre-canned prefs. + assertEquals(2, testElement.sites_.length); + assertEquals('https://foo-allow.com:443', testElement.sites_[0].url); + assertEquals(undefined, testElement.selectedOrigin); + + // Validate that the sites are shown in UI and can be selected. + var firstItem = testElement.$.listContainer.items[0]; + var clickable = firstItem.querySelector('.flex paper-item'); + assertNotEquals(undefined, clickable); + MockInteractions.tap(clickable); + assertEquals('https://foo-allow.com:443', testElement.selectedOrigin); + }); + }); + } + return { + registerTests: registerTests, + }; +});
diff --git a/chrome/test/data/webui/settings/site_settings_category_tests.js b/chrome/test/data/webui/settings/site_settings_category_tests.js new file mode 100644 index 0000000..26a3c7b --- /dev/null +++ b/chrome/test/data/webui/settings/site_settings_category_tests.js
@@ -0,0 +1,73 @@ +// Copyright 2015 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. + +/** @fileoverview Suite of tests for site-settings-category. */ +cr.define('site_settings_category', function() { + function registerTests() { + suite('SiteSettingsCategory', function() { + /** + * A site settings category created before each test. + * @type {SiteSettingsCategory} + */ + var testElement; + + /** + * An example pref where the location category is disabled. + */ + var prefsLocationDisabled = { + 'profile': { + 'default_content_setting_values': { + 'geolocation': { + 'value': 2, + } + }, + }, + }; + + /** + * An example pref where the location category is enabled. + */ + var prefsLocationEnabled = { + 'profile': { + 'default_content_setting_values': { + 'geolocation': { + 'value': 3, + } + } + }, + }; + + // Import necessary html before running suite. + suiteSetup(function() { + return PolymerTest.importHtml( + 'chrome://md-settings/site_settings/site_settings_category.html'); + }); + + // Initialize a site-settings-category before each test. + setup(function() { + PolymerTest.clearBody(); + testElement = document.createElement('site-settings-category'); + document.body.appendChild(testElement); + }); + + test('categoryEnabled correctly represents prefs', function() { + testElement.category = settings.ContentSettingsTypes.GEOLOCATION; + + testElement.prefs = prefsLocationEnabled; + assertTrue(testElement.categoryEnabled); + MockInteractions.tap(testElement.$.toggle); + assertFalse(testElement.categoryEnabled); + + testElement.prefs = prefsLocationDisabled; + assertFalse(testElement.categoryEnabled); + MockInteractions.tap(testElement.$.toggle); + assertTrue(testElement.categoryEnabled); + }); + }); + } + + return { + registerTests: registerTests, + }; +});
diff --git a/chrome/utility/BUILD.gn b/chrome/utility/BUILD.gn index 4777889..4d3dccb 100644 --- a/chrome/utility/BUILD.gn +++ b/chrome/utility/BUILD.gn
@@ -27,6 +27,9 @@ public_deps = [] deps = [ "//base", + "//chrome:resources", + "//chrome:strings", + "//chrome/common", "//components/safe_json:safe_json_parser_message_filter", "//components/search_engines", "//components/strings", @@ -36,9 +39,6 @@ "//media", "//skia", "//third_party/libxml", - "//chrome:resources", - "//chrome:strings", - "//chrome/common", ] if (!is_android) {
diff --git a/chromecast/BUILD.gn b/chromecast/BUILD.gn index b529c499..d6afec4 100644 --- a/chromecast/BUILD.gn +++ b/chromecast/BUILD.gn
@@ -203,8 +203,8 @@ "//content/app/resources", "//content/app/strings", "//net:net_resources", - "//third_party/WebKit/public:resources", "//third_party/WebKit/public:image_resources_grit", + "//third_party/WebKit/public:resources", "//ui/resources", "//ui/strings", ]
diff --git a/chromecast/base/cast_sys_info_dummy.cc b/chromecast/base/cast_sys_info_dummy.cc index 57e8bea..f675dfd9a 100644 --- a/chromecast/base/cast_sys_info_dummy.cc +++ b/chromecast/base/cast_sys_info_dummy.cc
@@ -6,74 +6,154 @@ namespace chromecast { -CastSysInfoDummy::CastSysInfoDummy() { +CastSysInfoDummy::CastSysInfoDummy() + : build_type_(BUILD_ENG), + serial_number_("dummy.serial.number"), + factory_country_("US"), + factory_locale_("en-US") { } CastSysInfoDummy::~CastSysInfoDummy() { } CastSysInfo::BuildType CastSysInfoDummy::GetBuildType() { - return BUILD_ENG; + return build_type_; } std::string CastSysInfoDummy::GetSystemReleaseChannel() { - return ""; + return system_release_channel_; } std::string CastSysInfoDummy::GetSerialNumber() { - return "dummy.serial.number"; + return serial_number_; } std::string CastSysInfoDummy::GetProductName() { - return ""; + return product_name_; } std::string CastSysInfoDummy::GetDeviceModel() { - return ""; + return device_model_; } std::string CastSysInfoDummy::GetBoardName() { - return ""; + return board_name_; } std::string CastSysInfoDummy::GetBoardRevision() { - return ""; + return board_revision_; } std::string CastSysInfoDummy::GetManufacturer() { - return ""; + return manufacturer_; } std::string CastSysInfoDummy::GetSystemBuildNumber() { - return ""; + return system_build_number_; } std::string CastSysInfoDummy::GetFactoryCountry() { - return "US"; + return factory_country_; } std::string CastSysInfoDummy::GetFactoryLocale(std::string* second_locale) { - return "en-US"; + return factory_locale_; } std::string CastSysInfoDummy::GetWifiInterface() { - return ""; + return wifi_interface_; } std::string CastSysInfoDummy::GetApInterface() { - return ""; + return ap_interface_; } std::string CastSysInfoDummy::GetGlVendor() { - return ""; + return gl_vendor_; } std::string CastSysInfoDummy::GetGlRenderer() { - return ""; + return gl_renderer_; } std::string CastSysInfoDummy::GetGlVersion() { - return ""; + return gl_version_; +} + +void CastSysInfoDummy::SetBuildTypeForTesting( + CastSysInfo::BuildType build_type) { + build_type_ = build_type; +} + +void CastSysInfoDummy::SetSystemReleaseChannelForTesting( + const std::string& system_release_channel) { + system_release_channel_ = system_release_channel; +} + +void CastSysInfoDummy::SetSerialNumberForTesting( + const std::string& serial_number) { + serial_number_ = serial_number; +} + +void CastSysInfoDummy::SetProductNameForTesting( + const std::string& product_name) { + product_name_ = product_name; +} + +void CastSysInfoDummy::SetDeviceModelForTesting( + const std::string& device_model) { + device_model_ = device_model; +} + +void CastSysInfoDummy::SetBoardNameForTesting(const std::string& board_name) { + board_name_ = board_name; +} + +void CastSysInfoDummy::SetBoardRevisionForTesting( + const std::string& board_revision) { + board_revision_ = board_revision; +} + +void CastSysInfoDummy::SetManufacturerForTesting( + const std::string& manufacturer) { + manufacturer_ = manufacturer; +} + +void CastSysInfoDummy::SetSystemBuildNumberForTesting( + const std::string& system_build_number) { + system_build_number_ = system_build_number; +} + +void CastSysInfoDummy::SetFactoryCountryForTesting( + const std::string& factory_country) { + factory_country_ = factory_country; +} + +void CastSysInfoDummy::SetFactoryLocaleForTesting( + const std::string& factory_locale) { + factory_locale_ = factory_locale; +} + +void CastSysInfoDummy::SetWifiInterfaceForTesting( + const std::string& wifi_interface) { + wifi_interface_ = wifi_interface_; +} + +void CastSysInfoDummy::SetApInterfaceForTesting( + const std::string& ap_interface) { + ap_interface_ = ap_interface; +} + +void CastSysInfoDummy::SetGlVendorForTesting(const std::string& gl_vendor) { + gl_vendor_ = gl_vendor; +} + +void CastSysInfoDummy::SetGlRendererForTesting(const std::string& gl_renderer) { + gl_renderer_ = gl_renderer; +} + +void CastSysInfoDummy::SetGlVersionForTesting(const std::string& gl_version) { + gl_version_ = gl_version; } } // namespace chromecast
diff --git a/chromecast/base/cast_sys_info_dummy.h b/chromecast/base/cast_sys_info_dummy.h index ec6c0eab..10d03a8 100644 --- a/chromecast/base/cast_sys_info_dummy.h +++ b/chromecast/base/cast_sys_info_dummy.h
@@ -12,6 +12,7 @@ namespace chromecast { +// Dummy implementation of CastSysInfo. Fields can be overwritten for test. class CastSysInfoDummy : public CastSysInfo { public: CastSysInfoDummy(); @@ -35,7 +36,42 @@ std::string GetGlRenderer() override; std::string GetGlVersion() override; + void SetBuildTypeForTesting(BuildType build_type); + void SetSystemReleaseChannelForTesting( + const std::string& system_release_channel); + void SetSerialNumberForTesting(const std::string& serial_number); + void SetProductNameForTesting(const std::string& product_name); + void SetDeviceModelForTesting(const std::string& device_model); + void SetBoardNameForTesting(const std::string& board_name); + void SetBoardRevisionForTesting(const std::string& board_revision); + void SetManufacturerForTesting(const std::string& manufacturer); + void SetSystemBuildNumberForTesting(const std::string& system_build_number); + void SetFactoryCountryForTesting(const std::string& factory_country); + void SetFactoryLocaleForTesting(const std::string& factory_locale); + void SetWifiInterfaceForTesting(const std::string& wifi_interface); + void SetApInterfaceForTesting(const std::string& ap_interface); + void SetGlVendorForTesting(const std::string& gl_vendor); + void SetGlRendererForTesting(const std::string& gl_renderer); + void SetGlVersionForTesting(const std::string& gl_version); + private: + BuildType build_type_; + std::string system_release_channel_; + std::string serial_number_; + std::string product_name_; + std::string device_model_; + std::string board_name_; + std::string board_revision_; + std::string manufacturer_; + std::string system_build_number_; + std::string factory_country_; + std::string factory_locale_; + std::string wifi_interface_; + std::string ap_interface_; + std::string gl_vendor_; + std::string gl_renderer_; + std::string gl_version_; + DISALLOW_COPY_AND_ASSIGN(CastSysInfoDummy); };
diff --git a/chromecast/base/metrics/cast_histograms.h b/chromecast/base/metrics/cast_histograms.h index 19cb98e..bac472c 100644 --- a/chromecast/base/metrics/cast_histograms.h +++ b/chromecast/base/metrics/cast_histograms.h
@@ -29,8 +29,8 @@ base::Histogram::kUmaTargetedHistogramFlag)) #define UMA_HISTOGRAM_CUSTOM_COUNTS_NO_CACHE(name, sample, min, max, \ - bucket_count) \ - STATIC_HISTOGRAM_POINTER_BLOCK_NO_CACHE(name, Add(sample), \ + bucket_count, count) \ + STATIC_HISTOGRAM_POINTER_BLOCK_NO_CACHE(name, AddCount(sample, count), \ base::Histogram::FactoryGet(name, min, max, bucket_count, \ base::HistogramBase::kUmaTargetedHistogramFlag))
diff --git a/chromecast/browser/BUILD.gn b/chromecast/browser/BUILD.gn index 2fc0a3b..a38dab1 100644 --- a/chromecast/browser/BUILD.gn +++ b/chromecast/browser/BUILD.gn
@@ -62,8 +62,8 @@ deps = [ "//base", - "//base:prefs", "//base:i18n", + "//base:prefs", "//cc", "//chromecast/app:chromecast_settings", "//chromecast/app:resources", @@ -92,8 +92,8 @@ "//content/public/common", "//content/public/utility", "//gpu", - "//media", "//ipc", + "//media", "//net", "//ui/aura", "//ui/base",
diff --git a/chromecast/browser/metrics/BUILD.gn b/chromecast/browser/metrics/BUILD.gn index 81233e8c..fad608a3 100644 --- a/chromecast/browser/metrics/BUILD.gn +++ b/chromecast/browser/metrics/BUILD.gn
@@ -22,8 +22,8 @@ "//components/metrics:gpu", "//components/metrics:net", "//components/metrics:profiler", - "//content/public/common", "//content/public/browser", + "//content/public/common", ] if (is_linux) {
diff --git a/chromecast/browser/metrics/external_metrics.cc b/chromecast/browser/metrics/external_metrics.cc index 698e02b..df9fa79b 100644 --- a/chromecast/browser/metrics/external_metrics.cc +++ b/chromecast/browser/metrics/external_metrics.cc
@@ -129,7 +129,8 @@ sample.sample(), sample.min(), sample.max(), - sample.bucket_count()); + sample.bucket_count(), + 1); break; case ::metrics::MetricSample::LINEAR_HISTOGRAM: if (!CheckLinearValues(sample.name(), sample.max())) {
diff --git a/chromecast/media/BUILD.gn b/chromecast/media/BUILD.gn index b54ba7d1..2b0e5c82 100644 --- a/chromecast/media/BUILD.gn +++ b/chromecast/media/BUILD.gn
@@ -38,6 +38,11 @@ deps = [ ":media", + "//base", + "//base:i18n", + "//base/test:test_support", + "//chromecast/base", + "//chromecast/base/metrics:test_support", "//chromecast/media/audio", "//chromecast/media/base:message_loop", "//chromecast/media/cma/backend", @@ -45,11 +50,6 @@ "//chromecast/media/cma/ipc", "//chromecast/media/cma/ipc_streamer", "//chromecast/media/cma/pipeline", - "//base", - "//base:i18n", - "//base/test:test_support", - "//chromecast/base", - "//chromecast/base/metrics:test_support", "//chromecast/public", "//media", "//media/base:test_support",
diff --git a/chromecast/media/cma/pipeline/BUILD.gn b/chromecast/media/cma/pipeline/BUILD.gn index c8581e6..a5809da8a 100644 --- a/chromecast/media/cma/pipeline/BUILD.gn +++ b/chromecast/media/cma/pipeline/BUILD.gn
@@ -30,10 +30,10 @@ deps = [ "//base", - "//chromecast/media/cma/backend", - "//chromecast/media/cma/base", "//chromecast/media/base", "//chromecast/media/cdm", + "//chromecast/media/cma/backend", + "//chromecast/media/cma/base", "//crypto", "//crypto:platform", "//media",
diff --git a/chromecast/renderer/BUILD.gn b/chromecast/renderer/BUILD.gn index 940fc39..ae6dfa35 100644 --- a/chromecast/renderer/BUILD.gn +++ b/chromecast/renderer/BUILD.gn
@@ -33,8 +33,8 @@ deps = [ "//base", "//chromecast/base", - "//chromecast/crash", "//chromecast/common/media", + "//chromecast/crash", "//chromecast/media", "//components/cdm/renderer", "//components/network_hints/renderer",
diff --git a/chromecast/renderer/media/hole_frame_factory.cc b/chromecast/renderer/media/hole_frame_factory.cc index 8c2cb0a..c4f26e6 100644 --- a/chromecast/renderer/media/hole_frame_factory.cc +++ b/chromecast/renderer/media/hole_frame_factory.cc
@@ -27,16 +27,15 @@ gl->BindTexture(GL_TEXTURE_2D, texture_); image_id_ = gl->CreateGpuMemoryBufferImageCHROMIUM(1, 1, GL_RGBA, GL_READ_WRITE_CHROMIUM); - if (image_id_) { - gl->BindTexImage2DCHROMIUM(GL_TEXTURE_2D, image_id_); + CHECK(image_id_); + gl->BindTexImage2DCHROMIUM(GL_TEXTURE_2D, image_id_); - gl->GenMailboxCHROMIUM(mailbox_.name); - gl->ProduceTextureDirectCHROMIUM(texture_, GL_TEXTURE_2D, mailbox_.name); + gl->GenMailboxCHROMIUM(mailbox_.name); + gl->ProduceTextureDirectCHROMIUM(texture_, GL_TEXTURE_2D, mailbox_.name); - const GLuint64 fence_sync = gl->InsertFenceSyncCHROMIUM(); - gl->ShallowFlushCHROMIUM(); - gl->GenSyncTokenCHROMIUM(fence_sync, sync_token_.GetData()); - } + const GLuint64 fence_sync = gl->InsertFenceSyncCHROMIUM(); + gl->ShallowFlushCHROMIUM(); + gl->GenSyncTokenCHROMIUM(fence_sync, sync_token_.GetData()); } } @@ -47,17 +46,15 @@ CHECK(lock); gpu::gles2::GLES2Interface* gl = lock->ContextGL(); gl->BindTexture(GL_TEXTURE_2D, texture_); - if (image_id_) - gl->ReleaseTexImage2DCHROMIUM(GL_TEXTURE_2D, image_id_); + gl->ReleaseTexImage2DCHROMIUM(GL_TEXTURE_2D, image_id_); gl->DeleteTextures(1, &texture_); - if (image_id_) - gl->DestroyImageCHROMIUM(image_id_); + gl->DestroyImageCHROMIUM(image_id_); } } scoped_refptr<::media::VideoFrame> HoleFrameFactory::CreateHoleFrame( const gfx::Size& size) { - if (texture_ && image_id_) { + if (texture_) { scoped_refptr<::media::VideoFrame> frame = ::media::VideoFrame::WrapNativeTexture( ::media::PIXEL_FORMAT_XRGB,
diff --git a/chromeos/BUILD.gn b/chromeos/BUILD.gn index 268a5b2..b25c21a 100644 --- a/chromeos/BUILD.gn +++ b/chromeos/BUILD.gn
@@ -20,14 +20,16 @@ "//dbus", ] deps = [ + ":cryptohome_proto", + ":power_manager_proto", "//base", "//base:i18n", "//base:prefs", "//base/third_party/dynamic_annotations", "//chromeos/ime:gencode", "//components/device_event_log", - "//components/policy/proto", "//components/onc", + "//components/policy/proto", "//components/proxy_config", "//components/signin/core/account_id", "//crypto", @@ -37,8 +39,6 @@ "//third_party/libxml", "//third_party/protobuf:protobuf_lite", "//url", - ":cryptohome_proto", - ":power_manager_proto", ] sources = gypi_values.chromeos_sources defines = [ "CHROMEOS_IMPLEMENTATION" ] @@ -109,10 +109,10 @@ testonly = true configs += [ "//build/config/linux:dbus" ] deps = [ - "//crypto", ":chromeos", ":cryptohome_proto", ":power_manager_proto", + "//crypto", ] sources = [ "dbus/fake_cros_disks_client.cc", @@ -132,6 +132,9 @@ "//net/third_party/nss/ssl:ssl_config", ] deps = [ + ":cryptohome_proto", + ":power_manager_proto", + ":test_support", "//base:prefs_test_support", "//base/test:run_all_unittests", "//base/test:test_support", @@ -147,9 +150,6 @@ "//testing/gtest", "//third_party/icu", "//url", - ":cryptohome_proto", - ":power_manager_proto", - ":test_support", ] sources = gypi_values.chromeos_test_sources if (use_allocator != "none") {
diff --git a/chromeos/CHROMEOS_LKGM b/chromeos/CHROMEOS_LKGM index 85f09f5..e62e0f8 100644 --- a/chromeos/CHROMEOS_LKGM +++ b/chromeos/CHROMEOS_LKGM
@@ -1 +1 @@ -7657.0.0 \ No newline at end of file +7660.0.0 \ No newline at end of file
diff --git a/chromeos/ime/input_methods.txt b/chromeos/ime/input_methods.txt index 58f9accf..2181789 100644 --- a/chromeos/ime/input_methods.txt +++ b/chromeos/ime/input_methods.txt
@@ -43,16 +43,18 @@ # # U.S. English -xkb:us::eng us en,en-US,en-AU,en-NZ US login -xkb:us:intl:eng us(intl) en,en-US INTL login -xkb:us:altgr-intl:eng us(altgr-intl) en,en-US EXTD login -xkb:us:dvorak:eng us(dvorak) en,en-US DV login -xkb:us:colemak:eng us(colemak) en,en-US CO login -xkb:us:intl:nld us(intl) nl INTL login -xkb:us:intl:por us(intl) pt-BR INTL login -xkb:us::ind us id US login -xkb:us::fil us fil US login -xkb:us::msa us ms US login +xkb:us::eng us en,en-US,en-AU,en-NZ US login +xkb:us:intl:eng us(intl) en,en-US INTL login +xkb:us:altgr-intl:eng us(altgr-intl) en,en-US EXTD login +xkb:us:dvorak:eng us(dvorak) en,en-US DV login +xkb:us:colemak:eng us(colemak) en,en-US CO login +xkb:us:workman:eng us(workman) en,en-US WM login +xkb:us:workman-intl:eng us(workman-intl) en,en-US WMI login +xkb:us:intl:nld us(intl) nl INTL login +xkb:us:intl:por us(intl) pt-BR INTL login +xkb:us::ind us id US login +xkb:us::fil us fil US login +xkb:us::msa us ms US login # U.S. English entiries have to be above the Dutch entry so that xkb:us:intl:eng # will be selected as the default keyboard when the UI language is set to Dutch.
diff --git a/cloud_print/service/win/BUILD.gn b/cloud_print/service/win/BUILD.gn index 2c050b0b..1cc937f 100644 --- a/cloud_print/service/win/BUILD.gn +++ b/cloud_print/service/win/BUILD.gn
@@ -79,8 +79,8 @@ ":config_version", ":exe_manifest", "//cloud_print/common:install_utils", - "//cloud_print/service:resources", "//cloud_print/service:lib", + "//cloud_print/service:resources", ] libs = [ "secur32.lib" ] @@ -106,8 +106,8 @@ deps = [ ":exe_manifest", "//cloud_print/common:install_utils", - "//cloud_print/service:resources", "//cloud_print/service:lib", + "//cloud_print/service:resources", ] libs = [ "secur32.lib" ]
diff --git a/components/BUILD.gn b/components/BUILD.gn index 33fbe66..b24ef8e 100644 --- a/components/BUILD.gn +++ b/components/BUILD.gn
@@ -47,63 +47,66 @@ "//components/history/core/browser", "//components/history/core/common", "//components/history/core/test", + "//components/infobars/core", + "//components/invalidation/impl", + "//components/invalidation/public", "//components/keyed_service/core", + "//components/leveldb_proto", "//components/metrics", "//components/net_log", "//components/network_time", "//components/ntp_snippets", + "//components/omnibox/browser", + "//components/open_from_clipboard", + "//components/os_crypt", "//components/password_manager/core/browser", "//components/password_manager/core/common", "//components/password_manager/sync/browser", + "//components/pref_registry", + "//components/proxy_config", + "//components/rappor", "//components/search", "//components/search_engines", "//components/sessions", - "//components/sync_bookmarks", - "//components/undo", - "//components/update_client", - "//components/strings", - "//components/leveldb_proto", - "//components/pref_registry", - "//components/rappor", - "//components/proxy_config", - "//components/omnibox/browser", - "//components/open_from_clipboard", - "//components/infobars/core", - "//components/invalidation/impl", - "//components/invalidation/public", "//components/signin/core/browser", + "//components/strings", "//components/suggestions", + "//components/sync_bookmarks", "//components/sync_driver", "//components/syncable_prefs", "//components/translate/core/browser", "//components/translate/core/common", + "//components/undo", + "//components/update_client", "//components/upload_list", "//components/variations", "//components/variations/service", "//components/version_info", "//components/version_ui", - "//components/os_crypt", "//components/web_resource", "//components/webdata_services", ] if (!is_ios) { deps += [ - "//components/bitmap_uploader", - "//components/certificate_reporting", - "//components/cdm/browser", "//components/about_handler", + "//components/app_modal", "//components/auto_login_parser", "//components/autofill/content/browser", "//components/autofill/content/common", "//components/autofill/content/renderer", + "//components/bitmap_uploader", + "//components/browsing_data", "//components/bubble", "//components/captive_portal", "//components/cdm/browser", + "//components/cdm/browser", "//components/cdm/common", "//components/cdm/renderer", - "//components/cloud_devices/common", + "//components/certificate_reporting", + "//components/certificate_transparency", "//components/chrome_apps", + "//components/cloud_devices/common", "//components/compression", "//components/cookie_config", "//components/crash/content/app", @@ -120,6 +123,9 @@ "//components/feedback", "//components/gcm_driver/crypto", "//components/gcm_driver/instance_id", + "//components/guest_view/browser", + "//components/guest_view/common", + "//components/guest_view/renderer", "//components/history/content/browser", "//components/json_schema", "//components/keyed_service/content", @@ -143,18 +149,21 @@ "//components/pdf/renderer", "//components/plugins/renderer", "//components/power", - "//components/precache/core", "//components/precache/content", + "//components/precache/core", "//components/query_parser", "//components/renderer_context_menu", "//components/resources:components_resources", "//components/safe_browsing_db", + "//components/safe_json", + "//components/scheduler", "//components/search_provider_logos", "//components/security_interstitials/core", "//components/ssl_config", - "//components/startup_metric_utils/common", "//components/startup_metric_utils/browser", + "//components/startup_metric_utils/common", "//components/sync_sessions", + "//components/test_runner", "//components/tracing", "//components/tracing:startup_tracing", "//components/translate/content/browser", @@ -175,19 +184,10 @@ "//components/web_cache/renderer", "//components/web_modal", "//components/webcrypto", + "//components/webcrypto", "//components/webdata/common", "//components/wifi", "//components/wifi_sync", - "//components/app_modal", - "//components/browsing_data", - "//components/certificate_transparency", - "//components/guest_view/browser", - "//components/guest_view/common", - "//components/guest_view/renderer", - "//components/safe_json", - "//components/scheduler", - "//components/test_runner", - "//components/webcrypto", ] if (enable_configuration_policy) { @@ -210,11 +210,11 @@ # TODO(agrieve): Add to main deps list once compile errors are resolved. deps += [ "//components/audio_modem", + "//components/copresence", "//components/proximity_auth", "//components/proximity_auth/cryptauth", - "//components/webusb", - "//components/copresence", "//components/storage_monitor", + "//components/webusb", ] } @@ -261,13 +261,13 @@ "//components/autofill/content/browser", # Blocked on content/blink. "//components/autofill/content/common", # Blocked on content. "//components/autofill/content/renderer", # Blocked on content/blink. - "//components/crash/content/app", # Should work, needs checking. - "//components/crash/content/browser", # Should work, needs checking. "//components/captive_portal", # Should work, needs checking. - "//components/cloud_devices/common", # Should work, needs checking. "//components/cdm/browser", # Blocked on content. "//components/cdm/common", # Blocked on content. "//components/cdm/renderer", # Blocked on content. + "//components/cloud_devices/common", # Should work, needs checking. + "//components/crash/content/app", # Should work, needs checking. + "//components/crash/content/browser", # Should work, needs checking. "//components/data_reduction_proxy/core/browser", # Should work, needs checking. "//components/data_reduction_proxy/core/common", # Should work, needs checking. "//components/dom_distiller/core", # Blocked on content. @@ -283,16 +283,16 @@ "//components/invalidation/impl", # Should work, needs checking. "//components/invalidation/public", # Should work, needs checking. "//components/json_schema", # Should work, needs checking. - "//components/keyed_service/core", # Blocked on content. "//components/keyed_service/content", # Blocked on content. + "//components/keyed_service/core", # Blocked on content. "//components/navigation_interception", # Blocked on content. "//components/omnibox/browser", # Should work, needs checking. "//components/password_manager/content/browser", # Blocked on content. "//components/password_manager/core/browser", # Should work, needs checking. "//components/password_manager/core/common", # Should work, needs checking. "//components/plugins/renderer", # Blocked on blink. - "//components/power", # Blocked on content. "//components/policy", # Blocked on content (indirectly via autofill). + "//components/power", # Blocked on content. "//components/precache/content", # Blocked on content. "//components/precache/core", # Should work, needs checking. "//components/rappor", # Should work, needs checking. @@ -310,8 +310,8 @@ "//components/visitedlink/renderer", # Blocked on blink "//components/web_cache/browser", # Blocked on content and blink. "//components/web_cache/renderer", # Blocked on content and blink. - "//components/webdata_services", # Should work, needs checking. "//components/web_modal", # Blocked on content. + "//components/webdata_services", # Should work, needs checking. ] } } @@ -369,75 +369,63 @@ "//components/history/core/common:unit_tests", "//components/invalidation/impl:unit_tests", "//components/keyed_service/core:unit_tests", + "//components/leveldb_proto:unit_tests", "//components/metrics:unit_tests", "//components/net_log:unit_tests", "//components/network_time:unit_tests", + "//components/omnibox/browser:unit_tests", "//components/open_from_clipboard:unit_tests", + "//components/os_crypt:unit_tests", "//components/password_manager/core/browser:unit_tests", "//components/password_manager/core/common:unit_tests", "//components/password_manager/sync/browser:unit_tests", "//components/proxy_config:unit_tests", "//components/rappor:unit_tests", "//components/search:unit_tests", - "//components/sessions:unit_tests", - "//components/syncable_prefs:unit_tests", - "//components/undo:unit_tests", - "//components/update_client:unit_tests", - "//components/upload_list:unit_tests", - "//net", - "//ui/base", - "//ui/resources:ui_test_pak", "//components/search_engines:unit_tests", - "//components/leveldb_proto:unit_tests", + "//components/sessions:unit_tests", "//components/signin/core/browser:unit_tests", "//components/suggestions:unit_tests", "//components/sync_driver:unit_tests", + "//components/syncable_prefs:unit_tests", "//components/translate/core/browser:unit_tests", "//components/translate/core/common:unit_tests", "//components/translate/core/language_detection:unit_tests", + "//components/undo:unit_tests", + "//components/update_client:unit_tests", + "//components/upload_list:unit_tests", "//components/variations:unit_tests", "//components/variations/service:unit_tests", - "//components/omnibox/browser:unit_tests", - "//components/os_crypt:unit_tests", "//components/web_resource:unit_tests", + "//net", + "//ui/base", + "//ui/resources:ui_test_pak", ] if (!is_ios) { deps += [ - "//components/certificate_transparency:unit_tests", - "//components/data_use_measurement/content:unit_tests", - "//components/error_page/renderer:unit_tests", - "//components/guest_view/browser:unit_tests", - "//components/navigation_interception:unit_tests", - "//components/network_hints/renderer:unit_tests", - "//components/page_load_metrics/browser:unit_tests", - "//components/page_load_metrics/renderer:unit_tests", - "//components/power:unit_tests", - "//components/safe_json:unit_tests", - "//components/scheduler:unit_tests", - "//components/test_runner:test_runner", - "//components/tracing:unit_tests", - "//components/ui/zoom:unit_tests", - "//components/visitedlink/test:unit_tests", - "//components/web_cache/browser:unit_tests", "//components/auto_login_parser:unit_tests", "//components/autofill/content/browser:unit_tests", "//components/autofill/content/renderer:unit_tests", "//components/bubble:unit_tests", "//components/captive_portal:unit_tests", + "//components/certificate_transparency:unit_tests", "//components/cloud_devices/common:unit_tests", "//components/component_updater:unit_tests", "//components/crx_file:unit_tests", "//components/data_reduction_proxy/content/browser:unit_tests", "//components/data_reduction_proxy/core/browser:unit_tests", "//components/data_reduction_proxy/core/common:unit_tests", + "//components/data_use_measurement/content:unit_tests", "//components/device_event_log:unit_tests", "//components/devtools_http_handler:unit_tests", "//components/dom_distiller/content:unit_tests", "//components/domain_reliability:unit_tests", + "//components/error_page/renderer:unit_tests", "//components/favicon/content:unit_tests", "//components/gcm_driver/crypto:unit_tests", "//components/gcm_driver/instance_id:unit_tests", + "//components/guest_view/browser:unit_tests", "//components/history/content/browser:unit_tests", "//components/json_schema:unit_tests", "//components/keyed_service/content:unit_tests", @@ -445,23 +433,35 @@ "//components/login:unit_tests", "//components/memory_pressure:unit_tests", "//components/mime_util:unit_tests", + "//components/navigation_interception:unit_tests", + "//components/network_hints/renderer:unit_tests", "//components/offline_pages:unit_tests", "//components/packed_ct_ev_whitelist:unit_tests", + "//components/page_load_metrics/browser:unit_tests", + "//components/page_load_metrics/renderer:unit_tests", "//components/password_manager/content/browser:unit_tests", + "//components/power:unit_tests", "//components/precache/content:unit_tests", "//components/precache/core:unit_tests", "//components/query_parser:unit_tests", "//components/safe_browsing_db:unit_tests", - "//components/search_engines:unit_tests", + "//components/safe_json:unit_tests", + "//components/scheduler:unit_tests", "//components/search:unit_tests", + "//components/search_engines:unit_tests", "//components/search_provider_logos:unit_tests", "//components/ssl_config:unit_tests", "//components/sync_bookmarks:unit_tests", "//components/sync_sessions:unit_tests", + "//components/test_runner:test_runner", + "//components/tracing:unit_tests", + "//components/ui/zoom:unit_tests", "//components/url_formatter:unit_tests", "//components/url_matcher:unit_tests", "//components/user_prefs/tracked:unit_tests", + "//components/visitedlink/test:unit_tests", "//components/wallpaper:unit_tests", + "//components/web_cache/browser:unit_tests", "//components/webcrypto:unit_tests", "//components/webdata/common:unit_tests", @@ -648,23 +648,23 @@ defines = [ "HAS_OUT_OF_PROC_TEST_RUNNER" ] deps = [ - "strings", "//base", "//base/test:test_support", + "//components/strings", "//testing/gmock", "//testing/gtest", ] if (!is_ios) { deps += [ - "autofill/content/browser", - "autofill/content/renderer", - "content_settings/core/common", - "dom_distiller/content:content_browser", - "dom_distiller/core", - "dom_distiller/core:test_support", - "password_manager/content/browser", - "password_manager/content/common", - "password_manager/content/renderer", + "//components/autofill/content/browser", + "//components/autofill/content/renderer", + "//components/content_settings/core/common", + "//components/dom_distiller/content:content_browser", + "//components/dom_distiller/core", + "//components/dom_distiller/core:test_support", + "//components/password_manager/content/browser", + "//components/password_manager/content/common", + "//components/password_manager/content/renderer", "//components/tracing", "//content/test:browsertest_support", "//content/test:test_support", @@ -697,8 +697,8 @@ # a MANUAL component_browsertest. sources += [ "dom_distiller/standalone/content_extractor_browsertest.cc" ] deps += [ - "pref_registry:test_support", "//base:prefs_test_support", + "//components/pref_registry:test_support", ] } @@ -727,8 +727,8 @@ deps += [ "//base", "//base/test:test_support_perf", - "//content/test:test_support", "//components/visitedlink/browser", + "//content/test:test_support", ] } }
diff --git a/components/autofill/content/browser/BUILD.gn b/components/autofill/content/browser/BUILD.gn index 36f97605..05ef2c18 100644 --- a/components/autofill/content/browser/BUILD.gn +++ b/components/autofill/content/browser/BUILD.gn
@@ -78,8 +78,8 @@ deps = [ ":browser", "//base", - "//components/autofill/content/common", "//components/autofill/content/browser/wallet:test_support", + "//components/autofill/content/common", "//components/autofill/core/browser", "//components/autofill/core/browser:test_support", "//components/autofill/core/common",
diff --git a/components/autofill/content/renderer/BUILD.gn b/components/autofill/content/renderer/BUILD.gn index 3e6888a..bb9101a4 100644 --- a/components/autofill/content/renderer/BUILD.gn +++ b/components/autofill/content/renderer/BUILD.gn
@@ -35,8 +35,8 @@ "//ipc", "//net", "//skia", - "//third_party/icu", "//third_party/WebKit/public:blink", + "//third_party/icu", "//ui/base", ]
diff --git a/components/autofill/content/renderer/autofill_agent.cc b/components/autofill/content/renderer/autofill_agent.cc index ed9969d..06228ad 100644 --- a/components/autofill/content/renderer/autofill_agent.cc +++ b/components/autofill/content/renderer/autofill_agent.cc
@@ -4,6 +4,8 @@ #include "components/autofill/content/renderer/autofill_agent.h" +#include <tuple> + #include "base/auto_reset.h" #include "base/bind.h" #include "base/command_line.h" @@ -163,15 +165,8 @@ bool AutofillAgent::FormDataCompare::operator()(const FormData& lhs, const FormData& rhs) const { - if (lhs.name != rhs.name) - return lhs.name < rhs.name; - if (lhs.origin != rhs.origin) - return lhs.origin < rhs.origin; - if (lhs.action != rhs.action) - return lhs.action < rhs.action; - if (lhs.is_form_tag != rhs.is_form_tag) - return lhs.is_form_tag < rhs.is_form_tag; - return false; + return std::tie(lhs.name, lhs.origin, lhs.action, lhs.is_form_tag) < + std::tie(rhs.name, rhs.origin, rhs.action, rhs.is_form_tag); } bool AutofillAgent::OnMessageReceived(const IPC::Message& message) {
diff --git a/components/autofill/core/browser/BUILD.gn b/components/autofill/core/browser/BUILD.gn index 73c5cb3..ee20687 100644 --- a/components/autofill/core/browser/BUILD.gn +++ b/components/autofill/core/browser/BUILD.gn
@@ -157,7 +157,6 @@ "//base", "//base:i18n", "//base:prefs", - "//third_party/re2", "//components/autofill/core/common", "//components/compression", "//components/data_use_measurement/core", @@ -181,8 +180,9 @@ "//third_party/fips181", "//third_party/icu", "//third_party/libaddressinput:util", - "//third_party/libphonenumber", "//third_party/libjingle", + "//third_party/libphonenumber", + "//third_party/re2", "//ui/base", "//ui/gfx", "//ui/gfx/geometry", @@ -218,10 +218,11 @@ ] deps = [ + ":browser", "//base", - "//base/test:test_support", "//base:prefs", "//base:prefs_test_support", + "//base/test:test_support", "//components/autofill/core/browser", "//components/autofill/core/common", "//components/os_crypt", @@ -233,9 +234,8 @@ "//google_apis:test_support", "//skia", "//testing/gtest", - "//ui/gfx/geometry", "//ui/gfx:test_support", - ":browser", + "//ui/gfx/geometry", ] } @@ -309,8 +309,8 @@ "//testing/gmock", "//testing/gtest", "//third_party/libaddressinput:util", - "//third_party/libphonenumber", "//third_party/libjingle", + "//third_party/libphonenumber", "//ui/base", "//url", ]
diff --git a/components/autofill/core/browser/webdata/autofill_entry.cc b/components/autofill/core/browser/webdata/autofill_entry.cc index bca50c5..83fd639b 100644 --- a/components/autofill/core/browser/webdata/autofill_entry.cc +++ b/components/autofill/core/browser/webdata/autofill_entry.cc
@@ -4,6 +4,8 @@ #include "components/autofill/core/browser/webdata/autofill_entry.h" +#include <tuple> + #include "base/strings/utf_string_conversions.h" namespace autofill { @@ -33,14 +35,7 @@ } bool AutofillKey::operator<(const AutofillKey& key) const { - int diff = name_.compare(key.name()); - if (diff < 0) - return true; - - if (diff == 0) - return value_.compare(key.value()) < 0; - - return false; + return std::tie(name_, value_) < std::tie(key.name(), key.value()); } AutofillEntry::AutofillEntry(const AutofillKey& key,
diff --git a/components/autofill/core/browser/webdata/autofill_table.cc b/components/autofill/core/browser/webdata/autofill_table.cc index 99c49be9..3e400e16 100644 --- a/components/autofill/core/browser/webdata/autofill_table.cc +++ b/components/autofill/core/browser/webdata/autofill_table.cc
@@ -700,15 +700,19 @@ return result; } -int AutofillTable::GetCountOfEntriesContainedBetween( +int AutofillTable::GetCountOfValuesContainedBetween( const Time& begin, const Time& end) { const time_t begin_time_t = begin.ToTimeT(); const time_t end_time_t = GetEndTime(end); sql::Statement s(db_->GetUniqueStatement( - "SELECT COUNT(*) FROM autofill " - "WHERE date_created >= ? AND date_last_used < ?")); + "SELECT COUNT(DISTINCT(value1)) FROM ( " + " SELECT value AS value1 FROM autofill " + " WHERE NOT EXISTS ( " + " SELECT value AS value2, date_created, date_last_used FROM autofill " + " WHERE value1 = value2 AND " + " (date_created < ? OR date_last_used >= ?)))")); s.BindInt64(0, begin_time_t); s.BindInt64(1, end_time_t);
diff --git a/components/autofill/core/browser/webdata/autofill_table.h b/components/autofill/core/browser/webdata/autofill_table.h index d2d6510..73fcb16 100644 --- a/components/autofill/core/browser/webdata/autofill_table.h +++ b/components/autofill/core/browser/webdata/autofill_table.h
@@ -272,10 +272,11 @@ virtual bool RemoveFormElement(const base::string16& name, const base::string16& value); - // Returns the number of autofill entries whose interval between creation date - // and last usage is entirely contained between [|begin|, |end|). - virtual int GetCountOfEntriesContainedBetween(const base::Time& begin, - const base::Time& end); + // Returns the number of unique values such that for all autofill entries with + // that value, the interval between creation date and last usage is entirely + // contained between [|begin|, |end|). + virtual int GetCountOfValuesContainedBetween(const base::Time& begin, + const base::Time& end); // Retrieves all of the entries in the autofill table. virtual bool GetAllAutofillEntries(std::vector<AutofillEntry>* entries); @@ -414,7 +415,7 @@ FRIEND_TEST_ALL_PREFIXES(AutofillTableTest, Autofill_AddChanges); FRIEND_TEST_ALL_PREFIXES( AutofillTableTest, - Autofill_GetCountOfEntriesContainedBetween); + Autofill_GetCountOfValuesContainedBetween); FRIEND_TEST_ALL_PREFIXES(AutofillTableTest, Autofill_RemoveBetweenChanges); FRIEND_TEST_ALL_PREFIXES(AutofillTableTest, Autofill_UpdateDontReplace); FRIEND_TEST_ALL_PREFIXES(
diff --git a/components/autofill/core/browser/webdata/autofill_table_unittest.cc b/components/autofill/core/browser/webdata/autofill_table_unittest.cc index 6e6e2d1..9341d5d 100644 --- a/components/autofill/core/browser/webdata/autofill_table_unittest.cc +++ b/components/autofill/core/browser/webdata/autofill_table_unittest.cc
@@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include <tuple> #include <utility> #include <vector> @@ -68,18 +69,10 @@ typedef AutofillEntrySet::iterator AutofillEntrySetIterator; bool CompareAutofillEntries(const AutofillEntry& a, const AutofillEntry& b) { - int compVal = a.key().name().compare(b.key().name()); - if (compVal != 0) - return compVal < 0; - - compVal = a.key().value().compare(b.key().value()); - if (compVal != 0) - return compVal < 0; - - if (a.date_created() != b.date_created()) - return a.date_created() < b.date_created(); - - return a.date_last_used() < b.date_last_used(); + return std::tie(a.key().name(), a.key().value(), + a.date_created(), a.date_last_used()) < + std::tie(b.key().name(), b.key().value(), + b.date_created(), b.date_last_used()); } AutofillEntry MakeAutofillEntry(const char* name, @@ -274,7 +267,7 @@ EXPECT_EQ(4U, v.size()); } -TEST_F(AutofillTableTest, Autofill_GetCountOfEntriesContainedBetween) { +TEST_F(AutofillTableTest, Autofill_GetCountOfValuesContainedBetween) { AutofillChangeList changes; // This test makes time comparisons that are precise to a microsecond, but the // database uses the time_t format which is only precise to a second. @@ -292,7 +285,7 @@ { "Name", "Clark Kent" }, { "Name", "Superman" }, { "Name", "Clark Sutter" }, - { "Name", "Clark Kent" } + { "Nomen", "Clark Kent" } }; for (Entry entry : entries) { @@ -303,47 +296,46 @@ now += second; } - // Only "Alter ego" : "Superman" is entirely contained within the - // first second. - EXPECT_EQ(1, table_->GetCountOfEntriesContainedBetween( + // While the entry "Alter ego" : "Superman" is entirely contained within + // the first second, the value "Superman" itself appears in another entry, + // so it is not contained. + EXPECT_EQ(0, table_->GetCountOfValuesContainedBetween( begin, begin + second)); - // No other entries are entirely contained within the first three seconds + // No values are entirely contained within the first three seconds either // (note that the second time constraint is exclusive). - EXPECT_EQ(1, table_->GetCountOfEntriesContainedBetween( + EXPECT_EQ(0, table_->GetCountOfValuesContainedBetween( begin, begin + 3 * second)); - // "Name" : "Superman" is entirely contained within the first four seconds. - // We already have an entry for "Superman", but with different field name, - // so we should now count two different entries. - EXPECT_EQ(2, table_->GetCountOfEntriesContainedBetween( + // Only "Superman" is entirely contained within the first four seconds. + EXPECT_EQ(1, table_->GetCountOfValuesContainedBetween( begin, begin + 4 * second)); - // "Name" : {"Superman", "Clark Kent", "Clark Sutter"} are contained between - // the first and seventh second. - EXPECT_EQ(3, table_->GetCountOfEntriesContainedBetween( + // "Clark Kent" and "Clark Sutter" are contained between the first + // and seventh second. + EXPECT_EQ(2, table_->GetCountOfValuesContainedBetween( begin + second, begin + 7 * second)); - // Beginning from the second second, "Name" : "Superman" is not contained. - EXPECT_EQ(2, table_->GetCountOfEntriesContainedBetween( - begin + 2 * second, begin + 7 * second)); + // Beginning from the third second, "Clark Kent" is not contained. + EXPECT_EQ(1, table_->GetCountOfValuesContainedBetween( + begin + 3 * second, begin + 7 * second)); - // We have four entries total. - EXPECT_EQ(4, table_->GetCountOfEntriesContainedBetween( + // We have three distinct values total. + EXPECT_EQ(3, table_->GetCountOfValuesContainedBetween( begin, begin + 7 * second)); // And we should get the same result for unlimited time interval. - EXPECT_EQ(4, table_->GetCountOfEntriesContainedBetween(Time(), Time::Max())); + EXPECT_EQ(3, table_->GetCountOfValuesContainedBetween(Time(), Time::Max())); // The null time interval is also interpreted as unlimited. - EXPECT_EQ(4, table_->GetCountOfEntriesContainedBetween(Time(), Time())); + EXPECT_EQ(3, table_->GetCountOfValuesContainedBetween(Time(), Time())); // An interval that does not fully contain any entries returns zero. - EXPECT_EQ(0, table_->GetCountOfEntriesContainedBetween( + EXPECT_EQ(0, table_->GetCountOfValuesContainedBetween( begin + second, begin + 2 * second)); // So does an interval which has no intersection with any entry. - EXPECT_EQ(0, table_->GetCountOfEntriesContainedBetween(Time(), begin)); + EXPECT_EQ(0, table_->GetCountOfValuesContainedBetween(Time(), begin)); } TEST_F(AutofillTableTest, Autofill_RemoveBetweenChanges) {
diff --git a/components/autofill/core/browser/webdata/autofill_webdata.h b/components/autofill/core/browser/webdata/autofill_webdata.h index 310b0ec..069731cc 100644 --- a/components/autofill/core/browser/webdata/autofill_webdata.h +++ b/components/autofill/core/browser/webdata/autofill_webdata.h
@@ -74,10 +74,10 @@ virtual WebDataServiceBase::Handle GetServerProfiles( WebDataServiceConsumer* consumer) = 0; - // Schedules a task to count the number of entries contained in the time - // interval [|begin|, |end|). |begin| and |end| can be null to indicate - // no time limitation. - virtual WebDataServiceBase::Handle GetCountOfEntriesContainedBetween( + // Schedules a task to count the number of unique autofill values contained + // in the time interval [|begin|, |end|). |begin| and |end| can be null + // to indicate no time limitation. + virtual WebDataServiceBase::Handle GetCountOfValuesContainedBetween( const base::Time& begin, const base::Time& end, WebDataServiceConsumer* consumer) = 0;
diff --git a/components/autofill/core/browser/webdata/autofill_webdata_backend_impl.cc b/components/autofill/core/browser/webdata/autofill_webdata_backend_impl.cc index c696cde..655285c 100644 --- a/components/autofill/core/browser/webdata/autofill_webdata_backend_impl.cc +++ b/components/autofill/core/browser/webdata/autofill_webdata_backend_impl.cc
@@ -256,13 +256,13 @@ } scoped_ptr<WDTypedResult> - AutofillWebDataBackendImpl::GetCountOfEntriesContainedBetween( + AutofillWebDataBackendImpl::GetCountOfValuesContainedBetween( const base::Time& begin, const base::Time& end, WebDatabase* db) { DCHECK(db_thread_->BelongsToCurrentThread()); int value = AutofillTable::FromWebDatabase(db) - ->GetCountOfEntriesContainedBetween(begin, end); + ->GetCountOfValuesContainedBetween(begin, end); return scoped_ptr<WDTypedResult>( new WDResult<int>(AUTOFILL_VALUE_RESULT, value)); }
diff --git a/components/autofill/core/browser/webdata/autofill_webdata_backend_impl.h b/components/autofill/core/browser/webdata/autofill_webdata_backend_impl.h index fbd1c9c..86932b3 100644 --- a/components/autofill/core/browser/webdata/autofill_webdata_backend_impl.h +++ b/components/autofill/core/browser/webdata/autofill_webdata_backend_impl.h
@@ -111,9 +111,10 @@ scoped_ptr<WDTypedResult> GetAutofillProfiles(WebDatabase* db); scoped_ptr<WDTypedResult> GetServerProfiles(WebDatabase* db); - // Returns the number of autofill entries whose interval between creation date - // and last usage is entirely contained between [|begin|, |end|). - scoped_ptr<WDTypedResult> GetCountOfEntriesContainedBetween( + // Returns the number of values such that all for autofill entries with that + // value, the interval between creation date and last usage is entirely + // contained between [|begin|, |end|). + scoped_ptr<WDTypedResult> GetCountOfValuesContainedBetween( const base::Time& begin, const base::Time& end, WebDatabase* db);
diff --git a/components/autofill/core/browser/webdata/autofill_webdata_service.cc b/components/autofill/core/browser/webdata/autofill_webdata_service.cc index cd66d55..65124926 100644 --- a/components/autofill/core/browser/webdata/autofill_webdata_service.cc +++ b/components/autofill/core/browser/webdata/autofill_webdata_service.cc
@@ -132,10 +132,10 @@ } WebDataServiceBase::Handle - AutofillWebDataService::GetCountOfEntriesContainedBetween( + AutofillWebDataService::GetCountOfValuesContainedBetween( const Time& begin, const Time& end, WebDataServiceConsumer* consumer) { return wdbs_->ScheduleDBTaskWithResult(FROM_HERE, - Bind(&AutofillWebDataBackendImpl::GetCountOfEntriesContainedBetween, + Bind(&AutofillWebDataBackendImpl::GetCountOfValuesContainedBetween, autofill_backend_, begin, end), consumer); }
diff --git a/components/autofill/core/browser/webdata/autofill_webdata_service.h b/components/autofill/core/browser/webdata/autofill_webdata_service.h index 00ea4ed..fc2761a 100644 --- a/components/autofill/core/browser/webdata/autofill_webdata_service.h +++ b/components/autofill/core/browser/webdata/autofill_webdata_service.h
@@ -73,7 +73,7 @@ WebDataServiceBase::Handle GetServerProfiles( WebDataServiceConsumer* consumer) override; - WebDataServiceBase::Handle GetCountOfEntriesContainedBetween( + WebDataServiceBase::Handle GetCountOfValuesContainedBetween( const base::Time& begin, const base::Time& end, WebDataServiceConsumer* consumer) override;
diff --git a/components/autofill/core/common/form_data.cc b/components/autofill/core/common/form_data.cc index aaa8178f..3d68639 100644 --- a/components/autofill/core/common/form_data.cc +++ b/components/autofill/core/common/form_data.cc
@@ -4,6 +4,8 @@ #include "components/autofill/core/common/form_data.h" +#include <tuple> + #include "base/base64.h" #include "base/pickle.h" #include "base/strings/string_util.h" @@ -86,15 +88,9 @@ } bool FormData::operator<(const FormData& form) const { - if (name != form.name) - return name < form.name; - if (origin != form.origin) - return origin < form.origin; - if (action != form.action) - return action < form.action; - if (is_form_tag != form.is_form_tag) - return is_form_tag < form.is_form_tag; - return fields < form.fields; + return std::tie(name, origin, action, is_form_tag, fields) < + std::tie(form.name, form.origin, form.action, form.is_form_tag, + form.fields); } std::ostream& operator<<(std::ostream& os, const FormData& form) {
diff --git a/components/autofill/core/common/form_field_data.cc b/components/autofill/core/common/form_field_data.cc index 1ae34468e..54db610 100644 --- a/components/autofill/core/common/form_field_data.cc +++ b/components/autofill/core/common/form_field_data.cc
@@ -4,6 +4,8 @@ #include "components/autofill/core/common/form_field_data.h" +#include <tuple> + #include "base/pickle.h" #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" @@ -117,29 +119,15 @@ bool FormFieldData::operator<(const FormFieldData& field) const { // Like operator==, this ignores the value. - if (label < field.label) return true; - if (label > field.label) return false; - if (name < field.name) return true; - if (name > field.name) return false; - if (form_control_type < field.form_control_type) return true; - if (form_control_type > field.form_control_type) return false; - if (autocomplete_attribute < field.autocomplete_attribute) return true; - if (autocomplete_attribute > field.autocomplete_attribute) return false; - if (max_length < field.max_length) return true; - if (max_length > field.max_length) return false; // Skip |is_checked| and |is_autofilled| as in SameFieldAs. - if (is_checkable < field.is_checkable) return true; - if (is_checkable > field.is_checkable) return false; - if (is_focusable < field.is_focusable) return true; - if (is_focusable > field.is_focusable) return false; - if (should_autocomplete < field.should_autocomplete) return true; - if (should_autocomplete > field.should_autocomplete) return false; - if (role < field.role) return true; - if (role > field.role) return false; - if (text_direction < field.text_direction) return true; - if (text_direction > field.text_direction) return false; // See operator== above for why we don't check option_values/contents. - return false; + return std::tie(label, name, form_control_type, autocomplete_attribute, + max_length, is_checkable, is_focusable, should_autocomplete, + role, text_direction) < + std::tie(field.label, field.name, field.form_control_type, + field.autocomplete_attribute, field.max_length, + field.is_checkable, field.is_focusable, + field.should_autocomplete, field.role, field.text_direction); } void SerializeFormFieldData(const FormFieldData& field_data,
diff --git a/components/autofill/core/common/password_form_fill_data.cc b/components/autofill/core/common/password_form_fill_data.cc index 148b5c2..1c35ba2b 100644 --- a/components/autofill/core/common/password_form_fill_data.cc +++ b/components/autofill/core/common/password_form_fill_data.cc
@@ -4,6 +4,8 @@ #include "components/autofill/core/common/password_form_fill_data.h" +#include <tuple> + #include "base/strings/utf_string_conversions.h" #include "components/autofill/core/common/form_field_data.h" @@ -15,11 +17,8 @@ bool UsernamesCollectionKey::operator<( const UsernamesCollectionKey& other) const { - if (username != other.username) - return username < other.username; - if (password != other.password) - return password < other.password; - return realm < other.realm; + return std::tie(username, password, realm) < + std::tie(other.username, other.password, other.realm); } PasswordFormFillData::PasswordFormFillData()
diff --git a/components/autofill/ios/browser/BUILD.gn b/components/autofill/ios/browser/BUILD.gn index 63dcd96..b15bbb1 100644 --- a/components/autofill/ios/browser/BUILD.gn +++ b/components/autofill/ios/browser/BUILD.gn
@@ -23,11 +23,11 @@ ] deps = [ + ":injected_js", "//components/autofill/core/browser", "//components/autofill/core/common", "//ios/public/provider/web", "//ios/web", - ":injected_js", ] }
diff --git a/components/bitmap_uploader/BUILD.gn b/components/bitmap_uploader/BUILD.gn index 4f48ee20..496565c4 100644 --- a/components/bitmap_uploader/BUILD.gn +++ b/components/bitmap_uploader/BUILD.gn
@@ -12,8 +12,8 @@ deps = [ "//base", - "//components/mus/public/interfaces", "//components/mus/public/cpp", + "//components/mus/public/interfaces", "//gpu", "//mojo/converters/surfaces", "//mojo/public/c/gles2",
diff --git a/components/browser_sync/browser/BUILD.gn b/components/browser_sync/browser/BUILD.gn index e2123ce..bd7cb88 100644 --- a/components/browser_sync/browser/BUILD.gn +++ b/components/browser_sync/browser/BUILD.gn
@@ -27,10 +27,10 @@ "//components/pref_registry", "//components/signin/core/browser", "//components/strings", - "//components/syncable_prefs", "//components/sync_bookmarks", "//components/sync_driver", "//components/sync_sessions", + "//components/syncable_prefs", "//components/variations", "//components/version_info", "//components/version_info:generate_version_info",
diff --git a/components/cdm/common/BUILD.gn b/components/cdm/common/BUILD.gn index 6ca677c..25cd70b 100644 --- a/components/cdm/common/BUILD.gn +++ b/components/cdm/common/BUILD.gn
@@ -12,7 +12,7 @@ deps = [ "//base", "//content/public/common", - "//media", "//ipc", + "//media", ] }
diff --git a/components/chrome_apps/BUILD.gn b/components/chrome_apps/BUILD.gn index a5595001..6b7b67ae 100644 --- a/components/chrome_apps/BUILD.gn +++ b/components/chrome_apps/BUILD.gn
@@ -22,8 +22,8 @@ "chrome_apps_resource_util.h", ] deps = [ - "//base", ":resources", + "//base", ] defines = [ "CHROME_APPS_IMPLEMENTATION" ] }
diff --git a/components/clipboard/clipboard_apptest.cc b/components/clipboard/clipboard_apptest.cc index 081fac3..1f009704 100644 --- a/components/clipboard/clipboard_apptest.cc +++ b/components/clipboard/clipboard_apptest.cc
@@ -54,9 +54,7 @@ void SetUp() override { mojo::test::ApplicationTestBase::SetUp(); - mojo::URLRequestPtr request(mojo::URLRequest::New()); - request->url = mojo::String::From("mojo:clipboard"); - application_impl()->ConnectToService(request.Pass(), &clipboard_); + application_impl()->ConnectToService("mojo:clipboard", &clipboard_); } uint64_t GetSequenceNumber() {
diff --git a/components/component_updater/BUILD.gn b/components/component_updater/BUILD.gn index a868cdd..1f9cfb4 100644 --- a/components/component_updater/BUILD.gn +++ b/components/component_updater/BUILD.gn
@@ -44,7 +44,7 @@ "//base", "//base/test:test_support", "//components/update_client:test_support", - "//testing/gtest", "//testing/gmock", + "//testing/gtest", ] }
diff --git a/components/components_tests.gyp b/components/components_tests.gyp index 4eb1410..067b2665 100644 --- a/components/components_tests.gyp +++ b/components/components_tests.gyp
@@ -359,6 +359,13 @@ 'metrics/stability_metrics_helper_unittest.cc', 'metrics/ui/screen_info_metrics_provider_unittest.cc', ], + 'metrics_leak_detector_unittest_sources': [ + 'metrics/leak_detector/call_stack_manager_unittest.cc', + 'metrics/leak_detector/call_stack_table_unittest.cc', + 'metrics/leak_detector/leak_analyzer_unittest.cc', + 'metrics/leak_detector/leak_detector_impl_unittest.cc', + 'metrics/leak_detector/ranked_list_unittest.cc', + ], 'mime_util_unittest_sources': [ 'mime_util/mime_util_unittest.cc', ], @@ -536,7 +543,6 @@ 'proximity_auth/bluetooth_connection_unittest.cc', 'proximity_auth/bluetooth_throttler_impl_unittest.cc', 'proximity_auth/connection_unittest.cc', - 'proximity_auth/cryptauth/base64url_unittest.cc', 'proximity_auth/cryptauth/cryptauth_access_token_fetcher_impl_unittest.cc', 'proximity_auth/cryptauth/cryptauth_api_call_flow_unittest.cc', 'proximity_auth/cryptauth/cryptauth_client_impl_unittest.cc', @@ -601,6 +607,7 @@ 'scheduler/base/test_always_fail_time_source.h', 'scheduler/base/test_time_source.cc', 'scheduler/base/test_time_source.h', + 'scheduler/base/time_domain_unittest.cc', 'scheduler/child/idle_helper_unittest.cc', 'scheduler/child/scheduler_helper_unittest.cc', 'scheduler/child/scheduler_tqm_delegate_for_test.cc', @@ -1371,6 +1378,7 @@ 'wifi_sync/wifi_credential_unittest.cc', 'wifi_sync/wifi_security_class_chromeos_unittest.cc', 'wifi_sync/wifi_security_class_unittest.cc', + '<@(metrics_leak_detector_unittest_sources)', '<@(ownership_unittest_sources)', ], 'sources!': [ @@ -1379,6 +1387,7 @@ ], 'dependencies': [ '../chromeos/chromeos.gyp:chromeos_test_support', + 'components.gyp:metrics_leak_detector', 'components.gyp:ownership', 'components.gyp:pairing', 'components.gyp:user_manager_test_support', @@ -1609,7 +1618,7 @@ ], }, 'includes': [ '../build/host_jar.gypi' ], - }, + }, ], 'conditions': [ ['test_isolation_mode != "noop"',
diff --git a/components/constrained_window/BUILD.gn b/components/constrained_window/BUILD.gn index 01257f8d..8e0952e 100644 --- a/components/constrained_window/BUILD.gn +++ b/components/constrained_window/BUILD.gn
@@ -12,8 +12,8 @@ deps = [ "//components/guest_view/browser", "//components/web_modal", - "//ui/views", "//skia", + "//ui/views", ] }
diff --git a/components/content_settings/core/browser/content_settings_origin_identifier_value_map.cc b/components/content_settings/core/browser/content_settings_origin_identifier_value_map.cc index d51e624..0c3ab90 100644 --- a/components/content_settings/core/browser/content_settings_origin_identifier_value_map.cc +++ b/components/content_settings/core/browser/content_settings_origin_identifier_value_map.cc
@@ -4,6 +4,8 @@ #include "components/content_settings/core/browser/content_settings_origin_identifier_value_map.h" +#include <tuple> + #include "base/compiler_specific.h" #include "base/logging.h" #include "base/memory/scoped_ptr.h" @@ -61,9 +63,8 @@ bool OriginIdentifierValueMap::EntryMapKey::operator<( const OriginIdentifierValueMap::EntryMapKey& other) const { - if (content_type != other.content_type) - return content_type < other.content_type; - return (resource_identifier < other.resource_identifier); + return std::tie(content_type, resource_identifier) < + std::tie(other.content_type, other.resource_identifier); } OriginIdentifierValueMap::PatternPair::PatternPair( @@ -78,11 +79,8 @@ // Note that this operator is the other way around than // |ContentSettingsPattern::operator<|. It sorts patterns with higher // precedence first. - if (primary_pattern > other.primary_pattern) - return true; - else if (other.primary_pattern > primary_pattern) - return false; - return (secondary_pattern > other.secondary_pattern); + return std::tie(primary_pattern, secondary_pattern) > + std::tie(other.primary_pattern, other.secondary_pattern); } RuleIterator* OriginIdentifierValueMap::GetRuleIterator(
diff --git a/components/copresence/BUILD.gn b/components/copresence/BUILD.gn index 06d9d53..63ddbefdd 100644 --- a/components/copresence/BUILD.gn +++ b/components/copresence/BUILD.gn
@@ -81,7 +81,7 @@ "//components/copresence/proto", "//components/gcm_driver:test_support", "//net:test_support", - "//testing/gtest", "//testing/gmock", + "//testing/gtest", ] }
diff --git a/components/crash/content/app/BUILD.gn b/components/crash/content/app/BUILD.gn index 0d84e5e..cc610d6 100644 --- a/components/crash/content/app/BUILD.gn +++ b/components/crash/content/app/BUILD.gn
@@ -115,8 +115,8 @@ if (is_win) { deps += [ - "//sandbox", "//breakpad:breakpad_handler", + "//sandbox", #'../breakpad/breakpad.gyp:breakpad_sender', TODO(GYP) ]
diff --git a/components/crash/core/common/BUILD.gn b/components/crash/core/common/BUILD.gn index 07aad2b..e602f4e 100644 --- a/components/crash/core/common/BUILD.gn +++ b/components/crash/core/common/BUILD.gn
@@ -27,9 +27,9 @@ "objc_zombie_unittest.mm", ] deps = [ + ":common", "//base", "//testing/gtest", - ":common", ] } }
diff --git a/components/data_reduction_proxy/content/browser/BUILD.gn b/components/data_reduction_proxy/content/browser/BUILD.gn index 9a2650b..fdc5ad9 100644 --- a/components/data_reduction_proxy/content/browser/BUILD.gn +++ b/components/data_reduction_proxy/content/browser/BUILD.gn
@@ -58,8 +58,8 @@ "//content/public/common", "//content/test:test_support", "//net:test_support", - "//testing/gtest", "//testing/gmock", + "//testing/gtest", ] if (is_android) {
diff --git a/components/devtools_service/devtools_http_server.cc b/components/devtools_service/devtools_http_server.cc index 6ae3a340..1555e46 100644 --- a/components/devtools_service/devtools_http_server.cc +++ b/components/devtools_service/devtools_http_server.cc
@@ -335,9 +335,8 @@ VLOG(1) << "Remote debugging HTTP server is started on port " << remote_debugging_port << "."; mojo::NetworkServicePtr network_service; - mojo::URLRequestPtr request(mojo::URLRequest::New()); - request->url = "mojo:network_service"; - service_->application()->ConnectToService(request.Pass(), &network_service); + service_->application()->ConnectToService("mojo:network_service", + &network_service); mojo::NetAddressPtr local_address(mojo::NetAddress::New()); local_address->family = mojo::NET_ADDRESS_FAMILY_IPV4;
diff --git a/components/dom_distiller/standalone/content_extractor_browsertest.cc b/components/dom_distiller/standalone/content_extractor_browsertest.cc index de20ade..ca7a454 100644 --- a/components/dom_distiller/standalone/content_extractor_browsertest.cc +++ b/components/dom_distiller/standalone/content_extractor_browsertest.cc
@@ -112,6 +112,9 @@ // "kUrlsSwitch". const char* kOriginalUrls = "original-urls"; +// The pagination algorithm to use, one of "next", "pagenum". +const char* kPaginationAlgo = "pagination-algo"; + // Maximum number of concurrent started extractor requests. const int kMaxExtractorTasks = 8; @@ -148,6 +151,16 @@ &debug_level)) { options.set_debug_level(debug_level); } + // Options for pagination algorithm: + // - "next": detect anchors with "next" text + // - "pagenum": detect anchors with numeric page numbers + // Default is "next". + if (base::CommandLine::ForCurrentProcess()->HasSwitch(kPaginationAlgo)) { + options.set_pagination_algo( + base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII( + kPaginationAlgo)); + } + scoped_ptr<DistillerFactory> distiller_factory( new TestDistillerFactoryImpl(distiller_url_fetcher_factory.Pass(), options,
diff --git a/components/drive/BUILD.gn b/components/drive/BUILD.gn index e8329209..c1957fb 100644 --- a/components/drive/BUILD.gn +++ b/components/drive/BUILD.gn
@@ -110,7 +110,6 @@ # TODO(lukasza): Remove this dependency (see DEPS file for more info). "//content/public/browser", - "//google_apis:google_apis", "//net:net", "//third_party/cacheinvalidation",
diff --git a/components/exo.gypi b/components/exo.gypi index a757de7..63bcfdf 100644 --- a/components/exo.gypi +++ b/components/exo.gypi
@@ -66,6 +66,13 @@ 'exo/wayland/server.cc', 'exo/wayland/server.h', ], + 'conditions': [ + ['use_ozone==1', { + 'dependencies': [ + '../third_party/mesa/mesa.gyp:wayland_drm_protocol', + ], + }], + ], }, ], }],
diff --git a/components/exo/display.cc b/components/exo/display.cc index b13c7fe..51a353ac 100644 --- a/components/exo/display.cc +++ b/components/exo/display.cc
@@ -11,6 +11,14 @@ #include "components/exo/sub_surface.h" #include "components/exo/surface.h" +#if defined(USE_OZONE) +#include "components/exo/buffer.h" +#include "gpu/command_buffer/client/gpu_memory_buffer_manager.h" +#include "third_party/khronos/GLES2/gl2.h" +#include "third_party/khronos/GLES2/gl2ext.h" +#include "ui/aura/env.h" +#endif + namespace exo { //////////////////////////////////////////////////////////////////////////////// @@ -37,6 +45,33 @@ return make_scoped_ptr(new SharedMemory(handle)); } +#if defined(USE_OZONE) +scoped_ptr<Buffer> Display::CreatePrimeBuffer(base::ScopedFD fd, + const gfx::Size& size, + gfx::BufferFormat format, + int stride) { + TRACE_EVENT1("exo", "Display::CreatePrimeBuffer", "size", size.ToString()); + + gfx::GpuMemoryBufferHandle handle; + handle.type = gfx::OZONE_NATIVE_PIXMAP; + handle.native_pixmap_handle.fd = base::FileDescriptor(fd.Pass()); + handle.native_pixmap_handle.stride = stride; + + scoped_ptr<gfx::GpuMemoryBuffer> gpu_memory_buffer = + aura::Env::GetInstance() + ->context_factory() + ->GetGpuMemoryBufferManager() + ->CreateGpuMemoryBufferFromHandle(handle, size, format); + if (!gpu_memory_buffer) { + LOG(ERROR) << "Failed to create GpuMemoryBuffer from handle"; + return nullptr; + } + + return make_scoped_ptr( + new Buffer(gpu_memory_buffer.Pass(), GL_TEXTURE_EXTERNAL_OES)); +} +#endif + scoped_ptr<ShellSurface> Display::CreateShellSurface(Surface* surface) { TRACE_EVENT1("exo", "Display::CreateShellSurface", "surface", surface->AsTracedValue());
diff --git a/components/exo/display.h b/components/exo/display.h index 41099509a..92a4c1c 100644 --- a/components/exo/display.h +++ b/components/exo/display.h
@@ -9,12 +9,22 @@ #include "base/memory/scoped_ptr.h" #include "base/memory/shared_memory_handle.h" +#if defined(USE_OZONE) +#include "base/files/scoped_file.h" +#include "ui/gfx/buffer_types.h" +#include "ui/gfx/geometry/size.h" +#endif + namespace exo { class SharedMemory; class ShellSurface; class SubSurface; class Surface; +#if defined(USE_OZONE) +class Buffer; +#endif + // The core display class. This class provides functions for creating surfaces // and is in charge of combining the contents of multiple surfaces into one // displayable output. @@ -32,6 +42,14 @@ const base::SharedMemoryHandle& handle, size_t size); +#if defined(USE_OZONE) + // Creates a buffer for the prime fd. + scoped_ptr<Buffer> CreatePrimeBuffer(base::ScopedFD fd, + const gfx::Size& size, + gfx::BufferFormat format, + int stride); +#endif + // Creates a shell surface for an existing surface. scoped_ptr<ShellSurface> CreateShellSurface(Surface* surface);
diff --git a/components/exo/display_unittest.cc b/components/exo/display_unittest.cc index f79aae65..2e122096 100644 --- a/components/exo/display_unittest.cc +++ b/components/exo/display_unittest.cc
@@ -11,6 +11,12 @@ #include "components/exo/test/exo_test_base.h" #include "testing/gtest/include/gtest/gtest.h" +#if defined(USE_OZONE) +#include "ui/ozone/public/native_pixmap.h" +#include "ui/ozone/public/ozone_platform.h" +#include "ui/ozone/public/surface_factory_ozone.h" +#endif + namespace exo { namespace { @@ -46,6 +52,33 @@ EXPECT_FALSE(shm2); } +#if defined(USE_OZONE) +TEST_F(DisplayTest, CreatePrimeBuffer) { + const gfx::Size buffer_size(256, 256); + + scoped_ptr<Display> display(new Display); + + // Creating a prime buffer from a native pixmap handle should succeed. + scoped_refptr<ui::NativePixmap> pixmap = + ui::OzonePlatform::GetInstance() + ->GetSurfaceFactoryOzone() + ->CreateNativePixmap(gfx::kNullAcceleratedWidget, buffer_size, + gfx::BufferFormat::RGBA_8888, + gfx::BufferUsage::GPU_READ); + gfx::NativePixmapHandle native_pixmap_handle = pixmap->ExportHandle(); + scoped_ptr<Buffer> buffer1 = display->CreatePrimeBuffer( + base::ScopedFD(native_pixmap_handle.fd.fd), buffer_size, + gfx::BufferFormat::RGBA_8888, native_pixmap_handle.stride); + EXPECT_TRUE(buffer1); + + // Creating a prime buffer using an invalid fd should fail. + scoped_ptr<Buffer> buffer2 = display->CreatePrimeBuffer( + base::ScopedFD(), buffer_size, gfx::BufferFormat::RGBA_8888, + buffer_size.width() * 4); + EXPECT_FALSE(buffer2); +} +#endif + TEST_F(DisplayTest, CreateShellSurface) { scoped_ptr<Display> display(new Display);
diff --git a/components/exo/wayland/BUILD.gn b/components/exo/wayland/BUILD.gn index 2041108..67d6d63 100644 --- a/components/exo/wayland/BUILD.gn +++ b/components/exo/wayland/BUILD.gn
@@ -2,6 +2,8 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +import("//build/config/ui.gni") + source_set("wayland") { sources = [ "scoped_wl_types.cc", @@ -18,6 +20,10 @@ "//skia", "//third_party/wayland:wayland_server", ] + + if (use_ozone) { + deps += [ "//third_party/mesa:wayland_drm_protocol" ] + } } source_set("unit_tests") { @@ -28,8 +34,8 @@ ] deps = [ + ":wayland", "//testing/gtest", "//third_party/wayland:wayland_client", - ":wayland", ] }
diff --git a/components/exo/wayland/server.cc b/components/exo/wayland/server.cc index 89bc961b..7cc2250 100644 --- a/components/exo/wayland/server.cc +++ b/components/exo/wayland/server.cc
@@ -20,6 +20,10 @@ #include "components/exo/surface.h" #include "third_party/skia/include/core/SkRegion.h" +#if defined(USE_OZONE) +#include <wayland-drm-server-protocol.h> +#endif + namespace exo { namespace wayland { namespace { @@ -270,7 +274,7 @@ int32_t height, int32_t stride, uint32_t format) { - const auto supported_format = + const auto* supported_format = std::find_if(shm_supported_formats, shm_supported_formats + arraysize(shm_supported_formats), [format](const shm_supported_format& supported_format) { @@ -365,6 +369,123 @@ } //////////////////////////////////////////////////////////////////////////////// +// wl_drm_interface: + +#if defined(USE_OZONE) +const struct drm_supported_format { + uint32_t drm_format; + gfx::BufferFormat buffer_format; +} drm_supported_formats[] = { + {WL_DRM_FORMAT_XBGR8888, gfx::BufferFormat::RGBX_8888}, + {WL_DRM_FORMAT_ABGR8888, gfx::BufferFormat::RGBA_8888}, + {WL_DRM_FORMAT_XRGB8888, gfx::BufferFormat::BGRX_8888}, + {WL_DRM_FORMAT_ARGB8888, gfx::BufferFormat::BGRA_8888}}; + +void drm_authenticate(wl_client* client, wl_resource* resource, uint32_t id) { + wl_drm_send_authenticated(resource); +} + +void drm_create_buffer(wl_client* client, + wl_resource* resource, + uint32_t id, + uint32_t name, + int32_t width, + int32_t height, + uint32_t stride, + uint32_t format) { + wl_resource_post_error(resource, WL_DRM_ERROR_INVALID_NAME, + "GEM names are not supported"); +} + +void drm_create_planar_buffer(wl_client* client, + wl_resource* resource, + uint32_t id, + uint32_t name, + int32_t width, + int32_t height, + uint32_t format, + int32_t offset0, + int32_t stride0, + int32_t offset1, + int32_t stride1, + int32_t offset2, + int32_t stride3) { + wl_resource_post_error(resource, WL_DRM_ERROR_INVALID_NAME, + "GEM names are not supported"); +} + +void drm_create_prime_buffer(wl_client* client, + wl_resource* resource, + uint32_t id, + int32_t name, + int32_t width, + int32_t height, + uint32_t format, + int32_t offset0, + int32_t stride0, + int32_t offset1, + int32_t stride1, + int32_t offset2, + int32_t stride2) { + const auto* supported_format = + std::find_if(drm_supported_formats, + drm_supported_formats + arraysize(drm_supported_formats), + [format](const drm_supported_format& supported_format) { + return supported_format.drm_format == format; + }); + if (supported_format == + (drm_supported_formats + arraysize(drm_supported_formats))) { + wl_resource_post_error(resource, WL_DRM_ERROR_INVALID_FORMAT, + "invalid format 0x%x", format); + return; + } + + scoped_ptr<Buffer> buffer = + GetUserDataAs<Display>(resource) + ->CreatePrimeBuffer(base::ScopedFD(name), gfx::Size(width, height), + supported_format->buffer_format, stride0); + if (!buffer) { + wl_resource_post_no_memory(resource); + return; + } + + wl_resource* buffer_resource = + wl_resource_create(client, &wl_buffer_interface, 1, id); + if (!buffer_resource) { + wl_resource_post_no_memory(resource); + return; + } + + buffer->set_release_callback( + base::Bind(&wl_buffer_send_release, base::Unretained(buffer_resource))); + + SetImplementation(buffer_resource, &buffer_implementation, buffer.Pass()); +} + +const struct wl_drm_interface drm_implementation = { + drm_authenticate, drm_create_buffer, drm_create_planar_buffer, + drm_create_prime_buffer}; + +const uint32_t drm_version = 2; + +void bind_drm(wl_client* client, void* data, uint32_t version, uint32_t id) { + wl_resource* resource = wl_resource_create( + client, &wl_drm_interface, std::min(version, drm_version), id); + if (!resource) { + wl_client_post_no_memory(client); + return; + } + wl_resource_set_implementation(resource, &drm_implementation, data, nullptr); + + if (version >= 2) + wl_drm_send_capabilities(resource, WL_DRM_CAPABILITY_PRIME); + + for (const auto& supported_format : drm_supported_formats) + wl_drm_send_format(resource, supported_format.drm_format); +} +#endif + +//////////////////////////////////////////////////////////////////////////////// // wl_subsurface_interface: void subsurface_destroy(wl_client* client, wl_resource* resource) { @@ -584,6 +705,10 @@ wl_global_create(wl_display_.get(), &wl_compositor_interface, compositor_version, display_, bind_compositor); wl_global_create(wl_display_.get(), &wl_shm_interface, 1, display_, bind_shm); +#if defined(USE_OZONE) + wl_global_create(wl_display_.get(), &wl_drm_interface, drm_version, display_, + bind_drm); +#endif wl_global_create(wl_display_.get(), &wl_subcompositor_interface, 1, display_, bind_subcompositor); wl_global_create(wl_display_.get(), &wl_shell_interface, 1, display_,
diff --git a/components/feedback/BUILD.gn b/components/feedback/BUILD.gn index 022de4a..f126e05 100644 --- a/components/feedback/BUILD.gn +++ b/components/feedback/BUILD.gn
@@ -28,9 +28,9 @@ deps = [ "//base", - "//components/keyed_service/core", - "//components/keyed_service/content", "//components/feedback/proto", + "//components/keyed_service/content", + "//components/keyed_service/core", "//components/variations/net", "//content/public/browser", "//content/public/common",
diff --git a/components/filesystem/files_test_base.cc b/components/filesystem/files_test_base.cc index bf7a3d03..3ed9a61a 100644 --- a/components/filesystem/files_test_base.cc +++ b/components/filesystem/files_test_base.cc
@@ -19,10 +19,7 @@ void FilesTestBase::SetUp() { ApplicationTestBase::SetUp(); - - mojo::URLRequestPtr request(mojo::URLRequest::New()); - request->url = mojo::String::From("mojo:filesystem"); - application_impl()->ConnectToService(request.Pass(), &files_); + application_impl()->ConnectToService("mojo:filesystem", &files_); } void FilesTestBase::OnFileSystemShutdown() {
diff --git a/components/font_service/public/cpp/font_loader.cc b/components/font_service/public/cpp/font_loader.cc index f029349..da04518 100644 --- a/components/font_service/public/cpp/font_loader.cc +++ b/components/font_service/public/cpp/font_loader.cc
@@ -30,10 +30,8 @@ } FontLoader::FontLoader(mojo::ApplicationImpl* application_impl) { - mojo::URLRequestPtr request(mojo::URLRequest::New()); - request->url = mojo::String::From("mojo:font_service"); FontServicePtr font_service; - application_impl->ConnectToService(request.Pass(), &font_service); + application_impl->ConnectToService("mojo:font_service", &font_service); thread_ = new internal::FontServiceThread(font_service.Pass()); }
diff --git a/components/gcm_driver/BUILD.gn b/components/gcm_driver/BUILD.gn index 46c35eb..65ea0e4 100644 --- a/components/gcm_driver/BUILD.gn +++ b/components/gcm_driver/BUILD.gn
@@ -58,7 +58,6 @@ ] deps = [ - "crypto", "//base", "//components/gcm_driver/common", "//components/os_crypt", @@ -67,6 +66,7 @@ "//net", "//sync/protocol", "//url:url", + "crypto", ] if (is_chromeos) {
diff --git a/components/gcm_driver/crypto/BUILD.gn b/components/gcm_driver/crypto/BUILD.gn index 95dc4125..d1b7f30 100644 --- a/components/gcm_driver/crypto/BUILD.gn +++ b/components/gcm_driver/crypto/BUILD.gn
@@ -24,12 +24,12 @@ ] deps = [ - "proto", "//base", + "//components/leveldb_proto", "//crypto", "//crypto:platform", - "//components/leveldb_proto", "//third_party/protobuf:protobuf_lite", + "proto", ] if (use_openssl) {
diff --git a/components/gcm_driver/crypto/p256_key_util.cc b/components/gcm_driver/crypto/p256_key_util.cc index 7fd38b561..6f577f4 100644 --- a/components/gcm_driver/crypto/p256_key_util.cc +++ b/components/gcm_driver/crypto/p256_key_util.cc
@@ -9,7 +9,6 @@ #include "base/logging.h" #include "base/memory/scoped_ptr.h" -#include "base/stl_util.h" #include "crypto/ec_private_key.h" namespace gcm { @@ -72,11 +71,10 @@ return false; } - out_private_key->assign( - reinterpret_cast<const char*>(vector_as_array(&private_key)), - private_key.size()); + out_private_key->assign(reinterpret_cast<const char*>(private_key.data()), + private_key.size()); out_public_key_x509->assign( - reinterpret_cast<const char*>(vector_as_array(&public_key_x509)), + reinterpret_cast<const char*>(public_key_x509.data()), public_key_x509.size()); // Concatenate the leading 0x04 byte and the two uncompressed points.
diff --git a/components/gcm_driver/instance_id/BUILD.gn b/components/gcm_driver/instance_id/BUILD.gn index 4b578d3..4da83de 100644 --- a/components/gcm_driver/instance_id/BUILD.gn +++ b/components/gcm_driver/instance_id/BUILD.gn
@@ -15,8 +15,8 @@ deps = [ "//base", - "//crypto", "//components/gcm_driver", + "//crypto", ] if (is_android) {
diff --git a/components/guest_view/browser/guest_view_manager.cc b/components/guest_view/browser/guest_view_manager.cc index 4c86e9d1..c93f9530 100644 --- a/components/guest_view/browser/guest_view_manager.cc +++ b/components/guest_view/browser/guest_view_manager.cc
@@ -4,6 +4,8 @@ #include "components/guest_view/browser/guest_view_manager.h" +#include <tuple> + #include "base/macros.h" #include "base/strings/stringprintf.h" #include "components/guest_view/browser/guest_view_base.h" @@ -476,10 +478,8 @@ bool GuestViewManager::ElementInstanceKey::operator<( const GuestViewManager::ElementInstanceKey& other) const { - if (embedder_process_id != other.embedder_process_id) - return embedder_process_id < other.embedder_process_id; - - return element_instance_id < other.element_instance_id; + return std::tie(embedder_process_id, element_instance_id) < + std::tie(other.embedder_process_id, other.element_instance_id); } bool GuestViewManager::ElementInstanceKey::operator==(
diff --git a/components/html_viewer/BUILD.gn b/components/html_viewer/BUILD.gn index 95d6539..447d0a22 100644 --- a/components/html_viewer/BUILD.gn +++ b/components/html_viewer/BUILD.gn
@@ -164,16 +164,16 @@ "//components/resource_provider/public/interfaces", "//components/scheduler:scheduler", "//components/startup_metric_utils/browser:lib", - "//components/webcrypto", "//components/web_view:switches", "//components/web_view/public/interfaces", + "//components/webcrypto", "//gin", - "//gpu/command_buffer/common:gles2_utils", "//gpu/blink:blink", + "//gpu/command_buffer/common:gles2_utils", "//media", + "//media:shared_memory_support", "//media/blink", "//media/mojo", - "//media:shared_memory_support", "//mojo/application/public/cpp", "//mojo/application/public/interfaces", "//mojo/common", @@ -190,9 +190,9 @@ "//mojo/services/tracing/public/interfaces", "//net", "//skia", - "//third_party/mojo_services/src/accessibility/public/interfaces", "//third_party/WebKit/public:image_resources", "//third_party/WebKit/public:resources", + "//third_party/mojo_services/src/accessibility/public/interfaces", "//ui/base:base", "//ui/events", "//ui/events:gesture_detection", @@ -367,6 +367,7 @@ "//components/web_view/public/interfaces", "//mojo/application/public/cpp:sources", "//mojo/application/public/cpp:test_support", + "//mojo/converters/network", "//mojo/public/c/system:for_shared_library", "//net:test_support", "//testing/gtest",
diff --git a/components/html_viewer/DEPS b/components/html_viewer/DEPS index 75ddf750..21d04e94 100644 --- a/components/html_viewer/DEPS +++ b/components/html_viewer/DEPS
@@ -26,6 +26,7 @@ "+mojo/common", "+mojo/converters/geometry", "+mojo/converters/input_events", + "+mojo/converters/network", "+mojo/converters/surfaces", "+mojo/gles2", "+mojo/gpu",
diff --git a/components/html_viewer/ax_provider_apptest.cc b/components/html_viewer/ax_provider_apptest.cc index 431356e9..fa040623 100644 --- a/components/html_viewer/ax_provider_apptest.cc +++ b/components/html_viewer/ax_provider_apptest.cc
@@ -14,6 +14,7 @@ #include "components/web_view/public/interfaces/frame.mojom.h" #include "mojo/application/public/cpp/application_impl.h" #include "mojo/application/public/cpp/application_test_base.h" +#include "mojo/converters/network/network_type_converters.h" #include "net/test/embedded_test_server/embedded_test_server.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/mojo_services/src/accessibility/public/interfaces/accessibility.mojom.h" @@ -77,12 +78,9 @@ ASSERT_TRUE(server.Start()); // Connect to the URL through the mojo:html_viewer content handler. - const uint16_t assigned_port = server.host_port_pair().port(); - mojo::URLRequestPtr request(mojo::URLRequest::New()); - request->url = mojo::String::From( - base::StringPrintf("http://127.0.0.1:%u/test.html", assigned_port)); scoped_ptr<ApplicationConnection> connection = - application_impl()->ConnectToApplication(request.Pass()); + application_impl()->ConnectToApplication( + server.GetURL("/test.html").spec()); // Embed the html_viewer in a Window. mus::mojom::WindowTreeClientPtr tree_client;
diff --git a/components/html_viewer/blink_platform_impl.cc b/components/html_viewer/blink_platform_impl.cc index f7a13723..c50fb5e 100644 --- a/components/html_viewer/blink_platform_impl.cc +++ b/components/html_viewer/blink_platform_impl.cc
@@ -8,7 +8,6 @@ #include "base/command_line.h" #include "base/rand_util.h" -#include "base/stl_util.h" #include "base/synchronization/waitable_event.h" #include "base/thread_task_runner_handle.h" #include "base/threading/platform_thread.h" @@ -77,10 +76,8 @@ main_thread_task_runner_(renderer_scheduler->DefaultTaskRunner()), main_thread_(renderer_scheduler->CreateMainThread()) { if (app) { - mojo::URLRequestPtr request(mojo::URLRequest::New()); - request->url = mojo::String::From("mojo:network_service"); scoped_ptr<mojo::ApplicationConnection> connection = - app->ConnectToApplication(request.Pass()); + app->ConnectToApplication("mojo:network_service"); connection->ConnectToService(&web_socket_factory_); connection->ConnectToService(&url_loader_factory_); @@ -89,9 +86,7 @@ cookie_jar_.reset(new WebCookieJarImpl(cookie_store.Pass())); mojo::ClipboardPtr clipboard; - mojo::URLRequestPtr request2(mojo::URLRequest::New()); - request2->url = mojo::String::From("mojo:clipboard"); - app->ConnectToService(request2.Pass(), &clipboard); + app->ConnectToService("mojo:clipboard", &clipboard); clipboard_.reset(new WebClipboardImpl(clipboard.Pass())); } } @@ -290,8 +285,7 @@ std::vector<base::WaitableEvent*> events; for (size_t i = 0; i < web_events.size(); ++i) events.push_back(static_cast<WebWaitableEventImpl*>(web_events[i])->impl()); - size_t idx = base::WaitableEvent::WaitMany( - vector_as_array(&events), events.size()); + size_t idx = base::WaitableEvent::WaitMany(events.data(), events.size()); DCHECK_LT(idx, web_events.size()); return web_events[idx]; }
diff --git a/components/html_viewer/devtools_agent_impl.cc b/components/html_viewer/devtools_agent_impl.cc index bc4c871..a547062a 100644 --- a/components/html_viewer/devtools_agent_impl.cc +++ b/components/html_viewer/devtools_agent_impl.cc
@@ -21,7 +21,7 @@ if (state) { cache_until_client_ready_ = true; - frame_->devToolsAgent()->reattach(blink::WebString::fromUTF8(id_), + frame_->devToolsAgent()->reattach(blink::WebString::fromUTF8(id_), 0, blink::WebString::fromUTF8(*state)); } } @@ -52,16 +52,17 @@ message.state); cached_client_messages_.clear(); } else { - frame_->devToolsAgent()->attach(blink::WebString::fromUTF8(id_)); + frame_->devToolsAgent()->attach(blink::WebString::fromUTF8(id_), 0); } } void DevToolsAgentImpl::DispatchProtocolMessage(const mojo::String& message) { frame_->devToolsAgent()->dispatchOnInspectorBackend( - blink::WebString::fromUTF8(message)); + 0, blink::WebString::fromUTF8(message)); } -void DevToolsAgentImpl::sendProtocolMessage(int call_id, +void DevToolsAgentImpl::sendProtocolMessage(int session_id, + int call_id, const blink::WebString& response, const blink::WebString& state) { DCHECK(!response.isNull());
diff --git a/components/html_viewer/devtools_agent_impl.h b/components/html_viewer/devtools_agent_impl.h index 85da5fd..8b942d4 100644 --- a/components/html_viewer/devtools_agent_impl.h +++ b/components/html_viewer/devtools_agent_impl.h
@@ -38,7 +38,8 @@ void DispatchProtocolMessage(const mojo::String& message) override; // blink::WebDevToolsAgentClient implementation. - void sendProtocolMessage(int call_id, + void sendProtocolMessage(int session_id, + int call_id, const blink::WebString& response, const blink::WebString& state);
diff --git a/components/html_viewer/global_state.cc b/components/html_viewer/global_state.cc index 9d7f46b..dea9891e 100644 --- a/components/html_viewer/global_state.cc +++ b/components/html_viewer/global_state.cc
@@ -124,9 +124,7 @@ DisplaysFromSizeAndScale(screen_size_in_pixels_, device_pixel_ratio_))); base::DiscardableMemoryAllocator::SetInstance(&discardable_memory_allocator_); - mojo::URLRequestPtr request(mojo::URLRequest::New()); - request->url = mojo::String::From("mojo:mus"); - app_->ConnectToService(request.Pass(), &gpu_service_); + app_->ConnectToService("mojo:mus", &gpu_service_); gpu_service_->GetGpuInfo(base::Bind(&GlobalState::GetGpuInfoCallback, base::Unretained(this)));
diff --git a/components/html_viewer/html_document_application_delegate.cc b/components/html_viewer/html_document_application_delegate.cc index db537c6b..8bdbc35 100644 --- a/components/html_viewer/html_document_application_delegate.cc +++ b/components/html_viewer/html_document_application_delegate.cc
@@ -91,11 +91,7 @@ // ApplicationDelegate; void HTMLDocumentApplicationDelegate::Initialize(mojo::ApplicationImpl* app) { - mojo::URLRequestPtr request(mojo::URLRequest::New()); - request->url = mojo::String::From("mojo:network_service"); - scoped_ptr<mojo::ApplicationConnection> connection = - app_.ConnectToApplication(request.Pass()); - connection->ConnectToService(&url_loader_factory_); + app_.ConnectToService("mojo:network_service", &url_loader_factory_); } bool HTMLDocumentApplicationDelegate::ConfigureIncomingConnection(
diff --git a/components/html_viewer/html_widget.cc b/components/html_viewer/html_widget.cc index 5a60d3e..a7515ce 100644 --- a/components/html_viewer/html_widget.cc +++ b/components/html_viewer/html_widget.cc
@@ -35,10 +35,8 @@ mus::Window* window, blink::WebWidget* widget) { DCHECK(window); - mojo::URLRequestPtr request(mojo::URLRequest::New()); - request->url = mojo::String::From("mojo:mus"); mus::mojom::GpuPtr gpu_service; - app->ConnectToService(request.Pass(), &gpu_service); + app->ConnectToService("mojo:mus", &gpu_service); web_layer_tree_view->Initialize(gpu_service.Pass(), window, widget); }
diff --git a/components/html_viewer/layout_test_html_viewer.cc b/components/html_viewer/layout_test_html_viewer.cc index 3c0a72dd1..459e301 100644 --- a/components/html_viewer/layout_test_html_viewer.cc +++ b/components/html_viewer/layout_test_html_viewer.cc
@@ -37,9 +37,7 @@ test_interfaces_->ResetAll(); web_view::LayoutTestRunnerPtr test_runner_ptr; - mojo::URLRequestPtr request(mojo::URLRequest::New()); - request->url = mojo::String::From("mojo:web_view_test_runner"); - app()->ConnectToService(request.Pass(), &test_runner_ptr); + app()->ConnectToService("mojo:web_view_test_runner", &test_runner_ptr); test_runner_ptr->TestFinished(); }
diff --git a/components/html_viewer/stats_collection_controller.cc b/components/html_viewer/stats_collection_controller.cc index 965c317..24cdd393 100644 --- a/components/html_viewer/stats_collection_controller.cc +++ b/components/html_viewer/stats_collection_controller.cc
@@ -79,10 +79,8 @@ v8::Context::Scope context_scope(context); - mojo::URLRequestPtr request(mojo::URLRequest::New()); - request->url = mojo::String::From("mojo:tracing"); scoped_ptr<mojo::ApplicationConnection> connection = - app->ConnectToApplication(request.Pass()); + app->ConnectToApplication("mojo:tracing"); if (!connection) return nullptr; tracing::StartupPerformanceDataCollectorPtr collector_for_controller; @@ -109,10 +107,8 @@ return nullptr; } - mojo::URLRequestPtr request(mojo::URLRequest::New()); - request->url = mojo::String::From("mojo:tracing"); tracing::StartupPerformanceDataCollectorPtr collector; - app->ConnectToService(request.Pass(), &collector); + app->ConnectToService("mojo:tracing", &collector); return collector.Pass(); }
diff --git a/components/html_viewer/web_graphics_context_3d_command_buffer_impl.cc b/components/html_viewer/web_graphics_context_3d_command_buffer_impl.cc index a99b9c82..862d54c 100644 --- a/components/html_viewer/web_graphics_context_3d_command_buffer_impl.cc +++ b/components/html_viewer/web_graphics_context_3d_command_buffer_impl.cc
@@ -34,10 +34,8 @@ gl_info->rendererInfo = gpu_info->renderer_info.To<blink::WebString>(); gl_info->driverVersion = gpu_info->driver_version.To<blink::WebString>(); - mojo::URLRequestPtr request(mojo::URLRequest::New()); - request->url = mojo::String::From("mojo:mus"); mus::mojom::GpuPtr gpu_service; - app->ConnectToService(request.Pass(), &gpu_service); + app->ConnectToService("mojo:mus", &gpu_service); mus::mojom::CommandBufferPtr cb; gpu_service->CreateOffscreenGLES2Context(GetProxy(&cb)); return new WebGraphicsContext3DCommandBufferImpl(
diff --git a/components/html_viewer/web_test_delegate_impl.cc b/components/html_viewer/web_test_delegate_impl.cc index a97a95f..9aba1a6 100644 --- a/components/html_viewer/web_test_delegate_impl.cc +++ b/components/html_viewer/web_test_delegate_impl.cc
@@ -318,7 +318,13 @@ NOTIMPLEMENTED(); } -bool WebTestDelegateImpl::AddMediaStreamSourceAndTrack( +bool WebTestDelegateImpl::AddMediaStreamVideoSourceAndTrack( + blink::WebMediaStream* stream) { + NOTIMPLEMENTED(); + return false; +} + +bool WebTestDelegateImpl::AddMediaStreamAudioSourceAndTrack( blink::WebMediaStream* stream) { NOTIMPLEMENTED(); return false;
diff --git a/components/html_viewer/web_test_delegate_impl.h b/components/html_viewer/web_test_delegate_impl.h index 1967d7e3..3bbb264 100644 --- a/components/html_viewer/web_test_delegate_impl.h +++ b/components/html_viewer/web_test_delegate_impl.h
@@ -109,7 +109,10 @@ const GURL& origin, const GURL& embedding_origin) override; void ResetPermissions() override; - bool AddMediaStreamSourceAndTrack(blink::WebMediaStream* stream) override; + bool AddMediaStreamVideoSourceAndTrack( + blink::WebMediaStream* stream) override; + bool AddMediaStreamAudioSourceAndTrack( + blink::WebMediaStream* stream) override; cc::SharedBitmapManager* GetSharedBitmapManager() override; void DispatchBeforeInstallPromptEvent( int request_id,
diff --git a/components/keyed_service/core/keyed_service.h b/components/keyed_service/core/keyed_service.h index ad5b529..e9c6f29 100644 --- a/components/keyed_service/core/keyed_service.h +++ b/components/keyed_service/core/keyed_service.h
@@ -17,11 +17,11 @@ public: KeyedService(); - // The first pass is to call Shutdown on a KeyedService. - virtual void Shutdown(); - // The second pass is the actual deletion of each object. virtual ~KeyedService(); + + // The first pass is to call Shutdown on a KeyedService. + virtual void Shutdown(); }; #endif // COMPONENTS_KEYED_SERVICE_CORE_KEYED_SERVICE_H_
diff --git a/components/login/BUILD.gn b/components/login/BUILD.gn index 8d20888..22249304 100644 --- a/components/login/BUILD.gn +++ b/components/login/BUILD.gn
@@ -15,8 +15,8 @@ defines = [ "LOGIN_IMPLEMENTATION" ] deps = [ - "//ui/base", "//components/signin/core/account_id", + "//ui/base", ] public_deps = [
diff --git a/components/metrics.gypi b/components/metrics.gypi index 36e8e57..99db0491 100644 --- a/components/metrics.gypi +++ b/components/metrics.gypi
@@ -104,6 +104,29 @@ ], }, { + 'target_name': 'metrics_leak_detector', + 'type': 'static_library', + 'dependencies': [ + '../base/base.gyp:base', + ], + 'sources': [ + 'metrics/leak_detector/call_stack_manager.cc', + 'metrics/leak_detector/call_stack_manager.h', + 'metrics/leak_detector/call_stack_table.cc', + 'metrics/leak_detector/call_stack_table.h', + 'metrics/leak_detector/custom_allocator.cc', + 'metrics/leak_detector/custom_allocator.h', + 'metrics/leak_detector/leak_analyzer.cc', + 'metrics/leak_detector/leak_analyzer.h', + 'metrics/leak_detector/leak_detector_impl.cc', + 'metrics/leak_detector/leak_detector_impl.h', + 'metrics/leak_detector/leak_detector_value_type.cc', + 'metrics/leak_detector/leak_detector_value_type.h', + 'metrics/leak_detector/ranked_list.cc', + 'metrics/leak_detector/ranked_list.h', + ], + }, + { # GN version: //components/metrics:net 'target_name': 'metrics_net', 'type': 'static_library',
diff --git a/components/metrics/BUILD.gn b/components/metrics/BUILD.gn index 836c243..f711a59b 100644 --- a/components/metrics/BUILD.gn +++ b/components/metrics/BUILD.gn
@@ -111,6 +111,30 @@ } } +# GYP version: components/metrics.gypi:metrics_leak_detector +static_library("leak_detector") { + sources = [ + "leak_detector/call_stack_manager.cc", + "leak_detector/call_stack_manager.h", + "leak_detector/call_stack_table.cc", + "leak_detector/call_stack_table.h", + "leak_detector/custom_allocator.cc", + "leak_detector/custom_allocator.h", + "leak_detector/leak_analyzer.cc", + "leak_detector/leak_analyzer.h", + "leak_detector/leak_detector_impl.cc", + "leak_detector/leak_detector_impl.h", + "leak_detector/leak_detector_value_type.cc", + "leak_detector/leak_detector_value_type.h", + "leak_detector/ranked_list.cc", + "leak_detector/ranked_list.h", + ] + + deps = [ + "//base", + ] +} + # GYP version: components/metrics.gypi:metrics_net static_library("net") { sources = [ @@ -241,6 +265,22 @@ } } +source_set("leak_detector_unit_tests") { + testonly = true + sources = [ + "leak_detector/call_stack_manager_unittest.cc", + "leak_detector/call_stack_table_unittest.cc", + "leak_detector/leak_analyzer_unittest.cc", + "leak_detector/leak_detector_impl_unittest.cc", + "leak_detector/ranked_list_unittest.cc", + ] + + deps = [ + ":leak_detector", + "//testing/gtest", + ] +} + source_set("unit_tests") { testonly = true sources = [ @@ -280,5 +320,9 @@ sources += [ "serialization/serialization_utils_unittest.cc" ] deps += [ ":serialization" ] } + + if (is_chromeos) { + deps += [ ":leak_detector_unit_tests" ] + } } # TODO(GYP): metrics_chromeos
diff --git a/components/metrics/leak_detector/OWNERS b/components/metrics/leak_detector/OWNERS new file mode 100644 index 0000000..d8bfc45 --- /dev/null +++ b/components/metrics/leak_detector/OWNERS
@@ -0,0 +1,2 @@ +sque@chromium.org +wfh@chromium.org
diff --git a/components/metrics/leak_detector/call_stack_manager.cc b/components/metrics/leak_detector/call_stack_manager.cc new file mode 100644 index 0000000..de9fcd8 --- /dev/null +++ b/components/metrics/leak_detector/call_stack_manager.cc
@@ -0,0 +1,67 @@ +// Copyright 2015 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 "components/metrics/leak_detector/call_stack_manager.h" + +#include <algorithm> // For std::copy. +#include <new> + +#include "base/hash.h" +#include "components/metrics/leak_detector/custom_allocator.h" + +namespace metrics { +namespace leak_detector { + +CallStackManager::CallStackManager() {} + +CallStackManager::~CallStackManager() { + for (CallStack* call_stack : call_stacks_) { + CustomAllocator::Free(call_stack->stack, + call_stack->depth * sizeof(*call_stack->stack)); + call_stack->stack = nullptr; + call_stack->depth = 0; + + CustomAllocator::Free(call_stack, sizeof(CallStack)); + } + call_stacks_.clear(); +} + +const CallStack* CallStackManager::GetCallStack(size_t depth, + const void* const stack[]) { + // Temporarily create a call stack object for lookup in |call_stacks_|. + CallStack temp; + temp.depth = depth; + temp.stack = const_cast<const void**>(stack); + // This is the only place where the call stack's hash is computed. This value + // can be reused in the created object to avoid further hash computation. + temp.hash = + base::Hash(reinterpret_cast<const char*>(stack), sizeof(*stack) * depth); + + auto iter = call_stacks_.find(&temp); + if (iter != call_stacks_.end()) + return *iter; + + // Since |call_stacks_| stores CallStack pointers rather than actual objects, + // create new call objects manually here. + CallStack* call_stack = + new (CustomAllocator::Allocate(sizeof(CallStack))) CallStack; + call_stack->depth = depth; + call_stack->hash = temp.hash; // Don't run the hash function again. + call_stack->stack = reinterpret_cast<const void**>( + CustomAllocator::Allocate(sizeof(*stack) * depth)); + std::copy(stack, stack + depth, call_stack->stack); + + call_stacks_.insert(call_stack); + return call_stack; +} + +bool CallStackManager::CallStackPointerEqual::operator()( + const CallStack* c1, + const CallStack* c2) const { + return c1->depth == c2->depth && c1->hash == c2->hash && + std::equal(c1->stack, c1->stack + c1->depth, c2->stack); +} + +} // namespace leak_detector +} // namespace metrics
diff --git a/components/metrics/leak_detector/call_stack_manager.h b/components/metrics/leak_detector/call_stack_manager.h new file mode 100644 index 0000000..1ec6b9d --- /dev/null +++ b/components/metrics/leak_detector/call_stack_manager.h
@@ -0,0 +1,100 @@ +// Copyright 2015 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 COMPONENTS_METRICS_LEAK_DETECTOR_CALL_STACK_MANAGER_H_ +#define COMPONENTS_METRICS_LEAK_DETECTOR_CALL_STACK_MANAGER_H_ + +#include <stdint.h> + +#include "base/containers/hash_tables.h" +#include "base/macros.h" +#include "components/metrics/leak_detector/custom_allocator.h" +#include "components/metrics/leak_detector/stl_allocator.h" + +// Summary of structures: +// +// struct CallStack: +// Represents a unique call stack, defined by its raw call stack (array of +// pointers), and hash value. All CallStack objects are owned by class +// CallStackManager. Other classes may hold pointers to them but should not +// attempt to create or modify any CallStack objects. +// +// class CallStackManager: +// Creates CallStack objects to represent unique call stacks. Owns all +// CallStack objects that it creates, storing them internally. +// +// Returns the call stacks as const pointers because no caller should take +// ownership of them and modify or delete them. The lifetime of all CallStack +// objects is limited to that of the CallStackManager object that created +// them. When the CallStackManager is destroyed, the CallStack objects will be +// invalidated. Hence the caller should make sure that it does not use +// CallStack objects beyond the lifetime of the CallStackManager that created +// them. + +namespace metrics { +namespace leak_detector { + +// Struct to represent a call stack. +struct CallStack { + // Call stack as an array of pointers, |stack|. The array length is stored in + // |depth|. There is no null terminator. + const void** stack; + size_t depth; + + // Hash of call stack. It is cached here so that it doesn not have to be + // recomputed each time. + size_t hash; +}; + +// Maintains and owns all unique call stack objects. +// Not thread-safe. +class CallStackManager { + public: + CallStackManager(); + ~CallStackManager(); + + // Returns a CallStack object for a given raw call stack. The first time a + // particular raw call stack is passed into this function, it will create a + // new CallStack object to hold the raw call stack data, and then return it. + // The CallStack object is stored internally. + // + // On subsequent calls with the same raw call stack, this function will return + // the previously created CallStack object. + const CallStack* GetCallStack(size_t depth, const void* const stack[]); + + size_t size() const { return call_stacks_.size(); } + + private: + // Allocator class for unique call stacks. + using CallStackPointerAllocator = STLAllocator<CallStack*, CustomAllocator>; + + // Hash operator for call stack object given as a pointer. + // Does not actually compute the hash. Instead, returns the already computed + // hash value stored in a CallStack object. + struct CallStackPointerStoredHash { + size_t operator()(const CallStack* call_stack) const { + return call_stack->hash; + } + }; + + // Equality comparator for call stack objects given as pointers. Compares + // their stack trace contents. + struct CallStackPointerEqual { + bool operator()(const CallStack* c1, const CallStack* c2) const; + }; + + // Holds all call stack objects. Each object is allocated elsewhere and stored + // as a pointer because the container may rearrange itself internally. + base::hash_set<CallStack*, + CallStackPointerStoredHash, + CallStackPointerEqual, + CallStackPointerAllocator> call_stacks_; + + DISALLOW_COPY_AND_ASSIGN(CallStackManager); +}; + +} // namespace leak_detector +} // namespace metrics + +#endif // COMPONENTS_METRICS_LEAK_DETECTOR_CALL_STACK_MANAGER_H_
diff --git a/components/metrics/leak_detector/call_stack_manager_unittest.cc b/components/metrics/leak_detector/call_stack_manager_unittest.cc new file mode 100644 index 0000000..8b49006 --- /dev/null +++ b/components/metrics/leak_detector/call_stack_manager_unittest.cc
@@ -0,0 +1,260 @@ +// Copyright 2015 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 "components/metrics/leak_detector/call_stack_manager.h" + +#include <stdint.h> + +#include <algorithm> + +#include "base/macros.h" +#include "base/memory/scoped_ptr.h" +#include "components/metrics/leak_detector/custom_allocator.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace metrics { +namespace leak_detector { + +namespace { + +// Some test call stacks. The addresses are 64-bit but they should automatically +// be truncated to 32 bits on a 32-bit machine. +const void* kRawStack0[] = { + reinterpret_cast<const void*>(0x8899aabbccddeeff), + reinterpret_cast<const void*>(0x0000112233445566), + reinterpret_cast<const void*>(0x5566778899aabbcc), + reinterpret_cast<const void*>(0x9988776655443322), +}; +// This is similar to kRawStack0, differing only in one address by 1. It should +// still produce a distinct CallStack object and hash. +const void* kRawStack1[] = { + kRawStack0[0], kRawStack0[1], + reinterpret_cast<const void*>(reinterpret_cast<uintptr_t>(kRawStack0[2]) + + 1), + kRawStack0[3], +}; +const void* kRawStack2[] = { + reinterpret_cast<const void*>(0x900df00dcab58888), + reinterpret_cast<const void*>(0x00001337cafedeed), + reinterpret_cast<const void*>(0x0000deafbabe1234), +}; +const void* kRawStack3[] = { + reinterpret_cast<const void*>(0x0000000012345678), + reinterpret_cast<const void*>(0x00000000abcdef01), + reinterpret_cast<const void*>(0x00000000fdecab98), + reinterpret_cast<const void*>(0x0000deadbeef0001), + reinterpret_cast<const void*>(0x0000900ddeed0002), + reinterpret_cast<const void*>(0x0000f00dcafe0003), + reinterpret_cast<const void*>(0x0000f00d900d0004), + reinterpret_cast<const void*>(0xdeedcafebabe0005), +}; + +// Creates a copy of a call stack as a scoped_ptr to a raw stack. The depth is +// the same as the original stack, but it is not stored in the result. +scoped_ptr<const void* []> CopyStack(const CallStack* stack) { + scoped_ptr<const void* []> stack_copy(new const void*[stack->depth]); + std::copy(stack->stack, stack->stack + stack->depth, stack_copy.get()); + return stack_copy.Pass(); +} + +} // namespace + +class CallStackManagerTest : public ::testing::Test { + public: + CallStackManagerTest() {} + + void SetUp() override { CustomAllocator::Initialize(); } + void TearDown() override { EXPECT_TRUE(CustomAllocator::Shutdown()); } + + private: + DISALLOW_COPY_AND_ASSIGN(CallStackManagerTest); +}; + +TEST_F(CallStackManagerTest, NewStacks) { + CallStackManager manager; + EXPECT_EQ(0U, manager.size()); + + // Request some new stacks and make sure their creation is reflected in the + // size of |manager|. + const CallStack* stack0 = + manager.GetCallStack(arraysize(kRawStack0), kRawStack0); + EXPECT_EQ(arraysize(kRawStack0), stack0->depth); + EXPECT_EQ(1U, manager.size()); + + const CallStack* stack1 = + manager.GetCallStack(arraysize(kRawStack1), kRawStack1); + EXPECT_EQ(arraysize(kRawStack1), stack1->depth); + EXPECT_EQ(2U, manager.size()); + + const CallStack* stack2 = + manager.GetCallStack(arraysize(kRawStack2), kRawStack2); + EXPECT_EQ(arraysize(kRawStack2), stack2->depth); + EXPECT_EQ(3U, manager.size()); + + const CallStack* stack3 = + manager.GetCallStack(arraysize(kRawStack3), kRawStack3); + EXPECT_EQ(arraysize(kRawStack3), stack3->depth); + EXPECT_EQ(4U, manager.size()); + + // Call stack objects should be unique. + EXPECT_NE(stack0, stack1); + EXPECT_NE(stack0, stack2); + EXPECT_NE(stack0, stack3); + EXPECT_NE(stack1, stack2); + EXPECT_NE(stack1, stack3); + EXPECT_NE(stack2, stack3); +} + +TEST_F(CallStackManagerTest, Hashes) { + CallStackManager manager; + + const CallStack* stack0 = + manager.GetCallStack(arraysize(kRawStack0), kRawStack0); + const CallStack* stack1 = + manager.GetCallStack(arraysize(kRawStack1), kRawStack1); + const CallStack* stack2 = + manager.GetCallStack(arraysize(kRawStack2), kRawStack2); + const CallStack* stack3 = + manager.GetCallStack(arraysize(kRawStack3), kRawStack3); + + // Hash values should be unique. This test is not designed to make sure the + // hash function is generating unique hashes, but that CallStackManager is + // properly storing the hashes in CallStack structs. + EXPECT_NE(stack0->hash, stack1->hash); + EXPECT_NE(stack0->hash, stack2->hash); + EXPECT_NE(stack0->hash, stack3->hash); + EXPECT_NE(stack1->hash, stack2->hash); + EXPECT_NE(stack1->hash, stack3->hash); + EXPECT_NE(stack2->hash, stack3->hash); +} + +TEST_F(CallStackManagerTest, MultipleManagersHashes) { + CallStackManager manager1; + const CallStack* stack10 = + manager1.GetCallStack(arraysize(kRawStack0), kRawStack0); + const CallStack* stack11 = + manager1.GetCallStack(arraysize(kRawStack1), kRawStack1); + const CallStack* stack12 = + manager1.GetCallStack(arraysize(kRawStack2), kRawStack2); + const CallStack* stack13 = + manager1.GetCallStack(arraysize(kRawStack3), kRawStack3); + + CallStackManager manager2; + const CallStack* stack20 = + manager2.GetCallStack(arraysize(kRawStack0), kRawStack0); + const CallStack* stack21 = + manager2.GetCallStack(arraysize(kRawStack1), kRawStack1); + const CallStack* stack22 = + manager2.GetCallStack(arraysize(kRawStack2), kRawStack2); + const CallStack* stack23 = + manager2.GetCallStack(arraysize(kRawStack3), kRawStack3); + + // Different CallStackManagers should still generate the same hashes. + EXPECT_EQ(stack10->hash, stack20->hash); + EXPECT_EQ(stack11->hash, stack21->hash); + EXPECT_EQ(stack12->hash, stack22->hash); + EXPECT_EQ(stack13->hash, stack23->hash); +} + +TEST_F(CallStackManagerTest, HashWithReducedDepth) { + CallStackManager manager; + const CallStack* stack = + manager.GetCallStack(arraysize(kRawStack3), kRawStack3); + + // Hash function should only operate on the first |CallStack::depth| elements + // of CallStack::stack. To test this, reduce the depth value of one of the + // stacks and make sure the hash changes. + EXPECT_NE(stack->hash, + manager.GetCallStack(stack->depth - 1, stack->stack)->hash); + EXPECT_NE(stack->hash, + manager.GetCallStack(stack->depth - 2, stack->stack)->hash); + EXPECT_NE(stack->hash, + manager.GetCallStack(stack->depth - 3, stack->stack)->hash); + EXPECT_NE(stack->hash, + manager.GetCallStack(stack->depth - 4, stack->stack)->hash); + + // Also try subsets of the stack that don't start from the beginning. + EXPECT_NE(stack->hash, + manager.GetCallStack(stack->depth - 1, stack->stack + 1)->hash); + EXPECT_NE(stack->hash, + manager.GetCallStack(stack->depth - 2, stack->stack + 2)->hash); + EXPECT_NE(stack->hash, + manager.GetCallStack(stack->depth - 3, stack->stack + 3)->hash); + EXPECT_NE(stack->hash, + manager.GetCallStack(stack->depth - 4, stack->stack + 4)->hash); +} + +TEST_F(CallStackManagerTest, DuplicateStacks) { + CallStackManager manager; + EXPECT_EQ(0U, manager.size()); + + // Calling manager.GetCallStack() multiple times with the same raw stack + // arguments will not result in creation of new call stack objects after the + // first call. Instead, the previously created object will be returned, and + // the size of |manager| will remain unchanged. + // + // Thus a call to GetCallStack() will always return the same result, given the + // same inputs. + + // Add stack0. + const CallStack* stack0 = + manager.GetCallStack(arraysize(kRawStack0), kRawStack0); + + scoped_ptr<const void* []> rawstack0_duplicate0 = CopyStack(stack0); + const CallStack* stack0_duplicate0 = + manager.GetCallStack(arraysize(kRawStack0), rawstack0_duplicate0.get()); + EXPECT_EQ(1U, manager.size()); + EXPECT_EQ(stack0, stack0_duplicate0); + + // Add stack1. + const CallStack* stack1 = + manager.GetCallStack(arraysize(kRawStack1), kRawStack1); + EXPECT_EQ(2U, manager.size()); + + scoped_ptr<const void* []> rawstack0_duplicate1 = CopyStack(stack0); + const CallStack* stack0_duplicate1 = + manager.GetCallStack(arraysize(kRawStack0), rawstack0_duplicate1.get()); + EXPECT_EQ(2U, manager.size()); + EXPECT_EQ(stack0, stack0_duplicate1); + + scoped_ptr<const void* []> rawstack1_duplicate0 = CopyStack(stack1); + const CallStack* stack1_duplicate0 = + manager.GetCallStack(arraysize(kRawStack1), rawstack1_duplicate0.get()); + EXPECT_EQ(2U, manager.size()); + EXPECT_EQ(stack1, stack1_duplicate0); + + // Add stack2 and stack3. + const CallStack* stack2 = + manager.GetCallStack(arraysize(kRawStack2), kRawStack2); + const CallStack* stack3 = + manager.GetCallStack(arraysize(kRawStack3), kRawStack3); + EXPECT_EQ(4U, manager.size()); + + scoped_ptr<const void* []> rawstack1_duplicate1 = CopyStack(stack1); + const CallStack* stack1_duplicate1 = + manager.GetCallStack(arraysize(kRawStack1), rawstack1_duplicate1.get()); + EXPECT_EQ(4U, manager.size()); + EXPECT_EQ(stack1, stack1_duplicate1); + + scoped_ptr<const void* []> rawstack0_duplicate2 = CopyStack(stack0); + const CallStack* stack0_duplicate2 = + manager.GetCallStack(arraysize(kRawStack0), rawstack0_duplicate2.get()); + EXPECT_EQ(4U, manager.size()); + EXPECT_EQ(stack0, stack0_duplicate2); + + scoped_ptr<const void* []> rawstack3_duplicate0 = CopyStack(stack3); + const CallStack* stack3_duplicate0 = + manager.GetCallStack(arraysize(kRawStack3), rawstack3_duplicate0.get()); + EXPECT_EQ(4U, manager.size()); + EXPECT_EQ(stack3, stack3_duplicate0); + + scoped_ptr<const void* []> rawstack2_duplicate0 = CopyStack(stack2); + const CallStack* stack2_duplicate0 = + manager.GetCallStack(arraysize(kRawStack2), rawstack2_duplicate0.get()); + EXPECT_EQ(4U, manager.size()); + EXPECT_EQ(stack2, stack2_duplicate0); +} + +} // namespace leak_detector +} // namespace metrics
diff --git a/components/metrics/leak_detector/call_stack_table.cc b/components/metrics/leak_detector/call_stack_table.cc new file mode 100644 index 0000000..f861ebbe --- /dev/null +++ b/components/metrics/leak_detector/call_stack_table.cc
@@ -0,0 +1,78 @@ +// Copyright 2015 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 "components/metrics/leak_detector/call_stack_table.h" + +#include "components/metrics/leak_detector/call_stack_manager.h" + +namespace metrics { +namespace leak_detector { + +namespace { + +using ValueType = LeakDetectorValueType; + +// During leak analysis, we only want to examine the top +// |kMaxCountOfSuspciousStacks| entries. +const int kMaxCountOfSuspciousStacks = 16; + +const int kInitialHashTableSize = 1999; + +} // namespace + +size_t CallStackTable::StoredHash::operator()( + const CallStack* call_stack) const { + // The call stack object should already have a hash computed when it was + // created. + // + // This is NOT the actual hash computation function for a new call stack. + return call_stack->hash; +} + +CallStackTable::CallStackTable(int call_stack_suspicion_threshold) + : num_allocs_(0), + num_frees_(0), + entry_map_(kInitialHashTableSize), + leak_analyzer_(kMaxCountOfSuspciousStacks, + call_stack_suspicion_threshold) {} + +CallStackTable::~CallStackTable() {} + +void CallStackTable::Add(const CallStack* call_stack) { + Entry* entry = &entry_map_[call_stack]; + + ++entry->net_num_allocs; + ++num_allocs_; +} + +void CallStackTable::Remove(const CallStack* call_stack) { + auto iter = entry_map_.find(call_stack); + if (iter == entry_map_.end()) + return; + Entry* entry = &iter->second; + --entry->net_num_allocs; + ++num_frees_; + + // Delete zero-alloc entries to free up space. + if (entry->net_num_allocs == 0) + entry_map_.erase(iter); +} + +void CallStackTable::TestForLeaks() { + // Add all entries to the ranked list. + RankedList ranked_list(kMaxCountOfSuspciousStacks); + + for (const auto& entry_pair : entry_map_) { + const Entry& entry = entry_pair.second; + // Assumes that |entry.net_num_allocs| is always > 0. If that changes + // elsewhere in this class, this code should be updated to only pass values + // > 0 to |ranked_list|. + LeakDetectorValueType call_stack_value(entry_pair.first); + ranked_list.Add(call_stack_value, entry.net_num_allocs); + } + leak_analyzer_.AddSample(ranked_list.Pass()); +} + +} // namespace leak_detector +} // namespace metrics
diff --git a/components/metrics/leak_detector/call_stack_table.h b/components/metrics/leak_detector/call_stack_table.h new file mode 100644 index 0000000..c412895 --- /dev/null +++ b/components/metrics/leak_detector/call_stack_table.h
@@ -0,0 +1,81 @@ +// Copyright 2015 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 COMPONENTS_METRICS_LEAK_DETECTOR_CALL_STACK_TABLE_H_ +#define COMPONENTS_METRICS_LEAK_DETECTOR_CALL_STACK_TABLE_H_ + +#include <stdint.h> + +#include <functional> // For std::equal_to. + +#include "base/containers/hash_tables.h" +#include "base/macros.h" +#include "components/metrics/leak_detector/custom_allocator.h" +#include "components/metrics/leak_detector/leak_analyzer.h" +#include "components/metrics/leak_detector/stl_allocator.h" + +namespace metrics { +namespace leak_detector { + +struct CallStack; + +// Contains a hash table where the key is the call stack and the value is the +// number of allocations from that call stack. +// Not thread-safe. +class CallStackTable { + public: + struct StoredHash { + size_t operator()(const CallStack* call_stack) const; + }; + + explicit CallStackTable(int call_stack_suspicion_threshold); + ~CallStackTable(); + + // Add/Remove an allocation for the given call stack. + // Note that this class does NOT own the CallStack objects. Instead, it + // identifies different CallStacks by their hashes. + void Add(const CallStack* call_stack); + void Remove(const CallStack* call_stack); + + // Check for leak patterns in the allocation data. + void TestForLeaks(); + + const LeakAnalyzer& leak_analyzer() const { return leak_analyzer_; } + + size_t size() const { return entry_map_.size(); } + bool empty() const { return entry_map_.empty(); } + + uint32_t num_allocs() const { return num_allocs_; } + uint32_t num_frees() const { return num_frees_; } + + private: + // Hash table entry used to track allocation stats for a given call stack. + struct Entry { + // Net number of allocs (allocs minus frees). + uint32_t net_num_allocs; + }; + + // Total number of allocs and frees in this table. + uint32_t num_allocs_; + uint32_t num_frees_; + + // Hash table containing entries. + using TableEntryAllocator = + STLAllocator<std::pair<const CallStack*, Entry>, CustomAllocator>; + base::hash_map<const CallStack*, + Entry, + StoredHash, + std::equal_to<const CallStack*>, + TableEntryAllocator> entry_map_; + + // For detecting leak patterns in incoming allocations. + LeakAnalyzer leak_analyzer_; + + DISALLOW_COPY_AND_ASSIGN(CallStackTable); +}; + +} // namespace leak_detector +} // namespace metrics + +#endif // COMPONENTS_METRICS_LEAK_DETECTOR_CALL_STACK_TABLE_H_
diff --git a/components/metrics/leak_detector/call_stack_table_unittest.cc b/components/metrics/leak_detector/call_stack_table_unittest.cc new file mode 100644 index 0000000..c455f37 --- /dev/null +++ b/components/metrics/leak_detector/call_stack_table_unittest.cc
@@ -0,0 +1,306 @@ +// Copyright 2015 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 "components/metrics/leak_detector/call_stack_table.h" + +#include <set> + +#include "base/macros.h" +#include "base/memory/scoped_ptr.h" +#include "components/metrics/leak_detector/call_stack_manager.h" +#include "components/metrics/leak_detector/custom_allocator.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace metrics { +namespace leak_detector { + +namespace { + +// Default threshold used for leak analysis. +const int kDefaultLeakThreshold = 5; + +// Some test call stacks. +const void* kRawStack0[] = { + reinterpret_cast<const void*>(0xaabbccdd), + reinterpret_cast<const void*>(0x11223344), + reinterpret_cast<const void*>(0x55667788), + reinterpret_cast<const void*>(0x99887766), +}; +const void* kRawStack1[] = { + reinterpret_cast<const void*>(0xdeadbeef), + reinterpret_cast<const void*>(0x900df00d), + reinterpret_cast<const void*>(0xcafedeed), + reinterpret_cast<const void*>(0xdeafbabe), +}; +const void* kRawStack2[] = { + reinterpret_cast<const void*>(0x12345678), + reinterpret_cast<const void*>(0xabcdef01), + reinterpret_cast<const void*>(0xfdecab98), +}; +const void* kRawStack3[] = { + reinterpret_cast<const void*>(0xdead0001), + reinterpret_cast<const void*>(0xbeef0002), + reinterpret_cast<const void*>(0x900d0003), + reinterpret_cast<const void*>(0xf00d0004), + reinterpret_cast<const void*>(0xcafe0005), + reinterpret_cast<const void*>(0xdeed0006), + reinterpret_cast<const void*>(0xdeaf0007), + reinterpret_cast<const void*>(0xbabe0008), +}; + +} // namespace + +class CallStackTableTest : public ::testing::Test { + public: + CallStackTableTest() + : stack0_(nullptr), + stack1_(nullptr), + stack2_(nullptr), + stack3_(nullptr) {} + + void SetUp() override { + CustomAllocator::Initialize(); + + manager_.reset(new CallStackManager); + + // The unit tests expect a certain order to the call stack pointers. It is + // an important detail when checking the output of LeakAnalyzer's suspected + // leaks, which are ordered by the leak value (call stack pointer). Use a + // set to sort the pointers as they are created. + std::set<const CallStack*> stacks; + stacks.insert(manager_->GetCallStack(arraysize(kRawStack0), kRawStack0)); + stacks.insert(manager_->GetCallStack(arraysize(kRawStack1), kRawStack1)); + stacks.insert(manager_->GetCallStack(arraysize(kRawStack2), kRawStack2)); + stacks.insert(manager_->GetCallStack(arraysize(kRawStack3), kRawStack3)); + ASSERT_EQ(4U, stacks.size()); + + std::set<const CallStack*>::const_iterator iter = stacks.begin(); + stack0_ = *iter++; + stack1_ = *iter++; + stack2_ = *iter++; + stack3_ = *iter++; + } + + void TearDown() override { + // All call stacks generated by |manager_| will be invalidated when it is + // destroyed. + stack0_ = nullptr; + stack1_ = nullptr; + stack2_ = nullptr; + stack3_ = nullptr; + + // Destroy the call stack manager before shutting down the allocator. + manager_.reset(); + + EXPECT_TRUE(CustomAllocator::Shutdown()); + } + + protected: + // Unit tests should directly reference these pointers to CallStack objects. + const CallStack* stack0_; + const CallStack* stack1_; + const CallStack* stack2_; + const CallStack* stack3_; + + private: + scoped_ptr<CallStackManager> manager_; + + DISALLOW_COPY_AND_ASSIGN(CallStackTableTest); +}; + +TEST_F(CallStackTableTest, PointerOrder) { + EXPECT_LT(stack0_, stack1_); + EXPECT_LT(stack1_, stack2_); + EXPECT_LT(stack2_, stack3_); +} + +TEST_F(CallStackTableTest, EmptyTable) { + CallStackTable table(kDefaultLeakThreshold); + EXPECT_TRUE(table.empty()); + + EXPECT_EQ(0U, table.num_allocs()); + EXPECT_EQ(0U, table.num_frees()); + + // The table should be able to gracefully handle an attempt to remove a call + // stack entry when none exists. + table.Remove(stack0_); + table.Remove(stack1_); + table.Remove(stack2_); + table.Remove(stack3_); + + EXPECT_EQ(0U, table.num_allocs()); + EXPECT_EQ(0U, table.num_frees()); +} + +TEST_F(CallStackTableTest, InsertionAndRemoval) { + CallStackTable table(kDefaultLeakThreshold); + + table.Add(stack0_); + EXPECT_EQ(1U, table.size()); + EXPECT_EQ(1U, table.num_allocs()); + table.Add(stack1_); + EXPECT_EQ(2U, table.size()); + EXPECT_EQ(2U, table.num_allocs()); + table.Add(stack2_); + EXPECT_EQ(3U, table.size()); + EXPECT_EQ(3U, table.num_allocs()); + table.Add(stack3_); + EXPECT_EQ(4U, table.size()); + EXPECT_EQ(4U, table.num_allocs()); + + // Add some call stacks that have already been added. There should be no + // change in the number of entries, as they are aggregated by call stack. + table.Add(stack2_); + EXPECT_EQ(4U, table.size()); + EXPECT_EQ(5U, table.num_allocs()); + table.Add(stack3_); + EXPECT_EQ(4U, table.size()); + EXPECT_EQ(6U, table.num_allocs()); + + // Start removing entries. + EXPECT_EQ(0U, table.num_frees()); + + table.Remove(stack0_); + EXPECT_EQ(3U, table.size()); + EXPECT_EQ(1U, table.num_frees()); + table.Remove(stack1_); + EXPECT_EQ(2U, table.size()); + EXPECT_EQ(2U, table.num_frees()); + + // Removing call stacks with multiple counts will not reduce the overall + // number of table entries, until the count reaches 0. + table.Remove(stack2_); + EXPECT_EQ(2U, table.size()); + EXPECT_EQ(3U, table.num_frees()); + table.Remove(stack3_); + EXPECT_EQ(2U, table.size()); + EXPECT_EQ(4U, table.num_frees()); + + table.Remove(stack2_); + EXPECT_EQ(1U, table.size()); + EXPECT_EQ(5U, table.num_frees()); + table.Remove(stack3_); + EXPECT_EQ(0U, table.size()); + EXPECT_EQ(6U, table.num_frees()); + + // Now the table should be empty, but attempt to remove some more and make + // sure nothing breaks. + table.Remove(stack0_); + table.Remove(stack1_); + table.Remove(stack2_); + table.Remove(stack3_); + + EXPECT_TRUE(table.empty()); + EXPECT_EQ(6U, table.num_allocs()); + EXPECT_EQ(6U, table.num_frees()); +} + +TEST_F(CallStackTableTest, MassiveInsertionAndRemoval) { + CallStackTable table(kDefaultLeakThreshold); + + for (int i = 0; i < 100; ++i) + table.Add(stack3_); + EXPECT_EQ(1U, table.size()); + EXPECT_EQ(100U, table.num_allocs()); + + for (int i = 0; i < 100; ++i) + table.Add(stack2_); + EXPECT_EQ(2U, table.size()); + EXPECT_EQ(200U, table.num_allocs()); + + for (int i = 0; i < 100; ++i) + table.Add(stack1_); + EXPECT_EQ(3U, table.size()); + EXPECT_EQ(300U, table.num_allocs()); + + for (int i = 0; i < 100; ++i) + table.Add(stack0_); + EXPECT_EQ(4U, table.size()); + EXPECT_EQ(400U, table.num_allocs()); + + // Remove them in a different order, by removing one of each stack during one + // iteration. The size should not decrease until the last iteration. + EXPECT_EQ(0U, table.num_frees()); + + for (int i = 0; i < 100; ++i) { + table.Remove(stack0_); + EXPECT_EQ(4U * i + 1, table.num_frees()); + + table.Remove(stack1_); + EXPECT_EQ(4U * i + 2, table.num_frees()); + + table.Remove(stack2_); + EXPECT_EQ(4U * i + 3, table.num_frees()); + + table.Remove(stack3_); + EXPECT_EQ(4U * i + 4, table.num_frees()); + } + EXPECT_EQ(400U, table.num_frees()); + EXPECT_TRUE(table.empty()); + + // Try to remove some more from an empty table and make sure nothing breaks. + table.Remove(stack0_); + table.Remove(stack1_); + table.Remove(stack2_); + table.Remove(stack3_); + + EXPECT_TRUE(table.empty()); + EXPECT_EQ(400U, table.num_allocs()); + EXPECT_EQ(400U, table.num_frees()); +} + +TEST_F(CallStackTableTest, DetectLeak) { + CallStackTable table(kDefaultLeakThreshold); + + // Add some base number of entries. + for (int i = 0; i < 60; ++i) + table.Add(stack0_); + for (int i = 0; i < 50; ++i) + table.Add(stack1_); + for (int i = 0; i < 64; ++i) + table.Add(stack2_); + for (int i = 0; i < 72; ++i) + table.Add(stack3_); + + table.TestForLeaks(); + EXPECT_TRUE(table.leak_analyzer().suspected_leaks().empty()); + + // Use the following scheme: + // - stack0_: increase by 4 each time -- leak suspect + // - stack1_: increase by 3 each time -- leak suspect + // - stack2_: increase by 1 each time -- not a suspect + // - stack3_: alternate between increasing and decreasing - not a suspect + bool increase_kstack3 = true; + for (int i = 0; i < kDefaultLeakThreshold; ++i) { + EXPECT_TRUE(table.leak_analyzer().suspected_leaks().empty()); + + for (int j = 0; j < 4; ++j) + table.Add(stack0_); + + for (int j = 0; j < 3; ++j) + table.Add(stack1_); + + table.Add(stack2_); + + // Alternate between adding and removing. + if (increase_kstack3) + table.Add(stack3_); + else + table.Remove(stack3_); + increase_kstack3 = !increase_kstack3; + + table.TestForLeaks(); + } + + // Check that the correct leak values have been detected. + const auto& leaks = table.leak_analyzer().suspected_leaks(); + ASSERT_EQ(2U, leaks.size()); + // Suspected leaks are reported in increasing leak value -- in this case, the + // CallStack object's address. + EXPECT_EQ(stack0_, leaks[0].call_stack()); + EXPECT_EQ(stack1_, leaks[1].call_stack()); +} + +} // namespace leak_detector +} // namespace metrics
diff --git a/components/metrics/leak_detector/custom_allocator.cc b/components/metrics/leak_detector/custom_allocator.cc new file mode 100644 index 0000000..1f80a971 --- /dev/null +++ b/components/metrics/leak_detector/custom_allocator.cc
@@ -0,0 +1,61 @@ +// Copyright 2015 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 "components/metrics/leak_detector/custom_allocator.h" + +#include <stddef.h> + +namespace metrics { +namespace leak_detector { + +namespace { + +// Wrappers around new and delete. +void* DefaultAlloc(size_t size) { + return new char[size]; +} +void DefaultFree(void* ptr, size_t /* size */) { + delete[] reinterpret_cast<char*>(ptr); +} + +CustomAllocator::AllocFunc g_alloc_func = nullptr; +CustomAllocator::FreeFunc g_free_func = nullptr; + +} // namespace + +// static +void CustomAllocator::Initialize() { + Initialize(&DefaultAlloc, &DefaultFree); +} + +// static +void CustomAllocator::Initialize(AllocFunc alloc_func, FreeFunc free_func) { + g_alloc_func = alloc_func; + g_free_func = free_func; +} + +// static +bool CustomAllocator::Shutdown() { + g_alloc_func = nullptr; + g_free_func = nullptr; + return true; +} + +// static +bool CustomAllocator::IsInitialized() { + return g_alloc_func && g_free_func; +} + +// static +void* CustomAllocator::Allocate(size_t size) { + return g_alloc_func(size); +} + +// static +void CustomAllocator::Free(void* ptr, size_t size) { + g_free_func(ptr, size); +} + +} // namespace leak_detector +} // namespace metrics
diff --git a/components/metrics/leak_detector/custom_allocator.h b/components/metrics/leak_detector/custom_allocator.h new file mode 100644 index 0000000..fdbfc77 --- /dev/null +++ b/components/metrics/leak_detector/custom_allocator.h
@@ -0,0 +1,50 @@ +// Copyright 2015 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 COMPONENTS_METRICS_LEAK_DETECTOR_CUSTOM_ALLOCATOR_H_ +#define COMPONENTS_METRICS_LEAK_DETECTOR_CUSTOM_ALLOCATOR_H_ + +#include <stddef.h> + +#include <type_traits> + +namespace metrics { +namespace leak_detector { + +// Custom allocator class to be passed to STLAllocator as a template argument. +// +// By default, CustomAllocator uses the default allocator (new/delete), but the +// caller of Initialize ()can provide a pair of alternative alloc/ free +// functions to use as an external allocator. +// +// This is a stateless class, but there is static data within the module that +// needs to be created and deleted. +// +// Not thread-safe. +class CustomAllocator { + public: + using AllocFunc = std::add_pointer<void*(size_t)>::type; + using FreeFunc = std::add_pointer<void(void*, size_t)>::type; + + // Initialize CustomAllocator to use the default allocator. + static void Initialize(); + + // Initialize CustomAllocator to use the given alloc/free functions. + static void Initialize(AllocFunc alloc_func, FreeFunc free_func); + + // Performs any cleanup required, e.g. unset custom functions. Returns true + // on success or false if something failed. + static bool Shutdown(); + + static bool IsInitialized(); + + // These functions must match the specifications in STLAllocator. + static void* Allocate(size_t size); + static void Free(void* ptr, size_t size); +}; + +} // namespace leak_detector +} // namespace metrics + +#endif // COMPONENTS_METRICS_LEAK_DETECTOR_CUSTOM_ALLOCATOR_H_
diff --git a/components/metrics/leak_detector/leak_analyzer.cc b/components/metrics/leak_detector/leak_analyzer.cc new file mode 100644 index 0000000..56905ba --- /dev/null +++ b/components/metrics/leak_detector/leak_analyzer.cc
@@ -0,0 +1,139 @@ +// Copyright 2015 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 "components/metrics/leak_detector/leak_analyzer.h" + +#include <set> + +namespace metrics { +namespace leak_detector { + +namespace { + +using RankedEntry = RankedList::Entry; + +// Increase suspicion scores by this much each time an entry is suspected as +// being a leak. +const int kSuspicionScoreIncrease = 1; + +} // namespace + +LeakAnalyzer::LeakAnalyzer(uint32_t ranking_size, + uint32_t num_suspicions_threshold) + : ranking_size_(ranking_size), + score_threshold_(num_suspicions_threshold), + ranked_entries_(ranking_size), + prev_ranked_entries_(ranking_size) { + suspected_leaks_.reserve(ranking_size); +} + +LeakAnalyzer::~LeakAnalyzer() {} + +void LeakAnalyzer::AddSample(RankedList ranked_list) { + // Save the ranked entries from the previous call. + prev_ranked_entries_ = ranked_entries_.Pass(); + + // Save the current entries. + ranked_entries_ = ranked_list.Pass(); + + RankedList ranked_deltas(ranking_size_); + for (const RankedEntry& entry : ranked_entries_) { + // Determine what count was recorded for this value last time. + uint32_t prev_count = 0; + if (GetPreviousCountForValue(entry.value, &prev_count)) + ranked_deltas.Add(entry.value, entry.count - prev_count); + } + + AnalyzeDeltas(ranked_deltas); +} + +void LeakAnalyzer::AnalyzeDeltas(const RankedList& ranked_deltas) { + bool found_drop = false; + RankedList::const_iterator drop_position = ranked_deltas.end(); + + if (ranked_deltas.size() > 1) { + RankedList::const_iterator entry_iter = ranked_deltas.begin(); + RankedList::const_iterator next_entry_iter = ranked_deltas.begin(); + ++next_entry_iter; + + // If the first entry is 0, that means all deltas are 0 or negative. Do + // not treat this as a suspicion of leaks; just quit. + if (entry_iter->count > 0) { + while (next_entry_iter != ranked_deltas.end()) { + const RankedEntry& entry = *entry_iter; + const RankedEntry& next_entry = *next_entry_iter; + + // Find the first major drop in values (i.e. by 50% or more). + if (entry.count > next_entry.count * 2) { + found_drop = true; + drop_position = next_entry_iter; + break; + } + ++entry_iter; + ++next_entry_iter; + } + } + } + + // All leak values before the drop are suspected during this analysis. + std::set<ValueType, std::less<ValueType>, Allocator<ValueType>> + current_suspects; + if (found_drop) { + for (RankedList::const_iterator ranked_list_iter = ranked_deltas.begin(); + ranked_list_iter != drop_position; ++ranked_list_iter) { + current_suspects.insert(ranked_list_iter->value); + } + } + + // Reset the score to 0 for all previously suspected leak values that did + // not get suspected this time. + auto iter = suspected_histogram_.begin(); + while (iter != suspected_histogram_.end()) { + const ValueType& value = iter->first; + // Erase entries whose suspicion score reaches 0. + auto erase_iter = iter++; + if (current_suspects.find(value) == current_suspects.end()) + suspected_histogram_.erase(erase_iter); + } + + // For currently suspected values, increase the leak score. + for (const ValueType& value : current_suspects) { + auto histogram_iter = suspected_histogram_.find(value); + if (histogram_iter != suspected_histogram_.end()) { + histogram_iter->second += kSuspicionScoreIncrease; + } else if (suspected_histogram_.size() < ranking_size_) { + // Create a new entry if it didn't already exist. + suspected_histogram_[value] = kSuspicionScoreIncrease; + } + } + + // Now check the leak suspicion scores. Make sure to erase the suspected + // leaks from the previous call. + suspected_leaks_.clear(); + for (const auto& entry : suspected_histogram_) { + if (suspected_leaks_.size() > ranking_size_) + break; + + // Only report suspected values that have accumulated a suspicion score. + // This is achieved by maintaining suspicion for several cycles, with few + // skips. + if (entry.second >= score_threshold_) + suspected_leaks_.emplace_back(entry.first); + } +} + +bool LeakAnalyzer::GetPreviousCountForValue(const ValueType& value, + uint32_t* count) const { + // Determine what count was recorded for this value last time. + for (const RankedEntry& entry : prev_ranked_entries_) { + if (entry.value == value) { + *count = entry.count; + return true; + } + } + return false; +} + +} // namespace leak_detector +} // namespace metrics
diff --git a/components/metrics/leak_detector/leak_analyzer.h b/components/metrics/leak_detector/leak_analyzer.h new file mode 100644 index 0000000..9ca9c3e7 --- /dev/null +++ b/components/metrics/leak_detector/leak_analyzer.h
@@ -0,0 +1,81 @@ +// Copyright 2015 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 COMPONENTS_METRICS_LEAK_DETECTOR_LEAK_ANALYZER_H_ +#define COMPONENTS_METRICS_LEAK_DETECTOR_LEAK_ANALYZER_H_ + +#include <map> +#include <vector> + +#include "base/macros.h" +#include "components/metrics/leak_detector/custom_allocator.h" +#include "components/metrics/leak_detector/leak_detector_value_type.h" +#include "components/metrics/leak_detector/ranked_list.h" +#include "components/metrics/leak_detector/stl_allocator.h" + +namespace metrics { +namespace leak_detector { + +// This class looks for possible leak patterns in allocation data over time. +// Not thread-safe. +class LeakAnalyzer { + public: + using ValueType = LeakDetectorValueType; + + template <typename Type> + using Allocator = STLAllocator<Type, CustomAllocator>; + + LeakAnalyzer(uint32_t ranking_size, uint32_t num_suspicions_threshold); + ~LeakAnalyzer(); + + // Take in a RankedList of allocations, sorted by count. Removes the contents + // of |ranked_list|, which must be passed in using move semantics. + void AddSample(RankedList ranked_list); + + // Used to report suspected leaks. Reported leaks are sorted by ValueType. + const std::vector<ValueType, Allocator<ValueType>>& suspected_leaks() const { + return suspected_leaks_; + } + + private: + // Analyze a list of allocation count deltas from the previous iteration. If + // anything looks like a possible leak, update the suspicion scores. + void AnalyzeDeltas(const RankedList& ranked_deltas); + + // Returns the count for the given value from the previous analysis in + // |count|. Returns true if the given value was present in the previous + // analysis, or false if not. + bool GetPreviousCountForValue(const ValueType& value, uint32_t* count) const; + + // Look for the top |ranking_size_| entries when analyzing leaks. + const uint32_t ranking_size_; + + // Report suspected leaks when the suspicion score reaches this value. + const uint32_t score_threshold_; + + // A mapping of allocation values to suspicion score. All allocations in this + // container are suspected leaks. The score can increase or decrease over + // time. Once the score reaches |score_threshold_|, the entry is reported as + // a suspected leak in |suspected_leaks_|. + std::map<ValueType, + uint32_t, + std::less<ValueType>, + Allocator<std::pair<ValueType, uint32_t>>> suspected_histogram_; + + // Array of allocated values that passed the suspicion threshold and are being + // reported. + std::vector<ValueType, Allocator<ValueType>> suspected_leaks_; + + // The most recent allocation entries, since the last call to AddSample(). + RankedList ranked_entries_; + // The previous allocation entries, from before the last call to AddSample(). + RankedList prev_ranked_entries_; + + DISALLOW_COPY_AND_ASSIGN(LeakAnalyzer); +}; + +} // namespace leak_detector +} // namespace metrics + +#endif // COMPONENTS_METRICS_LEAK_DETECTOR_LEAK_ANALYZER_H_
diff --git a/components/metrics/leak_detector/leak_analyzer_unittest.cc b/components/metrics/leak_detector/leak_analyzer_unittest.cc new file mode 100644 index 0000000..0008708 --- /dev/null +++ b/components/metrics/leak_detector/leak_analyzer_unittest.cc
@@ -0,0 +1,362 @@ +// Copyright 2015 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 "components/metrics/leak_detector/leak_analyzer.h" + +#include "base/macros.h" +#include "components/metrics/leak_detector/custom_allocator.h" +#include "components/metrics/leak_detector/ranked_list.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace metrics { +namespace leak_detector { + +namespace { + +// Default ranking size and threshold used for leak analysis. +const int kDefaultRankedListSize = 10; +const int kDefaultLeakThreshold = 5; + +// Makes it easier to instantiate LeakDetectorValueTypes. Instantiates with an +// integer value that indicates an allocation size. Storing the size allows us +// to track the storage of the LeakDetectorValueType object within LeakAnalyzer. +// +// There is no need to test this with call stacks in addition to sizes because +// call stacks will be contained in a LeakDetectorValueType object as well. +LeakDetectorValueType Size(uint32_t value) { + return LeakDetectorValueType(value); +} + +} // namespace + +class LeakAnalyzerTest : public ::testing::Test { + public: + LeakAnalyzerTest() {} + + void SetUp() override { CustomAllocator::Initialize(); } + void TearDown() override { EXPECT_TRUE(CustomAllocator::Shutdown()); } + + private: + DISALLOW_COPY_AND_ASSIGN(LeakAnalyzerTest); +}; + +TEST_F(LeakAnalyzerTest, Empty) { + LeakAnalyzer analyzer(kDefaultRankedListSize, kDefaultLeakThreshold); + EXPECT_TRUE(analyzer.suspected_leaks().empty()); +} + +TEST_F(LeakAnalyzerTest, SingleSize) { + LeakAnalyzer analyzer(kDefaultRankedListSize, kDefaultLeakThreshold); + + for (int i = 0; i < kDefaultLeakThreshold + 20; ++i) { + RankedList list(kDefaultRankedListSize); + list.Add(Size(24), 10); + analyzer.AddSample(list.Pass()); + + // No leaks should have been detected. + EXPECT_TRUE(analyzer.suspected_leaks().empty()); + } +} + +TEST_F(LeakAnalyzerTest, VariousSizesWithoutIncrease) { + LeakAnalyzer analyzer(kDefaultRankedListSize, kDefaultLeakThreshold); + + for (int i = 0; i < kDefaultLeakThreshold + 20; ++i) { + RankedList list(kDefaultRankedListSize); + list.Add(Size(24), 30); + list.Add(Size(32), 10); + list.Add(Size(56), 90); + list.Add(Size(64), 40); + analyzer.AddSample(list.Pass()); + + // No leaks should have been detected. + EXPECT_TRUE(analyzer.suspected_leaks().empty()); + } +} + +TEST_F(LeakAnalyzerTest, VariousSizesWithEqualIncrease) { + LeakAnalyzer analyzer(kDefaultRankedListSize, kDefaultLeakThreshold); + + for (int i = 0; i < kDefaultLeakThreshold + 20; ++i) { + RankedList list(kDefaultRankedListSize); + list.Add(Size(24), 30 + i * 10); + list.Add(Size(32), 10 + i * 10); + list.Add(Size(56), 90 + i * 10); + list.Add(Size(64), 40 + i * 10); + analyzer.AddSample(list.Pass()); + + // No leaks should have been detected. + EXPECT_TRUE(analyzer.suspected_leaks().empty()); + } +} + +TEST_F(LeakAnalyzerTest, NotEnoughRunsToTriggerLeakReport) { + LeakAnalyzer analyzer(kDefaultRankedListSize, kDefaultLeakThreshold); + + // Run this one iteration short of the number of cycles needed to trigger a + // leak report. Because LeakAnalyzer requires |kDefaultLeakThreshold| + // suspicions based on deltas between AddSample() calls, the below loop needs + // to run |kDefaultLeakThreshold + 1| times to trigger a leak report. + for (int i = 0; i <= kDefaultLeakThreshold - 1; ++i) { + RankedList list(kDefaultRankedListSize); + list.Add(Size(24), 30 + i * 10); // This one has a potential leak. + list.Add(Size(32), 10 + i * 2); + list.Add(Size(56), 90 + i); + list.Add(Size(64), 40 + i / 2); + analyzer.AddSample(list.Pass()); + + // No leaks should have been detected. + EXPECT_TRUE(analyzer.suspected_leaks().empty()); + } +} + +TEST_F(LeakAnalyzerTest, LeakSingleSize) { + LeakAnalyzer analyzer(kDefaultRankedListSize, kDefaultLeakThreshold); + + // Run this past the number of iterations required to trigger a leak report. + for (int i = 0; i < kDefaultLeakThreshold + 10; ++i) { + RankedList list(kDefaultRankedListSize); + list.Add(Size(32), 10); + list.Add(Size(56), 90); + list.Add(Size(24), 30 + i * 10); // This one has a potential leak. + list.Add(Size(64), 40); + analyzer.AddSample(list.Pass()); + + // No leaks should have been detected initially... + if (i < kDefaultLeakThreshold) { + EXPECT_TRUE(analyzer.suspected_leaks().empty()); + } else { + // ... but there should be reported leaks once the threshold is reached. + const auto& leaks = analyzer.suspected_leaks(); + ASSERT_EQ(1U, leaks.size()); + EXPECT_EQ(24U, leaks[0].size()); + } + } +} + +TEST_F(LeakAnalyzerTest, LeakSingleSizeOthersAlsoIncreasing) { + LeakAnalyzer analyzer(kDefaultRankedListSize, kDefaultLeakThreshold); + + for (int i = 0; i < kDefaultLeakThreshold + 10; ++i) { + RankedList list(kDefaultRankedListSize); + list.Add(Size(24), 30 + i * 10); // This one has a potential leak. + list.Add(Size(32), 10 + i * 2); + list.Add(Size(56), 90 + i); + list.Add(Size(64), 40 + i / 2); + analyzer.AddSample(list.Pass()); + + // No leaks should have been detected initially... + if (i < kDefaultLeakThreshold) { + EXPECT_TRUE(analyzer.suspected_leaks().empty()); + } else { + // ... but there should be reported leaks once the threshold is reached. + const auto& leaks = analyzer.suspected_leaks(); + ASSERT_EQ(1U, leaks.size()); + EXPECT_EQ(24U, leaks[0].size()); + } + } +} + +TEST_F(LeakAnalyzerTest, LeakMultipleSizes) { + LeakAnalyzer analyzer(kDefaultRankedListSize, kDefaultLeakThreshold); + + for (int i = 0; i < kDefaultLeakThreshold + 10; ++i) { + RankedList list(kDefaultRankedListSize); + list.Add(Size(24), 30 + i * 5); + list.Add(Size(32), 10 + i * 40); + list.Add(Size(56), 90 + i * 30); + list.Add(Size(64), 40 + i * 20); + list.Add(Size(80), 20 + i * 3); + analyzer.AddSample(list.Pass()); + + // No leaks should have been detected initially... + if (i < kDefaultLeakThreshold) { + EXPECT_TRUE(analyzer.suspected_leaks().empty()); + } else { + // ... but there should be reported leaks once the threshold is reached. + const auto& leaks = analyzer.suspected_leaks(); + ASSERT_EQ(3U, leaks.size()); + // These should be in order of increasing allocation size. + EXPECT_EQ(32U, leaks[0].size()); + EXPECT_EQ(56U, leaks[1].size()); + EXPECT_EQ(64U, leaks[2].size()); + } + } +} + +TEST_F(LeakAnalyzerTest, LeakMultipleSizesValueOrder) { + LeakAnalyzer analyzer(kDefaultRankedListSize, kDefaultLeakThreshold); + + for (int i = 0; i <= kDefaultLeakThreshold; ++i) { + RankedList list(kDefaultRankedListSize); + // These are similar to LeakMultipleSizes, but the relative order of + // allocation increases is different from the relative order of sizes. + list.Add(Size(24), 30 + i * 5); + list.Add(Size(32), 10 + i * 20); + list.Add(Size(56), 90 + i * 40); + list.Add(Size(64), 40 + i * 30); + list.Add(Size(80), 20 + i * 3); + analyzer.AddSample(list.Pass()); + } + + const auto& leaks = analyzer.suspected_leaks(); + ASSERT_EQ(3U, leaks.size()); + // These should be in order of increasing allocation size, NOT in order of + // allocation count or deltas. + EXPECT_EQ(32U, leaks[0].size()); + EXPECT_EQ(56U, leaks[1].size()); + EXPECT_EQ(64U, leaks[2].size()); +} + +TEST_F(LeakAnalyzerTest, EqualIncreasesNoLeak) { + LeakAnalyzer analyzer(kDefaultRankedListSize, kDefaultLeakThreshold); + + for (int i = 0; i < kDefaultLeakThreshold + 20; ++i) { + RankedList list(kDefaultRankedListSize); + list.Add(Size(24), 30 + i * 10); + list.Add(Size(32), 10 + i * 10); + list.Add(Size(56), 90 + i * 10); + list.Add(Size(64), 40 + i * 10); + list.Add(Size(80), 20 + i * 10); + analyzer.AddSample(list.Pass()); + + EXPECT_TRUE(analyzer.suspected_leaks().empty()); + } +} + +TEST_F(LeakAnalyzerTest, NotBigEnoughDeltaGap) { + LeakAnalyzer analyzer(kDefaultRankedListSize, kDefaultLeakThreshold); + + for (int i = 0; i < kDefaultLeakThreshold + 20; ++i) { + RankedList list(kDefaultRankedListSize); + // These all have different increments but there is no clear group of + // increases that are larger than the rest. + list.Add(Size(24), 30 + i * 80); + list.Add(Size(32), 10 + i * 45); + list.Add(Size(56), 90 + i * 25); + list.Add(Size(64), 40 + i * 15); + list.Add(Size(80), 20 + i * 10); + analyzer.AddSample(list.Pass()); + + EXPECT_TRUE(analyzer.suspected_leaks().empty()); + } +} + +TEST_F(LeakAnalyzerTest, RepeatedRisesUntilLeakFound) { + LeakAnalyzer analyzer(kDefaultRankedListSize, kDefaultLeakThreshold); + + // Remember, there is an extra iteration beyond |kDefaultLeakThreshold| needed + // to actually trigger the leak detection. + for (int i = 0; i <= kDefaultLeakThreshold - 2; ++i) { + RankedList list(kDefaultRankedListSize); + list.Add(Size(24), 30 + i * 10); + list.Add(Size(32), 10); + list.Add(Size(56), 90); + list.Add(Size(64), 40); + list.Add(Size(80), 20); + analyzer.AddSample(list.Pass()); + + EXPECT_TRUE(analyzer.suspected_leaks().empty()); + } + + // Drop back down to 30. + for (int i = 0; i <= kDefaultLeakThreshold - 1; ++i) { + RankedList list(kDefaultRankedListSize); + list.Add(Size(24), 30 + i * 10); + list.Add(Size(32), 10); + list.Add(Size(56), 90); + list.Add(Size(64), 40); + list.Add(Size(80), 20); + analyzer.AddSample(list.Pass()); + + EXPECT_TRUE(analyzer.suspected_leaks().empty()); + } + + // Drop back down to 30. + for (int i = 0; i <= kDefaultLeakThreshold; ++i) { + // Initially there should not be any leak detected. + EXPECT_TRUE(analyzer.suspected_leaks().empty()); + + RankedList list(kDefaultRankedListSize); + list.Add(Size(24), 30 + i * 10); + list.Add(Size(32), 10); + list.Add(Size(56), 90); + list.Add(Size(64), 40); + list.Add(Size(80), 20); + analyzer.AddSample(list.Pass()); + } + const auto& leaks = analyzer.suspected_leaks(); + ASSERT_EQ(1U, leaks.size()); + EXPECT_EQ(24U, leaks[0].size()); +} + +TEST_F(LeakAnalyzerTest, LeakWithMultipleGroupsOfDeltas) { + const int kRankedListSize = 20; + LeakAnalyzer analyzer(kRankedListSize, kDefaultLeakThreshold); + + for (int i = 0; i <= kDefaultLeakThreshold; ++i) { + RankedList list(kRankedListSize); + list.Add(Size(24), 30 + i * 10); // A group of smaller deltas. + list.Add(Size(32), 10 + i * 3); + list.Add(Size(80), 20 + i * 5); + list.Add(Size(40), 30 + i * 7); + list.Add(Size(56), 90); + list.Add(Size(64), 40); + list.Add(Size(128), 100); + list.Add(Size(44), 100 + i * 10); // A group of medium deltas. + list.Add(Size(16), 60 + i * 50); + list.Add(Size(4), 20 + i * 40); + list.Add(Size(8), 100 + i * 60); + list.Add(Size(48), 100); + list.Add(Size(72), 60 + i * 240); // A group of largest deltas. + list.Add(Size(28), 100); + list.Add(Size(100), 100 + i * 200); + list.Add(Size(104), 60 + i * 128); + analyzer.AddSample(list.Pass()); + } + // Only the group of largest deltas should be caught. + const auto& leaks = analyzer.suspected_leaks(); + ASSERT_EQ(3U, leaks.size()); + // These should be in order of increasing allocation size. + EXPECT_EQ(72U, leaks[0].size()); + EXPECT_EQ(100U, leaks[1].size()); + EXPECT_EQ(104U, leaks[2].size()); +} + +TEST_F(LeakAnalyzerTest, LeakMultipleSizesWithLargeThreshold) { + const int kLeakThreshold = 50; + LeakAnalyzer analyzer(kDefaultRankedListSize, kLeakThreshold); + + for (int i = 0; i <= kLeakThreshold + 10; ++i) { + RankedList list(kDefaultRankedListSize); + // * - Cluster of larger deltas + list.Add(Size(24), 30 + i * 5); + list.Add(Size(32), 10 + i * 40); // * + list.Add(Size(56), 90 + i * 30); // * + list.Add(Size(40), 30 + i * 7); + list.Add(Size(64), 40 + i * 25); // * + list.Add(Size(80), 20 + i * 3); + list.Add(Size(128), 100); + list.Add(Size(44), 100 + i * 10); + list.Add(Size(16), 60 + i * 50); // * + analyzer.AddSample(list.Pass()); + + // No leaks should have been detected initially... + if (i < kLeakThreshold) { + EXPECT_TRUE(analyzer.suspected_leaks().empty()); + } else { + // ... but there should be reported leaks once the threshold is reached. + const auto& leaks = analyzer.suspected_leaks(); + ASSERT_EQ(4U, leaks.size()); + // These should be in order of increasing allocation size. + EXPECT_EQ(16U, leaks[0].size()); + EXPECT_EQ(32U, leaks[1].size()); + EXPECT_EQ(56U, leaks[2].size()); + EXPECT_EQ(64U, leaks[3].size()); + } + } +} + +} // namespace leak_detector +} // namespace metrics
diff --git a/components/metrics/leak_detector/leak_detector_impl.cc b/components/metrics/leak_detector/leak_detector_impl.cc new file mode 100644 index 0000000..091d1d1 --- /dev/null +++ b/components/metrics/leak_detector/leak_detector_impl.cc
@@ -0,0 +1,215 @@ +// Copyright 2015 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 "leak_detector_impl.h" + +#include <inttypes.h> +#include <stddef.h> + +#include <algorithm> +#include <new> + +#include "base/hash.h" +#include "base/process/process_handle.h" +#include "components/metrics/leak_detector/call_stack_table.h" +#include "components/metrics/leak_detector/custom_allocator.h" +#include "components/metrics/leak_detector/ranked_list.h" + +namespace metrics { +namespace leak_detector { + +namespace { + +// Look for leaks in the the top N entries in each tier, where N is this value. +const int kRankedListSize = 16; + +// Initial hash table size for |LeakDetectorImpl::address_map_|. +const int kAddressMapNumBuckets = 100003; + +// Number of entries in the alloc size table. As sizes are aligned to 32-bits +// the max supported allocation size is (kNumSizeEntries * 4 - 1). Any larger +// sizes are ignored. This value is chosen high enough that such large sizes +// are rare if not nonexistent. +const int kNumSizeEntries = 2048; + +using ValueType = LeakDetectorValueType; + +// Functions to convert an allocation size to/from the array index used for +// |LeakDetectorImpl::size_entries_|. +size_t SizeToIndex(const size_t size) { + int result = static_cast<int>(size / sizeof(uint32_t)); + if (result < kNumSizeEntries) + return result; + return 0; +} + +size_t IndexToSize(size_t index) { + return sizeof(uint32_t) * index; +} + +} // namespace + +LeakDetectorImpl::LeakReport::LeakReport() : alloc_size_bytes_(0) {} + +LeakDetectorImpl::LeakReport::~LeakReport() {} + +bool LeakDetectorImpl::LeakReport::operator<(const LeakReport& other) const { + if (alloc_size_bytes_ != other.alloc_size_bytes_) + return alloc_size_bytes_ < other.alloc_size_bytes_; + for (size_t i = 0; i < call_stack_.size() && i < other.call_stack_.size(); + ++i) { + if (call_stack_[i] != other.call_stack_[i]) + return call_stack_[i] < other.call_stack_[i]; + } + return call_stack_.size() < other.call_stack_.size(); +} + +LeakDetectorImpl::LeakDetectorImpl(uintptr_t mapping_addr, + size_t mapping_size, + int size_suspicion_threshold, + int call_stack_suspicion_threshold) + : num_allocs_(0), + num_frees_(0), + alloc_size_(0), + free_size_(0), + num_allocs_with_call_stack_(0), + num_stack_tables_(0), + address_map_(kAddressMapNumBuckets), + size_leak_analyzer_(kRankedListSize, size_suspicion_threshold), + size_entries_(kNumSizeEntries), + mapping_addr_(mapping_addr), + mapping_size_(mapping_size), + call_stack_suspicion_threshold_(call_stack_suspicion_threshold) {} + +LeakDetectorImpl::~LeakDetectorImpl() { + // Free any call stack tables. + for (AllocSizeEntry& entry : size_entries_) { + CallStackTable* table = entry.stack_table; + if (!table) + continue; + table->~CallStackTable(); + CustomAllocator::Free(table, sizeof(CallStackTable)); + } + size_entries_.clear(); +} + +bool LeakDetectorImpl::ShouldGetStackTraceForSize(size_t size) const { + return size_entries_[SizeToIndex(size)].stack_table != nullptr; +} + +void LeakDetectorImpl::RecordAlloc(const void* ptr, + size_t size, + int stack_depth, + const void* const stack[]) { + AllocInfo alloc_info; + alloc_info.size = size; + + alloc_size_ += alloc_info.size; + ++num_allocs_; + + AllocSizeEntry* entry = &size_entries_[SizeToIndex(size)]; + ++entry->num_allocs; + + if (entry->stack_table && stack_depth > 0) { + alloc_info.call_stack = + call_stack_manager_.GetCallStack(stack_depth, stack); + entry->stack_table->Add(alloc_info.call_stack); + + ++num_allocs_with_call_stack_; + } + + uintptr_t addr = reinterpret_cast<uintptr_t>(ptr); + address_map_.insert(std::pair<uintptr_t, AllocInfo>(addr, alloc_info)); +} + +void LeakDetectorImpl::RecordFree(const void* ptr) { + // Look up address. + uintptr_t addr = reinterpret_cast<uintptr_t>(ptr); + auto iter = address_map_.find(addr); + // TODO(sque): Catch and report double frees. + if (iter == address_map_.end()) + return; + + const AllocInfo& alloc_info = iter->second; + + AllocSizeEntry* entry = &size_entries_[SizeToIndex(alloc_info.size)]; + ++entry->num_frees; + + const CallStack* call_stack = alloc_info.call_stack; + if (call_stack) { + if (entry->stack_table) + entry->stack_table->Remove(call_stack); + } + ++num_frees_; + free_size_ += alloc_info.size; + + address_map_.erase(iter); +} + +void LeakDetectorImpl::TestForLeaks(InternalVector<LeakReport>* reports) { + // Add net alloc counts for each size to a ranked list. + RankedList size_ranked_list(kRankedListSize); + for (size_t i = 0; i < size_entries_.size(); ++i) { + const AllocSizeEntry& entry = size_entries_[i]; + ValueType size_value(IndexToSize(i)); + size_ranked_list.Add(size_value, entry.num_allocs - entry.num_frees); + } + size_leak_analyzer_.AddSample(size_ranked_list.Pass()); + + // Get suspected leaks by size. + for (const ValueType& size_value : size_leak_analyzer_.suspected_leaks()) { + uint32_t size = size_value.size(); + AllocSizeEntry* entry = &size_entries_[SizeToIndex(size)]; + if (entry->stack_table) + continue; + entry->stack_table = new (CustomAllocator::Allocate(sizeof(CallStackTable))) + CallStackTable(call_stack_suspicion_threshold_); + ++num_stack_tables_; + } + + // Check for leaks in each CallStackTable. It makes sense to this before + // checking the size allocations, because that could potentially create new + // CallStackTable. However, the overhead to check a new CallStackTable is + // small since this function is run very rarely. So handle the leak checks of + // Tier 2 here. + reports->clear(); + for (size_t i = 0; i < size_entries_.size(); ++i) { + const AllocSizeEntry& entry = size_entries_[i]; + CallStackTable* stack_table = entry.stack_table; + if (!stack_table || stack_table->empty()) + continue; + + size_t size = IndexToSize(i); + + // Get suspected leaks by call stack. + stack_table->TestForLeaks(); + const LeakAnalyzer& leak_analyzer = stack_table->leak_analyzer(); + for (const ValueType& call_stack_value : leak_analyzer.suspected_leaks()) { + const CallStack* call_stack = call_stack_value.call_stack(); + + // Return reports by storing in |*reports|. + reports->resize(reports->size() + 1); + LeakReport* report = &reports->back(); + report->alloc_size_bytes_ = size; + report->call_stack_.resize(call_stack->depth); + for (size_t j = 0; j < call_stack->depth; ++j) { + report->call_stack_[j] = GetOffset(call_stack->stack[j]); + } + } + } +} + +size_t LeakDetectorImpl::AddressHash::operator()(uintptr_t addr) const { + return base::Hash(reinterpret_cast<const char*>(&addr), sizeof(addr)); +} + +uintptr_t LeakDetectorImpl::GetOffset(const void* ptr) const { + uintptr_t ptr_value = reinterpret_cast<uintptr_t>(ptr); + if (ptr_value >= mapping_addr_ && ptr_value < mapping_addr_ + mapping_size_) + return ptr_value - mapping_addr_; + return ptr_value; +} + +} // namespace leak_detector +} // namespace metrics
diff --git a/components/metrics/leak_detector/leak_detector_impl.h b/components/metrics/leak_detector/leak_detector_impl.h new file mode 100644 index 0000000..055743b4 --- /dev/null +++ b/components/metrics/leak_detector/leak_detector_impl.h
@@ -0,0 +1,161 @@ +// Copyright 2015 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 COMPONENTS_METRICS_LEAK_DETECTOR_LEAK_DETECTOR_IMPL_H_ +#define COMPONENTS_METRICS_LEAK_DETECTOR_LEAK_DETECTOR_IMPL_H_ + +#include <stdint.h> + +#include <vector> + +#include "base/containers/hash_tables.h" +#include "base/macros.h" +#include "components/metrics/leak_detector/call_stack_manager.h" +#include "components/metrics/leak_detector/custom_allocator.h" +#include "components/metrics/leak_detector/leak_analyzer.h" + +namespace metrics { +namespace leak_detector { + +class CallStackTable; + +// Class that contains the actual leak detection mechanism. +// Not thread-safe. +class LeakDetectorImpl { + public: + // Vector type that's safe to use within the memory leak detector. Uses + // CustomAllocator to avoid recursive malloc hook invocation. + template <typename T> + using InternalVector = std::vector<T, STLAllocator<T, CustomAllocator>>; + + // Leak report generated by LeakDetectorImpl. + class LeakReport { + public: + LeakReport(); + ~LeakReport(); + + size_t alloc_size_bytes() const { return alloc_size_bytes_; } + + const InternalVector<uintptr_t>& call_stack() const { return call_stack_; } + + // Used to compare the contents of two leak reports. + bool operator<(const LeakReport& other) const; + + private: + // LeakDetectorImpl needs access to class members when creating a new leak + // report. + friend class LeakDetectorImpl; + + // Number of bytes allocated by the leak site during each allocation. + size_t alloc_size_bytes_; + + // Unlike the CallStack struct, which consists of addresses, this call stack + // will contain offsets in the executable binary. + InternalVector<uintptr_t> call_stack_; + + // TODO(sque): Add leak detector parameters. + }; + + LeakDetectorImpl(uintptr_t mapping_addr, + size_t mapping_size, + int size_suspicion_threshold, + int call_stack_suspicion_threshold); + ~LeakDetectorImpl(); + + // Indicates whether the given allocation size has an associated call stack + // table, and thus requires a stack unwind. + bool ShouldGetStackTraceForSize(size_t size) const; + + // Record allocs and frees. + void RecordAlloc(const void* ptr, + size_t size, + int stack_depth, + const void* const call_stack[]); + void RecordFree(const void* ptr); + + // Run check for possible leaks based on the current profiling data. + void TestForLeaks(InternalVector<LeakReport>* reports); + + private: + // A record of allocations for a particular size. + struct AllocSizeEntry { + // Number of allocations and frees for this size. + uint32_t num_allocs; + uint32_t num_frees; + + // A stack table, if this size is being profiled for stack as well. + CallStackTable* stack_table; + }; + + // Info for a single allocation. + struct AllocInfo { + AllocInfo() : call_stack(nullptr) {} + + // Number of bytes in this allocation. + size_t size; + + // Points to a unique call stack. + const CallStack* call_stack; + }; + + // Allocator class for allocation entry map. Maps allocated addresses to + // AllocInfo objects. + using AllocationEntryAllocator = + STLAllocator<std::pair<const void*, AllocInfo>, CustomAllocator>; + + // Hash class for addresses. + struct AddressHash { + size_t operator()(uintptr_t addr) const; + }; + + // Returns the offset of |ptr| within the current binary. If it is not in the + // current binary, just return |ptr| as an integer. + uintptr_t GetOffset(const void* ptr) const; + + // Owns all unique call stack objects, which are allocated on the heap. Any + // other class or function that references a call stack must get it from here, + // but may not take ownership of the call stack object. + CallStackManager call_stack_manager_; + + // Allocation stats. + uint64_t num_allocs_; + uint64_t num_frees_; + uint64_t alloc_size_; + uint64_t free_size_; + + uint32_t num_allocs_with_call_stack_; + uint32_t num_stack_tables_; + + // Stores all individual recorded allocations. + base::hash_map<uintptr_t, + AllocInfo, + AddressHash, + std::equal_to<uintptr_t>, + AllocationEntryAllocator> address_map_; + + // Used to analyze potential leak patterns in the allocation sizes. + LeakAnalyzer size_leak_analyzer_; + + // Allocation stats for each size. + InternalVector<AllocSizeEntry> size_entries_; + + // Address mapping info of the current binary. + uintptr_t mapping_addr_; + size_t mapping_size_; + + // Number of consecutive times an allocation size must trigger suspicion to be + // considered a leak suspect. + int size_suspicion_threshold_; + + // Number of consecutive times a call stack must trigger suspicion to be + // considered a leak suspect. + int call_stack_suspicion_threshold_; + + DISALLOW_COPY_AND_ASSIGN(LeakDetectorImpl); +}; + +} // namespace leak_detector +} // namespace metrics + +#endif // COMPONENTS_METRICS_LEAK_DETECTOR_LEAK_DETECTOR_IMPL_H_
diff --git a/components/metrics/leak_detector/leak_detector_impl_unittest.cc b/components/metrics/leak_detector/leak_detector_impl_unittest.cc new file mode 100644 index 0000000..0e9293e --- /dev/null +++ b/components/metrics/leak_detector/leak_detector_impl_unittest.cc
@@ -0,0 +1,464 @@ +// Copyright 2015 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 "components/metrics/leak_detector/leak_detector_impl.h" + +#include <math.h> +#include <stdint.h> + +#include <complex> +#include <new> +#include <set> +#include <vector> + +#include "base/macros.h" +#include "base/memory/scoped_ptr.h" +#include "components/metrics/leak_detector/custom_allocator.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace metrics { +namespace leak_detector { + +using InternalLeakReport = LeakDetectorImpl::LeakReport; + +namespace { + +// Makes working with complex numbers easier. +using Complex = std::complex<double>; + +// The mapping location in memory for a fictional executable. +const uintptr_t kMappingAddr = 0x800000; +const size_t kMappingSize = 0x200000; + +// Some call stacks within the fictional executable. +// * - outside the mapping range, e.g. JIT code. +const uintptr_t kRawStack0[] = { + 0x800100, 0x900000, 0x880080, 0x810000, +}; +const uintptr_t kRawStack1[] = { + 0x940000, 0x980000, + 0xdeadbeef, // * + 0x9a0000, +}; +const uintptr_t kRawStack2[] = { + 0x8f0d00, 0x803abc, 0x9100a0, +}; +const uintptr_t kRawStack3[] = { + 0x90fcde, + 0x900df00d, // * + 0x801000, 0x880088, + 0xdeadcafe, // * + 0x9f0000, 0x8700a0, 0x96037c, +}; +const uintptr_t kRawStack4[] = { + 0x8c0000, 0x85d00d, 0x921337, + 0x780000, // * +}; +const uintptr_t kRawStack5[] = { + 0x990000, 0x888888, 0x830ac0, 0x8e0000, + 0xc00000, // * +}; + +// This struct makes it easier to pass call stack info to +// LeakDetectorImplTest::Alloc(). +struct TestCallStack { + const uintptr_t* stack; // A reference to the original stack data. + size_t depth; +}; + +const TestCallStack kStack0 = {kRawStack0, arraysize(kRawStack0)}; +const TestCallStack kStack1 = {kRawStack1, arraysize(kRawStack1)}; +const TestCallStack kStack2 = {kRawStack2, arraysize(kRawStack2)}; +const TestCallStack kStack3 = {kRawStack3, arraysize(kRawStack3)}; +const TestCallStack kStack4 = {kRawStack4, arraysize(kRawStack4)}; +const TestCallStack kStack5 = {kRawStack5, arraysize(kRawStack5)}; + +// The interval between consecutive analyses (LeakDetectorImpl::TestForLeaks), +// in number of bytes allocated. e.g. if |kAllocedSizeAnalysisInterval| = 1024 +// then call TestForLeaks() every 1024 bytes of allocation that occur. +static const size_t kAllocedSizeAnalysisInterval = 8192; + +} // namespace + +// This test suite will test the ability of LeakDetectorImpl to catch leaks in +// a program. Individual tests can run leaky code locally. +// +// The leaky code must call Alloc() and Free() for heap memory management. It +// should not call See comments on those +// functions for more details. +class LeakDetectorImplTest : public ::testing::Test { + public: + LeakDetectorImplTest() + : total_num_allocs_(0), + total_num_frees_(0), + total_alloced_size_(0), + next_analysis_total_alloced_size_(kAllocedSizeAnalysisInterval) {} + + void SetUp() override { + CustomAllocator::Initialize(); + + const int kSizeSuspicionThreshold = 4; + const int kCallStackSuspicionThreshold = 4; + detector_.reset(new LeakDetectorImpl(kMappingAddr, kMappingSize, + kSizeSuspicionThreshold, + kCallStackSuspicionThreshold)); + } + + void TearDown() override { + // Free any memory that was leaked by test cases. Do not use Free() because + // that will try to modify |alloced_ptrs_|. + for (void* ptr : alloced_ptrs_) + delete[] reinterpret_cast<char*>(ptr); + alloced_ptrs_.clear(); + + // Must destroy all objects that use CustomAllocator before shutting down. + detector_.reset(); + stored_reports_.clear(); + + EXPECT_TRUE(CustomAllocator::Shutdown()); + } + + protected: + // Alloc and free functions that allocate and free heap memory and + // automatically pass alloc/free info to |detector_|. They emulate the + // alloc/free hook functions that would call into LeakDetectorImpl in + // real-life usage. They also keep track of individual allocations locally, so + // any leaked memory could be cleaned up. + // + // |stack| is just a nominal call stack object to identify the call site. It + // doesn't have to contain the stack trace of the actual call stack. + void* Alloc(size_t size, const TestCallStack& stack) { + void* ptr = new char[size]; + detector_->RecordAlloc(ptr, size, stack.depth, + reinterpret_cast<const void* const*>(stack.stack)); + + EXPECT_TRUE(alloced_ptrs_.find(ptr) == alloced_ptrs_.end()); + alloced_ptrs_.insert(ptr); + + ++total_num_allocs_; + total_alloced_size_ += size; + if (total_alloced_size_ >= next_analysis_total_alloced_size_) { + LeakDetectorImpl::InternalVector<InternalLeakReport> reports; + detector_->TestForLeaks(&reports); + for (const InternalLeakReport& report : reports) + stored_reports_.insert(report); + + // Determine when the next leak analysis should occur. + while (total_alloced_size_ >= next_analysis_total_alloced_size_) + next_analysis_total_alloced_size_ += kAllocedSizeAnalysisInterval; + } + return ptr; + } + + // See comment for Alloc(). + void Free(void* ptr) { + auto find_ptr_iter = alloced_ptrs_.find(ptr); + EXPECT_FALSE(find_ptr_iter == alloced_ptrs_.end()); + if (find_ptr_iter == alloced_ptrs_.end()) + return; + alloced_ptrs_.erase(find_ptr_iter); + ++total_num_frees_; + + detector_->RecordFree(ptr); + + delete[] reinterpret_cast<char*>(ptr); + } + + // TEST CASE: Julia set fractal computation. Pass in enable_leaks=true to + // trigger some memory leaks. + void JuliaSet(bool enable_leaks); + + // Instance of the class being tested. + scoped_ptr<LeakDetectorImpl> detector_; + + // Number of pointers allocated and freed so far. + size_t total_num_allocs_; + size_t total_num_frees_; + + // Keeps count of total size allocated by Alloc(). + size_t total_alloced_size_; + + // The cumulative allocation size at which to trigger the TestForLeaks() call. + size_t next_analysis_total_alloced_size_; + + // Stores all pointers to memory allocated by by Alloc() so we can manually + // free the leaked pointers at the end. This also serves as redundant + // bookkeepping: it stores all pointers that have been allocated but not yet + // freed. + std::set<void*> alloced_ptrs_; + + // Store leak reports here. Use a set so duplicate reports are not stored. + std::set<InternalLeakReport> stored_reports_; + + private: + DISALLOW_COPY_AND_ASSIGN(LeakDetectorImplTest); +}; + +void LeakDetectorImplTest::JuliaSet(bool enable_leaks) { + // The center region of the complex plane that is the basis for our Julia set + // computations is a circle of radius kRadius. + constexpr double kRadius = 2; + + // To track points in the complex plane, we will use a rectangular grid in the + // range defined by [-kRadius, kRadius] along both axes. + constexpr double kRangeMin = -kRadius; + constexpr double kRangeMax = kRadius; + + // Divide each axis into intervals, each of which is associated with a point + // on that axis at its center. + constexpr double kIntervalInverse = 64; + constexpr double kInterval = 1.0 / kIntervalInverse; + constexpr int kNumPoints = (kRangeMax - kRangeMin) / kInterval + 1; + + // Contains some useful functions for converting between points on the complex + // plane and in a gridlike data structure. + struct ComplexPlane { + static int GetXGridIndex(const Complex& value) { + return (value.real() + kInterval / 2 - kRangeMin) / kInterval; + } + static int GetYGridIndex(const Complex& value) { + return (value.imag() + kInterval / 2 - kRangeMin) / kInterval; + } + static int GetArrayIndex(const Complex& value) { + return GetXGridIndex(value) + GetYGridIndex(value) * kNumPoints; + } + static Complex GetComplexForGridPoint(size_t x, size_t y) { + return Complex(kRangeMin + x * kInterval, kRangeMin + y * kInterval); + } + }; + + // Make sure the choice of interval doesn't result in any loss of precision. + ASSERT_EQ(1.0, kInterval * kIntervalInverse); + + // Create a grid for part of the complex plane, with each axis within the + // range [kRangeMin, kRangeMax]. + constexpr size_t width = kNumPoints; + constexpr size_t height = kNumPoints; + std::vector<Complex*> grid(width * height); + + // Initialize an object for each point within the inner circle |z| < kRadius. + for (size_t i = 0; i < width; ++i) { + for (size_t j = 0; j < height; ++j) { + Complex point = ComplexPlane::GetComplexForGridPoint(i, j); + // Do not store any values outside the inner circle. + if (abs(point) <= kRadius) { + grid[i + j * width] = + new (Alloc(sizeof(Complex), kStack0)) Complex(point); + } + } + } + EXPECT_LE(alloced_ptrs_.size(), width * height); + + // Create a new grid for the result of the transformation. + std::vector<Complex*> next_grid(width * height, nullptr); + + const int kNumIterations = 20; + for (int n = 0; n < kNumIterations; ++n) { + for (int i = 0; i < kNumPoints; ++i) { + for (int j = 0; j < kNumPoints; ++j) { + if (!grid[i + j * width]) + continue; + + // NOTE: The below code is NOT an efficient way to compute a Julia set. + // This is only to test the leak detector with some nontrivial code. + + // A simple polynomial function for generating Julia sets is: + // f(z) = z^n + c + + // But in this algorithm, we need the inverse: + // fInv(z) = (z - c)^(1/n) + + // Here, let's use n=5 and c=0.544. + const Complex c(0.544, 0); + const Complex& z = *grid[i + j * width]; + + // This is the principal root. + Complex root = pow(z - c, 0.2); + + // Discard the result if it is too far out from the center of the plane. + if (abs(root) > kRadius) + continue; + + // The below code only allocates Complex objects of the same size. The + // leak detector expects various sizes, so increase the allocation size + // by a different amount at each call site. + + // Nth root produces N results. + // Place all root results on |next_grid|. + + // First, place the principal root. + if (!next_grid[ComplexPlane::GetArrayIndex(root)]) { + next_grid[ComplexPlane::GetArrayIndex(root)] = + new (Alloc(sizeof(Complex) + 24, kStack1)) Complex(root); + } + + double magnitude = abs(root); + double angle = arg(root); + // To generate other roots, rotate the principal root by increments of + // 1/N of a full circle. + const double kAngleIncrement = M_PI * 2 / 5; + + // Second root. + root = std::polar(magnitude, angle + kAngleIncrement); + if (!next_grid[ComplexPlane::GetArrayIndex(root)]) { + next_grid[ComplexPlane::GetArrayIndex(root)] = + new (Alloc(sizeof(Complex) + 40, kStack2)) Complex(root); + } + + // In some of the sections below, setting |enable_leaks| to true will + // trigger a memory leak by overwriting the old Complex pointer value + // without freeing it. Due to the nature of complex roots being confined + // to equal sections of the complex plane, each new pointer will + // displace an old pointer that was allocated from the same line of + // code. + + // Third root. + root = std::polar(magnitude, angle + kAngleIncrement * 2); + // *** LEAK *** + if (enable_leaks || !next_grid[ComplexPlane::GetArrayIndex(root)]) { + next_grid[ComplexPlane::GetArrayIndex(root)] = + new (Alloc(sizeof(Complex) + 40, kStack3)) Complex(root); + } + + // Fourth root. + root = std::polar(magnitude, angle + kAngleIncrement * 3); + // *** LEAK *** + if (enable_leaks || !next_grid[ComplexPlane::GetArrayIndex(root)]) { + next_grid[ComplexPlane::GetArrayIndex(root)] = + new (Alloc(sizeof(Complex) + 52, kStack4)) Complex(root); + } + + // Fifth root. + root = std::polar(magnitude, angle + kAngleIncrement * 4); + if (!next_grid[ComplexPlane::GetArrayIndex(root)]) { + next_grid[ComplexPlane::GetArrayIndex(root)] = + new (Alloc(sizeof(Complex) + 52, kStack5)) Complex(root); + } + } + } + + // Clear the previously allocated points. + for (Complex*& point : grid) { + if (point) { + Free(point); + point = nullptr; + } + } + + // Now swap the two grids for the next iteration. + grid.swap(next_grid); + } + + // Clear the previously allocated points. + for (Complex*& point : grid) { + if (point) { + Free(point); + point = nullptr; + } + } +} + +TEST_F(LeakDetectorImplTest, CheckTestFramework) { + EXPECT_EQ(0U, total_num_allocs_); + EXPECT_EQ(0U, total_num_frees_); + EXPECT_EQ(0U, alloced_ptrs_.size()); + + // Allocate some memory. + void* ptr0 = Alloc(12, kStack0); + void* ptr1 = Alloc(16, kStack0); + void* ptr2 = Alloc(24, kStack0); + EXPECT_EQ(3U, total_num_allocs_); + EXPECT_EQ(0U, total_num_frees_); + EXPECT_EQ(3U, alloced_ptrs_.size()); + + // Free one of the pointers. + Free(ptr1); + EXPECT_EQ(3U, total_num_allocs_); + EXPECT_EQ(1U, total_num_frees_); + EXPECT_EQ(2U, alloced_ptrs_.size()); + + // Allocate some more memory. + void* ptr3 = Alloc(72, kStack1); + void* ptr4 = Alloc(104, kStack1); + void* ptr5 = Alloc(96, kStack1); + void* ptr6 = Alloc(24, kStack1); + EXPECT_EQ(7U, total_num_allocs_); + EXPECT_EQ(1U, total_num_frees_); + EXPECT_EQ(6U, alloced_ptrs_.size()); + + // Free more pointers. + Free(ptr2); + Free(ptr4); + Free(ptr6); + EXPECT_EQ(7U, total_num_allocs_); + EXPECT_EQ(4U, total_num_frees_); + EXPECT_EQ(3U, alloced_ptrs_.size()); + + // Free remaining memory. + Free(ptr0); + Free(ptr3); + Free(ptr5); + EXPECT_EQ(7U, total_num_allocs_); + EXPECT_EQ(7U, total_num_frees_); + EXPECT_EQ(0U, alloced_ptrs_.size()); +} + +TEST_F(LeakDetectorImplTest, JuliaSetNoLeak) { + JuliaSet(false /* enable_leaks */); + + // JuliaSet() should have run cleanly without leaking. + EXPECT_EQ(total_num_allocs_, total_num_frees_); + EXPECT_EQ(0U, alloced_ptrs_.size()); + ASSERT_EQ(0U, stored_reports_.size()); +} + +TEST_F(LeakDetectorImplTest, JuliaSetWithLeak) { + JuliaSet(true /* enable_leaks */); + + // JuliaSet() should have leaked some memory from two call sites. + EXPECT_GT(total_num_allocs_, total_num_frees_); + EXPECT_GT(alloced_ptrs_.size(), 0U); + + // There should be one unique leak report generated for each leaky call site. + ASSERT_EQ(2U, stored_reports_.size()); + + // The reports should be stored in order of size. + + // |report1| comes from the call site in JuliaSet() corresponding to + // |kStack3|. + const InternalLeakReport& report1 = *stored_reports_.begin(); + EXPECT_EQ(sizeof(Complex) + 40, report1.alloc_size_bytes()); + EXPECT_EQ(kStack3.depth, report1.call_stack().size()); + for (size_t i = 0; i < kStack3.depth && i < report1.call_stack().size(); + ++i) { + // The call stack's addresses may not fall within the mapping address. + // Those that don't will not be converted to mapping offsets. + if (kStack3.stack[i] >= kMappingAddr && + kStack3.stack[i] <= kMappingAddr + kMappingSize) { + EXPECT_EQ(kStack3.stack[i] - kMappingAddr, report1.call_stack()[i]); + } else { + EXPECT_EQ(kStack3.stack[i], report1.call_stack()[i]); + } + } + + // |report2| comes from the call site in JuliaSet() corresponding to + // |kStack4|. + const InternalLeakReport& report2 = *(++stored_reports_.begin()); + EXPECT_EQ(sizeof(Complex) + 52, report2.alloc_size_bytes()); + EXPECT_EQ(kStack4.depth, report2.call_stack().size()); + for (size_t i = 0; i < kStack4.depth && i < report2.call_stack().size(); + ++i) { + // The call stack's addresses may not fall within the mapping address. + // Those that don't will not be converted to mapping offsets. + if (kStack4.stack[i] >= kMappingAddr && + kStack4.stack[i] <= kMappingAddr + kMappingSize) { + EXPECT_EQ(kStack4.stack[i] - kMappingAddr, report2.call_stack()[i]); + } else { + EXPECT_EQ(kStack4.stack[i], report2.call_stack()[i]); + } + } +} + +} // namespace leak_detector +} // namespace metrics
diff --git a/components/metrics/leak_detector/leak_detector_value_type.cc b/components/metrics/leak_detector/leak_detector_value_type.cc new file mode 100644 index 0000000..4642f515 --- /dev/null +++ b/components/metrics/leak_detector/leak_detector_value_type.cc
@@ -0,0 +1,47 @@ +// Copyright 2015 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 "components/metrics/leak_detector/leak_detector_value_type.h" + +#include <stdio.h> + +namespace metrics { +namespace leak_detector { + +bool LeakDetectorValueType::operator==( + const LeakDetectorValueType& other) const { + if (type_ != other.type_) + return false; + + switch (type_) { + case TYPE_SIZE: + return size_ == other.size_; + case TYPE_CALL_STACK: + return call_stack_ == other.call_stack_; + case TYPE_NONE: + // "NONE" types are considered to be all identical. + return true; + } + return false; +} + +bool LeakDetectorValueType::operator<( + const LeakDetectorValueType& other) const { + if (type_ != other.type_) + return type_ < other.type_; + + switch (type_) { + case TYPE_SIZE: + return size_ < other.size_; + case TYPE_CALL_STACK: + return call_stack_ < other.call_stack_; + case TYPE_NONE: + // "NONE" types are considered to be all identical. + return false; + } + return false; +} + +} // namespace leak_detector +} // namespace metrics
diff --git a/components/metrics/leak_detector/leak_detector_value_type.h b/components/metrics/leak_detector/leak_detector_value_type.h new file mode 100644 index 0000000..40f6108 --- /dev/null +++ b/components/metrics/leak_detector/leak_detector_value_type.h
@@ -0,0 +1,52 @@ +// Copyright 2015 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 COMPONENTS_METRICS_LEAK_DETECTOR_LEAK_DETECTOR_VALUE_TYPE_ +#define COMPONENTS_METRICS_LEAK_DETECTOR_LEAK_DETECTOR_VALUE_TYPE_ + +#include <stddef.h> +#include <stdint.h> + +namespace metrics { +namespace leak_detector { + +// Used for tracking unique call stacks. +// Not thread-safe. +struct CallStack; + +class LeakDetectorValueType { + public: + // Supported types. + enum Type { + TYPE_NONE, + TYPE_SIZE, + TYPE_CALL_STACK, + }; + + LeakDetectorValueType() : type_(TYPE_NONE), size_(0), call_stack_(nullptr) {} + explicit LeakDetectorValueType(size_t size) + : type_(TYPE_SIZE), size_(size), call_stack_(nullptr) {} + explicit LeakDetectorValueType(const CallStack* call_stack) + : type_(TYPE_CALL_STACK), size_(0), call_stack_(call_stack) {} + + // Accessors. + Type type() const { return type_; } + size_t size() const { return size_; } + const CallStack* call_stack() const { return call_stack_; } + + // Comparators. + bool operator==(const LeakDetectorValueType& other) const; + bool operator<(const LeakDetectorValueType& other) const; + + private: + Type type_; + + size_t size_; + const CallStack* call_stack_; +}; + +} // namespace leak_detector +} // namespace metrics + +#endif // COMPONENTS_METRICS_LEAK_DETECTOR_LEAK_DETECTOR_VALUE_TYPE_
diff --git a/components/metrics/leak_detector/ranked_list.cc b/components/metrics/leak_detector/ranked_list.cc new file mode 100644 index 0000000..4900025c --- /dev/null +++ b/components/metrics/leak_detector/ranked_list.cc
@@ -0,0 +1,45 @@ +// Copyright 2015 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 "components/metrics/leak_detector/ranked_list.h" + +#include <algorithm> + +namespace metrics { +namespace leak_detector { + +RankedList::RankedList(size_t max_size) : max_size_(max_size) {} + +RankedList::~RankedList() {} + +RankedList::RankedList(RankedList::RValue other) + : max_size_(other.object->max_size_) { + entries_.swap(other.object->entries_); +} + +RankedList& RankedList::operator=(RankedList::RValue other) { + max_size_ = other.object->max_size_; + entries_.swap(other.object->entries_); + return *this; +} + +void RankedList::Add(const ValueType& value, int count) { + // Determine where to insert the value given its count. + EntryList::iterator iter = std::upper_bound(entries_.begin(), entries_.end(), + Entry{ValueType(), count}); + + // If the list is full, do not add any entry with |count| if does not exceed + // the lowest count of the entries in the list. + if (size() == max_size_ && iter == end()) + return; + + entries_.insert(iter, Entry({value, count})); + + // Limit the list size if it exceeds the maximum allowed size. + if (entries_.size() > max_size_) + entries_.resize(max_size_); +} + +} // namespace leak_detector +} // namespace metrics
diff --git a/components/metrics/leak_detector/ranked_list.h b/components/metrics/leak_detector/ranked_list.h new file mode 100644 index 0000000..5cb87ba --- /dev/null +++ b/components/metrics/leak_detector/ranked_list.h
@@ -0,0 +1,81 @@ +// Copyright 2015 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 COMPONENTS_METRICS_LEAK_DETECTOR_RANKED_LIST_H_ +#define COMPONENTS_METRICS_LEAK_DETECTOR_RANKED_LIST_H_ + +#include <stddef.h> + +#include <list> + +#include "base/macros.h" +#include "base/move.h" +#include "components/metrics/leak_detector/custom_allocator.h" +#include "components/metrics/leak_detector/leak_detector_value_type.h" +#include "components/metrics/leak_detector/stl_allocator.h" + +namespace metrics { +namespace leak_detector { + +// RankedList lets you add entries consisting of a value-count pair, and +// automatically sorts them internally by count in descending order. This allows +// for the user of this list to put value-count pairs into this list without +// having to explicitly sort them by count. +class RankedList { + MOVE_ONLY_TYPE_FOR_CPP_03(RankedList, RValue); + + public: + using ValueType = LeakDetectorValueType; + + // A single entry in the RankedList. The RankedList sorts entries by |count| + // in descending order. + struct Entry { + ValueType value; + int count; + + // Create a < comparator for reverse sorting. + bool operator<(const Entry& entry) const { return count > entry.count; } + }; + + using EntryList = std::list<Entry, STLAllocator<Entry, CustomAllocator>>; + using const_iterator = EntryList::const_iterator; + + explicit RankedList(size_t max_size); + ~RankedList(); + + // For move semantics. + RankedList(RValue other); + RankedList& operator=(RValue other); + + // Accessors for begin() and end() const iterators. + const_iterator begin() const { return entries_.begin(); } + const_iterator end() const { return entries_.end(); } + + size_t size() const { return entries_.size(); } + size_t max_size() const { return max_size_; } + + // Add a new value-count pair to the list. Does not check for existing entries + // with the same value. Is an O(n) operation due to ordering. + void Add(const ValueType& value, int count); + + private: + // Max and min counts. Returns 0 if the list is empty. + int max_count() const { + return entries_.empty() ? 0 : entries_.begin()->count; + } + int min_count() const { + return entries_.empty() ? 0 : entries_.rbegin()->count; + } + + // Max number of items that can be stored in the list. + size_t max_size_; + + // Points to the array of entries. + std::list<Entry, STLAllocator<Entry, CustomAllocator>> entries_; +}; + +} // namespace leak_detector +} // namespace metrics + +#endif // COMPONENTS_METRICS_LEAK_DETECTOR_RANKED_LIST_H_
diff --git a/components/metrics/leak_detector/ranked_list_unittest.cc b/components/metrics/leak_detector/ranked_list_unittest.cc new file mode 100644 index 0000000..9ebbefb --- /dev/null +++ b/components/metrics/leak_detector/ranked_list_unittest.cc
@@ -0,0 +1,266 @@ +// Copyright 2015 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 "components/metrics/leak_detector/ranked_list.h" + +#include "base/macros.h" +#include "components/metrics/leak_detector/custom_allocator.h" +#include "components/metrics/leak_detector/leak_detector_value_type.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace metrics { +namespace leak_detector { + +namespace { + +// Makes it easier to instantiate LeakDetectorValueTypes. +LeakDetectorValueType Value(uint32_t value) { + return LeakDetectorValueType(value); +} + +} // namespace + +class RankedListTest : public ::testing::Test { + public: + RankedListTest() {} + + void SetUp() override { CustomAllocator::Initialize(); } + void TearDown() override { EXPECT_TRUE(CustomAllocator::Shutdown()); } + + private: + DISALLOW_COPY_AND_ASSIGN(RankedListTest); +}; + +TEST_F(RankedListTest, Iterators) { + RankedList list(10); + EXPECT_TRUE(list.begin() == list.end()); + + list.Add(Value(0x1234), 100); + EXPECT_FALSE(list.begin() == list.end()); +} + +TEST_F(RankedListTest, SingleInsertion) { + RankedList list(10); + EXPECT_EQ(0U, list.size()); + + list.Add(Value(0x1234), 100); + EXPECT_EQ(1U, list.size()); + + auto iter = list.begin(); + EXPECT_EQ(0x1234U, iter->value.size()); + EXPECT_EQ(100, iter->count); +} + +TEST_F(RankedListTest, InOrderInsertion) { + RankedList list(10); + EXPECT_EQ(0U, list.size()); + + list.Add(Value(0x1234), 100); + EXPECT_EQ(1U, list.size()); + list.Add(Value(0x2345), 95); + EXPECT_EQ(2U, list.size()); + list.Add(Value(0x3456), 90); + EXPECT_EQ(3U, list.size()); + list.Add(Value(0x4567), 85); + EXPECT_EQ(4U, list.size()); + list.Add(Value(0x5678), 80); + EXPECT_EQ(5U, list.size()); + + // Iterate through the contents to make sure they match what went in. + const RankedList::Entry kExpectedValues[] = { + {Value(0x1234), 100}, {Value(0x2345), 95}, {Value(0x3456), 90}, + {Value(0x4567), 85}, {Value(0x5678), 80}, + }; + + size_t index = 0; + for (const auto& entry : list) { + EXPECT_LT(index, arraysize(kExpectedValues)); + EXPECT_EQ(kExpectedValues[index].value.size(), entry.value.size()); + EXPECT_EQ(kExpectedValues[index].count, entry.count); + ++index; + } +} + +TEST_F(RankedListTest, ReverseOrderInsertion) { + RankedList list(10); + EXPECT_EQ(0U, list.size()); + + list.Add(Value(0x1234), 0); + EXPECT_EQ(1U, list.size()); + list.Add(Value(0x2345), 5); + EXPECT_EQ(2U, list.size()); + list.Add(Value(0x3456), 10); + EXPECT_EQ(3U, list.size()); + list.Add(Value(0x4567), 15); + EXPECT_EQ(4U, list.size()); + list.Add(Value(0x5678), 20); + EXPECT_EQ(5U, list.size()); + + // Iterate through the contents to make sure they match what went in. + const RankedList::Entry kExpectedValues[] = { + {Value(0x5678), 20}, {Value(0x4567), 15}, {Value(0x3456), 10}, + {Value(0x2345), 5}, {Value(0x1234), 0}, + }; + + size_t index = 0; + for (const auto& entry : list) { + EXPECT_LT(index, arraysize(kExpectedValues)); + EXPECT_EQ(kExpectedValues[index].value.size(), entry.value.size()); + EXPECT_EQ(kExpectedValues[index].count, entry.count); + ++index; + } +} + +TEST_F(RankedListTest, UnorderedInsertion) { + RankedList list(10); + EXPECT_EQ(0U, list.size()); + + list.Add(Value(0x1234), 15); + list.Add(Value(0x2345), 20); + list.Add(Value(0x3456), 10); + list.Add(Value(0x4567), 30); + list.Add(Value(0x5678), 25); + EXPECT_EQ(5U, list.size()); + + // Iterate through the contents to make sure they match what went in. + const RankedList::Entry kExpectedValues1[] = { + {Value(0x4567), 30}, {Value(0x5678), 25}, {Value(0x2345), 20}, + {Value(0x1234), 15}, {Value(0x3456), 10}, + }; + + size_t index = 0; + for (const auto& entry : list) { + EXPECT_LT(index, arraysize(kExpectedValues1)); + EXPECT_EQ(kExpectedValues1[index].value.size(), entry.value.size()); + EXPECT_EQ(kExpectedValues1[index].count, entry.count); + ++index; + } + + // Add more items. + list.Add(Value(0x6789), 35); + list.Add(Value(0x789a), 40); + list.Add(Value(0x89ab), 50); + list.Add(Value(0x9abc), 5); + list.Add(Value(0xabcd), 0); + EXPECT_EQ(10U, list.size()); + + // Iterate through the contents to make sure they match what went in. + const RankedList::Entry kExpectedValues2[] = { + {Value(0x89ab), 50}, {Value(0x789a), 40}, {Value(0x6789), 35}, + {Value(0x4567), 30}, {Value(0x5678), 25}, {Value(0x2345), 20}, + {Value(0x1234), 15}, {Value(0x3456), 10}, {Value(0x9abc), 5}, + {Value(0xabcd), 0}, + }; + + index = 0; + for (const auto& entry : list) { + EXPECT_LT(index, arraysize(kExpectedValues2)); + EXPECT_EQ(kExpectedValues2[index].value.size(), entry.value.size()); + EXPECT_EQ(kExpectedValues2[index].count, entry.count); + ++index; + } +} + +TEST_F(RankedListTest, InsertionWithOverflow) { + RankedList list(5); + EXPECT_EQ(0U, list.size()); + + list.Add(Value(0x1234), 15); + list.Add(Value(0x2345), 20); + list.Add(Value(0x3456), 10); + list.Add(Value(0x4567), 30); + list.Add(Value(0x5678), 25); + EXPECT_EQ(5U, list.size()); + + // These values will not make it into the list, which is now full. + list.Add(Value(0x6789), 0); + EXPECT_EQ(5U, list.size()); + list.Add(Value(0x789a), 5); + EXPECT_EQ(5U, list.size()); + + // Iterate through the contents to make sure they match what went in. + const RankedList::Entry kExpectedValues1[] = { + {Value(0x4567), 30}, {Value(0x5678), 25}, {Value(0x2345), 20}, + {Value(0x1234), 15}, {Value(0x3456), 10}, + }; + + size_t index = 0; + for (const auto& entry : list) { + EXPECT_LT(index, arraysize(kExpectedValues1)); + EXPECT_EQ(kExpectedValues1[index].value.size(), entry.value.size()); + EXPECT_EQ(kExpectedValues1[index].count, entry.count); + ++index; + } + + // Insert some more values that go in the middle of the list. + list.Add(Value(0x89ab), 27); + EXPECT_EQ(5U, list.size()); + list.Add(Value(0x9abc), 22); + EXPECT_EQ(5U, list.size()); + + // Iterate through the contents to make sure they match what went in. + const RankedList::Entry kExpectedValues2[] = { + {Value(0x4567), 30}, {Value(0x89ab), 27}, {Value(0x5678), 25}, + {Value(0x9abc), 22}, {Value(0x2345), 20}, + }; + + index = 0; + for (const auto& entry : list) { + EXPECT_LT(index, arraysize(kExpectedValues2)); + EXPECT_EQ(kExpectedValues2[index].value.size(), entry.value.size()); + EXPECT_EQ(kExpectedValues2[index].count, entry.count); + ++index; + } + + // Insert some more values at the front of the list. + list.Add(Value(0xabcd), 40); + EXPECT_EQ(5U, list.size()); + list.Add(Value(0xbcde), 35); + EXPECT_EQ(5U, list.size()); + + // Iterate through the contents to make sure they match what went in. + const RankedList::Entry kExpectedValues3[] = { + {Value(0xabcd), 40}, {Value(0xbcde), 35}, {Value(0x4567), 30}, + {Value(0x89ab), 27}, {Value(0x5678), 25}, + }; + + index = 0; + for (const auto& entry : list) { + EXPECT_LT(index, arraysize(kExpectedValues3)); + EXPECT_EQ(kExpectedValues3[index].value.size(), entry.value.size()); + EXPECT_EQ(kExpectedValues3[index].count, entry.count); + ++index; + } +} + +TEST_F(RankedListTest, MoveOperation) { + const RankedList::Entry kExpectedValues[] = { + {Value(0x89ab), 50}, {Value(0x789a), 40}, {Value(0x6789), 35}, + {Value(0x4567), 30}, {Value(0x5678), 25}, {Value(0x2345), 20}, + {Value(0x1234), 15}, {Value(0x3456), 10}, {Value(0x9abc), 5}, + {Value(0xabcd), 0}, + }; + + RankedList source_list(10); + for (const RankedList::Entry& entry : kExpectedValues) { + source_list.Add(entry.value, entry.count); + } + EXPECT_EQ(10U, source_list.size()); + + RankedList dest_list(25); // This should be changed by the move. + dest_list = source_list.Pass(); + EXPECT_EQ(10U, dest_list.size()); + EXPECT_EQ(10U, dest_list.max_size()); + + size_t index = 0; + for (const auto& entry : dest_list) { + EXPECT_LT(index, arraysize(kExpectedValues)); + EXPECT_EQ(kExpectedValues[index].value.size(), entry.value.size()); + EXPECT_EQ(kExpectedValues[index].count, entry.count); + ++index; + } +} + +} // namespace leak_detector +} // namespace metrics
diff --git a/components/metrics/leak_detector/stl_allocator.h b/components/metrics/leak_detector/stl_allocator.h new file mode 100644 index 0000000..bfef0a38 --- /dev/null +++ b/components/metrics/leak_detector/stl_allocator.h
@@ -0,0 +1,61 @@ +// Copyright 2015 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 COMPONENTS_METRICS_LEAK_DETECTOR_STL_ALLOCATOR_H_ +#define COMPONENTS_METRICS_LEAK_DETECTOR_STL_ALLOCATOR_H_ + +#include <stddef.h> + +#include <limits> +#include <memory> + +#include "base/logging.h" + +// Generic allocator class for STL objects. +// deallocate() to use the template class Alloc's allocation. +// that uses a given type-less allocator Alloc, which must provide: +// static void* Alloc::Allocate(size_t size); +// static void Alloc::Free(void* ptr, size_t size); +// +// Inherits from the default allocator, std::allocator. Overrides allocate() and +// deallocate() and some other functions. +// +// STLAllocator<T, MyAlloc> provides the same thread-safety guarantees as +// MyAlloc. +// +// Usage example: +// set<T, less<T>, STLAllocator<T, MyAlloc> > my_set; + +template <typename T, class Alloc> +class STLAllocator : public std::allocator<T> { + public: + typedef size_t size_type; + typedef T* pointer; + + template <class T1> + struct rebind { + typedef STLAllocator<T1, Alloc> other; + }; + + STLAllocator() {} + explicit STLAllocator(const STLAllocator&) {} + template <class T1> + STLAllocator(const STLAllocator<T1, Alloc>&) {} + ~STLAllocator() {} + + pointer allocate(size_type n, const void* = 0) { + // Make sure the computation of the total allocation size does not cause an + // integer overflow. + RAW_CHECK(n < max_size()); + return static_cast<T*>(Alloc::Allocate(n * sizeof(T))); + } + + void deallocate(pointer p, size_type n) { Alloc::Free(p, n * sizeof(T)); } + + size_type max_size() const { + return std::numeric_limits<size_t>::max() / sizeof(T); + } +}; + +#endif // COMPONENTS_METRICS_LEAK_DETECTOR_STL_ALLOCATOR_H_
diff --git a/components/mus/BUILD.gn b/components/mus/BUILD.gn index e89df7e..bb2ebe5 100644 --- a/components/mus/BUILD.gn +++ b/components/mus/BUILD.gn
@@ -18,11 +18,11 @@ deps = [ ":lib", - "public/interfaces", "//mojo/application/public/cpp:sources", "//mojo/public/cpp/bindings", "//mojo/services/tracing/public/interfaces", "//mojo/shell", + "public/interfaces", ] } } else {
diff --git a/components/mus/example/window_type_launcher/BUILD.gn b/components/mus/example/window_type_launcher/BUILD.gn index b3086c1..2602af1 100644 --- a/components/mus/example/window_type_launcher/BUILD.gn +++ b/components/mus/example/window_type_launcher/BUILD.gn
@@ -28,8 +28,8 @@ "//mojo/converters/geometry", "//mojo/message_pump", "//mojo/public/cpp/bindings", - "//mojo/runner/child:lib", "//mojo/runner:init", + "//mojo/runner/child:lib", "//skia", "//third_party/mojo/src/mojo/edk/system", "//ui/aura",
diff --git a/components/mus/gles2/BUILD.gn b/components/mus/gles2/BUILD.gn index 39271d3..60bde747 100644 --- a/components/mus/gles2/BUILD.gn +++ b/components/mus/gles2/BUILD.gn
@@ -19,6 +19,8 @@ "command_buffer_local.cc", "command_buffer_local.h", "command_buffer_local_client.h", + "command_buffer_task_runner.cc", + "command_buffer_task_runner.h", "gpu_impl.cc", "gpu_impl.h", "gpu_memory_tracker.cc", @@ -39,10 +41,10 @@ "//gpu/config:config", "//mojo/converters/geometry", "//mojo/public/cpp/bindings", - "//ui/mojo/geometry:interfaces", "//ui/gfx", "//ui/gfx/geometry", "//ui/gl", + "//ui/mojo/geometry:interfaces", ] if (is_android) { @@ -72,8 +74,8 @@ "//base", "//cc", "//components/mus/public/interfaces", - "//gpu/command_buffer/common", "//gpu/command_buffer/client", + "//gpu/command_buffer/common", "//gpu/config:config", "//mojo/public/cpp/bindings", "//mojo/public/cpp/system",
diff --git a/components/mus/gles2/command_buffer_driver.cc b/components/mus/gles2/command_buffer_driver.cc index 2a7265a5..649216a4 100644 --- a/components/mus/gles2/command_buffer_driver.cc +++ b/components/mus/gles2/command_buffer_driver.cc
@@ -189,10 +189,6 @@ command_buffer_->DestroyTransferBuffer(id); } -void CommandBufferDriver::Echo(const mojo::Callback<void()>& callback) { - callback.Run(); -} - void CommandBufferDriver::CreateImage(int32_t id, mojo::ScopedHandle memory_handle, int32 type, @@ -272,6 +268,19 @@ image_manager->RemoveImage(id); } +bool CommandBufferDriver::IsScheduled() const { + return !scheduler_ || scheduler_->scheduled(); +} + +bool CommandBufferDriver::HasUnprocessedCommands() const { + if (command_buffer_) { + gpu::CommandBuffer::State state = command_buffer_->GetLastState(); + return command_buffer_->GetPutOffset() != state.get_offset && + !gpu::error::IsError(state.error); + } + return false; +} + void CommandBufferDriver::OnParseError() { gpu::CommandBuffer::State state = command_buffer_->GetLastState(); OnContextLost(state.context_lost_reason); @@ -330,6 +339,7 @@ void CommandBufferDriver::OnSyncPointRetired() { scheduler_->SetScheduled(true); + gpu_state_->command_buffer_task_runner()->OnScheduled(this); } void CommandBufferDriver::OnContextLost(uint32_t reason) {
diff --git a/components/mus/gles2/command_buffer_driver.h b/components/mus/gles2/command_buffer_driver.h index eccf13a..8703633 100644 --- a/components/mus/gles2/command_buffer_driver.h +++ b/components/mus/gles2/command_buffer_driver.h
@@ -61,7 +61,6 @@ mojo::ScopedSharedBufferHandle transfer_buffer, uint32_t size); void DestroyTransferBuffer(int32_t id); - void Echo(const mojo::Callback<void()>& callback); void CreateImage(int32_t id, mojo::ScopedHandle memory_handle, int32_t type, @@ -69,6 +68,8 @@ int32_t format, int32_t internal_format); void DestroyImage(int32_t id); + bool IsScheduled() const; + bool HasUnprocessedCommands() const; private: bool MakeCurrent();
diff --git a/components/mus/gles2/command_buffer_impl.cc b/components/mus/gles2/command_buffer_impl.cc index 9656199..941894318 100644 --- a/components/mus/gles2/command_buffer_impl.cc +++ b/components/mus/gles2/command_buffer_impl.cc
@@ -40,7 +40,6 @@ scoped_refptr<GpuState> gpu_state, scoped_ptr<CommandBufferDriver> driver) : gpu_state_(gpu_state), - driver_task_runner_(base::MessageLoop::current()->task_runner()), driver_(driver.Pass()), observer_(nullptr), weak_ptr_factory_(this) { @@ -52,6 +51,15 @@ weak_ptr_factory_.GetWeakPtr(), base::Passed(&request))); } +void CommandBufferImpl::DidLoseContext() { + OnConnectionError(); +} + +CommandBufferImpl::~CommandBufferImpl() { + if (observer_) + observer_->OnCommandBufferImplDestroyed(); +} + void CommandBufferImpl::Initialize( mus::mojom::CommandBufferSyncClientPtr sync_client, mus::mojom::CommandBufferSyncPointClientPtr sync_point_client, @@ -59,71 +67,81 @@ mojo::ScopedSharedBufferHandle shared_state, mojo::Array<int32_t> attribs) { sync_point_client_ = sync_point_client.Pass(); - driver_task_runner_->PostTask( - FROM_HERE, - base::Bind(&CommandBufferDriver::Initialize, - base::Unretained(driver_.get()), - base::Passed(sync_client.PassInterface()), - base::Passed(loss_observer.PassInterface()), + gpu_state_->command_buffer_task_runner()->PostTask( + driver_.get(), + base::Bind(&CommandBufferImpl::InitializeHelper, + base::Unretained(this), + base::Passed(&sync_client), + base::Passed(&loss_observer), base::Passed(&shared_state), base::Passed(&attribs))); } void CommandBufferImpl::SetGetBuffer(int32_t buffer) { - driver_task_runner_->PostTask( - FROM_HERE, base::Bind(&CommandBufferDriver::SetGetBuffer, - base::Unretained(driver_.get()), buffer)); + gpu_state_->command_buffer_task_runner()->PostTask( + driver_.get(), + base::Bind(&CommandBufferImpl::SetGetBufferHelper, + base::Unretained(this), buffer)); } void CommandBufferImpl::Flush(int32_t put_offset) { - driver_task_runner_->PostTask( - FROM_HERE, base::Bind(&CommandBufferDriver::Flush, - base::Unretained(driver_.get()), put_offset)); + gpu_state_->command_buffer_task_runner()->PostTask( + driver_.get(), + base::Bind(&CommandBufferImpl::FlushHelper, + base::Unretained(this), put_offset)); } void CommandBufferImpl::MakeProgress(int32_t last_get_offset) { - driver_task_runner_->PostTask( - FROM_HERE, base::Bind(&CommandBufferDriver::MakeProgress, - base::Unretained(driver_.get()), last_get_offset)); + gpu_state_->command_buffer_task_runner()->PostTask( + driver_.get(), + base::Bind(&CommandBufferImpl::MakeProgressHelper, + base::Unretained(this), last_get_offset)); } void CommandBufferImpl::RegisterTransferBuffer( int32_t id, mojo::ScopedSharedBufferHandle transfer_buffer, uint32_t size) { - driver_task_runner_->PostTask( - FROM_HERE, base::Bind(&CommandBufferDriver::RegisterTransferBuffer, - base::Unretained(driver_.get()), id, - base::Passed(&transfer_buffer), size)); + gpu_state_->command_buffer_task_runner()->PostTask( + driver_.get(), + base::Bind(&CommandBufferImpl::RegisterTransferBufferHelper, + base::Unretained(this), id, + base::Passed(&transfer_buffer), size)); } void CommandBufferImpl::DestroyTransferBuffer(int32_t id) { - driver_task_runner_->PostTask( - FROM_HERE, base::Bind(&CommandBufferDriver::DestroyTransferBuffer, - base::Unretained(driver_.get()), id)); + gpu_state_->command_buffer_task_runner()->PostTask( + driver_.get(), + base::Bind(&CommandBufferImpl::DestroyTransferBufferHelper, + base::Unretained(this), id)); } void CommandBufferImpl::InsertSyncPoint(bool retire) { uint32_t sync_point = gpu_state_->sync_point_manager()->GenerateSyncPoint(); sync_point_client_->DidInsertSyncPoint(sync_point); if (retire) { - driver_task_runner_->PostTask( - FROM_HERE, - base::Bind(&gpu::SyncPointManager::RetireSyncPoint, - base::Unretained(gpu_state_->sync_point_manager()), + gpu_state_->command_buffer_task_runner()->PostTask( + driver_.get(), + base::Bind(&CommandBufferImpl::RetireSyncPointHelper, + base::Unretained(this), sync_point)); } } void CommandBufferImpl::RetireSyncPoint(uint32_t sync_point) { - driver_task_runner_->PostTask( - FROM_HERE, base::Bind(&gpu::SyncPointManager::RetireSyncPoint, - base::Unretained(gpu_state_->sync_point_manager()), - sync_point)); + gpu_state_->command_buffer_task_runner()->PostTask( + driver_.get(), + base::Bind(&CommandBufferImpl::RetireSyncPointHelper, + base::Unretained(this), + sync_point)); } void CommandBufferImpl::Echo(const mojo::Callback<void()>& callback) { - driver_task_runner_->PostTaskAndReply(FROM_HERE, base::Bind(&base::DoNothing), - base::Bind(&RunCallback, callback)); + gpu_state_->command_buffer_task_runner()->PostTask( + driver_.get(), + base::Bind(&CommandBufferImpl::EchoHelper, base::Unretained(this), + FROM_HERE, + gpu_state_->control_task_runner(), + base::Bind(&RunCallback, callback))); } void CommandBufferImpl::CreateImage(int32_t id, @@ -132,22 +150,19 @@ mojo::SizePtr size, int32_t format, int32_t internal_format) { - driver_task_runner_->PostTask( - FROM_HERE, base::Bind(&CommandBufferDriver::CreateImage, - base::Unretained(driver_.get()), id, - base::Passed(&memory_handle), type, - base::Passed(&size), format, internal_format)); + gpu_state_->command_buffer_task_runner()->PostTask( + driver_.get(), + base::Bind(&CommandBufferImpl::CreateImageHelper, + base::Unretained(this), id, + base::Passed(&memory_handle), type, + base::Passed(&size), format, internal_format)); } void CommandBufferImpl::DestroyImage(int32_t id) { - driver_task_runner_->PostTask( - FROM_HERE, base::Bind(&CommandBufferDriver::DestroyImage, - base::Unretained(driver_.get()), id)); -} - -CommandBufferImpl::~CommandBufferImpl() { - if (observer_) - observer_->OnCommandBufferImplDestroyed(); + gpu_state_->command_buffer_task_runner()->PostTask( + driver_.get(), + base::Bind(&CommandBufferImpl::DestroyImageHelper, + base::Unretained(this), id)); } void CommandBufferImpl::BindToRequest( @@ -157,6 +172,88 @@ binding_->set_connection_error_handler([this]() { OnConnectionError(); }); } +bool CommandBufferImpl::InitializeHelper( + mojom::CommandBufferSyncClientPtr sync_client, + mojom::CommandBufferLostContextObserverPtr loss_observer, + mojo::ScopedSharedBufferHandle shared_state, + mojo::Array<int32_t> attribs) { + DCHECK(driver_->IsScheduled()); + driver_->Initialize(sync_client.PassInterface(), + loss_observer.PassInterface(), + shared_state.Pass(), + attribs.Pass()); + return true; +} + +bool CommandBufferImpl::SetGetBufferHelper(int32_t buffer) { + DCHECK(driver_->IsScheduled()); + driver_->SetGetBuffer(buffer); + return true; +} + +bool CommandBufferImpl::FlushHelper(int32_t put_offset) { + DCHECK(driver_->IsScheduled()); + driver_->Flush(put_offset); + + // Return false if the Flush is not finished, so the CommandBufferTaskRunner + // will not remove this task from the task queue. + return !driver_->HasUnprocessedCommands(); +} + +bool CommandBufferImpl::MakeProgressHelper(int32_t last_get_offset) { + DCHECK(driver_->IsScheduled()); + driver_->MakeProgress(last_get_offset); + return true; +} + +bool CommandBufferImpl::RegisterTransferBufferHelper( + int32_t id, + mojo::ScopedSharedBufferHandle transfer_buffer, + uint32_t size) { + DCHECK(driver_->IsScheduled()); + driver_->RegisterTransferBuffer(id, transfer_buffer.Pass(), size); + return true; +} + +bool CommandBufferImpl::DestroyTransferBufferHelper(int32_t id) { + DCHECK(driver_->IsScheduled()); + driver_->DestroyTransferBuffer(id); + return true; +} + +bool CommandBufferImpl::RetireSyncPointHelper(uint32_t sync_point) { + DCHECK(driver_->IsScheduled()); + gpu_state_->sync_point_manager()->RetireSyncPoint(sync_point); + return true; +} + +bool CommandBufferImpl::EchoHelper( + const tracked_objects::Location& from_here, + scoped_refptr<base::SingleThreadTaskRunner> origin_task_runner, + const base::Closure& reply) { + origin_task_runner->PostTask(from_here, reply); + return true; +} + +bool CommandBufferImpl::CreateImageHelper( + int32_t id, + mojo::ScopedHandle memory_handle, + int32_t type, + mojo::SizePtr size, + int32_t format, + int32_t internal_format) { + DCHECK(driver_->IsScheduled()); + driver_->CreateImage(id, memory_handle.Pass(), type, size.Pass(), format, + internal_format); + return true; +} + +bool CommandBufferImpl::DestroyImageHelper(int32_t id) { + DCHECK(driver_->IsScheduled()); + driver_->DestroyImage(id); + return true; +} + void CommandBufferImpl::OnConnectionError() { // OnConnectionError() is called on the control thread |control_task_runner|. // sync_point_client_ is assigned and accessed on the control thread and so it @@ -170,11 +267,14 @@ // Objects we own (such as CommandBufferDriver) need to be destroyed on the // thread we were created on. - driver_task_runner_->DeleteSoon(FROM_HERE, this); + gpu_state_->command_buffer_task_runner()->PostTask( + driver_.get(), + base::Bind(&CommandBufferImpl::DeleteHelper, base::Unretained(this))); } -void CommandBufferImpl::DidLoseContext() { - OnConnectionError(); +bool CommandBufferImpl::DeleteHelper() { + delete this; + return true; } } // namespace mus
diff --git a/components/mus/gles2/command_buffer_impl.h b/components/mus/gles2/command_buffer_impl.h index cdf54e2a..aa237da4 100644 --- a/components/mus/gles2/command_buffer_impl.h +++ b/components/mus/gles2/command_buffer_impl.h
@@ -26,6 +26,15 @@ CommandBufferImpl(mojo::InterfaceRequest<CommandBuffer> request, scoped_refptr<GpuState> gpu_state, scoped_ptr<CommandBufferDriver> driver); + void DidLoseContext(); + + void set_observer(CommandBufferImplObserver* observer) { + observer_ = observer; + } + + private: + class CommandBufferDriverClientImpl; + ~CommandBufferImpl() override; // mojom::CommandBuffer: void Initialize(mojom::CommandBufferSyncClientPtr sync_client, @@ -51,25 +60,39 @@ int32_t internal_format) override; void DestroyImage(int32_t id) override; - void DidLoseContext(); - - void set_observer(CommandBufferImplObserver* observer) { - observer_ = observer; - } - - private: - class CommandBufferDriverClientImpl; - - friend class base::DeleteHelper<CommandBufferImpl>; - - ~CommandBufferImpl() override; + bool InitializeHelper( + mojom::CommandBufferSyncClientPtr sync_client, + mojom::CommandBufferLostContextObserverPtr loss_observer, + mojo::ScopedSharedBufferHandle shared_state, + mojo::Array<int32_t> attribs); + bool SetGetBufferHelper(int32_t buffer); + bool FlushHelper(int32_t put_offset); + bool MakeProgressHelper(int32_t last_get_offset); + bool RegisterTransferBufferHelper( + int32_t id, + mojo::ScopedSharedBufferHandle transfer_buffer, + uint32_t size); + bool DestroyTransferBufferHelper(int32_t id); + bool RetireSyncPointHelper(uint32_t sync_point); + bool EchoHelper( + const tracked_objects::Location& from_here, + scoped_refptr<base::SingleThreadTaskRunner> origin_task_runner, + const base::Closure& reply); + bool CreateImageHelper( + int32_t id, + mojo::ScopedHandle memory_handle, + int32_t type, + mojo::SizePtr size, + int32_t format, + int32_t internal_format); + bool DestroyImageHelper(int32_t id); void BindToRequest(mojo::InterfaceRequest<CommandBuffer> request); void OnConnectionError(); + bool DeleteHelper(); scoped_refptr<GpuState> gpu_state_; - scoped_refptr<base::SingleThreadTaskRunner> driver_task_runner_; scoped_ptr<CommandBufferDriver> driver_; mojom::CommandBufferSyncPointClientPtr sync_point_client_; scoped_ptr<mojo::Binding<CommandBuffer>> binding_;
diff --git a/components/mus/gles2/command_buffer_local.cc b/components/mus/gles2/command_buffer_local.cc index 9018c56e..abdaa48 100644 --- a/components/mus/gles2/command_buffer_local.cc +++ b/components/mus/gles2/command_buffer_local.cc
@@ -189,7 +189,9 @@ } void CommandBufferLocal::SignalSyncPoint(uint32_t sync_point, - const base::Closure& callback) {} + const base::Closure& callback) { + gpu_state_->sync_point_manager()->AddSyncPointCallback(sync_point, callback); +} void CommandBufferLocal::SignalQuery(uint32_t query, const base::Closure& callback) { @@ -269,13 +271,21 @@ bool CommandBufferLocal::OnWaitSyncPoint(uint32_t sync_point) { if (!sync_point) return true; - if (gpu_state_->sync_point_manager()->IsSyncPointRetired(sync_point)) - return true; - scheduler_->SetScheduled(false); - gpu_state_->sync_point_manager()->AddSyncPointCallback( - sync_point, base::Bind(&CommandBufferLocal::OnSyncPointRetired, - weak_factory_.GetWeakPtr())); - return scheduler_->scheduled(); + + bool context_changed = false; + while (!gpu_state_->sync_point_manager()->IsSyncPointRetired(sync_point)) { + gpu_state_->command_buffer_task_runner()->RunOneTask(); + context_changed = true; + } + + // RunOneTask() changes the current GL context, so we have to recover it. + if (context_changed) { + if (!decoder_->MakeCurrent()) { + command_buffer_->SetContextLostReason(decoder_->GetContextLostReason()); + command_buffer_->SetParseError(::gpu::error::kLostContext); + } + } + return true; } void CommandBufferLocal::OnFenceSyncRelease(uint64_t release) { @@ -327,8 +337,4 @@ client_->DidLoseContext(); } -void CommandBufferLocal::OnSyncPointRetired() { - scheduler_->SetScheduled(true); -} - } // namespace mus
diff --git a/components/mus/gles2/command_buffer_local.h b/components/mus/gles2/command_buffer_local.h index c9c0dd9..625bbd6 100644 --- a/components/mus/gles2/command_buffer_local.h +++ b/components/mus/gles2/command_buffer_local.h
@@ -92,7 +92,6 @@ uint64_t release); void OnParseError(); void OnContextLost(uint32_t reason); - void OnSyncPointRetired(); gfx::AcceleratedWidget widget_; scoped_refptr<GpuState> gpu_state_;
diff --git a/components/mus/gles2/command_buffer_task_runner.cc b/components/mus/gles2/command_buffer_task_runner.cc new file mode 100644 index 0000000..224dbccc --- /dev/null +++ b/components/mus/gles2/command_buffer_task_runner.cc
@@ -0,0 +1,108 @@ +// Copyright 2014 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 "components/mus/gles2/command_buffer_task_runner.h" + +#include "base/bind.h" +#include "base/thread_task_runner_handle.h" +#include "components/mus/gles2/command_buffer_driver.h" + +namespace mus { + +CommandBufferTaskRunner::CommandBufferTaskRunner() + : driver_task_runner_(base::ThreadTaskRunnerHandle::Get()), + need_post_task_(true), + cond_(&lock_) { +} + +bool CommandBufferTaskRunner::PostTask( + const CommandBufferDriver* driver, + const TaskCallback& task) { + base::AutoLock locker(lock_); + driver_map_[driver].push_back(task); + if (driver->IsScheduled()) { + ScheduleTaskIfNecessaryLocked(); + // A new task has been submitted, and we need singal the main thread. + // If the main thread is waiting for it, it will resume executing tasks. + cond_.Signal(); + } + return true; +} + +void CommandBufferTaskRunner::RunOneTask() { + DCHECK(thread_checker_.CalledOnValidThread()); + base::AutoLock locker(lock_); + const bool block = true; + bool result = RunOneTaskInternalLocked(block); + DCHECK(result); +} + +void CommandBufferTaskRunner::OnScheduled(const CommandBufferDriver* driver) { + base::AutoLock locker(lock_); + if (driver_map_.find(driver) != driver_map_.end()) { + ScheduleTaskIfNecessaryLocked(); + // Some task submitted from this |driver| become executable, and we need + // singal the main thread. If the main thread is waiting for it, it will + // resume executing tasks. + cond_.Signal(); + } +} + +CommandBufferTaskRunner::~CommandBufferTaskRunner() {} + +bool CommandBufferTaskRunner::RunOneTaskInternalLocked(bool block) { + DCHECK(thread_checker_.CalledOnValidThread()); + lock_.AssertAcquired(); + do { + for (auto it = driver_map_.begin(); it != driver_map_.end(); ++it) { + if (!it->first->IsScheduled()) + continue; + TaskQueue& task_queue = it->second; + DCHECK(!task_queue.empty()); + const TaskCallback& callback = task_queue.front(); + bool complete = false; + { + base::AutoUnlock unlocker(lock_); + complete = callback.Run(); + } + if (complete) { + // Only remove the task if it is complete. + task_queue.pop_front(); + if (task_queue.empty()) + driver_map_.erase(it); + } + return true; + } + // If we cannot find any executable task and block is true, we have to wait + // until other threads submit a new task or some tasks become executable. + if (block) + cond_.Wait(); + } while (block); + + return false; +} + +void CommandBufferTaskRunner::ScheduleTaskIfNecessaryLocked() { + lock_.AssertAcquired(); + if (!need_post_task_) + return; + driver_task_runner_->PostTask( + FROM_HERE, + base::Bind(&CommandBufferTaskRunner::RunCommandBufferTask, this)); + need_post_task_ = false; +} + +void CommandBufferTaskRunner::RunCommandBufferTask() { + DCHECK(thread_checker_.CalledOnValidThread()); + base::AutoLock locker(lock_); + + // Try executing all tasks in |driver_map_| until |RunOneTaskInternalLock()| + // returns false (Returning false means |driver_map_| is empty or all tasks + // in it aren't executable currently). + const bool block = false; + while (RunOneTaskInternalLocked(block)); + need_post_task_ = true; +} + +} // namespace mus
diff --git a/components/mus/gles2/command_buffer_task_runner.h b/components/mus/gles2/command_buffer_task_runner.h new file mode 100644 index 0000000..26bb334 --- /dev/null +++ b/components/mus/gles2/command_buffer_task_runner.h
@@ -0,0 +1,88 @@ +// Copyright 2014 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 COMPONENTS_MUS_GLES2_COMMAND_BUFFER_TASK_RUNNER_H_ +#define COMPONENTS_MUS_GLES2_COMMAND_BUFFER_TASK_RUNNER_H_ + +#include <deque> +#include <map> + +#include "base/callback.h" +#include "base/macros.h" +#include "base/memory/ref_counted.h" +#include "base/memory/scoped_ptr.h" +#include "base/single_thread_task_runner.h" +#include "base/synchronization/condition_variable.h" +#include "base/synchronization/lock.h" +#include "base/threading/thread_checker.h" + +namespace mus { + +class CommandBufferDriver; + +// This class maintains tasks submitted by |CommandBufferImpl|. Those tasks will +// be executed on the main thread. But if the main thread is blocked in +// |CommandBufferLocal::OnWaitFenceSync()| by waiting a sync point, the +// |CommandBufferTaskRunner::RunOneTask()| could be used for executing a task +// from other command buffers which may retire the sync point. +class CommandBufferTaskRunner + : public base::RefCountedThreadSafe<CommandBufferTaskRunner> { + public: + CommandBufferTaskRunner(); + + // TaskCallback returns true if the task is completed and should be removed + // from the task queue, otherwise returns false. + typedef base::Callback<bool(void)> TaskCallback; + bool PostTask(const CommandBufferDriver* driver, + const TaskCallback& task); + + // Run one task in the |driver_map_|. This method could be blocked, if there + // isn't any task which is executable. + // Note: this method must be called on the main thread which is the owner of + // |driver_task_runner_|. + void RunOneTask(); + + // Called by CommandBufferDriver when a driver becomes scheduled. + void OnScheduled(const CommandBufferDriver* driver); + + private: + friend class base::RefCountedThreadSafe<CommandBufferTaskRunner>; + + ~CommandBufferTaskRunner(); + + // Run one command buffer task from a scheduled command buffer. + // When there isn't any command buffer task, and if the |block| is false, + // this function will return false immediately, otherwise, this function + // will be blocked until a task is available for executing. + bool RunOneTaskInternalLocked(bool block); + + // Post a task to the main thread to execute tasks in |driver_map_|, if it is + // necessary. + void ScheduleTaskIfNecessaryLocked(); + + // The callback function for executing tasks in |driver_map_|. + void RunCommandBufferTask(); + + base::ThreadChecker thread_checker_; + scoped_refptr<base::SingleThreadTaskRunner> driver_task_runner_; + + typedef std::deque<TaskCallback> TaskQueue; + typedef std::map<const CommandBufferDriver*, TaskQueue> DriverMap; + DriverMap driver_map_; + bool need_post_task_; + + // The access lock for |driver_map_| and |need_post_task_|. + base::Lock lock_; + + // The condition variable is for signalling the blocked + // |RunOneTaskInternalLocked()| that new tasks are submitted into the + // |driver_map_| or some existing tasks in |driver_map_| become executable. + base::ConditionVariable cond_; + + DISALLOW_COPY_AND_ASSIGN(CommandBufferTaskRunner); +}; + +} // namespace mus + +#endif // COMPONENTS_MUS_GLES2_COMMAND_BUFFER_TASK_RUNNER_H_
diff --git a/components/mus/gles2/gpu_state.cc b/components/mus/gles2/gpu_state.cc index 137c1165..34481691 100644 --- a/components/mus/gles2/gpu_state.cc +++ b/components/mus/gles2/gpu_state.cc
@@ -13,6 +13,7 @@ GpuState::GpuState(bool hardware_rendering_available) : control_thread_("gpu_command_buffer_control"), + command_buffer_task_runner_(new CommandBufferTaskRunner), sync_point_manager_(new gpu::SyncPointManager(true)), share_group_(new gfx::GLShareGroup), mailbox_manager_(new gpu::gles2::MailboxManagerImpl),
diff --git a/components/mus/gles2/gpu_state.h b/components/mus/gles2/gpu_state.h index ea196681..7b39295 100644 --- a/components/mus/gles2/gpu_state.h +++ b/components/mus/gles2/gpu_state.h
@@ -9,6 +9,7 @@ #include "base/memory/scoped_ptr.h" #include "base/single_thread_task_runner.h" #include "base/threading/thread.h" +#include "components/mus/gles2/command_buffer_task_runner.h" #include "gpu/command_buffer/service/mailbox_manager_impl.h" #include "gpu/command_buffer/service/sync_point_manager.h" #include "gpu/config/gpu_info.h" @@ -31,6 +32,10 @@ void StopControlThread(); + CommandBufferTaskRunner* command_buffer_task_runner() const { + return command_buffer_task_runner_.get(); + } + // These objects are intended to be used on the "driver" thread (i.e., the // thread on which GpuImpl instances are created). gfx::GLShareGroup* share_group() const { return share_group_.get(); } @@ -54,6 +59,7 @@ ~GpuState(); base::Thread control_thread_; + scoped_refptr<CommandBufferTaskRunner> command_buffer_task_runner_; scoped_ptr<gpu::SyncPointManager> sync_point_manager_; scoped_refptr<gfx::GLShareGroup> share_group_; scoped_refptr<gpu::gles2::MailboxManager> mailbox_manager_;
diff --git a/components/mus/public/cpp/lib/window_tree_host_factory.cc b/components/mus/public/cpp/lib/window_tree_host_factory.cc index 80de37ff..76a2cac 100644 --- a/components/mus/public/cpp/lib/window_tree_host_factory.cc +++ b/components/mus/public/cpp/lib/window_tree_host_factory.cc
@@ -32,9 +32,7 @@ mojom::WindowManagerPtr window_manager, WindowManagerDelegate* window_manager_delegate) { mojom::WindowTreeHostFactoryPtr factory; - mojo::URLRequestPtr request(mojo::URLRequest::New()); - request->url = "mojo:mus"; - app->ConnectToService(request.Pass(), &factory); + app->ConnectToService("mojo:mus", &factory); CreateWindowTreeHost(factory.get(), mojom::WindowTreeHostClientPtr(), delegate, host, window_manager.Pass(), window_manager_delegate);
diff --git a/components/mus/public/interfaces/BUILD.gn b/components/mus/public/interfaces/BUILD.gn index 02ef8b5..899401a 100644 --- a/components/mus/public/interfaces/BUILD.gn +++ b/components/mus/public/interfaces/BUILD.gn
@@ -29,7 +29,7 @@ ] deps = [ - "//ui/mojo/ime:interfaces", "//ui/mojo/geometry:interfaces", + "//ui/mojo/ime:interfaces", ] }
diff --git a/components/mus/ws/BUILD.gn b/components/mus/ws/BUILD.gn index e7f9223..63fb2e8 100644 --- a/components/mus/ws/BUILD.gn +++ b/components/mus/ws/BUILD.gn
@@ -127,14 +127,14 @@ ] deps = [ - ":test_support", ":lib", + ":test_support", "//base", "//base/test:test_config", "//components/mus/common", - "//components/mus/surfaces", "//components/mus/public/cpp", "//components/mus/public/interfaces", + "//components/mus/surfaces", "//mojo/application/public/interfaces", "//mojo/converters/geometry", "//mojo/converters/input_events", @@ -143,13 +143,13 @@ "//mojo/gles2", "//mojo/platform_handle", "//mojo/public/cpp/bindings:bindings", - "//third_party/mojo/src/mojo/edk/test:run_all_unittests", - "//ui/mojo/geometry:interfaces", "//testing/gtest", + "//third_party/mojo/src/mojo/edk/test:run_all_unittests", "//ui/events", "//ui/gfx", "//ui/gfx:test_support", "//ui/gfx/geometry", + "//ui/mojo/geometry:interfaces", ] if (!is_android) { # TODO(GYP) Enable on Android when osmesa links.
diff --git a/components/mus/ws/ids.h b/components/mus/ws/ids.h index 3c814d0..8ae41c9ce 100644 --- a/components/mus/ws/ids.h +++ b/components/mus/ws/ids.h
@@ -5,6 +5,8 @@ #ifndef COMPONENTS_MUS_WS_IDS_H_ #define COMPONENTS_MUS_WS_IDS_H_ +#include <tuple> + #include "components/mus/common/types.h" #include "components/mus/common/util.h" @@ -29,10 +31,8 @@ bool operator!=(const WindowId& other) const { return !(*this == other); } bool operator<(const WindowId& other) const { - if (connection_id == other.connection_id) - return window_id < other.window_id; - - return connection_id < other.connection_id; + return std::tie(connection_id, window_id) < + std::tie(other.connection_id, other.window_id); } ConnectionSpecificId connection_id;
diff --git a/components/mus/ws/window_manager_client_apptest.cc b/components/mus/ws/window_manager_client_apptest.cc index e38b7634..7da2287d 100644 --- a/components/mus/ws/window_manager_client_apptest.cc +++ b/components/mus/ws/window_manager_client_apptest.cc
@@ -228,12 +228,8 @@ // WindowTreeClient. mus::mojom::WindowTreeClientPtr ConnectToApplicationAndGetWindowServerClient() { - mojo::URLRequestPtr request(mojo::URLRequest::New()); - request->url = mojo::String::From(application_impl()->url()); - scoped_ptr<mojo::ApplicationConnection> connection = - application_impl()->ConnectToApplication(request.Pass()); mus::mojom::WindowTreeClientPtr client; - connection->ConnectToService(&client); + application_impl()->ConnectToService(application_impl()->url(), &client); return client.Pass(); }
diff --git a/components/mus/ws/window_tree_apptest.cc b/components/mus/ws/window_tree_apptest.cc index 9f063d0..77755c7 100644 --- a/components/mus/ws/window_tree_apptest.cc +++ b/components/mus/ws/window_tree_apptest.cc
@@ -75,12 +75,8 @@ bool result = false; base::RunLoop run_loop; { - mojo::URLRequestPtr request(mojo::URLRequest::New()); - request->url = mojo::String::From(url); - scoped_ptr<ApplicationConnection> connection = - app->ConnectToApplication(request.Pass()); mojom::WindowTreeClientPtr client; - connection->ConnectToService(&client); + app->ConnectToService(url.get(), &client); ws->Embed(root_id, client.Pass(), mojom::WindowTree::ACCESS_POLICY_DEFAULT, base::Bind(&EmbedCallbackImpl, &run_loop, &result)); } @@ -540,11 +536,9 @@ void SetUp() override { ApplicationTestBase::SetUp(); client_factory_.reset(new WindowTreeClientFactory(application_impl())); - mojo::URLRequestPtr request(mojo::URLRequest::New()); - request->url = mojo::String::From("mojo:mus"); mojom::WindowTreeHostFactoryPtr factory; - application_impl()->ConnectToService(request.Pass(), &factory); + application_impl()->ConnectToService("mojo:mus", &factory); mojom::WindowTreeClientPtr tree_client_ptr; ws_client1_.reset(new TestWindowTreeClientImpl(application_impl()));
diff --git a/components/nacl/BUILD.gn b/components/nacl/BUILD.gn index 35c892e..7658660 100644 --- a/components/nacl/BUILD.gn +++ b/components/nacl/BUILD.gn
@@ -144,7 +144,6 @@ deps = [ ":nacl_common", ":nacl_switches", - "renderer/plugin:nacl_trusted_plugin", "//base", "//content/public/common", "//content/public/renderer", @@ -154,6 +153,7 @@ "//ppapi/proxy:ipc", "//ppapi/shared_impl", "//third_party/WebKit/public:blink", + "renderer/plugin:nacl_trusted_plugin", ] } @@ -259,8 +259,8 @@ "loader/nonsfi/nonsfi_main.h", ] deps = [ - ":nacl_switches", ":nacl_helper_nonsfi_sandbox", + ":nacl_switches", "//base", "//components/tracing", "//content",
diff --git a/components/net_log/BUILD.gn b/components/net_log/BUILD.gn index b2af91e..8bdc161 100644 --- a/components/net_log/BUILD.gn +++ b/components/net_log/BUILD.gn
@@ -26,9 +26,9 @@ "net_log_temp_file_unittest.cc", ] deps = [ + ":net_log", "//base", "//net", "//testing/gtest", - ":net_log", ] }
diff --git a/components/offline_pages/offline_page_model.cc b/components/offline_pages/offline_page_model.cc index 7b0922e..26de7168 100644 --- a/components/offline_pages/offline_page_model.cc +++ b/components/offline_pages/offline_page_model.cc
@@ -472,6 +472,16 @@ MarkPageForDeletion(node->id(), base::Bind(&EmptyDeleteCallback)); } +void OfflinePageModel::BookmarkNodeChanged( + bookmarks::BookmarkModel* model, + const bookmarks::BookmarkNode* node) { + // BookmarkNodeChanged could be triggered if title or URL gets changed. If + // the latter, we need to invalidate the offline copy. + DCHECK(offline_pages_.count(node->id()) > 0); + if (offline_pages_[node->id()].url != node->url()) + DeletePageByBookmarkId(node->id(), DeletePageCallback()); +} + void OfflinePageModel::OnEnsureArchivesDirCreatedDone() { store_->Load(base::Bind(&OfflinePageModel::OnLoadDone, weak_ptr_factory_.GetWeakPtr())); @@ -569,6 +579,12 @@ "OfflinePages.DeletePage.PageSize", iter->second.file_size / 1024); UMA_HISTOGRAM_COUNTS( "OfflinePages.DeletePage.AccessCount", iter->second.access_count); + // If the page is not marked for deletion at this point, the model has not + // yet informed the observer that the offline page is deleted. + if (!iter->second.IsMarkedForDeletion()) { + FOR_EACH_OBSERVER(Observer, observers_, + OfflinePageDeleted(iter->second.bookmark_id)); + } offline_pages_.erase(iter); } if (bookmark_ids.size() > 1) {
diff --git a/components/offline_pages/offline_page_model.h b/components/offline_pages/offline_page_model.h index 628de2a..c6e93f2e 100644 --- a/components/offline_pages/offline_page_model.h +++ b/components/offline_pages/offline_page_model.h
@@ -214,6 +214,8 @@ int old_index, const bookmarks::BookmarkNode* node, const std::set<GURL>& removed_urls) override; + void BookmarkNodeChanged(bookmarks::BookmarkModel* model, + const bookmarks::BookmarkNode* node) override; // Callback for ensuring archive directory is created. void OnEnsureArchivesDirCreatedDone();
diff --git a/components/offline_pages/offline_page_model_unittest.cc b/components/offline_pages/offline_page_model_unittest.cc index 2da4fd0..b6b6a8a 100644 --- a/components/offline_pages/offline_page_model_unittest.cc +++ b/components/offline_pages/offline_page_model_unittest.cc
@@ -671,6 +671,7 @@ PumpLoop(); + EXPECT_EQ(last_deleted_bookmark_id(), kTestPageBookmarkId1); EXPECT_EQ(DeletePageResult::SUCCESS, last_delete_result()); ASSERT_EQ(1u, store->offline_pages().size()); EXPECT_EQ(kTestUrl2, store->offline_pages()[0].url); @@ -684,6 +685,7 @@ PumpLoop(); + EXPECT_EQ(last_deleted_bookmark_id(), kTestPageBookmarkId2); EXPECT_EQ(DeletePageResult::SUCCESS, last_delete_result()); EXPECT_EQ(0u, store->offline_pages().size()); }
diff --git a/components/omnibox/browser/BUILD.gn b/components/omnibox/browser/BUILD.gn index b1984fd3..e9e926d 100644 --- a/components/omnibox/browser/BUILD.gn +++ b/components/omnibox/browser/BUILD.gn
@@ -107,6 +107,7 @@ "//components/metrics/proto", ] deps = [ + ":in_memory_url_index_cache_proto", "//base", "//base:i18n", "//base:prefs", @@ -135,7 +136,6 @@ "//ui/base", "//ui/gfx", "//url", - ":in_memory_url_index_cache_proto", ] } @@ -192,6 +192,8 @@ ] deps = [ + ":browser", + ":test_support", "//base", "//components/open_from_clipboard:test_support", "//components/search", @@ -200,7 +202,5 @@ "//testing/gmock", "//testing/gtest", "//url", - ":browser", - ":test_support", ] }
diff --git a/components/ownership/BUILD.gn b/components/ownership/BUILD.gn index eb65f21..f655565 100644 --- a/components/ownership/BUILD.gn +++ b/components/ownership/BUILD.gn
@@ -23,8 +23,8 @@ deps = [ "//base", "//components/keyed_service/core", - "//components/policy/proto", "//components/policy:policy_component_common", + "//components/policy/proto", "//crypto", ]
diff --git a/components/ownership/owner_key_util.h b/components/ownership/owner_key_util.h index ae083cf..8cedd88 100644 --- a/components/ownership/owner_key_util.h +++ b/components/ownership/owner_key_util.h
@@ -12,7 +12,6 @@ #include "base/macros.h" #include "base/memory/ref_counted.h" #include "base/memory/scoped_ptr.h" -#include "base/stl_util.h" #include "components/ownership/ownership_export.h" #include "crypto/scoped_nss_types.h" @@ -34,7 +33,7 @@ bool is_loaded() const { return !data_.empty(); } std::string as_string() { - return std::string(reinterpret_cast<const char*>(vector_as_array(&data_)), + return std::string(reinterpret_cast<const char*>(data_.data()), data_.size()); }
diff --git a/components/ownership/owner_key_util_impl.cc b/components/ownership/owner_key_util_impl.cc index fdf29e9..15efd1f 100644 --- a/components/ownership/owner_key_util_impl.cc +++ b/components/ownership/owner_key_util_impl.cc
@@ -47,8 +47,7 @@ // Get the key data off of disk int data_read = - base::ReadFile(public_key_file_, - reinterpret_cast<char*>(vector_as_array(output)), + base::ReadFile(public_key_file_, reinterpret_cast<char*>(output->data()), safe_file_size); return data_read == safe_file_size; }
diff --git a/components/ownership/owner_key_util_impl_unittest.cc b/components/ownership/owner_key_util_impl_unittest.cc index d79b3b23..43205c4 100644 --- a/components/ownership/owner_key_util_impl_unittest.cc +++ b/components/ownership/owner_key_util_impl_unittest.cc
@@ -12,7 +12,6 @@ #include "base/files/file_util.h" #include "base/files/scoped_temp_dir.h" #include "base/memory/ref_counted.h" -#include "base/stl_util.h" #include "testing/gtest/include/gtest/gtest.h" namespace ownership { @@ -70,10 +69,9 @@ std::vector<uint8> public_key(kTestKeyData, kTestKeyData + sizeof(kTestKeyData)); ASSERT_EQ(static_cast<int>(public_key.size()), - base::WriteFile( - key_file_, - reinterpret_cast<const char*>(vector_as_array(&public_key)), - public_key.size())); + base::WriteFile(key_file_, + reinterpret_cast<const char*>(public_key.data()), + public_key.size())); EXPECT_TRUE(util_->IsPublicKeyPresent()); std::vector<uint8> from_disk;
diff --git a/components/pairing/BUILD.gn b/components/pairing/BUILD.gn index 12096c8..dfbe94e 100644 --- a/components/pairing/BUILD.gn +++ b/components/pairing/BUILD.gn
@@ -29,10 +29,10 @@ ] deps = [ + ":proto", "//base", "//device/bluetooth", "//net", - ":proto", ] }
diff --git a/components/password_manager/content/browser/credential_manager_dispatcher.cc b/components/password_manager/content/browser/credential_manager_dispatcher.cc index a736209..0105074e 100644 --- a/components/password_manager/content/browser/credential_manager_dispatcher.cc +++ b/components/password_manager/content/browser/credential_manager_dispatcher.cc
@@ -66,19 +66,30 @@ credential, web_contents()->GetLastCommittedURL().GetOrigin())); form->skip_zero_click = !IsZeroClickAllowed(); - // TODO(mkwst): This is a stub; we should be checking the PasswordStore to - // determine whether or not the credential exists, and calling UpdateLogin - // accordingly. form_manager_.reset(new CredentialManagerPasswordFormManager( client_, GetDriver(), *form, this)); } void CredentialManagerDispatcher::OnProvisionalSaveComplete() { DCHECK(form_manager_); - if (client_->IsSavingAndFillingEnabledForCurrentPage()) { + DCHECK(client_->IsSavingAndFillingEnabledForCurrentPage()); + + if (form_manager_->IsNewLogin()) { + // If the PasswordForm we were given does not match an existing + // PasswordForm, ask the user if they'd like to save. client_->PromptUserToSaveOrUpdatePassword( form_manager_.Pass(), CredentialSourceType::CREDENTIAL_SOURCE_API, false); + } else { + // Otherwise, update the existing form, as we've been told by the site + // that the new PasswordForm is a functioning credential for the user. + // We use 'PasswordFormManager::Update(PasswordForm&)' here rather than + // 'PasswordFormManager::UpdateLogin', as we need to port over the + // 'skip_zero_click' state to ensure that we don't accidentally start + // signing users in just because the site asks us to. The simplest way + // to do so is simply to update the password field of the existing + // credential. + form_manager_->Update(*form_manager_->preferred_match()); } }
diff --git a/components/password_manager/content/browser/credential_manager_dispatcher_unittest.cc b/components/password_manager/content/browser/credential_manager_dispatcher_unittest.cc index d9c3b98..224064c 100644 --- a/components/password_manager/content/browser/credential_manager_dispatcher_unittest.cc +++ b/components/password_manager/content/browser/credential_manager_dispatcher_unittest.cc
@@ -18,6 +18,7 @@ #include "components/password_manager/content/common/credential_manager_messages.h" #include "components/password_manager/core/browser/credential_manager_password_form_manager.h" #include "components/password_manager/core/browser/mock_affiliated_match_helper.h" +#include "components/password_manager/core/browser/password_manager.h" #include "components/password_manager/core/browser/stub_password_manager_client.h" #include "components/password_manager/core/browser/stub_password_manager_driver.h" #include "components/password_manager/core/browser/test_password_store.h" @@ -146,6 +147,19 @@ run_loop.Run(); } +class SlightlyLessStubbyPasswordManagerDriver + : public StubPasswordManagerDriver { + public: + explicit SlightlyLessStubbyPasswordManagerDriver( + PasswordManagerClient* client) + : password_manager_(client) {} + + PasswordManager* GetPasswordManager() override { return &password_manager_; } + + private: + PasswordManager password_manager_; +}; + } // namespace class CredentialManagerDispatcherTest @@ -156,9 +170,12 @@ void SetUp() override { content::RenderViewHostTestHarness::SetUp(); store_ = new TestPasswordStore; - client_.reset(new MockPasswordManagerClient(store_.get())); + client_.reset( + new testing::NiceMock<MockPasswordManagerClient>(store_.get())); + stub_driver_.reset( + new SlightlyLessStubbyPasswordManagerDriver(client_.get())); dispatcher_.reset(new TestCredentialManagerDispatcher( - web_contents(), client_.get(), &stub_driver_)); + web_contents(), client_.get(), stub_driver_.get())); ON_CALL(*client_, IsSavingAndFillingEnabledForCurrentPage()) .WillByDefault(testing::Return(true)); ON_CALL(*client_, IsOffTheRecord()).WillByDefault(testing::Return(false)); @@ -266,8 +283,8 @@ autofill::PasswordForm origin_path_form_; autofill::PasswordForm cross_origin_form_; scoped_refptr<TestPasswordStore> store_; - scoped_ptr<MockPasswordManagerClient> client_; - StubPasswordManagerDriver stub_driver_; + scoped_ptr<testing::NiceMock<MockPasswordManagerClient>> client_; + scoped_ptr<SlightlyLessStubbyPasswordManagerDriver> stub_driver_; scoped_ptr<CredentialManagerDispatcher> dispatcher_; }; @@ -301,6 +318,63 @@ EXPECT_EQ(autofill::PasswordForm::SCHEME_HTML, new_form.scheme); } +TEST_F(CredentialManagerDispatcherTest, CredentialManagerStoreOverwrite) { + // Populate the PasswordStore with a form. + store_->AddLogin(form_); + RunAllPendingTasks(); + + // Calling 'OnStore' with a credential that matches |form_| should update + // the password without prompting the user. + CredentialInfo info(form_, CredentialType::CREDENTIAL_TYPE_PASSWORD); + info.password = base::ASCIIToUTF16("Totally new password."); + dispatcher()->OnStore(kRequestId, info); + + EXPECT_CALL(*client_, PromptUserToSavePasswordPtr( + _, CredentialSourceType::CREDENTIAL_SOURCE_API)) + .Times(testing::Exactly(0)); + + const uint32 kMsgID = CredentialManagerMsg_AcknowledgeStore::ID; + const IPC::Message* message = + process()->sink().GetFirstMessageMatching(kMsgID); + EXPECT_TRUE(message); + process()->sink().ClearMessages(); + + // Allow the PasswordFormManager to talk to the password store, determine + // the form is a match for an existing form, and update the PasswordStore. + RunAllPendingTasks(); + + TestPasswordStore::PasswordMap passwords = store_->stored_passwords(); + EXPECT_EQ(1U, passwords.size()); + EXPECT_EQ(1U, passwords[form_.signon_realm].size()); + EXPECT_EQ(base::ASCIIToUTF16("Totally new password."), + passwords[form_.signon_realm][0].password_value); +} + +TEST_F(CredentialManagerDispatcherTest, + CredentialManagerStoreOverwriteZeroClick) { + // Set the global zero click flag on, and populate the PasswordStore with a + // form that's set to skip zero click. + client_->set_zero_click_enabled(true); + form_.skip_zero_click = true; + store_->AddLogin(form_); + RunAllPendingTasks(); + + // Calling 'OnStore' with a credential that matches |form_| should update + // the password without prompting the user. + CredentialInfo info(form_, CredentialType::CREDENTIAL_TYPE_PASSWORD); + info.password = base::ASCIIToUTF16("Totally new password."); + dispatcher()->OnStore(kRequestId, info); + process()->sink().ClearMessages(); + + // Allow the PasswordFormManager to talk to the password store, determine + // the form is a match for an existing form, and update the PasswordStore. + RunAllPendingTasks(); + + // Verify that the update didn't toggle the skip_zero_click flag off. + TestPasswordStore::PasswordMap passwords = store_->stored_passwords(); + EXPECT_TRUE(passwords[form_.signon_realm][0].skip_zero_click); +} + TEST_F(CredentialManagerDispatcherTest, CredentialManagerSignInWithSavingDisabledForCurrentPage) { CredentialInfo info(form_, CredentialType::CREDENTIAL_TYPE_PASSWORD);
diff --git a/components/password_manager/core/browser/credential_manager_password_form_manager.h b/components/password_manager/core/browser/credential_manager_password_form_manager.h index 846c2552..09ee7acd 100644 --- a/components/password_manager/core/browser/credential_manager_password_form_manager.h +++ b/components/password_manager/core/browser/credential_manager_password_form_manager.h
@@ -26,7 +26,7 @@ virtual void OnProvisionalSaveComplete() = 0; }; -// A PasswordFormManager built to handle PassworForm objects synthesized +// A PasswordFormManager built to handle PasswordForm objects synthesized // by the Credential Manager API. class CredentialManagerPasswordFormManager : public PasswordFormManager { public:
diff --git a/components/password_manager/core/browser/password_form_manager.cc b/components/password_manager/core/browser/password_form_manager.cc index cb61d4b..1aa1039 100644 --- a/components/password_manager/core/browser/password_form_manager.cc +++ b/components/password_manager/core/browser/password_form_manager.cc
@@ -23,6 +23,7 @@ #include "components/password_manager/core/browser/password_manager_client.h" #include "components/password_manager/core/browser/password_manager_driver.h" #include "components/password_manager/core/browser/password_manager_metrics_util.h" +#include "components/password_manager/core/browser/password_manager_util.h" #include "components/password_manager/core/browser/password_store.h" #include "components/password_manager/core/browser/statistics_table.h" #include "google_apis/gaia/gaia_auth_util.h" @@ -313,7 +314,7 @@ } scoped_ptr<BrowserSavePasswordProgressLogger> logger; - if (client_->GetLogManager()->IsLoggingActive()) { + if (password_manager_util::IsLoggingActive(client_)) { logger.reset( new BrowserSavePasswordProgressLogger(client_->GetLogManager())); logger->LogMessage(Logger::STRING_FETCH_LOGINS_METHOD); @@ -384,7 +385,7 @@ const size_t logins_result_size = logins_result.size(); scoped_ptr<BrowserSavePasswordProgressLogger> logger; - if (client_->GetLogManager()->IsLoggingActive()) { + if (password_manager_util::IsLoggingActive(client_)) { logger.reset( new BrowserSavePasswordProgressLogger(client_->GetLogManager())); logger->LogMessage(Logger::STRING_ON_REQUEST_DONE_METHOD); @@ -588,7 +589,7 @@ } scoped_ptr<BrowserSavePasswordProgressLogger> logger; - if (client_->GetLogManager()->IsLoggingActive()) { + if (password_manager_util::IsLoggingActive(client_)) { logger.reset( new BrowserSavePasswordProgressLogger(client_->GetLogManager())); logger->LogMessage(Logger::STRING_ON_GET_STORE_RESULTS_METHOD);
diff --git a/components/password_manager/core/browser/password_manager.cc b/components/password_manager/core/browser/password_manager.cc index 17e791d..cf7d0d3 100644 --- a/components/password_manager/core/browser/password_manager.cc +++ b/components/password_manager/core/browser/password_manager.cc
@@ -26,6 +26,7 @@ #include "components/password_manager/core/browser/password_manager_client.h" #include "components/password_manager/core/browser/password_manager_driver.h" #include "components/password_manager/core/browser/password_manager_metrics_util.h" +#include "components/password_manager/core/browser/password_manager_util.h" #include "components/password_manager/core/common/password_manager_pref_names.h" #include "components/password_manager/core/common/password_manager_switches.h" #include "components/pref_registry/pref_registry_syncable.h" @@ -224,7 +225,7 @@ client_->IsSavingAndFillingEnabledForCurrentPage(); scoped_ptr<BrowserSavePasswordProgressLogger> logger; - if (client_->GetLogManager()->IsLoggingActive()) { + if (password_manager_util::IsLoggingActive(client_)) { logger.reset( new BrowserSavePasswordProgressLogger(client_->GetLogManager())); logger->LogMessage(Logger::STRING_PROVISIONALLY_SAVE_PASSWORD_METHOD); @@ -454,7 +455,7 @@ password_manager::PasswordManagerDriver* driver, const std::vector<PasswordForm>& forms) { scoped_ptr<BrowserSavePasswordProgressLogger> logger; - if (client_->GetLogManager()->IsLoggingActive()) { + if (password_manager_util::IsLoggingActive(client_)) { logger.reset( new BrowserSavePasswordProgressLogger(client_->GetLogManager())); logger->LogMessage(Logger::STRING_CREATE_LOGIN_MANAGERS_METHOD); @@ -528,7 +529,7 @@ bool PasswordManager::CanProvisionalManagerSave() { scoped_ptr<BrowserSavePasswordProgressLogger> logger; - if (client_->GetLogManager()->IsLoggingActive()) { + if (password_manager_util::IsLoggingActive(client_)) { logger.reset( new BrowserSavePasswordProgressLogger(client_->GetLogManager())); logger->LogMessage(Logger::STRING_CAN_PROVISIONAL_MANAGER_SAVE_METHOD); @@ -570,7 +571,7 @@ bool did_stop_loading) { CreatePendingLoginManagers(driver, visible_forms); scoped_ptr<BrowserSavePasswordProgressLogger> logger; - if (client_->GetLogManager()->IsLoggingActive()) { + if (password_manager_util::IsLoggingActive(client_)) { logger.reset( new BrowserSavePasswordProgressLogger(client_->GetLogManager())); logger->LogMessage(Logger::STRING_ON_PASSWORD_FORMS_RENDERED_METHOD); @@ -648,7 +649,7 @@ password_manager::PasswordManagerDriver* driver, const PasswordForm& password_form) { scoped_ptr<BrowserSavePasswordProgressLogger> logger; - if (client_->GetLogManager()->IsLoggingActive()) { + if (password_manager_util::IsLoggingActive(client_)) { logger.reset( new BrowserSavePasswordProgressLogger(client_->GetLogManager())); logger->LogMessage(Logger::STRING_ON_IN_PAGE_NAVIGATION); @@ -664,7 +665,7 @@ void PasswordManager::OnLoginSuccessful() { scoped_ptr<BrowserSavePasswordProgressLogger> logger; - if (client_->GetLogManager()->IsLoggingActive()) { + if (password_manager_util::IsLoggingActive(client_)) { logger.reset( new BrowserSavePasswordProgressLogger(client_->GetLogManager())); logger->LogMessage(Logger::STRING_ON_ASK_USER_OR_SAVE_PASSWORD); @@ -729,7 +730,7 @@ DCHECK_EQ(PasswordForm::SCHEME_HTML, preferred_match.scheme); scoped_ptr<BrowserSavePasswordProgressLogger> logger; - if (client_->GetLogManager()->IsLoggingActive()) { + if (password_manager_util::IsLoggingActive(client_)) { logger.reset( new BrowserSavePasswordProgressLogger(client_->GetLogManager())); logger->LogMessage(Logger::STRING_PASSWORDMANAGER_AUTOFILL); @@ -757,7 +758,7 @@ DCHECK_NE(PasswordForm::SCHEME_HTML, preferred_match.scheme); scoped_ptr<BrowserSavePasswordProgressLogger> logger; - if (client_->GetLogManager()->IsLoggingActive()) { + if (password_manager_util::IsLoggingActive(client_)) { logger.reset( new BrowserSavePasswordProgressLogger(client_->GetLogManager())); logger->LogMessage(Logger::STRING_PASSWORDMANAGER_AUTOFILLHTTPAUTH);
diff --git a/components/password_manager/core/browser/password_manager_util.cc b/components/password_manager/core/browser/password_manager_util.cc index 1b4bff4..bd7ca1c 100644 --- a/components/password_manager/core/browser/password_manager_util.cc +++ b/components/password_manager/core/browser/password_manager_util.cc
@@ -7,6 +7,7 @@ #include <algorithm> #include "components/autofill/core/common/password_form.h" +#include "components/password_manager/core/browser/log_manager.h" #include "components/sync_driver/sync_service.h" namespace password_manager_util { @@ -85,4 +86,9 @@ return new_vector; } +bool IsLoggingActive(const password_manager::PasswordManagerClient* client) { + const password_manager::LogManager* log_manager = client->GetLogManager(); + return log_manager && log_manager->IsLoggingActive(); +} + } // namespace password_manager_util
diff --git a/components/password_manager/core/browser/password_manager_util.h b/components/password_manager/core/browser/password_manager_util.h index 3b00570..ae683bfc 100644 --- a/components/password_manager/core/browser/password_manager_util.h +++ b/components/password_manager/core/browser/password_manager_util.h
@@ -50,6 +50,12 @@ std::vector<scoped_ptr<autofill::PasswordForm>> ConvertScopedVector( ScopedVector<autofill::PasswordForm> old_vector); +// A convenience function for testing that |client| has a non-null LogManager +// and that that LogManager returns true for IsLoggingActive. This function can +// be removed once PasswordManagerClient::GetLogManager is implemented on iOS +// and required to always return non-null. +bool IsLoggingActive(const password_manager::PasswordManagerClient* client); + } // namespace password_manager_util #endif // COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_PASSWORD_MANAGER_UTIL_H_
diff --git a/components/password_manager/sync/browser/BUILD.gn b/components/password_manager/sync/browser/BUILD.gn index f5a0e9b..3ccf7f33 100644 --- a/components/password_manager/sync/browser/BUILD.gn +++ b/components/password_manager/sync/browser/BUILD.gn
@@ -18,11 +18,11 @@ deps = [ "//base", - "//google_apis", "//components/autofill/core/common", "//components/password_manager/core/browser", "//components/signin/core/browser", "//components/sync_driver", + "//google_apis", "//net", "//url", ] @@ -38,6 +38,7 @@ "sync_username_test_base.h", ] deps = [ + ":browser", "//components/pref_registry", "//components/signin/core/common", "//components/sync_driver:test_support", @@ -46,6 +47,5 @@ "//sync", "//testing/gmock", "//testing/gtest", - ":browser", ] }
diff --git a/components/pdf/renderer/BUILD.gn b/components/pdf/renderer/BUILD.gn index 966ba98..5b4c2f70 100644 --- a/components/pdf/renderer/BUILD.gn +++ b/components/pdf/renderer/BUILD.gn
@@ -22,8 +22,8 @@ "//content/public/renderer", "//gin", "//ppapi/shared_impl", + "//third_party/WebKit/public:blink", "//third_party/icu", "//v8", - "//third_party/WebKit/public:blink", ] }
diff --git a/components/pdf_viewer/BUILD.gn b/components/pdf_viewer/BUILD.gn index 984b212b..fc565e6 100644 --- a/components/pdf_viewer/BUILD.gn +++ b/components/pdf_viewer/BUILD.gn
@@ -14,8 +14,8 @@ deps = [ "//base", "//components/bitmap_uploader", - "//components/mus/public/interfaces", "//components/mus/public/cpp", + "//components/mus/public/interfaces", "//components/web_view/public/interfaces", "//gpu", "//mojo/application/public/cpp",
diff --git a/components/policy/android/BUILD.gn b/components/policy/android/BUILD.gn index ab1003b..7399ba2 100644 --- a/components/policy/android/BUILD.gn +++ b/components/policy/android/BUILD.gn
@@ -26,9 +26,9 @@ android_library("policy_java_test_support") { testonly = true deps = [ + ":policy_java", "//base:base_java", "//base:base_java_test_support", - ":policy_java", ] java_files = [ "javatests/src/org/chromium/policy/test/annotations/Policies.java", @@ -51,8 +51,8 @@ "junit/src/org/chromium/policy/test/annotations/PoliciesTest.java", ] deps = [ - ":policy_java_test_support", ":policy_java", + ":policy_java_test_support", "//base:base_java", "//third_party/junit:hamcrest", ]
diff --git a/components/policy/core/common/policy_namespace.cc b/components/policy/core/common/policy_namespace.cc index 0fac9ca..33a9992 100644 --- a/components/policy/core/common/policy_namespace.cc +++ b/components/policy/core/common/policy_namespace.cc
@@ -4,6 +4,8 @@ #include "components/policy/core/common/policy_namespace.h" +#include <tuple> + namespace policy { PolicyNamespace::PolicyNamespace() {} @@ -26,8 +28,8 @@ } bool PolicyNamespace::operator<(const PolicyNamespace& other) const { - return domain < other.domain || - (domain == other.domain && component_id < other.component_id); + return std::tie(domain, component_id) < + std::tie(other.domain, other.component_id); } bool PolicyNamespace::operator==(const PolicyNamespace& other) const {
diff --git a/components/precache/android/BUILD.gn b/components/precache/android/BUILD.gn index 537150b..7deabcd 100644 --- a/components/precache/android/BUILD.gn +++ b/components/precache/android/BUILD.gn
@@ -14,8 +14,8 @@ android_library("precache_javatests") { deps = [ - "//base:base_java_test_support", ":precache_java", + "//base:base_java_test_support", ] DEPRECATED_java_in_dir = "javatests/src" }
diff --git a/components/proximity_auth.gypi b/components/proximity_auth.gypi index 0f4fee9..42c732c9 100644 --- a/components/proximity_auth.gypi +++ b/components/proximity_auth.gypi
@@ -172,8 +172,6 @@ '../net/net.gyp:net', ], 'sources': [ - "proximity_auth/cryptauth/base64url.cc", - "proximity_auth/cryptauth/base64url.h", "proximity_auth/cryptauth/cryptauth_access_token_fetcher.h", "proximity_auth/cryptauth/cryptauth_access_token_fetcher_impl.cc", "proximity_auth/cryptauth/cryptauth_access_token_fetcher_impl.h",
diff --git a/components/proximity_auth/ble/BUILD.gn b/components/proximity_auth/ble/BUILD.gn index 3fd1b688..5f204fb 100644 --- a/components/proximity_auth/ble/BUILD.gn +++ b/components/proximity_auth/ble/BUILD.gn
@@ -46,8 +46,8 @@ deps = [ ":ble", - "//components/proximity_auth", "//base/test:test_support", + "//components/proximity_auth", "//device/bluetooth:mocks", "//testing/gmock", "//testing/gtest",
diff --git a/components/proximity_auth/cryptauth/BUILD.gn b/components/proximity_auth/cryptauth/BUILD.gn index a272435..a7363ac1 100644 --- a/components/proximity_auth/cryptauth/BUILD.gn +++ b/components/proximity_auth/cryptauth/BUILD.gn
@@ -4,8 +4,6 @@ source_set("cryptauth") { sources = [ - "base64url.cc", - "base64url.h", "cryptauth_access_token_fetcher.h", "cryptauth_access_token_fetcher_impl.cc", "cryptauth_access_token_fetcher_impl.h", @@ -39,9 +37,9 @@ deps = [ "//base", - "//crypto", "//components/gcm_driver", "//components/proximity_auth/logging", + "//crypto", "//google_apis", "//net", ] @@ -79,7 +77,6 @@ source_set("unit_tests") { testonly = true sources = [ - "base64url_unittest.cc", "cryptauth_access_token_fetcher_impl_unittest.cc", "cryptauth_api_call_flow_unittest.cc", "cryptauth_client_impl_unittest.cc",
diff --git a/components/proximity_auth/cryptauth/base64url.cc b/components/proximity_auth/cryptauth/base64url.cc deleted file mode 100644 index d32f188..0000000 --- a/components/proximity_auth/cryptauth/base64url.cc +++ /dev/null
@@ -1,34 +0,0 @@ -// Copyright 2014 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 "components/proximity_auth/cryptauth/base64url.h" - -#include "base/base64.h" -#include "base/strings/string_util.h" - -namespace proximity_auth { - -void Base64UrlEncode(const std::string& decoded_input, - std::string* encoded_output) { - base::Base64Encode(decoded_input, encoded_output); - base::ReplaceChars(*encoded_output, "+", "-", encoded_output); - base::ReplaceChars(*encoded_output, "/", "_", encoded_output); -} - -bool Base64UrlDecode(const std::string& encoded_input, - std::string* decoded_output) { - // Bail on malformed strings, which already contain a '+' or a '/'. All valid - // strings should escape these special characters as '-' and '_', - // respectively. - if (encoded_input.find_first_of("+/") != std::string::npos) - return false; - - std::string adjusted_encoded_input = encoded_input; - base::ReplaceChars(adjusted_encoded_input, "-", "+", &adjusted_encoded_input); - base::ReplaceChars(adjusted_encoded_input, "_", "/", &adjusted_encoded_input); - - return base::Base64Decode(adjusted_encoded_input, decoded_output); -} - -} // namespace proximity_auth
diff --git a/components/proximity_auth/cryptauth/base64url.h b/components/proximity_auth/cryptauth/base64url.h deleted file mode 100644 index 5317cd8..0000000 --- a/components/proximity_auth/cryptauth/base64url.h +++ /dev/null
@@ -1,29 +0,0 @@ -// Copyright 2014 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 COMPONENTS_PROXIMITY_AUTH_CRYPTAUTH_BASE64URL_H -#define COMPONENTS_PROXIMITY_AUTH_CRYPTAUTH_BASE64URL_H - -#include <string> - -namespace proximity_auth { - -// An implmentation of the base64url encoding. Escapes the unsafe '+' and '/' -// characters with the url-safe alternatives '-' and '_', respectively. For more -// info, see the section on "Base 64 Encoding with URL and Filename Safe -// Alphabet" in http://www.ietf.org/rfc/rfc4648.txt -// NOTE: Unlike many common web-safe encodings, this function does not escape -// the '=' character. This is to match the expectations set by Android. -// TODO(isherman): There are several (semantically slightly different) -// implementations of this within the Chromium codebase. Try to unify them. -void Base64UrlEncode(const std::string& decoded_input, - std::string* encoded_output); - -// The inverse operation for the base64url encoding above. -bool Base64UrlDecode(const std::string& encoded_input, - std::string* decoded_output); - -} // namespace proximity_auth - -#endif // COMPONENTS_PROXIMITY_BASE64URL_H
diff --git a/components/proximity_auth/cryptauth/base64url_unittest.cc b/components/proximity_auth/cryptauth/base64url_unittest.cc deleted file mode 100644 index 487ea444..0000000 --- a/components/proximity_auth/cryptauth/base64url_unittest.cc +++ /dev/null
@@ -1,85 +0,0 @@ -// Copyright 2014 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 "components/proximity_auth/cryptauth/base64url.h" - -#include "base/base64.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace proximity_auth { - -TEST(ProximityAuthBase64UrlTest, EncodeRegularString) { - const std::string input = "Hello world!"; - const std::string expected_output = "SGVsbG8gd29ybGQh"; - - std::string web_safe_output; - Base64UrlEncode(input, &web_safe_output); - EXPECT_EQ(expected_output, web_safe_output); - - // For good measure, make sure that the encoding matches the //base - // implemenation as well. - std::string non_web_safe_output; - base::Base64Encode(input, &non_web_safe_output); - EXPECT_EQ(web_safe_output, non_web_safe_output); -} - -TEST(ProximityAuthBase64UrlTest, DecodeRegularString) { - const std::string input = "SGVsbG8gd29ybGQh"; - const std::string expected_output = "Hello world!"; - - std::string web_safe_output; - EXPECT_TRUE(Base64UrlDecode(input, &web_safe_output)); - EXPECT_EQ(expected_output, web_safe_output); - - // For good measure, make sure that the encoding matches the //base - // implemenation as well. - std::string non_web_safe_output; - EXPECT_TRUE(base::Base64Decode(input, &non_web_safe_output)); - EXPECT_EQ(web_safe_output, non_web_safe_output); -} - -TEST(ProximityAuthBase64UrlTest, EncodeSpecialCharacters) { - // This happens to be a stable encoding, i.e. encode(decode(s)) gives back s. - const std::string encoded = "/+Y="; - std::string decoded; - ASSERT_TRUE(base::Base64Decode(encoded, &decoded)); - - // Decoded strings that encode to special characters are non-printable, so, - // for ease of testing, just compare the web-safe and non-web-safe encodings. - std::string web_safe_encoded; - Base64UrlEncode(decoded, &web_safe_encoded); - EXPECT_EQ("_-Y=", web_safe_encoded); -} - -TEST(ProximityAuthBase64UrlTest, DecodeSpecialCharacters) { - const std::string encoded = "_-Y="; - std::string decoded; - ASSERT_TRUE(Base64UrlDecode(encoded, &decoded)); - - // Decoded strings that encode to special characters are non-printable, so, - // for ease of testing, just compare the web-safe and non-web-safe encodings. - std::string non_web_safe_encoded; - base::Base64Encode(decoded, &non_web_safe_encoded); - EXPECT_EQ("/+Y=", non_web_safe_encoded); -} - -TEST(ProximityAuthBase64UrlTest, DecodeBailsOnPlus) { - // Note that "_-Y=" is a valid encoded string, as tested above. This test - // simply verifies that an otherwise correctly encoded string cannot use '+' - // in place of '-', since the proximity auth code expects websafe encodings. - const std::string encoded = "_+Y="; - std::string decoded; - EXPECT_FALSE(Base64UrlDecode(encoded, &decoded)); -} - -TEST(ProximityAuthBase64UrlTest, DecodeBailsOnSlash) { - // Note that "_-Y=" is a valid encoded string, as tested above. This test - // simply verifies that an otherwise correctly encoded string cannot use '/' - // in place of '_', since the proximity auth code expects websafe encodings. - const std::string encoded = "/-Y="; - std::string decoded; - EXPECT_FALSE(Base64UrlDecode(encoded, &decoded)); -} - -} // namespace proximity_auth
diff --git a/components/proximity_auth/cryptauth/cryptauth_device_manager.cc b/components/proximity_auth/cryptauth/cryptauth_device_manager.cc index ecc0e5c7..2055322 100644 --- a/components/proximity_auth/cryptauth/cryptauth_device_manager.cc +++ b/components/proximity_auth/cryptauth/cryptauth_device_manager.cc
@@ -4,10 +4,10 @@ #include "components/proximity_auth/cryptauth/cryptauth_device_manager.h" +#include "base/base64url.h" #include "base/prefs/pref_registry_simple.h" #include "base/prefs/pref_service.h" #include "base/prefs/scoped_user_pref_update.h" -#include "components/proximity_auth/cryptauth/base64url.h" #include "components/proximity_auth/cryptauth/cryptauth_client.h" #include "components/proximity_auth/cryptauth/pref_names.h" #include "components/proximity_auth/cryptauth/sync_scheduler_impl.h" @@ -42,9 +42,15 @@ // We store the device information in Base64Url form because dictionary values // must be valid UTF8 strings. std::string public_key_b64, device_name_b64, bluetooth_address_b64; - Base64UrlEncode(device.public_key(), &public_key_b64); - Base64UrlEncode(device.friendly_device_name(), &device_name_b64); - Base64UrlEncode(device.bluetooth_address(), &bluetooth_address_b64); + base::Base64UrlEncode(device.public_key(), + base::Base64UrlEncodePolicy::INCLUDE_PADDING, + &public_key_b64); + base::Base64UrlEncode(device.friendly_device_name(), + base::Base64UrlEncodePolicy::INCLUDE_PADDING, + &device_name_b64); + base::Base64UrlEncode(device.bluetooth_address(), + base::Base64UrlEncodePolicy::INCLUDE_PADDING, + &bluetooth_address_b64); dictionary->SetString(kExternalDeviceKeyPublicKey, public_key_b64); dictionary->SetString(kExternalDeviceKeyDeviceName, device_name_b64); @@ -69,9 +75,15 @@ // We store the device information in Base64Url form because dictionary values // must be valid UTF8 strings. std::string public_key, device_name, bluetooth_address; - if (!Base64UrlDecode(public_key_b64, &public_key) || - !Base64UrlDecode(device_name_b64, &device_name) || - !Base64UrlDecode(bluetooth_address_b64, &bluetooth_address)) { + if (!base::Base64UrlDecode(public_key_b64, + base::Base64UrlDecodePolicy::REQUIRE_PADDING, + &public_key) || + !base::Base64UrlDecode(device_name_b64, + base::Base64UrlDecodePolicy::REQUIRE_PADDING, + &device_name) || + !base::Base64UrlDecode(bluetooth_address_b64, + base::Base64UrlDecodePolicy::REQUIRE_PADDING, + &bluetooth_address)) { return false; }
diff --git a/components/proximity_auth/cryptauth/cryptauth_device_manager_unittest.cc b/components/proximity_auth/cryptauth/cryptauth_device_manager_unittest.cc index d524001..3888ca2d6 100644 --- a/components/proximity_auth/cryptauth/cryptauth_device_manager_unittest.cc +++ b/components/proximity_auth/cryptauth/cryptauth_device_manager_unittest.cc
@@ -4,12 +4,12 @@ #include "components/proximity_auth/cryptauth/cryptauth_device_manager.h" +#include "base/base64url.h" #include "base/memory/weak_ptr.h" #include "base/prefs/scoped_user_pref_update.h" #include "base/prefs/testing_pref_service.h" #include "base/strings/stringprintf.h" #include "base/test/simple_test_clock.h" -#include "components/proximity_auth/cryptauth/base64url.h" #include "components/proximity_auth/cryptauth/fake_cryptauth_gcm_manager.h" #include "components/proximity_auth/cryptauth/mock_cryptauth_client.h" #include "components/proximity_auth/cryptauth/mock_sync_scheduler.h" @@ -87,9 +87,15 @@ &bluetooth_address_b64)); std::string public_key, device_name, bluetooth_address; - ASSERT_TRUE(Base64UrlDecode(public_key_b64, &public_key)); - ASSERT_TRUE(Base64UrlDecode(device_name_b64, &device_name)); - ASSERT_TRUE(Base64UrlDecode(bluetooth_address_b64, &bluetooth_address)); + ASSERT_TRUE(base::Base64UrlDecode( + public_key_b64, base::Base64UrlDecodePolicy::REQUIRE_PADDING, + &public_key)); + ASSERT_TRUE(base::Base64UrlDecode( + device_name_b64, base::Base64UrlDecodePolicy::REQUIRE_PADDING, + &device_name)); + ASSERT_TRUE(base::Base64UrlDecode( + bluetooth_address_b64, base::Base64UrlDecodePolicy::REQUIRE_PADDING, + &bluetooth_address)); const auto& expected_unlock_key = expected_unlock_keys[i]; EXPECT_EQ(expected_unlock_key.public_key(), public_key); @@ -176,9 +182,15 @@ new base::DictionaryValue()); std::string public_key_b64, device_name_b64, bluetooth_address_b64; - Base64UrlEncode(kStoredPublicKey, &public_key_b64); - Base64UrlEncode(kStoredDeviceName, &device_name_b64); - Base64UrlEncode(kStoredBluetoothAddress, &bluetooth_address_b64); + base::Base64UrlEncode(kStoredPublicKey, + base::Base64UrlEncodePolicy::INCLUDE_PADDING, + &public_key_b64); + base::Base64UrlEncode(kStoredDeviceName, + base::Base64UrlEncodePolicy::INCLUDE_PADDING, + &device_name_b64); + base::Base64UrlEncode(kStoredBluetoothAddress, + base::Base64UrlEncodePolicy::INCLUDE_PADDING, + &bluetooth_address_b64); unlock_key_dictionary->SetString("public_key", public_key_b64); unlock_key_dictionary->SetString("device_name", device_name_b64);
diff --git a/components/proximity_auth/cryptauth/cryptauth_enroller_impl.cc b/components/proximity_auth/cryptauth/cryptauth_enroller_impl.cc index c595be1..d8bc831 100644 --- a/components/proximity_auth/cryptauth/cryptauth_enroller_impl.cc +++ b/components/proximity_auth/cryptauth/cryptauth_enroller_impl.cc
@@ -5,7 +5,6 @@ #include "components/proximity_auth/cryptauth/cryptauth_enroller_impl.h" #include "base/bind.h" -#include "components/proximity_auth/cryptauth/base64url.h" #include "components/proximity_auth/cryptauth/cryptauth_client_impl.h" #include "components/proximity_auth/cryptauth/cryptauth_enrollment_utils.h" #include "components/proximity_auth/cryptauth/fake_secure_message_delegate.h"
diff --git a/components/proximity_auth/cryptauth/cryptauth_enrollment_manager.cc b/components/proximity_auth/cryptauth/cryptauth_enrollment_manager.cc index 39c5e49..026b42a1 100644 --- a/components/proximity_auth/cryptauth/cryptauth_enrollment_manager.cc +++ b/components/proximity_auth/cryptauth/cryptauth_enrollment_manager.cc
@@ -4,11 +4,11 @@ #include "components/proximity_auth/cryptauth/cryptauth_enrollment_manager.h" +#include "base/base64url.h" #include "base/prefs/pref_registry_simple.h" #include "base/prefs/pref_service.h" #include "base/time/clock.h" #include "base/time/time.h" -#include "components/proximity_auth/cryptauth/base64url.h" #include "components/proximity_auth/cryptauth/cryptauth_enroller.h" #include "components/proximity_auth/cryptauth/pref_names.h" #include "components/proximity_auth/cryptauth/secure_message_delegate.h" @@ -164,9 +164,9 @@ std::string CryptAuthEnrollmentManager::GetUserPublicKey() { std::string public_key; - if (!Base64UrlDecode( + if (!base::Base64UrlDecode( pref_service_->GetString(prefs::kCryptAuthEnrollmentUserPublicKey), - &public_key)) { + base::Base64UrlDecodePolicy::REQUIRE_PADDING, &public_key)) { PA_LOG(ERROR) << "Invalid public key stored in user prefs."; return std::string(); } @@ -175,9 +175,9 @@ std::string CryptAuthEnrollmentManager::GetUserPrivateKey() { std::string private_key; - if (!Base64UrlDecode( + if (!base::Base64UrlDecode( pref_service_->GetString(prefs::kCryptAuthEnrollmentUserPrivateKey), - &private_key)) { + base::Base64UrlDecodePolicy::REQUIRE_PADDING, &private_key)) { PA_LOG(ERROR) << "Invalid private key stored in user prefs."; return std::string(); } @@ -204,8 +204,12 @@ // Store the keypair in Base64 format because pref values require readable // string values. std::string public_key_b64, private_key_b64; - Base64UrlEncode(public_key, &public_key_b64); - Base64UrlEncode(private_key, &private_key_b64); + base::Base64UrlEncode(public_key, + base::Base64UrlEncodePolicy::INCLUDE_PADDING, + &public_key_b64); + base::Base64UrlEncode(private_key, + base::Base64UrlEncodePolicy::INCLUDE_PADDING, + &private_key_b64); pref_service_->SetString(prefs::kCryptAuthEnrollmentUserPublicKey, public_key_b64); pref_service_->SetString(prefs::kCryptAuthEnrollmentUserPrivateKey, @@ -275,7 +279,9 @@ device_info.set_device_software_package(kDeviceSoftwarePackage); std::string public_key_b64; - Base64UrlEncode(GetUserPublicKey(), &public_key_b64); + base::Base64UrlEncode(GetUserPublicKey(), + base::Base64UrlEncodePolicy::INCLUDE_PADDING, + &public_key_b64); PA_LOG(INFO) << "Making enrollment:\n" << " public_key: " << public_key_b64 << "\n" << " invocation_reason: " << invocation_reason << "\n"
diff --git a/components/proximity_auth/cryptauth/cryptauth_enrollment_manager_unittest.cc b/components/proximity_auth/cryptauth/cryptauth_enrollment_manager_unittest.cc index af954b1..3704e17 100644 --- a/components/proximity_auth/cryptauth/cryptauth_enrollment_manager_unittest.cc +++ b/components/proximity_auth/cryptauth/cryptauth_enrollment_manager_unittest.cc
@@ -4,12 +4,12 @@ #include "components/proximity_auth/cryptauth/cryptauth_enrollment_manager.h" +#include "base/base64url.h" #include "base/memory/weak_ptr.h" #include "base/prefs/testing_pref_service.h" #include "base/test/simple_test_clock.h" #include "base/time/clock.h" #include "base/time/time.h" -#include "components/proximity_auth/cryptauth/base64url.h" #include "components/proximity_auth/cryptauth/cryptauth_enroller.h" #include "components/proximity_auth/cryptauth/fake_cryptauth_gcm_manager.h" #include "components/proximity_auth/cryptauth/fake_secure_message_delegate.h" @@ -175,8 +175,12 @@ new base::FundamentalValue(cryptauth::INVOCATION_REASON_UNKNOWN)); std::string public_key_b64, private_key_b64; - Base64UrlEncode(public_key_, &public_key_b64); - Base64UrlEncode(private_key_, &private_key_b64); + base::Base64UrlEncode(public_key_, + base::Base64UrlEncodePolicy::INCLUDE_PADDING, + &public_key_b64); + base::Base64UrlEncode(private_key_, + base::Base64UrlEncodePolicy::INCLUDE_PADDING, + &private_key_b64); pref_service_.SetString(prefs::kCryptAuthEnrollmentUserPublicKey, public_key_b64); pref_service_.SetString(prefs::kCryptAuthEnrollmentUserPrivateKey,
diff --git a/components/proximity_auth/cryptauth/cryptauth_enrollment_utils.cc b/components/proximity_auth/cryptauth/cryptauth_enrollment_utils.cc index ee5cec2..177d4dd 100644 --- a/components/proximity_auth/cryptauth/cryptauth_enrollment_utils.cc +++ b/components/proximity_auth/cryptauth/cryptauth_enrollment_utils.cc
@@ -6,9 +6,9 @@ #include <math.h> +#include "base/base64url.h" #include "base/md5.h" #include "base/sha1.h" -#include "components/proximity_auth/cryptauth/base64url.h" namespace proximity_auth { @@ -34,8 +34,9 @@ std::string CalculateDeviceUserId(const std::string& device_id, const std::string& user_id) { std::string device_user_id; - Base64UrlEncode(base::SHA1HashString(device_id + "|" + user_id), - &device_user_id); + base::Base64UrlEncode(base::SHA1HashString(device_id + "|" + user_id), + base::Base64UrlEncodePolicy::INCLUDE_PADDING, + &device_user_id); return device_user_id; }
diff --git a/components/proximity_auth/device_to_device_authenticator_unittest.cc b/components/proximity_auth/device_to_device_authenticator_unittest.cc index 895fbee8..45b4849 100644 --- a/components/proximity_auth/device_to_device_authenticator_unittest.cc +++ b/components/proximity_auth/device_to_device_authenticator_unittest.cc
@@ -4,12 +4,12 @@ #include "components/proximity_auth/device_to_device_authenticator.h" +#include "base/base64url.h" #include "base/bind.h" #include "base/memory/scoped_vector.h" #include "base/rand_util.h" #include "base/timer/mock_timer.h" #include "components/proximity_auth/connection.h" -#include "components/proximity_auth/cryptauth/base64url.h" #include "components/proximity_auth/cryptauth/fake_secure_message_delegate.h" #include "components/proximity_auth/device_to_device_responder_operations.h" #include "components/proximity_auth/proximity_auth_test_util.h" @@ -142,10 +142,14 @@ void SetUp() override { // Set up the session asymmetric keys for both the local and remote devices. - Base64UrlDecode(kInitiatorSessionPublicKeyBase64, - &local_session_public_key_); - Base64UrlDecode(kResponderSessionPublicKeyBase64, - &remote_session_public_key_); + ASSERT_TRUE( + base::Base64UrlDecode(kInitiatorSessionPublicKeyBase64, + base::Base64UrlDecodePolicy::REQUIRE_PADDING, + &local_session_public_key_)); + ASSERT_TRUE( + base::Base64UrlDecode(kResponderSessionPublicKeyBase64, + base::Base64UrlDecodePolicy::REQUIRE_PADDING, + &remote_session_public_key_)); remote_session_private_key_ = secure_message_delegate_->GetPrivateKeyForPublicKey( remote_session_public_key_),
diff --git a/components/proximity_auth/device_to_device_operations_unittest.cc b/components/proximity_auth/device_to_device_operations_unittest.cc index 0ba34ad..18fd7d0 100644 --- a/components/proximity_auth/device_to_device_operations_unittest.cc +++ b/components/proximity_auth/device_to_device_operations_unittest.cc
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "base/base64url.h" #include "base/bind.h" -#include "components/proximity_auth/cryptauth/base64url.h" #include "components/proximity_auth/cryptauth/fake_secure_message_delegate.h" #include "components/proximity_auth/device_to_device_initiator_operations.h" #include "components/proximity_auth/device_to_device_responder_operations.h" @@ -59,14 +59,18 @@ ~ProximityAuthDeviceToDeviceOperationsTest() override {} void SetUp() override { - ASSERT_TRUE(Base64UrlDecode(kInitiatorSessionPublicKeyBase64, - &local_session_public_key_)); + ASSERT_TRUE( + base::Base64UrlDecode(kInitiatorSessionPublicKeyBase64, + base::Base64UrlDecodePolicy::REQUIRE_PADDING, + &local_session_public_key_)); local_session_private_key_ = secure_message_delegate_.GetPrivateKeyForPublicKey( local_session_public_key_); - ASSERT_TRUE(Base64UrlDecode(kResponderSessionPublicKeyBase64, - &remote_session_public_key_)); + ASSERT_TRUE( + base::Base64UrlDecode(kResponderSessionPublicKeyBase64, + base::Base64UrlDecodePolicy::REQUIRE_PADDING, + &remote_session_public_key_)); remote_session_private_key_ = secure_message_delegate_.GetPrivateKeyForPublicKey( remote_session_public_key_);
diff --git a/components/proximity_auth/messenger_impl.cc b/components/proximity_auth/messenger_impl.cc index 7753bc5d..d6a1869a 100644 --- a/components/proximity_auth/messenger_impl.cc +++ b/components/proximity_auth/messenger_impl.cc
@@ -4,6 +4,7 @@ #include "components/proximity_auth/messenger_impl.h" +#include "base/base64url.h" #include "base/bind.h" #include "base/json/json_reader.h" #include "base/json/json_writer.h" @@ -11,7 +12,6 @@ #include "base/thread_task_runner_handle.h" #include "base/values.h" #include "components/proximity_auth/connection.h" -#include "components/proximity_auth/cryptauth/base64url.h" #include "components/proximity_auth/logging/logging.h" #include "components/proximity_auth/messenger_observer.h" #include "components/proximity_auth/remote_status_update.h" @@ -119,7 +119,9 @@ const std::string encrypted_message_data = challenge; std::string encrypted_message_data_base64; - Base64UrlEncode(encrypted_message_data, &encrypted_message_data_base64); + base::Base64UrlEncode(encrypted_message_data, + base::Base64UrlEncodePolicy::INCLUDE_PADDING, + &encrypted_message_data_base64); base::DictionaryValue message; message.SetString(kTypeKey, kMessageTypeDecryptRequest); @@ -268,7 +270,9 @@ std::string decrypted_data; if (!message.GetString(kDataKey, &base64_data) || base64_data.empty()) { PA_LOG(ERROR) << "Decrypt response missing '" << kDataKey << "' value."; - } else if (!Base64UrlDecode(base64_data, &decrypted_data)) { + } else if (!base::Base64UrlDecode( + base64_data, base::Base64UrlDecodePolicy::REQUIRE_PADDING, + &decrypted_data)) { PA_LOG(ERROR) << "Unable to base64-decode decrypt response."; }
diff --git a/components/proximity_auth/remote_device_loader.cc b/components/proximity_auth/remote_device_loader.cc index 98594f21..9d47f64f 100644 --- a/components/proximity_auth/remote_device_loader.cc +++ b/components/proximity_auth/remote_device_loader.cc
@@ -4,8 +4,8 @@ #include "components/proximity_auth/remote_device_loader.h" +#include "base/base64url.h" #include "base/bind.h" -#include "components/proximity_auth/cryptauth/base64url.h" #include "components/proximity_auth/cryptauth/secure_message_delegate.h" #include "components/proximity_auth/logging/logging.h" #include "components/proximity_auth/proximity_auth_pref_manager.h" @@ -73,7 +73,9 @@ std::string bluetooth_address = unlock_key.bluetooth_address(); if (bluetooth_address.empty() && pref_manager_) { std::string b64_public_key; - Base64UrlEncode(unlock_key.public_key(), &b64_public_key); + base::Base64UrlEncode(unlock_key.public_key(), + base::Base64UrlEncodePolicy::INCLUDE_PADDING, + &b64_public_key); bluetooth_address = pref_manager_->GetDeviceAddress(b64_public_key); PA_LOG(INFO) << "The BLE address of " << unlock_key.friendly_device_name() << " is " << bluetooth_address;
diff --git a/components/proximity_auth/webui/proximity_auth_webui_handler.cc b/components/proximity_auth/webui/proximity_auth_webui_handler.cc index 60faa7ce..929a1c73 100644 --- a/components/proximity_auth/webui/proximity_auth_webui_handler.cc +++ b/components/proximity_auth/webui/proximity_auth_webui_handler.cc
@@ -6,6 +6,7 @@ #include <algorithm> +#include "base/base64url.h" #include "base/bind.h" #include "base/i18n/time_formatting.h" #include "base/prefs/pref_service.h" @@ -15,7 +16,6 @@ #include "base/values.h" #include "components/proximity_auth/ble/pref_names.h" #include "components/proximity_auth/bluetooth_connection_finder.h" -#include "components/proximity_auth/cryptauth/base64url.h" #include "components/proximity_auth/cryptauth/cryptauth_enrollment_manager.h" #include "components/proximity_auth/cryptauth/proto/cryptauth_api.pb.h" #include "components/proximity_auth/cryptauth/secure_message_delegate.h" @@ -249,7 +249,9 @@ bool make_unlock_key; if (args->GetSize() != 2 || !args->GetString(0, &public_key_b64) || !args->GetBoolean(1, &make_unlock_key) || - !Base64UrlDecode(public_key_b64, &public_key)) { + !base::Base64UrlDecode(public_key_b64, + base::Base64UrlDecodePolicy::REQUIRE_PADDING, + &public_key)) { PA_LOG(ERROR) << "Invalid arguments to toggleUnlockKey"; return; } @@ -327,7 +329,9 @@ std::string public_key; if (!enrollment_manager || !device_manager || !args->GetSize() || !args->GetString(0, &b64_public_key) || - !Base64UrlDecode(b64_public_key, &public_key)) { + !base::Base64UrlDecode(b64_public_key, + base::Base64UrlDecodePolicy::REQUIRE_PADDING, + &public_key)) { return; } @@ -474,7 +478,9 @@ ProximityAuthWebUIHandler::ExternalDeviceInfoToDictionary( const cryptauth::ExternalDeviceInfo& device_info) { std::string base64_public_key; - Base64UrlEncode(device_info.public_key(), &base64_public_key); + base::Base64UrlEncode(device_info.public_key(), + base::Base64UrlEncodePolicy::INCLUDE_PADDING, + &base64_public_key); // Set the fields in the ExternalDeviceInfo proto. scoped_ptr<base::DictionaryValue> dictionary(new base::DictionaryValue());
diff --git a/components/proximity_auth/wire_message.cc b/components/proximity_auth/wire_message.cc index 8ee5deb5..3a640086 100644 --- a/components/proximity_auth/wire_message.cc +++ b/components/proximity_auth/wire_message.cc
@@ -6,11 +6,11 @@ #include <limits> +#include "base/base64url.h" #include "base/json/json_reader.h" #include "base/json/json_writer.h" #include "base/macros.h" #include "base/values.h" -#include "components/proximity_auth/cryptauth/base64url.h" #include "components/proximity_auth/logging/logging.h" // The wire messages have a simple format: @@ -106,7 +106,9 @@ } std::string payload; - if (!Base64UrlDecode(payload_base64, &payload)) { + if (!base::Base64UrlDecode(payload_base64, + base::Base64UrlDecodePolicy::REQUIRE_PADDING, + &payload)) { PA_LOG(WARNING) << "Error: Invalid base64 encoding for payload."; return scoped_ptr<WireMessage>(); } @@ -126,7 +128,8 @@ body.SetString(kPermitIdKey, permit_id_); std::string base64_payload; - Base64UrlEncode(payload_, &base64_payload); + base::Base64UrlEncode(payload_, base::Base64UrlEncodePolicy::INCLUDE_PADDING, + &base64_payload); body.SetString(kPayloadKey, base64_payload); std::string json_body;
diff --git a/components/renderer_context_menu/BUILD.gn b/components/renderer_context_menu/BUILD.gn index 21b4e06..912888c 100644 --- a/components/renderer_context_menu/BUILD.gn +++ b/components/renderer_context_menu/BUILD.gn
@@ -26,8 +26,8 @@ deps = [ "//base", - "//content/public/browser", "//components/search_engines", + "//content/public/browser", "//third_party/WebKit/public:blink_headers", ] }
diff --git a/components/resource_provider/public/cpp/resource_loader.cc b/components/resource_provider/public/cpp/resource_loader.cc index 5dd763f..023418b 100644 --- a/components/resource_provider/public/cpp/resource_loader.cc +++ b/components/resource_provider/public/cpp/resource_loader.cc
@@ -27,9 +27,7 @@ ResourceLoader::ResourceLoader(mojo::ApplicationImpl* app, const std::set<std::string>& paths) : loaded_(false), did_block_(false) { - mojo::URLRequestPtr request(mojo::URLRequest::New()); - request->url = mojo::String::From("mojo:resource_provider"); - app->ConnectToService(request.Pass(), &resource_provider_); + app->ConnectToService("mojo:resource_provider", &resource_provider_); std::vector<std::string> paths_vector(paths.begin(), paths.end()); resource_provider_->GetResources( mojo::Array<mojo::String>::From(paths_vector),
diff --git a/components/rlz/BUILD.gn b/components/rlz/BUILD.gn index dad456e..72e0efb6 100644 --- a/components/rlz/BUILD.gn +++ b/components/rlz/BUILD.gn
@@ -32,9 +32,9 @@ ] deps = [ + ":rlz", "//net:test_support", "//rlz:test_support", "//ui/base", - ":rlz", ] }
diff --git a/components/scheduler/BUILD.gn b/components/scheduler/BUILD.gn index 5b34961c..5031a61 100644 --- a/components/scheduler/BUILD.gn +++ b/components/scheduler/BUILD.gn
@@ -48,6 +48,7 @@ "base/test_always_fail_time_source.h", "base/test_time_source.cc", "base/test_time_source.h", + "base/time_domain_unittest.cc", "child/idle_helper_unittest.cc", "child/scheduler_helper_unittest.cc", "child/scheduler_tqm_delegate_for_test.cc",
diff --git a/components/scheduler/base/lazy_now.cc b/components/scheduler/base/lazy_now.cc index c80dd47..3492ca67 100644 --- a/components/scheduler/base/lazy_now.cc +++ b/components/scheduler/base/lazy_now.cc
@@ -8,13 +8,10 @@ #include "components/scheduler/base/task_queue_manager.h" namespace scheduler { -namespace internal { - base::TimeTicks LazyNow::Now() { if (now_.is_null()) now_ = tick_clock_->NowTicks(); return now_; } -} // namespace internal } // namespace scheduler
diff --git a/components/scheduler/base/lazy_now.h b/components/scheduler/base/lazy_now.h index fd52322..34c659b 100644 --- a/components/scheduler/base/lazy_now.h +++ b/components/scheduler/base/lazy_now.h
@@ -12,7 +12,6 @@ } namespace scheduler { -namespace internal { // Now() is somewhat expensive so it makes sense not to call Now() unless we // really need to. @@ -31,7 +30,6 @@ base::TimeTicks now_; }; -} // namespace internal } // namespace scheduler #endif // COMPONENTS_SCHEDULER_BASE_LAZY_NOW_H_
diff --git a/components/scheduler/base/real_time_domain.cc b/components/scheduler/base/real_time_domain.cc new file mode 100644 index 0000000..8a57a041 --- /dev/null +++ b/components/scheduler/base/real_time_domain.cc
@@ -0,0 +1,43 @@ +// Copyright 2015 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 "components/scheduler/base/real_time_domain.h" + +#include "base/bind.h" +#include "components/scheduler/base/task_queue_impl.h" +#include "components/scheduler/base/task_queue_manager_delegate.h" + +namespace scheduler { + +RealTimeDomain::RealTimeDomain( + TaskQueueManagerDelegate* task_queue_manager_delegate, + base::Closure do_work_closure) + : task_queue_manager_delegate_(task_queue_manager_delegate), + do_work_closure_(do_work_closure) { + DCHECK(task_queue_manager_delegate_); +} + +RealTimeDomain::~RealTimeDomain() {} + +LazyNow RealTimeDomain::CreateLazyNow() { + return LazyNow(task_queue_manager_delegate_); +} + +void RealTimeDomain::RequestWakeup(base::TimeDelta delay) { + task_queue_manager_delegate_->PostDelayedTask(FROM_HERE, do_work_closure_, + delay); +} + +bool RealTimeDomain::MaybeAdvanceTime() { + return false; +} + +void RealTimeDomain::AsValueIntoInternal( + base::trace_event::TracedValue* state) const {} + +const char* RealTimeDomain::GetName() const { + return "RealTimeDomain"; +} + +} // namespace scheduler
diff --git a/components/scheduler/base/real_time_domain.h b/components/scheduler/base/real_time_domain.h new file mode 100644 index 0000000..f4f9ba8 --- /dev/null +++ b/components/scheduler/base/real_time_domain.h
@@ -0,0 +1,42 @@ +// Copyright 2015 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 COMPONENTS_SCHEDULER_BASE_REAL_TIME_DOMAIN_H_ +#define COMPONENTS_SCHEDULER_BASE_REAL_TIME_DOMAIN_H_ + +#include "base/callback.h" +#include "base/macros.h" +#include "components/scheduler/base/time_domain.h" +#include "components/scheduler/scheduler_export.h" + +namespace scheduler { +class TaskQueueManagerDelegate; + +class SCHEDULER_EXPORT RealTimeDomain : public TimeDomain { + public: + RealTimeDomain(TaskQueueManagerDelegate* task_queue_manager_delegate, + base::Closure do_work_closure); + + // TimeDomain implementation: + LazyNow CreateLazyNow() override; + bool MaybeAdvanceTime() override; + const char* GetName() const override; + + protected: + void RequestWakeup(base::TimeDelta delay) override; + void AsValueIntoInternal( + base::trace_event::TracedValue* state) const override; + + private: + TaskQueueManagerDelegate* task_queue_manager_delegate_; // NOT OWNED + base::Closure do_work_closure_; + + ~RealTimeDomain() override; + + DISALLOW_COPY_AND_ASSIGN(RealTimeDomain); +}; + +} // namespace scheduler + +#endif // COMPONENTS_SCHEDULER_BASE_REAL_TIME_DOMAIN_H_
diff --git a/components/scheduler/base/task_queue.h b/components/scheduler/base/task_queue.h index abc3665..393cc50 100644 --- a/components/scheduler/base/task_queue.h +++ b/components/scheduler/base/task_queue.h
@@ -10,6 +10,7 @@ #include "components/scheduler/scheduler_export.h" namespace scheduler { +class TimeDomain; class SCHEDULER_EXPORT TaskQueue : public base::SingleThreadTaskRunner { public: @@ -102,6 +103,7 @@ should_monitor_quiescence(false), pump_policy(TaskQueue::PumpPolicy::AUTO), wakeup_policy(TaskQueue::WakeupPolicy::CAN_WAKE_OTHER_QUEUES), + time_domain(nullptr), should_notify_observers(true) {} Spec SetShouldMonitorQuiescence(bool should_monitor) { @@ -124,10 +126,16 @@ return *this; } + Spec SetTimeDomain(TimeDomain* domain) { + time_domain = domain; + return *this; + } + const char* name; bool should_monitor_quiescence; TaskQueue::PumpPolicy pump_policy; TaskQueue::WakeupPolicy wakeup_policy; + TimeDomain* time_domain; bool should_notify_observers; }; @@ -173,6 +181,10 @@ virtual void RemoveTaskObserver( base::MessageLoop::TaskObserver* task_observer) = 0; + // Removes the task queue from the previous TimeDomain and adds it to + // |domain|. This is a moderately expensive operation. + virtual void SetTimeDomain(const scoped_refptr<TimeDomain>& domain) = 0; + protected: ~TaskQueue() override {}
diff --git a/components/scheduler/base/task_queue_impl.cc b/components/scheduler/base/task_queue_impl.cc index 6517707..a09e84d 100644 --- a/components/scheduler/base/task_queue_impl.cc +++ b/components/scheduler/base/task_queue_impl.cc
@@ -6,17 +6,19 @@ #include "components/scheduler/base/task_queue_manager.h" #include "components/scheduler/base/task_queue_manager_delegate.h" +#include "components/scheduler/base/time_domain.h" namespace scheduler { namespace internal { TaskQueueImpl::TaskQueueImpl( TaskQueueManager* task_queue_manager, + const scoped_refptr<TimeDomain>& time_domain, const Spec& spec, const char* disabled_by_default_tracing_category, const char* disabled_by_default_verbose_tracing_category) : thread_id_(base::PlatformThread::CurrentId()), - any_thread_(task_queue_manager, spec.pump_policy), + any_thread_(task_queue_manager, spec.pump_policy, time_domain), name_(spec.name), disabled_by_default_tracing_category_( disabled_by_default_tracing_category), @@ -25,7 +27,9 @@ main_thread_only_(task_queue_manager), wakeup_policy_(spec.wakeup_policy), should_monitor_quiescence_(spec.should_monitor_quiescence), - should_notify_observers_(spec.should_notify_observers) {} + should_notify_observers_(spec.should_notify_observers) { + DCHECK(time_domain.get()); +} TaskQueueImpl::~TaskQueueImpl() {} @@ -53,9 +57,13 @@ sequence_num = sequence_number; } -TaskQueueImpl::AnyThread::AnyThread(TaskQueueManager* task_queue_manager, - PumpPolicy pump_policy) - : task_queue_manager(task_queue_manager), pump_policy(pump_policy) {} +TaskQueueImpl::AnyThread::AnyThread( + TaskQueueManager* task_queue_manager, + PumpPolicy pump_policy, + const scoped_refptr<TimeDomain>& time_domain) + : task_queue_manager(task_queue_manager), + pump_policy(pump_policy), + time_domain(time_domain) {} TaskQueueImpl::AnyThread::~AnyThread() {} @@ -70,6 +78,8 @@ base::AutoLock lock(any_thread_lock_); if (!any_thread().task_queue_manager) return; + any_thread().time_domain->UnregisterQueue(this); + any_thread().time_domain = nullptr; any_thread().task_queue_manager->UnregisterTaskQueue(this); any_thread().task_queue_manager = nullptr; @@ -104,7 +114,7 @@ base::AutoLock lock(any_thread_lock_); if (!any_thread().task_queue_manager) return false; - LazyNow lazy_now(any_thread().task_queue_manager->delegate().get()); + LazyNow lazy_now(any_thread().time_domain->CreateLazyNow()); return PostDelayedTaskLocked(&lazy_now, from_here, task, desired_run_time, TaskType::NORMAL); } @@ -117,7 +127,7 @@ base::AutoLock lock(any_thread_lock_); if (!any_thread().task_queue_manager) return false; - LazyNow lazy_now(any_thread().task_queue_manager->delegate().get()); + LazyNow lazy_now(any_thread().time_domain->CreateLazyNow()); base::TimeTicks desired_run_time; if (delay > base::TimeDelta()) desired_run_time = lazy_now.Now() + delay; @@ -143,8 +153,22 @@ any_thread().delayed_task_queue.push(pending_task); TraceQueueSize(true); // Schedule a later call to MoveReadyDelayedTasksToIncomingQueue. - any_thread().task_queue_manager->ScheduleDelayedWork(this, desired_run_time, - lazy_now); + if (base::PlatformThread::CurrentId() == thread_id_) { + any_thread().time_domain->ScheduleDelayedWork(this, desired_run_time, + lazy_now); + } else { + // NOTE posting a delayed task from a different thread is not expected to + // be common. This pathway is less optimal than perhaps it could be + // because it causes two main thread tasks to be run. Should this + // assumption prove to be false in future, we may need to revisit this. + Task thread_hop_task( + FROM_HERE, base::Bind(&TaskQueueImpl::ScheduleDelayedWorkTask, this, + any_thread().time_domain, desired_run_time), + any_thread().task_queue_manager->GetNextSequenceNumber(), true); + thread_hop_task.set_enqueue_order(thread_hop_task.sequence_num); + any_thread().task_queue_manager->DidQueueTask(thread_hop_task); + EnqueueTaskLocked(thread_hop_task); + } return true; } pending_task.set_enqueue_order(pending_task.sequence_num); @@ -152,6 +176,14 @@ return true; } +void TaskQueueImpl::ScheduleDelayedWorkTask( + const scoped_refptr<TimeDomain> time_domain, + base::TimeTicks desired_run_time) { + DCHECK(main_thread_checker_.CalledOnValidThread()); + LazyNow lazy_now(time_domain->CreateLazyNow()); + time_domain->ScheduleDelayedWork(this, desired_run_time, &lazy_now); +} + void TaskQueueImpl::MoveReadyDelayedTasksToIncomingQueue(LazyNow* lazy_now) { base::AutoLock lock(any_thread_lock_); if (!any_thread().task_queue_manager) @@ -222,16 +254,6 @@ return true; } -bool TaskQueueImpl::NextPendingDelayedTaskRunTime( - base::TimeTicks* next_pending_delayed_task) { - base::AutoLock lock(any_thread_lock_); - if (any_thread().delayed_task_queue.empty()) - return false; - *next_pending_delayed_task = - any_thread().delayed_task_queue.top().delayed_run_time; - return true; -} - void TaskQueueImpl::UpdateWorkQueue(LazyNow* lazy_now, bool should_trigger_wakeup, const Task* previous_task) { @@ -241,10 +263,9 @@ return; MoveReadyDelayedTasksToIncomingQueueLocked(lazy_now); std::swap(main_thread_only().work_queue, any_thread().incoming_queue); - // |any_thread().incoming_queue| is now empty so - // TaskQueueManager::UpdateQueues no longer needs to consider - // this queue for reloading. - any_thread().task_queue_manager->UnregisterAsUpdatableTaskQueue(this); + // |any_thread().incoming_queue| is now empty so TimeDomain::UpdateQueues + // no longer needs to consider this queue for reloading. + any_thread().time_domain->UnregisterAsUpdatableTaskQueue(this); if (!main_thread_only().work_queue.empty()) { DCHECK(any_thread().task_queue_manager); any_thread().task_queue_manager->selector_.GetTaskQueueSets()->OnPushQueue( @@ -287,7 +308,7 @@ if (!any_thread().task_queue_manager) return; if (any_thread().incoming_queue.empty()) - any_thread().task_queue_manager->RegisterAsUpdatableTaskQueue(this); + any_thread().time_domain->RegisterAsUpdatableTaskQueue(this); if (any_thread().pump_policy == PumpPolicy::AUTO && any_thread().incoming_queue.empty()) { any_thread().task_queue_manager->MaybePostDoWorkOnMainRunner(); @@ -297,11 +318,17 @@ TraceQueueSize(true); } +// TODO(alexclarke): Consider merging EnqueueTaskLocked & +// EnqueueDelayedTaskLocked. void TaskQueueImpl::EnqueueDelayedTaskLocked(const Task& pending_task) { if (!any_thread().task_queue_manager) return; if (any_thread().incoming_queue.empty()) - any_thread().task_queue_manager->RegisterAsUpdatableTaskQueue(this); + any_thread().time_domain->RegisterAsUpdatableTaskQueue(this); + if (any_thread().pump_policy == PumpPolicy::AUTO && + any_thread().incoming_queue.empty()) { + any_thread().task_queue_manager->MaybePostDoWorkOnMainRunner(); + } // TODO(alexclarke): consider std::move() when allowed. any_thread().incoming_queue.push(pending_task); any_thread().incoming_queue.back().set_enqueue_order( @@ -322,7 +349,7 @@ if (!any_thread().task_queue_manager) return; - LazyNow lazy_now(any_thread().task_queue_manager->delegate().get()); + LazyNow lazy_now(any_thread().time_domain->CreateLazyNow()); MoveReadyDelayedTasksToIncomingQueueLocked(&lazy_now); bool was_empty = main_thread_only().work_queue.empty(); @@ -331,9 +358,9 @@ main_thread_only().work_queue.push(any_thread().incoming_queue.front()); any_thread().incoming_queue.pop(); } - // |incoming_queue| is now empty so TaskQueueManager::UpdateQueues no longer - // needs to consider this queue for reloading. - any_thread().task_queue_manager->UnregisterAsUpdatableTaskQueue(this); + // |incoming_queue| is now empty so TimeDomain::UpdateQueues no longer needs + // to consider this queue for reloading. + any_thread().time_domain->UnregisterAsUpdatableTaskQueue(this); if (!main_thread_only().work_queue.empty()) { if (was_empty) { any_thread() @@ -430,6 +457,7 @@ base::AutoLock lock(any_thread_lock_); state->BeginDictionary(); state->SetString("name", GetName()); + state->SetString("time_domain_name", any_thread().time_domain->GetName()); state->SetString("pump_policy", PumpPolicyToString(any_thread().pump_policy)); state->SetString("wakeup_policy", WakeupPolicyToString(wakeup_policy_)); bool verbose_tracing_enabled = false; @@ -481,6 +509,17 @@ DidProcessTask(pending_task)); } +void TaskQueueImpl::SetTimeDomain( + const scoped_refptr<TimeDomain>& time_domain) { + base::AutoLock lock(any_thread_lock_); + DCHECK(main_thread_checker_.CalledOnValidThread()); + if (time_domain == any_thread().time_domain) + return; + + any_thread().time_domain->MigrateQueue(this, time_domain.get()); + any_thread().time_domain = time_domain; +} + // static void TaskQueueImpl::QueueAsValueInto(const std::queue<Task>& queue, base::trace_event::TracedValue* state) { @@ -516,5 +555,10 @@ state->EndDictionary(); } +size_t TaskQueueImpl::IncomingQueueSizeForTest() const { + base::AutoLock lock(any_thread_lock_); + return any_thread().incoming_queue.size(); +} + } // namespace internal } // namespace scheduler
diff --git a/components/scheduler/base/task_queue_impl.h b/components/scheduler/base/task_queue_impl.h index e75746ce..1f130e124 100644 --- a/components/scheduler/base/task_queue_impl.h +++ b/components/scheduler/base/task_queue_impl.h
@@ -11,18 +11,19 @@ #include "base/threading/thread_checker.h" #include "base/trace_event/trace_event.h" #include "base/trace_event/trace_event_argument.h" -#include "components/scheduler/base/lazy_now.h" #include "components/scheduler/base/task_queue.h" #include "components/scheduler/scheduler_export.h" namespace scheduler { +class LazyNow; +class TimeDomain; class TaskQueueManager; namespace internal { - class SCHEDULER_EXPORT TaskQueueImpl final : public TaskQueue { public: TaskQueueImpl(TaskQueueManager* task_queue_manager, + const scoped_refptr<TimeDomain>& time_domain, const Spec& spec, const char* disabled_by_default_tracing_category, const char* disabled_by_default_verbose_tracing_category); @@ -81,9 +82,7 @@ void AddTaskObserver(base::MessageLoop::TaskObserver* task_observer) override; void RemoveTaskObserver( base::MessageLoop::TaskObserver* task_observer) override; - - bool NextPendingDelayedTaskRunTime( - base::TimeTicks* next_pending_delayed_task); + void SetTimeDomain(const scoped_refptr<TimeDomain>& time_domain) override; void UpdateWorkQueue(LazyNow* lazy_now, bool should_trigger_wakeup, @@ -124,9 +123,8 @@ // Delayed task posted to the underlying run loop, which locks // |any_thread_lock_| and calls MoveReadyDelayedTasksToIncomingQueueLocked to - // process dealyed tasks - // that need to be run now. Thread safe, but in practice it's always called - // from the main thread. + // process dealyed tasks that need to be run now. Thread safe, but in + // practice it's always called from the main thread. void MoveReadyDelayedTasksToIncomingQueue(LazyNow* lazy_now); // Test support functions. These should not be used in production code. @@ -135,6 +133,7 @@ size_t WorkQueueSizeForTest() const { return main_thread_only().work_queue.size(); } + size_t IncomingQueueSizeForTest() const; // Can be called on any thread. static const char* PumpPolicyToString(TaskQueue::PumpPolicy pump_policy); @@ -153,7 +152,9 @@ }; struct AnyThread { - AnyThread(TaskQueueManager* task_queue_manager, PumpPolicy pump_policy); + AnyThread(TaskQueueManager* task_queue_manager, + PumpPolicy pump_policy, + const scoped_refptr<TimeDomain>& time_domain); ~AnyThread(); // TaskQueueManager is maintained in two copies: inside AnyThread and inside @@ -164,10 +165,11 @@ std::queue<Task> incoming_queue; PumpPolicy pump_policy; std::priority_queue<Task> delayed_task_queue; + scoped_refptr<TimeDomain> time_domain; }; struct MainThreadOnly { - explicit MainThreadOnly(TaskQueueManager* task_queue_manager); + MainThreadOnly(TaskQueueManager* task_queue_manager); ~MainThreadOnly(); // Another copy of TaskQueueManager for lock-free access from the main @@ -190,9 +192,10 @@ const base::Closure& task, base::TimeTicks desired_run_time, TaskType task_type); + void ScheduleDelayedWorkTask(const scoped_refptr<TimeDomain> time_domain, + base::TimeTicks desired_run_time); - // Enqueues any delayed tasks which should be run now on the incoming_queue_ - // and calls ScheduleDelayedWorkLocked to ensure future tasks are scheduled. + // Enqueues any delayed tasks which should be run now on the incoming_queue_. // Must be called with |any_thread_lock_| locked. void MoveReadyDelayedTasksToIncomingQueueLocked(LazyNow* lazy_now);
diff --git a/components/scheduler/base/task_queue_manager.cc b/components/scheduler/base/task_queue_manager.cc index 2f55735..4a3602e 100644 --- a/components/scheduler/base/task_queue_manager.cc +++ b/components/scheduler/base/task_queue_manager.cc
@@ -8,16 +8,12 @@ #include <set> #include "base/bind.h" -#include "components/scheduler/base/lazy_now.h" +#include "components/scheduler/base/real_time_domain.h" #include "components/scheduler/base/task_queue_impl.h" #include "components/scheduler/base/task_queue_manager_delegate.h" #include "components/scheduler/base/task_queue_selector.h" #include "components/scheduler/base/task_queue_sets.h" -namespace { -const int64_t kMaxTimeTicks = std::numeric_limits<int64>::max(); -} - namespace scheduler { TaskQueueManager::TaskQueueManager( @@ -46,6 +42,10 @@ base::Bind(&TaskQueueManager::DoWork, weak_factory_.GetWeakPtr(), true); do_work_closure_ = base::Bind(&TaskQueueManager::DoWork, weak_factory_.GetWeakPtr(), false); + + real_time_domain_ = + make_scoped_refptr(new RealTimeDomain(delegate.get(), do_work_closure_)); + RegisterTimeDomain(real_time_domain_); } TaskQueueManager::~TaskQueueManager() { @@ -58,14 +58,28 @@ selector_.SetTaskQueueSelectorObserver(nullptr); } +void TaskQueueManager::RegisterTimeDomain( + const scoped_refptr<TimeDomain>& time_domain) { + time_domains_.insert(time_domain); +} + +void TaskQueueManager::UnregisterTimeDomain( + const scoped_refptr<TimeDomain>& time_domain) { + time_domains_.erase(time_domain); +} + scoped_refptr<internal::TaskQueueImpl> TaskQueueManager::NewTaskQueue( const TaskQueue::Spec& spec) { TRACE_EVENT1(tracing_category_, "TaskQueueManager::NewTaskQueue", "queue_name", spec.name); DCHECK(main_thread_checker_.CalledOnValidThread()); + TimeDomain* time_domain = + spec.time_domain ? spec.time_domain : real_time_domain_.get(); + DCHECK(time_domains_.find(make_scoped_refptr(time_domain)) != + time_domains_.end()); scoped_refptr<internal::TaskQueueImpl> queue( make_scoped_refptr(new internal::TaskQueueImpl( - this, spec, disabled_by_default_tracing_category_, + this, time_domain, spec, disabled_by_default_tracing_category_, disabled_by_default_verbose_tracing_category_))); queues_.insert(queue); selector_.AddQueue(queue.get()); @@ -91,156 +105,16 @@ queues_to_delete_.insert(task_queue); queues_.erase(task_queue); selector_.RemoveQueue(task_queue.get()); - - // We need to remove |task_queue| from delayed_wakeup_multimap_ which is a - // little awkward since it's keyed by time. O(n) running time. - for (DelayedWakeupMultimap::iterator iter = delayed_wakeup_multimap_.begin(); - iter != delayed_wakeup_multimap_.end();) { - if (iter->second == task_queue.get()) { - DelayedWakeupMultimap::iterator temp = iter; - iter++; - // O(1) amortized. - delayed_wakeup_multimap_.erase(temp); - } else { - iter++; - } - } - - // |newly_updatable_| might contain |task_queue|, we use - // MoveNewlyUpdatableQueuesIntoUpdatableQueueSet to flush it out. - MoveNewlyUpdatableQueuesIntoUpdatableQueueSet(); - updatable_queue_set_.erase(task_queue.get()); -} - -base::TimeTicks TaskQueueManager::NextPendingDelayedTaskRunTime() { - DCHECK(main_thread_checker_.CalledOnValidThread()); - bool found_pending_task = false; - base::TimeTicks next_pending_delayed_task( - base::TimeTicks::FromInternalValue(kMaxTimeTicks)); - for (auto& queue : queues_) { - base::TimeTicks queues_next_pending_delayed_task; - if (queue->NextPendingDelayedTaskRunTime( - &queues_next_pending_delayed_task)) { - found_pending_task = true; - next_pending_delayed_task = - std::min(next_pending_delayed_task, queues_next_pending_delayed_task); - } - } - - if (!found_pending_task) - return base::TimeTicks(); - - DCHECK_NE(next_pending_delayed_task, - base::TimeTicks::FromInternalValue(kMaxTimeTicks)); - return next_pending_delayed_task; -} - -void TaskQueueManager::RegisterAsUpdatableTaskQueue( - internal::TaskQueueImpl* queue) { - base::AutoLock lock(newly_updatable_lock_); - newly_updatable_.push_back(queue); -} - -void TaskQueueManager::UnregisterAsUpdatableTaskQueue( - internal::TaskQueueImpl* queue) { - DCHECK(main_thread_checker_.CalledOnValidThread()); - MoveNewlyUpdatableQueuesIntoUpdatableQueueSet(); -#ifndef NDEBUG - { - base::AutoLock lock(newly_updatable_lock_); - DCHECK(!(updatable_queue_set_.find(queue) == updatable_queue_set_.end() && - std::find(newly_updatable_.begin(), newly_updatable_.end(), - queue) != newly_updatable_.end())); - } -#endif - updatable_queue_set_.erase(queue); -} - -void TaskQueueManager::MoveNewlyUpdatableQueuesIntoUpdatableQueueSet() { - DCHECK(main_thread_checker_.CalledOnValidThread()); - base::AutoLock lock(newly_updatable_lock_); - while (!newly_updatable_.empty()) { - updatable_queue_set_.insert(newly_updatable_.back()); - newly_updatable_.pop_back(); - } } void TaskQueueManager::UpdateWorkQueues( bool should_trigger_wakeup, const internal::TaskQueueImpl::Task* previous_task) { - DCHECK(main_thread_checker_.CalledOnValidThread()); TRACE_EVENT0(disabled_by_default_tracing_category_, "TaskQueueManager::UpdateWorkQueues"); - internal::LazyNow lazy_now(delegate().get()); - // Move any ready delayed tasks into the incomming queues. - WakeupReadyDelayedQueues(&lazy_now); - - MoveNewlyUpdatableQueuesIntoUpdatableQueueSet(); - - auto iter = updatable_queue_set_.begin(); - while (iter != updatable_queue_set_.end()) { - internal::TaskQueueImpl* queue = *iter++; - // NOTE Update work queue may erase itself from |updatable_queue_set_|. - // This is fine, erasing an element won't invalidate any interator, as long - // as the iterator isn't the element being delated. - if (queue->work_queue().empty()) - queue->UpdateWorkQueue(&lazy_now, should_trigger_wakeup, previous_task); - } -} - -void TaskQueueManager::ScheduleDelayedWorkTask( - scoped_refptr<internal::TaskQueueImpl> queue, - base::TimeTicks delayed_run_time) { - internal::LazyNow lazy_now(delegate().get()); - ScheduleDelayedWork(queue.get(), delayed_run_time, &lazy_now); -} - -void TaskQueueManager::ScheduleDelayedWork(internal::TaskQueueImpl* queue, - base::TimeTicks delayed_run_time, - internal::LazyNow* lazy_now) { - if (!delegate_->BelongsToCurrentThread()) { - // NOTE posting a delayed task from a different thread is not expected to be - // common. This pathway is less optimal than perhaps it could be because - // it causes two main thread tasks to be run. Should this assumption prove - // to be false in future, we may need to revisit this. - delegate_->PostTask( - FROM_HERE, base::Bind(&TaskQueueManager::ScheduleDelayedWorkTask, - weak_factory_.GetWeakPtr(), - scoped_refptr<internal::TaskQueueImpl>(queue), - delayed_run_time)); - return; - } - - // Make sure there's one (and only one) task posted to |delegate_| - // to call |DelayedDoWork| at |delayed_run_time|. - if (delayed_wakeup_multimap_.find(delayed_run_time) == - delayed_wakeup_multimap_.end()) { - base::TimeDelta delay = - std::max(base::TimeDelta(), delayed_run_time - lazy_now->Now()); - delegate_->PostDelayedTask(FROM_HERE, do_work_closure_, delay); - } - delayed_wakeup_multimap_.insert(std::make_pair(delayed_run_time, queue)); -} - -void TaskQueueManager::WakeupReadyDelayedQueues(internal::LazyNow* lazy_now) { - // Wake up any queues with pending delayed work. Note std::multipmap stores - // the elements sorted by key, so the begin() iterator points to the earliest - // queue to wakeup. - std::set<internal::TaskQueueImpl*> dedup_set; - while (!delayed_wakeup_multimap_.empty()) { - DelayedWakeupMultimap::iterator next_wakeup = - delayed_wakeup_multimap_.begin(); - if (next_wakeup->first > lazy_now->Now()) - break; - // A queue could have any number of delayed tasks pending so it's worthwhile - // deduping calls to MoveReadyDelayedTasksToIncomingQueue since it takes a - // lock. NOTE the order in which these are called matters since the order - // in which EnqueueTaskLocks is called is respected when choosing which - // queue to execute a task from. - if (dedup_set.insert(next_wakeup->second).second) - next_wakeup->second->MoveReadyDelayedTasksToIncomingQueue(lazy_now); - delayed_wakeup_multimap_.erase(next_wakeup); + for (const scoped_refptr<TimeDomain>& time_domain : time_domains_) { + time_domain->UpdateWorkQueues(should_trigger_wakeup, previous_task); } } @@ -303,7 +177,7 @@ // TODO(alexclarke): Consider refactoring the above loop to terminate only // when there's no more work left to be done, rather than posting a // continuation task. - if (!selector_.EnabledWorkQueuesEmpty()) { + if (!selector_.EnabledWorkQueuesEmpty() || TryAdvanceTimeDomains()) { MaybePostDoWorkOnMainRunner(); } else { // Tell the task runner we have no more work. @@ -311,6 +185,14 @@ } } +bool TaskQueueManager::TryAdvanceTimeDomains() { + bool can_advance = false; + for (const scoped_refptr<TimeDomain>& time_domain : time_domains_) { + can_advance |= time_domain->MaybeAdvanceTime(); + } + return can_advance; +} + bool TaskQueueManager::SelectQueueToService( internal::TaskQueueImpl** out_queue) { bool should_run = selector_.SelectQueueToService(out_queue); @@ -426,9 +308,9 @@ if (should_run) state->SetString("selected_queue", selected_queue->GetName()); - state->BeginArray("updatable_queue_set"); - for (auto& queue : updatable_queue_set_) - state->AppendString(queue->GetName()); + state->BeginArray("time_domains"); + for (auto& time_domain : time_domains_) + time_domain->AsValueInto(state.get()); state->EndArray(); return state; }
diff --git a/components/scheduler/base/task_queue_manager.h b/components/scheduler/base/task_queue_manager.h index 002c4bc..f6af854 100644 --- a/components/scheduler/base/task_queue_manager.h +++ b/components/scheduler/base/task_queue_manager.h
@@ -30,10 +30,12 @@ namespace scheduler { namespace internal { -class LazyNow; class TaskQueueImpl; } // namespace internal +class LazyNow; +class RealTimeDomain; +class TimeDomain; class TaskQueueManagerDelegate; // The task queue manager provides N task queues and a selector interface for @@ -60,12 +62,6 @@ const char* disabled_by_default_verbose_tracing_category); ~TaskQueueManager() override; - // Returns the time of the next pending delayed task in any queue. Ignores - // any delayed tasks whose delay has expired. Returns a null TimeTicks object - // if no tasks are pending. NOTE this is somewhat expensive since every queue - // will get locked. - base::TimeTicks NextPendingDelayedTaskRunTime(); - // Set the number of tasks executed in a single invocation of the task queue // manager. Increasing the batch size can reduce the overhead of yielding // back to the main message loop -- at the cost of potentially delaying other @@ -103,8 +99,16 @@ // Returns the delegate used by the TaskQueueManager. const scoped_refptr<TaskQueueManagerDelegate>& delegate() const; + // Time domains must be registered for the task queues to get updated. + void RegisterTimeDomain(const scoped_refptr<TimeDomain>& time_domain); + void UnregisterTimeDomain(const scoped_refptr<TimeDomain>& time_domain); + + const scoped_refptr<RealTimeDomain>& real_time_domain() const { + return real_time_domain_; + } + private: - friend class internal::LazyNow; + friend class LazyNow; friend class internal::TaskQueueImpl; friend class TaskQueueManagerTest; @@ -166,34 +170,14 @@ int GetNextSequenceNumber(); + bool TryAdvanceTimeDomains(); + scoped_refptr<base::trace_event::ConvertableToTraceFormat> AsValueWithSelectorResult(bool should_run, internal::TaskQueueImpl* selected_queue) const; - // Causes DoWork to start calling UpdateWorkQueue for |queue|. Can be called - // from any thread. - void RegisterAsUpdatableTaskQueue(internal::TaskQueueImpl* queue); - - // Prevents DoWork from calling UpdateWorkQueue for |queue|. Must be called - // from the thread the TaskQueueManager was created on. - void UnregisterAsUpdatableTaskQueue(internal::TaskQueueImpl* queue); - - // Schedule a call to DoWork at |delayed_run_time| which indirectly calls - // TaskQueueImpl::MoveReadyDelayedTasksToIncomingQueue for |queue|. - // Can be called from any thread. - void ScheduleDelayedWork(internal::TaskQueueImpl* queue, - base::TimeTicks delayed_run_time, - internal::LazyNow* lazy_now); - - // Function calling ScheduleDelayedWork that's suitable for use in base::Bind. - void ScheduleDelayedWorkTask(scoped_refptr<internal::TaskQueueImpl> queue, - base::TimeTicks delayed_run_time); - - // Call TaskQueueImpl::MoveReadyDelayedTasksToIncomingQueue for each - // registered queue for which the delay has elapsed. - void WakeupReadyDelayedQueues(internal::LazyNow* lazy_now); - - void MoveNewlyUpdatableQueuesIntoUpdatableQueueSet(); + std::set<scoped_refptr<TimeDomain>> time_domains_; + scoped_refptr<RealTimeDomain> real_time_domain_; std::set<scoped_refptr<internal::TaskQueueImpl>> queues_; @@ -201,19 +185,6 @@ // raw pointers and doesn't expect the rug to be pulled out from underneath. std::set<scoped_refptr<internal::TaskQueueImpl>> queues_to_delete_; - // This lock guards only |newly_updatable_|. It's not expected to be heavily - // contended. - base::Lock newly_updatable_lock_; - std::vector<internal::TaskQueueImpl*> newly_updatable_; - - // Set of task queues with avaliable work on the incoming queue. This should - // only be accessed from the main thread. - std::set<internal::TaskQueueImpl*> updatable_queue_set_; - - typedef std::multimap<base::TimeTicks, internal::TaskQueueImpl*> - DelayedWakeupMultimap; - - DelayedWakeupMultimap delayed_wakeup_multimap_; base::AtomicSequenceNumber task_sequence_num_; base::debug::TaskAnnotator task_annotator_; @@ -241,6 +212,7 @@ Observer* observer_; // NOT OWNED scoped_refptr<DeletionSentinel> deletion_sentinel_; + scoped_refptr<TimeDomain> time_domain_; base::WeakPtrFactory<TaskQueueManager> weak_factory_; DISALLOW_COPY_AND_ASSIGN(TaskQueueManager);
diff --git a/components/scheduler/base/task_queue_manager_unittest.cc b/components/scheduler/base/task_queue_manager_unittest.cc index 1c46c69..d5ad8e5 100644 --- a/components/scheduler/base/task_queue_manager_unittest.cc +++ b/components/scheduler/base/task_queue_manager_unittest.cc
@@ -10,12 +10,14 @@ #include "base/test/simple_test_tick_clock.h" #include "base/threading/thread.h" #include "cc/test/ordered_simple_task_runner.h" +#include "components/scheduler/base/real_time_domain.h" #include "components/scheduler/base/task_queue_impl.h" #include "components/scheduler/base/task_queue_manager_delegate_for_test.h" #include "components/scheduler/base/task_queue_selector.h" #include "components/scheduler/base/task_queue_sets.h" #include "components/scheduler/base/test_always_fail_time_source.h" #include "components/scheduler/base/test_time_source.h" +#include "components/scheduler/base/virtual_time_domain.h" #include "testing/gmock/include/gmock/gmock.h" using testing::ElementsAre; @@ -71,6 +73,7 @@ } void InitializeWithRealMessageLoop(size_t num_queues) { + now_src_.reset(new base::SimpleTestTickClock()); message_loop_.reset(new base::MessageLoop()); manager_ = make_scoped_ptr(new TaskQueueManager( MessageLoopTaskRunner::Create( @@ -897,47 +900,49 @@ EXPECT_TRUE(runners_[0]->RunsTasksOnCurrentThread()); } -TEST_F(TaskQueueManagerTest, NextPendingDelayedTaskRunTime) { +TEST_F(TaskQueueManagerTest, TimeDomain_NextScheduledRunTime) { Initialize(2u); now_src_->Advance(base::TimeDelta::FromMicroseconds(10000)); // With no delayed tasks. - EXPECT_TRUE(manager_->NextPendingDelayedTaskRunTime().is_null()); + base::TimeTicks run_time; + EXPECT_FALSE(manager_->real_time_domain()->NextScheduledRunTime(&run_time)); // With a non-delayed task. runners_[0]->PostTask(FROM_HERE, base::Bind(&NopTask)); - EXPECT_TRUE(manager_->NextPendingDelayedTaskRunTime().is_null()); + EXPECT_FALSE(manager_->real_time_domain()->NextScheduledRunTime(&run_time)); // With a delayed task. base::TimeDelta expected_delay = base::TimeDelta::FromMilliseconds(50); runners_[0]->PostDelayedTask(FROM_HERE, base::Bind(&NopTask), expected_delay); - EXPECT_EQ(now_src_->NowTicks() + expected_delay, - manager_->NextPendingDelayedTaskRunTime()); + EXPECT_TRUE(manager_->real_time_domain()->NextScheduledRunTime(&run_time)); + EXPECT_EQ(now_src_->NowTicks() + expected_delay, run_time); // With another delayed task in the same queue with a longer delay. runners_[0]->PostDelayedTask(FROM_HERE, base::Bind(&NopTask), base::TimeDelta::FromMilliseconds(100)); - EXPECT_EQ(now_src_->NowTicks() + expected_delay, - manager_->NextPendingDelayedTaskRunTime()); + EXPECT_TRUE(manager_->real_time_domain()->NextScheduledRunTime(&run_time)); + EXPECT_EQ(now_src_->NowTicks() + expected_delay, run_time); // With another delayed task in the same queue with a shorter delay. expected_delay = base::TimeDelta::FromMilliseconds(20); runners_[0]->PostDelayedTask(FROM_HERE, base::Bind(&NopTask), expected_delay); - EXPECT_EQ(now_src_->NowTicks() + expected_delay, - manager_->NextPendingDelayedTaskRunTime()); + EXPECT_TRUE(manager_->real_time_domain()->NextScheduledRunTime(&run_time)); + EXPECT_EQ(now_src_->NowTicks() + expected_delay, run_time); // With another delayed task in a different queue with a shorter delay. expected_delay = base::TimeDelta::FromMilliseconds(10); runners_[1]->PostDelayedTask(FROM_HERE, base::Bind(&NopTask), expected_delay); - EXPECT_EQ(now_src_->NowTicks() + expected_delay, - manager_->NextPendingDelayedTaskRunTime()); + EXPECT_TRUE(manager_->real_time_domain()->NextScheduledRunTime(&run_time)); + EXPECT_EQ(now_src_->NowTicks() + expected_delay, run_time); // Test it updates as time progresses now_src_->Advance(expected_delay); - EXPECT_EQ(now_src_->NowTicks(), manager_->NextPendingDelayedTaskRunTime()); + EXPECT_TRUE(manager_->real_time_domain()->NextScheduledRunTime(&run_time)); + EXPECT_EQ(now_src_->NowTicks(), run_time); } -TEST_F(TaskQueueManagerTest, NextPendingDelayedTaskRunTime_MultipleQueues) { +TEST_F(TaskQueueManagerTest, TimeDomain_NextScheduledRunTime_MultipleQueues) { Initialize(3u); base::TimeDelta delay1 = base::TimeDelta::FromMilliseconds(50); @@ -946,9 +951,11 @@ runners_[0]->PostDelayedTask(FROM_HERE, base::Bind(&NopTask), delay1); runners_[1]->PostDelayedTask(FROM_HERE, base::Bind(&NopTask), delay2); runners_[2]->PostDelayedTask(FROM_HERE, base::Bind(&NopTask), delay3); + runners_[0]->PostTask(FROM_HERE, base::Bind(&NopTask)); - EXPECT_EQ(now_src_->NowTicks() + delay2, - manager_->NextPendingDelayedTaskRunTime()); + base::TimeTicks run_time; + EXPECT_TRUE(manager_->real_time_domain()->NextScheduledRunTime(&run_time)); + EXPECT_EQ(now_src_->NowTicks() + delay2, run_time); } TEST_F(TaskQueueManagerTest, DeleteTaskQueueManagerInsideATask) { @@ -1376,4 +1383,79 @@ EXPECT_THAT(log, ElementsAre(false, false, true)); } +TEST_F(TaskQueueManagerTest, TimeDomainsAreIndependant) { + Initialize(2u); + + base::TimeTicks start_time = manager_->delegate()->NowTicks(); + scoped_refptr<VirtualTimeDomain> domain_a(new VirtualTimeDomain(start_time)); + scoped_refptr<VirtualTimeDomain> domain_b(new VirtualTimeDomain(start_time)); + manager_->RegisterTimeDomain(domain_a); + manager_->RegisterTimeDomain(domain_b); + runners_[0]->SetTimeDomain(domain_a); + runners_[1]->SetTimeDomain(domain_b); + + std::vector<int> run_order; + runners_[0]->PostDelayedTask(FROM_HERE, base::Bind(&TestTask, 1, &run_order), + base::TimeDelta::FromMilliseconds(10)); + runners_[0]->PostDelayedTask(FROM_HERE, base::Bind(&TestTask, 2, &run_order), + base::TimeDelta::FromMilliseconds(20)); + runners_[0]->PostDelayedTask(FROM_HERE, base::Bind(&TestTask, 3, &run_order), + base::TimeDelta::FromMilliseconds(30)); + + runners_[1]->PostDelayedTask(FROM_HERE, base::Bind(&TestTask, 4, &run_order), + base::TimeDelta::FromMilliseconds(10)); + runners_[1]->PostDelayedTask(FROM_HERE, base::Bind(&TestTask, 5, &run_order), + base::TimeDelta::FromMilliseconds(20)); + runners_[1]->PostDelayedTask(FROM_HERE, base::Bind(&TestTask, 6, &run_order), + base::TimeDelta::FromMilliseconds(30)); + + domain_b->AdvanceTo(start_time + base::TimeDelta::FromMilliseconds(50)); + + test_task_runner_->RunUntilIdle(); + EXPECT_THAT(run_order, ElementsAre(4, 5, 6)); + + domain_a->AdvanceTo(start_time + base::TimeDelta::FromMilliseconds(50)); + + test_task_runner_->RunUntilIdle(); + EXPECT_THAT(run_order, ElementsAre(4, 5, 6, 1, 2, 3)); + + manager_->UnregisterTimeDomain(domain_a); + manager_->UnregisterTimeDomain(domain_b); +} + +TEST_F(TaskQueueManagerTest, TimeDomainMigration) { + Initialize(1u); + + base::TimeTicks start_time = manager_->delegate()->NowTicks(); + scoped_refptr<VirtualTimeDomain> domain_a(new VirtualTimeDomain(start_time)); + manager_->RegisterTimeDomain(domain_a); + runners_[0]->SetTimeDomain(domain_a); + + std::vector<int> run_order; + runners_[0]->PostDelayedTask(FROM_HERE, base::Bind(&TestTask, 1, &run_order), + base::TimeDelta::FromMilliseconds(10)); + runners_[0]->PostDelayedTask(FROM_HERE, base::Bind(&TestTask, 2, &run_order), + base::TimeDelta::FromMilliseconds(20)); + runners_[0]->PostDelayedTask(FROM_HERE, base::Bind(&TestTask, 3, &run_order), + base::TimeDelta::FromMilliseconds(30)); + runners_[0]->PostDelayedTask(FROM_HERE, base::Bind(&TestTask, 4, &run_order), + base::TimeDelta::FromMilliseconds(40)); + + domain_a->AdvanceTo(start_time + base::TimeDelta::FromMilliseconds(20)); + test_task_runner_->RunUntilIdle(); + EXPECT_THAT(run_order, ElementsAre(1, 2)); + + scoped_refptr<VirtualTimeDomain> domain_b(new VirtualTimeDomain(start_time)); + manager_->RegisterTimeDomain(domain_b); + runners_[0]->SetTimeDomain(domain_b); + + domain_b->AdvanceTo(start_time + base::TimeDelta::FromMilliseconds(50)); + + test_task_runner_->RunUntilIdle(); + EXPECT_THAT(run_order, ElementsAre(1, 2, 3, 4)); + + manager_->UnregisterTimeDomain(domain_a); + manager_->UnregisterTimeDomain(domain_b); +} + } // namespace scheduler
diff --git a/components/scheduler/base/task_queue_selector_unittest.cc b/components/scheduler/base/task_queue_selector_unittest.cc index 5f78459..382a440d 100644 --- a/components/scheduler/base/task_queue_selector_unittest.cc +++ b/components/scheduler/base/task_queue_selector_unittest.cc
@@ -9,6 +9,7 @@ #include "base/pending_task.h" #include "components/scheduler/base/task_queue_impl.h" #include "components/scheduler/base/task_queue_sets.h" +#include "components/scheduler/base/virtual_time_domain.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -74,10 +75,12 @@ protected: void SetUp() final { + virtual_time_domain_ = make_scoped_refptr<VirtualTimeDomain>( + new VirtualTimeDomain(base::TimeTicks())); for (size_t i = 0; i < kTaskQueueCount; i++) { - scoped_refptr<TaskQueueImpl> task_queue = - make_scoped_refptr(new TaskQueueImpl( - nullptr, TaskQueue::Spec("test queue"), "test", "test")); + scoped_refptr<TaskQueueImpl> task_queue = make_scoped_refptr( + new TaskQueueImpl(nullptr, virtual_time_domain_, + TaskQueue::Spec("test queue"), "test", "test")); selector_.AddQueue(task_queue.get()); task_queues_.push_back(task_queue); } @@ -90,6 +93,7 @@ const size_t kTaskQueueCount = 5; base::Closure test_closure_; TaskQueueSelector selector_; + scoped_refptr<VirtualTimeDomain> virtual_time_domain_; std::vector<scoped_refptr<TaskQueueImpl>> task_queues_; std::map<TaskQueueImpl*, size_t> queue_to_index_map_; };
diff --git a/components/scheduler/base/task_queue_sets_unittest.cc b/components/scheduler/base/task_queue_sets_unittest.cc index 2daf205..568c0d1 100644 --- a/components/scheduler/base/task_queue_sets_unittest.cc +++ b/components/scheduler/base/task_queue_sets_unittest.cc
@@ -5,14 +5,21 @@ #include "components/scheduler/base/task_queue_sets.h" #include "components/scheduler/base/task_queue_impl.h" +#include "components/scheduler/base/virtual_time_domain.h" #include "testing/gmock/include/gmock/gmock.h" namespace scheduler { +class TimeDomain; + namespace internal { class TaskQueueSetsTest : public testing::Test { public: - void SetUp() override { task_queue_sets_.reset(new TaskQueueSets(kNumSets)); } + void SetUp() override { + virtual_time_domain_ = make_scoped_refptr<VirtualTimeDomain>( + new VirtualTimeDomain(base::TimeTicks())); + task_queue_sets_.reset(new TaskQueueSets(kNumSets)); + } protected: enum { @@ -22,7 +29,8 @@ TaskQueueImpl* NewTaskQueue(const char* queue_name) { scoped_refptr<internal::TaskQueueImpl> queue = make_scoped_refptr(new internal::TaskQueueImpl( - nullptr, TaskQueue::Spec(queue_name), "test", "test")); + nullptr, virtual_time_domain_, TaskQueue::Spec(queue_name), "test", + "test")); task_queues_.push_back(queue); return queue.get(); } @@ -33,6 +41,7 @@ return fake_task; } + scoped_refptr<VirtualTimeDomain> virtual_time_domain_; std::vector<scoped_refptr<internal::TaskQueueImpl>> task_queues_; scoped_ptr<TaskQueueSets> task_queue_sets_; };
diff --git a/components/scheduler/base/test_time_source.cc b/components/scheduler/base/test_time_source.cc index 7c620ad..6bbe83ba 100644 --- a/components/scheduler/base/test_time_source.cc +++ b/components/scheduler/base/test_time_source.cc
@@ -7,7 +7,9 @@ namespace scheduler { TestTimeSource::TestTimeSource(base::SimpleTestTickClock* time_source) - : time_source_(time_source) {} + : time_source_(time_source) { + DCHECK(time_source_); +} TestTimeSource::~TestTimeSource() {}
diff --git a/components/scheduler/base/time_domain.cc b/components/scheduler/base/time_domain.cc new file mode 100644 index 0000000..825812e --- /dev/null +++ b/components/scheduler/base/time_domain.cc
@@ -0,0 +1,178 @@ +// Copyright 2015 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 "components/scheduler/base/time_domain.h" + +#include <set> + +#include "components/scheduler/base/task_queue_impl.h" +#include "components/scheduler/base/task_queue_manager_delegate.h" +#include "components/scheduler/scheduler_export.h" + +namespace scheduler { + +TimeDomain::TimeDomain() : weak_factory_(this) {} + +TimeDomain::~TimeDomain() {} + +void TimeDomain::UnregisterQueue(internal::TaskQueueImpl* queue) { + // We need to remove |task_queue| from delayed_wakeup_multimap_ which is a + // little awkward since it's keyed by time. O(n) running time. + for (DelayedWakeupMultimap::iterator iter = delayed_wakeup_multimap_.begin(); + iter != delayed_wakeup_multimap_.end();) { + if (iter->second == queue) { + DelayedWakeupMultimap::iterator temp = iter; + iter++; + // O(1) amortized. + delayed_wakeup_multimap_.erase(temp); + } else { + iter++; + } + } + + // |newly_updatable_| might contain |task_queue|, we use + // MoveNewlyUpdatableQueuesIntoUpdatableQueueSet to flush it out. + MoveNewlyUpdatableQueuesIntoUpdatableQueueSet(); + updatable_queue_set_.erase(queue); +} + +void TimeDomain::MigrateQueue(internal::TaskQueueImpl* queue, + TimeDomain* destination_time_domain) { + LazyNow destination_lazy_now = destination_time_domain->CreateLazyNow(); + // We need to remove |task_queue| from delayed_wakeup_multimap_ which is a + // little awkward since it's keyed by time. O(n) running time. + for (DelayedWakeupMultimap::iterator iter = delayed_wakeup_multimap_.begin(); + iter != delayed_wakeup_multimap_.end();) { + if (iter->second == queue) { + destination_time_domain->ScheduleDelayedWork(queue, iter->first, + &destination_lazy_now); + DelayedWakeupMultimap::iterator temp = iter; + iter++; + // O(1) amortized. + delayed_wakeup_multimap_.erase(temp); + } else { + iter++; + } + } + + // |newly_updatable_| might contain |queue|, we use + // MoveNewlyUpdatableQueuesIntoUpdatableQueueSet to flush it out. + MoveNewlyUpdatableQueuesIntoUpdatableQueueSet(); + updatable_queue_set_.erase(queue); +} + +void TimeDomain::ScheduleDelayedWork(internal::TaskQueueImpl* queue, + base::TimeTicks delayed_run_time, + LazyNow* lazy_now) { + DCHECK(main_thread_checker_.CalledOnValidThread()); + // Dedupe wakeups. + if (delayed_wakeup_multimap_.find(delayed_run_time) == + delayed_wakeup_multimap_.end()) { + base::TimeDelta delay = + std::max(base::TimeDelta(), delayed_run_time - lazy_now->Now()); + RequestWakeup(delay); + } + delayed_wakeup_multimap_.insert(std::make_pair(delayed_run_time, queue)); +} + +void TimeDomain::RegisterAsUpdatableTaskQueue(internal::TaskQueueImpl* queue) { + base::AutoLock lock(newly_updatable_lock_); + newly_updatable_.push_back(queue); +} + +void TimeDomain::UnregisterAsUpdatableTaskQueue( + internal::TaskQueueImpl* queue) { + DCHECK(main_thread_checker_.CalledOnValidThread()); + MoveNewlyUpdatableQueuesIntoUpdatableQueueSet(); +#ifndef NDEBUG + { + base::AutoLock lock(newly_updatable_lock_); + DCHECK(!(updatable_queue_set_.find(queue) == updatable_queue_set_.end() && + std::find(newly_updatable_.begin(), newly_updatable_.end(), + queue) != newly_updatable_.end())); + } +#endif + updatable_queue_set_.erase(queue); +} + +void TimeDomain::UpdateWorkQueues( + bool should_trigger_wakeup, + const internal::TaskQueueImpl::Task* previous_task) { + DCHECK(main_thread_checker_.CalledOnValidThread()); + LazyNow lazy_now(CreateLazyNow()); + + // Move any ready delayed tasks into the incomming queues. + WakeupReadyDelayedQueues(&lazy_now); + + MoveNewlyUpdatableQueuesIntoUpdatableQueueSet(); + + auto iter = updatable_queue_set_.begin(); + while (iter != updatable_queue_set_.end()) { + internal::TaskQueueImpl* queue = *iter++; + // NOTE Update work queue may erase itself from |updatable_queue_set_|. + // This is fine, erasing an element won't invalidate any interator, as long + // as the iterator isn't the element being delated. + if (queue->work_queue().empty()) + queue->UpdateWorkQueue(&lazy_now, should_trigger_wakeup, previous_task); + } +} + +void TimeDomain::MoveNewlyUpdatableQueuesIntoUpdatableQueueSet() { + DCHECK(main_thread_checker_.CalledOnValidThread()); + base::AutoLock lock(newly_updatable_lock_); + while (!newly_updatable_.empty()) { + updatable_queue_set_.insert(newly_updatable_.back()); + newly_updatable_.pop_back(); + } +} + +void TimeDomain::WakeupReadyDelayedQueues(LazyNow* lazy_now) { + // Wake up any queues with pending delayed work. Note std::multipmap stores + // the elements sorted by key, so the begin() iterator points to the earliest + // queue to wakeup. + std::set<internal::TaskQueueImpl*> dedup_set; + while (!delayed_wakeup_multimap_.empty()) { + DelayedWakeupMultimap::iterator next_wakeup = + delayed_wakeup_multimap_.begin(); + if (next_wakeup->first > lazy_now->Now()) + break; + // A queue could have any number of delayed tasks pending so it's worthwhile + // deduping calls to MoveReadyDelayedTasksToIncomingQueue since it takes a + // lock. NOTE the order in which these are called matters since the order + // in which EnqueueTaskLocks is called is respected when choosing which + // queue to execute a task from. + if (dedup_set.insert(next_wakeup->second).second) + next_wakeup->second->MoveReadyDelayedTasksToIncomingQueue(lazy_now); + delayed_wakeup_multimap_.erase(next_wakeup); + } +} + +bool TimeDomain::NextScheduledRunTime(base::TimeTicks* out_time) const { + if (delayed_wakeup_multimap_.empty()) + return false; + + *out_time = delayed_wakeup_multimap_.begin()->first; + return true; +} + +bool TimeDomain::NextScheduledTaskQueue(TaskQueue** out_task_queue) const { + if (delayed_wakeup_multimap_.empty()) + return false; + + *out_task_queue = delayed_wakeup_multimap_.begin()->second; + return true; +} + +void TimeDomain::AsValueInto(base::trace_event::TracedValue* state) const { + state->BeginDictionary(); + state->SetString("name", GetName()); + state->BeginArray("updatable_queue_set"); + for (auto& queue : updatable_queue_set_) + state->AppendString(queue->GetName()); + state->EndArray(); + AsValueIntoInternal(state); + state->EndDictionary(); +} + +} // namespace scheduler
diff --git a/components/scheduler/base/time_domain.h b/components/scheduler/base/time_domain.h new file mode 100644 index 0000000..b01f05d9 --- /dev/null +++ b/components/scheduler/base/time_domain.h
@@ -0,0 +1,119 @@ +// Copyright 2015 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 COMPONENTS_SCHEDULER_BASE_TIME_DOMAIN_H_ +#define COMPONENTS_SCHEDULER_BASE_TIME_DOMAIN_H_ + +#include <map> + +#include "base/macros.h" +#include "base/memory/ref_counted.h" +#include "base/memory/weak_ptr.h" +#include "base/time/time.h" +#include "components/scheduler/base/lazy_now.h" +#include "components/scheduler/base/task_queue_impl.h" +#include "components/scheduler/scheduler_export.h" + +namespace scheduler { +namespace internal { +class TaskQueueImpl; +} // internal +class TaskQueueManager; + +class SCHEDULER_EXPORT TimeDomain : public base::RefCounted<TimeDomain> { + public: + TimeDomain(); + + // Returns a LazyNow that evaluate this TimeDomain's Now. Can be called from + // any thread. + // TODO(alexclarke): Make this main thread only. + virtual LazyNow CreateLazyNow() = 0; + + // Some TimeDomains support virtual time, this method tells us to advance time + // if possible and return true if time was advanced. + virtual bool MaybeAdvanceTime() = 0; + + // Returns the name of this time domain for tracing. + virtual const char* GetName() const = 0; + + // If there is a scheduled delayed task, |out_time| is set to the scheduled + // runtime for the next one and it returns true. Returns false otherwise. + bool NextScheduledRunTime(base::TimeTicks* out_time) const; + + protected: + friend class internal::TaskQueueImpl; + friend class TaskQueueManager; + friend class base::RefCounted<TimeDomain>; + + virtual ~TimeDomain(); + + void AsValueInto(base::trace_event::TracedValue* state) const; + + // Migrates |queue| from this time domain to |destination_time_domain|. + void MigrateQueue(internal::TaskQueueImpl* queue, + TimeDomain* destination_time_domain); + + // If there is a scheduled delayed task, |out_task_queue| is set to the queue + // the next task was posted to and it returns true. Returns false otherwise. + bool NextScheduledTaskQueue(TaskQueue** out_task_queue) const; + + // Adds |queue| to the set of task queues that UpdateWorkQueues calls + // UpdateWorkQueue on. + void RegisterAsUpdatableTaskQueue(internal::TaskQueueImpl* queue); + + // Schedules a call to TaskQueueImpl::MoveReadyDelayedTasksToIncomingQueue + // when this TimeDomain reaches |delayed_run_time|. + void ScheduleDelayedWork(internal::TaskQueueImpl* queue, + base::TimeTicks delayed_run_time, + LazyNow* lazy_now); + + // Removes |queue| from the set of task queues that UpdateWorkQueues calls + // UpdateWorkQueue on. + void UnregisterAsUpdatableTaskQueue(internal::TaskQueueImpl* queue); + + // Removes |queue| from all internal data structures. + void UnregisterQueue(internal::TaskQueueImpl* queue); + + // Updates active queues associated with this TimeDomain. + void UpdateWorkQueues(bool should_trigger_wakeup, + const internal::TaskQueueImpl::Task* previous_task); + + // The implementaion will secedule task processing to run with |delay| with + // respect to the TimeDomain's time source. + virtual void RequestWakeup(base::TimeDelta delay) = 0; + + // For implementation specific tracing. + virtual void AsValueIntoInternal( + base::trace_event::TracedValue* state) const = 0; + + // Call TaskQueueImpl::MoveReadyDelayedTasksToIncomingQueue for each + // queue where the delay has elapsed. + void WakeupReadyDelayedQueues(LazyNow* lazy_now); + + private: + void MoveNewlyUpdatableQueuesIntoUpdatableQueueSet(); + + typedef std::multimap<base::TimeTicks, internal::TaskQueueImpl*> + DelayedWakeupMultimap; + + DelayedWakeupMultimap delayed_wakeup_multimap_; + + // This lock guards only |newly_updatable_|. It's not expected to be heavily + // contended. + base::Lock newly_updatable_lock_; + std::vector<internal::TaskQueueImpl*> newly_updatable_; + + // Set of task queues with avaliable work on the incoming queue. This should + // only be accessed from the main thread. + std::set<internal::TaskQueueImpl*> updatable_queue_set_; + + base::ThreadChecker main_thread_checker_; + base::WeakPtrFactory<TimeDomain> weak_factory_; + + DISALLOW_COPY_AND_ASSIGN(TimeDomain); +}; + +} // namespace scheduler + +#endif // COMPONENTS_SCHEDULER_BASE_TIME_DOMAIN_H_
diff --git a/components/scheduler/base/time_domain_unittest.cc b/components/scheduler/base/time_domain_unittest.cc new file mode 100644 index 0000000..75e5459 --- /dev/null +++ b/components/scheduler/base/time_domain_unittest.cc
@@ -0,0 +1,148 @@ +// Copyright 2015 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 "components/scheduler/base/time_domain.h" + +#include "base/test/simple_test_tick_clock.h" +#include "cc/test/ordered_simple_task_runner.h" +#include "components/scheduler/base/task_queue_impl.h" +#include "components/scheduler/base/task_queue_manager.h" +#include "components/scheduler/base/task_queue_manager_delegate_for_test.h" +#include "components/scheduler/base/test_time_source.h" +#include "testing/gmock/include/gmock/gmock.h" + +using testing::_; + +namespace scheduler { + +class MockTimeDomain : public TimeDomain { + public: + MockTimeDomain() + : now_(base::TimeTicks() + base::TimeDelta::FromSeconds(1)) {} + + using TimeDomain::NextScheduledRunTime; + using TimeDomain::NextScheduledTaskQueue; + using TimeDomain::ScheduleDelayedWork; + using TimeDomain::UnregisterQueue; + using TimeDomain::UpdateWorkQueues; + + // TimeSource implementation: + LazyNow CreateLazyNow() override { return LazyNow(now_); } + + void AsValueIntoInternal( + base::trace_event::TracedValue* state) const override {} + + bool MaybeAdvanceTime() override { return false; } + + const char* GetName() const override { return "Test"; } + + MOCK_METHOD1(RequestWakeup, void(base::TimeDelta delay)); + + void SetNow(base::TimeTicks now) { now_ = now; } + + base::TimeTicks Now() const { return now_; } + + private: + base::TimeTicks now_; + + ~MockTimeDomain() override {} + + DISALLOW_COPY_AND_ASSIGN(MockTimeDomain); +}; + +class TimeDomainTest : public testing::Test { + public: + void SetUp() final { + time_domain_ = make_scoped_refptr(new MockTimeDomain()); + task_queue_ = make_scoped_refptr(new internal::TaskQueueImpl( + nullptr, time_domain_, TaskQueue::Spec("test_queue"), "test.category", + "test.category")); + } + + scoped_refptr<MockTimeDomain> time_domain_; + scoped_refptr<internal::TaskQueueImpl> task_queue_; +}; + +TEST_F(TimeDomainTest, ScheduleDelayedWork) { + base::TimeDelta delay = base::TimeDelta::FromMilliseconds(10); + base::TimeTicks delayed_runtime = time_domain_->Now() + delay; + EXPECT_CALL(*time_domain_.get(), RequestWakeup(delay)); + LazyNow lazy_now = time_domain_->CreateLazyNow(); + time_domain_->ScheduleDelayedWork(task_queue_.get(), + time_domain_->Now() + delay, &lazy_now); + + base::TimeTicks next_scheduled_runtime; + EXPECT_TRUE(time_domain_->NextScheduledRunTime(&next_scheduled_runtime)); + EXPECT_EQ(delayed_runtime, next_scheduled_runtime); + + TaskQueue* next_task_queue; + EXPECT_TRUE(time_domain_->NextScheduledTaskQueue(&next_task_queue)); + EXPECT_EQ(task_queue_.get(), next_task_queue); +} + +TEST_F(TimeDomainTest, UnregisterQueue) { + scoped_refptr<internal::TaskQueueImpl> task_queue2_ = + make_scoped_refptr(new internal::TaskQueueImpl( + nullptr, time_domain_, TaskQueue::Spec("test_queue2"), + "test.category", "test.category")); + + EXPECT_CALL(*time_domain_.get(), RequestWakeup(_)).Times(2); + LazyNow lazy_now = time_domain_->CreateLazyNow(); + time_domain_->ScheduleDelayedWork( + task_queue_.get(), + time_domain_->Now() + base::TimeDelta::FromMilliseconds(10), &lazy_now); + time_domain_->ScheduleDelayedWork( + task_queue2_.get(), + time_domain_->Now() + base::TimeDelta::FromMilliseconds(100), &lazy_now); + + TaskQueue* next_task_queue; + EXPECT_TRUE(time_domain_->NextScheduledTaskQueue(&next_task_queue)); + EXPECT_EQ(task_queue_.get(), next_task_queue); + + time_domain_->UnregisterQueue(task_queue_.get()); + EXPECT_TRUE(time_domain_->NextScheduledTaskQueue(&next_task_queue)); + EXPECT_EQ(task_queue2_.get(), next_task_queue); + + time_domain_->UnregisterQueue(task_queue2_.get()); + EXPECT_FALSE(time_domain_->NextScheduledTaskQueue(&next_task_queue)); +} + +TEST_F(TimeDomainTest, UpdateWorkQueues) { + scoped_refptr<MockTimeDomain> dummy_delegate(new MockTimeDomain()); + base::SimpleTestTickClock dummy_time_source; + scoped_refptr<cc::OrderedSimpleTaskRunner> dummy_task_runner( + new cc::OrderedSimpleTaskRunner(&dummy_time_source, false)); + TaskQueueManager task_queue_manager( + TaskQueueManagerDelegateForTest::Create( + dummy_task_runner, + make_scoped_ptr(new TestTimeSource(&dummy_time_source))), + "test.scheduler", "test.scheduler", "scheduler.debug"); + scoped_refptr<internal::TaskQueueImpl> dummy_queue = + task_queue_manager.NewTaskQueue(TaskQueue::Spec("test_queue")); + + // Post a delayed task on |dummy_queue| and advance the queue's clock so that + // next time MoveReadyDelayedTasksToIncomingQueue is called, the task will + // get moved onto the incomming queue. + base::TimeDelta dummy_delay = base::TimeDelta::FromMilliseconds(10); + dummy_queue->PostDelayedTask(FROM_HERE, base::Closure(), dummy_delay); + dummy_time_source.Advance(dummy_delay); + + // Now we can test that ScheduleDelayedWork triggers calls to + // MoveReadyDelayedTasksToIncomingQueue as expected. + base::TimeDelta delay = base::TimeDelta::FromMilliseconds(50); + base::TimeTicks delayed_runtime = time_domain_->Now() + delay; + EXPECT_CALL(*time_domain_.get(), RequestWakeup(delay)); + LazyNow lazy_now = time_domain_->CreateLazyNow(); + time_domain_->ScheduleDelayedWork(dummy_queue.get(), delayed_runtime, + &lazy_now); + + time_domain_->UpdateWorkQueues(false, nullptr); + EXPECT_EQ(0UL, dummy_queue->IncomingQueueSizeForTest()); + + time_domain_->SetNow(delayed_runtime); + time_domain_->UpdateWorkQueues(false, nullptr); + EXPECT_EQ(1UL, dummy_queue->IncomingQueueSizeForTest()); +} + +} // namespace scheduler
diff --git a/components/scheduler/base/virtual_time_domain.cc b/components/scheduler/base/virtual_time_domain.cc new file mode 100644 index 0000000..fdd997c --- /dev/null +++ b/components/scheduler/base/virtual_time_domain.cc
@@ -0,0 +1,46 @@ +// Copyright 2015 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 "components/scheduler/base/virtual_time_domain.h" + +#include "base/bind.h" +#include "components/scheduler/base/task_queue_impl.h" +#include "components/scheduler/base/task_queue_manager_delegate.h" + +namespace scheduler { + +VirtualTimeDomain::VirtualTimeDomain(base::TimeTicks initial_time) + : now_(initial_time) {} + +VirtualTimeDomain::~VirtualTimeDomain() {} + +LazyNow VirtualTimeDomain::CreateLazyNow() { + base::AutoLock lock(lock_); + return LazyNow(now_); +} + +void VirtualTimeDomain::RequestWakeup(base::TimeDelta delay) { + // We don't need to do anything here because AdvanceTo triggers delayed tasks. +} + +bool VirtualTimeDomain::MaybeAdvanceTime() { + return false; +} + +void VirtualTimeDomain::AsValueIntoInternal( + base::trace_event::TracedValue* state) const {} + +void VirtualTimeDomain::AdvanceTo(base::TimeTicks now) { + base::AutoLock lock(lock_); + DCHECK_GE(now, now_); + now_ = now; + LazyNow lazy_now(now_); + WakeupReadyDelayedQueues(&lazy_now); +} + +const char* VirtualTimeDomain::GetName() const { + return "VirtualTimeDomain"; +} + +} // namespace scheduler
diff --git a/components/scheduler/base/virtual_time_domain.h b/components/scheduler/base/virtual_time_domain.h new file mode 100644 index 0000000..2e38414 --- /dev/null +++ b/components/scheduler/base/virtual_time_domain.h
@@ -0,0 +1,45 @@ +// Copyright 2015 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 COMPONENTS_SCHEDULER_BASE_VIRTUAL_TIME_DOMAIN_H_ +#define COMPONENTS_SCHEDULER_BASE_VIRTUAL_TIME_DOMAIN_H_ + +#include "base/callback.h" +#include "base/macros.h" +#include "components/scheduler/base/time_domain.h" +#include "components/scheduler/scheduler_export.h" + +namespace scheduler { +class TaskQueueManagerDelegate; + +class SCHEDULER_EXPORT VirtualTimeDomain : public TimeDomain { + public: + VirtualTimeDomain(base::TimeTicks initial_time); + + // TimeDomain implementation: + LazyNow CreateLazyNow() override; + bool MaybeAdvanceTime() override; + const char* GetName() const override; + + // Advances this time domain to |now|. NOTE |now| is supposed to be + // monotonically increasing. + void AdvanceTo(base::TimeTicks now); + + protected: + void RequestWakeup(base::TimeDelta delay) override; + void AsValueIntoInternal( + base::trace_event::TracedValue* state) const override; + + private: + mutable base::Lock lock_; // Protects |now_|. + base::TimeTicks now_; + + ~VirtualTimeDomain() override; + + DISALLOW_COPY_AND_ASSIGN(VirtualTimeDomain); +}; + +} // namespace scheduler + +#endif // COMPONENTS_SCHEDULER_BASE_VIRTUAL_TIME_DOMAIN_H_
diff --git a/components/scheduler/child/idle_helper.cc b/components/scheduler/child/idle_helper.cc index 84f6171..f007baec 100644 --- a/components/scheduler/child/idle_helper.cc +++ b/components/scheduler/child/idle_helper.cc
@@ -7,6 +7,7 @@ #include "base/time/time.h" #include "base/trace_event/trace_event.h" #include "base/trace_event/trace_event_argument.h" +#include "components/scheduler/base/real_time_domain.h" #include "components/scheduler/base/task_queue.h" #include "components/scheduler/base/task_queue_manager.h" #include "components/scheduler/child/scheduler_helper.h" @@ -76,17 +77,17 @@ return IdlePeriodState::NOT_IN_IDLE_PERIOD; } - base::TimeTicks next_pending_delayed_task = - helper_->NextPendingDelayedTaskRunTime(); + base::TimeTicks next_pending_delayed_task; base::TimeDelta max_long_idle_period_duration = base::TimeDelta::FromMilliseconds(kMaximumIdlePeriodMillis); base::TimeDelta long_idle_period_duration; - if (next_pending_delayed_task.is_null()) { - long_idle_period_duration = max_long_idle_period_duration; - } else { + if (helper_->real_time_domain()->NextScheduledRunTime( + &next_pending_delayed_task)) { // Limit the idle period duration to be before the next pending task. long_idle_period_duration = std::min(next_pending_delayed_task - now, max_long_idle_period_duration); + } else { + long_idle_period_duration = max_long_idle_period_duration; } if (long_idle_period_duration >=
diff --git a/components/scheduler/child/idle_helper_unittest.cc b/components/scheduler/child/idle_helper_unittest.cc index b4f559b..54c70e67 100644 --- a/components/scheduler/child/idle_helper_unittest.cc +++ b/components/scheduler/child/idle_helper_unittest.cc
@@ -7,6 +7,7 @@ #include "base/callback.h" #include "base/test/simple_test_tick_clock.h" #include "cc/test/ordered_simple_task_runner.h" +#include "components/scheduler/base/real_time_domain.h" #include "components/scheduler/base/task_queue.h" #include "components/scheduler/base/task_queue_manager.h" #include "components/scheduler/base/test_time_source.h" @@ -844,8 +845,9 @@ idle_helper_->EnableLongIdlePeriod(); CheckIdlePeriodStateIs("in_long_idle_period_paused"); // There shouldn't be any delayed tasks posted by the idle helper when paused. - EXPECT_EQ(base::TimeTicks(), - scheduler_helper_->NextPendingDelayedTaskRunTime()); + base::TimeTicks next_pending_delayed_task; + EXPECT_FALSE(scheduler_helper_->real_time_domain()->NextScheduledRunTime( + &next_pending_delayed_task)); // Posting a task should transition us to the an active state. max_idle_task_reposts = 2; @@ -865,8 +867,8 @@ // Once all task have been run we should go back to the paused state. CheckIdlePeriodStateIs("in_long_idle_period_paused"); - EXPECT_EQ(base::TimeTicks(), - scheduler_helper_->NextPendingDelayedTaskRunTime()); + EXPECT_FALSE(scheduler_helper_->real_time_domain()->NextScheduledRunTime( + &next_pending_delayed_task)); idle_helper_->EndIdlePeriod(); CheckIdlePeriodStateIs("not_in_idle_period");
diff --git a/components/scheduler/child/scheduler_helper.cc b/components/scheduler/child/scheduler_helper.cc index 9056e2b..f4081fd 100644 --- a/components/scheduler/child/scheduler_helper.cc +++ b/components/scheduler/child/scheduler_helper.cc
@@ -96,11 +96,6 @@ return task_queue_manager_delegate_; } -base::TimeTicks SchedulerHelper::NextPendingDelayedTaskRunTime() const { - CheckOnValidThread(); - DCHECK(task_queue_manager_.get()); - return task_queue_manager_->NextPendingDelayedTaskRunTime(); -} bool SchedulerHelper::GetAndClearSystemIsQuiescentBit() { CheckOnValidThread(); @@ -135,4 +130,10 @@ observer_->OnUnregisterTaskQueue(queue); } +const scoped_refptr<RealTimeDomain>& SchedulerHelper::real_time_domain() const { + CheckOnValidThread(); + DCHECK(task_queue_manager_); + return task_queue_manager_->real_time_domain(); +} + } // namespace scheduler
diff --git a/components/scheduler/child/scheduler_helper.h b/components/scheduler/child/scheduler_helper.h index 9570f73..27e33aa 100644 --- a/components/scheduler/child/scheduler_helper.h +++ b/components/scheduler/child/scheduler_helper.h
@@ -83,8 +83,8 @@ void SetObserver(Observer* observer); // Accessor methods. + const scoped_refptr<RealTimeDomain>& real_time_domain() const; const scoped_refptr<SchedulerTqmDelegate>& scheduler_tqm_delegate() const; - base::TimeTicks NextPendingDelayedTaskRunTime() const; bool GetAndClearSystemIsQuiescentBit(); // Test helpers.
diff --git a/components/scheduler/scheduler.gypi b/components/scheduler/scheduler.gypi index 5067979..dbd40ce 100644 --- a/components/scheduler/scheduler.gypi +++ b/components/scheduler/scheduler.gypi
@@ -13,6 +13,8 @@ 'base/cancelable_closure_holder.h', 'base/lazy_now.cc', 'base/lazy_now.h', + 'base/real_time_domain.cc', + 'base/real_time_domain.h', 'base/task_queue.cc', 'base/task_queue.h', 'base/task_queue_impl.cc', @@ -24,8 +26,12 @@ 'base/task_queue_selector.h', 'base/task_queue_sets.cc', 'base/task_queue_sets.h', + 'base/time_domain.cc', + 'base/time_domain.h', 'base/pollable_thread_safe_flag.cc', 'base/pollable_thread_safe_flag.h', + 'base/virtual_time_domain.cc', + 'base/virtual_time_domain.h', 'child/child_scheduler.h', 'child/idle_helper.cc', 'child/idle_helper.h',
diff --git a/components/search_engines/BUILD.gn b/components/search_engines/BUILD.gn index 3176fc6..9740b88 100644 --- a/components/search_engines/BUILD.gn +++ b/components/search_engines/BUILD.gn
@@ -60,8 +60,8 @@ "//components/metrics/proto", "//components/pref_registry", "//components/rappor", - "//components/sync_driver", "//components/strings", + "//components/sync_driver", "//components/url_formatter", "//components/webdata/common", "//google_apis", @@ -114,8 +114,8 @@ } deps = [ - "//components/pref_registry:test_support", ":test_support", + "//components/pref_registry:test_support", "//testing/gmock", "//testing/gtest", ]
diff --git a/components/security_interstitials.gypi b/components/security_interstitials.gypi index 3092d03..ba336af 100644 --- a/components/security_interstitials.gypi +++ b/components/security_interstitials.gypi
@@ -11,6 +11,9 @@ 'dependencies': [ '../base/base.gyp:base', '../net/net.gyp:net', + '../ui/base/ui_base.gyp:ui_base', + 'components_strings.gyp:components_strings', + 'google_core_browser', 'history_core_browser', 'metrics', 'rappor', @@ -20,6 +23,8 @@ ], 'sources': [ # Note: sources list duplicated in GN build. + 'security_interstitials/core/controller_client.cc', + 'security_interstitials/core/controller_client.h', 'security_interstitials/core/metrics_helper.cc', 'security_interstitials/core/metrics_helper.h', ]
diff --git a/components/security_interstitials/DEPS b/components/security_interstitials/DEPS index a32a580..59d6ff0 100644 --- a/components/security_interstitials/DEPS +++ b/components/security_interstitials/DEPS
@@ -1,6 +1,9 @@ include_rules = [ + "+components/google/core/browser", "+components/history/core/browser", "+components/metrics", "+components/rappor", - "+net/base" + "+grit/components_strings.h", + "+net/base", + "+ui/base" ]
diff --git a/components/security_interstitials/core/BUILD.gn b/components/security_interstitials/core/BUILD.gn index d60bad3..a9c0c81 100644 --- a/components/security_interstitials/core/BUILD.gn +++ b/components/security_interstitials/core/BUILD.gn
@@ -5,15 +5,20 @@ # GYP version: components/security_interstitials.gyp:security_interstitials_core static_library("core") { sources = [ + "controller_client.cc", + "controller_client.h", "metrics_helper.cc", "metrics_helper.h", ] deps = [ "//base", + "//components/google/core/browser", "//components/history/core/browser", "//components/metrics", "//components/rappor", + "//components/strings", "//net", + "//ui/base", ] }
diff --git a/components/security_interstitials/core/controller_client.cc b/components/security_interstitials/core/controller_client.cc new file mode 100644 index 0000000..7be4d84a --- /dev/null +++ b/components/security_interstitials/core/controller_client.cc
@@ -0,0 +1,44 @@ +// Copyright 2015 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 "components/security_interstitials/core/controller_client.h" + +#include "base/prefs/pref_service.h" +#include "components/google/core/browser/google_util.h" +#include "components/security_interstitials/core/metrics_helper.h" +#include "grit/components_strings.h" +#include "ui/base/l10n/l10n_util.h" +#include "url/gurl.h" + +namespace security_interstitials { + +ControllerClient::ControllerClient() {} +ControllerClient::~ControllerClient() {} + +MetricsHelper* ControllerClient::metrics_helper() const { + return metrics_helper_.get(); +} + +void ControllerClient::set_metrics_helper( + scoped_ptr<MetricsHelper> metrics_helper) { + metrics_helper_ = metrics_helper.Pass(); +} + +void ControllerClient::SetReportingPreference(bool report) { + GetPrefService()->SetBoolean(GetExtendedReportingPrefName(), report); + metrics_helper_->RecordUserInteraction( + report ? MetricsHelper::SET_EXTENDED_REPORTING_ENABLED + : MetricsHelper::SET_EXTENDED_REPORTING_DISABLED); +} + +void ControllerClient::OpenExtendedReportingPrivacyPolicy() { + metrics_helper_->RecordUserInteraction(MetricsHelper::SHOW_PRIVACY_POLICY); + GURL privacy_url( + l10n_util::GetStringUTF8(IDS_SAFE_BROWSING_PRIVACY_POLICY_URL)); + privacy_url = + google_util::AppendGoogleLocaleParam(privacy_url, GetApplicationLocale()); + OpenUrlInCurrentTab(privacy_url); +} + +} // namespace security_interstitials
diff --git a/components/security_interstitials/core/controller_client.h b/components/security_interstitials/core/controller_client.h new file mode 100644 index 0000000..9b18284 --- /dev/null +++ b/components/security_interstitials/core/controller_client.h
@@ -0,0 +1,76 @@ +// Copyright 2015 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 COMPONENTS_SECURITY_INTERSTITIALS_CORE_CONTROLLER_CLIENT_H_ +#define COMPONENTS_SECURITY_INTERSTITIALS_CORE_CONTROLLER_CLIENT_H_ + +#include <string> + +#include "base/macros.h" +#include "base/memory/scoped_ptr.h" + +class GURL; +class PrefService; + +namespace security_interstitials { + +class MetricsHelper; + +// Provides methods for handling commands from the user, which requires some +// embedder-specific abstraction. +class ControllerClient { + public: + // These represent the commands sent from the interstitial JavaScript. + // DO NOT reorder or change these without also changing the JavaScript! + // See components/security_interstitials/core/browser/resources/ + enum SecurityInterstitialCommands { + // Used by tests + CMD_ERROR = -3, + CMD_TEXT_FOUND = -2, + CMD_TEXT_NOT_FOUND = -1, + // Decisions + CMD_DONT_PROCEED = 0, + CMD_PROCEED = 1, + // Ways for user to get more information + CMD_SHOW_MORE_SECTION = 2, + CMD_OPEN_HELP_CENTER = 3, + CMD_OPEN_DIAGNOSTIC = 4, + // Primary button actions + CMD_RELOAD = 5, + CMD_OPEN_DATE_SETTINGS = 6, + CMD_OPEN_LOGIN = 7, + // Safe Browsing Extended Reporting + CMD_DO_REPORT = 8, + CMD_DONT_REPORT = 9, + CMD_OPEN_REPORTING_PRIVACY = 10, + // Report a phishing error + CMD_REPORT_PHISHING_ERROR = 11, + }; + + ControllerClient(); + virtual ~ControllerClient(); + + // Handle the user's reporting preferences. + void SetReportingPreference(bool report); + void OpenExtendedReportingPrivacyPolicy(); + + MetricsHelper* metrics_helper() const; + void set_metrics_helper(scoped_ptr<MetricsHelper> metrics_helper); + + protected: + virtual void OpenUrlInCurrentTab(const GURL& url) = 0; + + virtual const std::string& GetApplicationLocale() = 0; + virtual PrefService* GetPrefService() = 0; + virtual const std::string GetExtendedReportingPrefName() = 0; + + private: + scoped_ptr<MetricsHelper> metrics_helper_; + + DISALLOW_COPY_AND_ASSIGN(ControllerClient); +}; + +} // namespace security_interstitials + +#endif // COMPONENTS_SECURITY_INTERSTITIALS_CORE_CONTROLLER_CLIENT_H_
diff --git a/components/security_interstitials_strings.grdp b/components/security_interstitials_strings.grdp index a5a7f13..35fbbe1 100644 --- a/components/security_interstitials_strings.grdp +++ b/components/security_interstitials_strings.grdp
@@ -49,4 +49,9 @@ </message> </if> + <!-- Extended reporting strings --> + <message name="IDS_SAFE_BROWSING_PRIVACY_POLICY_URL" translateable="false"> + https://www.google.com/chrome/browser/privacy/whitepaper.html#malware + </message> + </grit-part> \ No newline at end of file
diff --git a/components/signin/core/browser/BUILD.gn b/components/signin/core/browser/BUILD.gn index d27e7273..3a30522 100644 --- a/components/signin/core/browser/BUILD.gn +++ b/components/signin/core/browser/BUILD.gn
@@ -68,12 +68,6 @@ deps = [ "//base", - "//crypto", - "//google_apis", - "//net", - "//sql", - "//third_party/icu", - "//components/signin/core/common", "//components/content_settings/core/browser", "//components/content_settings/core/common", "//components/google/core/browser", @@ -81,8 +75,14 @@ "//components/keyed_service/core", "//components/metrics", "//components/os_crypt", - "//components/webdata/common", "//components/signin/core/account_id", + "//components/signin/core/common", + "//components/webdata/common", + "//crypto", + "//google_apis", + "//net", + "//sql", + "//third_party/icu", ] if (is_chromeos) {
diff --git a/components/sync_driver/BUILD.gn b/components/sync_driver/BUILD.gn index 67bc4e89..ffe41b8 100644 --- a/components/sync_driver/BUILD.gn +++ b/components/sync_driver/BUILD.gn
@@ -235,8 +235,8 @@ "//components/pref_registry:test_support", "//components/version_info", "//net:test_support", - "//sync:test_support_sync_internal_api", "//sync:test_support_sync_api", + "//sync:test_support_sync_internal_api", "//testing/gmock", "//testing/gtest", "//url",
diff --git a/components/sync_driver/device_info_service.cc b/components/sync_driver/device_info_service.cc index b2575189..fb45112 100644 --- a/components/sync_driver/device_info_service.cc +++ b/components/sync_driver/device_info_service.cc
@@ -4,6 +4,8 @@ #include "components/sync_driver/device_info_service.h" +#include <vector> + #include "base/bind.h" #include "sync/api/model_type_change_processor.h" #include "sync/api/sync_error.h" @@ -32,69 +34,42 @@ DeviceInfoService::~DeviceInfoService() {} -syncer::SyncError DeviceInfoService::ApplySyncChanges() { - // TODO(skym): For every model change, if not local, apply to memory + disk. - // TODO(skym): For ever entity metadata change, apply to disk. - // TODO(skym): Apply type metadata to disk. +syncer_v2::MetadataChanges* DeviceInfoService::CreateMetadataChanges() { + // TODO(skym): Implementation. + return nullptr; +} + +syncer::SyncError DeviceInfoService::MergeSyncData( + syncer_v2::MetadataChanges* metadata_changes, + syncer_v2::EntityDataList entity_data_list) { + // TODO(skym): Implementation. return syncer::SyncError(); } -syncer::SyncError DeviceInfoService::LoadMetadata() { - // TODO(skym): Read out metadata from disk. +syncer::SyncError DeviceInfoService::ApplySyncChanges( + syncer_v2::MetadataChanges* metadata_changes, + syncer_v2::EntityDataList entity_data_list) { + // TODO(skym): Implementation. return syncer::SyncError(); } -syncer::SyncError DeviceInfoService::UpdateMetadata() { - // TODO(skym): Persist metadata to disk. - return syncer::SyncError(); +void DeviceInfoService::LoadMetadata(MetadataCallback callback) { + // TODO(skym): Implementation. } -syncer::SyncError DeviceInfoService::GetData() { - // TODO(skym): This is tricky. We're currently indexing data in memory by - // cache_guid, not client tags. And we cannot change this, because they're not - // equal on old clients. So maybe O(n*m) iterating through our map for every - // peice of data we were asked for? Alternative we could make a set, and do - // O(n + m). Another approach would to have two maps, which one ruling - // ownership. Or we could just read out of disk for this, instead of memory. - return syncer::SyncError(); +void DeviceInfoService::GetData(ClientKeyList client_keys, + DataCallback callback) { + // TODO(skym): Implementation. } -syncer::SyncError DeviceInfoService::GetAllData() { - // TODO(skym): Return all data from memory, unless we're not initialized. - return syncer::SyncError(); +void DeviceInfoService::GetAllData(DataCallback callback) { + // TODO(skym): Implementation. } -syncer::SyncError DeviceInfoService::ClearMetadata() { - // We act a little differently than most sync services here. All functionality - // is to be shutdown and stopped, and all data is to be deleted. - - bool was_syncing = IsSyncing(); - - all_data_.clear(); - clear_local_device_backup_time(); - clear_change_processor(); - - if (was_syncing) { - NotifyObservers(); - } - - // TODO(skym): Remove all data that's been persisted to storage. - // TODO(skym): Somehow remember we're no longer intialize. - - return syncer::SyncError(); -} - -syncer_v2::ModelTypeChangeProcessor* DeviceInfoService::get_change_processor() { - return change_processor_.get(); -} - -void DeviceInfoService::set_change_processor( - scoped_ptr<syncer_v2::ModelTypeChangeProcessor> change_processor) { - change_processor_.swap(change_processor); -} - -void DeviceInfoService::clear_change_processor() { - change_processor_.reset(); +std::string DeviceInfoService::GetClientTag( + const syncer_v2::EntityData* entity_data) { + // TODO(skym): Implementation. + return ""; } bool DeviceInfoService::IsSyncing() const {
diff --git a/components/sync_driver/device_info_service.h b/components/sync_driver/device_info_service.h index 47d334a..af57d3c 100644 --- a/components/sync_driver/device_info_service.h +++ b/components/sync_driver/device_info_service.h
@@ -6,11 +6,11 @@ #define COMPONENTS_SYNC_DRIVER_DEVICE_INFO_SERVICE_H_ #include <string> +#include <vector> #include "base/containers/scoped_ptr_map.h" #include "base/macros.h" #include "base/memory/scoped_ptr.h" -#include "base/memory/scoped_vector.h" #include "base/observer_list.h" #include "components/sync_driver/device_info_tracker.h" #include "components/sync_driver/local_device_info_provider.h" @@ -30,8 +30,6 @@ namespace sync_driver_v2 { -class ModelTypeChangeProcessor; - // USS service implementation for DEVICE_INFO model type. Handles storage of // device info and associated sync metadata, applying/merging foreign changes, // and allows public read access. @@ -42,19 +40,18 @@ sync_driver::LocalDeviceInfoProvider* local_device_info_provider); ~DeviceInfoService() override; - // TODO(skym): Update once these are added to ModelTypeService interface. // ModelTypeService implementation. - syncer::SyncError ApplySyncChanges(); - syncer::SyncError LoadMetadata(); - syncer::SyncError UpdateMetadata(); - syncer::SyncError GetData(); - syncer::SyncError GetAllData(); - syncer::SyncError ClearMetadata(); - // TODO(skym): See crbug/547087, do we need all these accessors? - syncer_v2::ModelTypeChangeProcessor* get_change_processor(); - void set_change_processor( - scoped_ptr<syncer_v2::ModelTypeChangeProcessor> change_processor); - void clear_change_processor(); + syncer_v2::MetadataChanges* CreateMetadataChanges() override; + syncer::SyncError MergeSyncData( + syncer_v2::MetadataChanges* metadata_changes, + syncer_v2::EntityDataList entity_data_list) override; + syncer::SyncError ApplySyncChanges( + syncer_v2::MetadataChanges* metadata_changes, + syncer_v2::EntityDataList entity_data_list) override; + void LoadMetadata(MetadataCallback callback) override; + void GetData(ClientKeyList client_keys, DataCallback callback) override; + void GetAllData(DataCallback callback) override; + std::string GetClientTag(const syncer_v2::EntityData* entity_data) override; // DeviceInfoTracker implementation. bool IsSyncing() const override; @@ -84,6 +81,7 @@ void StoreSpecifics(scoped_ptr<sync_pb::DeviceInfoSpecifics> specifics); // Delete SyncData from the cache. void DeleteSpecifics(const std::string& client_id); + // Notify all registered observers. void NotifyObservers(); @@ -107,9 +105,6 @@ // |local_device_info_provider_| isn't owned. const sync_driver::LocalDeviceInfoProvider* const local_device_info_provider_; - // Recieves ownership in set_change_processor(...). - scoped_ptr<syncer_v2::ModelTypeChangeProcessor> change_processor_; - // TODO(skym): Switch to use client tag hash instead of cache guid as key. // Cache of all syncable and local data, stored by device cache guid. typedef base::ScopedPtrMap<std::string,
diff --git a/components/sync_sessions/BUILD.gn b/components/sync_sessions/BUILD.gn index cffd15a..3f6ceb8 100644 --- a/components/sync_sessions/BUILD.gn +++ b/components/sync_sessions/BUILD.gn
@@ -100,15 +100,15 @@ "//base:prefs", "//base:prefs_test_support", "//base/test:test_support", - "//testing/gmock", "//components/bookmarks/browser", "//components/history/core/browser", "//components/sessions:test_support", "//components/sync_driver", "//components/sync_driver:test_support", - "//testing/gtest", "//sync", "//sync:test_support_sync_api", + "//testing/gmock", + "//testing/gtest", "//ui/base:base", "//url", ]
diff --git a/components/syncable_prefs/BUILD.gn b/components/syncable_prefs/BUILD.gn index 4706b6f..c854abb 100644 --- a/components/syncable_prefs/BUILD.gn +++ b/components/syncable_prefs/BUILD.gn
@@ -64,7 +64,7 @@ ":test_support", "//base:prefs", "//components/pref_registry", - "//testing/gtest", "//sync:test_support_sync_api", + "//testing/gtest", ] }
diff --git a/components/test_runner/mock_web_user_media_client.cc b/components/test_runner/mock_web_user_media_client.cc index 7cff4c3..3bd55e5f9f6 100644 --- a/components/test_runner/mock_web_user_media_client.cc +++ b/components/test_runner/mock_web_user_media_client.cc
@@ -165,7 +165,8 @@ WebVector<WebMediaStreamTrack>()); stream.setExtraData(new MockExtraData()); - if (request.audio()) { + if (request.audio() && + !delegate_->AddMediaStreamAudioSourceAndTrack(&stream)) { WebMediaStreamSource source; source.initialize("MockAudioDevice#1", WebMediaStreamSource::TypeAudio, @@ -177,7 +178,8 @@ stream.addTrack(web_track); } - if (request.video() && !delegate_->AddMediaStreamSourceAndTrack(&stream)) { + if (request.video() && + !delegate_->AddMediaStreamVideoSourceAndTrack(&stream)) { WebMediaStreamSource source; source.initialize("MockVideoDevice#1", WebMediaStreamSource::TypeVideo,
diff --git a/components/test_runner/web_test_delegate.h b/components/test_runner/web_test_delegate.h index 893cbae..753831db7 100644 --- a/components/test_runner/web_test_delegate.h +++ b/components/test_runner/web_test_delegate.h
@@ -250,7 +250,10 @@ virtual void ResetPermissions() = 0; // Add content MediaStream classes to the Blink MediaStream ones. - virtual bool AddMediaStreamSourceAndTrack(blink::WebMediaStream* stream) = 0; + virtual bool AddMediaStreamVideoSourceAndTrack( + blink::WebMediaStream* stream) = 0; + virtual bool AddMediaStreamAudioSourceAndTrack( + blink::WebMediaStream* stream) = 0; virtual cc::SharedBitmapManager* GetSharedBitmapManager() = 0;
diff --git a/components/tracing/trace_config_file.cc b/components/tracing/trace_config_file.cc index f1df192..f3b908e7 100644 --- a/components/tracing/trace_config_file.cc +++ b/components/tracing/trace_config_file.cc
@@ -69,19 +69,25 @@ // default configuration for 5 sec. startup_duration_ = 5; is_enabled_ = true; + DLOG(WARNING) << "Use default trace config."; return; } - if (!base::PathExists(trace_config_file)) + if (!base::PathExists(trace_config_file)) { + DLOG(WARNING) << "The trace config file does not exist."; return; + } std::string trace_config_file_content; if (!base::ReadFileToString(trace_config_file, &trace_config_file_content, kTraceConfigFileSizeLimit)) { + DLOG(WARNING) << "Cannot read the trace config file correctly."; return; } is_enabled_ = ParseTraceConfigFileContent(trace_config_file_content); + if (!is_enabled_) + DLOG(WARNING) << "Cannot parse the trace config file correctly."; } TraceConfigFile::~TraceConfigFile() {
diff --git a/components/translate/ios/browser/BUILD.gn b/components/translate/ios/browser/BUILD.gn index 420954a..9554190 100644 --- a/components/translate/ios/browser/BUILD.gn +++ b/components/translate/ios/browser/BUILD.gn
@@ -19,13 +19,13 @@ ] deps = [ + ":injected_js", "//base", "//components/translate/core/browser", "//components/translate/core/common", "//components/translate/core/language_detection", "//ios/web", "//url", - ":injected_js", ] } @@ -46,6 +46,7 @@ ] deps = [ + ":browser", "//base", "//components/resources", "//components/translate/core/common", @@ -54,6 +55,5 @@ "//third_party/ocmock", "//ui/base", "//url", - ":browser", ] }
diff --git a/components/update_client/BUILD.gn b/components/update_client/BUILD.gn index eeefaea..32722d0c 100644 --- a/components/update_client/BUILD.gn +++ b/components/update_client/BUILD.gn
@@ -55,9 +55,9 @@ "//components/crx_file", "//courgette:courgette_lib", "//crypto", + "//net", "//third_party/libxml", "//third_party/zlib:zip", - "//net", "//ui/base", "//url", ] @@ -80,8 +80,8 @@ deps = [ "//base", "//net:test_support", - "//testing/gtest", "//testing/gmock", + "//testing/gtest", "//url", ] } @@ -100,13 +100,13 @@ ] deps = [ - ":update_client", ":test_support", + ":update_client", "//base", "//courgette:courgette_lib", "//net:test_support", - "//testing/gtest", "//testing/gmock", + "//testing/gtest", "//third_party/libxml", ] }
diff --git a/components/url_formatter/BUILD.gn b/components/url_formatter/BUILD.gn index b74ef78..1756f02 100644 --- a/components/url_formatter/BUILD.gn +++ b/components/url_formatter/BUILD.gn
@@ -19,8 +19,8 @@ deps = [ "//base", - "//third_party/icu", "//net", + "//third_party/icu", "//url", ]
diff --git a/components/url_matcher/string_pattern.cc b/components/url_matcher/string_pattern.cc index d103bce..a4b87bca 100644 --- a/components/url_matcher/string_pattern.cc +++ b/components/url_matcher/string_pattern.cc
@@ -4,6 +4,8 @@ #include "components/url_matcher/string_pattern.h" +#include <tuple> + namespace url_matcher { StringPattern::StringPattern(const std::string& pattern, @@ -13,8 +15,7 @@ StringPattern::~StringPattern() {} bool StringPattern::operator<(const StringPattern& rhs) const { - if (id_ != rhs.id_) return id_ < rhs.id_; - return pattern_ < rhs.pattern_; + return std::tie(id_, pattern_) < std::tie(rhs.id_, rhs.pattern_); } } // namespace url_matcher
diff --git a/components/user_prefs/tracked/BUILD.gn b/components/user_prefs/tracked/BUILD.gn index e749217..8c32ec7 100644 --- a/components/user_prefs/tracked/BUILD.gn +++ b/components/user_prefs/tracked/BUILD.gn
@@ -53,8 +53,8 @@ deps = [ "//base:base", "//base:prefs", - "//crypto:crypto", "//components/pref_registry", + "//crypto:crypto", ] }
diff --git a/components/variations/BUILD.gn b/components/variations/BUILD.gn index a65148a..3f9c7c7d 100644 --- a/components/variations/BUILD.gn +++ b/components/variations/BUILD.gn
@@ -62,7 +62,6 @@ } deps = [ - "proto", "//base", "//base:prefs", "//components/compression", @@ -70,6 +69,7 @@ "//crypto", "//third_party/mt19937ar", "//third_party/protobuf:protobuf_lite", + "proto", ] if (is_android) { @@ -111,11 +111,11 @@ deps = [ ":variations", - "net", - "proto", "//base:prefs_test_support", "//base/test:test_support", "//components/compression", "//testing/gtest", + "net", + "proto", ] }
diff --git a/components/variations/android/java/src/org/chromium/components/variations/firstrun/VariationsSeedBridge.java b/components/variations/android/java/src/org/chromium/components/variations/firstrun/VariationsSeedBridge.java index 2b5a5be..64e2877 100644 --- a/components/variations/android/java/src/org/chromium/components/variations/firstrun/VariationsSeedBridge.java +++ b/components/variations/android/java/src/org/chromium/components/variations/firstrun/VariationsSeedBridge.java
@@ -16,26 +16,28 @@ * in SharedPreferences and to get the seed from there. To store raw seed data class serializes * byte[] to Base64 encoded string and decodes this string before passing to C++ side. */ -public final class VariationsSeedBridge { - private static final String VARIATIONS_FIRST_RUN_SEED_BASE64 = "variations_seed_base64"; - private static final String VARIATIONS_FIRST_RUN_SEED_SIGNATURE = "variations_seed_signature"; - private static final String VARIATIONS_FIRST_RUN_SEED_COUNTRY = "variations_seed_country"; - private static final String VARIATIONS_FIRST_RUN_SEED_DATE = "variations_seed_date"; - private static final String VARIATIONS_FIRST_RUN_SEED_IS_GZIP_COMPRESSED = +public class VariationsSeedBridge { + protected static final String VARIATIONS_FIRST_RUN_SEED_BASE64 = "variations_seed_base64"; + protected static final String VARIATIONS_FIRST_RUN_SEED_SIGNATURE = "variations_seed_signature"; + protected static final String VARIATIONS_FIRST_RUN_SEED_COUNTRY = "variations_seed_country"; + protected static final String VARIATIONS_FIRST_RUN_SEED_DATE = "variations_seed_date"; + protected static final String VARIATIONS_FIRST_RUN_SEED_IS_GZIP_COMPRESSED = "variations_seed_is_gzip_compressed"; // This pref is used to store information about successful seed storing on the C++ side, in // order to not fetch the seed again. - private static final String VARIATIONS_FIRST_RUN_SEED_NATIVE_STORED = + protected static final String VARIATIONS_FIRST_RUN_SEED_NATIVE_STORED = "variations_seed_native_stored"; - private static String getVariationsFirstRunSeedPref(Context context, String prefName) { + protected static String getVariationsFirstRunSeedPref(Context context, String prefName) { return PreferenceManager.getDefaultSharedPreferences(context).getString(prefName, ""); } /** * Stores variations seed data (raw data, seed signature and country code) in SharedPreferences. + * CalledByNative attribute is used by unit tests code to set test data. */ + @CalledByNative public static void setVariationsFirstRunSeed(Context context, byte[] rawSeed, String signature, String country, String date, boolean isGzipCompressed) { PreferenceManager.getDefaultSharedPreferences(context) @@ -56,6 +58,8 @@ .remove(VARIATIONS_FIRST_RUN_SEED_BASE64) .remove(VARIATIONS_FIRST_RUN_SEED_SIGNATURE) .remove(VARIATIONS_FIRST_RUN_SEED_COUNTRY) + .remove(VARIATIONS_FIRST_RUN_SEED_DATE) + .remove(VARIATIONS_FIRST_RUN_SEED_IS_GZIP_COMPRESSED) .apply(); }
diff --git a/components/variations/android/variations_seed_bridge.cc b/components/variations/android/variations_seed_bridge.cc index 16dfeca..9016692 100644 --- a/components/variations/android/variations_seed_bridge.cc +++ b/components/variations/android/variations_seed_bridge.cc
@@ -15,6 +15,7 @@ using base::android::AttachCurrentThread; using base::android::ConvertJavaStringToUTF8; +using base::android::ConvertUTF8ToJavaString; using base::android::GetApplicationContext; using base::android::ScopedJavaLocalRef; @@ -28,6 +29,13 @@ return std::string(array_data.begin(), array_data.end()); } +ScopedJavaLocalRef<jbyteArray> StringToJavaByteArray( + JNIEnv* env, + const std::string& str_data) { + std::vector<uint8> array_data(str_data.begin(), str_data.end()); + return base::android::ToJavaByteArray(env, array_data); +} + } // namespace namespace variations { @@ -76,5 +84,19 @@ GetApplicationContext()); } +void SetJavaFirstRunPrefsForTesting(const std::string& seed_data, + const std::string& seed_signature, + const std::string& seed_country, + const std::string& response_date, + bool is_gzip_compressed) { + JNIEnv* env = AttachCurrentThread(); + Java_VariationsSeedBridge_setVariationsFirstRunSeed( + env, GetApplicationContext(), StringToJavaByteArray(env, seed_data).obj(), + ConvertUTF8ToJavaString(env, seed_signature).obj(), + ConvertUTF8ToJavaString(env, seed_country).obj(), + ConvertUTF8ToJavaString(env, response_date).obj(), + static_cast<jboolean>(is_gzip_compressed)); +} + } // namespace android } // namespace variations
diff --git a/components/variations/android/variations_seed_bridge.h b/components/variations/android/variations_seed_bridge.h index 63ce5e2fc..85e633f 100644 --- a/components/variations/android/variations_seed_bridge.h +++ b/components/variations/android/variations_seed_bridge.h
@@ -28,6 +28,15 @@ // the Java side. void MarkVariationsSeedAsStored(); +// Sets test data on the Java side. The data is pulled during the unit tests to +// C++ side and is being checked for consistency. +// This method is used for unit testing purposes only. +void SetJavaFirstRunPrefsForTesting(const std::string& seed_data, + const std::string& seed_signature, + const std::string& seed_country, + const std::string& response_date, + bool is_gzip_compressed); + } // namespace android } // namespace variations
diff --git a/components/variations/service/generate_ui_string_overrider.gni b/components/variations/service/generate_ui_string_overrider.gni index 4b16c52e..14497f9 100644 --- a/components/variations/service/generate_ui_string_overrider.gni +++ b/components/variations/service/generate_ui_string_overrider.gni
@@ -62,8 +62,8 @@ source_set(target_name) { sources = get_target_outputs(":$gen_action_target_name") deps = [ - "//components/variations/service", ":$gen_action_target_name", + "//components/variations/service", ] forward_variables_from(invoker, [ "visibility" ])
diff --git a/components/variations/variations_seed_store_unittest.cc b/components/variations/variations_seed_store_unittest.cc index ab7f506..419784f 100644 --- a/components/variations/variations_seed_store_unittest.cc +++ b/components/variations/variations_seed_store_unittest.cc
@@ -12,6 +12,10 @@ #include "components/variations/proto/variations_seed.pb.h" #include "testing/gtest/include/gtest/gtest.h" +#if defined(OS_ANDROID) +#include "components/variations/android/variations_seed_bridge.h" +#endif // OS_ANDROID + namespace variations { namespace { @@ -378,4 +382,39 @@ EXPECT_EQ(after_seed_data, output); } +#if defined(OS_ANDROID) +TEST(VariationsSeedStoreTest, ImportFirstRunJavaSeed) { + const std::string test_seed_data = "raw_seed_data_test"; + const std::string test_seed_signature = "seed_signature_test"; + const std::string test_seed_country = "seed_country_code_test"; + const std::string test_response_date = "seed_response_date_test"; + const bool test_is_gzip_compressed = true; + android::SetJavaFirstRunPrefsForTesting(test_seed_data, test_seed_signature, + test_seed_country, test_response_date, + test_is_gzip_compressed); + + std::string seed_data; + std::string seed_signature; + std::string seed_country; + std::string response_date; + bool is_gzip_compressed; + android::GetVariationsFirstRunSeed(&seed_data, &seed_signature, &seed_country, + &response_date, &is_gzip_compressed); + EXPECT_EQ(test_seed_data, seed_data); + EXPECT_EQ(test_seed_signature, seed_signature); + EXPECT_EQ(test_seed_country, seed_country); + EXPECT_EQ(test_response_date, response_date); + EXPECT_EQ(test_is_gzip_compressed, is_gzip_compressed); + + android::ClearJavaFirstRunPrefs(); + android::GetVariationsFirstRunSeed(&seed_data, &seed_signature, &seed_country, + &response_date, &is_gzip_compressed); + EXPECT_EQ("", seed_data); + EXPECT_EQ("", seed_signature); + EXPECT_EQ("", seed_country); + EXPECT_EQ("", response_date); + EXPECT_FALSE(is_gzip_compressed); +} +#endif // OS_ANDROID + } // namespace variations
diff --git a/components/version_info/BUILD.gn b/components/version_info/BUILD.gn index 1f08c3f2..7f51c0a4 100644 --- a/components/version_info/BUILD.gn +++ b/components/version_info/BUILD.gn
@@ -22,9 +22,9 @@ ] deps = [ + ":generate_version_info", "//base", "//components/strings", - ":generate_version_info", ] if (use_unofficial_version_number) {
diff --git a/components/web_contents_delegate_android/BUILD.gn b/components/web_contents_delegate_android/BUILD.gn index 56ee8de1..24bc34e 100644 --- a/components/web_contents_delegate_android/BUILD.gn +++ b/components/web_contents_delegate_android/BUILD.gn
@@ -42,9 +42,9 @@ deps = [ ":web_contents_delegate_android_java_resources", "//base:base_java", - "//ui/android:ui_java", "//content/public/android:content_java", "//content/public/android:content_java_resources", + "//ui/android:ui_java", ] DEPRECATED_java_in_dir = "android/java/src" }
diff --git a/components/web_resource/BUILD.gn b/components/web_resource/BUILD.gn index 4b24750..6c396d9 100644 --- a/components/web_resource/BUILD.gn +++ b/components/web_resource/BUILD.gn
@@ -63,8 +63,8 @@ } deps = [ - ":web_resource", ":test_support", + ":web_resource", "//base", "//base:prefs_test_support", "//components/version_info",
diff --git a/components/web_view/BUILD.gn b/components/web_view/BUILD.gn index 569cc4b..b228220 100644 --- a/components/web_view/BUILD.gn +++ b/components/web_view/BUILD.gn
@@ -119,9 +119,9 @@ ":test_support", "//base", "//base/test:test_config", + "//components/mus/public/cpp", "//components/mus/public/cpp/tests:test_support", "//components/mus/public/interfaces", - "//components/mus/public/cpp", "//components/web_view/public/cpp", "//components/web_view/public/interfaces", "//mojo/application/public/cpp:sources",
diff --git a/components/web_view/frame_connection.cc b/components/web_view/frame_connection.cc index 68d8fc0..4d40337 100644 --- a/components/web_view/frame_connection.cc +++ b/components/web_view/frame_connection.cc
@@ -110,8 +110,9 @@ filter->filter.insert("mojo:font_service", font_service_interfaces.Pass()); #endif - application_connection_ = app->ConnectToApplicationWithCapabilityFilter( - request.Pass(), filter.Pass()); + mojo::ApplicationImpl::ConnectParams params(request.Pass()); + params.set_filter(filter.Pass()); + application_connection_ = app->ConnectToApplication(¶ms); application_connection_->ConnectToService(&frame_client_); application_connection_->AddContentHandlerIDCallback(on_got_id_callback); }
diff --git a/components/web_view/frame_devtools_agent.cc b/components/web_view/frame_devtools_agent.cc index b11a946e..a9bceeb 100644 --- a/components/web_view/frame_devtools_agent.cc +++ b/components/web_view/frame_devtools_agent.cc
@@ -120,10 +120,8 @@ if (binding_.is_bound()) return; - mojo::URLRequestPtr request(mojo::URLRequest::New()); - request->url = "mojo:devtools_service"; DevToolsRegistryPtr devtools_registry; - app_->ConnectToService(request.Pass(), &devtools_registry); + app_->ConnectToService("mojo:devtools_service", &devtools_registry); DevToolsAgentPtr agent; binding_.Bind(&agent);
diff --git a/components/web_view/public/cpp/web_view.cc b/components/web_view/public/cpp/web_view.cc index fe53997..0aee7653 100644 --- a/components/web_view/public/cpp/web_view.cc +++ b/components/web_view/public/cpp/web_view.cc
@@ -21,16 +21,13 @@ WebView::~WebView() {} void WebView::Init(mojo::ApplicationImpl* app, mus::Window* window) { - mojo::URLRequestPtr request(mojo::URLRequest::New()); - request->url = "mojo:web_view"; - mojom::WebViewClientPtr client; mojo::InterfaceRequest<mojom::WebViewClient> client_request = GetProxy(&client); binding_.Bind(client_request.Pass()); mojom::WebViewFactoryPtr factory; - app->ConnectToService(request.Pass(), &factory); + app->ConnectToService("mojo:web_view", &factory); factory->CreateWebView(client.Pass(), GetProxy(&web_view_)); mus::mojom::WindowTreeClientPtr window_tree_client;
diff --git a/components/web_view/public/interfaces/BUILD.gn b/components/web_view/public/interfaces/BUILD.gn index 6ce73b5..5ddf39d8 100644 --- a/components/web_view/public/interfaces/BUILD.gn +++ b/components/web_view/public/interfaces/BUILD.gn
@@ -10,9 +10,7 @@ "web_view.mojom", ] - import_dirs = [ - "//mojo/services" - ] + import_dirs = [ "//mojo/services" ] deps = [ "//components/mus/public/interfaces",
diff --git a/components/webcrypto/BUILD.gn b/components/webcrypto/BUILD.gn index aef7867..ce98092 100644 --- a/components/webcrypto/BUILD.gn +++ b/components/webcrypto/BUILD.gn
@@ -87,8 +87,8 @@ "//components/test_runner:test_runner", "//crypto", "//crypto:platform", - "//testing/perf", "//testing/gtest", + "//testing/perf", "//third_party/WebKit/public:blink", "//third_party/re2", ]
diff --git a/components/webcrypto/algorithms/aes_cbc.cc b/components/webcrypto/algorithms/aes_cbc.cc index 0d9c88e..2cda785 100644 --- a/components/webcrypto/algorithms/aes_cbc.cc +++ b/components/webcrypto/algorithms/aes_cbc.cc
@@ -7,7 +7,6 @@ #include "base/logging.h" #include "base/numerics/safe_math.h" -#include "base/stl_util.h" #include "components/webcrypto/algorithms/aes.h" #include "components/webcrypto/algorithms/util.h" #include "components/webcrypto/blink_key_handle.h" @@ -77,15 +76,13 @@ buffer->resize(output_max_len.ValueOrDie()); - unsigned char* const buffer_data = vector_as_array(buffer); - int output_len = 0; - if (!EVP_CipherUpdate(context.get(), buffer_data, &output_len, data.bytes(), - data.byte_length())) { + if (!EVP_CipherUpdate(context.get(), buffer->data(), &output_len, + data.bytes(), data.byte_length())) { return Status::OperationError(); } int final_output_chunk_len = 0; - if (!EVP_CipherFinal_ex(context.get(), buffer_data + output_len, + if (!EVP_CipherFinal_ex(context.get(), buffer->data() + output_len, &final_output_chunk_len)) { return Status::OperationError(); }
diff --git a/components/webcrypto/algorithms/aes_cbc_unittest.cc b/components/webcrypto/algorithms/aes_cbc_unittest.cc index 44f07ea0..7fe9409 100644 --- a/components/webcrypto/algorithms/aes_cbc_unittest.cc +++ b/components/webcrypto/algorithms/aes_cbc_unittest.cc
@@ -2,7 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "base/stl_util.h" #include "base/values.h" #include "components/webcrypto/algorithm_dispatch.h" #include "components/webcrypto/algorithms/test_helpers.h" @@ -20,7 +19,7 @@ const std::vector<uint8_t>& iv) { return blink::WebCryptoAlgorithm::adoptParamsAndCreate( blink::WebCryptoAlgorithmIdAesCbc, - new blink::WebCryptoAesCbcParams(vector_as_array(&iv), + new blink::WebCryptoAesCbcParams(iv.data(), static_cast<unsigned int>(iv.size()))); }
diff --git a/components/webcrypto/algorithms/aes_ctr.cc b/components/webcrypto/algorithms/aes_ctr.cc index f4c16b6..39ca087 100644 --- a/components/webcrypto/algorithms/aes_ctr.cc +++ b/components/webcrypto/algorithms/aes_ctr.cc
@@ -8,7 +8,6 @@ #include "base/logging.h" #include "base/macros.h" #include "base/numerics/safe_math.h" -#include "base/stl_util.h" #include "components/webcrypto/algorithms/aes.h" #include "components/webcrypto/algorithms/util.h" #include "components/webcrypto/blink_key_handle.h" @@ -104,8 +103,7 @@ counter_block.bytes() + counter_block.byte_length()); counter[0] &= ~(0xFF << counter_length_remainder_bits); - return crypto::ScopedBIGNUM( - BN_bin2bn(vector_as_array(&counter), counter.size(), NULL)); + return crypto::ScopedBIGNUM(BN_bin2bn(counter.data(), counter.size(), NULL)); } // Returns a counter block with the counter bits all set all zero. @@ -206,7 +204,7 @@ // wrapping-around, do it as a single call into BoringSSL. if (BN_cmp(num_blocks_until_reset.get(), num_output_blocks.get()) >= 0) { return AesCtrEncrypt128BitCounter(cipher, CryptoData(raw_key), data, - counter_block, vector_as_array(buffer)); + counter_block, buffer->data()); } // Otherwise the encryption needs to be done in 2 parts. The first part using @@ -222,7 +220,7 @@ // Encrypt the first part (before wrap-around). Status status = AesCtrEncrypt128BitCounter( cipher, CryptoData(raw_key), CryptoData(data.bytes(), input_size_part1), - counter_block, vector_as_array(buffer)); + counter_block, buffer->data()); if (status.IsError()) return status; @@ -234,8 +232,7 @@ cipher, CryptoData(raw_key), CryptoData(data.bytes() + input_size_part1, data.byte_length() - input_size_part1), - CryptoData(counter_block_part2), - vector_as_array(buffer) + input_size_part1); + CryptoData(counter_block_part2), buffer->data() + input_size_part1); } class AesCtrImplementation : public AesAlgorithm {
diff --git a/components/webcrypto/algorithms/aes_ctr_unittest.cc b/components/webcrypto/algorithms/aes_ctr_unittest.cc index 9bdbf38..9668ca5 100644 --- a/components/webcrypto/algorithms/aes_ctr_unittest.cc +++ b/components/webcrypto/algorithms/aes_ctr_unittest.cc
@@ -2,7 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "base/stl_util.h" #include "base/values.h" #include "components/webcrypto/algorithm_dispatch.h" #include "components/webcrypto/algorithms/test_helpers.h" @@ -22,7 +21,7 @@ return blink::WebCryptoAlgorithm::adoptParamsAndCreate( blink::WebCryptoAlgorithmIdAesCtr, new blink::WebCryptoAesCtrParams( - length_bits, vector_as_array(&counter), + length_bits, counter.data(), static_cast<unsigned int>(counter.size()))); } @@ -140,8 +139,8 @@ // 16 and 17 AES blocks worth of data respectively (AES blocks are 16 bytes // long). - CryptoData input_16(vector_as_array(&buffer), 256); - CryptoData input_17(vector_as_array(&buffer), 272); + CryptoData input_16(buffer.data(), 256); + CryptoData input_17(buffer.data(), 272); std::vector<uint8_t> output;
diff --git a/components/webcrypto/algorithms/aes_gcm_unittest.cc b/components/webcrypto/algorithms/aes_gcm_unittest.cc index 94ba9be..d912cbd 100644 --- a/components/webcrypto/algorithms/aes_gcm_unittest.cc +++ b/components/webcrypto/algorithms/aes_gcm_unittest.cc
@@ -2,7 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "base/stl_util.h" #include "base/values.h" #include "components/webcrypto/algorithm_dispatch.h" #include "components/webcrypto/algorithms/test_helpers.h" @@ -24,8 +23,8 @@ return blink::WebCryptoAlgorithm::adoptParamsAndCreate( blink::WebCryptoAlgorithmIdAesGcm, new blink::WebCryptoAesGcmParams( - vector_as_array(&iv), static_cast<unsigned int>(iv.size()), true, - vector_as_array(&additional_data), + iv.data(), static_cast<unsigned int>(iv.size()), true, + additional_data.data(), static_cast<unsigned int>(additional_data.size()), true, tag_length_bits)); }
diff --git a/components/webcrypto/algorithms/ec.cc b/components/webcrypto/algorithms/ec.cc index 20baa57..e489b87f 100644 --- a/components/webcrypto/algorithms/ec.cc +++ b/components/webcrypto/algorithms/ec.cc
@@ -10,7 +10,6 @@ #include <openssl/pkcs12.h> #include "base/logging.h" -#include "base/stl_util.h" #include "components/webcrypto/algorithms/asymmetric_key_util.h" #include "components/webcrypto/algorithms/util.h" #include "components/webcrypto/blink_key_handle.h" @@ -159,10 +158,8 @@ size_t padded_length, JwkWriter* jwk) { std::vector<uint8_t> padded_bytes(padded_length); - if (!BN_bn2bin_padded(vector_as_array(&padded_bytes), padded_bytes.size(), - value)) { + if (!BN_bn2bin_padded(padded_bytes.data(), padded_bytes.size(), value)) return Status::OperationError(); - } jwk->SetBytes(member_name, CryptoData(padded_bytes)); return Status::Success(); }
diff --git a/components/webcrypto/algorithms/ecdh.cc b/components/webcrypto/algorithms/ecdh.cc index 9da36e9..b4bff4c 100644 --- a/components/webcrypto/algorithms/ecdh.cc +++ b/components/webcrypto/algorithms/ecdh.cc
@@ -7,7 +7,6 @@ #include <openssl/evp.h> #include "base/logging.h" -#include "base/stl_util.h" #include "components/webcrypto/algorithm_implementation.h" #include "components/webcrypto/algorithms/ec.h" #include "components/webcrypto/algorithms/util.h" @@ -112,9 +111,8 @@ // buffer than field_size_bytes). derived_bytes->resize(NumBitsToBytes(length_bits)); - int result = - ECDH_compute_key(vector_as_array(derived_bytes), derived_bytes->size(), - public_key_point, private_key_ec.get(), 0); + int result = ECDH_compute_key(derived_bytes->data(), derived_bytes->size(), + public_key_point, private_key_ec.get(), 0); if (result < 0 || static_cast<size_t>(result) != derived_bytes->size()) return Status::OperationError();
diff --git a/components/webcrypto/algorithms/ecdsa.cc b/components/webcrypto/algorithms/ecdsa.cc index 367e0f0..8a283af1 100644 --- a/components/webcrypto/algorithms/ecdsa.cc +++ b/components/webcrypto/algorithms/ecdsa.cc
@@ -7,7 +7,6 @@ #include <openssl/evp.h> #include "base/logging.h" -#include "base/stl_util.h" #include "components/webcrypto/algorithm_implementation.h" #include "components/webcrypto/algorithms/ec.h" #include "components/webcrypto/algorithms/util.h" @@ -66,16 +65,11 @@ std::vector<uint8_t>* signature) { crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); - const unsigned char* der_data = vector_as_array(signature); crypto::ScopedECDSA_SIG ecdsa_sig( - d2i_ECDSA_SIG(NULL, &der_data, static_cast<long>(signature->size()))); + ECDSA_SIG_from_bytes(signature->data(), signature->size())); if (!ecdsa_sig.get()) return Status::ErrorUnexpected(); - // |der_data| is updated to point to past the end of the DER structure. - if (der_data != vector_as_array(signature) + signature->size()) - return Status::ErrorUnexpected(); - // Determine the maximum length of r and s. size_t order_size_bytes; Status status = GetEcGroupOrderSize(key, &order_size_bytes); @@ -84,7 +78,7 @@ signature->resize(order_size_bytes * 2); - if (!BN_bn2bin_padded(vector_as_array(signature), order_size_bytes, + if (!BN_bn2bin_padded(signature->data(), order_size_bytes, ecdsa_sig.get()->r)) { return Status::ErrorUnexpected(); } @@ -149,7 +143,7 @@ // DER-encode the signature. der_signature->resize(der_encoding_size); - uint8_t* result = vector_as_array(der_signature); + uint8_t* result = der_signature->data(); if (0 > i2d_ECDSA_SIG(ecdsa_sig.get(), &result)) return Status::OperationError(); @@ -205,7 +199,7 @@ } buffer->resize(sig_len); - if (!EVP_DigestSignFinal(ctx.get(), vector_as_array(buffer), &sig_len)) + if (!EVP_DigestSignFinal(ctx.get(), buffer->data(), &sig_len)) return Status::OperationError(); buffer->resize(sig_len); @@ -250,7 +244,7 @@ } *signature_match = - 1 == EVP_DigestVerifyFinal(ctx.get(), vector_as_array(&der_signature), + 1 == EVP_DigestVerifyFinal(ctx.get(), der_signature.data(), der_signature.size()); return Status::Success(); }
diff --git a/components/webcrypto/algorithms/hkdf.cc b/components/webcrypto/algorithms/hkdf.cc index 0ccb8579..2f5dc07 100644 --- a/components/webcrypto/algorithms/hkdf.cc +++ b/components/webcrypto/algorithms/hkdf.cc
@@ -6,7 +6,6 @@ #include <openssl/hkdf.h> #include "base/logging.h" -#include "base/stl_util.h" #include "components/webcrypto/algorithm_implementation.h" #include "components/webcrypto/algorithms/secret_key_util.h" #include "components/webcrypto/algorithms/util.h" @@ -69,10 +68,10 @@ // Algorithm dispatch checks that the algorithm in |base_key| matches // |algorithm|. const std::vector<uint8_t>& raw_key = GetSymmetricKeyData(base_key); - if (!HKDF(vector_as_array(derived_bytes), derived_bytes_len, - digest_algorithm, vector_as_array(&raw_key), raw_key.size(), - params->salt().data(), params->salt().size(), - params->info().data(), params->info().size())) { + if (!HKDF(derived_bytes->data(), derived_bytes_len, digest_algorithm, + raw_key.data(), raw_key.size(), params->salt().data(), + params->salt().size(), params->info().data(), + params->info().size())) { uint32_t error = ERR_get_error(); if (ERR_GET_LIB(error) == ERR_LIB_HKDF && ERR_GET_REASON(error) == HKDF_R_OUTPUT_TOO_LARGE) {
diff --git a/components/webcrypto/algorithms/hmac.cc b/components/webcrypto/algorithms/hmac.cc index 28ef3a05..33d60bb 100644 --- a/components/webcrypto/algorithms/hmac.cc +++ b/components/webcrypto/algorithms/hmac.cc
@@ -6,7 +6,6 @@ #include "base/logging.h" #include "base/numerics/safe_math.h" -#include "base/stl_util.h" #include "components/webcrypto/algorithm_implementation.h" #include "components/webcrypto/algorithms/secret_key_util.h" #include "components/webcrypto/algorithms/util.h" @@ -95,12 +94,12 @@ buffer->resize(hmac_expected_length); crypto::ScopedOpenSSLSafeSizeBuffer<EVP_MAX_MD_SIZE> hmac_result( - vector_as_array(buffer), hmac_expected_length); + buffer->data(), hmac_expected_length); unsigned int hmac_actual_length; - unsigned char* const success = HMAC( - digest_algorithm, vector_as_array(&raw_key), raw_key.size(), data.bytes(), - data.byte_length(), hmac_result.safe_buffer(), &hmac_actual_length); + unsigned char* const success = + HMAC(digest_algorithm, raw_key.data(), raw_key.size(), data.bytes(), + data.byte_length(), hmac_result.safe_buffer(), &hmac_actual_length); if (!success || hmac_actual_length != hmac_expected_length) return Status::OperationError(); @@ -250,10 +249,9 @@ return status; // Do not allow verification of truncated MACs. - *signature_match = - result.size() == signature.byte_length() && - crypto::SecureMemEqual(vector_as_array(&result), signature.bytes(), - signature.byte_length()); + *signature_match = result.size() == signature.byte_length() && + crypto::SecureMemEqual(result.data(), signature.bytes(), + signature.byte_length()); return Status::Success(); }
diff --git a/components/webcrypto/algorithms/hmac_unittest.cc b/components/webcrypto/algorithms/hmac_unittest.cc index 4c8a67aa..f7ae170 100644 --- a/components/webcrypto/algorithms/hmac_unittest.cc +++ b/components/webcrypto/algorithms/hmac_unittest.cc
@@ -3,7 +3,6 @@ // found in the LICENSE file. #include "base/logging.h" -#include "base/stl_util.h" #include "base/values.h" #include "components/webcrypto/algorithm_dispatch.h" #include "components/webcrypto/algorithms/test_helpers.h" @@ -92,7 +91,7 @@ // Ensure truncated signature does not verify by passing one less byte. EXPECT_EQ(Status::Success(), Verify(algorithm, key, - CryptoData(vector_as_array(&output), + CryptoData(output.data(), static_cast<unsigned int>(output.size()) - 1), CryptoData(test_message), &signature_match)); EXPECT_FALSE(signature_match);
diff --git a/components/webcrypto/algorithms/pbkdf2.cc b/components/webcrypto/algorithms/pbkdf2.cc index c3449f5..6c78f51 100644 --- a/components/webcrypto/algorithms/pbkdf2.cc +++ b/components/webcrypto/algorithms/pbkdf2.cc
@@ -76,10 +76,9 @@ const std::vector<uint8_t>& password = GetSymmetricKeyData(base_key); if (!PKCS5_PBKDF2_HMAC( - reinterpret_cast<const char*>(vector_as_array(&password)), - password.size(), params->salt().data(), params->salt().size(), - params->iterations(), digest_algorithm, keylen_bytes, - vector_as_array(derived_bytes))) { + reinterpret_cast<const char*>(password.data()), password.size(), + params->salt().data(), params->salt().size(), params->iterations(), + digest_algorithm, keylen_bytes, derived_bytes->data())) { return Status::OperationError(); } return Status::Success();
diff --git a/components/webcrypto/algorithms/rsa.cc b/components/webcrypto/algorithms/rsa.cc index e789d292..888b157 100644 --- a/components/webcrypto/algorithms/rsa.cc +++ b/components/webcrypto/algorithms/rsa.cc
@@ -7,7 +7,6 @@ #include <openssl/evp.h> #include "base/logging.h" -#include "base/stl_util.h" #include "components/webcrypto/algorithms/asymmetric_key_util.h" #include "components/webcrypto/algorithms/util.h" #include "components/webcrypto/blink_key_handle.h" @@ -232,7 +231,7 @@ // Converts a BIGNUM to a big endian byte array. std::vector<uint8_t> BIGNUMToVector(const BIGNUM* n) { std::vector<uint8_t> v(BN_num_bytes(n)); - BN_bn2bin(n, vector_as_array(&v)); + BN_bn2bin(n, v.data()); return v; }
diff --git a/components/webcrypto/algorithms/rsa_oaep.cc b/components/webcrypto/algorithms/rsa_oaep.cc index 5a697095..6fdc41c83 100644 --- a/components/webcrypto/algorithms/rsa_oaep.cc +++ b/components/webcrypto/algorithms/rsa_oaep.cc
@@ -4,7 +4,6 @@ #include <openssl/evp.h> -#include "base/stl_util.h" #include "components/webcrypto/algorithms/rsa.h" #include "components/webcrypto/algorithms/util.h" #include "components/webcrypto/blink_key_handle.h" @@ -80,8 +79,8 @@ buffer->resize(outlen); // Do the actual encryption/decryption. - if (!encrypt_decrypt_func(ctx.get(), vector_as_array(buffer), &outlen, - data.bytes(), data.byte_length())) { + if (!encrypt_decrypt_func(ctx.get(), buffer->data(), &outlen, data.bytes(), + data.byte_length())) { return Status::OperationError(); } buffer->resize(outlen);
diff --git a/components/webcrypto/algorithms/rsa_oaep_unittest.cc b/components/webcrypto/algorithms/rsa_oaep_unittest.cc index a30d329..66368ad7 100644 --- a/components/webcrypto/algorithms/rsa_oaep_unittest.cc +++ b/components/webcrypto/algorithms/rsa_oaep_unittest.cc
@@ -4,7 +4,6 @@ #include "base/base64url.h" #include "base/logging.h" -#include "base/stl_util.h" #include "components/webcrypto/algorithm_dispatch.h" #include "components/webcrypto/algorithms/test_helpers.h" #include "components/webcrypto/crypto_data.h" @@ -24,7 +23,7 @@ return blink::WebCryptoAlgorithm::adoptParamsAndCreate( blink::WebCryptoAlgorithmIdRsaOaep, new blink::WebCryptoRsaOaepParams( - !label.empty(), vector_as_array(&label), + !label.empty(), label.data(), static_cast<unsigned int>(label.size()))); } @@ -33,7 +32,7 @@ // https://tools.ietf.org/html/draft-ietf-jose-json-web-signature-36#section-2 std::string base64url_encoded; base::Base64UrlEncode( - base::StringPiece(reinterpret_cast<const char*>(vector_as_array(&input)), + base::StringPiece(reinterpret_cast<const char*>(input.data()), input.size()), base::Base64UrlEncodePolicy::OMIT_PADDING, &base64url_encoded); return base64url_encoded;
diff --git a/components/webcrypto/algorithms/rsa_sign.cc b/components/webcrypto/algorithms/rsa_sign.cc index 5c038b54..1ea0b8ea9 100644 --- a/components/webcrypto/algorithms/rsa_sign.cc +++ b/components/webcrypto/algorithms/rsa_sign.cc
@@ -3,7 +3,6 @@ // found in the LICENSE file. #include "base/numerics/safe_math.h" -#include "base/stl_util.h" #include "components/webcrypto/algorithms/rsa_sign.h" #include "components/webcrypto/algorithms/util.h" #include "components/webcrypto/blink_key_handle.h" @@ -102,7 +101,7 @@ } buffer->resize(sig_len); - if (!EVP_DigestSignFinal(ctx.get(), vector_as_array(buffer), &sig_len)) + if (!EVP_DigestSignFinal(ctx.get(), buffer->data(), &sig_len)) return Status::OperationError(); buffer->resize(sig_len);
diff --git a/components/webcrypto/algorithms/rsa_ssa_unittest.cc b/components/webcrypto/algorithms/rsa_ssa_unittest.cc index 31cc967b..360bdb98 100644 --- a/components/webcrypto/algorithms/rsa_ssa_unittest.cc +++ b/components/webcrypto/algorithms/rsa_ssa_unittest.cc
@@ -3,7 +3,6 @@ // found in the LICENSE file. #include "base/logging.h" -#include "base/stl_util.h" #include "base/values.h" #include "components/webcrypto/algorithm_dispatch.h" #include "components/webcrypto/algorithms/test_helpers.h" @@ -546,7 +545,7 @@ // Ensure truncated signature does not verify by passing one less byte. EXPECT_EQ(Status::Success(), Verify(algorithm, public_key, - CryptoData(vector_as_array(&signature), + CryptoData(signature.data(), static_cast<unsigned int>(signature.size()) - 1), CryptoData(data), &signature_match)); EXPECT_FALSE(signature_match);
diff --git a/components/webcrypto/algorithms/secret_key_util.cc b/components/webcrypto/algorithms/secret_key_util.cc index dcdecfa..3110e26 100644 --- a/components/webcrypto/algorithms/secret_key_util.cc +++ b/components/webcrypto/algorithms/secret_key_util.cc
@@ -6,7 +6,6 @@ #include <openssl/rand.h> -#include "base/stl_util.h" #include "components/webcrypto/algorithms/util.h" #include "components/webcrypto/blink_key_handle.h" #include "components/webcrypto/crypto_data.h" @@ -25,10 +24,10 @@ crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); unsigned int keylen_bytes = NumBitsToBytes(keylen_bits); - std::vector<unsigned char> random_bytes(keylen_bytes, 0); + std::vector<uint8_t> random_bytes(keylen_bytes, 0); if (keylen_bytes > 0) { - if (!RAND_bytes(vector_as_array(&random_bytes), keylen_bytes)) + if (!RAND_bytes(random_bytes.data(), keylen_bytes)) return Status::OperationError(); TruncateToBitLength(keylen_bits, &random_bytes); }
diff --git a/components/webcrypto/algorithms/sha.cc b/components/webcrypto/algorithms/sha.cc index 2d8b544..69135cf 100644 --- a/components/webcrypto/algorithms/sha.cc +++ b/components/webcrypto/algorithms/sha.cc
@@ -7,7 +7,6 @@ #include <vector> #include "base/logging.h" -#include "base/stl_util.h" #include "components/webcrypto/algorithm_implementation.h" #include "components/webcrypto/algorithms/util.h" #include "components/webcrypto/crypto_data.h" @@ -58,9 +57,8 @@ Status FinishWithVectorAndStatus(std::vector<uint8_t>* result) { const int hash_expected_size = EVP_MD_CTX_size(digest_context_.get()); result->resize(hash_expected_size); - unsigned char* const hash_buffer = vector_as_array(result); unsigned int hash_buffer_size; // ignored - return FinishInternal(hash_buffer, &hash_buffer_size); + return FinishInternal(result->data(), &hash_buffer_size); } private:
diff --git a/components/webcrypto/algorithms/sha_unittest.cc b/components/webcrypto/algorithms/sha_unittest.cc index 4e82d987..cab92394 100644 --- a/components/webcrypto/algorithms/sha_unittest.cc +++ b/components/webcrypto/algorithms/sha_unittest.cc
@@ -3,7 +3,6 @@ // found in the LICENSE file. #include "base/logging.h" -#include "base/stl_util.h" #include "base/values.h" #include "components/webcrypto/algorithm_dispatch.h" #include "components/webcrypto/algorithms/test_helpers.h" @@ -69,7 +68,7 @@ size_t chunk_length = std::min(kChunkSizeBytes, length - chunk_index); std::vector<uint8_t> chunk(begin, begin + chunk_length); ASSERT_TRUE(chunk.size() > 0); - EXPECT_TRUE(digestor->consume(vector_as_array(&chunk), + EXPECT_TRUE(digestor->consume(chunk.data(), static_cast<unsigned int>(chunk.size()))); chunk_index = chunk_index + chunk_length; begin = begin + chunk_length;
diff --git a/components/webcrypto/algorithms/test_helpers.cc b/components/webcrypto/algorithms/test_helpers.cc index bc036ac..c715c40 100644 --- a/components/webcrypto/algorithms/test_helpers.cc +++ b/components/webcrypto/algorithms/test_helpers.cc
@@ -12,7 +12,6 @@ #include "base/json/json_writer.h" #include "base/logging.h" #include "base/path_service.h" -#include "base/stl_util.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_util.h" #include "base/values.h" @@ -110,10 +109,10 @@ const std::vector<uint8_t>& public_exponent) { DCHECK(blink::WebCryptoAlgorithm::isHash(hash_id)); return blink::WebCryptoAlgorithm::adoptParamsAndCreate( - algorithm_id, new blink::WebCryptoRsaHashedKeyGenParams( - CreateAlgorithm(hash_id), modulus_length, - vector_as_array(&public_exponent), - static_cast<unsigned int>(public_exponent.size()))); + algorithm_id, + new blink::WebCryptoRsaHashedKeyGenParams( + CreateAlgorithm(hash_id), modulus_length, public_exponent.data(), + static_cast<unsigned int>(public_exponent.size()))); } std::vector<uint8_t> Corrupted(const std::vector<uint8_t>& input) { @@ -388,8 +387,8 @@ scoped_ptr<base::DictionaryValue> GetJwkDictionary( const std::vector<uint8_t>& json) { - base::StringPiece json_string( - reinterpret_cast<const char*>(vector_as_array(&json)), json.size()); + base::StringPiece json_string(reinterpret_cast<const char*>(json.data()), + json.size()); scoped_ptr<base::Value> value = base::JSONReader::Read(json_string); EXPECT_TRUE(value.get()); EXPECT_TRUE(value->IsType(base::Value::TYPE_DICTIONARY));
diff --git a/components/webcrypto/algorithms/util.cc b/components/webcrypto/algorithms/util.cc index 43e728cd..4a3b747 100644 --- a/components/webcrypto/algorithms/util.cc +++ b/components/webcrypto/algorithms/util.cc
@@ -9,7 +9,6 @@ #include <openssl/digest.h> #include "base/logging.h" -#include "base/stl_util.h" #include "components/webcrypto/crypto_data.h" #include "components/webcrypto/status.h" #include "crypto/openssl_util.h" @@ -87,8 +86,8 @@ if (!aead_alg) return Status::ErrorUnexpected(); - if (!EVP_AEAD_CTX_init(&ctx, aead_alg, vector_as_array(&raw_key), - raw_key.size(), tag_length_bytes, NULL)) { + if (!EVP_AEAD_CTX_init(&ctx, aead_alg, raw_key.data(), raw_key.size(), + tag_length_bytes, NULL)) { return Status::OperationError(); } @@ -103,7 +102,7 @@ buffer->resize(data.byte_length() - tag_length_bytes); - ok = EVP_AEAD_CTX_open(&ctx, vector_as_array(buffer), &len, buffer->size(), + ok = EVP_AEAD_CTX_open(&ctx, buffer->data(), &len, buffer->size(), iv.bytes(), iv.byte_length(), data.bytes(), data.byte_length(), additional_data.bytes(), additional_data.byte_length()); @@ -112,7 +111,7 @@ // the output buffer is too small). buffer->resize(data.byte_length() + EVP_AEAD_max_overhead(aead_alg)); - ok = EVP_AEAD_CTX_seal(&ctx, vector_as_array(buffer), &len, buffer->size(), + ok = EVP_AEAD_CTX_seal(&ctx, buffer->data(), &len, buffer->size(), iv.bytes(), iv.byte_length(), data.bytes(), data.byte_length(), additional_data.bytes(), additional_data.byte_length());
diff --git a/components/webcrypto/crypto_data.cc b/components/webcrypto/crypto_data.cc index dd369ca..f2937da 100644 --- a/components/webcrypto/crypto_data.cc +++ b/components/webcrypto/crypto_data.cc
@@ -3,7 +3,6 @@ // found in the LICENSE file. #include "components/webcrypto/crypto_data.h" -#include "base/stl_util.h" namespace webcrypto { @@ -15,9 +14,8 @@ } CryptoData::CryptoData(const std::vector<unsigned char>& bytes) - : bytes_(vector_as_array(&bytes)), - byte_length_(static_cast<unsigned int>(bytes.size())) { -} + : bytes_(bytes.data()), + byte_length_(static_cast<unsigned int>(bytes.size())) {} CryptoData::CryptoData(const std::string& bytes) : bytes_(bytes.size() ? reinterpret_cast<const unsigned char*>(bytes.data())
diff --git a/components/webcrypto/webcrypto_impl.cc b/components/webcrypto/webcrypto_impl.cc index 0647b77d..47a0237 100644 --- a/components/webcrypto/webcrypto_impl.cc +++ b/components/webcrypto/webcrypto_impl.cc
@@ -10,7 +10,6 @@ #include "base/logging.h" #include "base/memory/scoped_ptr.h" #include "base/single_thread_task_runner.h" -#include "base/stl_util.h" #include "base/task_runner.h" #include "base/thread_task_runner_handle.h" #include "base/threading/sequenced_worker_pool.h" @@ -118,7 +117,7 @@ // theoretically this could overflow. CompleteWithError(Status::ErrorUnexpected(), result); } else { - result->completeWithBuffer(vector_as_array(&buffer), + result->completeWithBuffer(buffer.data(), static_cast<unsigned int>(buffer.size())); } } @@ -467,7 +466,7 @@ CompleteWithError(state->status, &state->result); } else { state->result.completeWithJson( - reinterpret_cast<const char*>(vector_as_array(&state->buffer)), + reinterpret_cast<const char*>(state->buffer.data()), static_cast<unsigned int>(state->buffer.size())); } }
diff --git a/components/webp_transcode/BUILD.gn b/components/webp_transcode/BUILD.gn index 2e15974..f62f6913 100644 --- a/components/webp_transcode/BUILD.gn +++ b/components/webp_transcode/BUILD.gn
@@ -28,11 +28,11 @@ ] deps = [ + ":webp_transcode", "//base", "//net", "//testing/gmock", "//testing/gtest", "//third_party/ocmock", - ":webp_transcode", ] }
diff --git a/content/app/BUILD.gn b/content/app/BUILD.gn index b83b529..7d3e5ee 100644 --- a/content/app/BUILD.gn +++ b/content/app/BUILD.gn
@@ -3,6 +3,7 @@ # found in the LICENSE file. import("//build/config/chrome_build.gni") +import("//build/config/ui.gni") content_app_sources = [ "android/app_jni_registrar.cc", @@ -49,8 +50,10 @@ "//device/vibration", "//skia", "//third_party/android_tools:cpu_features", - "//ui/android", ] + if (!use_aura) { + content_app_deps += [ "//ui/android" ] + } } if (is_ios) {
diff --git a/content/app/android/library_loader_hooks.cc b/content/app/android/library_loader_hooks.cc index 0d36b85..eae2537 100644 --- a/content/app/android/library_loader_hooks.cc +++ b/content/app/android/library_loader_hooks.cc
@@ -62,11 +62,6 @@ if (!ui::events::android::RegisterJni(env)) return false; -#if !defined(USE_AURA) - if (!ui::shell_dialogs::RegisterJni(env)) - return false; -#endif - if (!content::android::RegisterCommonJni(env)) return false; @@ -85,8 +80,13 @@ if (!media::midi::RegisterJni(env)) return false; +#if !defined(USE_AURA) + if (!ui::shell_dialogs::RegisterJni(env)) + return false; + if (!ui::RegisterUIAndroidJni(env)) return false; +#endif g_jni_init_done = true; } @@ -97,17 +97,17 @@ bool LibraryLoaded(JNIEnv* env, jclass clazz) { base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); + // Enable startup tracing asap to avoid early TRACE_EVENT calls being ignored. if (command_line->HasSwitch(switches::kTraceStartup)) { base::trace_event::TraceConfig trace_config( command_line->GetSwitchValueASCII(switches::kTraceStartup), ""); base::trace_event::TraceLog::GetInstance()->SetEnabled( trace_config, base::trace_event::TraceLog::RECORDING_MODE); - } else { - if (tracing::TraceConfigFile::GetInstance()->IsEnabled()) { - base::trace_event::TraceLog::GetInstance()->SetEnabled( - tracing::TraceConfigFile::GetInstance()->GetTraceConfig(), - base::trace_event::TraceLog::RECORDING_MODE); - } + } else if (tracing::TraceConfigFile::GetInstance()->IsEnabled()) { + // This checks kTraceConfigFile switch. + base::trace_event::TraceLog::GetInstance()->SetEnabled( + tracing::TraceConfigFile::GetInstance()->GetTraceConfig(), + base::trace_event::TraceLog::RECORDING_MODE); } // Android's main browser loop is custom so we set the browser
diff --git a/content/app/content_main_runner.cc b/content/app/content_main_runner.cc index 6df8137..b352c3e 100644 --- a/content/app/content_main_runner.cc +++ b/content/app/content_main_runner.cc
@@ -615,8 +615,10 @@ base::RouteStdioToConsole(true); #endif +#if !defined(OS_ANDROID) // Enable startup tracing asap to avoid early TRACE_EVENT calls being - // ignored. + // ignored. For Android, startup tracing is enabled in an even earlier place + // content/app/android/library_loader_hooks.cc. if (command_line.HasSwitch(switches::kTraceStartup)) { base::trace_event::TraceConfig trace_config( command_line.GetSwitchValueASCII(switches::kTraceStartup), @@ -627,11 +629,13 @@ } else if (process_type != switches::kZygoteProcess && process_type != switches::kRendererProcess) { if (tracing::TraceConfigFile::GetInstance()->IsEnabled()) { + // This checks kTraceConfigFile switch. base::trace_event::TraceLog::GetInstance()->SetEnabled( tracing::TraceConfigFile::GetInstance()->GetTraceConfig(), base::trace_event::TraceLog::RECORDING_MODE); } } +#endif // !OS_ANDROID #if defined(OS_WIN) // Enable exporting of events to ETW if requested on the command line.
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn index fb2092e..6f6c3b9 100644 --- a/content/browser/BUILD.gn +++ b/content/browser/BUILD.gn
@@ -381,6 +381,7 @@ ".", "//content") sources -= [ "renderer_host/begin_frame_observer_proxy.cc" ] + deps += [ "//ui/android" ] } deps -= [ "//device/battery" ] @@ -388,7 +389,6 @@ "//content/public/android:jni", "//media", "//mojo/android:libsystem_java", - "//ui/android", ] defines += [ "APPCACHE_USE_SIMPLE_CACHE" ] libs += [ "jnigraphics" ]
diff --git a/content/browser/android/url_request_content_job.cc b/content/browser/android/url_request_content_job.cc index 1bcbf210..6e661a2 100644 --- a/content/browser/android/url_request_content_job.cc +++ b/content/browser/android/url_request_content_job.cc
@@ -11,6 +11,7 @@ #include "base/task_runner.h" #include "net/base/file_stream.h" #include "net/base/io_buffer.h" +#include "net/base/net_errors.h" #include "net/http/http_util.h" #include "net/url_request/url_request_error_job.h" #include "url/gurl.h" @@ -33,7 +34,6 @@ content_path_(content_path), stream_(new net::FileStream(content_task_runner)), content_task_runner_(content_task_runner), - range_parse_result_(net::OK), remaining_bytes_(0), io_pending_(false), weak_ptr_factory_(this) {} @@ -56,28 +56,43 @@ net::URLRequestJob::Kill(); } -int URLRequestContentJob::ReadRawData(net::IOBuffer* dest, int dest_size) { +bool URLRequestContentJob::ReadRawData(net::IOBuffer* dest, + int dest_size, + int* bytes_read) { DCHECK_GT(dest_size, 0); + DCHECK(bytes_read); DCHECK_GE(remaining_bytes_, 0); if (remaining_bytes_ < dest_size) - dest_size = remaining_bytes_; + dest_size = static_cast<int>(remaining_bytes_); // If we should copy zero bytes because |remaining_bytes_| is zero, short // circuit here. - if (!dest_size) - return 0; + if (!dest_size) { + *bytes_read = 0; + return true; + } - int rv = stream_->Read(dest, dest_size, - base::Bind(&URLRequestContentJob::DidRead, - weak_ptr_factory_.GetWeakPtr())); + int rv = + stream_->Read(dest, dest_size, base::Bind(&URLRequestContentJob::DidRead, + weak_ptr_factory_.GetWeakPtr(), + make_scoped_refptr(dest))); + if (rv >= 0) { + // Data is immediately available. + *bytes_read = rv; + remaining_bytes_ -= rv; + DCHECK_GE(remaining_bytes_, 0); + return true; + } + + // Otherwise, a read error occured. We may just need to wait... if (rv == net::ERR_IO_PENDING) { io_pending_ = true; - } else if (rv > 0) { - remaining_bytes_ -= rv; + SetStatus(net::URLRequestStatus(net::URLRequestStatus::IO_PENDING, 0)); + } else { + NotifyDone(net::URLRequestStatus(net::URLRequestStatus::FAILED, rv)); } - DCHECK_GE(remaining_bytes_, 0); - return rv; + return false; } bool URLRequestContentJob::IsRedirectResponse(GURL* location, @@ -100,16 +115,15 @@ if (!headers.GetHeader(net::HttpRequestHeaders::kRange, &range_header)) return; - // Currently this job only cares about the Range header. Note that validation - // is deferred to DidOpen(), because NotifyStartError is not legal to call - // since the job has not started. + // We only care about "Range" header here. std::vector<net::HttpByteRange> ranges; if (net::HttpUtil::ParseRangeHeader(range_header, &ranges)) { if (ranges.size() == 1) { byte_range_ = ranges[0]; } else { // We don't support multiple range requests. - range_parse_result_ = net::ERR_REQUEST_RANGE_NOT_SATISFIABLE; + NotifyDone(net::URLRequestStatus(net::URLRequestStatus::FAILED, + net::ERR_REQUEST_RANGE_NOT_SATISFIABLE)); } } } @@ -146,20 +160,13 @@ void URLRequestContentJob::DidOpen(int result) { if (result != net::OK) { - NotifyStartError( - net::URLRequestStatus(net::URLRequestStatus::FAILED, result)); - return; - } - - if (range_parse_result_ != net::OK) { - NotifyStartError(net::URLRequestStatus(net::URLRequestStatus::FAILED, - range_parse_result_)); + NotifyDone(net::URLRequestStatus(net::URLRequestStatus::FAILED, result)); return; } if (!byte_range_.ComputeBounds(meta_info_.content_size)) { - NotifyStartError(net::URLRequestStatus( - net::URLRequestStatus::FAILED, net::ERR_REQUEST_RANGE_NOT_SATISFIABLE)); + NotifyDone(net::URLRequestStatus(net::URLRequestStatus::FAILED, + net::ERR_REQUEST_RANGE_NOT_SATISFIABLE)); return; } @@ -186,8 +193,8 @@ void URLRequestContentJob::DidSeek(int64 result) { if (result != byte_range_.first_byte_position()) { - NotifyStartError(net::URLRequestStatus( - net::URLRequestStatus::FAILED, net::ERR_REQUEST_RANGE_NOT_SATISFIABLE)); + NotifyDone(net::URLRequestStatus(net::URLRequestStatus::FAILED, + net::ERR_REQUEST_RANGE_NOT_SATISFIABLE)); return; } @@ -195,16 +202,24 @@ NotifyHeadersComplete(); } -void URLRequestContentJob::DidRead(int result) { - DCHECK(io_pending_); - io_pending_ = false; - +void URLRequestContentJob::DidRead(scoped_refptr<net::IOBuffer> buf, + int result) { if (result > 0) { + SetStatus(net::URLRequestStatus()); // Clear the IO_PENDING status remaining_bytes_ -= result; DCHECK_GE(remaining_bytes_, 0); } - ReadRawDataComplete(result); + DCHECK(io_pending_); + io_pending_ = false; + + if (result == 0) { + NotifyDone(net::URLRequestStatus()); + } else if (result < 0) { + NotifyDone(net::URLRequestStatus(net::URLRequestStatus::FAILED, result)); + } + + NotifyReadComplete(result); } } // namespace content
diff --git a/content/browser/android/url_request_content_job.h b/content/browser/android/url_request_content_job.h index dad9fbfc..5d3d9336 100644 --- a/content/browser/android/url_request_content_job.h +++ b/content/browser/android/url_request_content_job.h
@@ -12,7 +12,6 @@ #include "base/memory/ref_counted.h" #include "base/memory/weak_ptr.h" #include "content/common/content_export.h" -#include "net/base/net_errors.h" #include "net/http/http_byte_range.h" #include "net/url_request/url_request.h" #include "net/url_request/url_request_job.h" @@ -43,7 +42,7 @@ // net::URLRequestJob: void Start() override; void Kill() override; - int ReadRawData(net::IOBuffer* buf, int buf_size) override; + bool ReadRawData(net::IOBuffer* buf, int buf_size, int* bytes_read) override; bool IsRedirectResponse(GURL* location, int* http_status_code) override; bool GetMimeType(std::string* mime_type) const override; void SetExtraRequestHeaders(const net::HttpRequestHeaders& headers) override; @@ -80,7 +79,7 @@ void DidSeek(int64 result); // Callback after data is asynchronously read from the content URI into |buf|. - void DidRead(int result); + void DidRead(scoped_refptr<net::IOBuffer> buf, int result); // The full path of the content URI. base::FilePath content_path_; @@ -90,7 +89,6 @@ const scoped_refptr<base::TaskRunner> content_task_runner_; net::HttpByteRange byte_range_; - net::Error range_parse_result_; int64 remaining_bytes_; bool io_pending_;
diff --git a/content/browser/appcache/appcache_update_job.cc b/content/browser/appcache/appcache_update_job.cc index e0c23726..4b0d922 100644 --- a/content/browser/appcache/appcache_update_job.cc +++ b/content/browser/appcache/appcache_update_job.cc
@@ -406,11 +406,13 @@ if (internal_state_ != COMPLETED) Cancel(); - DCHECK(!manifest_fetcher_); - DCHECK(pending_url_fetches_.empty()); DCHECK(!inprogress_cache_.get()); DCHECK(pending_master_entries_.empty()); - DCHECK(master_entry_fetches_.empty()); + + // The job must not outlive any of its fetchers. + CHECK(!manifest_fetcher_); + CHECK(pending_url_fetches_.empty()); + CHECK(master_entry_fetches_.empty()); if (group_) group_->SetUpdateAppCacheStatus(AppCacheGroup::IDLE); @@ -427,6 +429,9 @@ DCHECK(!new_master_resource.has_ref()); DCHECK(new_master_resource.GetOrigin() == manifest_url_.GetOrigin()); + if (ContainsKey(failed_master_entries_, new_master_resource)) + return; + // Cannot add more to this update if already terminating. if (IsTerminating()) { group_->QueueUpdate(host, new_master_resource); @@ -864,6 +869,8 @@ } hosts.clear(); + failed_master_entries_.insert(url); + const char* kFormatString = "Manifest fetch failed (%d) %s"; std::string message = FormatUrlErrorMessage( kFormatString, request->url(), fetcher->result(), response_code);
diff --git a/content/browser/appcache/appcache_update_job.h b/content/browser/appcache/appcache_update_job.h index e876ad07..eaee83b9 100644 --- a/content/browser/appcache/appcache_update_job.h +++ b/content/browser/appcache/appcache_update_job.h
@@ -283,6 +283,7 @@ PendingMasters pending_master_entries_; size_t master_entries_completed_; + std::set<GURL> failed_master_entries_; // TODO(jennb): Delete when update no longer fetches master entries directly. // Helper containers to track which pending master entries have yet to be
diff --git a/content/browser/appcache/appcache_url_request_job.cc b/content/browser/appcache/appcache_url_request_job.cc index de924a1..82997f7 100644 --- a/content/browser/appcache/appcache_url_request_job.cc +++ b/content/browser/appcache/appcache_url_request_job.cc
@@ -341,6 +341,7 @@ void AppCacheURLRequestJob::OnReadComplete(int result) { DCHECK(is_delivering_appcache_response()); if (result == 0) { + NotifyDone(net::URLRequestStatus()); AppCacheHistograms::CountResponseRetrieval( true, is_main_resource_, manifest_url_.GetOrigin()); } else if (result < 0) { @@ -348,10 +349,13 @@ storage_->service()->CheckAppCacheResponse(manifest_url_, cache_id_, entry_.response_id()); } + NotifyDone(net::URLRequestStatus(net::URLRequestStatus::FAILED, result)); AppCacheHistograms::CountResponseRetrieval( false, is_main_resource_, manifest_url_.GetOrigin()); + } else { + SetStatus(net::URLRequestStatus()); // Clear the IO_PENDING status } - ReadRawDataComplete(result); + NotifyReadComplete(result); } // net::URLRequestJob overrides ------------------------------------------------ @@ -420,14 +424,18 @@ return http_info()->headers->response_code(); } -int AppCacheURLRequestJob::ReadRawData(net::IOBuffer* buf, int buf_size) { +bool AppCacheURLRequestJob::ReadRawData(net::IOBuffer* buf, + int buf_size, + int* bytes_read) { DCHECK(is_delivering_appcache_response()); DCHECK_NE(buf_size, 0); + DCHECK(bytes_read); DCHECK(!reader_->IsReadPending()); reader_->ReadData(buf, buf_size, base::Bind(&AppCacheURLRequestJob::OnReadComplete, base::Unretained(this))); - return net::ERR_IO_PENDING; + SetStatus(net::URLRequestStatus(net::URLRequestStatus::IO_PENDING, 0)); + return false; } void AppCacheURLRequestJob::SetExtraRequestHeaders(
diff --git a/content/browser/appcache/appcache_url_request_job.h b/content/browser/appcache/appcache_url_request_job.h index 8f51e7b..95a3e18 100644 --- a/content/browser/appcache/appcache_url_request_job.h +++ b/content/browser/appcache/appcache_url_request_job.h
@@ -148,7 +148,7 @@ net::LoadState GetLoadState() const override; bool GetCharset(std::string* charset) override; void GetResponseInfo(net::HttpResponseInfo* info) override; - int ReadRawData(net::IOBuffer* buf, int buf_size) override; + bool ReadRawData(net::IOBuffer* buf, int buf_size, int* bytes_read) override; // Sets extra request headers for Job types that support request headers. // This is how we get informed of range-requests.
diff --git a/content/browser/browser_child_process_host_impl.cc b/content/browser/browser_child_process_host_impl.cc index c9a61c6..b871aa92 100644 --- a/content/browser/browser_child_process_host_impl.cc +++ b/content/browser/browser_child_process_host_impl.cc
@@ -12,7 +12,6 @@ #include "base/lazy_instance.h" #include "base/logging.h" #include "base/metrics/histogram.h" -#include "base/profiler/scoped_tracker.h" #include "base/stl_util.h" #include "base/strings/string_util.h" #include "base/synchronization/waitable_event.h" @@ -142,7 +141,7 @@ AddFilter(new TraceMessageFilter(data_.id)); AddFilter(new ProfilerMessageFilter(process_type)); AddFilter(new HistogramMessageFilter); - AddFilter(new MemoryMessageFilter(this, process_type)); + AddFilter(new MemoryMessageFilter); g_child_process_list.Get().push_back(this); GetContentClient()->browser()->BrowserChildProcessHostCreated(this); @@ -397,11 +396,6 @@ void BrowserChildProcessHostImpl::OnProcessLaunched() { DCHECK_CURRENTLY_ON(BrowserThread::IO); - // TODO(erikchen): Remove ScopedTracker below once http://crbug.com/465841 - // is fixed. - tracked_objects::ScopedTracker tracking_profile( - FROM_HERE_WITH_EXPLICIT_FUNCTION( - "465841 BrowserChildProcessHostImpl::OnProcessLaunched")); const base::Process& process = child_process_->GetProcess(); DCHECK(process.IsValid());
diff --git a/content/browser/browser_main_loop.cc b/content/browser/browser_main_loop.cc index 12903fa..57a74fc 100644 --- a/content/browser/browser_main_loop.cc +++ b/content/browser/browser_main_loop.cc
@@ -598,10 +598,27 @@ if (parts_) parts_->PostMainMessageLoopStart(); + // Start startup tracing through TracingController's interface. TraceLog has + // been enabled in content_main_runner where threads are not available. Now We + // need to start tracing for all other tracing agents, which require threads. + if (parsed_command_line_.HasSwitch(switches::kTraceStartup)) { + base::trace_event::TraceConfig trace_config( + parsed_command_line_.GetSwitchValueASCII(switches::kTraceStartup), + base::trace_event::RECORD_UNTIL_FULL); + TracingController::GetInstance()->StartTracing( + trace_config, + TracingController::StartTracingDoneCallback()); + } else if (tracing::TraceConfigFile::GetInstance()->IsEnabled()) { + // This checks kTraceConfigFile switch. + TracingController::GetInstance()->StartTracing( + tracing::TraceConfigFile::GetInstance()->GetTraceConfig(), + TracingController::StartTracingDoneCallback()); + } #if !defined(OS_IOS) - // Start tracing to a file if needed. Only do this after starting the main - // message loop to avoid calling MessagePumpForUI::ScheduleWork() before - // MessagePumpForUI::Start() as it will crash the browser. + // Start tracing to a file for certain duration if needed. Only do this after + // starting the main message loop to avoid calling + // MessagePumpForUI::ScheduleWork() before MessagePumpForUI::Start() as it + // will crash the browser. if (is_tracing_startup_for_duration_) { TRACE_EVENT0("startup", "BrowserMainLoop::InitStartupTracingForDuration"); InitStartupTracingForDuration(parsed_command_line_); @@ -1421,9 +1438,6 @@ const base::CommandLine& command_line) { DCHECK(is_tracing_startup_for_duration_); - // Initialize the tracing controller, required for memory tracing. - TracingController::GetInstance(); - startup_trace_file_ = GetStartupTraceFileName(parsed_command_line_); int delay_secs = 5;
diff --git a/content/browser/child_process_launcher.cc b/content/browser/child_process_launcher.cc index e54cada9..6b71c84 100644 --- a/content/browser/child_process_launcher.cc +++ b/content/browser/child_process_launcher.cc
@@ -12,7 +12,6 @@ #include "base/memory/scoped_ptr.h" #include "base/metrics/histogram.h" #include "base/process/process.h" -#include "base/profiler/scoped_tracker.h" #include "base/strings/string_number_conversions.h" #include "base/synchronization/lock.h" #include "base/threading/thread.h" @@ -445,12 +444,6 @@ if (!process.IsValid()) LOG(ERROR) << "Failed to launch child process"; - // TODO(erikchen): Remove ScopedTracker below once http://crbug.com/465841 - // is fixed. - tracked_objects::ScopedTracker tracking_profile1( - FROM_HERE_WITH_EXPLICIT_FUNCTION( - "465841 ChildProcessLauncher::Context::Notify::Start")); - if (instance.get()) { instance->Notify(zygote, #if defined(OS_ANDROID) @@ -458,11 +451,6 @@ #endif process.Pass()); } else { - // TODO(erikchen): Remove ScopedTracker below once http://crbug.com/465841 - // is fixed. - tracked_objects::ScopedTracker tracking_profile4( - FROM_HERE_WITH_EXPLICIT_FUNCTION( - "465841 ChildProcessLauncher::Context::Notify::ProcessTerminate")); if (process.IsValid() && terminate_on_shutdown) { // On Posix, EnsureProcessTerminated can lead to 2 seconds of sleep! So // don't this on the UI/IO threads. @@ -487,18 +475,8 @@ zygote_ = zygote; #endif if (process_.IsValid()) { - // TODO(erikchen): Remove ScopedTracker below once http://crbug.com/465841 - // is fixed. - tracked_objects::ScopedTracker tracking_profile2( - FROM_HERE_WITH_EXPLICIT_FUNCTION( - "465841 ChildProcessLauncher::Context::Notify::ProcessLaunched")); client_->OnProcessLaunched(); } else { - // TODO(erikchen): Remove ScopedTracker below once http://crbug.com/465841 - // is fixed. - tracked_objects::ScopedTracker tracking_profile3( - FROM_HERE_WITH_EXPLICIT_FUNCTION( - "465841 ChildProcessLauncher::Context::Notify::ProcessFailed")); termination_status_ = base::TERMINATION_STATUS_LAUNCH_FAILED; client_->OnProcessLaunchFailed(); }
diff --git a/content/browser/devtools/browser_devtools_agent_host.cc b/content/browser/devtools/browser_devtools_agent_host.cc index d045571..d7c3423 100644 --- a/content/browser/devtools/browser_devtools_agent_host.cc +++ b/content/browser/devtools/browser_devtools_agent_host.cc
@@ -31,10 +31,7 @@ tethering_task_runner)), tracing_handler_(new devtools::tracing::TracingHandler( devtools::tracing::TracingHandler::Browser, GetIOContext())), - protocol_handler_(new DevToolsProtocolHandler( - this, - base::Bind(&BrowserDevToolsAgentHost::SendMessageToClient, - base::Unretained(this)))) { + protocol_handler_(new DevToolsProtocolHandler(this)) { DevToolsProtocolDispatcher* dispatcher = protocol_handler_->dispatcher(); dispatcher->SetIOHandler(io_handler_.get()); dispatcher->SetMemoryHandler(memory_handler_.get()); @@ -74,7 +71,7 @@ bool BrowserDevToolsAgentHost::DispatchProtocolMessage( const std::string& message) { - protocol_handler_->HandleMessage(message); + protocol_handler_->HandleMessage(session_id(), message); return true; }
diff --git a/content/browser/devtools/devtools_agent_host_impl.cc b/content/browser/devtools/devtools_agent_host_impl.cc index 4d93551..7385def 100644 --- a/content/browser/devtools/devtools_agent_host_impl.cc +++ b/content/browser/devtools/devtools_agent_host_impl.cc
@@ -76,8 +76,7 @@ } DevToolsAgentHostImpl::DevToolsAgentHostImpl() - : id_(base::GenerateGUID()), - client_(NULL) { + : id_(base::GenerateGUID()), session_id_(0), client_(NULL) { DCHECK_CURRENTLY_ON(BrowserThread::UI); g_instances.Get()[id_] = this; } @@ -106,6 +105,7 @@ void DevToolsAgentHostImpl::AttachClient(DevToolsAgentHostClient* client) { scoped_refptr<DevToolsAgentHostImpl> protect(this); + ++session_id_; if (client_) { client_->AgentHostClosed(this, true); InnerDetach(); @@ -153,6 +153,16 @@ void DevToolsAgentHostImpl::ConnectWebContents(WebContents* wc) { } +void DevToolsAgentHostImpl::SendProtocolResponse(int session_id, + const std::string& message) { + SendMessageToClient(session_id, message); +} + +void DevToolsAgentHostImpl::SendProtocolNotification( + const std::string& message) { + SendMessageToClient(session_id_, message); +} + void DevToolsAgentHostImpl::HostClosed() { if (!client_) return; @@ -164,9 +174,13 @@ client->AgentHostClosed(this, false); } -void DevToolsAgentHostImpl::SendMessageToClient(const std::string& message) { +void DevToolsAgentHostImpl::SendMessageToClient(int session_id, + const std::string& message) { if (!client_) return; + // Filter any messages from previous sessions. + if (session_id != session_id_) + return; client_->DispatchProtocolMessage(this, message); } @@ -249,7 +263,7 @@ if (chunk.is_first && chunk.is_last) { CHECK(message_buffer_size_ == 0); - callback_.Run(chunk.data); + callback_.Run(chunk.session_id, chunk.data); return; } @@ -265,7 +279,7 @@ if (chunk.is_last) { CHECK(message_buffer_.size() == message_buffer_size_); - callback_.Run(message_buffer_); + callback_.Run(chunk.session_id, message_buffer_); message_buffer_ = std::string(); message_buffer_size_ = 0; }
diff --git a/content/browser/devtools/devtools_agent_host_impl.h b/content/browser/devtools/devtools_agent_host_impl.h index 8474c0a..2dc09cc 100644 --- a/content/browser/devtools/devtools_agent_host_impl.h +++ b/content/browser/devtools/devtools_agent_host_impl.h
@@ -9,6 +9,7 @@ #include "base/compiler_specific.h" #include "content/browser/devtools/devtools_io_context.h" +#include "content/browser/devtools/protocol/devtools_protocol_delegate.h" #include "content/common/content_export.h" #include "content/common/devtools_messages.h" #include "content/public/browser/devtools_agent_host.h" @@ -22,7 +23,8 @@ class BrowserContext; // Describes interface for managing devtools agents from the browser process. -class CONTENT_EXPORT DevToolsAgentHostImpl : public DevToolsAgentHost { +class CONTENT_EXPORT DevToolsAgentHostImpl : public DevToolsAgentHost, + public DevToolsProtocolDelegate { public: // Informs the hosted agent that a client host has attached. virtual void Attach() = 0; @@ -44,14 +46,21 @@ void DisconnectWebContents() override; void ConnectWebContents(WebContents* wc) override; + // DevToolsProtocolDelegate implementation. + void SendProtocolResponse(int session_id, + const std::string& message) override; + void SendProtocolNotification(const std::string& message) override; + protected: DevToolsAgentHostImpl(); ~DevToolsAgentHostImpl() override; void HostClosed(); - void SendMessageToClient(const std::string& message); + void SendMessageToClient(int session_id, const std::string& message); devtools::DevToolsIOContext* GetIOContext() { return &io_context_; } + int session_id() { DCHECK(client_); return session_id_; } + static void NotifyCallbacks(DevToolsAgentHostImpl* agent_host, bool attached); private: @@ -59,13 +68,14 @@ void InnerDetach(); const std::string id_; + int session_id_; DevToolsAgentHostClient* client_; devtools::DevToolsIOContext io_context_; }; class DevToolsMessageChunkProcessor { public: - using SendMessageCallback = base::Callback<void(const std::string&)>; + using SendMessageCallback = base::Callback<void(int, const std::string&)>; explicit DevToolsMessageChunkProcessor(const SendMessageCallback& callback); ~DevToolsMessageChunkProcessor();
diff --git a/content/browser/devtools/devtools_protocol_handler.cc b/content/browser/devtools/devtools_protocol_handler.cc index 86ccd8e..9f69cfb 100644 --- a/content/browser/devtools/devtools_protocol_handler.cc +++ b/content/browser/devtools/devtools_protocol_handler.cc
@@ -7,6 +7,7 @@ #include "base/bind.h" #include "base/json/json_reader.h" #include "base/json/json_writer.h" +#include "content/browser/devtools/devtools_agent_host_impl.h" #include "content/browser/devtools/devtools_manager.h" #include "content/public/browser/devtools_manager_delegate.h" @@ -36,35 +37,35 @@ } // namespace DevToolsProtocolHandler::DevToolsProtocolHandler( - DevToolsAgentHost* agent_host, const Notifier& notifier) - : agent_host_(agent_host), - client_(notifier), - dispatcher_(notifier) { -} + DevToolsAgentHostImpl* agent_host) + : agent_host_(agent_host), client_(agent_host), dispatcher_(agent_host) {} DevToolsProtocolHandler::~DevToolsProtocolHandler() { } -void DevToolsProtocolHandler::HandleMessage(const std::string& message) { - scoped_ptr<base::DictionaryValue> command = ParseCommand(message); +void DevToolsProtocolHandler::HandleMessage(int session_id, + const std::string& message) { + scoped_ptr<base::DictionaryValue> command = ParseCommand(session_id, message); if (!command) return; - if (PassCommandToDelegate(command.get())) + if (PassCommandToDelegate(session_id, command.get())) return; - HandleCommand(command.Pass()); + HandleCommand(session_id, command.Pass()); } -bool DevToolsProtocolHandler::HandleOptionalMessage( - const std::string& message, int* call_id) { - scoped_ptr<base::DictionaryValue> command = ParseCommand(message); +bool DevToolsProtocolHandler::HandleOptionalMessage(int session_id, + const std::string& message, + int* call_id) { + scoped_ptr<base::DictionaryValue> command = ParseCommand(session_id, message); if (!command) return true; - if (PassCommandToDelegate(command.get())) + if (PassCommandToDelegate(session_id, command.get())) return true; - return HandleOptionalCommand(command.Pass(), call_id); + return HandleOptionalCommand(session_id, command.Pass(), call_id); } bool DevToolsProtocolHandler::PassCommandToDelegate( + int session_id, base::DictionaryValue* command) { DevToolsManagerDelegate* delegate = DevToolsManager::GetInstance()->delegate(); @@ -74,41 +75,41 @@ scoped_ptr<base::DictionaryValue> response( delegate->HandleCommand(agent_host_, command)); if (response) { - std::string json_response; - base::JSONWriter::Write(*response, &json_response); - client_.SendRawMessage(json_response); + client_.SendMessage(session_id, *response); return true; } return false; } -scoped_ptr<base::DictionaryValue> -DevToolsProtocolHandler::ParseCommand(const std::string& message) { +scoped_ptr<base::DictionaryValue> DevToolsProtocolHandler::ParseCommand( + int session_id, + const std::string& message) { scoped_ptr<base::Value> value = base::JSONReader::Read(message); if (!value || !value->IsType(base::Value::TYPE_DICTIONARY)) { - client_.SendError(DevToolsProtocolClient::kNoId, - Response(kStatusParseError, - "Message must be in JSON format")); + client_.SendError( + DevToolsCommandId(DevToolsCommandId::kNoId, session_id), + Response(kStatusParseError, "Message must be in JSON format")); return nullptr; } scoped_ptr<base::DictionaryValue> command = make_scoped_ptr(static_cast<base::DictionaryValue*>(value.release())); - int id = DevToolsProtocolClient::kNoId; - bool ok = command->GetInteger(kIdParam, &id) && id >= 0; + int call_id = DevToolsCommandId::kNoId; + bool ok = command->GetInteger(kIdParam, &call_id) && call_id >= 0; if (!ok) { - client_.SendError(id, Response(kStatusInvalidRequest, - "The type of 'id' property must be number")); + client_.SendError(DevToolsCommandId(call_id, session_id), + Response(kStatusInvalidRequest, + "The type of 'id' property must be number")); return nullptr; } std::string method; ok = command->GetString(kMethodParam, &method); if (!ok) { - client_.SendError(id, - Response(kStatusInvalidRequest, - "The type of 'method' property must be string")); + client_.SendError(DevToolsCommandId(call_id, session_id), + Response(kStatusInvalidRequest, + "The type of 'method' property must be string")); return nullptr; } @@ -116,34 +117,39 @@ } void DevToolsProtocolHandler::HandleCommand( + int session_id, scoped_ptr<base::DictionaryValue> command) { - int id = DevToolsProtocolClient::kNoId; + int call_id = DevToolsCommandId::kNoId; std::string method; - command->GetInteger(kIdParam, &id); + command->GetInteger(kIdParam, &call_id); command->GetString(kMethodParam, &method); DevToolsProtocolDispatcher::CommandHandler command_handler( dispatcher_.FindCommandHandler(method)); if (command_handler.is_null()) { - client_.SendError(id, Response(kStatusNoSuchMethod, "No such method")); + client_.SendError(DevToolsCommandId(call_id, session_id), + Response(kStatusNoSuchMethod, "No such method")); return; } bool result = - command_handler.Run(id, TakeDictionary(command.get(), kParamsParam)); + command_handler.Run(DevToolsCommandId(call_id, session_id), + TakeDictionary(command.get(), kParamsParam)); DCHECK(result); } bool DevToolsProtocolHandler::HandleOptionalCommand( - scoped_ptr<base::DictionaryValue> command, int* call_id) { - *call_id = DevToolsProtocolClient::kNoId; + int session_id, + scoped_ptr<base::DictionaryValue> command, + int* call_id) { + *call_id = DevToolsCommandId::kNoId; std::string method; command->GetInteger(kIdParam, call_id); command->GetString(kMethodParam, &method); DevToolsProtocolDispatcher::CommandHandler command_handler( dispatcher_.FindCommandHandler(method)); if (!command_handler.is_null()) { - return command_handler.Run( - *call_id, TakeDictionary(command.get(), kParamsParam)); + return command_handler.Run(DevToolsCommandId(*call_id, session_id), + TakeDictionary(command.get(), kParamsParam)); } return false; }
diff --git a/content/browser/devtools/devtools_protocol_handler.h b/content/browser/devtools/devtools_protocol_handler.h index 299b342..32f49287 100644 --- a/content/browser/devtools/devtools_protocol_handler.h +++ b/content/browser/devtools/devtools_protocol_handler.h
@@ -10,26 +10,30 @@ namespace content { class DevToolsAgentHost; +class DevToolsAgentHostImpl; +class DevToolsProtocolDelegate; class DevToolsProtocolHandler { public: using Response = DevToolsProtocolClient::Response; - using Notifier = base::Callback<void(const std::string& message)>; - DevToolsProtocolHandler(DevToolsAgentHost* agent_host, - const Notifier& notifier); + explicit DevToolsProtocolHandler(DevToolsAgentHostImpl* agent_host); virtual ~DevToolsProtocolHandler(); - void HandleMessage(const std::string& message); - bool HandleOptionalMessage(const std::string& message, int* call_id); + void HandleMessage(int session_id, const std::string& message); + bool HandleOptionalMessage(int session_id, + const std::string& message, + int* call_id); DevToolsProtocolDispatcher* dispatcher() { return &dispatcher_; } private: - scoped_ptr<base::DictionaryValue> ParseCommand(const std::string& message); - bool PassCommandToDelegate(base::DictionaryValue* command); - void HandleCommand(scoped_ptr<base::DictionaryValue> command); - bool HandleOptionalCommand(scoped_ptr<base::DictionaryValue> command, + scoped_ptr<base::DictionaryValue> ParseCommand(int session_id, + const std::string& message); + bool PassCommandToDelegate(int session_id, base::DictionaryValue* command); + void HandleCommand(int session_id, scoped_ptr<base::DictionaryValue> command); + bool HandleOptionalCommand(int session_id, + scoped_ptr<base::DictionaryValue> command, int* call_id); DevToolsAgentHost* agent_host_;
diff --git a/content/browser/devtools/forwarding_agent_host.cc b/content/browser/devtools/forwarding_agent_host.cc index ef7f82c..b8b8c2f8 100644 --- a/content/browser/devtools/forwarding_agent_host.cc +++ b/content/browser/devtools/forwarding_agent_host.cc
@@ -18,7 +18,7 @@ } void ForwardingAgentHost::DispatchOnClientHost(const std::string& message) { - SendMessageToClient(message); + SendMessageToClient(session_id(), message); } void ForwardingAgentHost::ConnectionClosed() {
diff --git a/content/browser/devtools/protocol/devtools_protocol_client.cc b/content/browser/devtools/protocol/devtools_protocol_client.cc index 4b7c25d..9ca03f9d 100644 --- a/content/browser/devtools/protocol/devtools_protocol_client.cc +++ b/content/browser/devtools/protocol/devtools_protocol_client.cc
@@ -6,6 +6,7 @@ #include "base/json/json_writer.h" #include "base/strings/stringprintf.h" +#include "content/browser/devtools/protocol/devtools_protocol_delegate.h" namespace content { @@ -30,24 +31,24 @@ } // namespace // static -const DevToolsCommandId DevToolsProtocolClient::kNoId = -1; +const int DevToolsCommandId::kNoId = -1; DevToolsProtocolClient::DevToolsProtocolClient( - const RawMessageCallback& raw_message_callback) - : raw_message_callback_(raw_message_callback) { -} + DevToolsProtocolDelegate* notifier) + : notifier_(notifier) {} DevToolsProtocolClient::~DevToolsProtocolClient() { } -void DevToolsProtocolClient::SendRawMessage(const std::string& message) { - raw_message_callback_.Run(message); +void DevToolsProtocolClient::SendRawNotification(const std::string& message) { + notifier_->SendProtocolNotification(message); } -void DevToolsProtocolClient::SendMessage(const base::DictionaryValue& message) { +void DevToolsProtocolClient::SendMessage(int session_id, + const base::DictionaryValue& message) { std::string json_message; base::JSONWriter::Write(message, &json_message); - SendRawMessage(json_message); + notifier_->SendProtocolResponse(session_id, json_message); } void DevToolsProtocolClient::SendNotification( @@ -58,19 +59,21 @@ if (params) notification.Set(kParamsParam, params.release()); - SendMessage(notification); + std::string json_message; + base::JSONWriter::Write(notification, &json_message); + SendRawNotification(json_message); } void DevToolsProtocolClient::SendSuccess( DevToolsCommandId command_id, scoped_ptr<base::DictionaryValue> params) { base::DictionaryValue response; - response.SetInteger(kIdParam, command_id); + response.SetInteger(kIdParam, command_id.call_id); response.Set(kResultParam, params ? params.release() : new base::DictionaryValue()); - SendMessage(response); + SendMessage(command_id.session_id, response); } bool DevToolsProtocolClient::SendError(DevToolsCommandId command_id, @@ -80,10 +83,10 @@ return false; } base::DictionaryValue dict; - if (command_id == kNoId) + if (command_id.call_id == DevToolsCommandId::kNoId) dict.Set(kIdParam, base::Value::CreateNullValue()); else - dict.SetInteger(kIdParam, command_id); + dict.SetInteger(kIdParam, command_id.call_id); base::DictionaryValue* error_object = new base::DictionaryValue(); error_object->SetInteger(kErrorCodeParam, response.status()); @@ -91,7 +94,7 @@ error_object->SetString(kErrorMessageParam, response.message()); dict.Set(kErrorParam, error_object); - SendMessage(dict); + SendMessage(command_id.session_id, dict); return true; }
diff --git a/content/browser/devtools/protocol/devtools_protocol_client.h b/content/browser/devtools/protocol/devtools_protocol_client.h index 9297187..780bc74 100644 --- a/content/browser/devtools/protocol/devtools_protocol_client.h +++ b/content/browser/devtools/protocol/devtools_protocol_client.h
@@ -10,16 +10,22 @@ namespace content { -using DevToolsCommandId = int; -class DevToolsProtocolHandler; +struct DevToolsCommandId { + static const int kNoId; + + DevToolsCommandId(int call_id, int session_id) + : call_id(call_id), session_id(session_id) {} + + int call_id; + int session_id; +}; + +class DevToolsProtocolDelegate; class DevToolsProtocolDispatcher; +class DevToolsProtocolHandler; class DevToolsProtocolClient { public: - typedef base::Callback<void(const std::string& message)> - RawMessageCallback; - static const DevToolsCommandId kNoId; - struct Response { public: static Response FallThrough(); @@ -46,12 +52,13 @@ bool SendError(DevToolsCommandId command_id, const Response& response); - // Sends message to client, the caller is presumed to properly + // Sends notification to client, the caller is presumed to properly // format the message. Do not use unless you must. - void SendRawMessage(const std::string& message); + void SendRawNotification(const std::string& message); - explicit DevToolsProtocolClient( - const RawMessageCallback& raw_message_callback); + void SendMessage(int session_id, const base::DictionaryValue& message); + + explicit DevToolsProtocolClient(DevToolsProtocolDelegate* notifier); virtual ~DevToolsProtocolClient(); protected: @@ -63,9 +70,7 @@ private: friend class DevToolsProtocolDispatcher; - void SendMessage(const base::DictionaryValue& message); - - RawMessageCallback raw_message_callback_; + DevToolsProtocolDelegate* notifier_; DISALLOW_COPY_AND_ASSIGN(DevToolsProtocolClient); };
diff --git a/content/browser/devtools/protocol/devtools_protocol_delegate.h b/content/browser/devtools/protocol/devtools_protocol_delegate.h new file mode 100644 index 0000000..489020b --- /dev/null +++ b/content/browser/devtools/protocol/devtools_protocol_delegate.h
@@ -0,0 +1,22 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CONTENT_BROWSER_DEVTOOLS_PROTOCOL_DEVTOOLS_PROTOCOL_DELEGATE_H_ +#define CONTENT_BROWSER_DEVTOOLS_PROTOCOL_DEVTOOLS_PROTOCOL_DELEGATE_H_ + +#include "content/common/content_export.h" + +namespace content { + +class CONTENT_EXPORT DevToolsProtocolDelegate { +public: + virtual ~DevToolsProtocolDelegate() { } + virtual void SendProtocolResponse(int session_id, + const std::string& message) = 0; + virtual void SendProtocolNotification(const std::string& message) = 0; +}; + +} // content + +#endif // CONTENT_BROWSER_DEVTOOLS_PROTOCOL_DEVTOOLS_PROTOCOL_DELEGATE_H_
diff --git a/content/browser/devtools/protocol/devtools_protocol_handler_generator.py b/content/browser/devtools/protocol/devtools_protocol_handler_generator.py index 6bce71e..6377be6f 100755 --- a/content/browser/devtools/protocol/devtools_protocol_handler_generator.py +++ b/content/browser/devtools/protocol/devtools_protocol_handler_generator.py
@@ -74,11 +74,11 @@ class DevToolsProtocolDispatcher { public: - using Notifier = DevToolsProtocolClient::RawMessageCallback; using CommandHandler = - base::Callback<bool(int, scoped_ptr<base::DictionaryValue>)>; + base::Callback<bool(DevToolsCommandId, + scoped_ptr<base::DictionaryValue>)>; - explicit DevToolsProtocolDispatcher(const Notifier& notifier); + explicit DevToolsProtocolDispatcher(DevToolsProtocolDelegate* notifier); ~DevToolsProtocolDispatcher(); CommandHandler FindCommandHandler(const std::string& method); @@ -91,7 +91,7 @@ ${methods}\ - Notifier notifier_; + DevToolsProtocolDelegate* notifier_; DevToolsProtocolClient client_; CommandHandlers command_handlers_; ${fields}\ @@ -208,7 +208,7 @@ namespace ${domain} { class Client : public DevToolsProtocolClient { public: - explicit Client(const RawMessageCallback& raw_message_callback); + explicit Client(DevToolsProtocolDelegate* notifier); ~Client() override; ${methods}\ @@ -252,7 +252,7 @@ namespace content { DevToolsProtocolDispatcher::DevToolsProtocolDispatcher( - const Notifier& notifier) + DevToolsProtocolDelegate* notifier) : notifier_(notifier), client_(notifier), ${fields_init} { @@ -405,8 +405,8 @@ tmpl_client_impl = string.Template("""\ namespace ${domain} { -Client::Client(const RawMessageCallback& raw_message_callback) - : DevToolsProtocolClient(raw_message_callback) { +Client::Client(DevToolsProtocolDelegate* notifier) + : DevToolsProtocolClient(notifier) { } Client::~Client() {
diff --git a/content/browser/devtools/protocol/input_handler.cc b/content/browser/devtools/protocol/input_handler.cc index 0b4bdcc3..c0def4e4 100644 --- a/content/browser/devtools/protocol/input_handler.cc +++ b/content/browser/devtools/protocol/input_handler.cc
@@ -398,8 +398,8 @@ DevToolsCommandId command_id) { if (!interaction_marker_name.empty()) { // TODO(alexclarke): Can we move this elsewhere? It doesn't really fit here. - TRACE_EVENT_COPY_ASYNC_BEGIN0("benchmark", - interaction_marker_name.c_str(), command_id); + TRACE_EVENT_COPY_ASYNC_BEGIN0("benchmark", interaction_marker_name.c_str(), + command_id.call_id); } host_->QueueSyntheticGesture( @@ -417,8 +417,8 @@ DevToolsCommandId command_id, SyntheticGesture::Result result) { if (!interaction_marker_name.empty()) { - TRACE_EVENT_COPY_ASYNC_END0("benchmark", - interaction_marker_name.c_str(), command_id); + TRACE_EVENT_COPY_ASYNC_END0("benchmark", interaction_marker_name.c_str(), + command_id.call_id); } if (repeat_count > 0) {
diff --git a/content/browser/devtools/protocol/page_handler.cc b/content/browser/devtools/protocol/page_handler.cc index c4aac86..a1441563 100644 --- a/content/browser/devtools/protocol/page_handler.cc +++ b/content/browser/devtools/protocol/page_handler.cc
@@ -96,11 +96,12 @@ screencast_quality_(kDefaultScreenshotQuality), screencast_max_width_(-1), screencast_max_height_(-1), + capture_every_nth_frame_(1), capture_retry_count_(0), has_compositor_frame_metadata_(false), - screencast_frame_sent_(0), - screencast_frame_acked_(0), - processing_screencast_frame_(false), + session_id_(0), + frame_counter_(0), + frames_in_flight_(0), color_picker_(new ColorPicker(base::Bind( &PageHandler::OnColorPicked, base::Unretained(this)))), host_(nullptr), @@ -288,7 +289,8 @@ Response PageHandler::StartScreencast(const std::string* format, const int* quality, const int* max_width, - const int* max_height) { + const int* max_height, + const int* every_nth_frame) { RenderWidgetHostImpl* widget_host = host_ ? host_->GetRenderWidgetHost() : nullptr; if (!widget_host) @@ -301,6 +303,10 @@ screencast_quality_ = kDefaultScreenshotQuality; screencast_max_width_ = max_width ? *max_width : -1; screencast_max_height_ = max_height ? *max_height : -1; + ++session_id_; + frame_counter_ = 0; + frames_in_flight_ = 0; + capture_every_nth_frame_ = every_nth_frame ? *every_nth_frame : 1; bool visible = !widget_host->is_hidden(); NotifyScreencastVisibility(visible); @@ -320,8 +326,9 @@ return Response::FallThrough(); } -Response PageHandler::ScreencastFrameAck(int frame_number) { - screencast_frame_acked_ = frame_number; +Response PageHandler::ScreencastFrameAck(int session_id) { + if (session_id == session_id_) + --frames_in_flight_; return Response::OK(); } @@ -372,14 +379,15 @@ } void PageHandler::InnerSwapCompositorFrame() { - if (screencast_frame_sent_ - screencast_frame_acked_ > - kMaxScreencastFramesInFlight || processing_screencast_frame_) { - return; - } - if (!host_ || !host_->GetView()) return; + if (frames_in_flight_ > kMaxScreencastFramesInFlight) + return; + + if (++frame_counter_ % capture_every_nth_frame_) + return; + RenderWidgetHostViewBase* view = static_cast<RenderWidgetHostViewBase*>( host_->GetView()); // TODO(vkuzkokov): do not use previous frame metadata. @@ -412,7 +420,6 @@ gfx::ScaleSize(viewport_size_dip, scale))); if (snapshot_size_dip.width() > 0 && snapshot_size_dip.height() > 0) { - processing_screencast_frame_ = true; gfx::Rect viewport_bounds_dip(gfx::ToRoundedSize(viewport_size_dip)); view->CopyFromCompositingSurface( viewport_bounds_dip, @@ -421,6 +428,7 @@ weak_factory_.GetWeakPtr(), last_compositor_frame_metadata_), kN32_SkColorType); + frames_in_flight_++; } } @@ -429,7 +437,6 @@ const SkBitmap& bitmap, ReadbackResponse response) { if (response != READBACK_SUCCESS) { - processing_screencast_frame_ = false; if (capture_retry_count_) { --capture_retry_count_; base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( @@ -437,6 +444,7 @@ weak_factory_.GetWeakPtr()), base::TimeDelta::FromMilliseconds(kFrameRetryDelayMs)); } + --frames_in_flight_; return; } base::PostTaskAndReplyWithResult( @@ -452,16 +460,18 @@ const cc::CompositorFrameMetadata& metadata, const base::Time& timestamp, const std::string& data) { - processing_screencast_frame_ = false; - // Consider metadata empty in case it has no device scale factor. - if (metadata.device_scale_factor == 0 || !host_ || data.empty()) + if (metadata.device_scale_factor == 0 || !host_ || data.empty()) { + --frames_in_flight_; return; + } RenderWidgetHostViewBase* view = static_cast<RenderWidgetHostViewBase*>( host_->GetView()); - if (!view) + if (!view) { + --frames_in_flight_; return; + } gfx::SizeF screen_size_dip = gfx::ScaleSize(gfx::SizeF(view->GetPhysicalBackingSize()), @@ -478,7 +488,7 @@ client_->ScreencastFrame(ScreencastFrameParams::Create() ->set_data(data) ->set_metadata(param_metadata) - ->set_frame_number(++screencast_frame_sent_)); + ->set_session_id(session_id_)); } void PageHandler::ScreenshotCaptured(DevToolsCommandId command_id,
diff --git a/content/browser/devtools/protocol/page_handler.h b/content/browser/devtools/protocol/page_handler.h index 053b059..5140fe3b 100644 --- a/content/browser/devtools/protocol/page_handler.h +++ b/content/browser/devtools/protocol/page_handler.h
@@ -65,9 +65,10 @@ Response StartScreencast(const std::string* format, const int* quality, const int* max_width, - const int* max_height); + const int* max_height, + const int* every_nth_frame); Response StopScreencast(); - Response ScreencastFrameAck(int frame_number); + Response ScreencastFrameAck(int session_id); Response HandleJavaScriptDialog(bool accept, const std::string* prompt_text); @@ -106,13 +107,14 @@ int screencast_quality_; int screencast_max_width_; int screencast_max_height_; + int capture_every_nth_frame_; int capture_retry_count_; bool has_compositor_frame_metadata_; cc::CompositorFrameMetadata next_compositor_frame_metadata_; cc::CompositorFrameMetadata last_compositor_frame_metadata_; - int screencast_frame_sent_; - int screencast_frame_acked_; - bool processing_screencast_frame_; + int session_id_; + int frame_counter_; + int frames_in_flight_; scoped_ptr<ColorPicker> color_picker_;
diff --git a/content/browser/devtools/protocol/tracing_handler.cc b/content/browser/devtools/protocol/tracing_handler.cc index 24890db..2fd8e4b 100644 --- a/content/browser/devtools/protocol/tracing_handler.cc +++ b/content/browser/devtools/protocol/tracing_handler.cc
@@ -113,7 +113,7 @@ message.reserve(message.size() + trace_fragment.size() + messageSuffixSize); message += trace_fragment; message += "] } }"; - client_->SendRawMessage(message); + client_->SendRawNotification(message); } void TracingHandler::OnTraceComplete() {
diff --git a/content/browser/devtools/render_frame_devtools_agent_host.cc b/content/browser/devtools/render_frame_devtools_agent_host.cc index 1280168d..3b6a207 100644 --- a/content/browser/devtools/render_frame_devtools_agent_host.cc +++ b/content/browser/devtools/render_frame_devtools_agent_host.cc
@@ -86,7 +86,9 @@ void Attach(); void Reattach(FrameHostHolder* old); void Detach(); - void DispatchProtocolMessage(int call_id, const std::string& message); + void DispatchProtocolMessage(int session_id, + int call_id, + const std::string& message); void InspectElement(int x, int y); void ProcessChunkedMessageFromAgent(const DevToolsMessageChunk& chunk); void Suspend(); @@ -95,15 +97,17 @@ private: void GrantPolicy(); void RevokePolicy(); - void SendMessageToClient(const std::string& message); + void SendMessageToClient(int session_id, const std::string& message); RenderFrameDevToolsAgentHost* agent_; RenderFrameHostImpl* host_; bool attached_; bool suspended_; DevToolsMessageChunkProcessor chunk_processor_; - std::vector<std::string> pending_messages_; - std::map<int, std::string> sent_messages_; + // <session_id, message> + std::vector<std::pair<int, std::string>> pending_messages_; + // <call_id> -> <session_id, message> + std::map<int, std::pair<int, std::string>> sent_messages_; }; RenderFrameDevToolsAgentHost::FrameHostHolder::FrameHostHolder( @@ -126,7 +130,7 @@ void RenderFrameDevToolsAgentHost::FrameHostHolder::Attach() { host_->Send(new DevToolsAgentMsg_Attach( - host_->GetRoutingID(), agent_->GetId())); + host_->GetRoutingID(), agent_->GetId(), agent_->session_id())); GrantPolicy(); attached_ = true; } @@ -136,10 +140,13 @@ if (old) chunk_processor_.set_state_cookie(old->chunk_processor_.state_cookie()); host_->Send(new DevToolsAgentMsg_Reattach( - host_->GetRoutingID(), agent_->GetId(), chunk_processor_.state_cookie())); + host_->GetRoutingID(), agent_->GetId(), agent_->session_id(), + chunk_processor_.state_cookie())); if (old) { - for (const auto& pair : old->sent_messages_) - DispatchProtocolMessage(pair.first, pair.second); + for (const auto& pair : old->sent_messages_) { + DispatchProtocolMessage(pair.second.first, pair.first, + pair.second.second); + } } GrantPolicy(); attached_ = true; @@ -179,10 +186,12 @@ } } void RenderFrameDevToolsAgentHost::FrameHostHolder::DispatchProtocolMessage( - int call_id, const std::string& message) { + int session_id, + int call_id, + const std::string& message) { host_->Send(new DevToolsAgentMsg_DispatchOnInspectorBackend( - host_->GetRoutingID(), message)); - sent_messages_[call_id] = message; + host_->GetRoutingID(), session_id, message)); + sent_messages_[call_id] = std::make_pair(session_id, message); } void RenderFrameDevToolsAgentHost::FrameHostHolder::InspectElement( @@ -199,12 +208,13 @@ } void RenderFrameDevToolsAgentHost::FrameHostHolder::SendMessageToClient( + int session_id, const std::string& message) { sent_messages_.erase(chunk_processor_.last_call_id()); if (suspended_) - pending_messages_.push_back(message); + pending_messages_.push_back(std::make_pair(session_id, message)); else - agent_->SendMessageToClient(message); + agent_->SendMessageToClient(session_id, message); } void RenderFrameDevToolsAgentHost::FrameHostHolder::Suspend() { @@ -213,9 +223,9 @@ void RenderFrameDevToolsAgentHost::FrameHostHolder::Resume() { suspended_ = false; - for (const std::string& message : pending_messages_) - agent_->SendMessageToClient(message); - std::vector<std::string> empty; + for (const auto& pair : pending_messages_) + agent_->SendMessageToClient(pair.first, pair.second); + std::vector<std::pair<int, std::string>> empty; pending_messages_.swap(empty); } @@ -326,10 +336,7 @@ GetIOContext())), emulation_handler_(nullptr), frame_trace_recorder_(nullptr), - protocol_handler_(new DevToolsProtocolHandler( - this, - base::Bind(&RenderFrameDevToolsAgentHost::SendMessageToClient, - base::Unretained(this)))), + protocol_handler_(new DevToolsProtocolHandler(this)), current_frame_crashed_(false) { DevToolsProtocolDispatcher* dispatcher = protocol_handler_->dispatcher(); dispatcher->SetDOMHandler(dom_handler_.get()); @@ -424,13 +431,13 @@ bool RenderFrameDevToolsAgentHost::DispatchProtocolMessage( const std::string& message) { int call_id = 0; - if (protocol_handler_->HandleOptionalMessage(message, &call_id)) + if (protocol_handler_->HandleOptionalMessage(session_id(), message, &call_id)) return true; if (current_) - current_->DispatchProtocolMessage(call_id, message); + current_->DispatchProtocolMessage(session_id(), call_id, message); if (pending_) - pending_->DispatchProtocolMessage(call_id, message); + pending_->DispatchProtocolMessage(session_id(), call_id, message); return true; }
diff --git a/content/browser/devtools/worker_devtools_agent_host.cc b/content/browser/devtools/worker_devtools_agent_host.cc index 32cd668e..d7be60a 100644 --- a/content/browser/devtools/worker_devtools_agent_host.cc +++ b/content/browser/devtools/worker_devtools_agent_host.cc
@@ -21,7 +21,8 @@ AttachToWorker(); } if (RenderProcessHost* host = RenderProcessHost::FromID(worker_id_.first)) - host->Send(new DevToolsAgentMsg_Attach(worker_id_.second, GetId())); + host->Send( + new DevToolsAgentMsg_Attach(worker_id_.second, GetId(), session_id())); OnAttachedStateChanged(true); DevToolsAgentHostImpl::NotifyCallbacks(this, true); } @@ -45,12 +46,12 @@ return true; int call_id; - if (protocol_handler_->HandleOptionalMessage(message, &call_id)) + if (protocol_handler_->HandleOptionalMessage(session_id(), message, &call_id)) return true; if (RenderProcessHost* host = RenderProcessHost::FromID(worker_id_.first)) { host->Send(new DevToolsAgentMsg_DispatchOnInspectorBackend( - worker_id_.second, message)); + worker_id_.second, session_id(), message)); } return true; } @@ -83,7 +84,8 @@ AttachToWorker(); if (RenderProcessHost* host = RenderProcessHost::FromID(worker_id_.first)) { host->Send(new DevToolsAgentMsg_Reattach( - worker_id_.second, GetId(), chunk_processor_.state_cookie())); + worker_id_.second, GetId(), session_id(), + chunk_processor_.state_cookie())); } OnAttachedStateChanged(true); } @@ -101,10 +103,7 @@ if (state_ == WORKER_INSPECTED) { DCHECK(IsAttached()); // Client host is debugging this worker agent host. - base::Callback<void(const std::string&)> raw_message_callback( - base::Bind(&WorkerDevToolsAgentHost::SendMessageToClient, - base::Unretained(this))); - devtools::inspector::Client inspector(raw_message_callback); + devtools::inspector::Client inspector(this); inspector.TargetCrashed( devtools::inspector::TargetCrashedParams::Create()); DetachFromWorker(); @@ -117,15 +116,10 @@ return state_ == WORKER_TERMINATED; } -WorkerDevToolsAgentHost::WorkerDevToolsAgentHost( - WorkerId worker_id) - : protocol_handler_(new DevToolsProtocolHandler( - this, - base::Bind(&WorkerDevToolsAgentHost::SendMessageToClient, - base::Unretained(this)))), - chunk_processor_( - base::Bind(&WorkerDevToolsAgentHost::SendMessageToClient, - base::Unretained(this))), +WorkerDevToolsAgentHost::WorkerDevToolsAgentHost(WorkerId worker_id) + : protocol_handler_(new DevToolsProtocolHandler(this)), + chunk_processor_(base::Bind(&WorkerDevToolsAgentHost::SendMessageToClient, + base::Unretained(this))), state_(WORKER_UNINSPECTED), worker_id_(worker_id) { WorkerCreated();
diff --git a/content/browser/download/save_file_manager.cc b/content/browser/download/save_file_manager.cc index 14abb51..3b6cd227 100644 --- a/content/browser/download/save_file_manager.cc +++ b/content/browser/download/save_file_manager.cc
@@ -68,23 +68,23 @@ SavePackage* save_package) { // Make sure it runs in the UI thread. DCHECK_CURRENTLY_ON(BrowserThread::UI); - int contents_id = save_package->contents_id(); + int save_package_id = save_package->id(); // Register this starting request. StartingRequestsMap& starting_requests = - contents_starting_requests_[contents_id]; + contents_starting_requests_[save_package_id]; bool never_present = starting_requests.insert( StartingRequestsMap::value_type(save_url.spec(), save_package)).second; DCHECK(never_present); } -SavePackage* SaveFileManager::UnregisterStartingRequest( - const GURL& save_url, int contents_id) { +SavePackage* SaveFileManager::UnregisterStartingRequest(const GURL& save_url, + int save_package_id) { // Make sure it runs in UI thread. DCHECK_CURRENTLY_ON(BrowserThread::UI); ContentsToStartingRequestsMap::iterator it = - contents_starting_requests_.find(contents_id); + contents_starting_requests_.find(save_package_id); if (it != contents_starting_requests_.end()) { StartingRequestsMap& requests = it->second; StartingRequestsMap::iterator sit = requests.find(save_url.spec()); @@ -113,16 +113,15 @@ } // Call from SavePackage for starting a saving job -void SaveFileManager::SaveURL( - const GURL& url, - const Referrer& referrer, - int render_process_host_id, - int render_view_id, - int render_frame_id, - SaveFileCreateInfo::SaveFileSource save_source, - const base::FilePath& file_full_path, - ResourceContext* context, - SavePackage* save_package) { +void SaveFileManager::SaveURL(const GURL& url, + const Referrer& referrer, + int render_process_host_id, + int render_view_routing_id, + int render_frame_routing_id, + SaveFileCreateInfo::SaveFileSource save_source, + const base::FilePath& file_full_path, + ResourceContext* context, + SavePackage* save_package) { DCHECK_CURRENTLY_ON(BrowserThread::UI); // Register a saving job. @@ -133,8 +132,8 @@ BrowserThread::PostTask( BrowserThread::IO, FROM_HERE, base::Bind(&SaveFileManager::OnSaveURL, this, url, referrer, - render_process_host_id, render_view_id, render_frame_id, - context)); + save_package->id(), render_process_host_id, + render_view_routing_id, render_frame_routing_id, context)); } else { // We manually start the save job. SaveFileCreateInfo* info = new SaveFileCreateInfo(file_full_path, @@ -142,7 +141,8 @@ save_source, -1); info->render_process_id = render_process_host_id; - info->render_frame_id = render_frame_id; + info->render_frame_routing_id = render_frame_routing_id; + info->save_package_id = save_package->id(); // Since the data will come from render process, so we need to start // this kind of save job by ourself. @@ -159,16 +159,17 @@ // If the save id is -1, it means we just send a request to save, but the // saving action has still not happened, need to call UnregisterStartingRequest // to remove it from the tracking map. -void SaveFileManager::RemoveSaveFile(int save_id, const GURL& save_url, - SavePackage* package) { - DCHECK(package); +void SaveFileManager::RemoveSaveFile(int save_id, + const GURL& save_url, + SavePackage* save_package) { + DCHECK(save_package); DCHECK_CURRENTLY_ON(BrowserThread::UI); // A save page job (SavePackage) can only have one manager, // so remove it if it exists. if (save_id == -1) { SavePackage* old_package = - UnregisterStartingRequest(save_url, package->contents_id()); - DCHECK_EQ(old_package, package); + UnregisterStartingRequest(save_url, save_package->id()); + DCHECK_EQ(old_package, save_package); } else { SavePackageMap::iterator it = packages_.find(save_id); if (it != packages_.end()) @@ -178,9 +179,13 @@ // Static SavePackage* SaveFileManager::GetSavePackageFromRenderIds( - int render_process_id, int render_frame_id) { + int render_process_id, + int render_frame_routing_id) { RenderFrameHost* render_frame_host = - RenderFrameHost::FromID(render_process_id, render_frame_id); + RenderFrameHost::FromID(render_process_id, render_frame_routing_id); + if (!render_frame_host) + return nullptr; + WebContentsImpl* web_contents = static_cast<WebContentsImpl*>(WebContents::FromRenderFrameHost( render_frame_host)); @@ -262,11 +267,12 @@ // delete it. void SaveFileManager::SaveFinished(int save_id, const GURL& save_url, - int render_process_id, + int save_package_id, bool is_success) { DVLOG(20) << " " << __FUNCTION__ << "()" - << " save_id = " << save_id - << " save_url = \"" << save_url.spec() << "\"" + << " save_id = " << save_id << " save_url = \"" << save_url.spec() + << "\"" + << " save_package_id = " << save_package_id << " is_success = " << is_success; DCHECK_CURRENTLY_ON(BrowserThread::FILE); SaveFileMap::iterator it = save_file_map_.find(save_id); @@ -290,10 +296,9 @@ } else if (save_id == -1) { // Before saving started, we got error. We still call finish process. DCHECK(!save_url.is_empty()); - BrowserThread::PostTask( - BrowserThread::UI, FROM_HERE, - base::Bind(&SaveFileManager::OnErrorFinished, this, save_url, - render_process_id)); + BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, + base::Bind(&SaveFileManager::OnErrorFinished, this, + save_url, save_package_id)); } } @@ -301,9 +306,8 @@ void SaveFileManager::OnStartSave(const SaveFileCreateInfo* info) { DCHECK_CURRENTLY_ON(BrowserThread::UI); - SavePackage* save_package = - GetSavePackageFromRenderIds(info->render_process_id, - info->render_frame_id); + SavePackage* save_package = GetSavePackageFromRenderIds( + info->render_process_id, info->render_frame_routing_id); if (!save_package) { // Cancel this request. SendCancelRequest(info->save_id); @@ -315,8 +319,8 @@ if (sit == packages_.end()) { // Find the registered request. If we can not find, it means we have // canceled the job before. - SavePackage* old_save_package = UnregisterStartingRequest(info->url, - info->render_process_id); + SavePackage* old_save_package = + UnregisterStartingRequest(info->url, info->save_package_id); if (!old_save_package) { // Cancel this request. SendCancelRequest(info->save_id); @@ -351,29 +355,28 @@ package->SaveFinished(save_id, bytes_so_far, is_success); } -void SaveFileManager::OnErrorFinished(const GURL& save_url, int contents_id) { +void SaveFileManager::OnErrorFinished(const GURL& save_url, + int save_package_id) { DCHECK_CURRENTLY_ON(BrowserThread::UI); - SavePackage* save_package = UnregisterStartingRequest(save_url, contents_id); + SavePackage* save_package = + UnregisterStartingRequest(save_url, save_package_id); if (save_package) save_package->SaveFailed(save_url); } // Notifications sent from the UI thread and run on the IO thread. -void SaveFileManager::OnSaveURL( - const GURL& url, - const Referrer& referrer, - int render_process_host_id, - int render_view_id, - int render_frame_id, - ResourceContext* context) { +void SaveFileManager::OnSaveURL(const GURL& url, + const Referrer& referrer, + int save_package_id, + int render_process_host_id, + int render_view_routing_id, + int render_frame_routing_id, + ResourceContext* context) { DCHECK_CURRENTLY_ON(BrowserThread::IO); - ResourceDispatcherHostImpl::Get()->BeginSaveFile(url, - referrer, - render_process_host_id, - render_view_id, - render_frame_id, - context); + ResourceDispatcherHostImpl::Get()->BeginSaveFile( + url, referrer, save_package_id, render_process_host_id, + render_view_routing_id, render_frame_routing_id, context); } void SaveFileManager::OnRequireSaveJobFromOtherSource( @@ -437,7 +440,7 @@ // using specified save_id, just return. void SaveFileManager::SaveLocalFile(const GURL& original_file_url, int save_id, - int render_process_id) { + int save_package_id) { DCHECK_CURRENTLY_ON(BrowserThread::FILE); SaveFile* save_file = LookupSaveFile(save_id); if (!save_file) @@ -456,14 +459,14 @@ // If we can not get valid file path from original URL, treat it as // disk error. if (file_path.empty()) - SaveFinished(save_id, original_file_url, render_process_id, false); + SaveFinished(save_id, original_file_url, save_package_id, false); // Copy the local file to the temporary file. It will be renamed to its // final name later. bool success = base::CopyFile(file_path, save_file->FullPath()); if (!success) base::DeleteFile(save_file->FullPath(), false); - SaveFinished(save_id, original_file_url, render_process_id, success); + SaveFinished(save_id, original_file_url, save_package_id, success); } void SaveFileManager::OnDeleteDirectoryOrFile(const base::FilePath& full_path, @@ -474,12 +477,11 @@ base::DeleteFile(full_path, is_dir); } -void SaveFileManager::RenameAllFiles( - const FinalNameList& final_names, - const base::FilePath& resource_dir, - int render_process_id, - int render_frame_id, - int save_package_id) { +void SaveFileManager::RenameAllFiles(const FinalNameList& final_names, + const base::FilePath& resource_dir, + int render_process_id, + int render_frame_routing_id, + int save_package_id) { DCHECK_CURRENTLY_ON(BrowserThread::FILE); if (!resource_dir.empty() && !base::PathExists(resource_dir)) @@ -499,17 +501,17 @@ BrowserThread::PostTask( BrowserThread::UI, FROM_HERE, - base::Bind(&SaveFileManager::OnFinishSavePageJob, this, - render_process_id, render_frame_id, save_package_id)); + base::Bind(&SaveFileManager::OnFinishSavePageJob, this, render_process_id, + render_frame_routing_id, save_package_id)); } void SaveFileManager::OnFinishSavePageJob(int render_process_id, - int render_frame_id, + int render_frame_routing_id, int save_package_id) { DCHECK_CURRENTLY_ON(BrowserThread::UI); SavePackage* save_package = - GetSavePackageFromRenderIds(render_process_id, render_frame_id); + GetSavePackageFromRenderIds(render_process_id, render_frame_routing_id); if (save_package && save_package->id() == save_package_id) save_package->Finish();
diff --git a/content/browser/download/save_file_manager.h b/content/browser/download/save_file_manager.h index 4302846..d42bafa 100644 --- a/content/browser/download/save_file_manager.h +++ b/content/browser/download/save_file_manager.h
@@ -99,8 +99,8 @@ void SaveURL(const GURL& url, const Referrer& referrer, int render_process_host_id, - int render_view_id, - int render_frame_id, + int render_view_routing_id, + int render_frame_routing_id, SaveFileCreateInfo::SaveFileSource save_source, const base::FilePath& file_full_path, ResourceContext* context, @@ -111,7 +111,7 @@ void UpdateSaveProgress(int save_id, net::IOBuffer* data, int size); void SaveFinished(int save_id, const GURL& save_url, - int render_process_id, + int save_package_id, bool is_success); // Notifications sent from the UI thread and run on the file thread. @@ -130,17 +130,16 @@ // original url is using file scheme. void SaveLocalFile(const GURL& original_file_url, int save_id, - int render_process_id); + int save_package_id); // Renames all the successfully saved files. // |final_names| points to a vector which contains pairs of save ids and // final names of successfully saved files. - void RenameAllFiles( - const FinalNameList& final_names, - const base::FilePath& resource_dir, - int render_process_id, - int render_frame_id, - int save_package_id); + void RenameAllFiles(const FinalNameList& final_names, + const base::FilePath& resource_dir, + int render_process_id, + int render_frame_routing_id, + int save_package_id); // When the user cancels the saving, we need to remove all remaining saved // files of this page saving job from save_file_map_. @@ -157,7 +156,7 @@ // Called only on UI thread to get the SavePackage for a contents's browser // context. static SavePackage* GetSavePackageFromRenderIds(int render_process_id, - int render_Frame_id); + int render_frame_routing_id); // Register a starting request. Associate the save URL with a // SavePackage for further matching. @@ -166,7 +165,7 @@ // Unregister a start request according save URL, disassociate // the save URL and SavePackage. SavePackage* UnregisterStartingRequest(const GURL& save_url, - int contents_id); + int save_package_id); // Look up the SavePackage according to save id. SavePackage* LookupPackage(int save_id); @@ -193,10 +192,10 @@ void OnSaveFinished(int save_id, int64 bytes_so_far, bool is_success); // For those requests that do not have valid save id, use // map:(url, SavePackage) to find the request and remove it. - void OnErrorFinished(const GURL& save_url, int contents_id); + void OnErrorFinished(const GURL& save_url, int save_package_id); // Notifies SavePackage that the whole page saving job is finished. void OnFinishSavePageJob(int render_process_id, - int render_frame_id, + int render_frame_routing_id, int save_package_id); // Notifications sent from the UI thread and run on the file thread. @@ -210,8 +209,9 @@ void OnSaveURL(const GURL& url, const Referrer& referrer, int render_process_host_id, - int render_view_id, - int render_frame_id, + int render_view_routing_id, + int render_frame_routing_id, + int save_package_id, ResourceContext* context); // Handler for a notification sent to the IO thread for generating save id. void OnRequireSaveJobFromOtherSource(SaveFileCreateInfo* info);
diff --git a/content/browser/download/save_file_resource_handler.cc b/content/browser/download/save_file_resource_handler.cc index de1e81f..43555ad 100644 --- a/content/browser/download/save_file_resource_handler.cc +++ b/content/browser/download/save_file_resource_handler.cc
@@ -17,18 +17,19 @@ namespace content { SaveFileResourceHandler::SaveFileResourceHandler(net::URLRequest* request, + int save_package_id, int render_process_host_id, - int render_frame_id, + int render_frame_routing_id, const GURL& url, SaveFileManager* manager) : ResourceHandler(request), save_id_(-1), + save_package_id_(save_package_id), render_process_id_(render_process_host_id), - render_frame_id_(render_frame_id), + render_frame_routing_id_(render_frame_routing_id), url_(url), content_length_(0), - save_manager_(manager) { -} + save_manager_(manager) {} SaveFileResourceHandler::~SaveFileResourceHandler() { } @@ -50,8 +51,9 @@ info->final_url = final_url_; info->total_bytes = content_length_; info->save_id = save_id_; + info->save_package_id = save_package_id_; info->render_process_id = render_process_id_; - info->render_frame_id = render_frame_id_; + info->render_frame_routing_id = render_frame_routing_id_; info->request_id = GetRequestID(); info->content_disposition = content_disposition_; info->save_source = SaveFileCreateInfo::SAVE_FILE_FROM_NET; @@ -101,7 +103,8 @@ BrowserThread::PostTask( BrowserThread::FILE, FROM_HERE, base::Bind(&SaveFileManager::SaveFinished, save_manager_, save_id_, url_, - render_process_id_, status.is_success() && !status.is_io_pending())); + save_package_id_, + status.is_success() && !status.is_io_pending())); read_buffer_ = NULL; }
diff --git a/content/browser/download/save_file_resource_handler.h b/content/browser/download/save_file_resource_handler.h index 4285134..a2bc2ee7 100644 --- a/content/browser/download/save_file_resource_handler.h +++ b/content/browser/download/save_file_resource_handler.h
@@ -22,8 +22,9 @@ class SaveFileResourceHandler : public ResourceHandler { public: SaveFileResourceHandler(net::URLRequest* request, + int save_package_id, int render_process_host_id, - int render_frame_id, + int render_frame_routing_id, const GURL& url, SaveFileManager* manager); ~SaveFileResourceHandler() override; @@ -72,8 +73,9 @@ private: int save_id_; + int save_package_id_; int render_process_id_; - int render_frame_id_; + int render_frame_routing_id_; scoped_refptr<net::IOBuffer> read_buffer_; std::string content_disposition_; GURL url_;
diff --git a/content/browser/download/save_package.cc b/content/browser/download/save_package.cc index 8c05e8b..15886f8 100644 --- a/content/browser/download/save_package.cc +++ b/content/browser/download/save_package.cc
@@ -159,7 +159,6 @@ all_save_items_count_(0), file_name_set_(&base::FilePath::CompareLessIgnoreCase), wait_state_(INITIALIZE), - contents_id_(web_contents->GetRenderProcessHost()->GetID()), unique_id_(g_save_package_id++), wrote_to_completed_file_(false), wrote_to_failed_file_(false) { @@ -192,7 +191,6 @@ all_save_items_count_(0), file_name_set_(&base::FilePath::CompareLessIgnoreCase), wait_state_(INITIALIZE), - contents_id_(web_contents->GetRenderProcessHost()->GetID()), unique_id_(g_save_package_id++), wrote_to_completed_file_(false), wrote_to_failed_file_(false) { @@ -222,7 +220,6 @@ all_save_items_count_(0), file_name_set_(&base::FilePath::CompareLessIgnoreCase), wait_state_(INITIALIZE), - contents_id_(0), unique_id_(g_save_package_id++), wrote_to_completed_file_(false), wrote_to_failed_file_(false) {} @@ -615,11 +612,8 @@ if (info->save_source == SaveFileCreateInfo::SAVE_FILE_FROM_FILE) { BrowserThread::PostTask( BrowserThread::FILE, FROM_HERE, - base::Bind(&SaveFileManager::SaveLocalFile, - file_manager_, - save_item->url(), - save_item->save_id(), - contents_id())); + base::Bind(&SaveFileManager::SaveLocalFile, file_manager_, + save_item->url(), save_item->save_id(), id())); return; } @@ -1105,8 +1099,6 @@ if (wait_state_ != HTML_DATA) return; - int id = contents_id(); - int frame_tree_node_id = sender->frame_tree_node()->frame_tree_node_id(); auto it = frame_tree_node_id_to_save_item_.find(frame_tree_node_id); if (it == frame_tree_node_id_to_save_item_.end()) { @@ -1156,12 +1148,8 @@ << " url = \"" << save_item->url().spec() << "\""; BrowserThread::PostTask( BrowserThread::FILE, FROM_HERE, - base::Bind(&SaveFileManager::SaveFinished, - file_manager_, - save_item->save_id(), - save_item->url(), - id, - true)); + base::Bind(&SaveFileManager::SaveFinished, file_manager_, + save_item->save_id(), save_item->url(), id(), true)); number_of_frames_pending_response_--; DCHECK_LE(0, number_of_frames_pending_response_); } @@ -1177,7 +1165,7 @@ BrowserThread::PostTask( BrowserThread::FILE, FROM_HERE, base::Bind(&SaveFileManager::SaveFinished, file_manager_, - it->second->save_id(), it->second->url(), id, true)); + it->second->save_id(), it->second->url(), id(), true)); } } }
diff --git a/content/browser/download/save_package.h b/content/browser/download/save_package.h index 4f5eac84..8c06208 100644 --- a/content/browser/download/save_package.h +++ b/content/browser/download/save_package.h
@@ -119,7 +119,6 @@ bool canceled() const { return user_canceled_ || disk_error_occurred_; } bool finished() const { return finished_; } SavePageType save_type() const { return save_type_; } - int contents_id() const { return contents_id_; } int id() const { return unique_id_; } void GetSaveInfo(); @@ -393,10 +392,6 @@ // from outside. WaitState wait_state_; - // Since for one contents, it can only have one SavePackage in same time. - // Now we actually use render_process_id as the contents's unique id. - const int contents_id_; - // Unique ID for this SavePackage. const int unique_id_;
diff --git a/content/browser/download/save_types.cc b/content/browser/download/save_types.cc index 2d02154..b2965326 100644 --- a/content/browser/download/save_types.cc +++ b/content/browser/download/save_types.cc
@@ -13,21 +13,21 @@ : path(path), url(url), save_id(save_id), + save_package_id(-1), render_process_id(-1), - render_frame_id(-1), + render_frame_routing_id(-1), request_id(-1), total_bytes(0), - save_source(save_source) { -} + save_source(save_source) {} SaveFileCreateInfo::SaveFileCreateInfo() : save_id(-1), + save_package_id(-1), render_process_id(-1), - render_frame_id(-1), + render_frame_routing_id(-1), request_id(-1), total_bytes(0), - save_source(SAVE_FILE_FROM_UNKNOWN) { -} + save_source(SAVE_FILE_FROM_UNKNOWN) {} SaveFileCreateInfo::~SaveFileCreateInfo() {}
diff --git a/content/browser/download/save_types.h b/content/browser/download/save_types.h index f8f8d10f..504be2f3 100644 --- a/content/browser/download/save_types.h +++ b/content/browser/download/save_types.h
@@ -52,9 +52,11 @@ // The unique identifier for saving job, assigned at creation by // the SaveFileManager for its internal record keeping. int save_id; + // ID of SavePackage object. + int save_package_id; // IDs for looking up the contents we are associated with. int render_process_id; - int render_frame_id; + int render_frame_routing_id; // Handle for informing the ResourceDispatcherHost of a UI based cancel. int request_id; // Disposition info from HTTP response.
diff --git a/content/browser/fileapi/file_writer_delegate_unittest.cc b/content/browser/fileapi/file_writer_delegate_unittest.cc index 9eb73b1..c9bcfbb7 100644 --- a/content/browser/fileapi/file_writer_delegate_unittest.cc +++ b/content/browser/fileapi/file_writer_delegate_unittest.cc
@@ -184,15 +184,17 @@ base::Bind(&FileWriterDelegateTestJob::NotifyHeadersComplete, this)); } - int ReadRawData(net::IOBuffer* buf, int buf_size) override { + bool ReadRawData(net::IOBuffer* buf, int buf_size, int* bytes_read) override { if (remaining_bytes_ < buf_size) - buf_size = remaining_bytes_; + buf_size = static_cast<int>(remaining_bytes_); for (int i = 0; i < buf_size; ++i) buf->data()[i] = content_[cursor_++]; remaining_bytes_ -= buf_size; - return buf_size; + SetStatus(net::URLRequestStatus()); + *bytes_read = buf_size; + return true; } int GetResponseCode() const override { return 200; }
diff --git a/content/browser/frame_host/frame_mojo_shell.cc b/content/browser/frame_host/frame_mojo_shell.cc index 91a3875..3176fc0 100644 --- a/content/browser/frame_host/frame_mojo_shell.cc +++ b/content/browser/frame_host/frame_mojo_shell.cc
@@ -4,15 +4,45 @@ #include "content/browser/frame_host/frame_mojo_shell.h" +#include <utility> + +#include "base/macros.h" +#include "base/memory/scoped_ptr.h" #include "content/browser/mojo/mojo_shell_context.h" #include "content/common/mojo/service_registry_impl.h" #include "content/public/browser/content_browser_client.h" #include "content/public/browser/render_frame_host.h" #include "content/public/browser/site_instance.h" #include "content/public/common/content_client.h" +#include "mojo/public/cpp/system/message_pipe.h" namespace content { +namespace { + +// This wraps a ServiceRegistryImpl in a mojo::ServiceProvider implementation +// so it can be bound to a mojo::ServiceProvider pipe. +class ServiceRegistryWrapper : public mojo::ServiceProvider { + public: + explicit ServiceRegistryWrapper(scoped_ptr<ServiceRegistryImpl> registry) + : registry_(std::move(registry)) { + } + ~ServiceRegistryWrapper() override {} + + private: + // mojo::ServiceProvider: + void ConnectToService(const mojo::String& service_name, + mojo::ScopedMessagePipeHandle pipe) override { + registry_->Connect(base::StringPiece(service_name), std::move(pipe)); + } + + const scoped_ptr<ServiceRegistryImpl> registry_; + + DISALLOW_COPY_AND_ASSIGN(ServiceRegistryWrapper); +}; + +} // namespace + FrameMojoShell::FrameMojoShell(RenderFrameHost* frame_host) : frame_host_(frame_host) { } @@ -22,7 +52,7 @@ void FrameMojoShell::BindRequest( mojo::InterfaceRequest<mojo::Shell> shell_request) { - bindings_.AddBinding(this, shell_request.Pass()); + bindings_.AddBinding(this, std::move(shell_request)); } // TODO(xhwang): Currently no callers are exposing |exposed_services|. So we @@ -35,7 +65,7 @@ mojo::CapabilityFilterPtr filter, const ConnectToApplicationCallback& callback) { mojo::ServiceProviderPtr frame_services; - service_provider_bindings_.AddBinding(GetServiceRegistry(), + service_provider_bindings_.AddBinding(GetServiceProvider(), GetProxy(&frame_services)); mojo::shell::CapabilityFilter capability_filter = @@ -44,21 +74,21 @@ capability_filter = filter->filter.To<mojo::shell::CapabilityFilter>(); MojoShellContext::ConnectToApplication( GURL(application_url->url), frame_host_->GetSiteInstance()->GetSiteURL(), - services.Pass(), frame_services.Pass(), capability_filter, callback); + std::move(services), std::move(frame_services), capability_filter, + callback); } void FrameMojoShell::QuitApplication() { } -ServiceRegistryImpl* FrameMojoShell::GetServiceRegistry() { - if (!service_registry_) { - service_registry_.reset(new ServiceRegistryImpl()); - +mojo::ServiceProvider* FrameMojoShell::GetServiceProvider() { + if (!service_provider_) { + scoped_ptr<ServiceRegistryImpl> registry(new ServiceRegistryImpl()); GetContentClient()->browser()->RegisterFrameMojoShellServices( - service_registry_.get(), frame_host_); + registry.get(), frame_host_); + service_provider_.reset(new ServiceRegistryWrapper(std::move(registry))); } - - return service_registry_.get(); + return service_provider_.get(); } } // namespace content
diff --git a/content/browser/frame_host/frame_mojo_shell.h b/content/browser/frame_host/frame_mojo_shell.h index d2cc6bb..b67e7c6 100644 --- a/content/browser/frame_host/frame_mojo_shell.h +++ b/content/browser/frame_host/frame_mojo_shell.h
@@ -7,6 +7,7 @@ #include "base/macros.h" #include "base/memory/scoped_ptr.h" +#include "mojo/application/public/interfaces/service_provider.mojom.h" #include "mojo/application/public/interfaces/shell.mojom.h" #include "mojo/common/weak_binding_set.h" #include "mojo/public/cpp/bindings/interface_request.h" @@ -35,13 +36,12 @@ const ConnectToApplicationCallback& callback) override; void QuitApplication() override; - ServiceRegistryImpl* GetServiceRegistry(); + mojo::ServiceProvider* GetServiceProvider(); RenderFrameHost* frame_host_; mojo::WeakBindingSet<mojo::Shell> bindings_; + scoped_ptr<mojo::ServiceProvider> service_provider_; - // ServiceRegistry providing browser services to connected applications. - scoped_ptr<ServiceRegistryImpl> service_registry_; mojo::WeakBindingSet<mojo::ServiceProvider> service_provider_bindings_; DISALLOW_COPY_AND_ASSIGN(FrameMojoShell);
diff --git a/content/browser/frame_host/frame_tree_browsertest.cc b/content/browser/frame_host/frame_tree_browsertest.cc index b9e3b43..f64e227 100644 --- a/content/browser/frame_host/frame_tree_browsertest.cc +++ b/content/browser/frame_host/frame_tree_browsertest.cc
@@ -215,26 +215,25 @@ // Extra '/' is added because the replicated origin is serialized in RFC 6454 // format, which dictates no trailing '/', whereas GURL::GetOrigin does put a // '/' at the end. - EXPECT_EQ(root->current_replication_state().origin.Serialize() + '/', + EXPECT_EQ(root->current_origin().Serialize() + '/', main_url.GetOrigin().spec()); GURL frame_url(embedded_test_server()->GetURL("/title1.html")); NavigateFrameToURL(root->child_at(0), frame_url); - EXPECT_EQ( - root->child_at(0)->current_replication_state().origin.Serialize() + '/', - frame_url.GetOrigin().spec()); + EXPECT_EQ(root->child_at(0)->current_origin().Serialize() + '/', + frame_url.GetOrigin().spec()); GURL data_url("data:text/html,foo"); EXPECT_TRUE(NavigateToURL(shell(), data_url)); // Navigating to a data URL should set a unique origin. This is represented // as "null" per RFC 6454. - EXPECT_EQ(root->current_replication_state().origin.Serialize(), "null"); + EXPECT_EQ(root->current_origin().Serialize(), "null"); // Re-navigating to a normal URL should update the origin. EXPECT_TRUE(NavigateToURL(shell(), main_url)); - EXPECT_EQ(root->current_replication_state().origin.Serialize() + '/', + EXPECT_EQ(root->current_origin().Serialize() + '/', main_url.GetOrigin().spec()); } @@ -266,13 +265,10 @@ // Sandboxed frames should set a unique origin unless they have the // "allow-same-origin" directive. - EXPECT_EQ(root->child_at(0)->current_replication_state().origin.Serialize(), - "null"); - EXPECT_EQ(root->child_at(1)->current_replication_state().origin.Serialize(), - "null"); - EXPECT_EQ( - root->child_at(2)->current_replication_state().origin.Serialize() + "/", - main_url.GetOrigin().spec()); + EXPECT_EQ(root->child_at(0)->current_origin().Serialize(), "null"); + EXPECT_EQ(root->child_at(1)->current_origin().Serialize(), "null"); + EXPECT_EQ(root->child_at(2)->current_origin().Serialize() + "/", + main_url.GetOrigin().spec()); // Navigating to a different URL should not clear sandbox flags. GURL frame_url(embedded_test_server()->GetURL("/title1.html")); @@ -393,32 +389,29 @@ FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents()) ->GetFrameTree()->root(); - EXPECT_EQ(root->current_replication_state().origin.Serialize() + '/', + EXPECT_EQ(root->current_origin().Serialize() + '/', main_url.GetOrigin().spec()); // First frame is an about:blank frame. Check that its origin is correctly // inherited from the parent. - EXPECT_EQ( - root->child_at(0)->current_replication_state().origin.Serialize() + '/', - main_url.GetOrigin().spec()); + EXPECT_EQ(root->child_at(0)->current_origin().Serialize() + '/', + main_url.GetOrigin().spec()); // Second frame loads a same-site page. Its origin should also be the same // as the parent. - EXPECT_EQ( - root->child_at(1)->current_replication_state().origin.Serialize() + '/', - main_url.GetOrigin().spec()); + EXPECT_EQ(root->child_at(1)->current_origin().Serialize() + '/', + main_url.GetOrigin().spec()); // Load cross-site page into the first frame. GURL cross_site_url( embedded_test_server()->GetURL("foo.com", "/title2.html")); NavigateFrameToURL(root->child_at(0), cross_site_url); - EXPECT_EQ( - root->child_at(0)->current_replication_state().origin.Serialize() + '/', - cross_site_url.GetOrigin().spec()); + EXPECT_EQ(root->child_at(0)->current_origin().Serialize() + '/', + cross_site_url.GetOrigin().spec()); // The root's origin shouldn't have changed. - EXPECT_EQ(root->current_replication_state().origin.Serialize() + '/', + EXPECT_EQ(root->current_origin().Serialize() + '/', main_url.GetOrigin().spec()); GURL data_url("data:text/html,foo"); @@ -426,8 +419,7 @@ // Navigating to a data URL should set a unique origin. This is represented // as "null" per RFC 6454. - EXPECT_EQ(root->child_at(1)->current_replication_state().origin.Serialize(), - "null"); + EXPECT_EQ(root->child_at(1)->current_origin().Serialize(), "null"); } } // namespace content
diff --git a/content/browser/frame_host/frame_tree_node.h b/content/browser/frame_host/frame_tree_node.h index 3d5d563e..d678c9a5 100644 --- a/content/browser/frame_host/frame_tree_node.h +++ b/content/browser/frame_host/frame_tree_node.h
@@ -112,6 +112,7 @@ return children_[index].get(); } + // Returns the URL of the last committed page in this frame. const GURL& current_url() const { return current_url_; } @@ -125,6 +126,11 @@ return has_committed_real_load_; } + // Returns the origin of the last committed page in this frame. + const url::Origin& current_origin() const { + return replication_state_.origin; + } + // Set the current origin and notify proxies about the update. void SetCurrentOrigin(const url::Origin& origin);
diff --git a/content/browser/frame_host/navigation_controller_impl.cc b/content/browser/frame_host/navigation_controller_impl.cc index ce13a160..194a0e8 100644 --- a/content/browser/frame_host/navigation_controller_impl.cc +++ b/content/browser/frame_host/navigation_controller_impl.cc
@@ -1382,6 +1382,9 @@ } WebPreferences prefs = rfh->GetRenderViewHost()->GetWebkitPreferences(); + const url::Origin& committed_origin = static_cast<RenderFrameHostImpl*>(rfh) + ->frame_tree_node() + ->current_origin(); bool is_same_origin = last_committed_url.is_empty() || // TODO(japhet): We should only permit navigations // originating from about:blank to be in-page if the @@ -1393,7 +1396,7 @@ last_committed_url.GetOrigin() == url.GetOrigin() || !prefs.web_security_enabled || (prefs.allow_universal_access_from_file_urls && - last_committed_url.SchemeIs(url::kFileScheme)); + committed_origin.scheme() == url::kFileScheme); if (!is_same_origin && renderer_says_in_page) { bad_message::ReceivedBadMessage(rfh->GetProcess(), bad_message::NC_IN_PAGE_NAVIGATION);
diff --git a/content/browser/frame_host/navigation_controller_impl_unittest.cc b/content/browser/frame_host/navigation_controller_impl_unittest.cc index 1cc7803..44b1acb 100644 --- a/content/browser/frame_host/navigation_controller_impl_unittest.cc +++ b/content/browser/frame_host/navigation_controller_impl_unittest.cc
@@ -3605,6 +3605,21 @@ EXPECT_TRUE(controller.IsURLInPageNavigation(other_url, true, main_test_rfh())); + // Don't believe the renderer if it claims a cross-origin navigation is + // in-page. + const GURL different_origin_url("http://www.example.com"); + MockRenderProcessHost* rph = main_test_rfh()->GetProcess(); + EXPECT_EQ(0, rph->bad_msg_count()); + EXPECT_FALSE(controller.IsURLInPageNavigation(different_origin_url, true, + main_test_rfh())); + EXPECT_EQ(1, rph->bad_msg_count()); +} + +// Tests that IsInPageNavigation behaves properly with the +// allow_universal_access_from_file_urls flag. +TEST_F(NavigationControllerTest, IsInPageNavigationWithUniversalFileAccess) { + NavigationControllerImpl& controller = controller_impl(); + // Test allow_universal_access_from_file_urls flag. const GURL different_origin_url("http://www.example.com"); MockRenderProcessHost* rph = main_test_rfh()->GetProcess(); @@ -3613,32 +3628,51 @@ test_rvh()->UpdateWebkitPreferences(prefs); prefs = test_rvh()->GetWebkitPreferences(); EXPECT_TRUE(prefs.allow_universal_access_from_file_urls); - // Allow in page navigation if existing URL is file scheme. + + // Allow in page navigation to be cross-origin if existing URL is file scheme. const GURL file_url("file:///foo/index.html"); - main_test_rfh()->NavigateAndCommitRendererInitiated(0, false, file_url); + const url::Origin file_origin(file_url); + main_test_rfh()->NavigateAndCommitRendererInitiated(0, true, file_url); + EXPECT_TRUE(file_origin.IsSameOriginWith( + main_test_rfh()->frame_tree_node()->current_origin())); EXPECT_EQ(0, rph->bad_msg_count()); EXPECT_TRUE(controller.IsURLInPageNavigation(different_origin_url, true, main_test_rfh())); EXPECT_EQ(0, rph->bad_msg_count()); - // Don't honor allow_universal_access_from_file_urls if existing URL is + + // Doing a replaceState to a cross-origin URL is thus allowed. + FrameHostMsg_DidCommitProvisionalLoad_Params params; + params.page_id = 1; + params.nav_entry_id = 1; + params.did_create_new_entry = false; + params.url = different_origin_url; + params.origin = file_origin; + params.transition = ui::PAGE_TRANSITION_LINK; + params.gesture = NavigationGestureUser; + params.page_state = PageState::CreateFromURL(different_origin_url); + params.was_within_same_page = true; + params.is_post = false; + params.post_id = -1; + main_test_rfh()->SendRendererInitiatedNavigationRequest(different_origin_url, + false); + main_test_rfh()->PrepareForCommit(); + contents()->GetMainFrame()->SendNavigateWithParams(¶ms); + + // At this point, we should still consider the current origin to be file://, + // so that a file URL would still be in-page. See https://crbug.com/553418. + EXPECT_TRUE(file_origin.IsSameOriginWith( + main_test_rfh()->frame_tree_node()->current_origin())); + EXPECT_TRUE( + controller.IsURLInPageNavigation(file_url, true, main_test_rfh())); + EXPECT_EQ(0, rph->bad_msg_count()); + + // Don't honor allow_universal_access_from_file_urls if actual URL is // not file scheme. - main_test_rfh()->NavigateAndCommitRendererInitiated(0, false, url); + const GURL url("http://www.google.com/home.html"); + main_test_rfh()->NavigateAndCommitRendererInitiated(2, true, url); EXPECT_FALSE(controller.IsURLInPageNavigation(different_origin_url, true, main_test_rfh())); EXPECT_EQ(1, rph->bad_msg_count()); - - // Remove allow_universal_access_from_file_urls flag. - prefs.allow_universal_access_from_file_urls = false; - test_rvh()->UpdateWebkitPreferences(prefs); - prefs = test_rvh()->GetWebkitPreferences(); - EXPECT_FALSE(prefs.allow_universal_access_from_file_urls); - - // Don't believe the renderer if it claims a cross-origin navigation is - // in-page. - EXPECT_EQ(1, rph->bad_msg_count()); - EXPECT_FALSE(controller.IsURLInPageNavigation(different_origin_url, true, - main_test_rfh())); - EXPECT_EQ(2, rph->bad_msg_count()); } // Some pages can have subframes with the same base URL (minus the reference) as
diff --git a/content/browser/frame_host/navigation_handle_impl.cc b/content/browser/frame_host/navigation_handle_impl.cc index 6ac5243..4fcb2c6c 100644 --- a/content/browser/frame_host/navigation_handle_impl.cc +++ b/content/browser/frame_host/navigation_handle_impl.cc
@@ -159,6 +159,13 @@ return is_same_page_; } +const net::HttpResponseHeaders* NavigationHandleImpl::GetResponseHeaders() { + DCHECK(state_ >= WILL_REDIRECT_REQUEST) + << "This accessor should only be called when the request encountered a " + "redirect or received a response"; + return response_headers_.get(); +} + bool NavigationHandleImpl::HasCommitted() { return state_ == DID_COMMIT || state_ == DID_COMMIT_ERROR_PAGE; } @@ -220,6 +227,7 @@ NavigationThrottle::ThrottleCheckResult result = NavigationThrottle::DEFER; WillRedirectRequest(new_url, new_method_is_post, new_referrer_url, new_is_external_protocol, + scoped_refptr<net::HttpResponseHeaders>(), base::Bind(&UpdateThrottleCheckResult, &result)); // Reset the callback to ensure it will not be called later. @@ -269,6 +277,7 @@ bool new_method_is_post, const GURL& new_referrer_url, bool new_is_external_protocol, + scoped_refptr<net::HttpResponseHeaders> response_headers, const ThrottleChecksFinishedCallback& callback) { // Update the navigation parameters. url_ = new_url; @@ -276,6 +285,7 @@ sanitized_referrer_.url = new_referrer_url; sanitized_referrer_ = Referrer::SanitizeForRequest(url_, sanitized_referrer_); is_external_protocol_ = new_is_external_protocol; + response_headers_ = response_headers; state_ = WILL_REDIRECT_REQUEST; complete_callback_ = callback; @@ -294,11 +304,19 @@ } void NavigationHandleImpl::ReadyToCommitNavigation( - RenderFrameHostImpl* render_frame_host) { - CHECK(!render_frame_host_); + RenderFrameHostImpl* render_frame_host, + scoped_refptr<net::HttpResponseHeaders> response_headers) { + DCHECK(!render_frame_host_); render_frame_host_ = render_frame_host; + response_headers_ = response_headers; state_ = READY_TO_COMMIT; - GetDelegate()->ReadyToCommitNavigation(this); + + // Only notify the WebContentsObservers when PlzNavigate is enabled, as + // |render_frame_host_| may be wrong in the case of transfer navigations. + if (base::CommandLine::ForCurrentProcess()->HasSwitch( + switches::kEnableBrowserSideNavigation)) { + GetDelegate()->ReadyToCommitNavigation(this); + } } void NavigationHandleImpl::DidCommitNavigation(
diff --git a/content/browser/frame_host/navigation_handle_impl.h b/content/browser/frame_host/navigation_handle_impl.h index 622512f2..70fb99e 100644 --- a/content/browser/frame_host/navigation_handle_impl.h +++ b/content/browser/frame_host/navigation_handle_impl.h
@@ -100,6 +100,12 @@ NavigatorDelegate* GetDelegate() const; + // Returns the response headers for the request. This can only be accessed + // after a redirect was encountered or after the the navigation is ready to + // commit. It should not be modified, as modifications will not be reflected + // in the network stack. + const net::HttpResponseHeaders* GetResponseHeaders(); + void set_net_error_code(net::Error net_error_code) { net_error_code_ = net_error_code; } @@ -113,6 +119,12 @@ is_transferring_ = is_transferring; } + // Updates the RenderFrameHost that is about to commit the navigation. This + // is used during transfer navigations. + void set_render_frame_host(RenderFrameHostImpl* render_frame_host) { + render_frame_host_ = render_frame_host; + } + // PlzNavigate ServiceWorkerNavigationHandle* service_worker_handle() const { return service_worker_handle_.get(); @@ -134,11 +146,13 @@ // Called when the URLRequest will be redirected in the network stack. // |callback| will be called when all throttles check have completed. This // will allow the caller to cancel the navigation or let it proceed. - void WillRedirectRequest(const GURL& new_url, - bool new_method_is_post, - const GURL& new_referrer_url, - bool new_is_external_protocol, - const ThrottleChecksFinishedCallback& callback); + void WillRedirectRequest( + const GURL& new_url, + bool new_method_is_post, + const GURL& new_referrer_url, + bool new_is_external_protocol, + scoped_refptr<net::HttpResponseHeaders> response_headers, + const ThrottleChecksFinishedCallback& callback); // Called when the navigation was redirected. This will update the |url_| and // inform the delegate. @@ -147,7 +161,9 @@ // Called when the navigation is ready to be committed in // |render_frame_host|. This will update the |state_| and inform the // delegate. - void ReadyToCommitNavigation(RenderFrameHostImpl* render_frame_host); + void ReadyToCommitNavigation( + RenderFrameHostImpl* render_frame_host, + scoped_refptr<net::HttpResponseHeaders> response_headers); // Called when the navigation was committed in |render_frame_host|. This will // update the |state_|. @@ -194,6 +210,7 @@ net::Error net_error_code_; RenderFrameHostImpl* render_frame_host_; bool is_same_page_; + scoped_refptr<net::HttpResponseHeaders> response_headers_; // The state the navigation is in. State state_;
diff --git a/content/browser/frame_host/navigation_handle_impl_unittest.cc b/content/browser/frame_host/navigation_handle_impl_unittest.cc index cd2d0ec..ee999cb 100644 --- a/content/browser/frame_host/navigation_handle_impl_unittest.cc +++ b/content/browser/frame_host/navigation_handle_impl_unittest.cc
@@ -103,7 +103,7 @@ // It's safe to use base::Unretained since the NavigationHandle is owned by // the NavigationHandleImplTest. test_handle_->WillRedirectRequest( - GURL(), false, GURL(), false, + GURL(), false, GURL(), false, scoped_refptr<net::HttpResponseHeaders>(), base::Bind(&NavigationHandleImplTest::UpdateThrottleCheckResult, base::Unretained(this))); }
diff --git a/content/browser/frame_host/navigation_request.cc b/content/browser/frame_host/navigation_request.cc index fbabed6d..7c7dcd6f 100644 --- a/content/browser/frame_host/navigation_request.cc +++ b/content/browser/frame_host/navigation_request.cc
@@ -17,6 +17,7 @@ #include "content/public/browser/navigation_controller.h" #include "content/public/browser/stream_handle.h" #include "content/public/common/content_client.h" +#include "content/public/common/resource_response.h" #include "net/base/load_flags.h" #include "net/http/http_request_headers.h" #include "net/url_request/redirect_info.h" @@ -224,8 +225,6 @@ void NavigationRequest::TransferNavigationHandleOwnership( RenderFrameHostImpl* render_frame_host) { render_frame_host->SetNavigationHandle(navigation_handle_.Pass()); - render_frame_host->navigation_handle()->ReadyToCommitNavigation( - render_frame_host); } void NavigationRequest::OnRequestRedirected( @@ -243,7 +242,7 @@ // TODO(clamy): pass the real value for |is_external_protocol| if needed. navigation_handle_->WillRedirectRequest( common_params_.url, begin_params_.method == "POST", - common_params_.referrer.url, false, + common_params_.referrer.url, false, response->head.headers, base::Bind(&NavigationRequest::OnRedirectChecksComplete, base::Unretained(this))); }
diff --git a/content/browser/frame_host/navigator_impl.cc b/content/browser/frame_host/navigator_impl.cc index 44bc5a8..ce8891c9 100644 --- a/content/browser/frame_host/navigator_impl.cc +++ b/content/browser/frame_host/navigator_impl.cc
@@ -151,6 +151,8 @@ // DidStartProvisionalLoad should not correspond to a new navigation. DCHECK_EQ(url, render_frame_host->navigation_handle()->GetURL()); render_frame_host->navigation_handle()->set_is_transferring(false); + render_frame_host->navigation_handle()->set_render_frame_host( + render_frame_host); return; } @@ -749,6 +751,8 @@ render_frame_host, navigation_request->common_params().url); navigation_request->TransferNavigationHandleOwnership(render_frame_host); + render_frame_host->navigation_handle()->ReadyToCommitNavigation( + render_frame_host, response ? response->head.headers : nullptr); render_frame_host->CommitNavigation(response, body.Pass(), navigation_request->common_params(), navigation_request->request_params()); @@ -779,6 +783,8 @@ render_frame_host, navigation_request->common_params().url); navigation_request->TransferNavigationHandleOwnership(render_frame_host); + render_frame_host->navigation_handle()->ReadyToCommitNavigation( + render_frame_host, scoped_refptr<net::HttpResponseHeaders>()); render_frame_host->FailedNavigation(navigation_request->common_params(), navigation_request->request_params(), has_stale_copy_in_cache, error_code);
diff --git a/content/browser/frame_host/render_frame_host_impl.cc b/content/browser/frame_host/render_frame_host_impl.cc index 9a8810b3..4a01694 100644 --- a/content/browser/frame_host/render_frame_host_impl.cc +++ b/content/browser/frame_host/render_frame_host_impl.cc
@@ -4,6 +4,8 @@ #include "content/browser/frame_host/render_frame_host_impl.h" +#include <utility> + #include "base/bind.h" #include "base/command_line.h" #include "base/containers/hash_tables.h" @@ -47,8 +49,8 @@ #include "content/common/frame_messages.h" #include "content/common/input_messages.h" #include "content/common/inter_process_time_ticks_converter.h" +#include "content/common/mojo/service_registry_for_route.h" #include "content/common/navigation_params.h" -#include "content/common/render_frame_setup.mojom.h" #include "content/common/site_isolation_policy.h" #include "content/common/swapped_out_messages.h" #include "content/public/browser/ax_event_notification_details.h" @@ -2025,29 +2027,23 @@ if (service_registry_.get()) return; - service_registry_.reset(new ServiceRegistryImpl()); - if (!GetProcess()->GetServiceRegistry()) + ServiceRegistryImpl* process_wide_registry = + static_cast<ServiceRegistryImpl*>(GetProcess()->GetServiceRegistry()); + if (!process_wide_registry) return; - RegisterMojoServices(); - RenderFrameSetupPtr setup; - GetProcess()->GetServiceRegistry()->ConnectToRemoteService( - mojo::GetProxy(&setup)); - - mojo::ServiceProviderPtr exposed_services; - service_registry_->Bind(GetProxy(&exposed_services)); - - mojo::ServiceProviderPtr services; - setup->ExchangeServiceProviders(routing_id_, GetProxy(&services), - exposed_services.Pass()); - service_registry_->BindRemoteServiceProvider(services.Pass()); + scoped_ptr<ServiceRegistryForRoute> registry = + process_wide_registry->CreateServiceRegistryForRoute(routing_id_); + DCHECK(registry); #if defined(OS_ANDROID) - service_registry_android_.reset( - new ServiceRegistryAndroid(service_registry_.get())); + service_registry_android_.reset(new ServiceRegistryAndroid(registry.get())); ServiceRegistrarAndroid::RegisterFrameHostServices( service_registry_android_.get()); #endif + + service_registry_ = std::move(registry); + RegisterMojoServices(); } void RenderFrameHostImpl::InvalidateMojoConnection() {
diff --git a/content/browser/frame_host/render_frame_host_impl.h b/content/browser/frame_host/render_frame_host_impl.h index cbefae8..dbc227de 100644 --- a/content/browser/frame_host/render_frame_host_impl.h +++ b/content/browser/frame_host/render_frame_host_impl.h
@@ -23,7 +23,6 @@ #include "content/common/frame_message_enums.h" #include "content/common/frame_replication_state.h" #include "content/common/image_downloader/image_downloader.mojom.h" -#include "content/common/mojo/service_registry_impl.h" #include "content/common/navigation_params.h" #include "content/public/browser/render_frame_host.h" #include "content/public/common/javascript_message_type.h" @@ -72,6 +71,7 @@ class RenderWidgetHostView; class RenderWidgetHostViewBase; class ResourceRequestBody; +class ServiceRegistry; class StreamHandle; class TimeoutMonitor; struct ContextMenuParams; @@ -775,7 +775,7 @@ // SiteInstance. scoped_ptr<TimeoutMonitor> swapout_event_monitor_timeout_; - scoped_ptr<ServiceRegistryImpl> service_registry_; + scoped_ptr<ServiceRegistry> service_registry_; #if defined(OS_ANDROID) scoped_ptr<ServiceRegistryAndroid> service_registry_android_;
diff --git a/content/browser/frame_host/render_frame_message_filter.cc b/content/browser/frame_host/render_frame_message_filter.cc index b5b5528..70fdd09 100644 --- a/content/browser/frame_host/render_frame_message_filter.cc +++ b/content/browser/frame_host/render_frame_message_filter.cc
@@ -352,6 +352,9 @@ if (base::CommandLine::ForCurrentProcess()->HasSwitch( switches::kEnableExperimentalWebPlatformFeatures)) { options.set_enforce_prefixes(); + // TODO(jww): This should be hooked up to a Finch flag for M49, rather + // than the generic "experimental web platform features" flag. + options.set_enforce_strict_secure(); } // Pass a null callback since we don't care about when the 'set' completes. context->cookie_store()->SetCookieWithOptionsAsync(
diff --git a/content/browser/host_zoom_map_impl.h b/content/browser/host_zoom_map_impl.h index a9b2a45..dbf166a 100644 --- a/content/browser/host_zoom_map_impl.h +++ b/content/browser/host_zoom_map_impl.h
@@ -7,6 +7,7 @@ #include <map> #include <string> +#include <tuple> #include <vector> #include "base/compiler_specific.h" @@ -112,9 +113,8 @@ : render_process_id(render_process_id), render_view_id(render_view_id) {} bool operator<(const RenderViewKey& other) const { - return render_process_id < other.render_process_id || - ((render_process_id == other.render_process_id) && - (render_view_id < other.render_view_id)); + return std::tie(render_process_id, render_view_id) < + std::tie(other.render_process_id, other.render_view_id); } };
diff --git a/content/browser/loader/global_routing_id.h b/content/browser/loader/global_routing_id.h index a15e93d..df5f202 100644 --- a/content/browser/loader/global_routing_id.h +++ b/content/browser/loader/global_routing_id.h
@@ -5,6 +5,8 @@ #ifndef CONTENT_BROWSER_LOADER_GLOBAL_ROUTING_ID_H_ #define CONTENT_BROWSER_LOADER_GLOBAL_ROUTING_ID_H_ +#include <tuple> + namespace content { // Uniquely identifies the route from which a net::URLRequest comes. @@ -24,9 +26,8 @@ int route_id; bool operator<(const GlobalRoutingID& other) const { - if (child_id == other.child_id) - return route_id < other.route_id; - return child_id < other.child_id; + return std::tie(child_id, route_id) < + std::tie(other.child_id, other.route_id); } bool operator==(const GlobalRoutingID& other) const { return child_id == other.child_id &&
diff --git a/content/browser/loader/navigation_resource_throttle.cc b/content/browser/loader/navigation_resource_throttle.cc index efb3ac9..44fd0c1 100644 --- a/content/browser/loader/navigation_resource_throttle.cc +++ b/content/browser/loader/navigation_resource_throttle.cc
@@ -59,13 +59,15 @@ is_external_protocol, base::Bind(&SendCheckResultToIOThread, callback)); } -void CheckWillRedirectRequestOnUIThread(UIChecksPerformedCallback callback, - int render_process_id, - int render_frame_host_id, - const GURL& new_url, - bool new_method_is_post, - const GURL& new_referrer_url, - bool new_is_external_protocol) { +void CheckWillRedirectRequestOnUIThread( + UIChecksPerformedCallback callback, + int render_process_id, + int render_frame_host_id, + const GURL& new_url, + bool new_method_is_post, + const GURL& new_referrer_url, + bool new_is_external_protocol, + scoped_refptr<net::HttpResponseHeaders> headers) { DCHECK_CURRENTLY_ON(BrowserThread::UI); RenderFrameHostImpl* render_frame_host = RenderFrameHostImpl::FromID(render_process_id, render_frame_host_id); @@ -86,10 +88,28 @@ ->FilterURL(false, &new_validated_url); navigation_handle->WillRedirectRequest( new_validated_url, new_method_is_post, new_referrer_url, - new_is_external_protocol, + new_is_external_protocol, headers, base::Bind(&SendCheckResultToIOThread, callback)); } +void WillProcessResponseOnUIThread( + int render_process_id, + int render_frame_host_id, + scoped_refptr<net::HttpResponseHeaders> headers) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + RenderFrameHostImpl* render_frame_host = + RenderFrameHostImpl::FromID(render_process_id, render_frame_host_id); + if (!render_frame_host) + return; + + NavigationHandleImpl* navigation_handle = + render_frame_host->navigation_handle(); + if (!navigation_handle) + return; + + navigation_handle->ReadyToCommitNavigation(render_frame_host, headers); +} + } // namespace NavigationResourceThrottle::NavigationResourceThrottle(net::URLRequest* request) @@ -98,6 +118,7 @@ NavigationResourceThrottle::~NavigationResourceThrottle() {} void NavigationResourceThrottle::WillStartRequest(bool* defer) { + DCHECK_CURRENTLY_ON(BrowserThread::IO); const ResourceRequestInfo* info = ResourceRequestInfo::ForRequest(request_); if (!info) return; @@ -128,6 +149,7 @@ void NavigationResourceThrottle::WillRedirectRequest( const net::RedirectInfo& redirect_info, bool* defer) { + DCHECK_CURRENTLY_ON(BrowserThread::IO); const ResourceRequestInfo* info = ResourceRequestInfo::ForRequest(request_); if (!info) return; @@ -144,15 +166,50 @@ UIChecksPerformedCallback callback = base::Bind(&NavigationResourceThrottle::OnUIChecksPerformed, weak_ptr_factory_.GetWeakPtr()); + + // Send the redirect info to the NavigationHandle on the UI thread. + // Note: to avoid threading issues, a copy of the HttpResponseHeaders is sent + // in lieu of the original. + scoped_refptr<net::HttpResponseHeaders> response_headers; + if (request_->response_headers()) { + response_headers = new net::HttpResponseHeaders( + request_->response_headers()->raw_headers()); + } + BrowserThread::PostTask( BrowserThread::UI, FROM_HERE, base::Bind(&CheckWillRedirectRequestOnUIThread, callback, render_process_id, render_frame_id, redirect_info.new_url, redirect_info.new_method == "POST", - GURL(redirect_info.new_referrer), new_is_external_protocol)); + GURL(redirect_info.new_referrer), new_is_external_protocol, + response_headers)); *defer = true; } +void NavigationResourceThrottle::WillProcessResponse(bool* defer) { + DCHECK_CURRENTLY_ON(BrowserThread::IO); + const ResourceRequestInfo* info = ResourceRequestInfo::ForRequest(request_); + if (!info) + return; + + int render_process_id, render_frame_id; + if (!info->GetAssociatedRenderFrame(&render_process_id, &render_frame_id)) + return; + + // Send a copy of the response headers to the NavigationHandle on the UI + // thread. + scoped_refptr<net::HttpResponseHeaders> response_headers; + if (request_->response_headers()) { + response_headers = new net::HttpResponseHeaders( + request_->response_headers()->raw_headers()); + } + + BrowserThread::PostTask( + BrowserThread::UI, FROM_HERE, + base::Bind(&WillProcessResponseOnUIThread, render_process_id, + render_frame_id, response_headers)); +} + const char* NavigationResourceThrottle::GetNameForLogging() const { return "NavigationResourceThrottle"; }
diff --git a/content/browser/loader/navigation_resource_throttle.h b/content/browser/loader/navigation_resource_throttle.h index e46b59d..753d99b 100644 --- a/content/browser/loader/navigation_resource_throttle.h +++ b/content/browser/loader/navigation_resource_throttle.h
@@ -28,6 +28,7 @@ void WillStartRequest(bool* defer) override; void WillRedirectRequest(const net::RedirectInfo& redirect_info, bool* defer) override; + void WillProcessResponse(bool* defer) override; const char* GetNameForLogging() const override; private:
diff --git a/content/browser/loader/resource_dispatcher_host_impl.cc b/content/browser/loader/resource_dispatcher_host_impl.cc index f342602..391a6b413 100644 --- a/content/browser/loader/resource_dispatcher_host_impl.cc +++ b/content/browser/loader/resource_dispatcher_host_impl.cc
@@ -1691,13 +1691,13 @@ } // This function is only used for saving feature. -void ResourceDispatcherHostImpl::BeginSaveFile( - const GURL& url, - const Referrer& referrer, - int child_id, - int render_view_route_id, - int render_frame_route_id, - ResourceContext* context) { +void ResourceDispatcherHostImpl::BeginSaveFile(const GURL& url, + const Referrer& referrer, + int save_package_id, + int child_id, + int render_view_route_id, + int render_frame_route_id, + ResourceContext* context) { if (is_shutdown_) return; @@ -1735,12 +1735,9 @@ render_frame_route_id, false, context); extra_info->AssociateWithRequest(request.get()); // Request takes ownership. - scoped_ptr<ResourceHandler> handler( - new SaveFileResourceHandler(request.get(), - child_id, - render_frame_route_id, - url, - save_file_manager_.get())); + scoped_ptr<ResourceHandler> handler(new SaveFileResourceHandler( + request.get(), save_package_id, child_id, render_frame_route_id, url, + save_file_manager_.get())); BeginRequestInternal(request.Pass(), handler.Pass()); }
diff --git a/content/browser/loader/resource_dispatcher_host_impl.h b/content/browser/loader/resource_dispatcher_host_impl.h index d575c104..d9105fa 100644 --- a/content/browser/loader/resource_dispatcher_host_impl.h +++ b/content/browser/loader/resource_dispatcher_host_impl.h
@@ -128,6 +128,7 @@ // request from the renderer or another child process). void BeginSaveFile(const GURL& url, const Referrer& referrer, + int save_package_id, int child_id, int render_view_route_id, int render_frame_route_id,
diff --git a/content/browser/media/webrtc_identity_store_backend.cc b/content/browser/media/webrtc_identity_store_backend.cc index 59ee816..48e51e6 100644 --- a/content/browser/media/webrtc_identity_store_backend.cc +++ b/content/browser/media/webrtc_identity_store_backend.cc
@@ -4,6 +4,8 @@ #include "content/browser/media/webrtc_identity_store_backend.h" +#include <tuple> + #include "base/files/file_path.h" #include "base/files/file_util.h" #include "base/memory/scoped_vector.h" @@ -53,8 +55,8 @@ : origin(origin), identity_name(identity_name) {} bool operator<(const IdentityKey& other) const { - return origin < other.origin || - (origin == other.origin && identity_name < other.identity_name); + return std::tie(origin, identity_name) < + std::tie(other.origin, other.identity_name); } GURL origin;
diff --git a/content/browser/memory/memory_message_filter.cc b/content/browser/memory/memory_message_filter.cc index 110f839..9a792d8 100644 --- a/content/browser/memory/memory_message_filter.cc +++ b/content/browser/memory/memory_message_filter.cc
@@ -9,20 +9,8 @@ namespace content { -MemoryMessageFilter::MemoryMessageFilter( - const BrowserChildProcessHost* child_process_host, - ProcessType process_type) - : BrowserMessageFilter(MemoryMsgStart), - process_host_(child_process_host), - process_type_(process_type) { - DCHECK_NE(process_type_, PROCESS_TYPE_RENDERER); -} - -MemoryMessageFilter::MemoryMessageFilter( - const RenderProcessHost* render_process_host) - : BrowserMessageFilter(MemoryMsgStart), - process_host_(render_process_host), - process_type_(PROCESS_TYPE_RENDERER) {} +MemoryMessageFilter::MemoryMessageFilter() + : BrowserMessageFilter(MemoryMsgStart) {} MemoryMessageFilter::~MemoryMessageFilter() {}
diff --git a/content/browser/memory/memory_message_filter.h b/content/browser/memory/memory_message_filter.h index 7567b37..c3fd30f 100644 --- a/content/browser/memory/memory_message_filter.h +++ b/content/browser/memory/memory_message_filter.h
@@ -8,20 +8,14 @@ #include "base/memory/memory_pressure_listener.h" #include "content/common/content_export.h" #include "content/public/browser/browser_message_filter.h" -#include "content/public/common/process_type.h" namespace content { -class BrowserChildProcessHost; -class RenderProcessHost; - // This class sends memory messages from the browser process. // See also: child_memory_message_filter.h class CONTENT_EXPORT MemoryMessageFilter : public BrowserMessageFilter { public: - MemoryMessageFilter(const BrowserChildProcessHost* child_process_host, - ProcessType process_type); - MemoryMessageFilter(const RenderProcessHost* render_process_host); + MemoryMessageFilter(); // BrowserMessageFilter implementation. void OnFilterAdded(IPC::Sender* sender) override; @@ -35,21 +29,9 @@ base::MemoryPressureListener::MemoryPressureLevel level); protected: - friend class MemoryPressureController; - ~MemoryMessageFilter() override; - const void* process_host() const { return process_host_; } - ProcessType process_type() const { return process_type_; } - private: - // The untyped process host and ProcessType associated with this filter - // instance. The process host is stored as untyped because it is only used as - // a key in MemoryPressureController; at no point is it ever deferenced to - // invoke any members on a process host. - const void* process_host_; - ProcessType process_type_; - DISALLOW_COPY_AND_ASSIGN(MemoryMessageFilter); };
diff --git a/content/browser/memory/memory_pressure_controller.cc b/content/browser/memory/memory_pressure_controller.cc index 11cdbe53..67f31b4a 100644 --- a/content/browser/memory/memory_pressure_controller.cc +++ b/content/browser/memory/memory_pressure_controller.cc
@@ -20,10 +20,7 @@ // Add the message filter to the set of all memory message filters and check // that it wasn't there beforehand. - const bool success = - memory_message_filters_.insert( - std::make_pair(filter->process_host(), filter)) - .second; + const bool success = memory_message_filters_.insert(filter).second; DCHECK(success); // There's no need to send a message to the child process if memory pressure @@ -36,12 +33,10 @@ MemoryMessageFilter* filter) { DCHECK_CURRENTLY_ON(BrowserThread::IO); - // Remove the message filter from the set of all memory message filters, - // ensuring that it was there beforehand. - auto it = memory_message_filters_.find(filter->process_host()); - DCHECK(it != memory_message_filters_.end()); - DCHECK_EQ(filter, it->second); - memory_message_filters_.erase(it); + // Remove the message filter from the set of all memory message filters and + // check that it was there beforehand. + const bool success = memory_message_filters_.erase(filter) == 1u; + DCHECK(success); } // static @@ -68,8 +63,9 @@ base::MemoryPressureListener::SetNotificationsSuppressed(suppressed); // Enable/disable suppressing memory notifications in all child processes. - for (const auto& filter_pair : memory_message_filters_) - filter_pair.second->SendSetPressureNotificationsSuppressed(suppressed); + for (const scoped_refptr<MemoryMessageFilter>& filter : + memory_message_filters_) + filter->SendSetPressureNotificationsSuppressed(suppressed); } void MemoryPressureController::SimulatePressureNotificationInAllProcesses( @@ -91,44 +87,9 @@ base::MemoryPressureListener::SimulatePressureNotification(level); // Simulate memory pressure notification in all child processes. - for (const auto& filter_pair : memory_message_filters_) - filter_pair.second->SendSimulatePressureNotification(level); -} - -void MemoryPressureController::SendPressureNotification( - const BrowserChildProcessHost* child_process_host, - base::MemoryPressureListener::MemoryPressureLevel level) { - SendPressureNotificationImpl(child_process_host, level); -} - -void MemoryPressureController::SendPressureNotification( - const RenderProcessHost* render_process_host, - base::MemoryPressureListener::MemoryPressureLevel level) { - SendPressureNotificationImpl(render_process_host, level); -} - -void MemoryPressureController::SendPressureNotificationImpl( - const void* child_process_host, - base::MemoryPressureListener::MemoryPressureLevel level) { - if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) { - // Note that passing base::Unretained(this) is safe here because the - // controller is a leaky singleton. It's also safe to pass an untyped - // child process pointer as the address is only used as a key for lookup in - // a map; at no point is it dereferenced. - BrowserThread::PostTask( - BrowserThread::IO, FROM_HERE, - base::Bind(&MemoryPressureController::SendPressureNotificationImpl, - base::Unretained(this), child_process_host, level)); - return; - } - - if (base::MemoryPressureListener::AreNotificationsSuppressed()) - return; - - // Find the appropriate message filter and dispatch the message. - auto it = memory_message_filters_.find(child_process_host); - if (it != memory_message_filters_.end()) - it->second->SendPressureNotification(level); + for (const scoped_refptr<MemoryMessageFilter>& filter : + memory_message_filters_) + filter->SendSimulatePressureNotification(level); } } // namespace content
diff --git a/content/browser/memory/memory_pressure_controller.h b/content/browser/memory/memory_pressure_controller.h index b315ad3..934f847 100644 --- a/content/browser/memory/memory_pressure_controller.h +++ b/content/browser/memory/memory_pressure_controller.h
@@ -5,7 +5,7 @@ #ifndef CONTENT_BROWSER_MEMORY_MEMORY_PRESSURE_CONTROLLER_H_ #define CONTENT_BROWSER_MEMORY_MEMORY_PRESSURE_CONTROLLER_H_ -#include <map> +#include <set> #include "base/callback.h" #include "base/memory/memory_pressure_listener.h" @@ -14,9 +14,7 @@ namespace content { -class BrowserChildProcessHost; class MemoryMessageFilter; -class RenderProcessHost; class CONTENT_EXPORT MemoryPressureController { public: @@ -28,12 +26,6 @@ void SetPressureNotificationsSuppressedInAllProcesses(bool suppressed); void SimulatePressureNotificationInAllProcesses( base::MemoryPressureListener::MemoryPressureLevel level); - void SendPressureNotification( - const BrowserChildProcessHost* child_process_host, - base::MemoryPressureListener::MemoryPressureLevel level); - void SendPressureNotification( - const RenderProcessHost* render_process_host, - base::MemoryPressureListener::MemoryPressureLevel level); // This method can be called from any thread. static MemoryPressureController* GetInstance(); @@ -46,16 +38,10 @@ MemoryPressureController(); - // Implementation of the various SendPressureNotification methods. - void SendPressureNotificationImpl( - const void* child_process_host, - base::MemoryPressureListener::MemoryPressureLevel level); - - // Map from untyped process host pointers to the associated memory message - // filters in the browser process. Always accessed on the IO thread. - typedef std::map<const void*, scoped_refptr<MemoryMessageFilter>> - MemoryMessageFilterMap; - MemoryMessageFilterMap memory_message_filters_; + // Set of all memory message filters in the browser process. Always accessed + // on the IO thread. + typedef std::set<scoped_refptr<MemoryMessageFilter>> MemoryMessageFilterSet; + MemoryMessageFilterSet memory_message_filters_; DISALLOW_COPY_AND_ASSIGN(MemoryPressureController); };
diff --git a/content/browser/memory/memory_pressure_controller_browsertest.cc b/content/browser/memory/memory_pressure_controller_browsertest.cc index 5b08a66..c0d4069 100644 --- a/content/browser/memory/memory_pressure_controller_browsertest.cc +++ b/content/browser/memory/memory_pressure_controller_browsertest.cc
@@ -38,25 +38,8 @@ return level == base::get<0>(param); } -MATCHER_P(IsPressureMessage, level, "") { - // Ensure that the message is deleted upon return. - scoped_ptr<IPC::Message> message(arg); - if (message == nullptr) - return false; - MemoryMsg_PressureNotification::Param param; - if (!MemoryMsg_PressureNotification::Read(message.get(), ¶m)) - return false; - return level == base::get<0>(param); -} - class MemoryMessageFilterForTesting : public MemoryMessageFilter { public: - // Use this object itself as a fake RenderProcessHost pointer. The address is - // only used for looking up the message filter in the controller and is never - // actually dereferenced, so this is safe. - MemoryMessageFilterForTesting() - : MemoryMessageFilter(reinterpret_cast<RenderProcessHost*>(this)) {} - MOCK_METHOD1(Send, bool(IPC::Message* message)); void Add() { @@ -108,21 +91,8 @@ ->SimulatePressureNotificationInAllProcesses(level); RunAllPendingInMessageLoop(BrowserThread::IO); } - - void SendPressureNotificationAndWait( - const void* fake_process_host, - base::MemoryPressureListener::MemoryPressureLevel level) { - MemoryPressureController::GetInstance()->SendPressureNotification( - reinterpret_cast<const RenderProcessHost*>(fake_process_host), level); - RunAllPendingInMessageLoop(BrowserThread::IO); - } }; -const auto MEMORY_PRESSURE_LEVEL_MODERATE = - base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE; -const auto MEMORY_PRESSURE_LEVEL_CRITICAL = - base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL; - IN_PROC_BROWSER_TEST_F(MemoryPressureControllerBrowserTest, SetPressureNotificationsSuppressedInAllProcesses) { scoped_refptr<MemoryMessageFilterForTesting> filter1( @@ -138,7 +108,6 @@ EXPECT_CALL(*filter2, Send(testing::_)).Times(0); filter1->Add(); EXPECT_FALSE(base::MemoryPressureListener::AreNotificationsSuppressed()); - testing::Mock::VerifyAndClearExpectations(this); // Enable suppressing memory pressure notifications in all processes. The // first filter should send a message. @@ -146,22 +115,12 @@ EXPECT_CALL(*filter2, Send(testing::_)).Times(0); SetPressureNotificationsSuppressedInAllProcessesAndWait(true); EXPECT_TRUE(base::MemoryPressureListener::AreNotificationsSuppressed()); - testing::Mock::VerifyAndClearExpectations(this); // Add the second filter. It should send a message because notifications are // suppressed. EXPECT_CALL(*filter1, Send(testing::_)).Times(0); EXPECT_CALL(*filter2, Send(IsSetSuppressedMessage(true))).Times(1); filter2->Add(); - testing::Mock::VerifyAndClearExpectations(this); - - // Send a memory pressure event to the first child process. No messages should - // be sent as the notifications are suppressed. - EXPECT_CALL(*filter1, Send(testing::_)).Times(0); - EXPECT_CALL(*filter2, Send(testing::_)).Times(0); - SendPressureNotificationAndWait(filter1.get(), - MEMORY_PRESSURE_LEVEL_MODERATE); - testing::Mock::VerifyAndClearExpectations(this); // Disable suppressing memory pressure notifications in all processes. Both // filters should send a message. @@ -169,30 +128,11 @@ EXPECT_CALL(*filter2, Send(IsSetSuppressedMessage(false))).Times(1); SetPressureNotificationsSuppressedInAllProcessesAndWait(false); EXPECT_FALSE(base::MemoryPressureListener::AreNotificationsSuppressed()); - testing::Mock::VerifyAndClearExpectations(this); - - // Send a memory pressure event to the first child process. A message should - // be received as messages are not being suppressed. - EXPECT_CALL(*filter1, Send(IsPressureMessage(MEMORY_PRESSURE_LEVEL_MODERATE))) - .Times(1); - EXPECT_CALL(*filter2, Send(testing::_)).Times(0); - SendPressureNotificationAndWait(filter1.get(), - MEMORY_PRESSURE_LEVEL_MODERATE); - testing::Mock::VerifyAndClearExpectations(this); - - // Send a memory pressure event to a non-existing child process. No message - // should be sent. - EXPECT_CALL(*filter1, Send(testing::_)).Times(0); - EXPECT_CALL(*filter2, Send(testing::_)).Times(0); - SendPressureNotificationAndWait(reinterpret_cast<const void*>(0xF005BA11), - MEMORY_PRESSURE_LEVEL_MODERATE); - testing::Mock::VerifyAndClearExpectations(this); // Remove the first filter. No messages should be sent. EXPECT_CALL(*filter1, Send(testing::_)).Times(0); EXPECT_CALL(*filter2, Send(testing::_)).Times(0); filter1->Remove(); - testing::Mock::VerifyAndClearExpectations(this); // Enable suppressing memory pressure notifications in all processes. The // second filter should send a message. @@ -200,7 +140,6 @@ EXPECT_CALL(*filter2, Send(IsSetSuppressedMessage(true))).Times(1); SetPressureNotificationsSuppressedInAllProcessesAndWait(true); EXPECT_TRUE(base::MemoryPressureListener::AreNotificationsSuppressed()); - testing::Mock::VerifyAndClearExpectations(this); // Remove the second filter and disable suppressing memory pressure // notifications in all processes. No messages should be sent. @@ -209,11 +148,15 @@ filter2->Remove(); SetPressureNotificationsSuppressedInAllProcessesAndWait(false); EXPECT_FALSE(base::MemoryPressureListener::AreNotificationsSuppressed()); - testing::Mock::VerifyAndClearExpectations(this); } IN_PROC_BROWSER_TEST_F(MemoryPressureControllerBrowserTest, SimulatePressureNotificationInAllProcesses) { + const auto MEMORY_PRESSURE_LEVEL_MODERATE = + base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE; + const auto MEMORY_PRESSURE_LEVEL_CRITICAL = + base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL; + scoped_refptr<MemoryMessageFilterForTesting> filter( new MemoryMessageFilterForTesting); scoped_ptr<base::MemoryPressureListener> listener( @@ -225,26 +168,17 @@ filter->Add(); - // Send a memory pressure event to the first child process. It should send a - // pressure notification message. - EXPECT_CALL(*filter, Send(IsPressureMessage(MEMORY_PRESSURE_LEVEL_MODERATE))) - .Times(1); - SendPressureNotificationAndWait(filter.get(), MEMORY_PRESSURE_LEVEL_MODERATE); - testing::Mock::VerifyAndClearExpectations(this); - EXPECT_CALL(*filter, Send(IsSimulateMessage(MEMORY_PRESSURE_LEVEL_CRITICAL))) .Times(1); EXPECT_CALL(*this, OnMemoryPressure(MEMORY_PRESSURE_LEVEL_CRITICAL)).Times(1); SimulatePressureNotificationInAllProcessesAndWait( MEMORY_PRESSURE_LEVEL_CRITICAL); RunAllPendingInMessageLoop(); // Wait for the listener to run. - testing::Mock::VerifyAndClearExpectations(this); // Enable suppressing memory pressure notifications in all processes. This // should have no impact on simulating memory pressure notifications. EXPECT_CALL(*filter, Send(IsSetSuppressedMessage(true))).Times(1); SetPressureNotificationsSuppressedInAllProcessesAndWait(true); - testing::Mock::VerifyAndClearExpectations(this); EXPECT_CALL(*filter, Send(IsSimulateMessage(MEMORY_PRESSURE_LEVEL_MODERATE))) .Times(1); @@ -252,13 +186,11 @@ SimulatePressureNotificationInAllProcessesAndWait( MEMORY_PRESSURE_LEVEL_MODERATE); RunAllPendingInMessageLoop(); // Wait for the listener to run. - testing::Mock::VerifyAndClearExpectations(this); // Disable suppressing memory pressure notifications in all processes. This // should have no impact on simulating memory pressure notifications. EXPECT_CALL(*filter, Send(IsSetSuppressedMessage(false))).Times(1); SetPressureNotificationsSuppressedInAllProcessesAndWait(false); - testing::Mock::VerifyAndClearExpectations(this); EXPECT_CALL(*filter, Send(IsSimulateMessage(MEMORY_PRESSURE_LEVEL_MODERATE))) .Times(1); @@ -266,7 +198,6 @@ SimulatePressureNotificationInAllProcessesAndWait( MEMORY_PRESSURE_LEVEL_MODERATE); RunAllPendingInMessageLoop(); // Wait for the listener to run. - testing::Mock::VerifyAndClearExpectations(this); filter->Remove(); }
diff --git a/content/browser/mojo/mojo_application_host.cc b/content/browser/mojo/mojo_application_host.cc index a9d0002..edd8d9b 100644 --- a/content/browser/mojo/mojo_application_host.cc +++ b/content/browser/mojo/mojo_application_host.cc
@@ -5,6 +5,7 @@ #include "content/browser/mojo/mojo_application_host.h" #include "content/common/mojo/mojo_messages.h" +#include "content/common/routed_service_provider.mojom.h" #include "content/public/browser/browser_thread.h" #include "ipc/ipc_sender.h" #include "third_party/mojo/src/mojo/edk/embedder/platform_channel_pair.h" @@ -35,8 +36,8 @@ private: // ApplicationSetup implementation. void ExchangeServiceProviders( - mojo::InterfaceRequest<mojo::ServiceProvider> services, - mojo::ServiceProviderPtr exposed_services) override { + mojo::InterfaceRequest<RoutedServiceProvider> services, + RoutedServiceProviderPtr exposed_services) override { service_registry_->Bind(services.Pass()); service_registry_->BindRemoteServiceProvider(exposed_services.Pass()); }
diff --git a/content/browser/mojo/mojo_application_host.h b/content/browser/mojo/mojo_application_host.h index 216b65a..194d30e4 100644 --- a/content/browser/mojo/mojo_application_host.h +++ b/content/browser/mojo/mojo_application_host.h
@@ -40,7 +40,7 @@ void WillDestroySoon(); - ServiceRegistry* service_registry() { return &service_registry_; } + ServiceRegistryImpl* service_registry() { return &service_registry_; } #if defined(OS_ANDROID) ServiceRegistryAndroid* service_registry_android() {
diff --git a/content/browser/mojo/mojo_shell_client_host.cc b/content/browser/mojo/mojo_shell_client_host.cc index e3f962f..1bc85b5 100644 --- a/content/browser/mojo/mojo_shell_client_host.cc +++ b/content/browser/mojo/mojo_shell_client_host.cc
@@ -72,8 +72,7 @@ base::ThreadTaskRunnerHandle::Get())); mojo::shell::mojom::ApplicationManagerPtr application_manager; MojoShellConnection::Get()->GetApplication()->ConnectToService( - mojo::URLRequest::From(std::string("mojo:shell")), - &application_manager); + "mojo:shell", &application_manager); // The content of the URL/qualifier we pass is actually meaningless, it's only // important that they're unique per process. // TODO(beng): We need to specify a restrictive CapabilityFilter here that
diff --git a/content/browser/mojo/mojo_shell_context.cc b/content/browser/mojo/mojo_shell_context.cc index 57f14ea..36ec546 100644 --- a/content/browser/mojo/mojo_shell_context.cc +++ b/content/browser/mojo/mojo_shell_context.cc
@@ -272,8 +272,9 @@ mojo::ServiceProviderPtr exposed_services, const mojo::shell::CapabilityFilter& filter, const mojo::Shell::ConnectToApplicationCallback& callback) { - proxy_.Get()->ConnectToApplication(url, requestor_url, request.Pass(), - exposed_services.Pass(), filter, callback); + proxy_.Get()->ConnectToApplication(url, requestor_url, + request.Pass(), exposed_services.Pass(), + filter, callback); } void MojoShellContext::ConnectToApplicationOnOwnThread(
diff --git a/content/browser/mojo/service_registry_android.cc b/content/browser/mojo/service_registry_android.cc index 269c8be..d2187a3 100644 --- a/content/browser/mojo/service_registry_android.cc +++ b/content/browser/mojo/service_registry_android.cc
@@ -4,10 +4,12 @@ #include "content/browser/mojo/service_registry_android.h" +#include <utility> + #include "base/android/jni_android.h" #include "base/android/jni_string.h" #include "base/callback.h" -#include "content/common/mojo/service_registry_impl.h" +#include "content/public/common/service_registry.h" #include "jni/ServiceRegistry_jni.h" using base::android::AttachCurrentThread; @@ -42,7 +44,7 @@ // Constructor and destructor call into Java. ServiceRegistryAndroid::ServiceRegistryAndroid( - ServiceRegistryImpl* service_registry) + ServiceRegistry* service_registry) : service_registry_(service_registry) { JNIEnv* env = AttachCurrentThread(); obj_.Reset( @@ -71,18 +73,17 @@ ScopedJavaGlobalRef<jobject> j_scoped_factory; j_scoped_factory.Reset(env, j_factory); - service_registry_->AddService(name, - base::Bind(&CreateImplAndAttach, - j_scoped_service_registry, - j_scoped_manager, - j_scoped_factory)); + service_registry_->Add(name, + base::Bind(&CreateImplAndAttach, + j_scoped_service_registry, + j_scoped_manager, j_scoped_factory)); } void ServiceRegistryAndroid::RemoveService(JNIEnv* env, jobject j_service_registry, jstring j_name) { std::string name(ConvertJavaStringToUTF8(env, j_name)); - service_registry_->RemoveService(name); + service_registry_->Remove(name); } void ServiceRegistryAndroid::ConnectToRemoteService(JNIEnv* env, @@ -91,7 +92,7 @@ jint j_handle) { std::string name(ConvertJavaStringToUTF8(env, j_name)); mojo::ScopedMessagePipeHandle handle((mojo::MessagePipeHandle(j_handle))); - service_registry_->ConnectToRemoteService(name, handle.Pass()); + service_registry_->Connect(name, std::move(handle)); } } // namespace content
diff --git a/content/browser/mojo/service_registry_android.h b/content/browser/mojo/service_registry_android.h index 37ec10a4..eb53d27 100644 --- a/content/browser/mojo/service_registry_android.h +++ b/content/browser/mojo/service_registry_android.h
@@ -13,16 +13,16 @@ namespace content { -class ServiceRegistryImpl; +class ServiceRegistry; -// Android wrapper over ServiceRegistryImpl, allowing the browser services in +// Android wrapper over a ServiceRegistry, allowing the browser services in // Java to register with ServiceRegistry.java (and abstracting away the JNI // calls). class CONTENT_EXPORT ServiceRegistryAndroid { public: static bool Register(JNIEnv* env); - explicit ServiceRegistryAndroid(ServiceRegistryImpl* service_registry); + explicit ServiceRegistryAndroid(ServiceRegistry* service_registry); virtual ~ServiceRegistryAndroid(); // Methods called from Java. @@ -40,7 +40,7 @@ const base::android::ScopedJavaGlobalRef<jobject>& GetObj() { return obj_; } private: - ServiceRegistryImpl* service_registry_; + ServiceRegistry* service_registry_; base::android::ScopedJavaGlobalRef<jobject> obj_; DISALLOW_COPY_AND_ASSIGN(ServiceRegistryAndroid);
diff --git a/content/browser/net/view_http_cache_job_factory.cc b/content/browser/net/view_http_cache_job_factory.cc index 22b408e..823ced9c 100644 --- a/content/browser/net/view_http_cache_job_factory.cc +++ b/content/browser/net/view_http_cache_job_factory.cc
@@ -45,8 +45,15 @@ bool GetCharset(std::string* charset) override { return core_->GetCharset(charset); } - int ReadRawData(net::IOBuffer* buf, int buf_size) override { - return core_->ReadRawData(buf, buf_size); + bool ReadRawData(net::IOBuffer* buf, + int buf_size, + int* out_bytes_read) override { + size_t bytes_read; + if (!core_->ReadRawData(buf, base::checked_cast<size_t>(buf_size), + &bytes_read)) + return false; + *out_bytes_read = base::checked_cast<int>(bytes_read); + return true; } private: @@ -66,7 +73,7 @@ bool GetMimeType(std::string* mime_type) const; bool GetCharset(std::string* charset); - int ReadRawData(net::IOBuffer* buf, int buf_size); + bool ReadRawData(net::IOBuffer* buf, size_t buf_size, size_t* bytes_read); private: friend class base::RefCounted<Core>; @@ -165,14 +172,18 @@ return true; } -int ViewHttpCacheJob::Core::ReadRawData(net::IOBuffer* buf, int buf_size) { +bool ViewHttpCacheJob::Core::ReadRawData(net::IOBuffer* buf, + size_t buf_size, + size_t* bytes_read) { + DCHECK(bytes_read); DCHECK_LE(data_offset_, data_.size()); - int remaining = base::checked_cast<int>(data_.size() - data_offset_); + size_t remaining = data_.size() - data_offset_; if (buf_size > remaining) buf_size = remaining; memcpy(buf->data(), data_.data() + data_offset_, buf_size); data_offset_ += buf_size; - return buf_size; + *bytes_read = buf_size; + return true; } void ViewHttpCacheJob::Core::OnIOComplete(int result) {
diff --git a/content/browser/notifications/PRESUBMIT.py b/content/browser/notifications/PRESUBMIT.py new file mode 100644 index 0000000..4fbc9a7 --- /dev/null +++ b/content/browser/notifications/PRESUBMIT.py
@@ -0,0 +1,12 @@ +# Copyright 2015 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. + +"""Top-level presubmit script for notifications. + +See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts +for more details about the presubmit API built into depot_tools. +""" + +def CheckChangeOnUpload(input_api, output_api): + return input_api.canned_checks.CheckPatchFormatted(input_api, output_api)
diff --git a/content/browser/notifications/notification_database.cc b/content/browser/notifications/notification_database.cc index 39f3b0a..4d9f42e 100644 --- a/content/browser/notifications/notification_database.cc +++ b/content/browser/notifications/notification_database.cc
@@ -68,8 +68,7 @@ if (!origin.is_valid()) return kDataKeyPrefix; - return base::StringPrintf("%s%s%c", - kDataKeyPrefix, + return base::StringPrintf("%s%s%c", kDataKeyPrefix, storage::GetIdentifierFromOrigin(origin).c_str(), kKeySeparator); } @@ -98,8 +97,7 @@ } // namespace NotificationDatabase::NotificationDatabase(const base::FilePath& path) - : path_(path) { -} + : path_(path) {} NotificationDatabase::~NotificationDatabase() { DCHECK(sequence_checker_.CalledOnValidSequencedThread()); @@ -111,8 +109,7 @@ DCHECK_EQ(STATE_UNINITIALIZED, state_); if (!create_if_missing) { - if (IsInMemoryDatabase() || - !base::PathExists(path_) || + if (IsInMemoryDatabase() || !base::PathExists(path_) || base::IsDirectoryEmpty(path_)) { return NotificationDatabase::STATUS_ERROR_NOT_FOUND; } @@ -164,8 +161,7 @@ notification_database_data); } -NotificationDatabase::Status -NotificationDatabase::ReadAllNotificationData( +NotificationDatabase::Status NotificationDatabase::ReadAllNotificationData( std::vector<NotificationDatabaseData>* notification_data_vector) const { return ReadAllNotificationDataInternal(GURL() /* origin */, kInvalidServiceWorkerRegistrationId, @@ -176,9 +172,8 @@ NotificationDatabase::ReadAllNotificationDataForOrigin( const GURL& origin, std::vector<NotificationDatabaseData>* notification_data_vector) const { - return ReadAllNotificationDataInternal(origin, - kInvalidServiceWorkerRegistrationId, - notification_data_vector); + return ReadAllNotificationDataInternal( + origin, kInvalidServiceWorkerRegistrationId, notification_data_vector); } NotificationDatabase::Status @@ -186,8 +181,7 @@ const GURL& origin, int64_t service_worker_registration_id, std::vector<NotificationDatabaseData>* notification_data_vector) const { - return ReadAllNotificationDataInternal(origin, - service_worker_registration_id, + return ReadAllNotificationDataInternal(origin, service_worker_registration_id, notification_data_vector); } @@ -206,8 +200,7 @@ storage_data.notification_id = next_notification_id_; std::string serialized_data; - if (!SerializeNotificationDatabaseData(storage_data, - &serialized_data)) { + if (!SerializeNotificationDatabaseData(storage_data, &serialized_data)) { DLOG(ERROR) << "Unable to serialize data for a notification belonging " << "to: " << origin; return STATUS_ERROR_FAILED; @@ -218,8 +211,8 @@ batch.Put(kNextNotificationIdKey, base::Int64ToString(next_notification_id_ + 1)); - Status status = LevelDBStatusToStatus( - db_->Write(leveldb::WriteOptions(), &batch)); + Status status = + LevelDBStatusToStatus(db_->Write(leveldb::WriteOptions(), &batch)); if (status != STATUS_OK) return status; @@ -243,9 +236,8 @@ NotificationDatabase::DeleteAllNotificationDataForOrigin( const GURL& origin, std::set<int64_t>* deleted_notification_set) { - return DeleteAllNotificationDataInternal(origin, - kInvalidServiceWorkerRegistrationId, - deleted_notification_set); + return DeleteAllNotificationDataInternal( + origin, kInvalidServiceWorkerRegistrationId, deleted_notification_set); } NotificationDatabase::Status @@ -253,9 +245,8 @@ const GURL& origin, int64_t service_worker_registration_id, std::set<int64_t>* deleted_notification_set) { - return DeleteAllNotificationDataInternal(origin, - service_worker_registration_id, - deleted_notification_set); + return DeleteAllNotificationDataInternal( + origin, service_worker_registration_id, deleted_notification_set); } NotificationDatabase::Status NotificationDatabase::Destroy() { @@ -359,7 +350,7 @@ return status; if (notification_database_data.service_worker_registration_id != - service_worker_registration_id) { + service_worker_registration_id) { continue; } }
diff --git a/content/browser/notifications/notification_database_data_conversions.cc b/content/browser/notifications/notification_database_data_conversions.cc index c6095e40..ff16527 100644 --- a/content/browser/notifications/notification_database_data_conversions.cc +++ b/content/browser/notifications/notification_database_data_conversions.cc
@@ -51,8 +51,7 @@ if (payload.vibration_pattern().size() > 0) { notification_data->vibration_pattern.assign( - payload.vibration_pattern().begin(), - payload.vibration_pattern().end()); + payload.vibration_pattern().begin(), payload.vibration_pattern().end()); } notification_data->silent = payload.silent();
diff --git a/content/browser/notifications/notification_database_data_unittest.cc b/content/browser/notifications/notification_database_data_unittest.cc index e2bf7d4c..502d3d8 100644 --- a/content/browser/notifications/notification_database_data_unittest.cc +++ b/content/browser/notifications/notification_database_data_unittest.cc
@@ -22,8 +22,8 @@ const char kNotificationBody[] = "Hello, world!"; const char kNotificationTag[] = "my_tag"; const char kNotificationIconUrl[] = "https://example.com/icon.png"; -const int kNotificationVibrationPattern[] = { 100, 200, 300 }; -const unsigned char kNotificationData[] = { 0xdf, 0xff, 0x0, 0x0, 0xff, 0xdf }; +const int kNotificationVibrationPattern[] = {100, 200, 300}; +const unsigned char kNotificationData[] = {0xdf, 0xff, 0x0, 0x0, 0xff, 0xdf}; TEST(NotificationDatabaseDataTest, SerializeAndDeserializeData) { std::vector<int> vibration_pattern( @@ -61,14 +61,14 @@ std::string serialized_data; // Serialize the data in |notification_data| to the string |serialized_data|. - ASSERT_TRUE(SerializeNotificationDatabaseData(database_data, - &serialized_data)); + ASSERT_TRUE( + SerializeNotificationDatabaseData(database_data, &serialized_data)); NotificationDatabaseData copied_data; // Deserialize the data in |serialized_data| to |copied_data|. - ASSERT_TRUE(DeserializeNotificationDatabaseData(serialized_data, - &copied_data)); + ASSERT_TRUE( + DeserializeNotificationDatabaseData(serialized_data, &copied_data)); EXPECT_EQ(database_data.notification_id, copied_data.notification_id); EXPECT_EQ(database_data.origin, copied_data.origin); @@ -86,7 +86,7 @@ EXPECT_EQ(notification_data.icon, copied_notification_data.icon); EXPECT_THAT(copied_notification_data.vibration_pattern, - testing::ElementsAreArray(kNotificationVibrationPattern)); + testing::ElementsAreArray(kNotificationVibrationPattern)); EXPECT_EQ(notification_data.silent, copied_notification_data.silent); EXPECT_EQ(notification_data.require_interaction, @@ -108,10 +108,9 @@ TEST(NotificationDatabaseDataTest, SerializeAndDeserializeDirections) { PlatformNotificationData::Direction directions[] = { - PlatformNotificationData::DIRECTION_LEFT_TO_RIGHT, - PlatformNotificationData::DIRECTION_RIGHT_TO_LEFT, - PlatformNotificationData::DIRECTION_AUTO - }; + PlatformNotificationData::DIRECTION_LEFT_TO_RIGHT, + PlatformNotificationData::DIRECTION_RIGHT_TO_LEFT, + PlatformNotificationData::DIRECTION_AUTO}; for (size_t i = 0; i < arraysize(directions); ++i) { PlatformNotificationData notification_data; @@ -121,12 +120,12 @@ database_data.notification_data = notification_data; std::string serialized_data; - ASSERT_TRUE(SerializeNotificationDatabaseData(database_data, - &serialized_data)); + ASSERT_TRUE( + SerializeNotificationDatabaseData(database_data, &serialized_data)); NotificationDatabaseData copied_data; - ASSERT_TRUE(DeserializeNotificationDatabaseData(serialized_data, - &copied_data)); + ASSERT_TRUE( + DeserializeNotificationDatabaseData(serialized_data, &copied_data)); EXPECT_EQ(directions[i], copied_data.notification_data.direction); }
diff --git a/content/browser/notifications/notification_database_unittest.cc b/content/browser/notifications/notification_database_unittest.cc index a4dbff33..9d94730 100644 --- a/content/browser/notifications/notification_database_unittest.cc +++ b/content/browser/notifications/notification_database_unittest.cc
@@ -22,14 +22,13 @@ const char* origin; int64_t service_worker_registration_id; } kExampleNotificationData[] = { - { "https://example.com", 0 }, - { "https://example.com", kExampleServiceWorkerRegistrationId }, - { "https://example.com", kExampleServiceWorkerRegistrationId }, - { "https://example.com", kExampleServiceWorkerRegistrationId + 1 }, - { "https://chrome.com", 0 }, - { "https://chrome.com", 0 }, - { "https://chrome.com", kExampleServiceWorkerRegistrationId } -}; + {"https://example.com", 0}, + {"https://example.com", kExampleServiceWorkerRegistrationId}, + {"https://example.com", kExampleServiceWorkerRegistrationId}, + {"https://example.com", kExampleServiceWorkerRegistrationId + 1}, + {"https://chrome.com", 0}, + {"https://chrome.com", 0}, + {"https://chrome.com", kExampleServiceWorkerRegistrationId}}; class NotificationDatabaseTest : public ::testing::Test { protected: @@ -39,8 +38,7 @@ } // Creates a new NotificationDatabase instance in |path|. - NotificationDatabase* CreateDatabaseOnFileSystem( - const base::FilePath& path) { + NotificationDatabase* CreateDatabaseOnFileSystem(const base::FilePath& path) { return new NotificationDatabase(path); } @@ -57,8 +55,7 @@ service_worker_registration_id; ASSERT_EQ(NotificationDatabase::STATUS_OK, - database->WriteNotificationData(origin, - database_data, + database->WriteNotificationData(origin, database_data, notification_id)); } @@ -68,8 +65,7 @@ int64_t notification_id; for (size_t i = 0; i < arraysize(kExampleNotificationData); ++i) { ASSERT_NO_FATAL_FAILURE(CreateAndWriteNotification( - database, - GURL(kExampleNotificationData[i].origin), + database, GURL(kExampleNotificationData[i].origin), kExampleNotificationData[i].service_worker_registration_id, ¬ification_id)); } @@ -210,15 +206,13 @@ database_data.notification_id = -1; int64_t notification_id = 0; - ASSERT_EQ(NotificationDatabase::STATUS_OK, - database->WriteNotificationData(origin, - database_data, - ¬ification_id)); + ASSERT_EQ( + NotificationDatabase::STATUS_OK, + database->WriteNotificationData(origin, database_data, ¬ification_id)); - ASSERT_EQ(NotificationDatabase::STATUS_OK, - database->ReadNotificationData(notification_id, - origin, - &database_data)); + ASSERT_EQ( + NotificationDatabase::STATUS_OK, + database->ReadNotificationData(notification_id, origin, &database_data)); EXPECT_EQ(notification_id, database_data.notification_id); } @@ -238,18 +232,16 @@ NotificationDatabaseData database_data; int64_t notification_id = 0; - ASSERT_EQ(NotificationDatabase::STATUS_OK, - database->WriteNotificationData(origin, - database_data, - ¬ification_id)); + ASSERT_EQ( + NotificationDatabase::STATUS_OK, + database->WriteNotificationData(origin, database_data, ¬ification_id)); EXPECT_EQ(notification_id, 1); // Deliberately write an invalid value as the next notification id. When // re-opening the database, the Open() method should realize that an invalid // value is being read, and mark the database as corrupted. - ASSERT_NO_FATAL_FAILURE(WriteLevelDBKeyValuePair(database.get(), - "NEXT_NOTIFICATION_ID", - "-42")); + ASSERT_NO_FATAL_FAILURE( + WriteLevelDBKeyValuePair(database.get(), "NEXT_NOTIFICATION_ID", "-42")); database.reset(CreateDatabaseOnFileSystem(database_dir.path())); EXPECT_EQ(NotificationDatabase::STATUS_ERROR_CORRUPTED, @@ -266,8 +258,7 @@ // Reading the notification data for a notification that does not exist should // return the ERROR_NOT_FOUND status code. EXPECT_EQ(NotificationDatabase::STATUS_ERROR_NOT_FOUND, - database->ReadNotificationData(9001, - GURL("https://chrome.com"), + database->ReadNotificationData(9001, GURL("https://chrome.com"), &database_data)); } @@ -282,23 +273,21 @@ NotificationDatabaseData database_data, read_database_data; database_data.notification_data.title = base::UTF8ToUTF16("My Notification"); - ASSERT_EQ(NotificationDatabase::STATUS_OK, - database->WriteNotificationData(origin, - database_data, - ¬ification_id)); + ASSERT_EQ( + NotificationDatabase::STATUS_OK, + database->WriteNotificationData(origin, database_data, ¬ification_id)); // Reading the notification from the database when given a different origin // should return the ERROR_NOT_FOUND status code. - EXPECT_EQ(NotificationDatabase::STATUS_ERROR_NOT_FOUND, - database->ReadNotificationData(notification_id, - GURL("https://chrome.com"), - &read_database_data)); + EXPECT_EQ( + NotificationDatabase::STATUS_ERROR_NOT_FOUND, + database->ReadNotificationData( + notification_id, GURL("https://chrome.com"), &read_database_data)); // However, reading the notification from the database with the same origin // should return STATUS_OK and the associated notification data. ASSERT_EQ(NotificationDatabase::STATUS_OK, - database->ReadNotificationData(notification_id, - origin, + database->ReadNotificationData(notification_id, origin, &read_database_data)); EXPECT_EQ(database_data.notification_data.title, @@ -332,15 +321,13 @@ // Write the constructed notification to the database, and then immediately // read it back from the database again as well. - ASSERT_EQ(NotificationDatabase::STATUS_OK, - database->WriteNotificationData(origin, - database_data, - ¬ification_id)); + ASSERT_EQ( + NotificationDatabase::STATUS_OK, + database->WriteNotificationData(origin, database_data, ¬ification_id)); NotificationDatabaseData read_database_data; ASSERT_EQ(NotificationDatabase::STATUS_OK, - database->ReadNotificationData(notification_id, - origin, + database->ReadNotificationData(notification_id, origin, &read_database_data)); // Verify that all members retrieved from the database are exactly the same @@ -386,8 +373,7 @@ // of each of them matches with how they were created. for (int i = 1; i <= 10; ++i) { ASSERT_EQ(NotificationDatabase::STATUS_OK, - database->ReadNotificationData(i /* notification_id */, - origin, + database->ReadNotificationData(i /* notification_id */, origin, &database_data)); EXPECT_EQ(i, database_data.service_worker_registration_id); @@ -401,8 +387,7 @@ // Deleting non-existing notifications is not considered to be a failure. ASSERT_EQ(NotificationDatabase::STATUS_OK, - database->DeleteNotificationData(9001, - GURL("https://chrome.com"))); + database->DeleteNotificationData(9001, GURL("https://chrome.com"))); } TEST_F(NotificationDatabaseTest, DeleteNotificationDataSameOrigin) { @@ -415,25 +400,22 @@ NotificationDatabaseData database_data; GURL origin("https://example.com"); - ASSERT_EQ(NotificationDatabase::STATUS_OK, - database->WriteNotificationData(origin, - database_data, - ¬ification_id)); + ASSERT_EQ( + NotificationDatabase::STATUS_OK, + database->WriteNotificationData(origin, database_data, ¬ification_id)); // Reading a notification after writing one should succeed. - EXPECT_EQ(NotificationDatabase::STATUS_OK, - database->ReadNotificationData(notification_id, - origin, - &database_data)); + EXPECT_EQ( + NotificationDatabase::STATUS_OK, + database->ReadNotificationData(notification_id, origin, &database_data)); // Delete the notification which was just written to the database, and verify // that reading it again will fail. EXPECT_EQ(NotificationDatabase::STATUS_OK, database->DeleteNotificationData(notification_id, origin)); - EXPECT_EQ(NotificationDatabase::STATUS_ERROR_NOT_FOUND, - database->ReadNotificationData(notification_id, - origin, - &database_data)); + EXPECT_EQ( + NotificationDatabase::STATUS_ERROR_NOT_FOUND, + database->ReadNotificationData(notification_id, origin, &database_data)); } TEST_F(NotificationDatabaseTest, DeleteNotificationDataDifferentOrigin) { @@ -446,10 +428,9 @@ NotificationDatabaseData database_data; GURL origin("https://example.com"); - ASSERT_EQ(NotificationDatabase::STATUS_OK, - database->WriteNotificationData(origin, - database_data, - ¬ification_id)); + ASSERT_EQ( + NotificationDatabase::STATUS_OK, + database->WriteNotificationData(origin, database_data, ¬ification_id)); // Attempting to delete the notification with a different origin, but with the // same |notification_id|, should not return an error (the notification could @@ -459,10 +440,9 @@ database->DeleteNotificationData(notification_id, GURL("https://chrome.com"))); - EXPECT_EQ(NotificationDatabase::STATUS_OK, - database->ReadNotificationData(notification_id, - origin, - &database_data)); + EXPECT_EQ( + NotificationDatabase::STATUS_OK, + database->ReadNotificationData(notification_id, origin, &database_data)); } TEST_F(NotificationDatabaseTest, ReadAllNotificationData) { @@ -575,8 +555,7 @@ std::set<int64_t> deleted_notification_set; ASSERT_EQ(NotificationDatabase::STATUS_OK, database->DeleteAllNotificationDataForServiceWorkerRegistration( - origin, - kExampleServiceWorkerRegistrationId, + origin, kExampleServiceWorkerRegistrationId, &deleted_notification_set)); EXPECT_EQ(2u, deleted_notification_set.size());
diff --git a/content/browser/notifications/notification_event_dispatcher_impl.cc b/content/browser/notifications/notification_event_dispatcher_impl.cc index a1166485..fb9d0b7 100644 --- a/content/browser/notifications/notification_event_dispatcher_impl.cc +++ b/content/browser/notifications/notification_event_dispatcher_impl.cc
@@ -67,8 +67,7 @@ break; } - BrowserThread::PostTask(BrowserThread::UI, - FROM_HERE, + BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, base::Bind(dispatch_complete_callback, status)); } @@ -83,9 +82,9 @@ service_worker_registration) { DCHECK_CURRENTLY_ON(BrowserThread::IO); #if defined(OS_ANDROID) - // This LOG(INFO) deliberately exists to help track down the cause of - // https://crbug.com/534537, where notifications sometimes do not react to - // the user clicking on them. It should be removed once that's fixed. + // This LOG(INFO) deliberately exists to help track down the cause of + // https://crbug.com/534537, where notifications sometimes do not react to + // the user clicking on them. It should be removed once that's fixed. LOG(INFO) << "Trying to dispatch notification for SW with status: " << service_worker_status << " action_index: " << action_index; #endif @@ -95,12 +94,10 @@ service_worker_registration); DCHECK(service_worker_registration->active_version()); - service_worker_registration->active_version()-> - DispatchNotificationClickEvent( - dispatch_event_callback, - notification_database_data.notification_id, - notification_database_data.notification_data, - action_index); + service_worker_registration->active_version() + ->DispatchNotificationClickEvent( + dispatch_event_callback, notification_database_data.notification_id, + notification_database_data.notification_data, action_index); return; } @@ -134,8 +131,7 @@ break; } - BrowserThread::PostTask(BrowserThread::UI, - FROM_HERE, + BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, base::Bind(dispatch_complete_callback, status)); } @@ -159,16 +155,14 @@ #endif if (!success) { BrowserThread::PostTask( - BrowserThread::UI, - FROM_HERE, + BrowserThread::UI, FROM_HERE, base::Bind(dispatch_complete_callback, PERSISTENT_NOTIFICATION_STATUS_DATABASE_ERROR)); return; } service_worker_context->FindReadyRegistrationForId( - notification_database_data.service_worker_registration_id, - origin, + notification_database_data.service_worker_registration_id, origin, base::Bind(&DispatchNotificationClickEventOnRegistration, notification_database_data, action_index, dispatch_complete_callback)); @@ -185,11 +179,9 @@ scoped_refptr<PlatformNotificationContextImpl> notification_context) { DCHECK_CURRENTLY_ON(BrowserThread::IO); notification_context->ReadNotificationData( - persistent_notification_id, - origin, - base::Bind(&FindServiceWorkerRegistration, - origin, action_index, dispatch_complete_callback, - service_worker_context)); + persistent_notification_id, origin, + base::Bind(&FindServiceWorkerRegistration, origin, action_index, + dispatch_complete_callback, service_worker_context)); } } // namespace @@ -231,15 +223,10 @@ partition->GetPlatformNotificationContext()); BrowserThread::PostTask( - BrowserThread::IO, - FROM_HERE, - base::Bind(&ReadNotificationDatabaseData, - persistent_notification_id, - origin, - action_index, - dispatch_complete_callback, - service_worker_context, - notification_context)); + BrowserThread::IO, FROM_HERE, + base::Bind(&ReadNotificationDatabaseData, persistent_notification_id, + origin, action_index, dispatch_complete_callback, + service_worker_context, notification_context)); } } // namespace content
diff --git a/content/browser/notifications/notification_id_generator_unittest.cc b/content/browser/notifications/notification_id_generator_unittest.cc index 770822f0..4f12fcc9 100644 --- a/content/browser/notifications/notification_id_generator_unittest.cc +++ b/content/browser/notifications/notification_id_generator_unittest.cc
@@ -37,9 +37,7 @@ NotificationIdGeneratorTest() : generator_(&browser_context_, kRenderProcessId) {} - void SetUp() override { - - } + void SetUp() override {} protected: GURL origin() const { return GURL("https://example.com"); } @@ -65,30 +63,26 @@ // in exactly the same notification ids being generated. TEST_F(NotificationIdGeneratorTest, DeterministicGeneration) { // Persistent notifications. - EXPECT_EQ( - generator()->GenerateForPersistentNotification( - origin(), kExampleTag, kPersistentNotificationId), - generator()->GenerateForPersistentNotification( - origin(), kExampleTag, kPersistentNotificationId)); + EXPECT_EQ(generator()->GenerateForPersistentNotification( + origin(), kExampleTag, kPersistentNotificationId), + generator()->GenerateForPersistentNotification( + origin(), kExampleTag, kPersistentNotificationId)); - EXPECT_EQ( - generator()->GenerateForPersistentNotification( - origin(), "" /* tag */, kPersistentNotificationId), - generator()->GenerateForPersistentNotification( - origin(), "" /* tag */, kPersistentNotificationId)); + EXPECT_EQ(generator()->GenerateForPersistentNotification( + origin(), "" /* tag */, kPersistentNotificationId), + generator()->GenerateForPersistentNotification( + origin(), "" /* tag */, kPersistentNotificationId)); // Non-persistent notifications. - EXPECT_EQ( - generator()->GenerateForNonPersistentNotification( - origin(), kExampleTag, kNonPersistentNotificationId), - generator()->GenerateForNonPersistentNotification( - origin(), kExampleTag, kNonPersistentNotificationId)); + EXPECT_EQ(generator()->GenerateForNonPersistentNotification( + origin(), kExampleTag, kNonPersistentNotificationId), + generator()->GenerateForNonPersistentNotification( + origin(), kExampleTag, kNonPersistentNotificationId)); - EXPECT_EQ( - generator()->GenerateForNonPersistentNotification( - origin(), "" /* tag */, kNonPersistentNotificationId), - generator()->GenerateForNonPersistentNotification( - origin(), "" /* tag */, kNonPersistentNotificationId)); + EXPECT_EQ(generator()->GenerateForNonPersistentNotification( + origin(), "" /* tag */, kNonPersistentNotificationId), + generator()->GenerateForNonPersistentNotification( + origin(), "" /* tag */, kNonPersistentNotificationId)); } // Uniqueness of notification ids will be impacted by the browser context. @@ -98,30 +92,26 @@ kRenderProcessId); // Persistent notifications. - EXPECT_NE( - generator()->GenerateForPersistentNotification( - origin(), kExampleTag, kPersistentNotificationId), - second_generator.GenerateForPersistentNotification( - origin(), kExampleTag, kPersistentNotificationId)); + EXPECT_NE(generator()->GenerateForPersistentNotification( + origin(), kExampleTag, kPersistentNotificationId), + second_generator.GenerateForPersistentNotification( + origin(), kExampleTag, kPersistentNotificationId)); - EXPECT_NE( - generator()->GenerateForPersistentNotification( - origin(), "" /* tag */, kPersistentNotificationId), - second_generator.GenerateForPersistentNotification( - origin(), "" /* tag */, kPersistentNotificationId)); + EXPECT_NE(generator()->GenerateForPersistentNotification( + origin(), "" /* tag */, kPersistentNotificationId), + second_generator.GenerateForPersistentNotification( + origin(), "" /* tag */, kPersistentNotificationId)); // Non-persistent notifications. - EXPECT_NE( - generator()->GenerateForNonPersistentNotification( - origin(), kExampleTag, kNonPersistentNotificationId), - second_generator.GenerateForNonPersistentNotification( - origin(), kExampleTag, kNonPersistentNotificationId)); + EXPECT_NE(generator()->GenerateForNonPersistentNotification( + origin(), kExampleTag, kNonPersistentNotificationId), + second_generator.GenerateForNonPersistentNotification( + origin(), kExampleTag, kNonPersistentNotificationId)); - EXPECT_NE( - generator()->GenerateForNonPersistentNotification( - origin(), "" /* tag */, kNonPersistentNotificationId), - second_generator.GenerateForNonPersistentNotification( - origin(), "" /* tag */, kNonPersistentNotificationId)); + EXPECT_NE(generator()->GenerateForNonPersistentNotification( + origin(), "" /* tag */, kNonPersistentNotificationId), + second_generator.GenerateForNonPersistentNotification( + origin(), "" /* tag */, kNonPersistentNotificationId)); } // Uniqueness of notification ids will be impacted by the fact whether the @@ -131,15 +121,15 @@ // Persistent notifications. std::string normal_persistent_notification_id = - generator()->GenerateForPersistentNotification( - origin(), kExampleTag, kPersistentNotificationId); + generator()->GenerateForPersistentNotification(origin(), kExampleTag, + kPersistentNotificationId); browser_context()->set_incognito(true); ASSERT_TRUE(browser_context()->IsOffTheRecord()); std::string incognito_persistent_notification_id = - generator()->GenerateForPersistentNotification( - origin(), kExampleTag, kPersistentNotificationId); + generator()->GenerateForPersistentNotification(origin(), kExampleTag, + kPersistentNotificationId); EXPECT_NE(normal_persistent_notification_id, incognito_persistent_notification_id); @@ -169,18 +159,16 @@ GURL different_origin("https://example2.com"); // Persistent notifications. - EXPECT_NE( - generator()->GenerateForPersistentNotification( - origin(), kExampleTag, kPersistentNotificationId), - generator()->GenerateForPersistentNotification( - different_origin, kExampleTag, kPersistentNotificationId)); + EXPECT_NE(generator()->GenerateForPersistentNotification( + origin(), kExampleTag, kPersistentNotificationId), + generator()->GenerateForPersistentNotification( + different_origin, kExampleTag, kPersistentNotificationId)); // Non-persistent notifications. - EXPECT_NE( - generator()->GenerateForNonPersistentNotification( - origin(), kExampleTag, kNonPersistentNotificationId), - generator()->GenerateForNonPersistentNotification( - different_origin, kExampleTag, kNonPersistentNotificationId)); + EXPECT_NE(generator()->GenerateForNonPersistentNotification( + origin(), kExampleTag, kNonPersistentNotificationId), + generator()->GenerateForNonPersistentNotification( + different_origin, kExampleTag, kNonPersistentNotificationId)); } // The tag, when non-empty, will impact the generated notification id. @@ -188,18 +176,16 @@ const std::string& different_tag = std::string(kExampleTag) + "2"; // Persistent notifications. - EXPECT_NE( - generator()->GenerateForPersistentNotification( - origin(), kExampleTag, kPersistentNotificationId), - generator()->GenerateForPersistentNotification( - origin(), different_tag, kPersistentNotificationId)); + EXPECT_NE(generator()->GenerateForPersistentNotification( + origin(), kExampleTag, kPersistentNotificationId), + generator()->GenerateForPersistentNotification( + origin(), different_tag, kPersistentNotificationId)); // Non-persistent notifications. - EXPECT_NE( - generator()->GenerateForNonPersistentNotification( - origin(), kExampleTag, kNonPersistentNotificationId), - generator()->GenerateForNonPersistentNotification( - origin(), different_tag, kNonPersistentNotificationId)); + EXPECT_NE(generator()->GenerateForNonPersistentNotification( + origin(), kExampleTag, kNonPersistentNotificationId), + generator()->GenerateForNonPersistentNotification( + origin(), different_tag, kNonPersistentNotificationId)); } // The persistent or non-persistent notification id will impact the generated @@ -209,47 +195,40 @@ kRenderProcessId + 1); // Persistent notifications. - EXPECT_NE( - generator()->GenerateForPersistentNotification( - origin(), "" /* tag */, kPersistentNotificationId), - generator()->GenerateForPersistentNotification( - origin(), "" /* tag */, kPersistentNotificationId + 1)); + EXPECT_NE(generator()->GenerateForPersistentNotification( + origin(), "" /* tag */, kPersistentNotificationId), + generator()->GenerateForPersistentNotification( + origin(), "" /* tag */, kPersistentNotificationId + 1)); // Non-persistent notifications. - EXPECT_NE( - generator()->GenerateForNonPersistentNotification( - origin(), "" /* tag */, kNonPersistentNotificationId), - generator()->GenerateForNonPersistentNotification( - origin(), "" /* tag */, kNonPersistentNotificationId + 1)); + EXPECT_NE(generator()->GenerateForNonPersistentNotification( + origin(), "" /* tag */, kNonPersistentNotificationId), + generator()->GenerateForNonPersistentNotification( + origin(), "" /* tag */, kNonPersistentNotificationId + 1)); // Non-persistent when a tag is being used. - EXPECT_EQ( - generator()->GenerateForNonPersistentNotification( - origin(), kExampleTag, kNonPersistentNotificationId), - second_generator.GenerateForNonPersistentNotification( - origin(), kExampleTag, kNonPersistentNotificationId)); + EXPECT_EQ(generator()->GenerateForNonPersistentNotification( + origin(), kExampleTag, kNonPersistentNotificationId), + second_generator.GenerateForNonPersistentNotification( + origin(), kExampleTag, kNonPersistentNotificationId)); } // Using a numeric tag that could resemble a persistent notification id should // not be equal to a notification without a tag, but with that id. TEST_F(NotificationIdGeneratorTest, NumericTagAmbiguity) { // Persistent notifications. - EXPECT_NE( - generator()->GenerateForPersistentNotification( - origin(), - base::Int64ToString(kPersistentNotificationId), - kPersistentNotificationId), - generator()->GenerateForPersistentNotification( - origin(), "" /* tag */, kPersistentNotificationId)); + EXPECT_NE(generator()->GenerateForPersistentNotification( + origin(), base::Int64ToString(kPersistentNotificationId), + kPersistentNotificationId), + generator()->GenerateForPersistentNotification( + origin(), "" /* tag */, kPersistentNotificationId)); // Non-persistent notifications. - EXPECT_NE( - generator()->GenerateForNonPersistentNotification( - origin(), - base::IntToString(kNonPersistentNotificationId), - kNonPersistentNotificationId), - generator()->GenerateForNonPersistentNotification( - origin(), "" /* tag */, kNonPersistentNotificationId)); + EXPECT_NE(generator()->GenerateForNonPersistentNotification( + origin(), base::IntToString(kNonPersistentNotificationId), + kNonPersistentNotificationId), + generator()->GenerateForNonPersistentNotification( + origin(), "" /* tag */, kNonPersistentNotificationId)); } // Using port numbers and a tag which, when concatenated, could end up being @@ -259,18 +238,16 @@ GURL origin_8051("https://example.com:8051"); // Persistent notifications. - EXPECT_NE( - generator()->GenerateForPersistentNotification( - origin_805, "17", kPersistentNotificationId), - generator()->GenerateForPersistentNotification( - origin_8051, "7", kPersistentNotificationId)); + EXPECT_NE(generator()->GenerateForPersistentNotification( + origin_805, "17", kPersistentNotificationId), + generator()->GenerateForPersistentNotification( + origin_8051, "7", kPersistentNotificationId)); // Non-persistent notifications. - EXPECT_NE( - generator()->GenerateForNonPersistentNotification( - origin_805, "17", kNonPersistentNotificationId), - generator()->GenerateForNonPersistentNotification( - origin_8051, "7", kNonPersistentNotificationId)); + EXPECT_NE(generator()->GenerateForNonPersistentNotification( + origin_805, "17", kNonPersistentNotificationId), + generator()->GenerateForNonPersistentNotification( + origin_8051, "7", kNonPersistentNotificationId)); } // ----------------------------------------------------------------------------- @@ -283,17 +260,15 @@ NotificationIdGenerator second_generator(browser_context(), kRenderProcessId + 1); - EXPECT_EQ( - generator()->GenerateForPersistentNotification( - origin(), kExampleTag, kPersistentNotificationId), - second_generator.GenerateForPersistentNotification( - origin(), kExampleTag, kPersistentNotificationId)); + EXPECT_EQ(generator()->GenerateForPersistentNotification( + origin(), kExampleTag, kPersistentNotificationId), + second_generator.GenerateForPersistentNotification( + origin(), kExampleTag, kPersistentNotificationId)); - EXPECT_EQ( - generator()->GenerateForPersistentNotification( - origin(), "" /* tag */, kPersistentNotificationId), - second_generator.GenerateForPersistentNotification( - origin(), "" /* tag */, kPersistentNotificationId)); + EXPECT_EQ(generator()->GenerateForPersistentNotification( + origin(), "" /* tag */, kPersistentNotificationId), + second_generator.GenerateForPersistentNotification( + origin(), "" /* tag */, kPersistentNotificationId)); } // ----------------------------------------------------------------------------- @@ -308,17 +283,15 @@ NotificationIdGenerator second_generator(browser_context(), kRenderProcessId + 1); - EXPECT_EQ( - generator()->GenerateForNonPersistentNotification( - origin(), kExampleTag, kNonPersistentNotificationId), - second_generator.GenerateForNonPersistentNotification( - origin(), kExampleTag, kNonPersistentNotificationId)); + EXPECT_EQ(generator()->GenerateForNonPersistentNotification( + origin(), kExampleTag, kNonPersistentNotificationId), + second_generator.GenerateForNonPersistentNotification( + origin(), kExampleTag, kNonPersistentNotificationId)); - EXPECT_NE( - generator()->GenerateForNonPersistentNotification( - origin(), "" /* tag */, kNonPersistentNotificationId), - second_generator.GenerateForNonPersistentNotification( - origin(), "" /* tag */, kNonPersistentNotificationId)); + EXPECT_NE(generator()->GenerateForNonPersistentNotification( + origin(), "" /* tag */, kNonPersistentNotificationId), + second_generator.GenerateForNonPersistentNotification( + origin(), "" /* tag */, kNonPersistentNotificationId)); } // Concatenation of the render process id and the non-persistent notification
diff --git a/content/browser/notifications/notification_message_filter.cc b/content/browser/notifications/notification_message_filter.cc index 3269156..1086cf11 100644 --- a/content/browser/notifications/notification_message_filter.cc +++ b/content/browser/notifications/notification_message_filter.cc
@@ -23,7 +23,7 @@ namespace { -const int kMinimumVibrationDurationMs = 1; // 1 millisecond +const int kMinimumVibrationDurationMs = 1; // 1 millisecond const int kMaximumVibrationDurationMs = 10000; // 10 seconds PlatformNotificationData SanitizeNotificationData( @@ -33,7 +33,7 @@ // Make sure that the vibration values are within reasonable bounds. for (int& pattern : sanitized_data.vibration_pattern) { pattern = std::min(kMaximumVibrationDurationMs, - std::max(kMinimumVibrationDurationMs, pattern)); + std::max(kMinimumVibrationDurationMs, pattern)); } // Ensure there aren't more actions than supported. @@ -124,12 +124,9 @@ return; base::Closure close_closure; - service->DisplayNotification(browser_context_, - origin, - icon, + service->DisplayNotification(browser_context_, origin, icon, SanitizeNotificationData(notification_data), - delegate.Pass(), - &close_closure); + delegate.Pass(), &close_closure); if (!close_closure.is_null()) close_closures_[notification_id] = close_closure; @@ -143,7 +140,7 @@ const PlatformNotificationData& notification_data) { DCHECK_CURRENTLY_ON(BrowserThread::IO); if (GetPermissionForOriginOnIO(origin) != - blink::WebNotificationPermissionAllowed) { + blink::WebNotificationPermissionAllowed) { bad_message::ReceivedBadMessage(this, bad_message::NMF_NO_PERMISSION_SHOW); return; } @@ -159,13 +156,9 @@ // TODO(peter): Significantly reduce the amount of information we need to // retain outside of the database for displaying notifications. notification_context_->WriteNotificationData( - origin, - database_data, + origin, database_data, base::Bind(&NotificationMessageFilter::DidWritePersistentNotificationData, - weak_factory_io_.GetWeakPtr(), - request_id, - origin, - icon, + weak_factory_io_.GetWeakPtr(), request_id, origin, icon, sanitized_notification_data)); } @@ -180,18 +173,14 @@ if (success) { PlatformNotificationService* service = - GetContentClient()->browser()->GetPlatformNotificationService(); + GetContentClient()->browser()->GetPlatformNotificationService(); DCHECK(service); BrowserThread::PostTask( - BrowserThread::UI, - FROM_HERE, + BrowserThread::UI, FROM_HERE, base::Bind(&PlatformNotificationService::DisplayPersistentNotification, base::Unretained(service), // The service is a singleton. - browser_context_, - persistent_notification_id, - origin, - icon, + browser_context_, persistent_notification_id, origin, icon, notification_data)); } @@ -205,7 +194,7 @@ const std::string& filter_tag) { DCHECK_CURRENTLY_ON(BrowserThread::IO); if (GetPermissionForOriginOnIO(origin) != - blink::WebNotificationPermissionAllowed) { + blink::WebNotificationPermissionAllowed) { // No permission has been granted for the given origin. It is harmless to // try to get notifications without permission, so return an empty vector // indicating that no (accessible) notifications exist at this time. @@ -215,12 +204,9 @@ } notification_context_->ReadAllNotificationDataForServiceWorkerRegistration( - origin, - service_worker_registration_id, + origin, service_worker_registration_id, base::Bind(&NotificationMessageFilter::DidGetNotifications, - weak_factory_io_.GetWeakPtr(), - request_id, - filter_tag)); + weak_factory_io_.GetWeakPtr(), request_id, filter_tag)); } void NotificationMessageFilter::DidGetNotifications( @@ -262,7 +248,7 @@ int64_t persistent_notification_id) { DCHECK_CURRENTLY_ON(BrowserThread::IO); if (GetPermissionForOriginOnIO(origin) != - blink::WebNotificationPermissionAllowed) { + blink::WebNotificationPermissionAllowed) { bad_message::ReceivedBadMessage(this, bad_message::NMF_NO_PERMISSION_CLOSE); return; } @@ -274,19 +260,16 @@ // There's no point in waiting until the database data has been removed before // closing the notification presented to the user. Post that task immediately. BrowserThread::PostTask( - BrowserThread::UI, - FROM_HERE, + BrowserThread::UI, FROM_HERE, base::Bind(&PlatformNotificationService::ClosePersistentNotification, base::Unretained(service), // The service is a singleton. - browser_context_, - persistent_notification_id)); + browser_context_, persistent_notification_id)); notification_context_->DeleteNotificationData( - persistent_notification_id, - origin, - base::Bind(&NotificationMessageFilter:: - DidDeletePersistentNotificationData, - weak_factory_io_.GetWeakPtr())); + persistent_notification_id, origin, + base::Bind( + &NotificationMessageFilter::DidDeletePersistentNotificationData, + weak_factory_io_.GetWeakPtr())); } void NotificationMessageFilter::DidDeletePersistentNotificationData( @@ -306,8 +289,7 @@ if (!service) return blink::WebNotificationPermissionDenied; - return service->CheckPermissionOnIOThread(resource_context_, - origin, + return service->CheckPermissionOnIOThread(resource_context_, origin, process_id_); } @@ -317,9 +299,7 @@ DCHECK_CURRENTLY_ON(BrowserThread::UI); blink::WebNotificationPermission permission = - service->CheckPermissionOnUIThread(browser_context_, - origin, - process_id_); + service->CheckPermissionOnUIThread(browser_context_, origin, process_id_); if (permission == blink::WebNotificationPermissionAllowed) return true;
diff --git a/content/browser/notifications/notification_message_filter.h b/content/browser/notifications/notification_message_filter.h index c5ad0a4ac..3eba9960 100644 --- a/content/browser/notifications/notification_message_filter.h +++ b/content/browser/notifications/notification_message_filter.h
@@ -39,8 +39,8 @@ // BrowserMessageFilter implementation. Called on the UI thread. void OnDestruct() const override; bool OnMessageReceived(const IPC::Message& message) override; - void OverrideThreadForMessage( - const IPC::Message& message, content::BrowserThread::ID* thread) override; + void OverrideThreadForMessage(const IPC::Message& message, + content::BrowserThread::ID* thread) override; protected: ~NotificationMessageFilter() override; @@ -67,9 +67,8 @@ const GURL& origin, const std::string& filter_tag); void OnClosePlatformNotification(int notification_id); - void OnClosePersistentNotification( - const GURL& origin, - int64_t persistent_notification_id); + void OnClosePersistentNotification(const GURL& origin, + int64_t persistent_notification_id); // Callback to be invoked by the notification context when the notification // data for the persistent notification may have been written, as indicated by @@ -107,9 +106,8 @@ // cases where the renderer shouldn't send messages if it weren't the case. If // no permission has been granted, a bad message has been received and the // renderer should be killed accordingly. - bool VerifyNotificationPermissionGranted( - PlatformNotificationService* service, - const GURL& origin); + bool VerifyNotificationPermissionGranted(PlatformNotificationService* service, + const GURL& origin); int process_id_; scoped_refptr<PlatformNotificationContextImpl> notification_context_;
diff --git a/content/browser/notifications/page_notification_delegate.cc b/content/browser/notifications/page_notification_delegate.cc index fdf085d..03f5b58 100644 --- a/content/browser/notifications/page_notification_delegate.cc +++ b/content/browser/notifications/page_notification_delegate.cc
@@ -33,7 +33,8 @@ sender->Send(new PlatformNotificationMsg_DidClose(notification_id_)); static_cast<RenderProcessHostImpl*>(sender) - ->notification_message_filter()->DidCloseNotification(notification_id_); + ->notification_message_filter() + ->DidCloseNotification(notification_id_); } void PageNotificationDelegate::NotificationClick() {
diff --git a/content/browser/notifications/platform_notification_context_impl.cc b/content/browser/notifications/platform_notification_context_impl.cc index c2ce26d3..99c9591c 100644 --- a/content/browser/notifications/platform_notification_context_impl.cc +++ b/content/browser/notifications/platform_notification_context_impl.cc
@@ -72,8 +72,7 @@ } BrowserThread::PostTask( - BrowserThread::IO, - FROM_HERE, + BrowserThread::IO, FROM_HERE, base::Bind(&PlatformNotificationContextImpl::InitializeOnIO, this)); } @@ -88,8 +87,7 @@ void PlatformNotificationContextImpl::Shutdown() { DCHECK_CURRENTLY_ON(BrowserThread::UI); BrowserThread::PostTask( - BrowserThread::IO, - FROM_HERE, + BrowserThread::IO, FROM_HERE, base::Bind(&PlatformNotificationContextImpl::ShutdownOnIO, this)); } @@ -107,9 +105,9 @@ const ReadResultCallback& callback) { DCHECK_CURRENTLY_ON(BrowserThread::IO); LazyInitialize( - base::Bind(&PlatformNotificationContextImpl::DoReadNotificationData, - this, notification_id, origin, callback), - base::Bind(callback, false /* success */, NotificationDatabaseData())); + base::Bind(&PlatformNotificationContextImpl::DoReadNotificationData, this, + notification_id, origin, callback), + base::Bind(callback, false /* success */, NotificationDatabaseData())); } void PlatformNotificationContextImpl::DoReadNotificationData( @@ -120,19 +118,15 @@ NotificationDatabaseData database_data; NotificationDatabase::Status status = - database_->ReadNotificationData(notification_id, - origin, - &database_data); + database_->ReadNotificationData(notification_id, origin, &database_data); - UMA_HISTOGRAM_ENUMERATION("Notifications.Database.ReadResult", - status, NotificationDatabase::STATUS_COUNT); + UMA_HISTOGRAM_ENUMERATION("Notifications.Database.ReadResult", status, + NotificationDatabase::STATUS_COUNT); if (status == NotificationDatabase::STATUS_OK) { - BrowserThread::PostTask(BrowserThread::IO, - FROM_HERE, - base::Bind(callback, - true /* success */, - database_data)); + BrowserThread::PostTask( + BrowserThread::IO, FROM_HERE, + base::Bind(callback, true /* success */, database_data)); return; } @@ -141,31 +135,29 @@ DestroyDatabase(); BrowserThread::PostTask( - BrowserThread::IO, - FROM_HERE, + BrowserThread::IO, FROM_HERE, base::Bind(callback, false /* success */, NotificationDatabaseData())); } void PlatformNotificationContextImpl:: ReadAllNotificationDataForServiceWorkerRegistration( - const GURL& origin, - int64_t service_worker_registration_id, - const ReadAllResultCallback& callback) { + const GURL& origin, + int64_t service_worker_registration_id, + const ReadAllResultCallback& callback) { DCHECK_CURRENTLY_ON(BrowserThread::IO); LazyInitialize( - base::Bind(&PlatformNotificationContextImpl:: - DoReadAllNotificationDataForServiceWorkerRegistration, - this, origin, service_worker_registration_id, callback), - base::Bind(callback, - false /* success */, - std::vector<NotificationDatabaseData>())); + base::Bind(&PlatformNotificationContextImpl:: + DoReadAllNotificationDataForServiceWorkerRegistration, + this, origin, service_worker_registration_id, callback), + base::Bind(callback, false /* success */, + std::vector<NotificationDatabaseData>())); } void PlatformNotificationContextImpl:: DoReadAllNotificationDataForServiceWorkerRegistration( - const GURL& origin, - int64_t service_worker_registration_id, - const ReadAllResultCallback& callback) { + const GURL& origin, + int64_t service_worker_registration_id, + const ReadAllResultCallback& callback) { DCHECK(task_runner_->RunsTasksOnCurrentThread()); std::vector<NotificationDatabaseData> notification_datas; @@ -178,11 +170,9 @@ status, NotificationDatabase::STATUS_COUNT); if (status == NotificationDatabase::STATUS_OK) { - BrowserThread::PostTask(BrowserThread::IO, - FROM_HERE, - base::Bind(callback, - true /* success */, - notification_datas)); + BrowserThread::PostTask( + BrowserThread::IO, FROM_HERE, + base::Bind(callback, true /* success */, notification_datas)); return; } @@ -190,12 +180,9 @@ if (status == NotificationDatabase::STATUS_ERROR_CORRUPTED) DestroyDatabase(); - BrowserThread::PostTask( - BrowserThread::IO, - FROM_HERE, - base::Bind(callback, - false /* success */, - std::vector<NotificationDatabaseData>())); + BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, + base::Bind(callback, false /* success */, + std::vector<NotificationDatabaseData>())); } void PlatformNotificationContextImpl::WriteNotificationData( @@ -204,9 +191,9 @@ const WriteResultCallback& callback) { DCHECK_CURRENTLY_ON(BrowserThread::IO); LazyInitialize( - base::Bind(&PlatformNotificationContextImpl::DoWriteNotificationData, - this, origin, database_data, callback), - base::Bind(callback, false /* success */, 0 /* notification_id */)); + base::Bind(&PlatformNotificationContextImpl::DoWriteNotificationData, + this, origin, database_data, callback), + base::Bind(callback, false /* success */, 0 /* notification_id */)); } void PlatformNotificationContextImpl::DoWriteNotificationData( @@ -217,20 +204,16 @@ int64_t notification_id = 0; NotificationDatabase::Status status = - database_->WriteNotificationData(origin, - database_data, - ¬ification_id); + database_->WriteNotificationData(origin, database_data, ¬ification_id); - UMA_HISTOGRAM_ENUMERATION("Notifications.Database.WriteResult", - status, NotificationDatabase::STATUS_COUNT); + UMA_HISTOGRAM_ENUMERATION("Notifications.Database.WriteResult", status, + NotificationDatabase::STATUS_COUNT); if (status == NotificationDatabase::STATUS_OK) { DCHECK_GT(notification_id, 0); - BrowserThread::PostTask(BrowserThread::IO, - FROM_HERE, - base::Bind(callback, - true /* success */, - notification_id)); + BrowserThread::PostTask( + BrowserThread::IO, FROM_HERE, + base::Bind(callback, true /* success */, notification_id)); return; } @@ -239,8 +222,7 @@ DestroyDatabase(); BrowserThread::PostTask( - BrowserThread::IO, - FROM_HERE, + BrowserThread::IO, FROM_HERE, base::Bind(callback, false /* success */, 0 /* notification_id */)); } @@ -250,9 +232,9 @@ const DeleteResultCallback& callback) { DCHECK_CURRENTLY_ON(BrowserThread::IO); LazyInitialize( - base::Bind(&PlatformNotificationContextImpl::DoDeleteNotificationData, - this, notification_id, origin, callback), - base::Bind(callback, false /* success */)); + base::Bind(&PlatformNotificationContextImpl::DoDeleteNotificationData, + this, notification_id, origin, callback), + base::Bind(callback, false /* success */)); } void PlatformNotificationContextImpl::DoDeleteNotificationData( @@ -264,8 +246,8 @@ NotificationDatabase::Status status = database_->DeleteNotificationData(notification_id, origin); - UMA_HISTOGRAM_ENUMERATION("Notifications.Database.DeleteResult", - status, NotificationDatabase::STATUS_COUNT); + UMA_HISTOGRAM_ENUMERATION("Notifications.Database.DeleteResult", status, + NotificationDatabase::STATUS_COUNT); bool success = status == NotificationDatabase::STATUS_OK; @@ -277,8 +259,7 @@ success = true; } - BrowserThread::PostTask(BrowserThread::IO, - FROM_HERE, + BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, base::Bind(callback, success)); } @@ -302,11 +283,11 @@ std::set<int64_t> deleted_notifications_set; NotificationDatabase::Status status = database_->DeleteAllNotificationDataForServiceWorkerRegistration( - origin, service_worker_registration_id, &deleted_notifications_set); + origin, service_worker_registration_id, &deleted_notifications_set); UMA_HISTOGRAM_ENUMERATION( - "Notifications.Database.DeleteServiceWorkerRegistrationResult", - status, NotificationDatabase::STATUS_COUNT); + "Notifications.Database.DeleteServiceWorkerRegistrationResult", status, + NotificationDatabase::STATUS_COUNT); // Blow away the database if a corruption error occurred during the deletion. if (status == NotificationDatabase::STATUS_ERROR_CORRUPTED) @@ -319,8 +300,9 @@ void PlatformNotificationContextImpl::OnStorageWiped() { DCHECK_CURRENTLY_ON(BrowserThread::IO); LazyInitialize( - base::Bind(base::IgnoreResult( - &PlatformNotificationContextImpl::DestroyDatabase), this), + base::Bind( + base::IgnoreResult(&PlatformNotificationContextImpl::DestroyDatabase), + this), base::Bind(&DoNothing)); } @@ -337,9 +319,8 @@ } task_runner_->PostTask( - FROM_HERE, - base::Bind(&PlatformNotificationContextImpl::OpenDatabase, - this, success_closure, failure_closure)); + FROM_HERE, base::Bind(&PlatformNotificationContextImpl::OpenDatabase, + this, success_closure, failure_closure)); } void PlatformNotificationContextImpl::OpenDatabase( @@ -356,8 +337,8 @@ NotificationDatabase::Status status = database_->Open(true /* create_if_missing */); - UMA_HISTOGRAM_ENUMERATION("Notifications.Database.OpenResult", - status, NotificationDatabase::STATUS_COUNT); + UMA_HISTOGRAM_ENUMERATION("Notifications.Database.OpenResult", status, + NotificationDatabase::STATUS_COUNT); // TODO(peter): Do finer-grained synchronization here. if (prune_database_on_open_) { @@ -379,8 +360,8 @@ status = database_->Open(true /* create_if_missing */); UMA_HISTOGRAM_ENUMERATION( - "Notifications.Database.OpenAfterCorruptionResult", - status, NotificationDatabase::STATUS_COUNT); + "Notifications.Database.OpenAfterCorruptionResult", status, + NotificationDatabase::STATUS_COUNT); } } @@ -399,8 +380,8 @@ DCHECK(database_); NotificationDatabase::Status status = database_->Destroy(); - UMA_HISTOGRAM_ENUMERATION("Notifications.Database.DestroyResult", - status, NotificationDatabase::STATUS_COUNT); + UMA_HISTOGRAM_ENUMERATION("Notifications.Database.DestroyResult", status, + NotificationDatabase::STATUS_COUNT); database_.reset();
diff --git a/content/browser/notifications/platform_notification_context_unittest.cc b/content/browser/notifications/platform_notification_context_unittest.cc index 4560f7d..b6533d52 100644 --- a/content/browser/notifications/platform_notification_context_unittest.cc +++ b/content/browser/notifications/platform_notification_context_unittest.cc
@@ -28,12 +28,11 @@ class PlatformNotificationContextTest : public ::testing::Test { public: PlatformNotificationContextTest() - : thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP), - success_(false) {} + : thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP), success_(false) {} // Callback to provide when reading a single notification from the database. - void DidReadNotificationData( - bool success, const NotificationDatabaseData& database_data) { + void DidReadNotificationData(bool success, + const NotificationDatabaseData& database_data) { success_ = success; database_data_ = database_data; } @@ -45,9 +44,7 @@ } // Callback to provide when deleting notification data from the database. - void DidDeleteNotificationData(bool success) { - success_ = success; - } + void DidDeleteNotificationData(bool success) { success_ = success; } // Callback to provide when registering a Service Worker with a Service // Worker Context. Will write the registration id to |store_registration_id|. @@ -88,8 +85,7 @@ // current message loop proxy will be used as the task runner. PlatformNotificationContextImpl* CreatePlatformNotificationContext() { PlatformNotificationContextImpl* context = - new PlatformNotificationContextImpl(base::FilePath(), - &browser_context_, + new PlatformNotificationContextImpl(base::FilePath(), &browser_context_, nullptr); context->Initialize(); @@ -132,8 +128,7 @@ CreatePlatformNotificationContext(); context->ReadNotificationData( - 42 /* notification_id */, - GURL("https://example.com"), + 42 /* notification_id */, GURL("https://example.com"), base::Bind(&PlatformNotificationContextTest::DidReadNotificationData, base::Unretained(this))); @@ -152,8 +147,7 @@ notification_database_data.origin = origin; context->WriteNotificationData( - origin, - notification_database_data, + origin, notification_database_data, base::Bind(&PlatformNotificationContextTest::DidWriteNotificationData, base::Unretained(this))); @@ -164,8 +158,7 @@ EXPECT_GT(notification_id(), 0); context->ReadNotificationData( - notification_id(), - origin, + notification_id(), origin, base::Bind(&PlatformNotificationContextTest::DidReadNotificationData, base::Unretained(this))); @@ -183,8 +176,7 @@ CreatePlatformNotificationContext(); context->DeleteNotificationData( - 42 /* notification_id */, - GURL("https://example.com"), + 42 /* notification_id */, GURL("https://example.com"), base::Bind(&PlatformNotificationContextTest::DidDeleteNotificationData, base::Unretained(this))); @@ -204,8 +196,7 @@ NotificationDatabaseData notification_database_data; context->WriteNotificationData( - origin, - notification_database_data, + origin, notification_database_data, base::Bind(&PlatformNotificationContextTest::DidWriteNotificationData, base::Unretained(this))); @@ -216,8 +207,7 @@ EXPECT_GT(notification_id(), 0); context->DeleteNotificationData( - notification_id(), - origin, + notification_id(), origin, base::Bind(&PlatformNotificationContextTest::DidDeleteNotificationData, base::Unretained(this))); @@ -227,8 +217,7 @@ ASSERT_TRUE(success()); context->ReadNotificationData( - notification_id(), - origin, + notification_id(), origin, base::Bind(&PlatformNotificationContextTest::DidReadNotificationData, base::Unretained(this))); @@ -247,8 +236,7 @@ // Worker context wrapper can be passed in. scoped_refptr<PlatformNotificationContextImpl> notification_context( new PlatformNotificationContextImpl( - base::FilePath(), - browser_context(), + base::FilePath(), browser_context(), embedded_worker_test_helper->context_wrapper())); notification_context->Initialize(); @@ -261,9 +249,7 @@ // Register a Service Worker to get a valid registration id. embedded_worker_test_helper->context()->RegisterServiceWorker( - origin, - script_url, - nullptr /* provider_host */, + origin, script_url, nullptr /* provider_host */, base::Bind(&PlatformNotificationContextTest::DidRegisterServiceWorker, base::Unretained(this), &service_worker_registration_id)); @@ -275,8 +261,7 @@ // Create a notification for that Service Worker registration. notification_context->WriteNotificationData( - origin, - notification_database_data, + origin, notification_database_data, base::Bind(&PlatformNotificationContextTest::DidWriteNotificationData, base::Unretained(this))); @@ -298,8 +283,7 @@ // And verify that the associated notification has indeed been dropped. notification_context->ReadNotificationData( - notification_id(), - origin, + notification_id(), origin, base::Bind(&PlatformNotificationContextTest::DidReadNotificationData, base::Unretained(this))); @@ -316,8 +300,7 @@ NotificationDatabaseData notification_database_data; context->WriteNotificationData( - origin, - notification_database_data, + origin, notification_database_data, base::Bind(&PlatformNotificationContextTest::DidWriteNotificationData, base::Unretained(this))); @@ -335,8 +318,7 @@ // exist anymore. Deliberately omit RunUntilIdle(), since this is unlikely to // be the case when OnStorageWiped gets called in production. context->ReadNotificationData( - notification_id(), - origin, + notification_id(), origin, base::Bind(&PlatformNotificationContextTest::DidReadNotificationData, base::Unretained(this))); @@ -353,15 +335,13 @@ // requires the database to be created on the filesystem. scoped_refptr<PlatformNotificationContextImpl> context( new PlatformNotificationContextImpl(database_dir.path(), - browser_context(), - nullptr)); + browser_context(), nullptr)); OverrideTaskRunnerForTesting(context.get()); // Trigger a read-operation to force creating the database. context->ReadNotificationData( - 42 /* notification_id */, - GURL("https://example.com"), + 42 /* notification_id */, GURL("https://example.com"), base::Bind(&PlatformNotificationContextTest::DidReadNotificationData, base::Unretained(this))); @@ -387,11 +367,9 @@ std::vector<NotificationDatabaseData> notification_database_datas; context->ReadAllNotificationDataForServiceWorkerRegistration( - origin, - kFakeServiceWorkerRegistrationId, + origin, kFakeServiceWorkerRegistrationId, base::Bind(&PlatformNotificationContextTest::DidReadAllNotificationDatas, - base::Unretained(this), - ¬ification_database_datas)); + base::Unretained(this), ¬ification_database_datas)); base::RunLoop().RunUntilIdle(); @@ -414,8 +392,7 @@ // test Service Worker Registration id. for (int i = 0; i < 10; ++i) { context->WriteNotificationData( - origin, - notification_database_data, + origin, notification_database_data, base::Bind(&PlatformNotificationContextTest::DidWriteNotificationData, base::Unretained(this))); @@ -428,11 +405,9 @@ // all set with the correct origin and Service Worker Registration id. std::vector<NotificationDatabaseData> notification_database_datas; context->ReadAllNotificationDataForServiceWorkerRegistration( - origin, - kFakeServiceWorkerRegistrationId, + origin, kFakeServiceWorkerRegistrationId, base::Bind(&PlatformNotificationContextTest::DidReadAllNotificationDatas, - base::Unretained(this), - ¬ification_database_datas)); + base::Unretained(this), ¬ification_database_datas)); base::RunLoop().RunUntilIdle();
diff --git a/content/browser/push_messaging/PRESUBMIT.py b/content/browser/push_messaging/PRESUBMIT.py new file mode 100644 index 0000000..aa4ae97d --- /dev/null +++ b/content/browser/push_messaging/PRESUBMIT.py
@@ -0,0 +1,12 @@ +# Copyright 2015 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. + +"""Top-level presubmit script for Push Messaging. + +See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts +for more details about the presubmit API built into depot_tools. +""" + +def CheckChangeOnUpload(input_api, output_api): + return input_api.canned_checks.CheckPatchFormatted(input_api, output_api)
diff --git a/content/browser/push_messaging/push_messaging_message_filter.cc b/content/browser/push_messaging/push_messaging_message_filter.cc index f75619d..95bde6a 100644 --- a/content/browser/push_messaging/push_messaging_message_filter.cc +++ b/content/browser/push_messaging/push_messaging_message_filter.cc
@@ -45,22 +45,19 @@ // https://groups.google.com/a/chromium.org/d/msg/chromium-dev/FNzZRJtN2aw/Aw0CWAXJJ1kJ void RecordRegistrationStatus(PushRegistrationStatus status) { DCHECK_CURRENTLY_ON(BrowserThread::IO); - UMA_HISTOGRAM_ENUMERATION("PushMessaging.RegistrationStatus", - status, + UMA_HISTOGRAM_ENUMERATION("PushMessaging.RegistrationStatus", status, PUSH_REGISTRATION_STATUS_LAST + 1); } void RecordUnregistrationStatus(PushUnregistrationStatus status) { DCHECK_CURRENTLY_ON(BrowserThread::IO); - UMA_HISTOGRAM_ENUMERATION("PushMessaging.UnregistrationStatus", - status, + UMA_HISTOGRAM_ENUMERATION("PushMessaging.UnregistrationStatus", status, PUSH_UNREGISTRATION_STATUS_LAST + 1); } void RecordGetRegistrationStatus(PushGetRegistrationStatus status) { DCHECK_CURRENTLY_ON(BrowserThread::IO); - UMA_HISTOGRAM_ENUMERATION("PushMessaging.GetRegistrationStatus", - status, + UMA_HISTOGRAM_ENUMERATION("PushMessaging.GetRegistrationStatus", status, PUSH_GETREGISTRATION_STATUS_LAST + 1); } @@ -69,10 +66,11 @@ void ForwardPublicEncryptionKeysToIOThreadProxy( const PushMessagingService::PublicKeyCallback& callback, bool success, - const std::vector<uint8_t>& p256dh) { + const std::vector<uint8_t>& p256dh, + const std::vector<uint8_t>& auth) { DCHECK_CURRENTLY_ON(BrowserThread::UI); BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, - base::Bind(callback, success, p256dh)); + base::Bind(callback, success, p256dh, auth)); } // Concatenates the subscription id with the endpoint base to create a new @@ -96,7 +94,6 @@ int render_frame_id; }; - // Inner core of this message filter which lives on the UI thread. class PushMessagingMessageFilter::Core { public: @@ -149,6 +146,7 @@ void DidRegister(const RegisterData& data, const std::string& push_registration_id, const std::vector<uint8_t>& p256dh, + const std::vector<uint8_t>& auth, PushRegistrationStatus status); // Private Unregister methods on UI thread ----------------------------------- @@ -173,13 +171,11 @@ DISALLOW_COPY_AND_ASSIGN(Core); }; - PushMessagingMessageFilter::RegisterData::RegisterData() : request_id(0), service_worker_registration_id(0), user_visible(false), - render_frame_id(ChildProcessHost::kInvalidUniqueID) { -} + render_frame_id(ChildProcessHost::kInvalidUniqueID) {} bool PushMessagingMessageFilter::RegisterData::FromDocument() const { return render_frame_id != ChildProcessHost::kInvalidUniqueID; @@ -210,8 +206,8 @@ // Normally, it would be unsafe to obtain a weak pointer from the UI thread, // but it's ok in the constructor since we can't be destroyed before our // constructor finishes. - ui_core_.reset(new Core(weak_factory_io_to_io_.GetWeakPtr(), - render_process_id)); + ui_core_.reset( + new Core(weak_factory_io_to_io_.GetWeakPtr(), render_process_id)); PushMessagingService* push_service = ui_core_->service(); if (push_service) push_endpoint_base_ = push_service->GetPushEndpoint(); @@ -231,9 +227,8 @@ OnSubscribeFromDocument) IPC_MESSAGE_HANDLER(PushMessagingHostMsg_SubscribeFromWorker, OnSubscribeFromWorker) - IPC_MESSAGE_HANDLER(PushMessagingHostMsg_Unsubscribe, - OnUnsubscribe) - IPC_MESSAGE_HANDLER(PushMessagingHostMsg_GetRegistration, OnGetRegistration) + IPC_MESSAGE_HANDLER(PushMessagingHostMsg_Unsubscribe, OnUnsubscribe) + IPC_MESSAGE_HANDLER(PushMessagingHostMsg_GetSubscription, OnGetSubscription) IPC_MESSAGE_HANDLER(PushMessagingHostMsg_GetPermissionStatus, OnGetPermissionStatus) IPC_MESSAGE_UNHANDLED(handled = false) @@ -264,19 +259,16 @@ service_worker_registration_id); if (!service_worker_registration || !service_worker_registration->active_version()) { - SendRegisterError(data, PUSH_REGISTRATION_STATUS_NO_SERVICE_WORKER); + SendSubscriptionError(data, PUSH_REGISTRATION_STATUS_NO_SERVICE_WORKER); return; } data.requesting_origin = service_worker_registration->pattern().GetOrigin(); service_worker_context_->StoreRegistrationUserData( - service_worker_registration_id, - data.requesting_origin, - kPushSenderIdServiceWorkerKey, - sender_id, + service_worker_registration_id, data.requesting_origin, + kPushSenderIdServiceWorkerKey, sender_id, base::Bind(&PushMessagingMessageFilter::DidPersistSenderId, - weak_factory_io_to_io_.GetWeakPtr(), - data, sender_id)); + weak_factory_io_to_io_.GetWeakPtr(), data, sender_id)); } void PushMessagingMessageFilter::OnSubscribeFromWorker( @@ -293,7 +285,7 @@ service_worker_context_->GetLiveRegistration( service_worker_registration_id); if (!service_worker_registration) { - SendRegisterError(data, PUSH_REGISTRATION_STATUS_NO_SERVICE_WORKER); + SendSubscriptionError(data, PUSH_REGISTRATION_STATUS_NO_SERVICE_WORKER); return; } data.requesting_origin = service_worker_registration->pattern().GetOrigin(); @@ -308,7 +300,7 @@ ServiceWorkerStatusCode service_worker_status) { DCHECK_CURRENTLY_ON(BrowserThread::IO); if (service_worker_status != SERVICE_WORKER_OK) - SendRegisterError(data, PUSH_REGISTRATION_STATUS_STORAGE_ERROR); + SendSubscriptionError(data, PUSH_REGISTRATION_STATUS_STORAGE_ERROR); else CheckForExistingRegistration(data, sender_id); } @@ -318,8 +310,7 @@ const std::string& sender_id) { DCHECK_CURRENTLY_ON(BrowserThread::IO); service_worker_context_->GetRegistrationUserData( - data.service_worker_registration_id, - kPushRegistrationIdServiceWorkerKey, + data.service_worker_registration_id, kPushRegistrationIdServiceWorkerKey, base::Bind(&PushMessagingMessageFilter::DidCheckForExistingRegistration, weak_factory_io_to_io_.GetWeakPtr(), data, sender_id)); } @@ -331,10 +322,9 @@ ServiceWorkerStatusCode service_worker_status) { DCHECK_CURRENTLY_ON(BrowserThread::IO); if (service_worker_status == SERVICE_WORKER_OK) { - auto callback = - base::Bind(&PushMessagingMessageFilter::DidGetEncryptionKeys, - weak_factory_io_to_io_.GetWeakPtr(), data, - push_registration_id); + auto callback = base::Bind( + &PushMessagingMessageFilter::DidGetEncryptionKeys, + weak_factory_io_to_io_.GetWeakPtr(), data, push_registration_id); BrowserThread::PostTask( BrowserThread::UI, FROM_HERE, @@ -351,12 +341,11 @@ if (data.FromDocument()) { BrowserThread::PostTask( BrowserThread::UI, FROM_HERE, - base::Bind(&Core::RegisterOnUI, base::Unretained(ui_core_.get()), - data, sender_id)); + base::Bind(&Core::RegisterOnUI, base::Unretained(ui_core_.get()), data, + sender_id)); } else { service_worker_context_->GetRegistrationUserData( - data.service_worker_registration_id, - kPushSenderIdServiceWorkerKey, + data.service_worker_registration_id, kPushSenderIdServiceWorkerKey, base::Bind(&PushMessagingMessageFilter::DidGetSenderIdFromStorage, weak_factory_io_to_io_.GetWeakPtr(), data)); } @@ -366,15 +355,17 @@ const RegisterData& data, const std::string& push_registration_id, bool success, - const std::vector<uint8_t>& p256dh) { + const std::vector<uint8_t>& p256dh, + const std::vector<uint8_t>& auth) { DCHECK_CURRENTLY_ON(BrowserThread::IO); if (!success) { - SendRegisterError(data, PUSH_REGISTRATION_STATUS_PUBLIC_KEY_UNAVAILABLE); + SendSubscriptionError( + data, PUSH_REGISTRATION_STATUS_PUBLIC_KEY_UNAVAILABLE); return; } - SendRegisterSuccess(data, PUSH_REGISTRATION_STATUS_SUCCESS_FROM_CACHE, - push_registration_id, p256dh); + SendSubscriptionSuccess(data, PUSH_REGISTRATION_STATUS_SUCCESS_FROM_CACHE, + push_registration_id, p256dh, auth); } void PushMessagingMessageFilter::DidGetSenderIdFromStorage( @@ -383,13 +374,13 @@ ServiceWorkerStatusCode service_worker_status) { DCHECK_CURRENTLY_ON(BrowserThread::IO); if (service_worker_status != SERVICE_WORKER_OK) { - SendRegisterError(data, PUSH_REGISTRATION_STATUS_NO_SENDER_ID); + SendSubscriptionError(data, PUSH_REGISTRATION_STATUS_NO_SENDER_ID); return; } BrowserThread::PostTask( BrowserThread::UI, FROM_HERE, - base::Bind(&Core::RegisterOnUI, base::Unretained(ui_core_.get()), - data, sender_id)); + base::Bind(&Core::RegisterOnUI, base::Unretained(ui_core_.get()), data, + sender_id)); } void PushMessagingMessageFilter::Core::RegisterOnUI( @@ -402,7 +393,7 @@ // TODO(johnme): Might be better not to expose the API in this case. BrowserThread::PostTask( BrowserThread::IO, FROM_HERE, - base::Bind(&PushMessagingMessageFilter::SendRegisterError, + base::Bind(&PushMessagingMessageFilter::SendSubscriptionError, io_parent_, data, PUSH_REGISTRATION_STATUS_SERVICE_NOT_AVAILABLE)); } else { @@ -412,9 +403,8 @@ // Throw a permission denied error under the same circumstances. BrowserThread::PostTask( BrowserThread::IO, FROM_HERE, - base::Bind(&PushMessagingMessageFilter::SendRegisterError, - io_parent_, - data, + base::Bind(&PushMessagingMessageFilter::SendSubscriptionError, + io_parent_, data, PUSH_REGISTRATION_STATUS_INCOGNITO_PERMISSION_DENIED)); } else { // Leave the promise hanging forever, to simulate a user ignoring the @@ -452,53 +442,54 @@ const RegisterData& data, const std::string& push_registration_id, const std::vector<uint8_t>& p256dh, + const std::vector<uint8_t>& auth, PushRegistrationStatus status) { DCHECK_CURRENTLY_ON(BrowserThread::UI); if (status == PUSH_REGISTRATION_STATUS_SUCCESS_FROM_PUSH_SERVICE) { BrowserThread::PostTask( BrowserThread::IO, FROM_HERE, base::Bind(&PushMessagingMessageFilter::PersistRegistrationOnIO, - io_parent_, data, push_registration_id, p256dh)); + io_parent_, data, push_registration_id, p256dh, auth)); } else { BrowserThread::PostTask( BrowserThread::IO, FROM_HERE, - base::Bind(&PushMessagingMessageFilter::SendRegisterError, io_parent_, - data, status)); + base::Bind(&PushMessagingMessageFilter::SendSubscriptionError, + io_parent_, data, status)); } } void PushMessagingMessageFilter::PersistRegistrationOnIO( const RegisterData& data, const std::string& push_registration_id, - const std::vector<uint8_t>& p256dh) { + const std::vector<uint8_t>& p256dh, + const std::vector<uint8_t>& auth) { DCHECK_CURRENTLY_ON(BrowserThread::IO); service_worker_context_->StoreRegistrationUserData( - data.service_worker_registration_id, - data.requesting_origin, - kPushRegistrationIdServiceWorkerKey, - push_registration_id, + data.service_worker_registration_id, data.requesting_origin, + kPushRegistrationIdServiceWorkerKey, push_registration_id, base::Bind(&PushMessagingMessageFilter::DidPersistRegistrationOnIO, - weak_factory_io_to_io_.GetWeakPtr(), - data, push_registration_id, p256dh)); + weak_factory_io_to_io_.GetWeakPtr(), data, + push_registration_id, p256dh, auth)); } void PushMessagingMessageFilter::DidPersistRegistrationOnIO( const RegisterData& data, const std::string& push_registration_id, const std::vector<uint8_t>& p256dh, + const std::vector<uint8_t>& auth, ServiceWorkerStatusCode service_worker_status) { DCHECK_CURRENTLY_ON(BrowserThread::IO); if (service_worker_status == SERVICE_WORKER_OK) { - SendRegisterSuccess(data, - PUSH_REGISTRATION_STATUS_SUCCESS_FROM_PUSH_SERVICE, - push_registration_id, p256dh); + SendSubscriptionSuccess(data, + PUSH_REGISTRATION_STATUS_SUCCESS_FROM_PUSH_SERVICE, + push_registration_id, p256dh, auth); } else { // TODO(johnme): Unregister, so PushMessagingServiceImpl can decrease count. - SendRegisterError(data, PUSH_REGISTRATION_STATUS_STORAGE_ERROR); + SendSubscriptionError(data, PUSH_REGISTRATION_STATUS_STORAGE_ERROR); } } -void PushMessagingMessageFilter::SendRegisterError( +void PushMessagingMessageFilter::SendSubscriptionError( const RegisterData& data, PushRegistrationStatus status) { // Only called from IO thread, but would be safe to call from UI thread. DCHECK_CURRENTLY_ON(BrowserThread::IO); @@ -506,37 +497,37 @@ Send(new PushMessagingMsg_SubscribeFromDocumentError( data.render_frame_id, data.request_id, status)); } else { - Send(new PushMessagingMsg_SubscribeFromWorkerError( - data.request_id, status)); + Send( + new PushMessagingMsg_SubscribeFromWorkerError(data.request_id, status)); } RecordRegistrationStatus(status); } -void PushMessagingMessageFilter::SendRegisterSuccess( +void PushMessagingMessageFilter::SendSubscriptionSuccess( const RegisterData& data, PushRegistrationStatus status, - const std::string& push_registration_id, - const std::vector<uint8_t>& p256dh) { + const std::string& push_subscription_id, + const std::vector<uint8_t>& p256dh, + const std::vector<uint8_t>& auth) { // Only called from IO thread, but would be safe to call from UI thread. DCHECK_CURRENTLY_ON(BrowserThread::IO); if (push_endpoint_base_.is_empty()) { // This shouldn't be possible in incognito mode, since we've already checked // that we have an existing registration. Hence it's ok to throw an error. DCHECK(!ui_core_->is_incognito()); - SendRegisterError(data, PUSH_REGISTRATION_STATUS_SERVICE_NOT_AVAILABLE); + SendSubscriptionError(data, PUSH_REGISTRATION_STATUS_SERVICE_NOT_AVAILABLE); return; } if (data.FromDocument()) { Send(new PushMessagingMsg_SubscribeFromDocumentSuccess( - data.render_frame_id, - data.request_id, - CreatePushEndpoint(push_endpoint_base_, push_registration_id), - p256dh)); + data.render_frame_id, data.request_id, + CreatePushEndpoint(push_endpoint_base_, push_subscription_id), p256dh, + auth)); } else { Send(new PushMessagingMsg_SubscribeFromWorkerSuccess( data.request_id, - CreatePushEndpoint(push_endpoint_base_, push_registration_id), - p256dh)); + CreatePushEndpoint(push_endpoint_base_, push_subscription_id), p256dh, + auth)); } RecordRegistrationStatus(status); } @@ -547,7 +538,7 @@ void PushMessagingMessageFilter::OnUnsubscribe( int request_id, int64_t service_worker_registration_id) { - DCHECK_CURRENTLY_ON(BrowserThread::IO); + DCHECK_CURRENTLY_ON(BrowserThread::IO); ServiceWorkerRegistration* service_worker_registration = service_worker_context_->GetLiveRegistration( service_worker_registration_id); @@ -557,8 +548,7 @@ } service_worker_context_->GetRegistrationUserData( - service_worker_registration_id, - kPushRegistrationIdServiceWorkerKey, + service_worker_registration_id, kPushRegistrationIdServiceWorkerKey, base::Bind(&PushMessagingMessageFilter:: UnsubscribeHavingGottenPushSubscriptionId, weak_factory_io_to_io_.GetWeakPtr(), request_id, @@ -576,21 +566,16 @@ if (service_worker_status == SERVICE_WORKER_OK) { service_worker_context_->GetRegistrationUserData( - service_worker_registration_id, - kPushSenderIdServiceWorkerKey, - base::Bind( - &PushMessagingMessageFilter::UnsubscribeHavingGottenSenderId, - weak_factory_io_to_io_.GetWeakPtr(), - request_id, - service_worker_registration_id, - requesting_origin)); + service_worker_registration_id, kPushSenderIdServiceWorkerKey, + base::Bind(&PushMessagingMessageFilter::UnsubscribeHavingGottenSenderId, + weak_factory_io_to_io_.GetWeakPtr(), request_id, + service_worker_registration_id, requesting_origin)); } else { // Errors are handled the same, whether we were trying to get the // push_subscription_id or the sender_id. - UnsubscribeHavingGottenSenderId(request_id, service_worker_registration_id, - requesting_origin, - std::string() /* sender_id */, - service_worker_status); + UnsubscribeHavingGottenSenderId( + request_id, service_worker_registration_id, requesting_origin, + std::string() /* sender_id */, service_worker_status); } } @@ -618,8 +603,7 @@ PUSH_UNREGISTRATION_STATUS_SUCCESS_WAS_NOT_REGISTERED); break; case SERVICE_WORKER_ERROR_FAILED: - DidUnregister(request_id, - PUSH_UNREGISTRATION_STATUS_STORAGE_ERROR); + DidUnregister(request_id, PUSH_UNREGISTRATION_STATUS_STORAGE_ERROR); break; case SERVICE_WORKER_ERROR_ABORT: case SERVICE_WORKER_ERROR_START_WORKER_FAILED: @@ -667,8 +651,8 @@ push_service->Unsubscribe( requesting_origin, service_worker_registration_id, sender_id, base::Bind(&Core::DidUnregisterFromService, - weak_factory_ui_to_ui_.GetWeakPtr(), - request_id, service_worker_registration_id)); + weak_factory_ui_to_ui_.GetWeakPtr(), request_id, + service_worker_registration_id)); } void PushMessagingMessageFilter::Core::DidUnregisterFromService( @@ -704,11 +688,10 @@ DCHECK_CURRENTLY_ON(BrowserThread::IO); service_worker_context_->ClearRegistrationUserData( - service_worker_registration_id, - kPushRegistrationIdServiceWorkerKey, + service_worker_registration_id, kPushRegistrationIdServiceWorkerKey, base::Bind(&PushMessagingMessageFilter::DidClearRegistrationData, - weak_factory_io_to_io_.GetWeakPtr(), - request_id, unregistration_status)); + weak_factory_io_to_io_.GetWeakPtr(), request_id, + unregistration_status)); } void PushMessagingMessageFilter::DidClearRegistrationData( @@ -755,27 +738,26 @@ RecordUnregistrationStatus(unregistration_status); } -// GetRegistration methods on both IO and UI threads, merged in order of use +// GetSubscription methods on both IO and UI threads, merged in order of use // from PushMessagingMessageFilter and Core. // ----------------------------------------------------------------------------- -void PushMessagingMessageFilter::OnGetRegistration( +void PushMessagingMessageFilter::OnGetSubscription( int request_id, int64_t service_worker_registration_id) { DCHECK_CURRENTLY_ON(BrowserThread::IO); // TODO(johnme): Validate arguments? service_worker_context_->GetRegistrationUserData( - service_worker_registration_id, - kPushRegistrationIdServiceWorkerKey, - base::Bind(&PushMessagingMessageFilter::DidGetRegistration, + service_worker_registration_id, kPushRegistrationIdServiceWorkerKey, + base::Bind(&PushMessagingMessageFilter::DidGetSubscription, weak_factory_io_to_io_.GetWeakPtr(), request_id, service_worker_registration_id)); } -void PushMessagingMessageFilter::DidGetRegistration( +void PushMessagingMessageFilter::DidGetSubscription( int request_id, int64_t service_worker_registration_id, - const std::string& push_registration_id, + const std::string& push_subscription_id, ServiceWorkerStatusCode service_worker_status) { DCHECK_CURRENTLY_ON(BrowserThread::IO); PushGetRegistrationStatus get_status = @@ -786,18 +768,21 @@ // Return not found in incognito mode, so websites can't detect it. get_status = ui_core_->is_incognito() - ? PUSH_GETREGISTRATION_STATUS_INCOGNITO_REGISTRATION_NOT_FOUND - : PUSH_GETREGISTRATION_STATUS_SERVICE_NOT_AVAILABLE; + ? PUSH_GETREGISTRATION_STATUS_INCOGNITO_REGISTRATION_NOT_FOUND + : PUSH_GETREGISTRATION_STATUS_SERVICE_NOT_AVAILABLE; break; } - const GURL origin = service_worker_context_->GetLiveRegistration( - service_worker_registration_id)->pattern().GetOrigin(); + ServiceWorkerRegistration* registration = + service_worker_context_->GetLiveRegistration( + service_worker_registration_id); + + const GURL origin = registration->pattern().GetOrigin(); const GURL endpoint = - CreatePushEndpoint(push_endpoint_base_, push_registration_id); + CreatePushEndpoint(push_endpoint_base_, push_subscription_id); auto callback = - base::Bind(&PushMessagingMessageFilter::DidGetRegistrationKeys, + base::Bind(&PushMessagingMessageFilter::DidGetSubscriptionKeys, weak_factory_io_to_io_.GetWeakPtr(), request_id, endpoint); BrowserThread::PostTask( @@ -839,28 +824,29 @@ break; } } - Send(new PushMessagingMsg_GetRegistrationError(request_id, get_status)); + Send(new PushMessagingMsg_GetSubscriptionError(request_id, get_status)); RecordGetRegistrationStatus(get_status); } -void PushMessagingMessageFilter::DidGetRegistrationKeys( +void PushMessagingMessageFilter::DidGetSubscriptionKeys( int request_id, const GURL& endpoint, bool success, - const std::vector<uint8_t>& p256dh) { + const std::vector<uint8_t>& p256dh, + const std::vector<uint8_t>& auth) { DCHECK_CURRENTLY_ON(BrowserThread::IO); if (!success) { PushGetRegistrationStatus status = PUSH_GETREGISTRATION_STATUS_PUBLIC_KEY_UNAVAILABLE; - Send(new PushMessagingMsg_GetRegistrationError(request_id, status)); + Send(new PushMessagingMsg_GetSubscriptionError(request_id, status)); RecordGetRegistrationStatus(status); return; } - Send(new PushMessagingMsg_GetRegistrationSuccess(request_id, endpoint, - p256dh)); + Send(new PushMessagingMsg_GetSubscriptionSuccess(request_id, endpoint, + p256dh, auth)); RecordGetRegistrationStatus(PUSH_GETREGISTRATION_STATUS_SUCCESS); } @@ -903,9 +889,8 @@ return; } GURL embedding_origin = requesting_origin; - permission_status = push_service->GetPermissionStatus(requesting_origin, - embedding_origin, - user_visible); + permission_status = push_service->GetPermissionStatus( + requesting_origin, embedding_origin, user_visible); } else if (is_incognito()) { // Return prompt, so the website can't detect incognito mode. permission_status = blink::WebPushPermissionStatusPrompt; @@ -936,10 +921,10 @@ return; } - BrowserThread::PostTask( - BrowserThread::IO, FROM_HERE, - base::Bind(io_thread_callback, false /* success */, - std::vector<uint8_t>())); + BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, + base::Bind(io_thread_callback, false /* success */, + std::vector<uint8_t>() /* public_key */, + std::vector<uint8_t>() /* auth */)); } void PushMessagingMessageFilter::Core::Send(IPC::Message* message) { @@ -958,8 +943,8 @@ RenderProcessHost* process_host = RenderProcessHost::FromID(render_process_id_); return process_host - ? process_host->GetBrowserContext()->GetPushMessagingService() - : nullptr; + ? process_host->GetBrowserContext()->GetPushMessagingService() + : nullptr; } } // namespace content
diff --git a/content/browser/push_messaging/push_messaging_message_filter.h b/content/browser/push_messaging/push_messaging_message_filter.h index 737baf2..674ec09 100644 --- a/content/browser/push_messaging/push_messaging_message_filter.h +++ b/content/browser/push_messaging/push_messaging_message_filter.h
@@ -62,9 +62,8 @@ ServiceWorkerStatusCode service_worker_status); // sender_id is ignored if data.FromDocument() is false. - void CheckForExistingRegistration( - const RegisterData& data, - const std::string& sender_id); + void CheckForExistingRegistration(const RegisterData& data, + const std::string& sender_id); // sender_id is ignored if data.FromDocument() is false. void DidCheckForExistingRegistration( @@ -76,7 +75,8 @@ void DidGetEncryptionKeys(const RegisterData& data, const std::string& push_registration_id, bool success, - const std::vector<uint8_t>& p256dh); + const std::vector<uint8_t>& p256dh, + const std::vector<uint8_t>& auth); void DidGetSenderIdFromStorage(const RegisterData& data, const std::string& sender_id, @@ -85,22 +85,25 @@ // Called via PostTask from UI thread. void PersistRegistrationOnIO(const RegisterData& data, const std::string& push_registration_id, - const std::vector<uint8_t>& p256dh); + const std::vector<uint8_t>& p256dh, + const std::vector<uint8_t>& auth); void DidPersistRegistrationOnIO( const RegisterData& data, const std::string& push_registration_id, const std::vector<uint8_t>& p256dh, + const std::vector<uint8_t>& auth, ServiceWorkerStatusCode service_worker_status); // Called both from IO thread, and via PostTask from UI thread. - void SendRegisterError(const RegisterData& data, - PushRegistrationStatus status); + void SendSubscriptionError(const RegisterData& data, + PushRegistrationStatus status); // Called both from IO thread, and via PostTask from UI thread. - void SendRegisterSuccess(const RegisterData& data, - PushRegistrationStatus status, - const std::string& push_registration_id, - const std::vector<uint8_t>& p256dh); + void SendSubscriptionSuccess(const RegisterData& data, + PushRegistrationStatus status, + const std::string& push_subscription_id, + const std::vector<uint8_t>& p256dh, + const std::vector<uint8_t>& auth); // Unsubscribe methods on IO thread ------------------------------------------ @@ -133,27 +136,28 @@ void DidUnregister(int request_id, PushUnregistrationStatus unregistration_status); - // GetRegistration methods on IO thread -------------------------------------- + // GetSubscription methods on IO thread -------------------------------------- - void OnGetRegistration(int request_id, + void OnGetSubscription(int request_id, int64_t service_worker_registration_id); - void DidGetRegistration(int request_id, + void DidGetSubscription(int request_id, int64_t service_worker_registration_id, - const std::string& push_registration_id, + const std::string& push_subscription_id, ServiceWorkerStatusCode status); + void DidGetSubscriptionKeys(int request_id, + const GURL& endpoint, + bool success, + const std::vector<uint8_t>& p256dh, + const std::vector<uint8_t>& auth); + // GetPermission methods on IO thread ---------------------------------------- void OnGetPermissionStatus(int request_id, int64_t service_worker_registration_id, bool user_visible); - void DidGetRegistrationKeys(int request_id, - const GURL& endpoint, - bool success, - const std::vector<uint8_t>& p256dh); - // Helper methods on IO thread ----------------------------------------------- // Called via PostTask from UI thread.
diff --git a/content/browser/push_messaging/push_messaging_router.cc b/content/browser/push_messaging/push_messaging_router.cc index d9b38186..35147cf 100644 --- a/content/browser/push_messaging/push_messaging_router.cc +++ b/content/browser/push_messaging/push_messaging_router.cc
@@ -43,13 +43,9 @@ static_cast<ServiceWorkerContextWrapper*>( partition->GetServiceWorkerContext()); BrowserThread::PostTask( - BrowserThread::IO, - FROM_HERE, - base::Bind(&PushMessagingRouter::FindServiceWorkerRegistration, - origin, - service_worker_registration_id, - data, - deliver_message_callback, + BrowserThread::IO, FROM_HERE, + base::Bind(&PushMessagingRouter::FindServiceWorkerRegistration, origin, + service_worker_registration_id, data, deliver_message_callback, service_worker_context)); } @@ -64,11 +60,9 @@ // Try to acquire the registration from storage. If it's already live we'll // receive it right away. If not, it will be revived from storage. service_worker_context->FindReadyRegistrationForId( - service_worker_registration_id, - origin, + service_worker_registration_id, origin, base::Bind(&PushMessagingRouter::FindServiceWorkerRegistrationCallback, - data, - deliver_message_callback)); + data, deliver_message_callback)); } // static
diff --git a/content/browser/push_messaging/push_messaging_router.h b/content/browser/push_messaging/push_messaging_router.h index d9f25cc..aeaf3e49 100644 --- a/content/browser/push_messaging/push_messaging_router.h +++ b/content/browser/push_messaging/push_messaging_router.h
@@ -19,8 +19,7 @@ class PushMessagingRouter { public: - typedef base::Callback<void(PushDeliveryStatus)> - DeliverMessageCallback; + typedef base::Callback<void(PushDeliveryStatus)> DeliverMessageCallback; // Delivers a push message with |data| to the Service Worker identified by // |origin| and |service_worker_registration_id|. Must be called on the UI
diff --git a/content/browser/renderer_host/input/synthetic_gesture.cc b/content/browser/renderer_host/input/synthetic_gesture.cc index 2e25288..ebe8712 100644 --- a/content/browser/renderer_host/input/synthetic_gesture.cc +++ b/content/browser/renderer_host/input/synthetic_gesture.cc
@@ -47,10 +47,4 @@ return scoped_ptr<SyntheticGesture>(); } -// static -double SyntheticGesture::ConvertTimestampToSeconds( - const base::TimeTicks& timestamp) { - return (timestamp - base::TimeTicks()).InSecondsF(); -} - } // namespace content
diff --git a/content/browser/renderer_host/input/synthetic_gesture.h b/content/browser/renderer_host/input/synthetic_gesture.h index 1d605ff9..f90b72c4 100644 --- a/content/browser/renderer_host/input/synthetic_gesture.h +++ b/content/browser/renderer_host/input/synthetic_gesture.h
@@ -40,6 +40,8 @@ GESTURE_RESULT_MAX = GESTURE_SOURCE_TYPE_NOT_IMPLEMENTED }; + enum PointerActionType { PRESS, MOVE, RELEASE }; + // Update the state of the gesture and forward the appropriate events to the // platform. This function is called repeatedly by the synthetic gesture // controller until it stops returning GESTURE_RUNNING. @@ -47,8 +49,6 @@ const base::TimeTicks& timestamp, SyntheticGestureTarget* target) = 0; protected: - static double ConvertTimestampToSeconds(const base::TimeTicks& timestamp); - DISALLOW_COPY_AND_ASSIGN(SyntheticGesture); };
diff --git a/content/browser/renderer_host/input/synthetic_gesture_controller_unittest.cc b/content/browser/renderer_host/input/synthetic_gesture_controller_unittest.cc index 44205c0a..1b04734e 100644 --- a/content/browser/renderer_host/input/synthetic_gesture_controller_unittest.cc +++ b/content/browser/renderer_host/input/synthetic_gesture_controller_unittest.cc
@@ -9,10 +9,12 @@ #include "content/browser/renderer_host/input/synthetic_gesture_controller.h" #include "content/browser/renderer_host/input/synthetic_gesture_target.h" #include "content/browser/renderer_host/input/synthetic_pinch_gesture.h" +#include "content/browser/renderer_host/input/synthetic_pointer_gesture.h" #include "content/browser/renderer_host/input/synthetic_smooth_drag_gesture.h" #include "content/browser/renderer_host/input/synthetic_smooth_move_gesture.h" #include "content/browser/renderer_host/input/synthetic_smooth_scroll_gesture.h" #include "content/browser/renderer_host/input/synthetic_tap_gesture.h" +#include "content/browser/renderer_host/input/synthetic_touch_pointer.h" #include "content/browser/renderer_host/input/synthetic_touchpad_pinch_gesture.h" #include "content/browser/renderer_host/input/synthetic_touchscreen_pinch_gesture.h" #include "content/browser/renderer_host/render_widget_host_delegate.h" @@ -34,6 +36,7 @@ using blink::WebMouseEvent; using blink::WebMouseWheelEvent; using blink::WebTouchEvent; +using blink::WebTouchPoint; namespace content { @@ -43,6 +46,7 @@ const int kPointerAssumedStoppedTimeMs = 43; const float kTouchSlopInDips = 7.0f; const float kMinScalingSpanInDips = 27.5f; +const int kTouchPointersLength = 16; enum TouchGestureType { TOUCH_SCROLL, TOUCH_DRAG }; @@ -463,6 +467,44 @@ } }; +class MockSyntheticPointerGestureTarget : public MockSyntheticGestureTarget { + public: + MockSyntheticPointerGestureTarget() {} + ~MockSyntheticPointerGestureTarget() override {} + + gfx::PointF positions(int index) const { return positions_[index]; } + int indexes(int index) const { return indexes_[index]; } + WebTouchPoint::State states(int index) { return states_[index]; } + unsigned touch_length() const { return touch_length_; } + WebInputEvent::Type type() const { return type_; } + + protected: + gfx::PointF positions_[kTouchPointersLength]; + unsigned touch_length_; + int indexes_[kTouchPointersLength]; + WebTouchPoint::State states_[kTouchPointersLength]; + WebInputEvent::Type type_; +}; + +class MockSyntheticPointerTouchTarget + : public MockSyntheticPointerGestureTarget { + public: + MockSyntheticPointerTouchTarget() {} + ~MockSyntheticPointerTouchTarget() override {} + + void DispatchInputEventToPlatform(const WebInputEvent& event) override { + ASSERT_TRUE(WebInputEvent::isTouchEventType(event.type)); + const WebTouchEvent& touch_event = static_cast<const WebTouchEvent&>(event); + type_ = touch_event.type; + for (size_t i = 0; i < touch_event.touchesLength; ++i) { + indexes_[i] = touch_event.touches[i].id; + positions_[i] = gfx::PointF(touch_event.touches[i].position); + states_[i] = touch_event.touches[i].state; + } + touch_length_ = touch_event.touchesLength; + } +}; + class SyntheticGestureControllerTestBase { public: SyntheticGestureControllerTestBase() {} @@ -1420,6 +1462,64 @@ base::TimeDelta::FromMilliseconds(params.duration_ms)); } +TEST_F(SyntheticGestureControllerTest, PointerGestureTouch) { + CreateControllerAndTarget<MockSyntheticPointerTouchTarget>(); + + SyntheticTouchPointer synthetic_pointer; + + gfx::PointF position(54, 89); + scoped_ptr<SyntheticPointerGesture> gesture(new SyntheticPointerGesture( + SyntheticGestureParams::TOUCH_INPUT, SyntheticGesture::PRESS, + &synthetic_pointer, position)); + QueueSyntheticGesture(gesture.Pass()); + FlushInputUntilComplete(); + + MockSyntheticPointerTouchTarget* pointer_touch_target = + static_cast<MockSyntheticPointerTouchTarget*>(target_); + EXPECT_EQ(pointer_touch_target->type(), WebInputEvent::TouchStart); + EXPECT_EQ(pointer_touch_target->positions(0), position); + EXPECT_EQ(pointer_touch_target->states(0), WebTouchPoint::StatePressed); + ASSERT_EQ(pointer_touch_target->touch_length(), 1U); + + position.SetPoint(79, 132); + gesture.reset(new SyntheticPointerGesture(SyntheticGestureParams::TOUCH_INPUT, + SyntheticGesture::PRESS, + &synthetic_pointer, position)); + QueueSyntheticGesture(gesture.Pass()); + FlushInputUntilComplete(); + + pointer_touch_target = static_cast<MockSyntheticPointerTouchTarget*>(target_); + EXPECT_EQ(pointer_touch_target->type(), WebInputEvent::TouchStart); + EXPECT_EQ(pointer_touch_target->indexes(1), 1); + EXPECT_EQ(pointer_touch_target->positions(1), position); + EXPECT_EQ(pointer_touch_target->states(1), WebTouchPoint::StatePressed); + ASSERT_EQ(pointer_touch_target->touch_length(), 2U); + + int index = 1; + position.SetPoint(133, 156); + gesture.reset(new SyntheticPointerGesture( + SyntheticGestureParams::TOUCH_INPUT, SyntheticGesture::MOVE, + &synthetic_pointer, position, index)); + QueueSyntheticGesture(gesture.Pass()); + FlushInputUntilComplete(); + + pointer_touch_target = static_cast<MockSyntheticPointerTouchTarget*>(target_); + EXPECT_EQ(pointer_touch_target->type(), WebInputEvent::TouchMove); + EXPECT_EQ(pointer_touch_target->positions(1), position); + EXPECT_EQ(pointer_touch_target->states(1), WebTouchPoint::StateMoved); + ASSERT_EQ(pointer_touch_target->touch_length(), 2U); + + gesture.reset(new SyntheticPointerGesture( + SyntheticGestureParams::TOUCH_INPUT, SyntheticGesture::RELEASE, + &synthetic_pointer, position, index)); + QueueSyntheticGesture(gesture.Pass()); + FlushInputUntilComplete(); + + pointer_touch_target = static_cast<MockSyntheticPointerTouchTarget*>(target_); + EXPECT_EQ(pointer_touch_target->type(), WebInputEvent::TouchEnd); + EXPECT_EQ(pointer_touch_target->states(1), WebTouchPoint::StateReleased); +} + } // namespace } // namespace content
diff --git a/content/browser/renderer_host/input/synthetic_gesture_target.h b/content/browser/renderer_host/input/synthetic_gesture_target.h index 14724bf..da44ba2 100644 --- a/content/browser/renderer_host/input/synthetic_gesture_target.h +++ b/content/browser/renderer_host/input/synthetic_gesture_target.h
@@ -6,7 +6,6 @@ #define CONTENT_BROWSER_RENDERER_HOST_INPUT_SYNTHETIC_GESTURE_TARGET_H_ #include "base/time/time.h" -#include "content/browser/renderer_host/input/synthetic_gesture.h" #include "content/common/content_export.h" #include "content/common/input/synthetic_gesture_params.h"
diff --git a/content/browser/renderer_host/input/synthetic_mouse_pointer.cc b/content/browser/renderer_host/input/synthetic_mouse_pointer.cc new file mode 100644 index 0000000..042603fe --- /dev/null +++ b/content/browser/renderer_host/input/synthetic_mouse_pointer.cc
@@ -0,0 +1,49 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "content/browser/renderer_host/input/synthetic_mouse_pointer.h" + +#include "content/browser/renderer_host/input/synthetic_gesture_target.h" + +namespace content { + +SyntheticMousePointer::SyntheticMousePointer() {} + +SyntheticMousePointer::~SyntheticMousePointer() {} + +void SyntheticMousePointer::DispatchEvent(SyntheticGestureTarget* target, + const base::TimeTicks& timestamp) { + mouse_event_.timeStampSeconds = ConvertTimestampToSeconds(timestamp); + target->DispatchInputEventToPlatform(mouse_event_); +} + +int SyntheticMousePointer::Press(float x, + float y, + SyntheticGestureTarget* target, + const base::TimeTicks& timestamp) { + mouse_event_ = SyntheticWebMouseEventBuilder::Build( + blink::WebInputEvent::MouseDown, x, y, 0); + mouse_event_.clickCount = 1; + return 0; +} + +void SyntheticMousePointer::Move(int index, + float x, + float y, + SyntheticGestureTarget* target, + const base::TimeTicks& timestamp) { + mouse_event_ = SyntheticWebMouseEventBuilder::Build( + blink::WebInputEvent::MouseMove, x, y, 0); + mouse_event_.button = blink::WebMouseEvent::ButtonLeft; +} + +void SyntheticMousePointer::Release(int index, + SyntheticGestureTarget* target, + const base::TimeTicks& timestamp) { + mouse_event_ = SyntheticWebMouseEventBuilder::Build( + blink::WebInputEvent::MouseUp, mouse_event_.x, mouse_event_.y, 0); + mouse_event_.clickCount = 1; +} + +} // namespace content
diff --git a/content/browser/renderer_host/input/synthetic_mouse_pointer.h b/content/browser/renderer_host/input/synthetic_mouse_pointer.h new file mode 100644 index 0000000..9f806f3b --- /dev/null +++ b/content/browser/renderer_host/input/synthetic_mouse_pointer.h
@@ -0,0 +1,44 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CONTENT_BROWSER_RENDERER_HOST_INPUT_SYNTHETIC_MOUSE_POINTER_H_ +#define CONTENT_BROWSER_RENDERER_HOST_INPUT_SYNTHETIC_MOUSE_POINTER_H_ + +#include "base/macros.h" +#include "content/browser/renderer_host/input/synthetic_pointer.h" +#include "content/common/content_export.h" +#include "content/common/input/synthetic_web_input_event_builders.h" + +namespace content { + +class CONTENT_EXPORT SyntheticMousePointer : public SyntheticPointer { + public: + SyntheticMousePointer(); + ~SyntheticMousePointer() override; + + void DispatchEvent(SyntheticGestureTarget* target, + const base::TimeTicks& timestamp) override; + + int Press(float x, + float y, + SyntheticGestureTarget* target, + const base::TimeTicks& timestamp) override; + void Move(int index, + float x, + float y, + SyntheticGestureTarget* target, + const base::TimeTicks& timestamp) override; + void Release(int index, + SyntheticGestureTarget* target, + const base::TimeTicks& timestamp) override; + + private: + SyntheticGestureParams::GestureSourceType gesture_source_type_; + blink::WebMouseEvent mouse_event_; + DISALLOW_COPY_AND_ASSIGN(SyntheticMousePointer); +}; + +} // namespace content + +#endif // CONTENT_BROWSER_RENDERER_HOST_INPUT_SYNTHETIC_MOUSE_POINTER_H_
diff --git a/content/browser/renderer_host/input/synthetic_pointer.cc b/content/browser/renderer_host/input/synthetic_pointer.cc new file mode 100644 index 0000000..29228fc --- /dev/null +++ b/content/browser/renderer_host/input/synthetic_pointer.cc
@@ -0,0 +1,35 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "content/browser/renderer_host/input/synthetic_pointer.h" + +#include "content/browser/renderer_host/input/synthetic_mouse_pointer.h" +#include "content/browser/renderer_host/input/synthetic_touch_pointer.h" +#include "third_party/WebKit/public/web/WebInputEvent.h" + +namespace content { + +SyntheticPointer::SyntheticPointer() {} +SyntheticPointer::~SyntheticPointer() {} + +// static +scoped_ptr<SyntheticPointer> SyntheticPointer::Create( + SyntheticGestureParams::GestureSourceType gesture_source_type) { + if (gesture_source_type == SyntheticGestureParams::TOUCH_INPUT) { + return make_scoped_ptr(new SyntheticTouchPointer()); + } else if (gesture_source_type == SyntheticGestureParams::MOUSE_INPUT) { + return make_scoped_ptr(new SyntheticMousePointer()); + } else { + NOTREACHED() << "Invalid gesture source type"; + return scoped_ptr<SyntheticPointer>(); + } +} + +// static +double SyntheticPointer::ConvertTimestampToSeconds( + const base::TimeTicks& timestamp) { + return (timestamp - base::TimeTicks()).InSecondsF(); +} + +} // namespace content
diff --git a/content/browser/renderer_host/input/synthetic_pointer.h b/content/browser/renderer_host/input/synthetic_pointer.h new file mode 100644 index 0000000..ae4fd35 --- /dev/null +++ b/content/browser/renderer_host/input/synthetic_pointer.h
@@ -0,0 +1,51 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CONTENT_BROWSER_RENDERER_HOST_INPUT_SYNTHETIC_POINTER_H_ +#define CONTENT_BROWSER_RENDERER_HOST_INPUT_SYNTHETIC_POINTER_H_ + +#include "base/macros.h" +#include "base/memory/scoped_ptr.h" +#include "content/common/content_export.h" +#include "content/common/input/synthetic_gesture_params.h" +#include "content/common/input/synthetic_web_input_event_builders.h" + +namespace content { + +class SyntheticGestureTarget; + +class CONTENT_EXPORT SyntheticPointer { + public: + SyntheticPointer(); + virtual ~SyntheticPointer(); + + static scoped_ptr<SyntheticPointer> Create( + SyntheticGestureParams::GestureSourceType gesture_source_type); + + virtual void DispatchEvent(SyntheticGestureTarget* target, + const base::TimeTicks& timestamp) = 0; + + virtual int Press(float x, + float y, + SyntheticGestureTarget* target, + const base::TimeTicks& timestamp) = 0; + virtual void Move(int index, + float x, + float y, + SyntheticGestureTarget* target, + const base::TimeTicks& timestamp) = 0; + virtual void Release(int index, + SyntheticGestureTarget* target, + const base::TimeTicks& timestamp) = 0; + + protected: + static double ConvertTimestampToSeconds(const base::TimeTicks& timestamp); + + private: + DISALLOW_COPY_AND_ASSIGN(SyntheticPointer); +}; + +} // namespace content + +#endif // CONTENT_BROWSER_RENDERER_HOST_INPUT_SYNTHETIC_POINTER_H_
diff --git a/content/browser/renderer_host/input/synthetic_pointer_gesture.cc b/content/browser/renderer_host/input/synthetic_pointer_gesture.cc new file mode 100644 index 0000000..60b5eef --- /dev/null +++ b/content/browser/renderer_host/input/synthetic_pointer_gesture.cc
@@ -0,0 +1,58 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "content/browser/renderer_host/input/synthetic_pointer_gesture.h" + +#include "base/logging.h" +#include "third_party/WebKit/public/web/WebInputEvent.h" +#include "ui/events/latency_info.h" + +namespace content { + +SyntheticPointerGesture::SyntheticPointerGesture( + SyntheticGestureParams::GestureSourceType gesture_source_type, + PointerActionType pointer_action_type, + SyntheticPointer* synthetic_pointer, + gfx::PointF position, + int index) + : gesture_source_type_(gesture_source_type), + pointer_action_type_(pointer_action_type), + position_(position), + index_(index), + synthetic_pointer_(synthetic_pointer) {} + +SyntheticPointerGesture::~SyntheticPointerGesture() {} + +SyntheticGesture::Result SyntheticPointerGesture::ForwardInputEvents( + const base::TimeTicks& timestamp, + SyntheticGestureTarget* target) { + if (gesture_source_type_ == SyntheticGestureParams::DEFAULT_INPUT) + gesture_source_type_ = target->GetDefaultSyntheticGestureSourceType(); + + DCHECK_NE(gesture_source_type_, SyntheticGestureParams::DEFAULT_INPUT); + + ForwardTouchOrMouseInputEvents(timestamp, target); + return SyntheticGesture::GESTURE_FINISHED; +} + +void SyntheticPointerGesture::ForwardTouchOrMouseInputEvents( + const base::TimeTicks& timestamp, + SyntheticGestureTarget* target) { + switch (pointer_action_type_) { + case SyntheticGesture::PRESS: + synthetic_pointer_->Press(position_.x(), position_.y(), target, + timestamp); + break; + case SyntheticGesture::MOVE: + synthetic_pointer_->Move(index_, position_.x(), position_.y(), target, + timestamp); + break; + case SyntheticGesture::RELEASE: + synthetic_pointer_->Release(index_, target, timestamp); + break; + } + synthetic_pointer_->DispatchEvent(target, timestamp); +} + +} // namespace content
diff --git a/content/browser/renderer_host/input/synthetic_pointer_gesture.h b/content/browser/renderer_host/input/synthetic_pointer_gesture.h new file mode 100644 index 0000000..bbadc7d --- /dev/null +++ b/content/browser/renderer_host/input/synthetic_pointer_gesture.h
@@ -0,0 +1,45 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CONTENT_BROWSER_RENDERER_HOST_INPUT_SYNTHETIC_POINTER_GESTURE_H_ +#define CONTENT_BROWSER_RENDERER_HOST_INPUT_SYNTHETIC_POINTER_GESTURE_H_ + +#include "base/macros.h" +#include "content/browser/renderer_host/input/synthetic_gesture.h" +#include "content/browser/renderer_host/input/synthetic_gesture_target.h" +#include "content/browser/renderer_host/input/synthetic_pointer.h" +#include "content/common/content_export.h" + +namespace content { + +class CONTENT_EXPORT SyntheticPointerGesture : public SyntheticGesture { + public: + SyntheticPointerGesture( + SyntheticGestureParams::GestureSourceType gesture_source_type, + PointerActionType pointer_action_type, + SyntheticPointer* synthetic_pointer, + gfx::PointF position, + int index = 0); + ~SyntheticPointerGesture() override; + + SyntheticGesture::Result ForwardInputEvents( + const base::TimeTicks& timestamp, + SyntheticGestureTarget* target) override; + + void ForwardTouchOrMouseInputEvents(const base::TimeTicks& timestamp, + SyntheticGestureTarget* target); + + private: + SyntheticGestureParams::GestureSourceType gesture_source_type_; + PointerActionType pointer_action_type_; + gfx::PointF position_; + int index_; + SyntheticPointer* synthetic_pointer_; + + DISALLOW_COPY_AND_ASSIGN(SyntheticPointerGesture); +}; + +} // namespace content + +#endif // CONTENT_BROWSER_RENDERER_HOST_INPUT_SYNTHETIC_POINTER_GESTURE_H_
diff --git a/content/browser/renderer_host/input/synthetic_smooth_move_gesture.cc b/content/browser/renderer_host/input/synthetic_smooth_move_gesture.cc index 80f3ef76..ec7f3bc5 100644 --- a/content/browser/renderer_host/input/synthetic_smooth_move_gesture.cc +++ b/content/browser/renderer_host/input/synthetic_smooth_move_gesture.cc
@@ -27,6 +27,10 @@ return gfx::ScaleVector2d(vector, scalar / vector.Length()); } +double ConvertTimestampToSeconds(const base::TimeTicks& timestamp) { + return (timestamp - base::TimeTicks()).InSecondsF(); +} + const int kDefaultSpeedInPixelsPerSec = 800; } // namespace @@ -58,9 +62,15 @@ switch (params_.input_type) { case SyntheticSmoothMoveGestureParams::TOUCH_INPUT: + if (!synthetic_pointer_) + synthetic_pointer_ = + SyntheticPointer::Create(SyntheticGestureParams::TOUCH_INPUT); ForwardTouchInputEvents(timestamp, target); break; case SyntheticSmoothMoveGestureParams::MOUSE_DRAG_INPUT: + if (!synthetic_pointer_) + synthetic_pointer_ = + SyntheticPointer::Create(SyntheticGestureParams::MOUSE_INPUT); ForwardMouseClickInputEvents(timestamp, target); break; case SyntheticSmoothMoveGestureParams::MOUSE_WHEEL_INPUT: @@ -92,13 +102,13 @@ if (params_.add_slop) AddTouchSlopToFirstDistance(target); ComputeNextMoveSegment(); - PressTouchPoint(target, event_timestamp); + PressPoint(target, event_timestamp); state_ = MOVING; break; case MOVING: { event_timestamp = ClampTimestamp(timestamp); gfx::Vector2dF delta = GetPositionDeltaAtTime(event_timestamp); - MoveTouchPoint(target, delta, event_timestamp); + MovePoint(target, delta, event_timestamp); if (FinishedCurrentMoveSegment(event_timestamp)) { if (!IsLastMoveSegment()) { @@ -108,7 +118,7 @@ } else if (params_.prevent_fling) { state_ = STOPPING; } else { - ReleaseTouchPoint(target, event_timestamp); + ReleasePoint(target, event_timestamp); state_ = DONE; } } @@ -118,7 +128,7 @@ target->PointerAssumedStoppedTime()) { event_timestamp = current_move_segment_stop_time_ + target->PointerAssumedStoppedTime(); - ReleaseTouchPoint(target, event_timestamp); + ReleasePoint(target, event_timestamp); state_ = DONE; } break; @@ -191,13 +201,13 @@ break; } ComputeNextMoveSegment(); - PressMousePoint(target, event_timestamp); + PressPoint(target, event_timestamp); state_ = MOVING; break; case MOVING: { base::TimeTicks event_timestamp = ClampTimestamp(timestamp); gfx::Vector2dF delta = GetPositionDeltaAtTime(event_timestamp); - MoveMousePoint(target, delta, event_timestamp); + MovePoint(target, delta, event_timestamp); if (FinishedCurrentMoveSegment(event_timestamp)) { if (!IsLastMoveSegment()) { @@ -205,7 +215,7 @@ params_.distances[current_move_segment_]; ComputeNextMoveSegment(); } else { - ReleaseMousePoint(target, event_timestamp); + ReleasePoint(target, event_timestamp); state_ = DONE; } } @@ -222,14 +232,6 @@ } } -void SyntheticSmoothMoveGesture::ForwardTouchEvent( - SyntheticGestureTarget* target, - const base::TimeTicks& timestamp) { - touch_event_.timeStampSeconds = ConvertTimestampToSeconds(timestamp); - - target->DispatchInputEventToPlatform(touch_event_); -} - void SyntheticSmoothMoveGesture::ForwardMouseWheelEvent( SyntheticGestureTarget* target, const gfx::Vector2dF& delta, @@ -245,74 +247,39 @@ target->DispatchInputEventToPlatform(mouse_wheel_event); } -void SyntheticSmoothMoveGesture::PressTouchPoint( - SyntheticGestureTarget* target, - const base::TimeTicks& timestamp) { +void SyntheticSmoothMoveGesture::PressPoint(SyntheticGestureTarget* target, + const base::TimeTicks& timestamp) { DCHECK_EQ(current_move_segment_, 0); - touch_event_.PressPoint(current_move_segment_start_position_.x(), - current_move_segment_start_position_.y()); - ForwardTouchEvent(target, timestamp); + synthetic_pointer_->Press(current_move_segment_start_position_.x(), + current_move_segment_start_position_.y(), target, + timestamp); + synthetic_pointer_->DispatchEvent(target, timestamp); } -void SyntheticSmoothMoveGesture::MoveTouchPoint( - SyntheticGestureTarget* target, - const gfx::Vector2dF& delta, - const base::TimeTicks& timestamp) { +void SyntheticSmoothMoveGesture::MovePoint(SyntheticGestureTarget* target, + const gfx::Vector2dF& delta, + const base::TimeTicks& timestamp) { DCHECK_GE(current_move_segment_, 0); DCHECK_LT(current_move_segment_, static_cast<int>(params_.distances.size())); - gfx::PointF touch_position = current_move_segment_start_position_ + delta; - touch_event_.MovePoint(0, touch_position.x(), touch_position.y()); - ForwardTouchEvent(target, timestamp); + gfx::PointF new_position = current_move_segment_start_position_ + delta; + synthetic_pointer_->Move(0, new_position.x(), new_position.y(), target, + timestamp); + synthetic_pointer_->DispatchEvent(target, timestamp); } -void SyntheticSmoothMoveGesture::ReleaseTouchPoint( +void SyntheticSmoothMoveGesture::ReleasePoint( SyntheticGestureTarget* target, const base::TimeTicks& timestamp) { DCHECK_EQ(current_move_segment_, static_cast<int>(params_.distances.size()) - 1); - touch_event_.ReleasePoint(0); - ForwardTouchEvent(target, timestamp); -} - -void SyntheticSmoothMoveGesture::PressMousePoint( - SyntheticGestureTarget* target, - const base::TimeTicks& timestamp) { - DCHECK_EQ(params_.input_type, - SyntheticSmoothMoveGestureParams::MOUSE_DRAG_INPUT); - blink::WebMouseEvent mouse_event = SyntheticWebMouseEventBuilder::Build( - blink::WebInputEvent::MouseDown, current_move_segment_start_position_.x(), - current_move_segment_start_position_.y(), 0); - mouse_event.clickCount = 1; - mouse_event.timeStampSeconds = ConvertTimestampToSeconds(timestamp); - target->DispatchInputEventToPlatform(mouse_event); -} - -void SyntheticSmoothMoveGesture::ReleaseMousePoint( - SyntheticGestureTarget* target, - const base::TimeTicks& timestamp) { - DCHECK_EQ(params_.input_type, - SyntheticSmoothMoveGestureParams::MOUSE_DRAG_INPUT); - gfx::PointF mouse_position = - current_move_segment_start_position_ + GetPositionDeltaAtTime(timestamp); - blink::WebMouseEvent mouse_event = SyntheticWebMouseEventBuilder::Build( - blink::WebInputEvent::MouseUp, mouse_position.x(), mouse_position.y(), 0); - mouse_event.timeStampSeconds = ConvertTimestampToSeconds(timestamp); - target->DispatchInputEventToPlatform(mouse_event); -} - -void SyntheticSmoothMoveGesture::MoveMousePoint( - SyntheticGestureTarget* target, - const gfx::Vector2dF& delta, - const base::TimeTicks& timestamp) { - gfx::PointF mouse_position = current_move_segment_start_position_ + delta; - DCHECK_EQ(params_.input_type, - SyntheticSmoothMoveGestureParams::MOUSE_DRAG_INPUT); - blink::WebMouseEvent mouse_event = SyntheticWebMouseEventBuilder::Build( - blink::WebInputEvent::MouseMove, mouse_position.x(), mouse_position.y(), - 0); - mouse_event.button = blink::WebMouseEvent::ButtonLeft; - mouse_event.timeStampSeconds = ConvertTimestampToSeconds(timestamp); - target->DispatchInputEventToPlatform(mouse_event); + gfx::PointF position; + if (params_.input_type == + SyntheticSmoothMoveGestureParams::MOUSE_DRAG_INPUT) { + position = current_move_segment_start_position_ + + GetPositionDeltaAtTime(timestamp); + } + synthetic_pointer_->Release(0, target, timestamp); + synthetic_pointer_->DispatchEvent(target, timestamp); } void SyntheticSmoothMoveGesture::AddTouchSlopToFirstDistance(
diff --git a/content/browser/renderer_host/input/synthetic_smooth_move_gesture.h b/content/browser/renderer_host/input/synthetic_smooth_move_gesture.h index 201dfcf8..931d2f4f 100644 --- a/content/browser/renderer_host/input/synthetic_smooth_move_gesture.h +++ b/content/browser/renderer_host/input/synthetic_smooth_move_gesture.h
@@ -10,10 +10,10 @@ #include "base/time/time.h" #include "content/browser/renderer_host/input/synthetic_gesture.h" #include "content/browser/renderer_host/input/synthetic_gesture_target.h" +#include "content/browser/renderer_host/input/synthetic_pointer.h" #include "content/common/content_export.h" #include "content/common/input/synthetic_smooth_drag_gesture_params.h" #include "content/common/input/synthetic_smooth_scroll_gesture_params.h" -#include "content/common/input/synthetic_web_input_event_builders.h" #include "third_party/WebKit/public/web/WebInputEvent.h" #include "ui/gfx/geometry/vector2d.h" #include "ui/gfx/geometry/vector2d_f.h" @@ -69,27 +69,17 @@ void ForwardMouseClickInputEvents( const base::TimeTicks& timestamp, SyntheticGestureTarget* target); - void ForwardTouchEvent(SyntheticGestureTarget* target, - const base::TimeTicks& timestamp); void ForwardMouseWheelEvent(SyntheticGestureTarget* target, const gfx::Vector2dF& delta, const base::TimeTicks& timestamp) const; - void PressTouchPoint(SyntheticGestureTarget* target, - const base::TimeTicks& timestamp); - void MoveTouchPoint(SyntheticGestureTarget* target, - const gfx::Vector2dF& delta, - const base::TimeTicks& timestamp); - void ReleaseTouchPoint(SyntheticGestureTarget* target, - const base::TimeTicks& timestamp); - - void PressMousePoint(SyntheticGestureTarget* target, - const base::TimeTicks& timestamp); - void ReleaseMousePoint(SyntheticGestureTarget* target, - const base::TimeTicks& timestamp); - void MoveMousePoint(SyntheticGestureTarget* target, - const gfx::Vector2dF& delta, - const base::TimeTicks& timestamp); + void PressPoint(SyntheticGestureTarget* target, + const base::TimeTicks& timestamp); + void MovePoint(SyntheticGestureTarget* target, + const gfx::Vector2dF& delta, + const base::TimeTicks& timestamp); + void ReleasePoint(SyntheticGestureTarget* target, + const base::TimeTicks& timestamp); void AddTouchSlopToFirstDistance(SyntheticGestureTarget* target); gfx::Vector2dF GetPositionDeltaAtTime(const base::TimeTicks& timestamp) const; @@ -100,11 +90,11 @@ bool MoveIsNoOp() const; SyntheticSmoothMoveGestureParams params_; + scoped_ptr<SyntheticPointer> synthetic_pointer_; // Used for mouse input. gfx::Vector2d current_move_segment_total_delta_discrete_; // Used for touch input. gfx::PointF current_move_segment_start_position_; - SyntheticWebTouchEvent touch_event_; GestureState state_; int current_move_segment_; base::TimeTicks current_move_segment_start_time_;
diff --git a/content/browser/renderer_host/input/synthetic_tap_gesture.cc b/content/browser/renderer_host/input/synthetic_tap_gesture.cc index e20412a0..46dc23ae 100644 --- a/content/browser/renderer_host/input/synthetic_tap_gesture.cc +++ b/content/browser/renderer_host/input/synthetic_tap_gesture.cc
@@ -31,6 +31,10 @@ } DCHECK_NE(gesture_source_type_, SyntheticGestureParams::DEFAULT_INPUT); + + if (!synthetic_pointer_) + synthetic_pointer_ = SyntheticPointer::Create(gesture_source_type_); + if (gesture_source_type_ == SyntheticGestureParams::TOUCH_INPUT || gesture_source_type_ == SyntheticGestureParams::MOUSE_INPUT) ForwardTouchOrMouseInputEvents(timestamp, target); @@ -45,10 +49,13 @@ const base::TimeTicks& timestamp, SyntheticGestureTarget* target) { switch (state_) { case PRESS: - Press(target, timestamp); + synthetic_pointer_->Press(params_.position.x(), params_.position.y(), + target, timestamp); + synthetic_pointer_->DispatchEvent(target, timestamp); // Release immediately if duration is 0. if (params_.duration_ms == 0) { - Release(target, timestamp); + synthetic_pointer_->Release(0, target, timestamp); + synthetic_pointer_->DispatchEvent(target, timestamp); state_ = DONE; } else { start_time_ = timestamp; @@ -57,7 +64,8 @@ break; case WAITING_TO_RELEASE: if (timestamp - start_time_ >= GetDuration()) { - Release(target, start_time_ + GetDuration()); + synthetic_pointer_->Release(0, target, start_time_ + GetDuration()); + synthetic_pointer_->DispatchEvent(target, start_time_ + GetDuration()); state_ = DONE; } break; @@ -68,46 +76,6 @@ } } -void SyntheticTapGesture::Press(SyntheticGestureTarget* target, - const base::TimeTicks& timestamp) { - if (gesture_source_type_ == SyntheticGestureParams::TOUCH_INPUT) { - touch_event_.PressPoint(params_.position.x(), params_.position.y()); - touch_event_.timeStampSeconds = ConvertTimestampToSeconds(timestamp); - target->DispatchInputEventToPlatform(touch_event_); - } else if (gesture_source_type_ == SyntheticGestureParams::MOUSE_INPUT) { - blink::WebMouseEvent mouse_event = - SyntheticWebMouseEventBuilder::Build(blink::WebInputEvent::MouseDown, - params_.position.x(), - params_.position.y(), - 0); - mouse_event.clickCount = 1; - mouse_event.timeStampSeconds = ConvertTimestampToSeconds(timestamp); - target->DispatchInputEventToPlatform(mouse_event); - } else { - NOTREACHED() << "Invalid gesture source type for synthetic tap gesture."; - } -} - -void SyntheticTapGesture::Release(SyntheticGestureTarget* target, - const base::TimeTicks& timestamp) { - if (gesture_source_type_ == SyntheticGestureParams::TOUCH_INPUT) { - touch_event_.ReleasePoint(0); - touch_event_.timeStampSeconds = ConvertTimestampToSeconds(timestamp); - target->DispatchInputEventToPlatform(touch_event_); - } else if (gesture_source_type_ == SyntheticGestureParams::MOUSE_INPUT) { - blink::WebMouseEvent mouse_event = - SyntheticWebMouseEventBuilder::Build(blink::WebInputEvent::MouseUp, - params_.position.x(), - params_.position.y(), - 0); - mouse_event.clickCount = 1; - mouse_event.timeStampSeconds = ConvertTimestampToSeconds(timestamp); - target->DispatchInputEventToPlatform(mouse_event); - } else { - NOTREACHED() << "Invalid gesture source type for synthetic tap gesture."; - } -} - base::TimeDelta SyntheticTapGesture::GetDuration() const { return base::TimeDelta::FromMilliseconds(params_.duration_ms); }
diff --git a/content/browser/renderer_host/input/synthetic_tap_gesture.h b/content/browser/renderer_host/input/synthetic_tap_gesture.h index a42b2dd1..b20c1ec 100644 --- a/content/browser/renderer_host/input/synthetic_tap_gesture.h +++ b/content/browser/renderer_host/input/synthetic_tap_gesture.h
@@ -7,9 +7,9 @@ #include "content/browser/renderer_host/input/synthetic_gesture.h" #include "content/browser/renderer_host/input/synthetic_gesture_target.h" +#include "content/browser/renderer_host/input/synthetic_pointer.h" #include "content/common/content_export.h" #include "content/common/input/synthetic_tap_gesture_params.h" -#include "content/common/input/synthetic_web_input_event_builders.h" namespace content { @@ -33,15 +33,11 @@ void ForwardTouchOrMouseInputEvents(const base::TimeTicks& timestamp, SyntheticGestureTarget* target); - void Press(SyntheticGestureTarget* target, const base::TimeTicks& timestamp); - void Release(SyntheticGestureTarget* target, - const base::TimeTicks& timestamp); - base::TimeDelta GetDuration() const; SyntheticTapGestureParams params_; + scoped_ptr<SyntheticPointer> synthetic_pointer_; base::TimeTicks start_time_; - SyntheticWebTouchEvent touch_event_; SyntheticGestureParams::GestureSourceType gesture_source_type_; GestureState state_;
diff --git a/content/browser/renderer_host/input/synthetic_touch_pointer.cc b/content/browser/renderer_host/input/synthetic_touch_pointer.cc new file mode 100644 index 0000000..ca4637a6 --- /dev/null +++ b/content/browser/renderer_host/input/synthetic_touch_pointer.cc
@@ -0,0 +1,46 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "content/browser/renderer_host/input/synthetic_touch_pointer.h" + +#include "content/browser/renderer_host/input/synthetic_gesture_target.h" + +namespace content { + +SyntheticTouchPointer::SyntheticTouchPointer() {} + +SyntheticTouchPointer::SyntheticTouchPointer(SyntheticWebTouchEvent touch_event) + : touch_event_(touch_event) {} + +SyntheticTouchPointer::~SyntheticTouchPointer() {} + +void SyntheticTouchPointer::DispatchEvent(SyntheticGestureTarget* target, + const base::TimeTicks& timestamp) { + touch_event_.timeStampSeconds = ConvertTimestampToSeconds(timestamp); + target->DispatchInputEventToPlatform(touch_event_); +} + +int SyntheticTouchPointer::Press(float x, + float y, + SyntheticGestureTarget* target, + const base::TimeTicks& timestamp) { + int index = touch_event_.PressPoint(x, y); + return index; +} + +void SyntheticTouchPointer::Move(int index, + float x, + float y, + SyntheticGestureTarget* target, + const base::TimeTicks& timestamp) { + touch_event_.MovePoint(index, x, y); +} + +void SyntheticTouchPointer::Release(int index, + SyntheticGestureTarget* target, + const base::TimeTicks& timestamp) { + touch_event_.ReleasePoint(index); +} + +} // namespace content
diff --git a/content/browser/renderer_host/input/synthetic_touch_pointer.h b/content/browser/renderer_host/input/synthetic_touch_pointer.h new file mode 100644 index 0000000..abd579e --- /dev/null +++ b/content/browser/renderer_host/input/synthetic_touch_pointer.h
@@ -0,0 +1,45 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CONTENT_BROWSER_RENDERER_HOST_INPUT_SYNTHETIC_TOUCH_POINTER_H_ +#define CONTENT_BROWSER_RENDERER_HOST_INPUT_SYNTHETIC_TOUCH_POINTER_H_ + +#include "base/macros.h" +#include "content/browser/renderer_host/input/synthetic_pointer.h" +#include "content/common/content_export.h" +#include "content/common/input/synthetic_web_input_event_builders.h" + +namespace content { + +class CONTENT_EXPORT SyntheticTouchPointer : public SyntheticPointer { + public: + SyntheticTouchPointer(); + explicit SyntheticTouchPointer(SyntheticWebTouchEvent touch_event); + ~SyntheticTouchPointer() override; + + void DispatchEvent(SyntheticGestureTarget* target, + const base::TimeTicks& timestamp) override; + + int Press(float x, + float y, + SyntheticGestureTarget* target, + const base::TimeTicks& timestamp) override; + void Move(int index, + float x, + float y, + SyntheticGestureTarget* target, + const base::TimeTicks& timestamp) override; + void Release(int index, + SyntheticGestureTarget* target, + const base::TimeTicks& timestamp) override; + + private: + SyntheticWebTouchEvent touch_event_; + + DISALLOW_COPY_AND_ASSIGN(SyntheticTouchPointer); +}; + +} // namespace content + +#endif // CONTENT_COMMON_INPUT_SYNTHETIC_TOUCH_POINTER_H_
diff --git a/content/browser/renderer_host/input/synthetic_touchscreen_pinch_gesture.cc b/content/browser/renderer_host/input/synthetic_touchscreen_pinch_gesture.cc index b3eb9f0..9d0ff71 100644 --- a/content/browser/renderer_host/input/synthetic_touchscreen_pinch_gesture.cc +++ b/content/browser/renderer_host/input/synthetic_touchscreen_pinch_gesture.cc
@@ -37,6 +37,10 @@ } DCHECK_NE(gesture_source_type_, SyntheticGestureParams::DEFAULT_INPUT); + + if (!synthetic_pointer_) + synthetic_pointer_ = SyntheticPointer::Create(gesture_source_type_); + if (gesture_source_type_ == SyntheticGestureParams::TOUCH_INPUT) { ForwardTouchInputEvents(timestamp, target); } else { @@ -80,9 +84,9 @@ void SyntheticTouchscreenPinchGesture::PressTouchPoints( SyntheticGestureTarget* target, const base::TimeTicks& timestamp) { - touch_event_.PressPoint(params_.anchor.x(), start_y_0_); - touch_event_.PressPoint(params_.anchor.x(), start_y_1_); - ForwardTouchEvent(target, timestamp); + synthetic_pointer_->Press(params_.anchor.x(), start_y_0_, target, timestamp); + synthetic_pointer_->Press(params_.anchor.x(), start_y_1_, target, timestamp); + synthetic_pointer_->DispatchEvent(target, timestamp); } void SyntheticTouchscreenPinchGesture::MoveTouchPoints( @@ -93,24 +97,19 @@ float current_y_0 = start_y_0_ + delta; float current_y_1 = start_y_1_ - delta; - touch_event_.MovePoint(0, params_.anchor.x(), current_y_0); - touch_event_.MovePoint(1, params_.anchor.x(), current_y_1); - ForwardTouchEvent(target, timestamp); + synthetic_pointer_->Move(0, params_.anchor.x(), current_y_0, target, + timestamp); + synthetic_pointer_->Move(1, params_.anchor.x(), current_y_1, target, + timestamp); + synthetic_pointer_->DispatchEvent(target, timestamp); } void SyntheticTouchscreenPinchGesture::ReleaseTouchPoints( SyntheticGestureTarget* target, const base::TimeTicks& timestamp) { - touch_event_.ReleasePoint(0); - touch_event_.ReleasePoint(1); - ForwardTouchEvent(target, timestamp); -} - -void SyntheticTouchscreenPinchGesture::ForwardTouchEvent( - SyntheticGestureTarget* target, - const base::TimeTicks& timestamp) { - touch_event_.timeStampSeconds = ConvertTimestampToSeconds(timestamp); - target->DispatchInputEventToPlatform(touch_event_); + synthetic_pointer_->Release(0, target, timestamp); + synthetic_pointer_->Release(1, target, timestamp); + synthetic_pointer_->DispatchEvent(target, timestamp); } void SyntheticTouchscreenPinchGesture::SetupCoordinatesAndStopTime(
diff --git a/content/browser/renderer_host/input/synthetic_touchscreen_pinch_gesture.h b/content/browser/renderer_host/input/synthetic_touchscreen_pinch_gesture.h index a549db0c..73d2c41 100644 --- a/content/browser/renderer_host/input/synthetic_touchscreen_pinch_gesture.h +++ b/content/browser/renderer_host/input/synthetic_touchscreen_pinch_gesture.h
@@ -8,6 +8,7 @@ #include "base/time/time.h" #include "content/browser/renderer_host/input/synthetic_gesture.h" #include "content/browser/renderer_host/input/synthetic_gesture_target.h" +#include "content/browser/renderer_host/input/synthetic_pointer.h" #include "content/common/content_export.h" #include "content/common/input/synthetic_pinch_gesture_params.h" #include "content/common/input/synthetic_web_input_event_builders.h" @@ -32,7 +33,6 @@ void ForwardTouchInputEvents(const base::TimeTicks& timestamp, SyntheticGestureTarget* target); - void UpdateTouchPoints(const base::TimeTicks& timestamp); void PressTouchPoints(SyntheticGestureTarget* target, const base::TimeTicks& timestamp); void MoveTouchPoints(SyntheticGestureTarget* target, @@ -40,8 +40,6 @@ const base::TimeTicks& timestamp); void ReleaseTouchPoints(SyntheticGestureTarget* target, const base::TimeTicks& timestamp); - void ForwardTouchEvent(SyntheticGestureTarget* target, - const base::TimeTicks& timestamp); void SetupCoordinatesAndStopTime(SyntheticGestureTarget* target); float GetDeltaForPointer0AtTime(const base::TimeTicks& timestamp) const; @@ -49,12 +47,12 @@ bool HasReachedTarget(const base::TimeTicks& timestamp) const; SyntheticPinchGestureParams params_; + scoped_ptr<SyntheticPointer> synthetic_pointer_; float start_y_0_; float start_y_1_; float max_pointer_delta_0_; SyntheticGestureParams::GestureSourceType gesture_source_type_; GestureState state_; - SyntheticWebTouchEvent touch_event_; base::TimeTicks start_time_; base::TimeTicks stop_time_;
diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc index fd9275e..d51107c0 100644 --- a/content/browser/renderer_host/render_process_host_impl.cc +++ b/content/browser/renderer_host/render_process_host_impl.cc
@@ -24,7 +24,6 @@ #include "base/metrics/field_trial.h" #include "base/metrics/histogram.h" #include "base/process/process_handle.h" -#include "base/profiler/scoped_tracker.h" #include "base/rand_util.h" #include "base/single_thread_task_runner.h" #include "base/stl_util.h" @@ -992,7 +991,7 @@ if (browser_command_line.HasSwitch(switches::kEnableMemoryBenchmarking)) AddFilter(new MemoryBenchmarkMessageFilter()); #endif - AddFilter(new MemoryMessageFilter(this)); + AddFilter(new MemoryMessageFilter()); AddFilter(new PushMessagingMessageFilter( GetID(), storage_partition_impl_->GetServiceWorkerContext())); // TODO(mfomitchev): Screen Orientation APIs on Aura - crbug.com/546719. @@ -2408,11 +2407,6 @@ } void RenderProcessHostImpl::OnProcessLaunched() { - // TODO(erikchen): Remove ScopedTracker below once http://crbug.com/465841 - // is fixed. - tracked_objects::ScopedTracker tracking_profile1( - FROM_HERE_WITH_EXPLICIT_FUNCTION( - "465841 RenderProcessHostImpl::OnProcessLaunched::Start")); // No point doing anything, since this object will be destructed soon. We // especially don't want to send the RENDERER_PROCESS_CREATED notification, // since some clients might expect a RENDERER_PROCESS_TERMINATED afterwards to @@ -2421,11 +2415,6 @@ return; if (child_process_launcher_) { - // TODO(erikchen): Remove ScopedTracker below once http://crbug.com/465841 - // is fixed. - tracked_objects::ScopedTracker tracking_profile2( - FROM_HERE_WITH_EXPLICIT_FUNCTION( - "465841 RenderProcessHostImpl::OnProcessLaunched::Backgrounded")); DCHECK(child_process_launcher_->GetProcess().IsValid()); DCHECK(!is_process_backgrounded_); @@ -2438,11 +2427,6 @@ UpdateProcessPriority(); } - // TODO(erikchen): Remove ScopedTracker below once http://crbug.com/465841 - // is fixed. - tracked_objects::ScopedTracker tracking_profile3( - FROM_HERE_WITH_EXPLICIT_FUNCTION( - "465841 RenderProcessHostImpl::OnProcessLaunched::Notify")); // NOTE: This needs to be before sending queued messages because // ExtensionService uses this notification to initialize the renderer process // with state that must be there before any JavaScript executes. @@ -2460,28 +2444,11 @@ RegisterChildWithExternalShell(id_, GetHandle(), this); #endif - // TODO(erikchen): Remove ScopedTracker below once http://crbug.com/465841 - // is fixed. - tracked_objects::ScopedTracker tracking_profile4( - FROM_HERE_WITH_EXPLICIT_FUNCTION( - "465841 RenderProcessHostImpl::OnProcessLaunched::MojoActivate")); // Allow Mojo to be setup before the renderer sees any Chrome IPC messages. // This way, Mojo can be safely used from the renderer in response to any // Chrome IPC message. mojo_application_host_->Activate(this, GetHandle()); - // TODO(erikchen): Remove ScopedTracker below once http://crbug.com/465841 - // is fixed. - tracked_objects::ScopedTracker tracking_profile5( - FROM_HERE_WITH_EXPLICIT_FUNCTION( - "465841 RenderProcessHostImpl::OnProcessLaunched::MojoClientLaunch")); - - // TODO(erikchen): Remove ScopedTracker below once http://crbug.com/465841 - // is fixed. - tracked_objects::ScopedTracker tracking_profile6( - FROM_HERE_WITH_EXPLICIT_FUNCTION( - "465841 " - "RenderProcessHostImpl::OnProcessLaunched::SendQueuedMessages")); while (!queued_messages_.empty()) { Send(queued_messages_.front()); queued_messages_.pop(); @@ -2497,11 +2464,6 @@ } #if defined(ENABLE_WEBRTC) - // TODO(erikchen): Remove ScopedTracker below once http://crbug.com/465841 - // is fixed. - tracked_objects::ScopedTracker tracking_profile7( - FROM_HERE_WITH_EXPLICIT_FUNCTION( - "465841 RenderProcessHostImpl::OnProcessLaunched::EnableAec")); if (WebRTCInternals::GetInstance()->IsAudioDebugRecordingsEnabled()) { EnableAudioDebugRecordings( WebRTCInternals::GetInstance()->GetAudioDebugRecordingsFilePath());
diff --git a/content/browser/renderer_host/render_view_host_browsertest.cc b/content/browser/renderer_host/render_view_host_browsertest.cc index feb4957..3e16cdfb 100644 --- a/content/browser/renderer_host/render_view_host_browsertest.cc +++ b/content/browser/renderer_host/render_view_host_browsertest.cc
@@ -128,7 +128,13 @@ EXPECT_TRUE(rvh->IsFocusedElementEditable()); } -IN_PROC_BROWSER_TEST_F(RenderViewHostTest, ReleaseSessionOnCloseACK) { +// Flaky on Linux (https://crbug.com/559192). +#if defined(OS_LINUX) +#define MAYBE_ReleaseSessionOnCloseACK DISABLED_ReleaseSessionOnCloseACK +#else +#define MAYBE_ReleaseSessionOnCloseACK ReleaseSessionOnCloseACK +#endif +IN_PROC_BROWSER_TEST_F(RenderViewHostTest, MAYBE_ReleaseSessionOnCloseACK) { ASSERT_TRUE(embedded_test_server()->Start()); GURL test_url = embedded_test_server()->GetURL( "/access-session-storage.html");
diff --git a/content/browser/renderer_host/render_widget_host_delegate.cc b/content/browser/renderer_host/render_widget_host_delegate.cc index 2026575..0609826f 100644 --- a/content/browser/renderer_host/render_widget_host_delegate.cc +++ b/content/browser/renderer_host/render_widget_host_delegate.cc
@@ -50,8 +50,9 @@ // If a delegate does not override this, the RenderWidgetHostView will // assume its own RenderWidgetHost should consume keyboard events. -RenderWidgetHostImpl* RenderWidgetHostDelegate::GetFocusedRenderWidgetHost() { - return nullptr; +RenderWidgetHostImpl* RenderWidgetHostDelegate::GetFocusedRenderWidgetHost( + RenderWidgetHostImpl* receiving_widget) { + return receiving_widget; } gfx::Rect RenderWidgetHostDelegate::GetRootWindowResizerRect(
diff --git a/content/browser/renderer_host/render_widget_host_delegate.h b/content/browser/renderer_host/render_widget_host_delegate.h index 604a3ac..61c2feb 100644 --- a/content/browser/renderer_host/render_widget_host_delegate.h +++ b/content/browser/renderer_host/render_widget_host_delegate.h
@@ -120,11 +120,17 @@ // current FrameTree, not including the main frame's SiteInstance. virtual void ReplicatePageFocus(bool is_focused) {} - // Get the RenderWidgetHost of the currently focused frame. With - // out-of-process iframes, multiple RenderWidgetHosts may be involved in - // rendering a page, and this function determines which RenderWidgetHost - // should consume a keyboard input event. - virtual RenderWidgetHostImpl* GetFocusedRenderWidgetHost(); + // Get the focused RenderWidgetHost associated with |receiving_widget|. A + // RenderWidgetHostView, upon receiving a keyboard event, will pass its + // RenderWidgetHost to this function to determine who should ultimately + // consume the event. This facilitates keyboard event routing with + // out-of-process iframes, where multiple RenderWidgetHosts may be involved + // in rendering a page, yet keyboard events all arrive at the main frame's + // RenderWidgetHostView. When a main frame's RenderWidgetHost is passed in, + // the function returns the focused frame that should consume keyboard + // events. In all other cases, the function returns back |receiving_widget|. + virtual RenderWidgetHostImpl* GetFocusedRenderWidgetHost( + RenderWidgetHostImpl* receiving_widget); // Notification that the renderer has become unresponsive. The // delegate can use this notification to show a warning to the user.
diff --git a/content/browser/renderer_host/render_widget_host_view_android.cc b/content/browser/renderer_host/render_widget_host_view_android.cc index d825cf7c..5ca0e0f 100644 --- a/content/browser/renderer_host/render_widget_host_view_android.cc +++ b/content/browser/renderer_host/render_widget_host_view_android.cc
@@ -1693,12 +1693,8 @@ // If there are multiple widgets on the page (such as when there are // out-of-process iframes), pick the one that should process this event. - if (host_->delegate()) { - RenderWidgetHostImpl* focused_host = - host_->delegate()->GetFocusedRenderWidgetHost(); - if (focused_host) - target_host = focused_host; - } + if (host_->delegate()) + target_host = host_->delegate()->GetFocusedRenderWidgetHost(host_); target_host->ForwardKeyboardEvent(event); }
diff --git a/content/browser/renderer_host/render_widget_host_view_aura.cc b/content/browser/renderer_host/render_widget_host_view_aura.cc index 75169bf..6bd2b455 100644 --- a/content/browser/renderer_host/render_widget_host_view_aura.cc +++ b/content/browser/renderer_host/render_widget_host_view_aura.cc
@@ -2803,12 +2803,8 @@ // If there are multiple widgets on the page (such as when there are // out-of-process iframes), pick the one that should process this event. - if (host_->delegate()) { - RenderWidgetHostImpl* focused_host = - host_->delegate()->GetFocusedRenderWidgetHost(); - if (focused_host) - target_host = focused_host; - } + if (host_->delegate()) + target_host = host_->delegate()->GetFocusedRenderWidgetHost(host_); #if defined(OS_LINUX) && !defined(OS_CHROMEOS) ui::TextEditKeyBindingsDelegateAuraLinux* keybinding_delegate =
diff --git a/content/browser/renderer_host/render_widget_host_view_mac.mm b/content/browser/renderer_host/render_widget_host_view_mac.mm index 8f6dab7..b368661f 100644 --- a/content/browser/renderer_host/render_widget_host_view_mac.mm +++ b/content/browser/renderer_host/render_widget_host_view_mac.mm
@@ -2102,12 +2102,8 @@ // If there are multiple widgets on the page (such as when there are // out-of-process iframes), pick the one that should process this event. - if (widgetHost->delegate()) { - RenderWidgetHostImpl* focusedHost = - widgetHost->delegate()->GetFocusedRenderWidgetHost(); - if (focusedHost) - widgetHost = focusedHost; - } + if (widgetHost->delegate()) + widgetHost = widgetHost->delegate()->GetFocusedRenderWidgetHost(widgetHost); // Suppress the escape key up event if necessary. if (event.windowsKeyCode == ui::VKEY_ESCAPE && suppressNextEscapeKeyUp_) {
diff --git a/content/browser/service_worker/embedded_worker_instance.cc b/content/browser/service_worker/embedded_worker_instance.cc index 0089bf56..3499888 100644 --- a/content/browser/service_worker/embedded_worker_instance.cc +++ b/content/browser/service_worker/embedded_worker_instance.cc
@@ -13,6 +13,7 @@ #include "content/browser/service_worker/service_worker_context_core.h" #include "content/common/content_switches_internal.h" #include "content/common/mojo/service_registry_impl.h" +#include "content/common/routed_service_provider.mojom.h" #include "content/common/service_worker/embedded_worker_messages.h" #include "content/common/service_worker/embedded_worker_setup.mojom.h" #include "content/common/service_worker/service_worker_types.h" @@ -77,8 +78,8 @@ void SetupMojoOnUIThread( int process_id, int thread_id, - mojo::InterfaceRequest<mojo::ServiceProvider> services, - mojo::InterfacePtrInfo<mojo::ServiceProvider> exposed_services) { + mojo::InterfaceRequest<RoutedServiceProvider> services, + mojo::InterfacePtrInfo<RoutedServiceProvider> exposed_services) { RenderProcessHost* rph = RenderProcessHost::FromID(process_id); // |rph| or its ServiceRegistry may be NULL in unit tests. if (!rph || !rph->GetServiceRegistry()) @@ -386,10 +387,10 @@ thread_id_ = thread_id; FOR_EACH_OBSERVER(Listener, listener_list_, OnThreadStarted()); - mojo::ServiceProviderPtr exposed_services; + RoutedServiceProviderPtr exposed_services; service_registry_->Bind(GetProxy(&exposed_services)); - mojo::ServiceProviderPtr services; - mojo::InterfaceRequest<mojo::ServiceProvider> services_request = + RoutedServiceProviderPtr services; + mojo::InterfaceRequest<RoutedServiceProvider> services_request = GetProxy(&services); BrowserThread::PostTask( BrowserThread::UI, FROM_HERE,
diff --git a/content/browser/service_worker/service_worker_read_from_cache_job.cc b/content/browser/service_worker/service_worker_read_from_cache_job.cc index 6aa92af8..93579911 100644 --- a/content/browser/service_worker/service_worker_read_from_cache_job.cc +++ b/content/browser/service_worker/service_worker_read_from_cache_job.cc
@@ -41,9 +41,26 @@ } void ServiceWorkerReadFromCacheJob::Start() { - base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, base::Bind(&ServiceWorkerReadFromCacheJob::StartAsync, - weak_factory_.GetWeakPtr())); + TRACE_EVENT_ASYNC_BEGIN1("ServiceWorker", + "ServiceWorkerReadFromCacheJob::ReadInfo", this, + "URL", request_->url().spec()); + if (!context_) { + NotifyStartError( + net::URLRequestStatus(net::URLRequestStatus::FAILED, net::ERR_FAILED)); + return; + } + + // Create a response reader and start reading the headers, + // we'll continue when thats done. + if (is_main_script()) + version_->embedded_worker()->OnScriptReadStarted(); + reader_ = context_->storage()->CreateResponseReader(resource_id_); + http_info_io_buffer_ = new HttpResponseInfoIOBuffer; + reader_->ReadInfo( + http_info_io_buffer_.get(), + base::Bind(&ServiceWorkerReadFromCacheJob::OnReadInfoComplete, + weak_factory_.GetWeakPtr())); + SetStatus(net::URLRequestStatus(net::URLRequestStatus::IO_PENDING, 0)); } void ServiceWorkerReadFromCacheJob::Kill() { @@ -105,9 +122,11 @@ range_requested_ = ranges[0]; } -int ServiceWorkerReadFromCacheJob::ReadRawData(net::IOBuffer* buf, - int buf_size) { +bool ServiceWorkerReadFromCacheJob::ReadRawData(net::IOBuffer* buf, + int buf_size, + int* bytes_read) { DCHECK_NE(buf_size, 0); + DCHECK(bytes_read); DCHECK(!reader_->IsReadPending()); TRACE_EVENT_ASYNC_BEGIN1("ServiceWorker", "ServiceWorkerReadFromCacheJob::ReadRawData", @@ -116,31 +135,8 @@ reader_->ReadData(buf, buf_size, base::Bind(&ServiceWorkerReadFromCacheJob::OnReadComplete, weak_factory_.GetWeakPtr())); - return net::ERR_IO_PENDING; -} - -void ServiceWorkerReadFromCacheJob::StartAsync() { - TRACE_EVENT_ASYNC_BEGIN1("ServiceWorker", - "ServiceWorkerReadFromCacheJob::ReadInfo", this, - "URL", request_->url().spec()); - if (!context_) { - // NotifyStartError is not safe to call synchronously in Start. - NotifyStartError( - net::URLRequestStatus(net::URLRequestStatus::FAILED, net::ERR_FAILED)); - return; - } - - // Create a response reader and start reading the headers, - // we'll continue when thats done. - if (is_main_script()) - version_->embedded_worker()->OnScriptReadStarted(); - reader_ = context_->storage()->CreateResponseReader(resource_id_); - http_info_io_buffer_ = new HttpResponseInfoIOBuffer; - reader_->ReadInfo( - http_info_io_buffer_.get(), - base::Bind(&ServiceWorkerReadFromCacheJob::OnReadInfoComplete, - weak_factory_.GetWeakPtr())); SetStatus(net::URLRequestStatus(net::URLRequestStatus::IO_PENDING, 0)); + return false; } const net::HttpResponseInfo* ServiceWorkerReadFromCacheJob::http_info() const { @@ -158,8 +154,6 @@ ServiceWorkerMetrics::CountReadResponseResult( ServiceWorkerMetrics::READ_HEADERS_ERROR); Done(net::URLRequestStatus(net::URLRequestStatus::FAILED, result)); - NotifyStartError( - net::URLRequestStatus(net::URLRequestStatus::FAILED, result)); return; } DCHECK_GE(result, 0); @@ -213,22 +207,23 @@ } if (is_main_script()) version_->embedded_worker()->OnScriptReadFinished(); + NotifyDone(status); } void ServiceWorkerReadFromCacheJob::OnReadComplete(int result) { ServiceWorkerMetrics::ReadResponseResult check_result; - - if (result >= 0) { + if (result == 0) { check_result = ServiceWorkerMetrics::READ_OK; - if (result == 0) - Done(net::URLRequestStatus()); - } else { + Done(net::URLRequestStatus()); + } else if (result < 0) { check_result = ServiceWorkerMetrics::READ_DATA_ERROR; Done(net::URLRequestStatus(net::URLRequestStatus::FAILED, result)); + } else { + check_result = ServiceWorkerMetrics::READ_OK; + SetStatus(net::URLRequestStatus()); // Clear the IO_PENDING status } - ServiceWorkerMetrics::CountReadResponseResult(check_result); - ReadRawDataComplete(result); + NotifyReadComplete(result); TRACE_EVENT_ASYNC_END1("ServiceWorker", "ServiceWorkerReadFromCacheJob::ReadRawData", this,
diff --git a/content/browser/service_worker/service_worker_read_from_cache_job.h b/content/browser/service_worker/service_worker_read_from_cache_job.h index a62893d..fccde7a 100644 --- a/content/browser/service_worker/service_worker_read_from_cache_job.h +++ b/content/browser/service_worker/service_worker_read_from_cache_job.h
@@ -51,14 +51,13 @@ void GetResponseInfo(net::HttpResponseInfo* info) override; int GetResponseCode() const override; void SetExtraRequestHeaders(const net::HttpRequestHeaders& headers) override; - int ReadRawData(net::IOBuffer* buf, int buf_size) override; + bool ReadRawData(net::IOBuffer* buf, int buf_size, int* bytes_read) override; // Reader completion callbacks. void OnReadInfoComplete(int result); void OnReadComplete(int result); // Helpers - void StartAsync(); const net::HttpResponseInfo* http_info() const; bool is_range_request() const { return range_requested_.IsValid(); } void SetupRangeResponse(int response_data_size);
diff --git a/content/browser/service_worker/service_worker_url_request_job.cc b/content/browser/service_worker/service_worker_url_request_job.cc index 143e354..15c85a1 100644 --- a/content/browser/service_worker/service_worker_url_request_job.cc +++ b/content/browser/service_worker/service_worker_url_request_job.cc
@@ -203,44 +203,50 @@ byte_range_ = ranges[0]; } -int ServiceWorkerURLRequestJob::ReadRawData(net::IOBuffer* buf, int buf_size) { +bool ServiceWorkerURLRequestJob::ReadRawData(net::IOBuffer* buf, + int buf_size, + int* bytes_read) { DCHECK(buf); DCHECK_GE(buf_size, 0); + DCHECK(bytes_read); DCHECK(waiting_stream_url_.is_empty()); - - int bytes_read = 0; - if (stream_.get()) { - switch (stream_->ReadRawData(buf, buf_size, &bytes_read)) { + switch (stream_->ReadRawData(buf, buf_size, bytes_read)) { case Stream::STREAM_HAS_DATA: - DCHECK_GT(bytes_read, 0); - return bytes_read; + DCHECK_GT(*bytes_read, 0); + return true; case Stream::STREAM_COMPLETE: - DCHECK_EQ(0, bytes_read); + DCHECK(!*bytes_read); RecordResult(ServiceWorkerMetrics::REQUEST_JOB_STREAM_RESPONSE); - return 0; + return true; case Stream::STREAM_EMPTY: stream_pending_buffer_ = buf; stream_pending_buffer_size_ = buf_size; - return net::ERR_IO_PENDING; + SetStatus(net::URLRequestStatus(net::URLRequestStatus::IO_PENDING, 0)); + return false; case Stream::STREAM_ABORTED: // Handle this as connection reset. RecordResult(ServiceWorkerMetrics::REQUEST_JOB_ERROR_STREAM_ABORTED); - return net::ERR_CONNECTION_RESET; + NotifyDone(net::URLRequestStatus(net::URLRequestStatus::FAILED, + net::ERR_CONNECTION_RESET)); + return false; } NOTREACHED(); - return net::ERR_FAILED; + return false; } - if (!blob_request_) - return 0; - blob_request_->Read(buf, buf_size, &bytes_read); + if (!blob_request_) { + *bytes_read = 0; + return true; + } + blob_request_->Read(buf, buf_size, bytes_read); net::URLRequestStatus status = blob_request_->status(); - if (status.status() != net::URLRequestStatus::SUCCESS) - return status.error(); - if (bytes_read == 0) + SetStatus(status); + if (status.is_io_pending()) + return false; + if (status.is_success() && *bytes_read == 0) RecordResult(ServiceWorkerMetrics::REQUEST_JOB_BLOB_RESPONSE); - return bytes_read; + return status.is_success(); } // TODO(falken): Refactor Blob and Stream specific handling to separate classes. @@ -286,18 +292,29 @@ void ServiceWorkerURLRequestJob::OnReadCompleted(net::URLRequest* request, int bytes_read) { + SetStatus(request->status()); if (!request->status().is_success()) { RecordResult(ServiceWorkerMetrics::REQUEST_JOB_ERROR_BLOB_READ); - } else if (bytes_read == 0) { - RecordResult(ServiceWorkerMetrics::REQUEST_JOB_BLOB_RESPONSE); + NotifyDone(request->status()); + return; } - net::URLRequestStatus status = request->status(); - ReadRawDataComplete(status.is_success() ? bytes_read : status.error()); + + if (bytes_read == 0) { + // Protect because NotifyReadComplete() can destroy |this|. + scoped_refptr<ServiceWorkerURLRequestJob> protect(this); + RecordResult(ServiceWorkerMetrics::REQUEST_JOB_BLOB_RESPONSE); + NotifyReadComplete(bytes_read); + NotifyDone(request->status()); + return; + } + NotifyReadComplete(bytes_read); } // Overrides for Stream reading ----------------------------------------------- void ServiceWorkerURLRequestJob::OnDataAvailable(Stream* stream) { + // Clear the IO_PENDING status. + SetStatus(net::URLRequestStatus()); // Do nothing if stream_pending_buffer_ is empty, i.e. there's no ReadRawData // operation waiting for IO completion. if (!stream_pending_buffer_.get()) @@ -306,15 +323,15 @@ // stream_pending_buffer_ is set to the IOBuffer instance provided to // ReadRawData() by URLRequestJob. - int result = 0; + int bytes_read = 0; switch (stream_->ReadRawData(stream_pending_buffer_.get(), - stream_pending_buffer_size_, &result)) { + stream_pending_buffer_size_, &bytes_read)) { case Stream::STREAM_HAS_DATA: - DCHECK_GT(result, 0); + DCHECK_GT(bytes_read, 0); break; case Stream::STREAM_COMPLETE: // Calling NotifyReadComplete with 0 signals completion. - DCHECK(!result); + DCHECK(!bytes_read); RecordResult(ServiceWorkerMetrics::REQUEST_JOB_STREAM_RESPONSE); break; case Stream::STREAM_EMPTY: @@ -322,8 +339,9 @@ break; case Stream::STREAM_ABORTED: // Handle this as connection reset. - result = net::ERR_CONNECTION_RESET; RecordResult(ServiceWorkerMetrics::REQUEST_JOB_ERROR_STREAM_ABORTED); + NotifyDone(net::URLRequestStatus(net::URLRequestStatus::FAILED, + net::ERR_CONNECTION_RESET)); break; } @@ -331,7 +349,7 @@ // safe for the observer to read. stream_pending_buffer_ = nullptr; stream_pending_buffer_size_ = 0; - ReadRawDataComplete(result); + NotifyReadComplete(bytes_read); } void ServiceWorkerURLRequestJob::OnStreamRegistered(Stream* stream) { @@ -627,7 +645,7 @@ // error. if (response.status_code == 0) { RecordStatusZeroResponseError(response.error); - NotifyStartError( + NotifyDone( net::URLRequestStatus(net::URLRequestStatus::FAILED, net::ERR_FAILED)); return; }
diff --git a/content/browser/service_worker/service_worker_url_request_job.h b/content/browser/service_worker/service_worker_url_request_job.h index 2a50c94..4815c0b 100644 --- a/content/browser/service_worker/service_worker_url_request_job.h +++ b/content/browser/service_worker/service_worker_url_request_job.h
@@ -87,7 +87,7 @@ void GetLoadTimingInfo(net::LoadTimingInfo* load_timing_info) const override; int GetResponseCode() const override; void SetExtraRequestHeaders(const net::HttpRequestHeaders& headers) override; - int ReadRawData(net::IOBuffer* buf, int buf_size) override; + bool ReadRawData(net::IOBuffer* buf, int buf_size, int* bytes_read) override; // net::URLRequest::Delegate overrides that read the blob from the // ServiceWorkerFetchResponse.
diff --git a/content/browser/service_worker/service_worker_write_to_cache_job.cc b/content/browser/service_worker/service_worker_write_to_cache_job.cc index ba605c06..24bcd0f4 100644 --- a/content/browser/service_worker/service_worker_write_to_cache_job.cc +++ b/content/browser/service_worker/service_worker_write_to_cache_job.cc
@@ -7,7 +7,6 @@ #include "base/bind.h" #include "base/callback.h" #include "base/strings/stringprintf.h" -#include "base/thread_task_runner_handle.h" #include "base/trace_event/trace_event.h" #include "content/browser/service_worker/service_worker_cache_writer.h" #include "content/browser/service_worker/service_worker_context_core.h" @@ -48,7 +47,7 @@ // developers. // TODO(falken): Redesign this class so we don't have to fail at the network // stack layer just to cancel the update. -const net::Error kIdenticalScriptError = net::ERR_FILE_EXISTS; +const int kIdenticalScriptError = net::ERR_FILE_EXISTS; } // namespace @@ -80,18 +79,11 @@ } void ServiceWorkerWriteToCacheJob::Start() { - base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, base::Bind(&ServiceWorkerWriteToCacheJob::StartAsync, - weak_factory_.GetWeakPtr())); -} - -void ServiceWorkerWriteToCacheJob::StartAsync() { TRACE_EVENT_ASYNC_BEGIN1("ServiceWorker", "ServiceWorkerWriteToCacheJob::ExecutingJob", this, "URL", request_->url().spec()); if (!context_) { - // NotifyStartError is not safe to call synchronously in Start(). NotifyStartError( net::URLRequestStatus(net::URLRequestStatus::FAILED, net::ERR_FAILED)); return; @@ -116,9 +108,8 @@ has_been_killed_ = true; net_request_.reset(); if (did_notify_started_) { - net::Error error = NotifyFinishedCaching( - net::URLRequestStatus::FromError(net::ERR_ABORTED), kKilledError); - DCHECK_EQ(net::ERR_ABORTED, error); + NotifyFinishedCaching(net::URLRequestStatus::FromError(net::ERR_ABORTED), + kKilledError); } writer_.reset(); context_.reset(); @@ -165,20 +156,40 @@ net_request_->SetExtraRequestHeaders(headers); } -int ServiceWorkerWriteToCacheJob::ReadRawData(net::IOBuffer* buf, - int buf_size) { - int bytes_read = 0; - net::URLRequestStatus status = ReadNetData(buf, buf_size, &bytes_read); +bool ServiceWorkerWriteToCacheJob::ReadRawData(net::IOBuffer* buf, + int buf_size, + int* bytes_read) { + net::URLRequestStatus status = ReadNetData(buf, buf_size, bytes_read); + SetStatus(status); if (status.is_io_pending()) - return net::ERR_IO_PENDING; + return false; if (!status.is_success()) { - net::Error error = NotifyFinishedCaching(status, kFetchScriptError); - DCHECK_EQ(status.error(), error); - return error; + NotifyDoneHelper(status, kFetchScriptError); + return false; } - return HandleNetData(bytes_read); + HandleNetData(*bytes_read); + status = GetStatus(); + + // Synchronous EOFs that do not replace the incumbent entry are considered + // failures. Since normally the URLRequestJob's status would be set by + // ReadNetData or HandleNetData, this code has to manually fix up the status + // to match the failure this function is about to return. + if (status.status() == net::URLRequestStatus::SUCCESS && *bytes_read == 0 && + !cache_writer_->did_replace()) { + status = net::URLRequestStatus::FromError(kIdenticalScriptError); + } + + if (!status.is_success()) { + NotifyDoneHelper(status, ""); + return false; + } + + // Since URLRequestStatus::is_success() means "SUCCESS or IO_PENDING", but the + // contract of this function is "return true for synchronous successes only", + // it is important to test against SUCCESS explicitly here. + return status.status() == net::URLRequestStatus::SUCCESS; } const net::HttpResponseInfo* ServiceWorkerWriteToCacheJob::http_info() const { @@ -233,9 +244,9 @@ TRACE_EVENT0("ServiceWorker", "ServiceWorkerWriteToCacheJob::OnReceivedRedirect"); // Script resources can't redirect. - NotifyStartErrorHelper(net::URLRequestStatus(net::URLRequestStatus::FAILED, - net::ERR_UNSAFE_REDIRECT), - kRedirectError); + NotifyDoneHelper(net::URLRequestStatus(net::URLRequestStatus::FAILED, + net::ERR_UNSAFE_REDIRECT), + kRedirectError); } void ServiceWorkerWriteToCacheJob::OnAuthRequired( @@ -245,7 +256,7 @@ TRACE_EVENT0("ServiceWorker", "ServiceWorkerWriteToCacheJob::OnAuthRequired"); // TODO(michaeln): Pass this thru to our jobs client. - NotifyStartErrorHelper( + NotifyDoneHelper( net::URLRequestStatus(net::URLRequestStatus::FAILED, net::ERR_FAILED), kClientAuthenticationError); } @@ -258,7 +269,7 @@ "ServiceWorkerWriteToCacheJob::OnCertificateRequested"); // TODO(michaeln): Pass this thru to our jobs client. // see NotifyCertificateRequested. - NotifyStartErrorHelper( + NotifyDoneHelper( net::URLRequestStatus(net::URLRequestStatus::FAILED, net::ERR_FAILED), kClientAuthenticationError); } @@ -272,9 +283,9 @@ "ServiceWorkerWriteToCacheJob::OnSSLCertificateError"); // TODO(michaeln): Pass this thru to our jobs client, // see NotifySSLCertificateError. - NotifyStartErrorHelper(net::URLRequestStatus(net::URLRequestStatus::FAILED, - net::ERR_INSECURE_RESPONSE), - kSSLError); + NotifyDoneHelper(net::URLRequestStatus(net::URLRequestStatus::FAILED, + net::ERR_INSECURE_RESPONSE), + kSSLError); } void ServiceWorkerWriteToCacheJob::OnBeforeNetworkStart( @@ -290,15 +301,15 @@ net::URLRequest* request) { DCHECK_EQ(net_request_.get(), request); if (!request->status().is_success()) { - NotifyStartErrorHelper(request->status(), kFetchScriptError); + NotifyDoneHelper(request->status(), kFetchScriptError); return; } if (request->GetResponseCode() / 100 != 2) { std::string error_message = base::StringPrintf(kBadHTTPResponseError, request->GetResponseCode()); - NotifyStartErrorHelper(net::URLRequestStatus(net::URLRequestStatus::FAILED, - net::ERR_INVALID_RESPONSE), - error_message); + NotifyDoneHelper(net::URLRequestStatus(net::URLRequestStatus::FAILED, + net::ERR_INVALID_RESPONSE), + error_message); // TODO(michaeln): Instead of error'ing immediately, send the net // response to our consumer, just don't cache it? return; @@ -309,10 +320,9 @@ const net::HttpNetworkSession::Params* session_params = request->context()->GetNetworkSessionParams(); if (!session_params || !session_params->ignore_certificate_errors) { - NotifyStartErrorHelper( - net::URLRequestStatus(net::URLRequestStatus::FAILED, - net::ERR_INSECURE_RESPONSE), - kSSLError); + NotifyDoneHelper(net::URLRequestStatus(net::URLRequestStatus::FAILED, + net::ERR_INSECURE_RESPONSE), + kSSLError); return; } } @@ -327,10 +337,9 @@ mime_type.empty() ? kNoMIMEError : base::StringPrintf(kBadMIMEError, mime_type.c_str()); - NotifyStartErrorHelper( - net::URLRequestStatus(net::URLRequestStatus::FAILED, - net::ERR_INSECURE_RESPONSE), - error_message); + NotifyDoneHelper(net::URLRequestStatus(net::URLRequestStatus::FAILED, + net::ERR_INSECURE_RESPONSE), + error_message); return; } @@ -366,31 +375,52 @@ NotifyHeadersComplete(); } +void ServiceWorkerWriteToCacheJob::HandleNetData(int bytes_read) { + io_buffer_bytes_ = bytes_read; + net::Error error = cache_writer_->MaybeWriteData( + io_buffer_.get(), bytes_read, + base::Bind(&ServiceWorkerWriteToCacheJob::OnWriteDataComplete, + weak_factory_.GetWeakPtr())); + SetStatus(net::URLRequestStatus::FromError(error)); + + // In case of ERR_IO_PENDING, this logic is done in OnWriteDataComplete. + if (error != net::ERR_IO_PENDING && bytes_read == 0) { + NotifyFinishedCaching(net::URLRequestStatus::FromError(error), + std::string()); + } +} + void ServiceWorkerWriteToCacheJob::OnWriteDataComplete(net::Error error) { SetStatus(net::URLRequestStatus::FromError(error)); DCHECK_NE(net::ERR_IO_PENDING, error); - if (io_buffer_bytes_ == 0) - error = NotifyFinishedCaching(net::URLRequestStatus::FromError(error), ""); - ReadRawDataComplete(error == net::OK ? io_buffer_bytes_ : error); + if (io_buffer_bytes_ == 0) { + NotifyDoneHelper(net::URLRequestStatus::FromError(error), std::string()); + } + NotifyReadComplete(error == net::OK ? io_buffer_bytes_ : error); } void ServiceWorkerWriteToCacheJob::OnReadCompleted(net::URLRequest* request, int bytes_read) { DCHECK_EQ(net_request_.get(), request); - - int result; if (bytes_read < 0) { DCHECK(!request->status().is_success()); - result = NotifyFinishedCaching(request->status(), kFetchScriptError); - } else { - result = HandleNetData(bytes_read); - } - - // ReadRawDataComplete will be called in OnWriteDataComplete, so return early. - if (result == net::ERR_IO_PENDING) + NotifyDoneHelper(request->status(), kFetchScriptError); return; - - ReadRawDataComplete(result); + } + HandleNetData(bytes_read); + // HandleNetData can cause status of this job to change. If the status changes + // to IO_PENDING, that means HandleNetData has pending IO, and + // NotifyReadComplete will be called later by the appropriate callback. + if (!GetStatus().is_io_pending()) { + int result = GetStatus().status() == net::URLRequestStatus::SUCCESS + ? bytes_read + : GetStatus().error(); + // If bytes_read is 0, HandleNetData synchronously completed and this job is + // at EOF. + if (bytes_read == 0) + NotifyDoneHelper(GetStatus(), std::string()); + NotifyReadComplete(result); + } } bool ServiceWorkerWriteToCacheJob::CheckPathRestriction( @@ -404,57 +434,43 @@ if (!ServiceWorkerUtils::IsPathRestrictionSatisfied( version_->scope(), url_, has_header ? &service_worker_allowed : nullptr, &error_message)) { - NotifyStartErrorHelper(net::URLRequestStatus(net::URLRequestStatus::FAILED, - net::ERR_INSECURE_RESPONSE), - error_message); + NotifyDoneHelper(net::URLRequestStatus(net::URLRequestStatus::FAILED, + net::ERR_INSECURE_RESPONSE), + error_message); return false; } return true; } -int ServiceWorkerWriteToCacheJob::HandleNetData(int bytes_read) { - io_buffer_bytes_ = bytes_read; - net::Error error = cache_writer_->MaybeWriteData( - io_buffer_.get(), bytes_read, - base::Bind(&ServiceWorkerWriteToCacheJob::OnWriteDataComplete, - weak_factory_.GetWeakPtr())); - - // In case of ERR_IO_PENDING, this logic is done in OnWriteDataComplete. - if (error != net::ERR_IO_PENDING && bytes_read == 0) { - error = NotifyFinishedCaching(net::URLRequestStatus::FromError(error), - std::string()); - } - return error == net::OK ? bytes_read : error; -} - -void ServiceWorkerWriteToCacheJob::NotifyStartErrorHelper( +void ServiceWorkerWriteToCacheJob::NotifyDoneHelper( const net::URLRequestStatus& status, const std::string& status_message) { DCHECK(!status.is_io_pending()); - net::Error error = NotifyFinishedCaching(status, status_message); - // The special case mentioned in NotifyFinishedCaching about script being - // identical does not apply here, since the entire body needs to be read - // before this is relevant. - DCHECK_EQ(status.error(), error); + // Note that NotifyFinishedCaching has logic in it to detect the special case + // mentioned below as well. + NotifyFinishedCaching(status, status_message); net::URLRequestStatus reported_status = status; std::string reported_status_message = status_message; + // A strange special case: requests that successfully fetch the entire + // ServiceWorker and write it back, but which did not replace the incumbent + // script because the new script was identical, are considered to have failed. + if (status.is_success() && !cache_writer_->did_replace()) { + reported_status = net::URLRequestStatus::FromError(kIdenticalScriptError); + reported_status_message = ""; + } + SetStatus(reported_status); - NotifyStartError(reported_status); + NotifyDone(reported_status); } -net::Error ServiceWorkerWriteToCacheJob::NotifyFinishedCaching( +void ServiceWorkerWriteToCacheJob::NotifyFinishedCaching( net::URLRequestStatus status, const std::string& status_message) { - net::Error result = static_cast<net::Error>(status.error()); if (did_notify_finished_) - return result; - - int size = -1; - if (status.is_success()) - size = cache_writer_->bytes_written(); + return; // If all the calls to MaybeWriteHeaders/MaybeWriteData succeeded, but the // incumbent entry wasn't actually replaced because the new entry was @@ -462,18 +478,17 @@ // exists. if (status.status() == net::URLRequestStatus::SUCCESS && !cache_writer_->did_replace()) { - result = kIdenticalScriptError; - status = net::URLRequestStatus::FromError(result); + status = net::URLRequestStatus::FromError(kIdenticalScriptError); version_->SetStartWorkerStatusCode(SERVICE_WORKER_ERROR_EXISTS); - version_->script_cache_map()->NotifyFinishedCaching(url_, size, status, - std::string()); - } else { - version_->script_cache_map()->NotifyFinishedCaching(url_, size, status, - status_message); } + int size = -1; + if (status.is_success()) + size = cache_writer_->bytes_written(); + + version_->script_cache_map()->NotifyFinishedCaching(url_, size, status, + status_message); did_notify_finished_ = true; - return result; } scoped_ptr<ServiceWorkerResponseReader>
diff --git a/content/browser/service_worker/service_worker_write_to_cache_job.h b/content/browser/service_worker/service_worker_write_to_cache_job.h index e614912..92272399 100644 --- a/content/browser/service_worker/service_worker_write_to_cache_job.h +++ b/content/browser/service_worker/service_worker_write_to_cache_job.h
@@ -64,7 +64,6 @@ // net::URLRequestJob overrides void Start() override; - void StartAsync(); void Kill() override; net::LoadState GetLoadState() const override; bool GetCharset(std::string* charset) override; @@ -72,7 +71,7 @@ void GetResponseInfo(net::HttpResponseInfo* info) override; int GetResponseCode() const override; void SetExtraRequestHeaders(const net::HttpRequestHeaders& headers) override; - int ReadRawData(net::IOBuffer* buf, int buf_size) override; + bool ReadRawData(net::IOBuffer* buf, int buf_size, int* bytes_read) override; const net::HttpResponseInfo* http_info() const; @@ -110,22 +109,18 @@ bool CheckPathRestriction(net::URLRequest* request); // Writes network data back to the script cache if needed, and notifies the - // script cache of fetch completion at EOF. This function returns - // net::IO_PENDING if the IO is to be completed asynchronously, returns a - // negative number that represents a corresponding net error code (other than - // net::IO_PENDING) if an error occurred, or returns a non-negative number - // that represents the number of network bytes read. If the return value is - // non-negative, all of the data in |io_buffer_| has been written back to the - // script cache if necessary. - int HandleNetData(int bytes_read); + // script cache of fetch completion at EOF. This function might need to do + // asynchronous IO; if so, it signals this through setting the URLRequestJob's + // status to IO_PENDING. After this function returns, if the URLRequestJob + // isn't IO_PENDING, all of the data in |io_buffer_| has been written back to + // the script cache if necessary. + void HandleNetData(int bytes_read); - void NotifyStartErrorHelper(const net::URLRequestStatus& status, - const std::string& status_message); + void NotifyDoneHelper(const net::URLRequestStatus& status, + const std::string& status_message); - // Returns an error code that is passed in through |status| or a new one if an - // additional error is found. - net::Error NotifyFinishedCaching(net::URLRequestStatus status, - const std::string& status_message); + void NotifyFinishedCaching(net::URLRequestStatus status, + const std::string& status_message); scoped_ptr<ServiceWorkerResponseReader> CreateCacheResponseReader(); scoped_ptr<ServiceWorkerResponseWriter> CreateCacheResponseWriter(); @@ -145,7 +140,6 @@ bool has_been_killed_; bool did_notify_started_; bool did_notify_finished_; - base::WeakPtrFactory<ServiceWorkerWriteToCacheJob> weak_factory_; DISALLOW_COPY_AND_ASSIGN(ServiceWorkerWriteToCacheJob);
diff --git a/content/browser/site_per_process_browsertest.cc b/content/browser/site_per_process_browsertest.cc index 34b20cb..c9bf3efb 100644 --- a/content/browser/site_per_process_browsertest.cc +++ b/content/browser/site_per_process_browsertest.cc
@@ -2785,8 +2785,7 @@ " parent.frames['frame2'].location.href = 'data:text/html,foo');")); console_delegate->Wait(); - std::string frame_origin = - root->child_at(1)->current_replication_state().origin.Serialize(); + std::string frame_origin = root->child_at(1)->current_origin().Serialize(); EXPECT_EQ(frame_origin + "/", frame_url.GetOrigin().spec()); EXPECT_TRUE( base::MatchPattern(console_delegate->message(), "*" + frame_origin + "*")) @@ -3858,7 +3857,8 @@ // by one, checking the value of document.hasFocus() in all frames. For any // given focused frame, document.hasFocus() should return true for that frame // and all its ancestor frames. -IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, DocumentHasFocus) { +// Disabled due to flakes; see https://crbug.com/559273. +IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, DISABLED_DocumentHasFocus) { GURL main_url(embedded_test_server()->GetURL( "a.com", "/cross_site_iframe_factory.html?a(b(c),d)")); EXPECT_TRUE(NavigateToURL(shell(), main_url));
diff --git a/content/browser/streams/stream_url_request_job.cc b/content/browser/streams/stream_url_request_job.cc index e26fe35..0392d108f 100644 --- a/content/browser/streams/stream_url_request_job.cc +++ b/content/browser/streams/stream_url_request_job.cc
@@ -40,6 +40,8 @@ } void StreamURLRequestJob::OnDataAvailable(Stream* stream) { + // Clear the IO_PENDING status. + SetStatus(net::URLRequestStatus()); // Do nothing if pending_buffer_ is empty, i.e. there's no ReadRawData() // operation waiting for IO completion. if (!pending_buffer_.get()) @@ -48,22 +50,24 @@ // pending_buffer_ is set to the IOBuffer instance provided to ReadRawData() // by URLRequestJob. - int result = 0; + int bytes_read; switch (stream_->ReadRawData(pending_buffer_.get(), pending_buffer_size_, - &result)) { + &bytes_read)) { case Stream::STREAM_HAS_DATA: - DCHECK_GT(result, 0); + DCHECK_GT(bytes_read, 0); break; case Stream::STREAM_COMPLETE: - // Ensure ReadRawData gives net::OK. - DCHECK_EQ(net::OK, result); + // Ensure this. Calling NotifyReadComplete call with 0 signals + // completion. + bytes_read = 0; break; case Stream::STREAM_EMPTY: NOTREACHED(); break; case Stream::STREAM_ABORTED: // Handle this as connection reset. - result = net::ERR_CONNECTION_RESET; + NotifyDone(net::URLRequestStatus(net::URLRequestStatus::FAILED, + net::ERR_CONNECTION_RESET)); break; } @@ -72,9 +76,8 @@ pending_buffer_ = NULL; pending_buffer_size_ = 0; - if (result > 0) - total_bytes_read_ += result; - ReadRawDataComplete(result); + total_bytes_read_ += bytes_read; + NotifyReadComplete(bytes_read); } // net::URLRequestJob methods. @@ -91,40 +94,43 @@ ClearStream(); } -int StreamURLRequestJob::ReadRawData(net::IOBuffer* buf, int buf_size) { - // TODO(ellyjones): This is not right. The old code returned true here, but - // ReadRawData's old contract was to return true only for synchronous - // successes, which had the effect of treating all errors as synchronous EOFs. - // See https://crbug.com/508957 +bool StreamURLRequestJob::ReadRawData(net::IOBuffer* buf, + int buf_size, + int* bytes_read) { if (request_failed_) - return 0; + return true; DCHECK(buf); + DCHECK(bytes_read); int to_read = buf_size; if (max_range_ && to_read) { if (to_read + total_bytes_read_ > max_range_) to_read = max_range_ - total_bytes_read_; - if (to_read == 0) - return 0; + if (to_read <= 0) { + *bytes_read = 0; + return true; + } } - int bytes_read = 0; - switch (stream_->ReadRawData(buf, to_read, &bytes_read)) { + switch (stream_->ReadRawData(buf, to_read, bytes_read)) { case Stream::STREAM_HAS_DATA: case Stream::STREAM_COMPLETE: - total_bytes_read_ += bytes_read; - return bytes_read; + total_bytes_read_ += *bytes_read; + return true; case Stream::STREAM_EMPTY: pending_buffer_ = buf; pending_buffer_size_ = to_read; - return net::ERR_IO_PENDING; + SetStatus(net::URLRequestStatus(net::URLRequestStatus::IO_PENDING, 0)); + return false; case Stream::STREAM_ABORTED: // Handle this as connection reset. - return net::ERR_CONNECTION_RESET; + NotifyDone(net::URLRequestStatus(net::URLRequestStatus::FAILED, + net::ERR_CONNECTION_RESET)); + return false; } NOTREACHED(); - return net::ERR_FAILED; + return false; } bool StreamURLRequestJob::GetMimeType(std::string* mime_type) const { @@ -183,8 +189,13 @@ void StreamURLRequestJob::NotifyFailure(int error_code) { request_failed_ = true; - // This method can only be called before headers are set. - DCHECK(!headers_set_); + // If we already return the headers on success, we can't change the headers + // now. Instead, we just error out. + if (headers_set_) { + NotifyDone( + net::URLRequestStatus(net::URLRequestStatus::FAILED, error_code)); + return; + } // TODO(zork): Share these with BlobURLRequestJob. net::HttpStatusCode status_code = net::HTTP_INTERNAL_SERVER_ERROR;
diff --git a/content/browser/streams/stream_url_request_job.h b/content/browser/streams/stream_url_request_job.h index f22311d..05c9551 100644 --- a/content/browser/streams/stream_url_request_job.h +++ b/content/browser/streams/stream_url_request_job.h
@@ -29,7 +29,7 @@ // net::URLRequestJob methods. void Start() override; void Kill() override; - int ReadRawData(net::IOBuffer* buf, int buf_size) override; + bool ReadRawData(net::IOBuffer* buf, int buf_size, int* bytes_read) override; bool GetMimeType(std::string* mime_type) const override; void GetResponseInfo(net::HttpResponseInfo* info) override; int GetResponseCode() const override;
diff --git a/content/browser/tracing/tracing_controller_impl.cc b/content/browser/tracing/tracing_controller_impl.cc index 6ee0709..13a5333 100644 --- a/content/browser/tracing/tracing_controller_impl.cc +++ b/content/browser/tracing/tracing_controller_impl.cc
@@ -150,7 +150,7 @@ #if defined(OS_CHROMEOS) || defined(OS_WIN) is_system_tracing_(false), #endif - is_tracing_(TraceLog::GetInstance()->IsEnabled()), + is_tracing_(false), is_monitoring_(false), is_power_tracing_(false) { base::trace_event::MemoryDumpManager::GetInstance()->Initialize( @@ -235,6 +235,10 @@ #endif } + // TraceLog may have been enabled in startup tracing before threads are ready. + if (TraceLog::GetInstance()->IsEnabled()) + return true; + base::Closure on_start_tracing_done_callback = base::Bind(&TracingControllerImpl::OnStartTracingDone, base::Unretained(this),
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc index 4b2385f..273f864 100644 --- a/content/browser/web_contents/web_contents_impl.cc +++ b/content/browser/web_contents/web_contents_impl.cc
@@ -1606,13 +1606,19 @@ frame_tree_.ReplicatePageFocus(is_focused); } -RenderWidgetHostImpl* WebContentsImpl::GetFocusedRenderWidgetHost() { +RenderWidgetHostImpl* WebContentsImpl::GetFocusedRenderWidgetHost( + RenderWidgetHostImpl* receiving_widget) { if (!SiteIsolationPolicy::AreCrossProcessFramesPossible()) - return GetMainFrame()->GetRenderWidgetHost(); + return receiving_widget; + + // Events for widgets other than the main frame (e.g., popup menus) should be + // forwarded directly to the widget they arrived on. + if (receiving_widget != GetMainFrame()->GetRenderWidgetHost()) + return receiving_widget; FrameTreeNode* focused_frame = frame_tree_.GetFocusedFrame(); if (!focused_frame) - return GetMainFrame()->GetRenderWidgetHost(); + return receiving_widget; return RenderWidgetHostImpl::From( focused_frame->current_frame_host()->GetView()->GetRenderWidgetHost());
diff --git a/content/browser/web_contents/web_contents_impl.h b/content/browser/web_contents/web_contents_impl.h index f8d02c9..441cedc2 100644 --- a/content/browser/web_contents/web_contents_impl.h +++ b/content/browser/web_contents/web_contents_impl.h
@@ -588,7 +588,8 @@ override; RenderWidgetHostInputEventRouter* GetInputEventRouter() override; void ReplicatePageFocus(bool is_focused) override; - RenderWidgetHostImpl* GetFocusedRenderWidgetHost() override; + RenderWidgetHostImpl* GetFocusedRenderWidgetHost( + RenderWidgetHostImpl* receiving_widget) override; void RendererUnresponsive(RenderWidgetHostImpl* render_widget_host) override; void RendererResponsive(RenderWidgetHostImpl* render_widget_host) override; void RequestToLockMouse(RenderWidgetHostImpl* render_widget_host,
diff --git a/content/browser/webui/url_data_manager_backend.cc b/content/browser/webui/url_data_manager_backend.cc index 485aff6..44302df1 100644 --- a/content/browser/webui/url_data_manager_backend.cc +++ b/content/browser/webui/url_data_manager_backend.cc
@@ -119,7 +119,7 @@ // net::URLRequestJob implementation. void Start() override; void Kill() override; - int ReadRawData(net::IOBuffer* buf, int buf_size) override; + bool ReadRawData(net::IOBuffer* buf, int buf_size, int* bytes_read) override; bool GetMimeType(std::string* mime_type) const override; int GetResponseCode() const override; void GetResponseInfo(net::HttpResponseInfo* info) override; @@ -190,9 +190,8 @@ bool RequiresUnsafeEval() const; // Do the actual copy from data_ (the data we're serving) into |buf|. - // Separate from ReadRawData so we can handle async I/O. Returns the number of - // bytes read. - int CompleteRead(net::IOBuffer* buf, int buf_size); + // Separate from ReadRawData so we can handle async I/O. + void CompleteRead(net::IOBuffer* buf, int buf_size, int* bytes_read); // The actual data we're serving. NULL until it's been fetched. scoped_refptr<base::RefCountedMemory> data_; @@ -337,16 +336,22 @@ void URLRequestChromeJob::DataAvailable(base::RefCountedMemory* bytes) { TRACE_EVENT_ASYNC_END0("browser", "DataManager:Request", this); if (bytes) { + // The request completed, and we have all the data. + // Clear any IO pending status. + SetStatus(net::URLRequestStatus()); + data_ = bytes; + int bytes_read; if (pending_buf_.get()) { CHECK(pending_buf_->data()); - int result = CompleteRead(pending_buf_.get(), pending_buf_size_); + CompleteRead(pending_buf_.get(), pending_buf_size_, &bytes_read); pending_buf_ = NULL; - ReadRawDataComplete(result); + NotifyReadComplete(bytes_read); } } else { // The request failed. - ReadRawDataComplete(net::ERR_FAILED); + NotifyDone( + net::URLRequestStatus(net::URLRequestStatus::FAILED, net::ERR_FAILED)); } } @@ -354,21 +359,27 @@ return weak_factory_.GetWeakPtr(); } -int URLRequestChromeJob::ReadRawData(net::IOBuffer* buf, int buf_size) { +bool URLRequestChromeJob::ReadRawData(net::IOBuffer* buf, + int buf_size, + int* bytes_read) { if (!data_.get()) { + SetStatus(net::URLRequestStatus(net::URLRequestStatus::IO_PENDING, 0)); DCHECK(!pending_buf_.get()); CHECK(buf->data()); pending_buf_ = buf; pending_buf_size_ = buf_size; - return net::ERR_IO_PENDING; + return false; // Tell the caller we're still waiting for data. } // Otherwise, the data is available. - return CompleteRead(buf, buf_size); + CompleteRead(buf, buf_size, bytes_read); + return true; } -int URLRequestChromeJob::CompleteRead(net::IOBuffer* buf, int buf_size) { - int remaining = data_->size() - data_offset_; +void URLRequestChromeJob::CompleteRead(net::IOBuffer* buf, + int buf_size, + int* bytes_read) { + int remaining = static_cast<int>(data_->size()) - data_offset_; if (buf_size > remaining) buf_size = remaining; if (buf_size > 0) { @@ -380,7 +391,7 @@ memcpy(buf->data(), data_->front() + data_offset_, buf_size); data_offset_ += buf_size; } - return buf_size; + *bytes_read = buf_size; } void URLRequestChromeJob::CheckStoragePartitionMatches(
diff --git a/content/child/child_thread_impl.h b/content/child/child_thread_impl.h index 83d07be4..eb90f70 100644 --- a/content/child/child_thread_impl.h +++ b/content/child/child_thread_impl.h
@@ -181,7 +181,7 @@ static void ShutdownThread(); #endif - ServiceRegistry* service_registry() const { + ServiceRegistryImpl* service_registry() const { return mojo_application_->service_registry(); }
diff --git a/content/child/memory/child_memory_message_filter.cc b/content/child/memory/child_memory_message_filter.cc index 91e6849..c824c5a 100644 --- a/content/child/memory/child_memory_message_filter.cc +++ b/content/child/memory/child_memory_message_filter.cc
@@ -19,7 +19,6 @@ OnSetPressureNotificationsSuppressed) IPC_MESSAGE_HANDLER(MemoryMsg_SimulatePressureNotification, OnSimulatePressureNotification) - IPC_MESSAGE_HANDLER(MemoryMsg_PressureNotification, OnPressureNotification) IPC_MESSAGE_UNHANDLED(handled = false) IPC_END_MESSAGE_MAP() return handled;
diff --git a/content/child/mojo/mojo_application.cc b/content/child/mojo/mojo_application.cc index aa85a478..98313554 100644 --- a/content/child/mojo/mojo_application.cc +++ b/content/child/mojo/mojo_application.cc
@@ -8,6 +8,7 @@ #include "content/common/application_setup.mojom.h" #include "content/common/mojo/channel_init.h" #include "content/common/mojo/mojo_messages.h" +#include "content/common/routed_service_provider.mojom.h" #include "ipc/ipc_message.h" #include "mojo/public/cpp/bindings/interface_ptr.h" @@ -47,8 +48,8 @@ application_setup.Bind( mojo::InterfacePtrInfo<ApplicationSetup>(message_pipe.Pass(), 0u)); - mojo::ServiceProviderPtr services; - mojo::ServiceProviderPtr exposed_services; + RoutedServiceProviderPtr services; + RoutedServiceProviderPtr exposed_services; service_registry_.Bind(GetProxy(&exposed_services)); application_setup->ExchangeServiceProviders(GetProxy(&services), exposed_services.Pass());
diff --git a/content/child/mojo/mojo_application.h b/content/child/mojo/mojo_application.h index 5c207f2..6739b63 100644 --- a/content/child/mojo/mojo_application.h +++ b/content/child/mojo/mojo_application.h
@@ -31,7 +31,7 @@ bool OnMessageReceived(const IPC::Message& msg); - ServiceRegistry* service_registry() { return &service_registry_; } + ServiceRegistryImpl* service_registry() { return &service_registry_; } private: void OnActivate(const IPC::PlatformFileForTransit& file);
diff --git a/content/child/notifications/PRESUBMIT.py b/content/child/notifications/PRESUBMIT.py new file mode 100644 index 0000000..4fbc9a7 --- /dev/null +++ b/content/child/notifications/PRESUBMIT.py
@@ -0,0 +1,12 @@ +# Copyright 2015 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. + +"""Top-level presubmit script for notifications. + +See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts +for more details about the presubmit API built into depot_tools. +""" + +def CheckChangeOnUpload(input_api, output_api): + return input_api.canned_checks.CheckPatchFormatted(input_api, output_api)
diff --git a/content/child/notifications/notification_data_conversions.cc b/content/child/notifications/notification_data_conversions.cc index 9f05f0d..5c38ea3 100644 --- a/content/child/notifications/notification_data_conversions.cc +++ b/content/child/notifications/notification_data_conversions.cc
@@ -29,8 +29,7 @@ PlatformNotificationData::DIRECTION_RIGHT_TO_LEFT; break; case WebNotificationData::DirectionAuto: - platform_data.direction = - PlatformNotificationData::DIRECTION_AUTO; + platform_data.direction = PlatformNotificationData::DIRECTION_AUTO; break; }
diff --git a/content/child/notifications/notification_data_conversions.h b/content/child/notifications/notification_data_conversions.h index 24a8bab..445ff60 100644 --- a/content/child/notifications/notification_data_conversions.h +++ b/content/child/notifications/notification_data_conversions.h
@@ -12,8 +12,8 @@ namespace content { // Converts Blink WebNotificationData to PlatformNotificationData. -CONTENT_EXPORT PlatformNotificationData ToPlatformNotificationData( - const blink::WebNotificationData& web_data); +CONTENT_EXPORT PlatformNotificationData +ToPlatformNotificationData(const blink::WebNotificationData& web_data); // Converts PlatformNotificationData to Blink WebNotificationData. CONTENT_EXPORT blink::WebNotificationData ToWebNotificationData(
diff --git a/content/child/notifications/notification_data_conversions_unittest.cc b/content/child/notifications/notification_data_conversions_unittest.cc index 93e247d..4b3e918 100644 --- a/content/child/notifications/notification_data_conversions_unittest.cc +++ b/content/child/notifications/notification_data_conversions_unittest.cc
@@ -21,8 +21,8 @@ const char kNotificationBody[] = "Hello, world!"; const char kNotificationTag[] = "my_tag"; const char kNotificationIconUrl[] = "https://example.com/icon.png"; -const int kNotificationVibrationPattern[] = { 100, 200, 300 }; -const unsigned char kNotificationData[] = { 0xdf, 0xff, 0x0, 0x0, 0xff, 0xdf }; +const int kNotificationVibrationPattern[] = {100, 200, 300}; +const unsigned char kNotificationData[] = {0xdf, 0xff, 0x0, 0x0, 0xff, 0xdf}; const char kAction1Name[] = "btn1"; const char kAction1Title[] = "Button 1"; const char kAction2Name[] = "btn2"; @@ -40,11 +40,11 @@ kNotificationVibrationPattern, arraysize(kNotificationVibrationPattern)); web_data.silent = true; web_data.requireInteraction = true; - web_data.data = blink::WebVector<char>(kNotificationData, - arraysize(kNotificationData)); + web_data.data = + blink::WebVector<char>(kNotificationData, arraysize(kNotificationData)); - web_data.actions = blink::WebVector<blink::WebNotificationAction>( - static_cast<size_t>(2)); + web_data.actions = + blink::WebVector<blink::WebNotificationAction>(static_cast<size_t>(2)); web_data.actions[0].action = blink::WebString::fromUTF8(kAction1Name); web_data.actions[0].title = blink::WebString::fromUTF8(kAction1Title); web_data.actions[1].action = blink::WebString::fromUTF8(kAction2Name); @@ -62,7 +62,7 @@ EXPECT_TRUE(platform_data.require_interaction); EXPECT_THAT(platform_data.vibration_pattern, - testing::ElementsAreArray(kNotificationVibrationPattern)); + testing::ElementsAreArray(kNotificationVibrationPattern)); ASSERT_EQ(web_data.data.size(), platform_data.data.size()); for (size_t i = 0; i < web_data.data.size(); ++i) @@ -84,8 +84,7 @@ PlatformNotificationData platform_data; platform_data.title = base::ASCIIToUTF16(kNotificationTitle); - platform_data.direction = - PlatformNotificationData::DIRECTION_LEFT_TO_RIGHT; + platform_data.direction = PlatformNotificationData::DIRECTION_LEFT_TO_RIGHT; platform_data.lang = kNotificationLang; platform_data.body = base::ASCIIToUTF16(kNotificationBody); platform_data.tag = kNotificationTag;
diff --git a/content/child/notifications/notification_dispatcher.cc b/content/child/notifications/notification_dispatcher.cc index 1c6fb54..cb2f1ca 100644 --- a/content/child/notifications/notification_dispatcher.cc +++ b/content/child/notifications/notification_dispatcher.cc
@@ -12,8 +12,7 @@ NotificationDispatcher::NotificationDispatcher( ThreadSafeSender* thread_safe_sender) - : WorkerThreadMessageFilter(thread_safe_sender) { -} + : WorkerThreadMessageFilter(thread_safe_sender) {} NotificationDispatcher::~NotificationDispatcher() {} @@ -33,8 +32,8 @@ void NotificationDispatcher::OnFilteredMessageReceived( const IPC::Message& msg) { NotificationManager::ThreadSpecificInstance(thread_safe_sender(), - main_thread_task_runner(), - this)->OnMessageReceived(msg); + main_thread_task_runner(), this) + ->OnMessageReceived(msg); } bool NotificationDispatcher::GetWorkerThreadIdForMessage(
diff --git a/content/child/notifications/notification_image_loader.cc b/content/child/notifications/notification_image_loader.cc index 0478188d..4eed91f 100644 --- a/content/child/notifications/notification_image_loader.cc +++ b/content/child/notifications/notification_image_loader.cc
@@ -50,11 +50,10 @@ url_loader_->loadAsynchronously(request, this); } -void NotificationImageLoader::didReceiveData( - WebURLLoader* loader, - const char* data, - int data_length, - int encoded_data_length) { +void NotificationImageLoader::didReceiveData(WebURLLoader* loader, + const char* data, + int data_length, + int encoded_data_length) { DCHECK(!completed_); DCHECK_GT(data_length, 0);
diff --git a/content/child/notifications/notification_manager.cc b/content/child/notifications/notification_manager.cc index 920cba7..84b8214 100644 --- a/content/child/notifications/notification_manager.cc +++ b/content/child/notifications/notification_manager.cc
@@ -77,13 +77,10 @@ } pending_notifications_.FetchPageNotificationResources( - notification_data, - delegate, + notification_data, delegate, base::Bind(&NotificationManager::DisplayPageNotification, base::Unretained(this), // this owns |pending_notifications_| - origin, - notification_data, - delegate)); + origin, notification_data, delegate)); } void NotificationManager::showPersistent( @@ -94,7 +91,8 @@ DCHECK(service_worker_registration); int64_t service_worker_registration_id = static_cast<WebServiceWorkerRegistrationImpl*>( - service_worker_registration)->registration_id(); + service_worker_registration) + ->registration_id(); scoped_ptr<blink::WebNotificationShowCallbacks> owned_callbacks(callbacks); @@ -116,11 +114,9 @@ } if (notification_data.icon.isEmpty()) { - DisplayPersistentNotification(origin, - notification_data, + DisplayPersistentNotification(origin, notification_data, service_worker_registration_id, - owned_callbacks.Pass(), - SkBitmap()); + owned_callbacks.Pass(), SkBitmap()); return; } @@ -128,9 +124,7 @@ notification_data, base::Bind(&NotificationManager::DisplayPersistentNotification, base::Unretained(this), // this owns |pending_notifications_| - origin, - notification_data, - service_worker_registration_id, + origin, notification_data, service_worker_registration_id, base::Passed(&owned_callbacks))); } @@ -156,12 +150,9 @@ pending_get_notification_requests_.AddWithID(callbacks, request_id); - thread_safe_sender_->Send( - new PlatformNotificationHostMsg_GetNotifications( - request_id, - service_worker_registration_id, - origin, - base::UTF16ToUTF8(base::StringPiece16(filter_tag)))); + thread_safe_sender_->Send(new PlatformNotificationHostMsg_GetNotifications( + request_id, service_worker_registration_id, origin, + base::UTF16ToUTF8(base::StringPiece16(filter_tag)))); } void NotificationManager::close(blink::WebNotificationDelegate* delegate) {
diff --git a/content/child/notifications/notification_manager.h b/content/child/notifications/notification_manager.h index 721a1f8..bfdbd978 100644 --- a/content/child/notifications/notification_manager.h +++ b/content/child/notifications/notification_manager.h
@@ -56,8 +56,8 @@ void close(blink::WebNotificationDelegate* delegate) override; void closePersistent(const blink::WebSecurityOrigin& origin, int64_t persistent_notification_id) override; - void notifyDelegateDestroyed(blink::WebNotificationDelegate* delegate) - override; + void notifyDelegateDestroyed( + blink::WebNotificationDelegate* delegate) override; blink::WebNotificationPermission checkPermission( const blink::WebSecurityOrigin& origin) override; size_t maxActions() override; @@ -66,10 +66,9 @@ bool OnMessageReceived(const IPC::Message& message); private: - NotificationManager( - ThreadSafeSender* thread_safe_sender, - base::SingleThreadTaskRunner* main_thread_task_runner, - NotificationDispatcher* notification_dispatcher); + NotificationManager(ThreadSafeSender* thread_safe_sender, + base::SingleThreadTaskRunner* main_thread_task_runner, + NotificationDispatcher* notification_dispatcher); // IPC message handlers. void OnDidShow(int notification_id);
diff --git a/content/child/notifications/pending_notifications_tracker.cc b/content/child/notifications/pending_notifications_tracker.cc index a705ed0e..8cef12e 100644 --- a/content/child/notifications/pending_notifications_tracker.cc +++ b/content/child/notifications/pending_notifications_tracker.cc
@@ -19,8 +19,7 @@ PendingNotification( const scoped_refptr<NotificationImageLoader>& image_loader, const NotificationResourcesFetchedCallback& callback) - : image_loader(image_loader), - callback(callback) {} + : image_loader(image_loader), callback(callback) {} scoped_refptr<NotificationImageLoader> image_loader; NotificationResourcesFetchedCallback callback; @@ -28,8 +27,7 @@ PendingNotificationsTracker::PendingNotificationsTracker( scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner) - : main_thread_task_runner_(main_thread_task_runner), - weak_factory_(this) {} + : main_thread_task_runner_(main_thread_task_runner), weak_factory_(this) {} PendingNotificationsTracker::~PendingNotificationsTracker() {} @@ -38,12 +36,10 @@ blink::WebNotificationDelegate* delegate, const NotificationResourcesFetchedCallback& callback) { delegate_to_pending_id_map_[delegate] = FetchNotificationResources( - notification_data, - callback, + notification_data, callback, new NotificationImageLoader( - base::Bind( - &PendingNotificationsTracker::DidFetchPageNotification, - weak_factory_.GetWeakPtr(), delegate), + base::Bind(&PendingNotificationsTracker::DidFetchPageNotification, + weak_factory_.GetWeakPtr(), delegate), base::ThreadTaskRunnerHandle::Get())); } @@ -51,8 +47,7 @@ const blink::WebNotificationData& notification_data, const NotificationResourcesFetchedCallback& callback) { FetchNotificationResources( - notification_data, - callback, + notification_data, callback, new NotificationImageLoader( base::Bind( &PendingNotificationsTracker::DidFetchPersistentNotification, @@ -105,9 +100,9 @@ new PendingNotification(image_loader, callback)); main_thread_task_runner_->PostTask( - FROM_HERE, base::Bind(&NotificationImageLoader::StartOnMainThread, - image_loader, notification_id, - GURL(notification_data.icon.spec()))); + FROM_HERE, + base::Bind(&NotificationImageLoader::StartOnMainThread, image_loader, + notification_id, GURL(notification_data.icon.spec()))); return notification_id; }
diff --git a/content/child/push_messaging/PRESUBMIT.py b/content/child/push_messaging/PRESUBMIT.py new file mode 100644 index 0000000..aa4ae97d --- /dev/null +++ b/content/child/push_messaging/PRESUBMIT.py
@@ -0,0 +1,12 @@ +# Copyright 2015 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. + +"""Top-level presubmit script for Push Messaging. + +See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts +for more details about the presubmit API built into depot_tools. +""" + +def CheckChangeOnUpload(input_api, output_api): + return input_api.canned_checks.CheckPatchFormatted(input_api, output_api)
diff --git a/content/child/push_messaging/push_dispatcher.cc b/content/child/push_messaging/push_dispatcher.cc index 8d49c122..99130fc 100644 --- a/content/child/push_messaging/push_dispatcher.cc +++ b/content/child/push_messaging/push_dispatcher.cc
@@ -10,11 +10,9 @@ namespace content { PushDispatcher::PushDispatcher(ThreadSafeSender* thread_safe_sender) - : WorkerThreadMessageFilter(thread_safe_sender), next_request_id_(0) { -} + : WorkerThreadMessageFilter(thread_safe_sender), next_request_id_(0) {} -PushDispatcher::~PushDispatcher() { -} +PushDispatcher::~PushDispatcher() {} int PushDispatcher::GenerateRequestId(int thread_id) { base::AutoLock lock(request_id_map_lock_); @@ -29,8 +27,8 @@ // RenderFrameObserver. return msg.type() == PushMessagingMsg_SubscribeFromWorkerSuccess::ID || msg.type() == PushMessagingMsg_SubscribeFromWorkerError::ID || - msg.type() == PushMessagingMsg_GetRegistrationSuccess::ID || - msg.type() == PushMessagingMsg_GetRegistrationError::ID || + msg.type() == PushMessagingMsg_GetSubscriptionSuccess::ID || + msg.type() == PushMessagingMsg_GetSubscriptionError::ID || msg.type() == PushMessagingMsg_GetPermissionStatusSuccess::ID || msg.type() == PushMessagingMsg_GetPermissionStatusError::ID || msg.type() == PushMessagingMsg_UnsubscribeSuccess::ID || @@ -38,8 +36,9 @@ } void PushDispatcher::OnFilteredMessageReceived(const IPC::Message& msg) { - bool handled = PushProvider::ThreadSpecificInstance( - thread_safe_sender(), this)->OnMessageReceived(msg); + bool handled = + PushProvider::ThreadSpecificInstance(thread_safe_sender(), this) + ->OnMessageReceived(msg); DCHECK(handled); }
diff --git a/content/child/push_messaging/push_provider.cc b/content/child/push_messaging/push_provider.cc index ab33df4..f8e807de 100644 --- a/content/child/push_messaging/push_provider.cc +++ b/content/child/push_messaging/push_provider.cc
@@ -28,7 +28,8 @@ int64_t GetServiceWorkerRegistrationId( blink::WebServiceWorkerRegistration* service_worker_registration) { return static_cast<WebServiceWorkerRegistrationImpl*>( - service_worker_registration)->registration_id(); + service_worker_registration) + ->registration_id(); } } // namespace @@ -102,7 +103,7 @@ subscription_callbacks_.AddWithID(callbacks, request_id); int64_t service_worker_registration_id = GetServiceWorkerRegistrationId(service_worker_registration); - thread_safe_sender_->Send(new PushMessagingHostMsg_GetRegistration( + thread_safe_sender_->Send(new PushMessagingHostMsg_GetSubscription( request_id, service_worker_registration_id)); } @@ -129,12 +130,11 @@ OnSubscribeFromWorkerError); IPC_MESSAGE_HANDLER(PushMessagingMsg_UnsubscribeSuccess, OnUnsubscribeSuccess); - IPC_MESSAGE_HANDLER(PushMessagingMsg_UnsubscribeError, - OnUnsubscribeError); - IPC_MESSAGE_HANDLER(PushMessagingMsg_GetRegistrationSuccess, - OnGetRegistrationSuccess); - IPC_MESSAGE_HANDLER(PushMessagingMsg_GetRegistrationError, - OnGetRegistrationError); + IPC_MESSAGE_HANDLER(PushMessagingMsg_UnsubscribeError, OnUnsubscribeError); + IPC_MESSAGE_HANDLER(PushMessagingMsg_GetSubscriptionSuccess, + OnGetSubscriptionSuccess); + IPC_MESSAGE_HANDLER(PushMessagingMsg_GetSubscriptionError, + OnGetSubscriptionError); IPC_MESSAGE_HANDLER(PushMessagingMsg_GetPermissionStatusSuccess, OnGetPermissionStatusSuccess); IPC_MESSAGE_HANDLER(PushMessagingMsg_GetPermissionStatusError, @@ -148,14 +148,15 @@ void PushProvider::OnSubscribeFromWorkerSuccess( int request_id, const GURL& endpoint, - const std::vector<uint8_t>& p256dh) { + const std::vector<uint8_t>& p256dh, + const std::vector<uint8_t>& auth) { blink::WebPushSubscriptionCallbacks* callbacks = subscription_callbacks_.Lookup(request_id); if (!callbacks) return; callbacks->onSuccess(blink::adoptWebPtr( - new blink::WebPushSubscription(endpoint, p256dh))); + new blink::WebPushSubscription(endpoint, p256dh, auth))); subscription_callbacks_.Remove(request_id); } @@ -190,10 +191,9 @@ unsubscribe_callbacks_.Remove(request_id); } -void PushProvider::OnUnsubscribeError( - int request_id, - blink::WebPushError::ErrorType error_type, - const std::string& error_message) { +void PushProvider::OnUnsubscribeError(int request_id, + blink::WebPushError::ErrorType error_type, + const std::string& error_message) { blink::WebPushUnsubscribeCallbacks* callbacks = unsubscribe_callbacks_.Lookup(request_id); if (!callbacks) @@ -205,24 +205,24 @@ unsubscribe_callbacks_.Remove(request_id); } -void PushProvider::OnGetRegistrationSuccess( +void PushProvider::OnGetSubscriptionSuccess( int request_id, const GURL& endpoint, - const std::vector<uint8_t>& p256dh) { + const std::vector<uint8_t>& p256dh, + const std::vector<uint8_t>& auth) { blink::WebPushSubscriptionCallbacks* callbacks = subscription_callbacks_.Lookup(request_id); if (!callbacks) return; callbacks->onSuccess(blink::adoptWebPtr( - new blink::WebPushSubscription(endpoint, p256dh))); + new blink::WebPushSubscription(endpoint, p256dh, auth))); subscription_callbacks_.Remove(request_id); } -void PushProvider::OnGetRegistrationError( - int request_id, - PushGetRegistrationStatus status) { +void PushProvider::OnGetSubscriptionError(int request_id, + PushGetRegistrationStatus status) { blink::WebPushSubscriptionCallbacks* callbacks = subscription_callbacks_.Lookup(request_id); if (!callbacks) @@ -262,8 +262,8 @@ "supported."; } - callbacks->onError(blink::WebPushError( - error, blink::WebString::fromUTF8(error_message))); + callbacks->onError( + blink::WebPushError(error, blink::WebString::fromUTF8(error_message))); permission_status_callbacks_.Remove(request_id); }
diff --git a/content/child/push_messaging/push_provider.h b/content/child/push_messaging/push_provider.h index c01796b..002fe1b 100644 --- a/content/child/push_messaging/push_provider.h +++ b/content/child/push_messaging/push_provider.h
@@ -67,17 +67,19 @@ // IPC message handlers. void OnSubscribeFromWorkerSuccess(int request_id, const GURL& endpoint, - const std::vector<uint8_t>& p256dh); + const std::vector<uint8_t>& p256dh, + const std::vector<uint8_t>& auth); void OnSubscribeFromWorkerError(int request_id, PushRegistrationStatus status); void OnUnsubscribeSuccess(int request_id, bool did_unsubscribe); void OnUnsubscribeError(int request_id, blink::WebPushError::ErrorType error_type, const std::string& error_message); - void OnGetRegistrationSuccess(int request_id, + void OnGetSubscriptionSuccess(int request_id, const GURL& endpoint, - const std::vector<uint8_t>& p256dh); - void OnGetRegistrationError(int request_id, PushGetRegistrationStatus status); + const std::vector<uint8_t>& p256dh, + const std::vector<uint8_t>& auth); + void OnGetSubscriptionError(int request_id, PushGetRegistrationStatus status); void OnGetPermissionStatusSuccess(int request_id, blink::WebPushPermissionStatus status); void OnGetPermissionStatusError(int request_id,
diff --git a/content/child/shared_worker_devtools_agent.cc b/content/child/shared_worker_devtools_agent.cc index 26a51ed..9b1996f 100644 --- a/content/child/shared_worker_devtools_agent.cc +++ b/content/child/shared_worker_devtools_agent.cc
@@ -44,6 +44,7 @@ } void SharedWorkerDevToolsAgent::SendDevToolsMessage( + int session_id, int call_id, const blink::WebString& msg, const blink::WebString& state) { @@ -55,6 +56,7 @@ if (message.length() < kMaxMessageChunkSize) { chunk.data.swap(message); + chunk.session_id = session_id; chunk.call_id = call_id; chunk.post_state = post_state; chunk.is_last = true; @@ -65,6 +67,7 @@ for (size_t pos = 0; pos < message.length(); pos += kMaxMessageChunkSize) { chunk.is_last = pos + kMaxMessageChunkSize >= message.length(); + chunk.session_id = chunk.is_last ? session_id : 0; chunk.call_id = chunk.is_last ? call_id : 0; chunk.post_state = chunk.is_last ? post_state : std::string(); chunk.data = message.substr(pos, kMaxMessageChunkSize); @@ -75,13 +78,15 @@ } } -void SharedWorkerDevToolsAgent::OnAttach(const std::string& host_id) { - webworker_->attachDevTools(WebString::fromUTF8(host_id)); +void SharedWorkerDevToolsAgent::OnAttach(const std::string& host_id, + int session_id) { + webworker_->attachDevTools(WebString::fromUTF8(host_id), session_id); } void SharedWorkerDevToolsAgent::OnReattach(const std::string& host_id, + int session_id, const std::string& state) { - webworker_->reattachDevTools(WebString::fromUTF8(host_id), + webworker_->reattachDevTools(WebString::fromUTF8(host_id), session_id, WebString::fromUTF8(state)); } @@ -90,8 +95,9 @@ } void SharedWorkerDevToolsAgent::OnDispatchOnInspectorBackend( + int session_id, const std::string& message) { - webworker_->dispatchDevToolsMessage(WebString::fromUTF8(message)); + webworker_->dispatchDevToolsMessage(session_id, WebString::fromUTF8(message)); } bool SharedWorkerDevToolsAgent::Send(IPC::Message* message) {
diff --git a/content/child/shared_worker_devtools_agent.h b/content/child/shared_worker_devtools_agent.h index 2d6a732a..19b1ea9 100644 --- a/content/child/shared_worker_devtools_agent.h +++ b/content/child/shared_worker_devtools_agent.h
@@ -27,15 +27,18 @@ // Called on the Worker thread. bool OnMessageReceived(const IPC::Message& message); - void SendDevToolsMessage(int call_id, + void SendDevToolsMessage(int session_id, + int call_id, const blink::WebString& message, const blink::WebString& post_state); private: - void OnAttach(const std::string& host_id); - void OnReattach(const std::string& host_id, const std::string& state); + void OnAttach(const std::string& host_id, int session_id); + void OnReattach(const std::string& host_id, + int session_id, + const std::string& state); void OnDetach(); - void OnDispatchOnInspectorBackend(const std::string& message); + void OnDispatchOnInspectorBackend(int session_id, const std::string& message); bool Send(IPC::Message* message); const int route_id_;
diff --git a/content/common/BUILD.gn b/content/common/BUILD.gn index fef64c5..339032d 100644 --- a/content/common/BUILD.gn +++ b/content/common/BUILD.gn
@@ -165,6 +165,7 @@ "//net", "//skia", "//third_party/icu", + "//third_party/libjingle", "//ui/accessibility", "//ui/base", "//ui/base/ime", @@ -174,10 +175,11 @@ "//ui/gfx/ipc", "//ui/shell_dialogs", "//url", - "//third_party/libjingle", ] if (!is_ios) { + public_deps += [ ":mojo_bindings" ] + deps += [ "//cc", "//device/bluetooth", @@ -195,8 +197,8 @@ "//gpu/ipc", "//gpu/skia_bindings", "//media", - "//media/midi", "//media:shared_memory_support", + "//media/midi", "//mojo/application/public/interfaces", "//mojo/common:common_base", "//mojo/environment:chromium", @@ -205,7 +207,6 @@ "//third_party/WebKit/public:blink", "//third_party/mojo/src/mojo/edk/system", "//ui/gl", - ":mojo_bindings", ] } @@ -238,8 +239,8 @@ deps += [ ":libvt_generate_stubs", - "//content/app/resources", "//content:resources", + "//content/app/resources", "//third_party/WebKit/public:image_resources", "//third_party/WebKit/public:resources", "//ui/accelerated_widget_mac", @@ -262,8 +263,8 @@ ] deps += [ - "//content/public/android:jni", "//content/public/android:common_aidl", + "//content/public/android:jni", ] libs += [ "android" ] @@ -533,7 +534,7 @@ "permission_service.mojom", "presentation/presentation_service.mojom", "process_control.mojom", - "render_frame_setup.mojom", + "routed_service_provider.mojom", "service_port_service.mojom", "service_worker/embedded_worker_setup.mojom", "vr_service.mojom",
diff --git a/content/common/application_setup.mojom b/content/common/application_setup.mojom index 1005663..630a4dfe 100644 --- a/content/common/application_setup.mojom +++ b/content/common/application_setup.mojom
@@ -4,9 +4,9 @@ module content; -import "mojo/application/public/interfaces/service_provider.mojom"; +import "content/common/routed_service_provider.mojom"; interface ApplicationSetup { - ExchangeServiceProviders(mojo.ServiceProvider& services, - mojo.ServiceProvider exposed_services); + ExchangeServiceProviders(RoutedServiceProvider& services, + RoutedServiceProvider exposed_services); };
diff --git a/content/common/cc_messages.cc b/content/common/cc_messages.cc index 34b5614d..992ff8a 100644 --- a/content/common/cc_messages.cc +++ b/content/common/cc_messages.cc
@@ -300,7 +300,6 @@ WriteParam(m, p.damage_rect); WriteParam(m, p.transform_to_root_target); WriteParam(m, p.has_transparent_background); - WriteParam(m, p.referenced_surfaces); WriteParam(m, p.quad_list.size()); cc::SharedQuadStateList::ConstIterator shared_quad_state_iter = @@ -384,9 +383,6 @@ // The largest quad type, verified by a unit test. to_reserve += p.quad_list.size() * cc::LargestDrawQuadSize(); - - // The actual list of referenced surfaces. - to_reserve += p.referenced_surfaces.size() * sizeof(cc::SurfaceId); return to_reserve; } @@ -408,14 +404,12 @@ gfx::Rect damage_rect; gfx::Transform transform_to_root_target; bool has_transparent_background; - std::vector<cc::SurfaceId> referenced_surfaces; size_t quad_list_size; if (!ReadParam(m, iter, &id) || !ReadParam(m, iter, &output_rect) || !ReadParam(m, iter, &damage_rect) || !ReadParam(m, iter, &transform_to_root_target) || !ReadParam(m, iter, &has_transparent_background) || - !ReadParam(m, iter, &referenced_surfaces) || !ReadParam(m, iter, &quad_list_size)) return false; @@ -424,7 +418,6 @@ damage_rect, transform_to_root_target, has_transparent_background); - p->referenced_surfaces.swap(referenced_surfaces); for (size_t i = 0; i < quad_list_size; ++i) { cc::DrawQuad::Material material; @@ -513,8 +506,6 @@ l->append(", "); LogParam(p.has_transparent_background, l); l->append(", "); - LogParam(p.referenced_surfaces, l); - l->append(", "); l->append("["); for (const auto& shared_quad_state : p.shared_quad_state_list) {
diff --git a/content/common/cc_messages.h b/content/common/cc_messages.h index f31964b..9f2e84ec 100644 --- a/content/common/cc_messages.h +++ b/content/common/cc_messages.h
@@ -318,6 +318,7 @@ IPC_STRUCT_TRAITS_MEMBER(selection) IPC_STRUCT_TRAITS_MEMBER(latency_info) IPC_STRUCT_TRAITS_MEMBER(satisfies_sequences) + IPC_STRUCT_TRAITS_MEMBER(referenced_surfaces) IPC_STRUCT_TRAITS_END() IPC_STRUCT_TRAITS_BEGIN(cc::GLFrameData)
diff --git a/content/common/cc_messages_unittest.cc b/content/common/cc_messages_unittest.cc index a94cd4a8e..87073960 100644 --- a/content/common/cc_messages_unittest.cc +++ b/content/common/cc_messages_unittest.cc
@@ -52,7 +52,6 @@ EXPECT_EQ(a->damage_rect.ToString(), b->damage_rect.ToString()); EXPECT_EQ(a->transform_to_root_target, b->transform_to_root_target); EXPECT_EQ(a->has_transparent_background, b->has_transparent_background); - EXPECT_EQ(a->referenced_surfaces, b->referenced_surfaces); } void Compare(const SharedQuadState* a, const SharedQuadState* b) { @@ -399,8 +398,6 @@ arbitrary_surface_id); pass_cmp->CopyFromAndAppendDrawQuad(surface_in, surface_in->shared_quad_state); - pass_in->referenced_surfaces.push_back(arbitrary_surface_id); - pass_cmp->referenced_surfaces.push_back(arbitrary_surface_id); TextureDrawQuad* texture_in = pass_in->CreateAndAppendDrawQuad<TextureDrawQuad>();
diff --git a/content/common/devtools_messages.h b/content/common/devtools_messages.h index f786a651..7edc617d 100644 --- a/content/common/devtools_messages.h +++ b/content/common/devtools_messages.h
@@ -58,12 +58,14 @@ // Agent -> Client message chunk. // |is_first| marks the first chunk, comes with the |message_size| for // total message size. -// |is_last| marks the last chunk. |call_id| and |post_state| are optional -// parameters passed with the last chunk of the protocol response. +// |is_last| marks the last chunk. |call_id|, |session_id| and |post_state| +// are optional parameters passed with the last chunk of the protocol +// response. IPC_STRUCT_BEGIN(DevToolsMessageChunk) IPC_STRUCT_MEMBER(bool, is_first) IPC_STRUCT_MEMBER(bool, is_last) IPC_STRUCT_MEMBER(int, message_size) + IPC_STRUCT_MEMBER(int, session_id) IPC_STRUCT_MEMBER(int, call_id) IPC_STRUCT_MEMBER(std::string, data) IPC_STRUCT_MEMBER(std::string, post_state) @@ -77,20 +79,23 @@ // These are messages sent from DevToolsClient to DevToolsAgent through the // browser. // Tells agent that there is a client host connected to it. -IPC_MESSAGE_ROUTED1(DevToolsAgentMsg_Attach, - std::string /* host_id */) +IPC_MESSAGE_ROUTED2(DevToolsAgentMsg_Attach, + std::string /* host_id */, + int /* session_id */) // Tells agent that a client host was disconnected from another agent and // connected to this one. -IPC_MESSAGE_ROUTED2(DevToolsAgentMsg_Reattach, +IPC_MESSAGE_ROUTED3(DevToolsAgentMsg_Reattach, std::string /* host_id */, + int /* session_id */, std::string /* agent_state */) // Tells agent that there is no longer a client host connected to it. IPC_MESSAGE_ROUTED0(DevToolsAgentMsg_Detach) // WebKit-level transport. -IPC_MESSAGE_ROUTED1(DevToolsAgentMsg_DispatchOnInspectorBackend, +IPC_MESSAGE_ROUTED2(DevToolsAgentMsg_DispatchOnInspectorBackend, + int /* session_id */, std::string /* message */) // Inspect element with the given coordinates.
diff --git a/content/common/gpu/client/context_provider_command_buffer.cc b/content/common/gpu/client/context_provider_command_buffer.cc index ba1baa9..7259ea1 100644 --- a/content/common/gpu/client/context_provider_command_buffer.cc +++ b/content/common/gpu/client/context_provider_command_buffer.cc
@@ -68,7 +68,7 @@ CommandBufferProxyImpl* ContextProviderCommandBuffer::GetCommandBufferProxy() { - return WebContext3D()->GetCommandBufferProxy(); + return WebContext3DNoChecks()->GetCommandBufferProxy(); } WebGraphicsContext3DCommandBufferImpl* @@ -119,11 +119,11 @@ gpu::gles2::GLES2Interface* ContextProviderCommandBuffer::ContextGL() { DCHECK(lost_context_callback_proxy_); // Is bound to thread. - return WebContext3DNoChecks()->GetImplementation(); + return WebContext3D()->GetImplementation(); } gpu::ContextSupport* ContextProviderCommandBuffer::ContextSupport() { - return WebContext3D()->GetContextSupport(); + return WebContext3DNoChecks()->GetContextSupport(); } class GrContext* ContextProviderCommandBuffer::GrContext() {
diff --git a/content/common/gpu/media/video_encode_accelerator_unittest.cc b/content/common/gpu/media/video_encode_accelerator_unittest.cc index 0f80d07..b0f8972 100644 --- a/content/common/gpu/media/video_encode_accelerator_unittest.cc +++ b/content/common/gpu/media/video_encode_accelerator_unittest.cc
@@ -639,8 +639,7 @@ const base::Closure& flush_complete_cb, const base::Closure& decode_error_cb) : profile_(profile), - decoder_(new media::FFmpegVideoDecoder(base::MessageLoop::current() - ->task_runner())), + decoder_(new media::FFmpegVideoDecoder()), decode_cb_(base::Bind(&VideoFrameQualityValidator::DecodeDone, base::Unretained(this))), eos_decode_cb_(base::Bind(&VideoFrameQualityValidator::FlushDone,
diff --git a/content/common/mojo/service_registry_for_route.cc b/content/common/mojo/service_registry_for_route.cc new file mode 100644 index 0000000..d4cbdc9 --- /dev/null +++ b/content/common/mojo/service_registry_for_route.cc
@@ -0,0 +1,49 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "content/common/mojo/service_registry_for_route.h" + +#include <utility> + +#include "content/common/mojo/service_registry_impl.h" + +namespace content { + +ServiceRegistryForRoute::~ServiceRegistryForRoute() { + if (!destruction_callback_.is_null()) + destruction_callback_.Run(); +} + +void ServiceRegistryForRoute::Add( + const std::string& service_name, + const base::Callback<void(mojo::ScopedMessagePipeHandle)> + service_factory) { + if (!registry_) + return; + registry_->AddRouted(routing_id_, service_name, service_factory); +} + +void ServiceRegistryForRoute::Remove(const std::string& service_name) { + if (!registry_) + return; + registry_->RemoveRouted(routing_id_, service_name); +} + +void ServiceRegistryForRoute::Connect(const base::StringPiece& name, + mojo::ScopedMessagePipeHandle handle) { + if (!registry_) + return; + registry_->ConnectRouted(routing_id_, name.as_string(), std::move(handle)); +} + +ServiceRegistryForRoute::ServiceRegistryForRoute( + base::WeakPtr<ServiceRegistryImpl> registry, + int routing_id, + const base::Closure& destruction_callback) + : registry_(registry), + routing_id_(routing_id), + destruction_callback_(destruction_callback) { +} + +} // namespace content
diff --git a/content/common/mojo/service_registry_for_route.h b/content/common/mojo/service_registry_for_route.h new file mode 100644 index 0000000..5fa71a7 --- /dev/null +++ b/content/common/mojo/service_registry_for_route.h
@@ -0,0 +1,49 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CONTENT_COMMON_MOJO_SERVICE_REGISTRY_FOR_ROUTE_H_ +#define CONTENT_COMMON_MOJO_SERVICE_REGISTRY_FOR_ROUTE_H_ + +#include "base/callback.h" +#include "base/macros.h" +#include "content/common/content_export.h" +#include "content/public/common/service_registry.h" + +namespace content { + +class ServiceRegistryImpl; + +// A ServiceRegistry which associates all service exposure and connection with a +// single route on an underlying ServiceRegistryImpl. +class CONTENT_EXPORT ServiceRegistryForRoute : public ServiceRegistry { + public: + ~ServiceRegistryForRoute() override; + + // ServiceRegistry: + void Add( + const std::string& service_name, + const base::Callback<void(mojo::ScopedMessagePipeHandle)> + service_factory) override; + void Remove(const std::string& service_name) override; + void Connect(const base::StringPiece& name, + mojo::ScopedMessagePipeHandle handle) override; + + private: + friend class ServiceRegistryImpl; + + ServiceRegistryForRoute( + base::WeakPtr<ServiceRegistryImpl> registry, + int routing_id, + const base::Closure& destruction_callback); + + const base::WeakPtr<ServiceRegistryImpl> registry_; + const int routing_id_; + const base::Closure destruction_callback_; + + DISALLOW_COPY_AND_ASSIGN(ServiceRegistryForRoute); +}; + +} // namespace content + +#endif // CONTENT_COMMON_MOJO_SERVICE_REGISTRY_FOR_ROUTE_H_
diff --git a/content/common/mojo/service_registry_impl.cc b/content/common/mojo/service_registry_impl.cc index c1df33a..99142b5 100644 --- a/content/common/mojo/service_registry_impl.cc +++ b/content/common/mojo/service_registry_impl.cc
@@ -4,74 +4,102 @@ #include "content/common/mojo/service_registry_impl.h" +#include <algorithm> +#include <utility> + +#include "base/macros.h" #include "mojo/common/common_type_converters.h" namespace content { +class ServiceRegistryImpl::ConnectionRequest { + public: + ConnectionRequest(const std::string& service_name, + mojo::ScopedMessagePipeHandle pipe) + : service_name_(service_name), pipe_(std::move(pipe)) { + } + ~ConnectionRequest() {} + + const std::string& service_name() const { return service_name_; } + mojo::ScopedMessagePipeHandle PassMessagePipe() { return std::move(pipe_); } + + private: + const std::string service_name_; + mojo::ScopedMessagePipeHandle pipe_; + + DISALLOW_COPY_AND_ASSIGN(ConnectionRequest); +}; + ServiceRegistryImpl::ServiceRegistryImpl() : binding_(this), weak_factory_(this) { - binding_.set_connection_error_handler( - base::Bind(&ServiceRegistryImpl::OnConnectionError, - base::Unretained(this))); + binding_.set_connection_error_handler([this]() { binding_.Close(); }); } ServiceRegistryImpl::~ServiceRegistryImpl() { - while (!pending_connects_.empty()) { - mojo::CloseRaw(pending_connects_.front().second); - pending_connects_.pop(); - } } void ServiceRegistryImpl::Bind( - mojo::InterfaceRequest<mojo::ServiceProvider> request) { - binding_.Bind(request.Pass()); + mojo::InterfaceRequest<RoutedServiceProvider> request) { + binding_.Bind(std::move(request)); } void ServiceRegistryImpl::BindRemoteServiceProvider( - mojo::ServiceProviderPtr service_provider) { + RoutedServiceProviderPtr service_provider) { CHECK(!remote_provider_); - remote_provider_ = service_provider.Pass(); - while (!pending_connects_.empty()) { + remote_provider_ = std::move(service_provider); + + ConnectionRequests requests; + std::swap(requests, pending_outgoing_connects_); + for (auto& request : requests) { remote_provider_->ConnectToService( - mojo::String::From(pending_connects_.front().first), - mojo::ScopedMessagePipeHandle(pending_connects_.front().second)); - pending_connects_.pop(); + request->service_name(), request->PassMessagePipe()); + } + + RoutedConnectionRequestMap request_map; + std::swap(request_map, pending_routed_outgoing_connects_); + for (auto& entry : request_map) { + const int route_id = entry.first; + for (auto& request : entry.second) { + remote_provider_->ConnectToServiceRouted( + route_id, request->service_name(), request->PassMessagePipe()); + } } } -void ServiceRegistryImpl::AddService( +scoped_ptr<ServiceRegistryForRoute> +ServiceRegistryImpl::CreateServiceRegistryForRoute(int route_id) { + // There should be no previously registered factories for this route ID. + DCHECK(routed_service_factories_.find(route_id) == + routed_service_factories_.end()); + return make_scoped_ptr(new ServiceRegistryForRoute( + weak_factory_.GetWeakPtr(), route_id, + base::Bind(&ServiceRegistryImpl::CloseRoute, + weak_factory_.GetWeakPtr(), route_id))); +} + +void ServiceRegistryImpl::Add( const std::string& service_name, const base::Callback<void(mojo::ScopedMessagePipeHandle)> service_factory) { service_factories_[service_name] = service_factory; } -void ServiceRegistryImpl::RemoveService(const std::string& service_name) { +void ServiceRegistryImpl::Remove(const std::string& service_name) { service_factories_.erase(service_name); } -void ServiceRegistryImpl::ConnectToRemoteService( - const base::StringPiece& service_name, - mojo::ScopedMessagePipeHandle handle) { +void ServiceRegistryImpl::Connect(const base::StringPiece& service_name, + mojo::ScopedMessagePipeHandle handle) { if (!remote_provider_) { - pending_connects_.push( - std::make_pair(service_name.as_string(), handle.release())); + pending_outgoing_connects_.push_back(make_scoped_ptr( + new ConnectionRequest(service_name.as_string(), std::move(handle)))); return; } remote_provider_->ConnectToService( - mojo::String::From(service_name.as_string()), handle.Pass()); + service_name.as_string(), std::move(handle)); } -bool ServiceRegistryImpl::IsBound() const { - return binding_.is_bound(); -} - -base::WeakPtr<ServiceRegistry> ServiceRegistryImpl::GetWeakPtr() { - return weak_factory_.GetWeakPtr(); -} - -void ServiceRegistryImpl::ConnectToService( - const mojo::String& name, - mojo::ScopedMessagePipeHandle client_handle) { +void ServiceRegistryImpl::ConnectToService(const mojo::String& name, + mojo::ScopedMessagePipeHandle pipe) { std::map<std::string, base::Callback<void(mojo::ScopedMessagePipeHandle)> >::iterator it = service_factories_.find(name); @@ -80,16 +108,67 @@ // It's possible and effectively unavoidable that under certain conditions // an invalid handle may be received. Don't invoke the factory in that case. - if (!client_handle.is_valid()) { + if (!pipe.is_valid()) { DVLOG(2) << "Invalid pipe handle for " << name << " interface request."; return; } - it->second.Run(client_handle.Pass()); + it->second.Run(std::move(pipe)); } -void ServiceRegistryImpl::OnConnectionError() { - binding_.Close(); +void ServiceRegistryImpl::ConnectToServiceRouted( + int32_t route_id, + const mojo::String& name, + mojo::ScopedMessagePipeHandle pipe) { + auto factories_iter = routed_service_factories_.find(route_id); + if (factories_iter == routed_service_factories_.end()) { + pending_routed_incoming_connects_[route_id].push_back(make_scoped_ptr( + new ConnectionRequest(name, std::move(pipe)))); + return; + } + + ServiceFactoryMap& factories = factories_iter->second; + auto factory_iter = factories.find(name); + if (factory_iter == factories.end()) + return; + + if (!pipe.is_valid()) { + DVLOG(2) << "Invalid pipe handle for " << name << " interface request."; + return; + } + + factory_iter->second.Run(std::move(pipe)); +} + +void ServiceRegistryImpl::AddRouted( + int route_id, + const std::string& service_name, + const ServiceFactory& service_factory) { + routed_service_factories_[route_id][service_name] = service_factory; +} + +void ServiceRegistryImpl::RemoveRouted(int route_id, + const std::string& service_name) { + routed_service_factories_[route_id].erase(service_name); +} + +void ServiceRegistryImpl::ConnectRouted( + int route_id, + const std::string& service_name, + mojo::ScopedMessagePipeHandle handle) { + if (!remote_provider_) { + pending_routed_outgoing_connects_[route_id].push_back(make_scoped_ptr( + new ConnectionRequest(service_name, std::move(handle)))); + return; + } + remote_provider_->ConnectToServiceRouted( + route_id, service_name, std::move(handle)); +} + +void ServiceRegistryImpl::CloseRoute(int route_id) { + routed_service_factories_.erase(route_id); + pending_routed_incoming_connects_.erase(route_id); + pending_routed_outgoing_connects_.erase(route_id); } } // namespace content
diff --git a/content/common/mojo/service_registry_impl.h b/content/common/mojo/service_registry_impl.h index 80f4ef06..da0688d9 100644 --- a/content/common/mojo/service_registry_impl.h +++ b/content/common/mojo/service_registry_impl.h
@@ -6,64 +6,104 @@ #define CONTENT_COMMON_MOJO_SERVICE_REGISTRY_IMPL_H_ #include <map> -#include <queue> +#include <set> #include <string> -#include <utility> +#include <vector> #include "base/callback.h" #include "base/compiler_specific.h" +#include "base/macros.h" +#include "base/memory/scoped_ptr.h" #include "base/memory/weak_ptr.h" +#include "content/common/mojo/service_registry_for_route.h" +#include "content/common/routed_service_provider.mojom.h" #include "content/public/common/service_registry.h" -#include "mojo/application/public/interfaces/service_provider.mojom.h" #include "mojo/public/cpp/bindings/binding.h" -#include "mojo/public/cpp/system/core.h" +#include "mojo/public/cpp/system/message_pipe.h" namespace content { class CONTENT_EXPORT ServiceRegistryImpl : public ServiceRegistry, - public NON_EXPORTED_BASE(mojo::ServiceProvider) { + public NON_EXPORTED_BASE(RoutedServiceProvider) { public: + using ServiceFactory = base::Callback<void(mojo::ScopedMessagePipeHandle)>; + ServiceRegistryImpl(); ~ServiceRegistryImpl() override; // Binds this ServiceProvider implementation to a message pipe endpoint. - void Bind(mojo::InterfaceRequest<mojo::ServiceProvider> request); + void Bind(mojo::InterfaceRequest<RoutedServiceProvider> request); // Binds to a remote ServiceProvider. This will expose added services to the // remote ServiceProvider with the corresponding handle and enable // ConnectToRemoteService to provide access to services exposed by the remote // ServiceProvider. - void BindRemoteServiceProvider(mojo::ServiceProviderPtr service_provider); + void BindRemoteServiceProvider(RoutedServiceProviderPtr service_provider); + + // Creates a new ServiceRegistryForRoute bound to this underlying registry + // and the given |route_id|. + scoped_ptr<ServiceRegistryForRoute> CreateServiceRegistryForRoute( + int route_id); // ServiceRegistry overrides. - void AddService(const std::string& service_name, - const base::Callback<void(mojo::ScopedMessagePipeHandle)> - service_factory) override; - void RemoveService(const std::string& service_name) override; - void ConnectToRemoteService(const base::StringPiece& service_name, - mojo::ScopedMessagePipeHandle handle) override; - - bool IsBound() const; - - base::WeakPtr<ServiceRegistry> GetWeakPtr(); + void Add(const std::string& service_name, + const base::Callback<void(mojo::ScopedMessagePipeHandle)> + service_factory) override; + void Remove(const std::string& service_name) override; + void Connect(const base::StringPiece& service_name, + mojo::ScopedMessagePipeHandle handle) override; private: - // mojo::ServiceProvider overrides. + friend class ServiceRegistryForRoute; + class ConnectionRequest; + + using ServiceFactoryMap = + std::map<std::string, + base::Callback<void(mojo::ScopedMessagePipeHandle)>>; + using ConnectionRequests = std::vector<scoped_ptr<ConnectionRequest>>; + using RoutedConnectionRequestMap = std::map<int, ConnectionRequests>; + + // RoutedServiceProvider overrides. void ConnectToService(const mojo::String& name, - mojo::ScopedMessagePipeHandle client_handle) override; + mojo::ScopedMessagePipeHandle pipe) override; + void ConnectToServiceRouted(int32_t route_id, + const mojo::String& name, + mojo::ScopedMessagePipeHandle pipe) override; - void OnConnectionError(); + // Methods used by ServiceRegistryForRoute. + void AddRouted(int route_id, + const std::string& service_name, + const ServiceFactory& service_factory); + void RemoveRouted(int route_id, const std::string& service_name); + void ConnectRouted(int route_id, + const std::string& service_name, + mojo::ScopedMessagePipeHandle handle); - mojo::Binding<mojo::ServiceProvider> binding_; - mojo::ServiceProviderPtr remote_provider_; + // Closes a route, rejecting any pending connections to or from its route ID + // and dropping any service factories attached to it. + void CloseRoute(int route_id); - std::map<std::string, base::Callback<void(mojo::ScopedMessagePipeHandle)> > - service_factories_; - std::queue<std::pair<std::string, mojo::MessagePipeHandle> > - pending_connects_; + mojo::Binding<RoutedServiceProvider> binding_; + RoutedServiceProviderPtr remote_provider_; - base::WeakPtrFactory<ServiceRegistry> weak_factory_; + ServiceFactoryMap service_factories_; + std::map<int, ServiceFactoryMap> routed_service_factories_; + + // A queue of outgoing connection requests which will accumulate as long + // as the remote ServiceProvider is not connected. + ConnectionRequests pending_outgoing_connects_; + + // Queues of routed connection requests. Outgoing requests will accumulate + // as long as the remote ServiceProvider is not connection. Incoming requests + // will accumulate until the route is established via a call to + // CreateServiceRegistryForRoute. + RoutedConnectionRequestMap pending_routed_incoming_connects_; + RoutedConnectionRequestMap pending_routed_outgoing_connects_; + + base::WeakPtrFactory<ServiceRegistryImpl> weak_factory_; + + DISALLOW_COPY_AND_ASSIGN(ServiceRegistryImpl); }; } // namespace content
diff --git a/content/common/push_messaging_messages.h b/content/common/push_messaging_messages.h index 4e591861..38a39e8 100644 --- a/content/common/push_messaging_messages.h +++ b/content/common/push_messaging_messages.h
@@ -31,15 +31,17 @@ // Messages sent from the browser to the child process. -IPC_MESSAGE_ROUTED3(PushMessagingMsg_SubscribeFromDocumentSuccess, +IPC_MESSAGE_ROUTED4(PushMessagingMsg_SubscribeFromDocumentSuccess, int32_t /* request_id */, GURL /* push_endpoint */, - std::vector<uint8_t> /* p256dh */) + std::vector<uint8_t> /* p256dh */, + std::vector<uint8_t> /* auth */) -IPC_MESSAGE_CONTROL3(PushMessagingMsg_SubscribeFromWorkerSuccess, +IPC_MESSAGE_CONTROL4(PushMessagingMsg_SubscribeFromWorkerSuccess, int32_t /* request_id */, GURL /* push_endpoint */, - std::vector<uint8_t> /* p256dh */) + std::vector<uint8_t> /* p256dh */, + std::vector<uint8_t> /* auth */) IPC_MESSAGE_ROUTED2(PushMessagingMsg_SubscribeFromDocumentError, int32_t /* request_id */, @@ -58,12 +60,13 @@ blink::WebPushError::ErrorType /* error_type */, std::string /* error_message */) -IPC_MESSAGE_CONTROL3(PushMessagingMsg_GetRegistrationSuccess, +IPC_MESSAGE_CONTROL4(PushMessagingMsg_GetSubscriptionSuccess, int32_t /* request_id */, GURL /* push_endpoint */, - std::vector<uint8_t> /* p256dh */) + std::vector<uint8_t> /* p256dh */, + std::vector<uint8_t> /* auth */) -IPC_MESSAGE_CONTROL2(PushMessagingMsg_GetRegistrationError, +IPC_MESSAGE_CONTROL2(PushMessagingMsg_GetSubscriptionError, int32_t /* request_id */, content::PushGetRegistrationStatus /* status */) @@ -93,7 +96,7 @@ int32_t /* request_id */, int64_t /* service_worker_registration_id */) -IPC_MESSAGE_CONTROL2(PushMessagingHostMsg_GetRegistration, +IPC_MESSAGE_CONTROL2(PushMessagingHostMsg_GetSubscription, int32_t /* request_id */, int64_t /* service_worker_registration_id */)
diff --git a/content/common/render_frame_setup.mojom b/content/common/render_frame_setup.mojom deleted file mode 100644 index b32f953..0000000 --- a/content/common/render_frame_setup.mojom +++ /dev/null
@@ -1,13 +0,0 @@ -// Copyright 2014 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. - -module content; - -import "mojo/application/public/interfaces/service_provider.mojom"; - -interface RenderFrameSetup { - ExchangeServiceProviders(int32 frame_routing_id, - mojo.ServiceProvider& services, - mojo.ServiceProvider exposed_services); -};
diff --git a/content/common/routed_service_provider.mojom b/content/common/routed_service_provider.mojom new file mode 100644 index 0000000..27e3f98 --- /dev/null +++ b/content/common/routed_service_provider.mojom
@@ -0,0 +1,22 @@ +// Copyright 2015 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. + +module content; + +// An extension of mojo.ServiceProvider which supports a routing ID in service +// connection requests. This can be implemented to support service providers +// which require some additional routing context, e.g., per-frame services +// exposed through a shrared, per-process service registry. +interface RoutedServiceProvider { + // Asks the host to provide the service identified by |interface_name| through + // the message |pipe| endpoint supplied by the caller. If the host is not + // willing or able to provide the requested service, it should close the + // |pipe|. + ConnectToService(string interface_name, handle<message_pipe> pipe); + + // Asks the host to provide the service identified by |interface_name| and + // associated with |route_id|. + ConnectToServiceRouted( + int32 route_id, string interface_name, handle<message_pipe> pipe); +};
diff --git a/content/common/service_worker/embedded_worker_setup.mojom b/content/common/service_worker/embedded_worker_setup.mojom index a4bede7..d69f392 100644 --- a/content/common/service_worker/embedded_worker_setup.mojom +++ b/content/common/service_worker/embedded_worker_setup.mojom
@@ -4,10 +4,10 @@ module content; -import "mojo/application/public/interfaces/service_provider.mojom"; +import "content/common/routed_service_provider.mojom"; interface EmbeddedWorkerSetup { ExchangeServiceProviders(int32 thread_id, - mojo.ServiceProvider& services, - mojo.ServiceProvider exposed_services); + RoutedServiceProvider& services, + RoutedServiceProvider exposed_services); };
diff --git a/content/content_browser.gypi b/content/content_browser.gypi index fcea59d..d9704651 100644 --- a/content/content_browser.gypi +++ b/content/content_browser.gypi
@@ -544,6 +544,7 @@ 'browser/devtools/forwarding_agent_host.h', 'browser/devtools/protocol/color_picker.cc', 'browser/devtools/protocol/color_picker.h', + 'browser/devtools/protocol/devtools_protocol_delegate.h', 'browser/devtools/protocol/devtools_protocol_client.cc', 'browser/devtools/protocol/devtools_protocol_client.h', 'browser/devtools/protocol/dom_handler.cc', @@ -1146,8 +1147,14 @@ 'browser/renderer_host/input/synthetic_gesture_target_base.h', 'browser/renderer_host/input/synthetic_gesture_target_mac.h', 'browser/renderer_host/input/synthetic_gesture_target_mac.mm', + 'browser/renderer_host/input/synthetic_mouse_pointer.cc', + 'browser/renderer_host/input/synthetic_mouse_pointer.h', 'browser/renderer_host/input/synthetic_pinch_gesture.cc', 'browser/renderer_host/input/synthetic_pinch_gesture.h', + 'browser/renderer_host/input/synthetic_pointer.cc', + 'browser/renderer_host/input/synthetic_pointer.h', + 'browser/renderer_host/input/synthetic_pointer_gesture.cc', + 'browser/renderer_host/input/synthetic_pointer_gesture.h', 'browser/renderer_host/input/synthetic_smooth_drag_gesture.cc', 'browser/renderer_host/input/synthetic_smooth_drag_gesture.h', 'browser/renderer_host/input/synthetic_smooth_move_gesture.cc', @@ -1160,6 +1167,8 @@ 'browser/renderer_host/input/synthetic_touchpad_pinch_gesture.h', 'browser/renderer_host/input/synthetic_touchscreen_pinch_gesture.cc', 'browser/renderer_host/input/synthetic_touchscreen_pinch_gesture.h', + 'browser/renderer_host/input/synthetic_touch_pointer.cc', + 'browser/renderer_host/input/synthetic_touch_pointer.h', 'browser/renderer_host/input/tap_suppression_controller.cc', 'browser/renderer_host/input/tap_suppression_controller.h', 'browser/renderer_host/input/tap_suppression_controller_client.h',
diff --git a/content/content_common.gypi b/content/content_common.gypi index b24ce41..e3560d2d 100644 --- a/content/content_common.gypi +++ b/content/content_common.gypi
@@ -443,6 +443,8 @@ 'common/mojo/channel_init.cc', 'common/mojo/channel_init.h', 'common/mojo/mojo_messages.h', + 'common/mojo/service_registry_for_route.cc', + 'common/mojo/service_registry_for_route.h', 'common/mojo/service_registry_impl.cc', 'common/mojo/service_registry_impl.h', 'common/navigation_gesture.h', @@ -634,6 +636,7 @@ 'export_dependent_settings' : [ '../mojo/mojo_base.gyp:mojo_application_bindings', '../third_party/mojo/mojo_public.gyp:mojo_cpp_bindings', + 'content_common_mojo_bindings.gyp:content_common_mojo_bindings', ], 'actions': [ {
diff --git a/content/content_common_mojo_bindings.gyp b/content/content_common_mojo_bindings.gyp index f8205961..d5a9ebd 100644 --- a/content/content_common_mojo_bindings.gyp +++ b/content/content_common_mojo_bindings.gyp
@@ -18,7 +18,7 @@ 'common/permission_service.mojom', 'common/presentation/presentation_service.mojom', 'common/process_control.mojom', - 'common/render_frame_setup.mojom', + 'common/routed_service_provider.mojom', 'common/service_port_service.mojom', 'common/service_worker/embedded_worker_setup.mojom', 'common/vr_service.mojom',
diff --git a/content/plugin/BUILD.gn b/content/plugin/BUILD.gn index 32b6e03e..ed12ee6fd 100644 --- a/content/plugin/BUILD.gn +++ b/content/plugin/BUILD.gn
@@ -35,8 +35,8 @@ "//content/public/common:common_sources", "//mojo/application/public/interfaces", "//skia", - "//third_party/npapi", "//third_party/WebKit/public:blink", + "//third_party/npapi", ] } } else {
diff --git a/content/ppapi_plugin/BUILD.gn b/content/ppapi_plugin/BUILD.gn index ef4dcdf..f5fc125 100644 --- a/content/ppapi_plugin/BUILD.gn +++ b/content/ppapi_plugin/BUILD.gn
@@ -42,8 +42,8 @@ "//mojo/application/public/interfaces", "//ppapi/proxy:ipc", "//skia", - "//third_party/icu", "//third_party/WebKit/public:blink", + "//third_party/icu", "//ui/base", "//ui/gfx", "//ui/gfx/geometry",
diff --git a/content/public/android/BUILD.gn b/content/public/android/BUILD.gn index 0d447ce2..bea70b9e 100644 --- a/content/public/android/BUILD.gn +++ b/content/public/android/BUILD.gn
@@ -32,22 +32,22 @@ deps = [ ":content_java_resources", "//base:base_java", - "//device/battery/android:battery_monitor_android", "//device/battery:mojo_bindings_java", + "//device/battery/android:battery_monitor_android", "//device/bluetooth:java", - "//device/vibration/android:vibration_manager_android", "//device/vibration:mojo_bindings_java", + "//device/vibration/android:vibration_manager_android", "//media/base/android:media_java", "//media/midi:midi_java", "//mojo/android:system_java", "//mojo/public/java:bindings", "//mojo/public/java:system", "//net/android:net_java", + "//third_party/WebKit/public:blink_headers_java", "//third_party/android_tools:android_support_v13_java", + "//third_party/jsr-305:jsr_305_javalib", "//ui/accessibility:ui_accessibility_java", "//ui/android:ui_java", - "//third_party/jsr-305:jsr_305_javalib", - "//third_party/WebKit/public:blink_headers_java", #"//content:content_common", ] @@ -165,15 +165,16 @@ android_library("content_javatests") { testonly = true deps = [ + ":content_java", "//base:base_java", "//base:base_java_test_support", "//content/public/test/android:content_java_test_support", + "//content/shell/android:content_shell_apk_java", "//content/shell/android:content_shell_java", "//content/shell/android:content_shell_java_resources", - "//content/shell/android:content_shell_apk_java", "//content/shell/android:content_shell_test_java", - "//device/vibration/android:vibration_manager_android", "//device/vibration:mojo_bindings_java", + "//device/vibration/android:vibration_manager_android", "//media/base/android:media_java", "//mojo/android:system_java", "//mojo/public/interfaces/bindings/tests:test_interfaces_java", @@ -184,7 +185,6 @@ "//third_party/android_tools:android_support_v13_java", "//third_party/android_tools:legacy_http_javalib", "//ui/android:ui_java", - ":content_java", ] DEPRECATED_java_in_dir = "javatests/src"
diff --git a/content/public/browser/desktop_media_id.h b/content/public/browser/desktop_media_id.h index c31875b..921dc95 100644 --- a/content/public/browser/desktop_media_id.h +++ b/content/public/browser/desktop_media_id.h
@@ -6,6 +6,7 @@ #define CONTENT_PUBLIC_BROWSER_DESKTOP_MEDIA_ID_H_ #include <string> +#include <tuple> #include "base/basictypes.h" #include "content/common/content_export.h" @@ -54,12 +55,10 @@ // Operators so that DesktopMediaID can be used with STL containers. bool operator<(const DesktopMediaID& other) const { #if defined(USE_AURA) - return (type < other.type || - (type == other.type && - (id < other.id || (id == other.id && - aura_id < other.aura_id)))); + return std::tie(type, id, aura_id) < + std::tie(other.type, other.id, other.aura_id); #else - return type < other.type || (type == other.type && id < other.id); + return std::tie(type, id) < std::tie(other.type, other.id); #endif } bool operator==(const DesktopMediaID& other) const {
diff --git a/content/public/browser/global_request_id.h b/content/public/browser/global_request_id.h index 8714b2f6..5f3f5995 100644 --- a/content/public/browser/global_request_id.h +++ b/content/public/browser/global_request_id.h
@@ -5,6 +5,8 @@ #ifndef CONTENT_PUBLIC_BROWSER_GLOBAL_REQUEST_ID_H_ #define CONTENT_PUBLIC_BROWSER_GLOBAL_REQUEST_ID_H_ +#include <tuple> + namespace content { // Uniquely identifies a net::URLRequest. @@ -24,9 +26,8 @@ int request_id; bool operator<(const GlobalRequestID& other) const { - if (child_id == other.child_id) - return request_id < other.request_id; - return child_id < other.child_id; + return std::tie(child_id, request_id) < + std::tie(other.child_id, other.request_id); } bool operator==(const GlobalRequestID& other) const { return child_id == other.child_id &&
diff --git a/content/public/browser/push_messaging_service.h b/content/public/browser/push_messaging_service.h index e7d7f7f..cd9d3b2 100644 --- a/content/public/browser/push_messaging_service.h +++ b/content/public/browser/push_messaging_service.h
@@ -27,12 +27,14 @@ using RegisterCallback = base::Callback<void(const std::string& registration_id, const std::vector<uint8_t>& p256dh, + const std::vector<uint8_t>& auth, PushRegistrationStatus status)>; using UnregisterCallback = base::Callback<void(PushUnregistrationStatus)>; using PublicKeyCallback = base::Callback<void( bool success, - const std::vector<uint8_t>& p256dh)>; + const std::vector<uint8_t>& p256dh, + const std::vector<uint8_t>& auth)>; using StringCallback = base::Callback<void(const std::string& data, bool success,
diff --git a/content/public/common/service_registry.h b/content/public/common/service_registry.h index 5832131..9f26dac 100644 --- a/content/public/common/service_registry.h +++ b/content/public/common/service_registry.h
@@ -32,32 +32,33 @@ // service will override the factory. Existing connections to the service are // unaffected. template <typename Interface> - void AddService(const base::Callback<void(mojo::InterfaceRequest<Interface>)> - service_factory) { - AddService(Interface::Name_, - base::Bind(&ServiceRegistry::ForwardToServiceFactory<Interface>, - service_factory)); + void AddService( + const base::Callback<void(mojo::InterfaceRequest<Interface>)> factory) { + Add(Interface::Name_, + base::Bind(&ServiceRegistry::ForwardToServiceFactory<Interface>, + factory)); } - virtual void AddService( - const std::string& service_name, - const base::Callback<void(mojo::ScopedMessagePipeHandle)> - service_factory) = 0; // Remove future access to the service implementing Interface. Existing // connections to the service are unaffected. template <typename Interface> void RemoveService() { - RemoveService(Interface::Name_); + Remove(Interface::Name_); } - virtual void RemoveService(const std::string& service_name) = 0; // Connect to an interface provided by the remote service provider. template <typename Interface> - void ConnectToRemoteService(mojo::InterfaceRequest<Interface> ptr) { - ConnectToRemoteService(Interface::Name_, ptr.PassMessagePipe()); + void ConnectToRemoteService(mojo::InterfaceRequest<Interface> request) { + Connect(Interface::Name_, request.PassMessagePipe()); } - virtual void ConnectToRemoteService(const base::StringPiece& name, - mojo::ScopedMessagePipeHandle handle) = 0; + + virtual void Add( + const std::string& service_name, + const base::Callback<void(mojo::ScopedMessagePipeHandle)> + service_factory) = 0; + virtual void Remove(const std::string& service_name) = 0; + virtual void Connect(const base::StringPiece& name, + mojo::ScopedMessagePipeHandle handle) = 0; private: template <typename Interface>
diff --git a/content/public/renderer/BUILD.gn b/content/public/renderer/BUILD.gn index 0ab2d33..719eadf 100644 --- a/content/public/renderer/BUILD.gn +++ b/content/public/renderer/BUILD.gn
@@ -31,8 +31,8 @@ "//content/public/common:common_sources", "//content/renderer", "//skia", - "//third_party/libjingle", "//third_party/WebKit/public:blink_headers", + "//third_party/libjingle", "//third_party/widevine/cdm:version_h", "//ui/gfx", "//v8",
diff --git a/content/public/renderer/media_stream_api.cc b/content/public/renderer/media_stream_api.cc index dfe7896..5908c996 100644 --- a/content/public/renderer/media_stream_api.cc +++ b/content/public/renderer/media_stream_api.cc
@@ -30,11 +30,10 @@ } // namespace -bool AddVideoTrackToMediaStream( - scoped_ptr<media::VideoCapturerSource> source, - bool is_remote, - bool is_readonly, - const std::string& media_stream_url) { +bool AddVideoTrackToMediaStream(scoped_ptr<media::VideoCapturerSource> source, + bool is_remote, + bool is_readonly, + const std::string& media_stream_url) { blink::WebMediaStream web_stream = blink::WebMediaStreamRegistry::lookupMediaStreamDescriptor( GURL(media_stream_url)); @@ -42,6 +41,31 @@ &web_stream); } +bool AddVideoTrackToMediaStream(scoped_ptr<media::VideoCapturerSource> source, + bool is_remote, + bool is_readonly, + blink::WebMediaStream* web_stream) { + if (web_stream->isNull()) { + DLOG(ERROR) << "Stream not found"; + return false; + } + const blink::WebString track_id = MakeTrackId(); + blink::WebMediaStreamSource webkit_source; + scoped_ptr<MediaStreamVideoSource> media_stream_source( + new MediaStreamVideoCapturerSource( + MediaStreamSource::SourceStoppedCallback(), source.Pass())); + webkit_source.initialize(track_id, blink::WebMediaStreamSource::TypeVideo, + track_id, is_remote, is_readonly); + webkit_source.setExtraData(media_stream_source.get()); + + blink::WebMediaConstraints constraints; + constraints.initialize(); + web_stream->addTrack(MediaStreamVideoTrack::CreateVideoTrack( + media_stream_source.release(), constraints, + MediaStreamVideoSource::ConstraintsCallback(), true)); + return true; +} + bool AddAudioTrackToMediaStream( const scoped_refptr<media::AudioCapturerSource>& source, const media::AudioParameters& params, @@ -52,10 +76,26 @@ blink::WebMediaStream web_stream = blink::WebMediaStreamRegistry::lookupMediaStreamDescriptor( GURL(media_stream_url)); - if (web_stream.isNull()) { + return AddAudioTrackToMediaStream(source, + is_remote, is_readonly, &web_stream); +} + +bool AddAudioTrackToMediaStream( + const scoped_refptr<media::AudioCapturerSource>& source, + bool is_remote, + bool is_readonly, + blink::WebMediaStream* web_stream) { + if (web_stream->isNull()) { DLOG(ERROR) << "Stream not found"; return false; } + + media::AudioParameters params( + media::AudioParameters::AUDIO_PCM_LINEAR, media::CHANNEL_LAYOUT_STEREO, + 48000, /* sample rate */ + 16, /* bits per sample */ + 480); /* frames per buffer */ + blink::WebMediaStreamSource webkit_source; const blink::WebString track_id = MakeTrackId(); webkit_source.initialize(track_id, @@ -85,38 +125,7 @@ RenderThreadImpl::current()->GetPeerConnectionDependencyFactory()-> CreateLocalAudioTrack(web_media_audio_track); - web_stream.addTrack(web_media_audio_track); - return true; -} - -bool AddVideoTrackToMediaStream(scoped_ptr<media::VideoCapturerSource> source, - bool is_remote, - bool is_readonly, - blink::WebMediaStream* web_stream) { - if (web_stream->isNull()) { - DLOG(ERROR) << "Stream not found"; - return false; - } - const blink::WebString track_id = MakeTrackId(); - blink::WebMediaStreamSource webkit_source; - scoped_ptr<MediaStreamVideoSource> media_stream_source( - new MediaStreamVideoCapturerSource( - MediaStreamSource::SourceStoppedCallback(), - source.Pass())); - webkit_source.initialize(track_id, - blink::WebMediaStreamSource::TypeVideo, - track_id, - is_remote, - is_readonly); - webkit_source.setExtraData(media_stream_source.get()); - - blink::WebMediaConstraints constraints; - constraints.initialize(); - web_stream->addTrack(MediaStreamVideoTrack::CreateVideoTrack( - media_stream_source.release(), - constraints, - MediaStreamVideoSource::ConstraintsCallback(), - true)); + web_stream->addTrack(web_media_audio_track); return true; }
diff --git a/content/public/renderer/media_stream_api.h b/content/public/renderer/media_stream_api.h index 2e87ff3..dfb2aaf6 100644 --- a/content/public/renderer/media_stream_api.h +++ b/content/public/renderer/media_stream_api.h
@@ -43,6 +43,11 @@ bool is_remote, bool is_readonly, const std::string& media_stream_url); +CONTENT_EXPORT bool AddAudioTrackToMediaStream( + const scoped_refptr<media::AudioCapturerSource>& source, + bool is_remote, + bool is_readonly, + blink::WebMediaStream* web_stream); } // namespace content
diff --git a/content/public/test/browser_test_utils.cc b/content/public/test/browser_test_utils.cc index 2708386..79fd617 100644 --- a/content/public/test/browser_test_utils.cc +++ b/content/public/test/browser_test_utils.cc
@@ -227,8 +227,11 @@ int modifiers) { NativeWebKeyboardEvent event; BuildSimpleWebKeyEvent(type, key_code, native_key_code, modifiers, &event); - static_cast<WebContentsImpl*>(web_contents) - ->GetFocusedRenderWidgetHost() + WebContentsImpl* web_contents_impl = + static_cast<WebContentsImpl*>(web_contents); + RenderWidgetHostImpl* main_frame_rwh = + web_contents_impl->GetMainFrame()->GetRenderWidgetHost(); + web_contents_impl->GetFocusedRenderWidgetHost(main_frame_rwh) ->ForwardKeyboardEvent(event); }
diff --git a/content/public/test/content_test_suite_base.cc b/content/public/test/content_test_suite_base.cc index 859e60d..b81448f8 100644 --- a/content/public/test/content_test_suite_base.cc +++ b/content/public/test/content_test_suite_base.cc
@@ -90,10 +90,10 @@ media::RegisterJni(env); net::android::RegisterJni(env); ui::android::RegisterJni(env); - ui::RegisterUIAndroidJni(env); ui::gl::android::RegisterJni(env); ui::events::android::RegisterJni(env); #if !defined(USE_AURA) + ui::RegisterUIAndroidJni(env); ui::shell_dialogs::RegisterJni(env); content::Compositor::Initialize(); #endif
diff --git a/content/renderer/BUILD.gn b/content/renderer/BUILD.gn index cf164b7..aa203aa 100644 --- a/content/renderer/BUILD.gn +++ b/content/renderer/BUILD.gn
@@ -24,7 +24,6 @@ deps = [ # TODO(GYP) bug 376846 remove this. This should be inherited from //net but # those don't cross component boundaries. - "//crypto:platform", "//base/allocator", "//cc", "//cc/blink", @@ -38,6 +37,7 @@ "//content/public/child:child_sources", "//content/public/common:common_sources", "//content/public/common:mojo_bindings", + "//crypto:platform", "//device/battery:mojo_bindings", "//device/vibration:mojo_bindings", "//gin", @@ -47,26 +47,26 @@ "//media", "//media/blink", "//mojo/application/public/interfaces", - "//mojo/environment:chromium", "//mojo/common:url_type_converters", "//mojo/converters/geometry", + "//mojo/environment:chromium", "//mojo/public/cpp/bindings", "//mojo/public/js", "//net", "//skia", "//skia/public", "//storage/common", + "//third_party/WebKit/public:blink", "//third_party/icu", "//third_party/libjingle", "//third_party/libyuv", "//third_party/mojo/src/mojo/edk/js", "//third_party/npapi", - "//third_party/WebKit/public:blink", "//third_party/widevine/cdm:version_h", "//ui/accessibility", "//ui/base", - "//ui/events:events_base", "//ui/events:dom_keycode_converter", + "//ui/events:events_base", "//ui/gl", "//ui/native_theme", "//ui/surface",
diff --git a/content/renderer/devtools/devtools_agent.cc b/content/renderer/devtools/devtools_agent.cc index 93dfd84..55b4c6b 100644 --- a/content/renderer/devtools/devtools_agent.cc +++ b/content/renderer/devtools/devtools_agent.cc
@@ -101,12 +101,12 @@ ContinueProgram(); } -void DevToolsAgent::sendProtocolMessage( - int call_id, - const blink::WebString& message, - const blink::WebString& state_cookie) { - SendChunkedProtocolMessage( - this, routing_id(), call_id, message.utf8(), state_cookie.utf8()); +void DevToolsAgent::sendProtocolMessage(int session_id, + int call_id, + const blink::WebString& message, + const blink::WebString& state_cookie) { + SendChunkedProtocolMessage(this, routing_id(), session_id, call_id, + message.utf8(), state_cookie.utf8()); } blink::WebDevToolsAgentClient::WebKitClientMessageLoop* @@ -131,6 +131,12 @@ } void DevToolsAgent::enableTracing(const WebString& category_filter) { + // Tracing is already started by DevTools TracingHandler::Start for the + // renderer target in the browser process. It will eventually start tracing in + // the renderer process via IPC. But we still need a redundant + // TraceLog::SetEnabled call here for + // InspectorTracingAgent::emitMetadataEvents(), at which point, we are not + // sure if tracing is already started in the renderer process. TraceLog* trace_log = TraceLog::GetInstance(); trace_log->SetEnabled( base::trace_event::TraceConfig(category_filter.utf8(), ""), @@ -151,18 +157,19 @@ } // static -void DevToolsAgent::SendChunkedProtocolMessage( - IPC::Sender* sender, - int routing_id, - int call_id, - const std::string& message, - const std::string& post_state) { +void DevToolsAgent::SendChunkedProtocolMessage(IPC::Sender* sender, + int routing_id, + int session_id, + int call_id, + const std::string& message, + const std::string& post_state) { DevToolsMessageChunk chunk; chunk.message_size = message.size(); chunk.is_first = true; if (message.length() < kMaxMessageChunkSize) { chunk.data = message; + chunk.session_id = session_id; chunk.call_id = call_id; chunk.post_state = post_state; chunk.is_last = true; @@ -173,6 +180,7 @@ for (size_t pos = 0; pos < message.length(); pos += kMaxMessageChunkSize) { chunk.is_last = pos + kMaxMessageChunkSize >= message.length(); + chunk.session_id = chunk.is_last ? session_id : 0; chunk.call_id = chunk.is_last ? call_id : 0; chunk.post_state = chunk.is_last ? post_state : std::string(); chunk.data = message.substr(pos, kMaxMessageChunkSize); @@ -183,19 +191,20 @@ } } -void DevToolsAgent::OnAttach(const std::string& host_id) { +void DevToolsAgent::OnAttach(const std::string& host_id, int session_id) { WebDevToolsAgent* web_agent = GetWebAgent(); if (web_agent) { - web_agent->attach(WebString::fromUTF8(host_id)); + web_agent->attach(WebString::fromUTF8(host_id), session_id); is_attached_ = true; } } void DevToolsAgent::OnReattach(const std::string& host_id, + int session_id, const std::string& agent_state) { WebDevToolsAgent* web_agent = GetWebAgent(); if (web_agent) { - web_agent->reattach(WebString::fromUTF8(host_id), + web_agent->reattach(WebString::fromUTF8(host_id), session_id, WebString::fromUTF8(agent_state)); is_attached_ = true; } @@ -209,11 +218,13 @@ } } -void DevToolsAgent::OnDispatchOnInspectorBackend(const std::string& message) { +void DevToolsAgent::OnDispatchOnInspectorBackend(int session_id, + const std::string& message) { TRACE_EVENT0("devtools", "DevToolsAgent::OnDispatchOnInspectorBackend"); WebDevToolsAgent* web_agent = GetWebAgent(); if (web_agent) - web_agent->dispatchOnInspectorBackend(WebString::fromUTF8(message)); + web_agent->dispatchOnInspectorBackend(session_id, + WebString::fromUTF8(message)); } void DevToolsAgent::OnInspectElement(int x, int y) {
diff --git a/content/renderer/devtools/devtools_agent.h b/content/renderer/devtools/devtools_agent.h index cbdccd5..f4163d7 100644 --- a/content/renderer/devtools/devtools_agent.h +++ b/content/renderer/devtools/devtools_agent.h
@@ -33,12 +33,12 @@ // Returns agent instance for its routing id. static DevToolsAgent* FromRoutingId(int routing_id); - static void SendChunkedProtocolMessage( - IPC::Sender* sender, - int routing_id, - int call_id, - const std::string& message, - const std::string& post_state); + static void SendChunkedProtocolMessage(IPC::Sender* sender, + int routing_id, + int session_id, + int call_id, + const std::string& message, + const std::string& post_state); blink::WebDevToolsAgent* GetWebAgent(); @@ -55,7 +55,8 @@ void WidgetWillClose() override; // WebDevToolsAgentClient implementation. - void sendProtocolMessage(int call_id, + void sendProtocolMessage(int session_id, + int call_id, const blink::WebString& response, const blink::WebString& state) override; blink::WebDevToolsAgentClient::WebKitClientMessageLoop* @@ -66,11 +67,12 @@ void enableTracing(const blink::WebString& category_filter) override; void disableTracing() override; - void OnAttach(const std::string& host_id); + void OnAttach(const std::string& host_id, int session_id); void OnReattach(const std::string& host_id, + int session_id, const std::string& agent_state); void OnDetach(); - void OnDispatchOnInspectorBackend(const std::string& message); + void OnDispatchOnInspectorBackend(int session_id, const std::string& message); void OnInspectElement(int x, int y); void ContinueProgram(); void OnSetupDevToolsClient(const std::string& compatibility_script);
diff --git a/content/renderer/devtools/devtools_agent_filter.cc b/content/renderer/devtools/devtools_agent_filter.cc index e1b3af0..94b9e0d4 100644 --- a/content/renderer/devtools/devtools_agent_filter.cc +++ b/content/renderer/devtools/devtools_agent_filter.cc
@@ -60,6 +60,7 @@ DevToolsAgentFilter::~DevToolsAgentFilter() {} void DevToolsAgentFilter::OnDispatchOnInspectorBackend( + int session_id, const std::string& message) { if (embedded_worker_routes_.find(current_routing_id_) != embedded_worker_routes_.end()) { @@ -69,7 +70,7 @@ if (WebDevToolsAgent::shouldInterruptForMessage( WebString::fromUTF8(message))) { WebDevToolsAgent::interruptAndDispatch( - new MessageImpl(message, current_routing_id_)); + session_id, new MessageImpl(message, current_routing_id_)); } }
diff --git a/content/renderer/devtools/devtools_agent_filter.h b/content/renderer/devtools/devtools_agent_filter.h index c8ba687..9113ae2b 100644 --- a/content/renderer/devtools/devtools_agent_filter.h +++ b/content/renderer/devtools/devtools_agent_filter.h
@@ -43,7 +43,7 @@ ~DevToolsAgentFilter() override; private: - void OnDispatchOnInspectorBackend(const std::string& message); + void OnDispatchOnInspectorBackend(int session_id, const std::string& message); // Called on IO thread void AddEmbeddedWorkerRoute(int32 routing_id);
diff --git a/content/renderer/geolocation_dispatcher.cc b/content/renderer/geolocation_dispatcher.cc index 9f544736..46412ff 100644 --- a/content/renderer/geolocation_dispatcher.cc +++ b/content/renderer/geolocation_dispatcher.cc
@@ -5,6 +5,7 @@ #include "content/renderer/geolocation_dispatcher.h" #include "content/public/common/geoposition.h" +#include "content/public/common/service_registry.h" #include "content/renderer/render_view_impl.h" #include "third_party/WebKit/public/platform/WebString.h" #include "third_party/WebKit/public/web/WebGeolocationPermissionRequest.h"
diff --git a/content/renderer/media/rtc_video_decoder.h b/content/renderer/media/rtc_video_decoder.h index b96779a..db7668c 100644 --- a/content/renderer/media/rtc_video_decoder.h +++ b/content/renderer/media/rtc_video_decoder.h
@@ -21,7 +21,7 @@ #include "media/base/video_decoder.h" #include "media/video/picture.h" #include "media/video/video_decode_accelerator.h" -#include "third_party/webrtc/modules/video_coding/codecs/interface/video_codec_interface.h" +#include "third_party/webrtc/modules/video_coding/include/video_codec_interface.h" #include "ui/gfx/geometry/rect.h" namespace base {
diff --git a/content/renderer/media/rtc_video_decoder_factory.h b/content/renderer/media/rtc_video_decoder_factory.h index 6c40693..ca797c1 100644 --- a/content/renderer/media/rtc_video_decoder_factory.h +++ b/content/renderer/media/rtc_video_decoder_factory.h
@@ -8,7 +8,7 @@ #include "base/threading/thread.h" #include "content/common/content_export.h" #include "third_party/libjingle/source/talk/media/webrtc/webrtcvideodecoderfactory.h" -#include "third_party/webrtc/modules/video_coding/codecs/interface/video_codec_interface.h" +#include "third_party/webrtc/modules/video_coding/include/video_codec_interface.h" namespace webrtc { class VideoDecoder;
diff --git a/content/renderer/media/rtc_video_encoder.h b/content/renderer/media/rtc_video_encoder.h index 303c368..c916d54 100644 --- a/content/renderer/media/rtc_video_encoder.h +++ b/content/renderer/media/rtc_video_encoder.h
@@ -14,7 +14,7 @@ #include "base/time/time.h" #include "content/common/content_export.h" #include "media/base/video_decoder_config.h" -#include "third_party/webrtc/modules/video_coding/codecs/interface/video_codec_interface.h" +#include "third_party/webrtc/modules/video_coding/include/video_codec_interface.h" #include "ui/gfx/geometry/size.h" namespace media {
diff --git a/content/renderer/mojo/service_registry_js_wrapper.cc b/content/renderer/mojo/service_registry_js_wrapper.cc index 4840b1e..19c2bd7a 100644 --- a/content/renderer/mojo/service_registry_js_wrapper.cc +++ b/content/renderer/mojo/service_registry_js_wrapper.cc
@@ -4,6 +4,8 @@ #include "content/renderer/mojo/service_registry_js_wrapper.h" +#include <utility> + #include "content/common/mojo/service_registry_impl.h" #include "content/public/common/service_registry.h" #include "third_party/mojo/src/mojo/edk/js/handle.h" @@ -21,11 +23,9 @@ // static gin::Handle<ServiceRegistryJsWrapper> ServiceRegistryJsWrapper::Create( v8::Isolate* isolate, - ServiceRegistry* service_registry) { + base::WeakPtr<ServiceRegistry> service_registry) { return gin::CreateHandle( - isolate, - new ServiceRegistryJsWrapper( - static_cast<ServiceRegistryImpl*>(service_registry)->GetWeakPtr())); + isolate, new ServiceRegistryJsWrapper(service_registry)); } gin::ObjectTemplateBuilder ServiceRegistryJsWrapper::GetObjectTemplateBuilder( @@ -39,8 +39,7 @@ const std::string& service_name) { mojo::MessagePipe pipe; if (service_registry_) - service_registry_->ConnectToRemoteService(service_name, - pipe.handle0.Pass()); + service_registry_->Connect(service_name, std::move(pipe.handle0)); return pipe.handle1.release(); }
diff --git a/content/renderer/mojo/service_registry_js_wrapper.h b/content/renderer/mojo/service_registry_js_wrapper.h index 2be7f95..d8b95a58 100644 --- a/content/renderer/mojo/service_registry_js_wrapper.h +++ b/content/renderer/mojo/service_registry_js_wrapper.h
@@ -7,6 +7,7 @@ #include <string> +#include "base/memory/weak_ptr.h" #include "content/common/content_export.h" #include "gin/handle.h" #include "gin/object_template_builder.h" @@ -25,7 +26,7 @@ ~ServiceRegistryJsWrapper() override; static gin::Handle<ServiceRegistryJsWrapper> Create( v8::Isolate* isolate, - ServiceRegistry* service_registry); + base::WeakPtr<ServiceRegistry> service_registry); // gin::Wrappable<ServiceRegistryJsWrapper> overrides. gin::ObjectTemplateBuilder GetObjectTemplateBuilder(
diff --git a/content/renderer/pepper/host_var_tracker.cc b/content/renderer/pepper/host_var_tracker.cc index e3da983..1b78ddc 100644 --- a/content/renderer/pepper/host_var_tracker.cc +++ b/content/renderer/pepper/host_var_tracker.cc
@@ -4,6 +4,8 @@ #include "content/renderer/pepper/host_var_tracker.h" +#include <tuple> + #include "base/logging.h" #include "content/renderer/pepper/host_array_buffer_var.h" #include "content/renderer/pepper/host_globals.h" @@ -32,9 +34,7 @@ bool HostVarTracker::V8ObjectVarKey::operator<( const V8ObjectVarKey& other) const { - if (instance == other.instance) - return hash < other.hash; - return instance < other.instance; + return std::tie(instance, hash) < std::tie(other.instance, other.hash); } HostVarTracker::HostVarTracker()
diff --git a/content/renderer/pepper/video_decoder_shim.cc b/content/renderer/pepper/video_decoder_shim.cc index 75242d2d..84dd33a 100644 --- a/content/renderer/pepper/video_decoder_shim.cc +++ b/content/renderer/pepper/video_decoder_shim.cc
@@ -696,7 +696,7 @@ #if !defined(MEDIA_DISABLE_FFMPEG) && !defined(DISABLE_FFMPEG_VIDEO_DECODERS) { scoped_ptr<media::FFmpegVideoDecoder> ffmpeg_video_decoder( - new media::FFmpegVideoDecoder(base::ThreadTaskRunnerHandle::Get())); + new media::FFmpegVideoDecoder()); ffmpeg_video_decoder->set_decode_nalus(true); decoder_ = ffmpeg_video_decoder.Pass(); }
diff --git a/content/renderer/push_messaging/PRESUBMIT.py b/content/renderer/push_messaging/PRESUBMIT.py new file mode 100644 index 0000000..aa4ae97d --- /dev/null +++ b/content/renderer/push_messaging/PRESUBMIT.py
@@ -0,0 +1,12 @@ +# Copyright 2015 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. + +"""Top-level presubmit script for Push Messaging. + +See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts +for more details about the presubmit API built into depot_tools. +""" + +def CheckChangeOnUpload(input_api, output_api): + return input_api.canned_checks.CheckPatchFormatted(input_api, output_api)
diff --git a/content/renderer/push_messaging/push_messaging_dispatcher.cc b/content/renderer/push_messaging/push_messaging_dispatcher.cc index ca9747e..ff2b53c 100644 --- a/content/renderer/push_messaging/push_messaging_dispatcher.cc +++ b/content/renderer/push_messaging/push_messaging_dispatcher.cc
@@ -22,8 +22,7 @@ namespace content { PushMessagingDispatcher::PushMessagingDispatcher(RenderFrame* render_frame) - : RenderFrameObserver(render_frame) { -} + : RenderFrameObserver(render_frame) {} PushMessagingDispatcher::~PushMessagingDispatcher() {} @@ -47,11 +46,9 @@ DCHECK(callbacks); RenderFrameImpl::FromRoutingID(routing_id()) ->manifest_manager() - ->GetManifest(base::Bind(&PushMessagingDispatcher::DoSubscribe, - base::Unretained(this), - service_worker_registration, - options, - callbacks)); + ->GetManifest(base::Bind( + &PushMessagingDispatcher::DoSubscribe, base::Unretained(this), + service_worker_registration, options, callbacks)); } void PushMessagingDispatcher::DoSubscribe( @@ -62,7 +59,8 @@ int request_id = subscription_callbacks_.Add(callbacks); int64_t service_worker_registration_id = static_cast<WebServiceWorkerRegistrationImpl*>( - service_worker_registration)->registration_id(); + service_worker_registration) + ->registration_id(); std::string sender_id = manifest.gcm_sender_id.is_null() @@ -85,13 +83,14 @@ void PushMessagingDispatcher::OnSubscribeFromDocumentSuccess( int32_t request_id, const GURL& endpoint, - const std::vector<uint8_t>& p256dh) { + const std::vector<uint8_t>& p256dh, + const std::vector<uint8_t>& auth) { blink::WebPushSubscriptionCallbacks* callbacks = subscription_callbacks_.Lookup(request_id); DCHECK(callbacks); callbacks->onSuccess(blink::adoptWebPtr( - new blink::WebPushSubscription(endpoint, p256dh))); + new blink::WebPushSubscription(endpoint, p256dh, auth))); subscription_callbacks_.Remove(request_id); }
diff --git a/content/renderer/push_messaging/push_messaging_dispatcher.h b/content/renderer/push_messaging/push_messaging_dispatcher.h index 6c2678e..13f3b72 100644 --- a/content/renderer/push_messaging/push_messaging_dispatcher.h +++ b/content/renderer/push_messaging/push_messaging_dispatcher.h
@@ -53,7 +53,8 @@ void OnSubscribeFromDocumentSuccess(int32_t request_id, const GURL& endpoint, - const std::vector<uint8_t>& p256dh); + const std::vector<uint8_t>& p256dh, + const std::vector<uint8_t>& auth); void OnSubscribeFromDocumentError(int32_t request_id, PushRegistrationStatus status);
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc index 2193a45..8ab011d 100644 --- a/content/renderer/render_frame_impl.cc +++ b/content/renderer/render_frame_impl.cc
@@ -13,6 +13,7 @@ #include "base/debug/asan_invalid_access.h" #include "base/debug/dump_without_crashing.h" #include "base/i18n/char_iterator.h" +#include "base/memory/weak_ptr.h" #include "base/metrics/histogram.h" #include "base/process/process.h" #include "base/strings/string16.h" @@ -41,6 +42,8 @@ #include "content/common/frame_messages.h" #include "content/common/frame_replication_state.h" #include "content/common/input_messages.h" +#include "content/common/mojo/service_registry_for_route.h" +#include "content/common/mojo/service_registry_impl.h" #include "content/common/navigation_params.h" #include "content/common/savable_subframe.h" #include "content/common/service_worker/service_worker_types.h" @@ -54,6 +57,7 @@ #include "content/public/common/isolated_world_ids.h" #include "content/public/common/page_state.h" #include "content/public/common/resource_response.h" +#include "content/public/common/service_registry.h" #include "content/public/common/url_constants.h" #include "content/public/common/url_utils.h" #include "content/public/renderer/browser_plugin_delegate.h" @@ -774,6 +778,17 @@ g_routing_id_frame_map.Get().insert(std::make_pair(routing_id_, this)); CHECK(result.second) << "Inserting a duplicate item."; + // ChildThreadImpl may be null in some tests, in which case we roll our own + // ServiceRegistry. + if (ChildThreadImpl::current()) { + service_registry_ = ChildThreadImpl::current()->service_registry() + ->CreateServiceRegistryForRoute(routing_id_); + } else { + service_registry_.reset(new ServiceRegistryImpl); + } + service_registry_weak_factory_.reset( + new base::WeakPtrFactory<ServiceRegistry>(service_registry_.get())); + RenderThread::Get()->AddRoute(routing_id_, this); render_view_->RegisterRenderFrame(this); @@ -1221,13 +1236,6 @@ frame_->loadRequest(request); } -void RenderFrameImpl::BindServiceRegistry( - mojo::InterfaceRequest<mojo::ServiceProvider> services, - mojo::ServiceProviderPtr exposed_services) { - service_registry_.Bind(services.Pass()); - service_registry_.BindRemoteServiceProvider(exposed_services.Pass()); -} - ManifestManager* RenderFrameImpl::manifest_manager() { return manifest_manager_; } @@ -2016,7 +2024,7 @@ } ServiceRegistry* RenderFrameImpl::GetServiceRegistry() { - return &service_registry_; + return service_registry_.get(); } #if defined(ENABLE_PLUGINS) @@ -2084,7 +2092,8 @@ registry->AddBuiltinModule( isolate, ServiceRegistryJsWrapper::kModuleName, - ServiceRegistryJsWrapper::Create(isolate, &service_registry_).ToV8()); + ServiceRegistryJsWrapper::Create( + isolate, service_registry_weak_factory_->GetWeakPtr()).ToV8()); } void RenderFrameImpl::AddMessageToConsole(ConsoleMessageLevel level, @@ -5325,7 +5334,7 @@ } void RenderFrameImpl::RegisterMojoServices() { - // Only main frame have ImageDownloader service. + // Only main frames have an ImageDownloader service. if (!frame_->parent()) { GetServiceRegistry()->AddService<image_downloader::ImageDownloader>( base::Bind(&ImageDownloaderImpl::CreateMojoService,
diff --git a/content/renderer/render_frame_impl.h b/content/renderer/render_frame_impl.h index bd386d4b..fd5fb08 100644 --- a/content/renderer/render_frame_impl.h +++ b/content/renderer/render_frame_impl.h
@@ -18,7 +18,6 @@ #include "base/process/process_handle.h" #include "content/common/accessibility_mode_enums.h" #include "content/common/frame_message_enums.h" -#include "content/common/mojo/service_registry_impl.h" #include "content/public/common/console_message_level.h" #include "content/public/common/javascript_message_type.h" #include "content/public/common/referrer.h" @@ -124,6 +123,7 @@ class RenderWidget; class RenderWidgetFullscreenPepper; class ScreenOrientationDispatcher; +class ServiceRegistry; class UserMediaClientImpl; class WakeLockDispatcher; struct CommonNavigationParams; @@ -603,11 +603,6 @@ // TODO(nasko): Remove this method once swapped out state is no longer used. void NavigateToSwappedOutURL(); - // Binds this render frame's service registry. - void BindServiceRegistry( - mojo::InterfaceRequest<mojo::ServiceProvider> services, - mojo::ServiceProviderPtr exposed_services); - ManifestManager* manifest_manager(); // TODO(creis): Remove when the only caller, the HistoryController, is no @@ -1056,7 +1051,11 @@ // initialized. PresentationDispatcher* presentation_dispatcher_; - ServiceRegistryImpl service_registry_; + scoped_ptr<ServiceRegistry> service_registry_; + + // Used to vend WeakPtrs to our ServiceRegistry. + scoped_ptr<base::WeakPtrFactory<ServiceRegistry>> + service_registry_weak_factory_; // The shell proxy used to connect to Mojo applications. mojo::ShellPtr mojo_shell_;
diff --git a/content/renderer/render_thread_impl.cc b/content/renderer/render_thread_impl.cc index c0d5b8a..3b17ea0d 100644 --- a/content/renderer/render_thread_impl.cc +++ b/content/renderer/render_thread_impl.cc
@@ -69,7 +69,6 @@ #include "content/common/gpu/client/gpu_channel_host.h" #include "content/common/gpu/gpu_messages.h" #include "content/common/gpu/gpu_process_launch_causes.h" -#include "content/common/render_frame_setup.mojom.h" #include "content/common/render_process_messages.h" #include "content/common/resource_messages.h" #include "content/common/service_worker/embedded_worker_setup.mojom.h" @@ -334,44 +333,6 @@ isolate->LowMemoryNotification(); } -class RenderFrameSetupImpl : public RenderFrameSetup { - public: - explicit RenderFrameSetupImpl( - mojo::InterfaceRequest<RenderFrameSetup> request) - : routing_id_highmark_(-1), binding_(this, request.Pass()) {} - - void ExchangeServiceProviders( - int32_t frame_routing_id, - mojo::InterfaceRequest<mojo::ServiceProvider> services, - mojo::ServiceProviderPtr exposed_services) - override { - // TODO(morrita): This is for investigating http://crbug.com/415059 and - // should be removed once it is fixed. - CHECK_LT(routing_id_highmark_, frame_routing_id); - routing_id_highmark_ = frame_routing_id; - - RenderFrameImpl* frame = RenderFrameImpl::FromRoutingID(frame_routing_id); - // We can receive a GetServiceProviderForFrame message for a frame not yet - // created due to a race between the message and a ViewMsg_New IPC that - // triggers creation of the RenderFrame we want. - if (!frame) { - RenderThreadImpl::current()->RegisterPendingRenderFrameConnect( - frame_routing_id, services.Pass(), exposed_services.Pass()); - return; - } - - frame->BindServiceRegistry(services.Pass(), exposed_services.Pass()); - } - - private: - int32_t routing_id_highmark_; - mojo::StrongBinding<RenderFrameSetup> binding_; -}; - -void CreateRenderFrameSetup(mojo::InterfaceRequest<RenderFrameSetup> request) { - new RenderFrameSetupImpl(request.Pass()); -} - blink::WebGraphicsContext3D::Attributes GetOffscreenAttribs() { blink::WebGraphicsContext3D::Attributes attributes; attributes.shareResources = true; @@ -383,8 +344,8 @@ } void SetupEmbeddedWorkerOnWorkerThread( - mojo::InterfaceRequest<mojo::ServiceProvider> services, - mojo::InterfacePtrInfo<mojo::ServiceProvider> exposed_services) { + mojo::InterfaceRequest<RoutedServiceProvider> services, + mojo::InterfacePtrInfo<RoutedServiceProvider> exposed_services) { ServiceWorkerContextClient* client = ServiceWorkerContextClient::ThreadSpecificInstance(); // It is possible for client to be null if for some reason the worker died @@ -404,8 +365,8 @@ void ExchangeServiceProviders( int32_t thread_id, - mojo::InterfaceRequest<mojo::ServiceProvider> services, - mojo::ServiceProviderPtr exposed_services) override { + mojo::InterfaceRequest<RoutedServiceProvider> services, + RoutedServiceProviderPtr exposed_services) override { WorkerTaskRunner::Instance()->GetTaskRunnerFor(thread_id)->PostTask( FROM_HERE, base::Bind(&SetupEmbeddedWorkerOnWorkerThread, base::Passed(&services), @@ -805,8 +766,6 @@ base::DiscardableMemoryAllocator::SetInstance( ChildThreadImpl::discardable_shared_memory_manager()); - service_registry()->AddService<RenderFrameSetup>( - base::Bind(CreateRenderFrameSetup)); service_registry()->AddService<EmbeddedWorkerSetup>( base::Bind(CreateEmbeddedWorkerSetup)); } @@ -1016,24 +975,6 @@ void RenderThreadImpl::AddRoute(int32 routing_id, IPC::Listener* listener) { ChildThreadImpl::GetRouter()->AddRoute(routing_id, listener); - PendingRenderFrameConnectMap::iterator it = - pending_render_frame_connects_.find(routing_id); - if (it == pending_render_frame_connects_.end()) - return; - - RenderFrameImpl* frame = RenderFrameImpl::FromRoutingID(routing_id); - if (!frame) - return; - - scoped_refptr<PendingRenderFrameConnect> connection(it->second); - mojo::InterfaceRequest<mojo::ServiceProvider> services( - connection->services().Pass()); - mojo::ServiceProviderPtr exposed_services( - connection->exposed_services().Pass()); - exposed_services.set_connection_error_handler(mojo::Closure()); - pending_render_frame_connects_.erase(it); - - frame->BindServiceRegistry(services.Pass(), exposed_services.Pass()); } void RenderThreadImpl::RemoveRoute(int32 routing_id) { @@ -1057,18 +998,6 @@ } } -void RenderThreadImpl::RegisterPendingRenderFrameConnect( - int routing_id, - mojo::InterfaceRequest<mojo::ServiceProvider> services, - mojo::ServiceProviderPtr exposed_services) { - std::pair<PendingRenderFrameConnectMap::iterator, bool> result = - pending_render_frame_connects_.insert(std::make_pair( - routing_id, - make_scoped_refptr(new PendingRenderFrameConnect( - routing_id, services.Pass(), exposed_services.Pass())))); - CHECK(result.second) << "Inserting a duplicate item."; -} - int RenderThreadImpl::GenerateRoutingID() { int routing_id = MSG_ROUTING_NONE; Send(new ViewHostMsg_GenerateRoutingID(&routing_id)); @@ -2050,29 +1979,4 @@ blink::decommitFreeableMemory(); } -RenderThreadImpl::PendingRenderFrameConnect::PendingRenderFrameConnect( - int routing_id, - mojo::InterfaceRequest<mojo::ServiceProvider> services, - mojo::ServiceProviderPtr exposed_services) - : routing_id_(routing_id), - services_(services.Pass()), - exposed_services_(exposed_services.Pass()) { - // The RenderFrame may be deleted before the ExchangeServiceProviders message - // is received. In that case, the RenderFrameHost should close the connection, - // which is detected by setting an error handler on |exposed_services_|. - exposed_services_.set_connection_error_handler(base::Bind( - &RenderThreadImpl::PendingRenderFrameConnect::OnConnectionError, - base::Unretained(this))); -} - -RenderThreadImpl::PendingRenderFrameConnect::~PendingRenderFrameConnect() { -} - -void RenderThreadImpl::PendingRenderFrameConnect::OnConnectionError() { - size_t erased = - RenderThreadImpl::current()->pending_render_frame_connects_.erase( - routing_id_); - DCHECK_EQ(1u, erased); -} - } // namespace content
diff --git a/content/renderer/render_thread_impl.h b/content/renderer/render_thread_impl.h index abd0289..ad108dc 100644 --- a/content/renderer/render_thread_impl.h +++ b/content/renderer/render_thread_impl.h
@@ -440,11 +440,6 @@ void AddEmbeddedWorkerRoute(int32 routing_id, IPC::Listener* listener); void RemoveEmbeddedWorkerRoute(int32 routing_id); - void RegisterPendingRenderFrameConnect( - int routing_id, - mojo::InterfaceRequest<mojo::ServiceProvider> services, - mojo::ServiceProviderPtr exposed_services); - protected: RenderThreadImpl(const InProcessChildThreadParams& params, scoped_ptr<scheduler::RendererScheduler> scheduler); @@ -657,37 +652,6 @@ bool are_image_decode_tasks_enabled_; bool is_threaded_animation_enabled_; - class PendingRenderFrameConnect - : public base::RefCounted<PendingRenderFrameConnect> { - public: - PendingRenderFrameConnect( - int routing_id, - mojo::InterfaceRequest<mojo::ServiceProvider> services, - mojo::ServiceProviderPtr exposed_services); - - mojo::InterfaceRequest<mojo::ServiceProvider>& services() { - return services_; - } - - mojo::ServiceProviderPtr& exposed_services() { return exposed_services_; } - - private: - friend class base::RefCounted<PendingRenderFrameConnect>; - - ~PendingRenderFrameConnect(); - - // Mojo error handler. - void OnConnectionError(); - - int routing_id_; - mojo::InterfaceRequest<mojo::ServiceProvider> services_; - mojo::ServiceProviderPtr exposed_services_; - }; - - typedef std::map<int, scoped_refptr<PendingRenderFrameConnect>> - PendingRenderFrameConnectMap; - PendingRenderFrameConnectMap pending_render_frame_connects_; - DISALLOW_COPY_AND_ASSIGN(RenderThreadImpl); };
diff --git a/content/renderer/render_view_browsertest.cc b/content/renderer/render_view_browsertest.cc index 724c8e8..85a8ae7 100644 --- a/content/renderer/render_view_browsertest.cc +++ b/content/renderer/render_view_browsertest.cc
@@ -338,7 +338,7 @@ public: void Attach() { std::string host_id = "host_id"; - agent()->OnAttach(host_id); + agent()->OnAttach(host_id, 17); } void Detach() { @@ -350,7 +350,7 @@ } void DispatchDevToolsMessage(const std::string& message) { - agent()->OnDispatchOnInspectorBackend(message); + agent()->OnDispatchOnInspectorBackend(17, message); } void CloseWhilePaused() {
diff --git a/content/renderer/service_worker/embedded_worker_devtools_agent.cc b/content/renderer/service_worker/embedded_worker_devtools_agent.cc index e1c640a..a099729 100644 --- a/content/renderer/service_worker/embedded_worker_devtools_agent.cc +++ b/content/renderer/service_worker/embedded_worker_devtools_agent.cc
@@ -40,13 +40,15 @@ return handled; } -void EmbeddedWorkerDevToolsAgent::OnAttach(const std::string& host_id) { - webworker_->attachDevTools(WebString::fromUTF8(host_id)); +void EmbeddedWorkerDevToolsAgent::OnAttach(const std::string& host_id, + int session_id) { + webworker_->attachDevTools(WebString::fromUTF8(host_id), session_id); } void EmbeddedWorkerDevToolsAgent::OnReattach(const std::string& host_id, + int session_id, const std::string& state) { - webworker_->reattachDevTools(WebString::fromUTF8(host_id), + webworker_->reattachDevTools(WebString::fromUTF8(host_id), session_id, WebString::fromUTF8(state)); } @@ -55,8 +57,9 @@ } void EmbeddedWorkerDevToolsAgent::OnDispatchOnInspectorBackend( + int session_id, const std::string& message) { - webworker_->dispatchDevToolsMessage(WebString::fromUTF8(message)); + webworker_->dispatchDevToolsMessage(session_id, WebString::fromUTF8(message)); } } // namespace content
diff --git a/content/renderer/service_worker/embedded_worker_devtools_agent.h b/content/renderer/service_worker/embedded_worker_devtools_agent.h index 97c15824..c63081e 100644 --- a/content/renderer/service_worker/embedded_worker_devtools_agent.h +++ b/content/renderer/service_worker/embedded_worker_devtools_agent.h
@@ -30,10 +30,12 @@ bool OnMessageReceived(const IPC::Message& message) override; private: - void OnAttach(const std::string& host_id); - void OnReattach(const std::string& host_id, const std::string& state); + void OnAttach(const std::string& host_id, int session_id); + void OnReattach(const std::string& host_id, + int session_id, + const std::string& state); void OnDetach(); - void OnDispatchOnInspectorBackend(const std::string& message); + void OnDispatchOnInspectorBackend(int session_id, const std::string& message); blink::WebEmbeddedWorker* webworker_; int route_id_;
diff --git a/content/renderer/service_worker/service_worker_context_client.cc b/content/renderer/service_worker/service_worker_context_client.cc index f11338fb..7a5e37e 100644 --- a/content/renderer/service_worker/service_worker_context_client.cc +++ b/content/renderer/service_worker/service_worker_context_client.cc
@@ -277,8 +277,8 @@ } void ServiceWorkerContextClient::BindServiceRegistry( - mojo::InterfaceRequest<mojo::ServiceProvider> services, - mojo::ServiceProviderPtr exposed_services) { + mojo::InterfaceRequest<RoutedServiceProvider> services, + RoutedServiceProviderPtr exposed_services) { context_->service_registry.Bind(services.Pass()); context_->service_registry.BindRemoteServiceProvider(exposed_services.Pass()); } @@ -468,12 +468,13 @@ } void ServiceWorkerContextClient::sendDevToolsMessage( + int session_id, int call_id, const blink::WebString& message, const blink::WebString& state_cookie) { DevToolsAgent::SendChunkedProtocolMessage( - sender_.get(), worker_devtools_agent_route_id_, - call_id, message.utf8(), state_cookie.utf8()); + sender_.get(), worker_devtools_agent_route_id_, session_id, call_id, + message.utf8(), state_cookie.utf8()); } void ServiceWorkerContextClient::didHandleActivateEvent(
diff --git a/content/renderer/service_worker/service_worker_context_client.h b/content/renderer/service_worker/service_worker_context_client.h index b3fd33d9..14bec2d 100644 --- a/content/renderer/service_worker/service_worker_context_client.h +++ b/content/renderer/service_worker/service_worker_context_client.h
@@ -15,10 +15,10 @@ #include "base/strings/string16.h" #include "base/time/time.h" #include "content/child/webmessageportchannel_impl.h" +#include "content/common/routed_service_provider.mojom.h" #include "content/common/service_worker/service_worker_types.h" #include "content/public/common/service_worker_event_status.mojom.h" #include "ipc/ipc_listener.h" -#include "mojo/application/public/interfaces/service_provider.mojom.h" #include "third_party/WebKit/public/platform/WebGeofencingEventType.h" #include "third_party/WebKit/public/platform/WebMessagePortChannel.h" #include "third_party/WebKit/public/platform/modules/serviceworker/WebServiceWorkerError.h" @@ -82,8 +82,8 @@ // ServiceRegistry to connect to services before this method is called are // queued up and will resolve after this method is called. void BindServiceRegistry( - mojo::InterfaceRequest<mojo::ServiceProvider> services, - mojo::ServiceProviderPtr exposed_services); + mojo::InterfaceRequest<RoutedServiceProvider> services, + RoutedServiceProviderPtr exposed_services); // WebServiceWorkerContextClient overrides. blink::WebURL scope() const override; @@ -117,7 +117,8 @@ const blink::WebString& message, int line_number, const blink::WebString& source_url) override; - void sendDevToolsMessage(int call_id, + void sendDevToolsMessage(int session_id, + int call_id, const blink::WebString& message, const blink::WebString& state) override; void didHandleActivateEvent(int request_id,
diff --git a/content/renderer/shared_worker/embedded_shared_worker_stub.cc b/content/renderer/shared_worker/embedded_shared_worker_stub.cc index 934dade..975bab9 100644 --- a/content/renderer/shared_worker/embedded_shared_worker_stub.cc +++ b/content/renderer/shared_worker/embedded_shared_worker_stub.cc
@@ -253,10 +253,12 @@ } void EmbeddedSharedWorkerStub::sendDevToolsMessage( + int session_id, int call_id, const blink::WebString& message, const blink::WebString& state) { - worker_devtools_agent_->SendDevToolsMessage(call_id, message, state); + worker_devtools_agent_->SendDevToolsMessage( + session_id, call_id, message, state); } void EmbeddedSharedWorkerStub::Shutdown() {
diff --git a/content/renderer/shared_worker/embedded_shared_worker_stub.h b/content/renderer/shared_worker/embedded_shared_worker_stub.h index 9f2c6c0..a7d62d0 100644 --- a/content/renderer/shared_worker/embedded_shared_worker_stub.h +++ b/content/renderer/shared_worker/embedded_shared_worker_stub.h
@@ -70,7 +70,8 @@ const blink::WebSecurityOrigin& origin) override; blink::WebServiceWorkerNetworkProvider* createServiceWorkerNetworkProvider( blink::WebDataSource*) override; - void sendDevToolsMessage(int call_id, + void sendDevToolsMessage(int session_id, + int call_id, const blink::WebString& message, const blink::WebString& state) override;
diff --git a/content/shell/BUILD.gn b/content/shell/BUILD.gn index 38a917ff..1e567e16 100644 --- a/content/shell/BUILD.gn +++ b/content/shell/BUILD.gn
@@ -288,9 +288,9 @@ sources += [ "browser/shell_views.cc" ] deps += [ "//ui/resources", - "//ui/views/controls/webview", "//ui/views", "//ui/views:test_support", + "//ui/views/controls/webview", ] } else { sources += [ "browser/shell_aura.cc" ]
diff --git a/content/shell/android/BUILD.gn b/content/shell/android/BUILD.gn index 756416d..bbffa73 100644 --- a/content/shell/android/BUILD.gn +++ b/content/shell/android/BUILD.gn
@@ -22,11 +22,11 @@ deps = [ ":content_shell_jni_headers", "//build/config/sanitizers:deps", + "//components/crash/content/browser", "//content/shell:content_shell_lib", "//content/shell:pak", - "//components/crash/content/browser", - "//skia", "//media/base/android", + "//skia", ] sources = [ "shell_library_loader.cc", @@ -42,13 +42,13 @@ android_library("content_shell_java") { testonly = true deps = [ + ":content_shell_java_resources", "//base:base_java", "//content/public/android:content_java", "//media/base/android:media_java", "//mojo/public/java:system", "//net/android:net_java", "//ui/android:ui_java", - ":content_shell_java_resources", ] DEPRECATED_java_in_dir = "java/src" } @@ -126,21 +126,21 @@ android_library("content_shell_test_java") { testonly = true deps = [ - ":content_shell_java", ":content_shell_apk_java", + ":content_shell_java", "//base:base_java", "//base:base_java_test_support", + "//content/public/android:content_java", "//content/public/test/android:content_java_test_support", "//content/shell/android:content_shell_java", - "//content/public/android:content_java", ] DEPRECATED_java_in_dir = "javatests/src" } instrumentation_test_apk("content_shell_test_apk") { deps = [ - "//content/public/android:content_javatests", "//base:base_javatests", + "//content/public/android:content_javatests", "//net/android:net_javatests", ] data_deps = [
diff --git a/content/shell/browser/layout_test/layout_test_push_messaging_service.cc b/content/shell/browser/layout_test/layout_test_push_messaging_service.cc index 78db934..95a6a86 100644 --- a/content/shell/browser/layout_test/layout_test_push_messaging_service.cc +++ b/content/shell/browser/layout_test/layout_test_push_messaging_service.cc
@@ -29,6 +29,14 @@ static_assert(sizeof(kTestP256Key) == 65, "The fake public key must be a valid P-256 uncompressed point."); +// 92-bit (12 byte) authentication key associated with a subscription. +const uint8_t kAuthentication[] = { + 0xA5, 0xD9, 0x3C, 0x43, 0x0C, 0x00, 0xA9, 0xE3, 0x1E, 0x65, 0xBF, 0xA1 +}; + +static_assert(sizeof(kAuthentication) == 12, + "The fake authentication key must be at least 12 bytes in size."); + blink::WebPushPermissionStatus ToWebPushPermissionStatus( PermissionStatus status) { switch (status) { @@ -78,11 +86,14 @@ blink::WebPushPermissionStatusGranted) { std::vector<uint8_t> p256dh( kTestP256Key, kTestP256Key + arraysize(kTestP256Key)); + std::vector<uint8_t> auth( + kAuthentication, kAuthentication + arraysize(kAuthentication)); - callback.Run("layoutTestRegistrationId", p256dh, + callback.Run("layoutTestRegistrationId", p256dh, auth, PUSH_REGISTRATION_STATUS_SUCCESS_FROM_PUSH_SERVICE); } else { - callback.Run("registration_id", std::vector<uint8_t>(), + callback.Run("registration_id", std::vector<uint8_t>() /* p256dh */, + std::vector<uint8_t>() /* auth */, PUSH_REGISTRATION_STATUS_PERMISSION_DENIED); } } @@ -93,8 +104,10 @@ const PublicKeyCallback& callback) { std::vector<uint8_t> p256dh( kTestP256Key, kTestP256Key + arraysize(kTestP256Key)); + std::vector<uint8_t> auth( + kAuthentication, kAuthentication + arraysize(kAuthentication)); - callback.Run(true /* success */, p256dh); + callback.Run(true /* success */, p256dh, auth); } blink::WebPushPermissionStatus
diff --git a/content/shell/browser/shell_mojo_test_utils_android.cc b/content/shell/browser/shell_mojo_test_utils_android.cc index e0f97c3..3a3e192c 100644 --- a/content/shell/browser/shell_mojo_test_utils_android.cc +++ b/content/shell/browser/shell_mojo_test_utils_android.cc
@@ -4,11 +4,14 @@ #include "content/shell/browser/shell_mojo_test_utils_android.h" +#include <utility> + #include "base/memory/scoped_vector.h" #include "base/message_loop/message_loop.h" #include "base/run_loop.h" #include "content/browser/mojo/service_registry_android.h" #include "content/common/mojo/service_registry_impl.h" +#include "content/common/routed_service_provider.mojom.h" #include "jni/ShellMojoTestUtils_jni.h" namespace { @@ -46,13 +49,13 @@ content::ServiceRegistryImpl* registry_b = new ServiceRegistryImpl(); test_environment->registries.push_back(registry_b); - mojo::ServiceProviderPtr exposed_services_a; + RoutedServiceProviderPtr exposed_services_a; registry_a->Bind(GetProxy(&exposed_services_a)); - registry_b->BindRemoteServiceProvider(exposed_services_a.Pass()); + registry_b->BindRemoteServiceProvider(std::move(exposed_services_a)); - mojo::ServiceProviderPtr exposed_services_b; + RoutedServiceProviderPtr exposed_services_b; registry_b->Bind(GetProxy(&exposed_services_b)); - registry_a->BindRemoteServiceProvider(exposed_services_b.Pass()); + registry_a->BindRemoteServiceProvider(std::move(exposed_services_b)); content::ServiceRegistryAndroid* wrapper_a = new ServiceRegistryAndroid(registry_a);
diff --git a/content/shell/renderer/layout_test/blink_test_runner.cc b/content/shell/renderer/layout_test/blink_test_runner.cc index 45f129e..583745c1 100644 --- a/content/shell/renderer/layout_test/blink_test_runner.cc +++ b/content/shell/renderer/layout_test/blink_test_runner.cc
@@ -47,6 +47,7 @@ #include "content/shell/renderer/layout_test/blink_test_helpers.h" #include "content/shell/renderer/layout_test/layout_test_render_process_observer.h" #include "content/shell/renderer/layout_test/leak_detector.h" +#include "media/audio/audio_parameters.h" #include "net/base/filename_util.h" #include "net/base/net_errors.h" #include "skia/ext/platform_canvas.h" @@ -239,6 +240,22 @@ void StopCapture() override {} }; +class MockAudioCapturerSource : public media::AudioCapturerSource { + public: + MockAudioCapturerSource() = default; + + void Initialize(const media::AudioParameters& params, + CaptureCallback* callback, + int session_id) override {} + void Start() override {} + void Stop() override {} + void SetVolume(double volume) override {} + void SetAutomaticGainControl(bool enable) override {} + + protected: + ~MockAudioCapturerSource() override {} +}; + } // namespace BlinkTestRunner::BlinkTestRunner(RenderView* render_view) @@ -743,15 +760,25 @@ test_runner::WebTestProxyBase* proxy) { } -bool BlinkTestRunner::AddMediaStreamSourceAndTrack( +bool BlinkTestRunner::AddMediaStreamVideoSourceAndTrack( blink::WebMediaStream* stream) { DCHECK(stream); #if defined(ENABLE_WEBRTC) return AddVideoTrackToMediaStream( make_scoped_ptr(new MockVideoCapturerSource()), - false /* is_remote */, - false /* is_readonly */, - stream); + false /* is_remote */, false /* is_readonly */, stream); +#else + return false; +#endif +} + +bool BlinkTestRunner::AddMediaStreamAudioSourceAndTrack( + blink::WebMediaStream* stream) { + DCHECK(stream); +#if defined(ENABLE_WEBRTC) + return AddAudioTrackToMediaStream( + make_scoped_refptr(new MockAudioCapturerSource()), + false /* is_remote */, false /* is_readonly */, stream); #else return false; #endif
diff --git a/content/shell/renderer/layout_test/blink_test_runner.h b/content/shell/renderer/layout_test/blink_test_runner.h index 0c45096..9e0f053 100644 --- a/content/shell/renderer/layout_test/blink_test_runner.h +++ b/content/shell/renderer/layout_test/blink_test_runner.h
@@ -133,7 +133,10 @@ const GURL& origin, const GURL& embedding_origin) override; void ResetPermissions() override; - bool AddMediaStreamSourceAndTrack(blink::WebMediaStream* stream) override; + bool AddMediaStreamVideoSourceAndTrack( + blink::WebMediaStream* stream) override; + bool AddMediaStreamAudioSourceAndTrack( + blink::WebMediaStream* stream) override; cc::SharedBitmapManager* GetSharedBitmapManager() override; void DispatchBeforeInstallPromptEvent( int request_id,
diff --git a/content/test/BUILD.gn b/content/test/BUILD.gn index 69fff6e..ec2bfca 100644 --- a/content/test/BUILD.gn +++ b/content/test/BUILD.gn
@@ -43,12 +43,12 @@ "//testing/gtest", "//ui/accessibility:ax_gen", "//ui/base", - "//ui/base/ime", "//ui/base:test_support", + "//ui/base/ime", "//ui/events:dom_keycode_converter", "//ui/events:events_base", - "//ui/events:test_support", "//ui/events:gesture_detection", + "//ui/events:test_support", "//ui/gfx:test_support", "//ui/gl", "//ui/gl:test_support", @@ -65,17 +65,17 @@ public_deps += [ "//third_party/WebKit/public:blink" ] deps += [ ":content_test_mojo_bindings", + "//cc", + "//cc:test_support", "//components/scheduler:scheduler", "//components/scheduler:test_support", "//content/browser/speech/proto", - "//content/public/child", "//content/gpu", + "//content/public/child", "//content/public/plugin", "//content/public/renderer", "//content/public/utility", "//content/shell:pak", - "//cc", - "//cc:test_support", "//ipc/mojo", "//media", "//mojo/application/public/cpp:cpp_for_chromium", @@ -134,8 +134,8 @@ if (use_aura || is_mac) { deps += [ - "//ui/compositor", "//third_party/libvpx_new", + "//ui/compositor", ] sources += [ @@ -155,7 +155,7 @@ ] } - if (is_android) { + if (is_android && !use_aura) { deps += [ "//ui/android", "//ui/shell_dialogs", @@ -243,8 +243,8 @@ "//components/test_runner:test_runner", "//content/public/common", "//skia", - "//v8", "//ui/accessibility:ax_gen", + "//v8", ] if (is_android) { @@ -356,13 +356,13 @@ ":web_ui_test_mojo_bindings", "//base/allocator", "//base/test:test_support", + "//content:resources", "//content/browser/background_sync:background_sync_proto", "//content/common:mojo_bindings", "//content/gpu", "//content/public/common", "//content/public/plugin", "//content/public/renderer", - "//content:resources", "//content/shell:content_shell_lib", "//content/shell:pak", "//content/test:test_support", @@ -372,10 +372,10 @@ "//gin", "//gpu", "//ipc:test_support", + "//media:shared_memory_support", "//media:test_support", "//media/audio:test_support", "//media/base:test_support", - "//media:shared_memory_support", "//mojo/application/public/cpp:cpp_for_chromium", "//mojo/environment:chromium", "//mojo/public/cpp/bindings", @@ -386,13 +386,13 @@ "//ppapi/proxy", "//ppapi/proxy:ipc", "//ppapi/shared_impl", - "//third_party/mojo/src/mojo/edk/system", - "//third_party/mojo/src/mojo/edk/test:test_support", "//testing/gmock", "//testing/gtest", "//third_party/WebKit/public:blink", "//third_party/leveldatabase", "//third_party/mesa:osmesa", + "//third_party/mojo/src/mojo/edk/system", + "//third_party/mojo/src/mojo/edk/test:test_support", "//third_party/zlib", "//ui/accessibility", "//ui/accessibility:ax_gen", @@ -443,8 +443,8 @@ [ "../browser/battery_status/battery_monitor_impl_browsertest.cc" ] deps -= [ "//device/battery" ] deps += [ - "//content/shell/android:content_shell_jni_headers", "//content/shell:content_shell_lib", + "//content/shell/android:content_shell_jni_headers", "//testing/android/native_test:native_test_support", ] apk_deps = [ @@ -549,9 +549,7 @@ } } - configs += [ - "//build/config:precompiled_headers", - ] + configs += [ "//build/config:precompiled_headers" ] deps = [ ":test_support", @@ -604,8 +602,8 @@ "//gpu", "//gpu:test_support", "//ipc:test_support", - "//media:test_support", "//media:shared_memory_support", + "//media:test_support", "//media/audio:test_support", "//media/base:test_support", "//media/midi:midi", @@ -782,10 +780,10 @@ deps = [ "//base/allocator", "//base/test:test_support", + "//cc", "//content/public/browser", "//content/public/common", "//content/test:test_support", - "//cc", "//skia", "//testing/gtest", "//testing/perf",
diff --git a/content/test/layouttest_support.cc b/content/test/layouttest_support.cc index 3996ccb..b33a505 100644 --- a/content/test/layouttest_support.cc +++ b/content/test/layouttest_support.cc
@@ -6,6 +6,7 @@ #include "base/callback.h" #include "base/lazy_instance.h" +#include "base/strings/string_util.h" #include "components/test_runner/test_common.h" #include "components/test_runner/web_frame_test_proxy.h" #include "components/test_runner/web_test_proxy.h" @@ -399,18 +400,12 @@ DisableAutoResizeForTesting(new_size); } -struct ToLower { - base::char16 operator()(base::char16 c) { return tolower(c); } -}; - // Returns True if node1 < node2. bool HistoryEntryCompareLess(HistoryEntry::HistoryNode* node1, HistoryEntry::HistoryNode* node2) { base::string16 target1 = node1->item().target(); base::string16 target2 = node2->item().target(); - std::transform(target1.begin(), target1.end(), target1.begin(), ToLower()); - std::transform(target2.begin(), target2.end(), target2.begin(), ToLower()); - return target1 < target2; + return base::CompareCaseInsensitiveASCII(target1, target2) < 0; } std::string DumpHistoryItem(HistoryEntry::HistoryNode* node,
diff --git a/content/test/net/url_request_abort_on_end_job.cc b/content/test/net/url_request_abort_on_end_job.cc index 6d237a8..f7ff5a9 100644 --- a/content/test/net/url_request_abort_on_end_job.cc +++ b/content/test/net/url_request_abort_on_end_job.cc
@@ -8,7 +8,6 @@ #include "base/compiler_specific.h" #include "base/location.h" -#include "base/numerics/safe_conversions.h" #include "base/single_thread_task_runner.h" #include "base/strings/string_util.h" #include "base/thread_task_runner_handle.h" @@ -112,16 +111,20 @@ weak_factory_.GetWeakPtr())); } -int URLRequestAbortOnEndJob::ReadRawData(net::IOBuffer* buf, int max_bytes) { +bool URLRequestAbortOnEndJob::ReadRawData(net::IOBuffer* buf, + const int max_bytes, + int* bytes_read) { if (!sent_data_) { - max_bytes = - std::min(max_bytes, base::checked_cast<int>(sizeof(kPageContent))); - std::memcpy(buf->data(), kPageContent, max_bytes); + *bytes_read = std::min(size_t(max_bytes), sizeof(kPageContent)); + std::memcpy(buf->data(), kPageContent, *bytes_read); sent_data_ = true; - return max_bytes; + return true; } - return net::ERR_CONNECTION_ABORTED; + SetStatus(net::URLRequestStatus(net::URLRequestStatus::FAILED, + net::ERR_CONNECTION_ABORTED)); + *bytes_read = -1; + return false; } } // namespace content
diff --git a/content/test/net/url_request_abort_on_end_job.h b/content/test/net/url_request_abort_on_end_job.h index 8a95533..88e348c 100644 --- a/content/test/net/url_request_abort_on_end_job.h +++ b/content/test/net/url_request_abort_on_end_job.h
@@ -29,7 +29,7 @@ void Start() override; bool GetMimeType(std::string* mime_type) const override; void GetResponseInfo(net::HttpResponseInfo* info) override; - int ReadRawData(net::IOBuffer* buf, int buf_size) override; + bool ReadRawData(net::IOBuffer* buf, int buf_size, int* bytes_read) override; static void AddUrlHandler();
diff --git a/content/test/test_render_frame_host.cc b/content/test/test_render_frame_host.cc index 687bae5..9a36b7c 100644 --- a/content/test/test_render_frame_host.cc +++ b/content/test/test_render_frame_host.cc
@@ -286,6 +286,12 @@ params.history_list_was_cleared = simulate_history_list_was_cleared_; params.original_request_url = url_copy; + // In most cases, the origin will match the URL's origin. Tests that need to + // check corner cases (like about:blank) should specify the origin param + // manually. + url::Origin origin(url_copy); + params.origin = origin; + url::Replacements<char> replacements; replacements.ClearRef(); params.was_within_same_page =
diff --git a/device/bluetooth/BUILD.gn b/device/bluetooth/BUILD.gn index 82c266f..666e1e3 100644 --- a/device/bluetooth/BUILD.gn +++ b/device/bluetooth/BUILD.gn
@@ -114,12 +114,12 @@ all_dependent_configs = [ ":bluetooth_config" ] deps = [ - "strings", - "uribeacon", "//base", "//crypto", "//net", "//ui/base", + "strings", + "uribeacon", ] if (is_android) {
diff --git a/device/bluetooth/bluetooth_bluez_unittest.cc b/device/bluetooth/bluetooth_bluez_unittest.cc index e82d04d..a01e73d 100644 --- a/device/bluetooth/bluetooth_bluez_unittest.cc +++ b/device/bluetooth/bluetooth_bluez_unittest.cc
@@ -175,7 +175,10 @@ dbus_setter->SetBluetoothAdapterClient( scoped_ptr<bluez::BluetoothAdapterClient>( fake_bluetooth_adapter_client_)); + fake_bluetooth_device_client_ = new bluez::FakeBluetoothDeviceClient; + // Use the original fake behavior for these tests. + fake_bluetooth_device_client_->set_delay_start_discovery(true); dbus_setter->SetBluetoothDeviceClient( scoped_ptr<bluez::BluetoothDeviceClient>( fake_bluetooth_device_client_));
diff --git a/device/bluetooth/dbus/fake_bluetooth_device_client.cc b/device/bluetooth/dbus/fake_bluetooth_device_client.cc index e6c137b..a2ea92db 100644 --- a/device/bluetooth/dbus/fake_bluetooth_device_client.cc +++ b/device/bluetooth/dbus/fake_bluetooth_device_client.cc
@@ -267,7 +267,8 @@ pairing_cancelled_(false), connection_rssi_(kUnkownPower), transmit_power_(kUnkownPower), - max_transmit_power_(kUnkownPower) { + max_transmit_power_(kUnkownPower), + delay_start_discovery_(false) { scoped_ptr<Properties> properties(new Properties( base::Bind(&FakeBluetoothDeviceClient::OnPropertyChanged, base::Unretained(this), dbus::ObjectPath(kPairedDevicePath)))); @@ -548,12 +549,13 @@ VLOG(1) << "starting discovery simulation"; discovery_simulation_step_ = 1; + int delay = delay_start_discovery_ ? simulation_interval_ms_ : 0; base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( FROM_HERE, base::Bind(&FakeBluetoothDeviceClient::DiscoverySimulationTimer, base::Unretained(this)), - base::TimeDelta::FromMilliseconds(simulation_interval_ms_)); + base::TimeDelta::FromMilliseconds(delay)); } void FakeBluetoothDeviceClient::EndDiscoverySimulation( @@ -1041,12 +1043,17 @@ // Timer fires every .75s, the numbers below are arbitrary to give a feel // for a discovery process. VLOG(1) << "discovery simulation, step " << discovery_simulation_step_; - if (discovery_simulation_step_ == 2) { + uint32_t initial_step = delay_start_discovery_ ? 2 : 1; + if (discovery_simulation_step_ == initial_step) { CreateDevice(dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath), dbus::ObjectPath(kLegacyAutopairPath)); CreateDevice(dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath), dbus::ObjectPath(kLowEnergyPath)); - + if (!delay_start_discovery_) { + // Include a device that requires a pairing overlay in the UI. + CreateDevice(dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath), + dbus::ObjectPath(kRequestPinCodePath)); + } } else if (discovery_simulation_step_ == 4) { UpdateDeviceRSSI(dbus::ObjectPath(kLowEnergyPath), base::RandInt(kMinRSSI, kMaxRSSI)); @@ -1064,11 +1071,12 @@ } else if (discovery_simulation_step_ == 8) { CreateDevice(dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath), dbus::ObjectPath(kDisplayPasskeyPath)); - CreateDevice(dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath), - dbus::ObjectPath(kRequestPinCodePath)); + if (delay_start_discovery_) { + CreateDevice(dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath), + dbus::ObjectPath(kRequestPinCodePath)); + } UpdateDeviceRSSI(dbus::ObjectPath(kLowEnergyPath), base::RandInt(kMinRSSI, kMaxRSSI)); - } else if (discovery_simulation_step_ == 10) { CreateDevice(dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath), dbus::ObjectPath(kConfirmPasskeyPath));
diff --git a/device/bluetooth/dbus/fake_bluetooth_device_client.h b/device/bluetooth/dbus/fake_bluetooth_device_client.h index f8051b4..67d760b4 100644 --- a/device/bluetooth/dbus/fake_bluetooth_device_client.h +++ b/device/bluetooth/dbus/fake_bluetooth_device_client.h
@@ -145,6 +145,8 @@ uint16 transmit_power, uint16 max_transmit_power); + void set_delay_start_discovery(bool value) { delay_start_discovery_ = value; } + static const char kTestPinCode[]; static const int kTestPassKey; @@ -314,6 +316,10 @@ int16 connection_rssi_; int16 transmit_power_; int16 max_transmit_power_; + + // Controls the fake behavior to allow more extensive UI testing without + // having to cycle the discovery simulation. + bool delay_start_discovery_; }; } // namespace bluez
diff --git a/device/core/BUILD.gn b/device/core/BUILD.gn index e85acb6..b7e6ac2 100644 --- a/device/core/BUILD.gn +++ b/device/core/BUILD.gn
@@ -8,6 +8,8 @@ sources = [ "device_client.cc", "device_client.h", + "device_info_query_win.cc", + "device_info_query_win.h", "device_monitor_win.cc", "device_monitor_win.h", ] @@ -17,4 +19,8 @@ public_deps = [ "//base", ] + + if (is_win) { + libs = [ "setupapi.lib" ] + } }
diff --git a/device/core/core.gyp b/device/core/core.gyp index d27073d..6002a5f 100644 --- a/device/core/core.gyp +++ b/device/core/core.gyp
@@ -19,6 +19,8 @@ 'sources': [ 'device_client.cc', 'device_client.h', + 'device_info_query_win.cc', + 'device_info_query_win.h', 'device_monitor_win.cc', 'device_monitor_win.h', ],
diff --git a/device/core/device_info_query_win.cc b/device/core/device_info_query_win.cc new file mode 100644 index 0000000..4d62b32 --- /dev/null +++ b/device/core/device_info_query_win.cc
@@ -0,0 +1,66 @@ +// Copyright 2015 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 "device/core/device_info_query_win.h" + +#include <string.h> + +#include "base/strings/string_util.h" + +namespace device { + +DeviceInfoQueryWin::DeviceInfoQueryWin() + : device_info_list_(SetupDiCreateDeviceInfoList(nullptr, nullptr)) { + memset(&device_info_data_, 0, sizeof(device_info_data_)); +} + +DeviceInfoQueryWin::~DeviceInfoQueryWin() { + if (device_info_list_valid()) { + // Release |device_info_data_| only when it is valid. + if (device_info_data_.cbSize != 0) + SetupDiDeleteDeviceInfo(device_info_list_, &device_info_data_); + SetupDiDestroyDeviceInfoList(device_info_list_); + } +} + +bool DeviceInfoQueryWin::AddDevice(const char* device_path) { + return SetupDiOpenDeviceInterfaceA(device_info_list_, device_path, 0, + nullptr) != FALSE; +} + +bool DeviceInfoQueryWin::GetDeviceInfo() { + DCHECK_EQ(0U, device_info_data_.cbSize); + device_info_data_.cbSize = sizeof(device_info_data_); + if (!SetupDiEnumDeviceInfo(device_info_list_, 0, &device_info_data_)) { + // Clear cbSize to maintain the invariant. + device_info_data_.cbSize = 0; + return false; + } + return true; +} + +bool DeviceInfoQueryWin::GetDeviceStringProperty(DWORD property, + std::string* property_buffer) { + DWORD property_reg_data_type; + const size_t property_buffer_length = 512; + if (!SetupDiGetDeviceRegistryPropertyA( + device_info_list_, &device_info_data_, property, + &property_reg_data_type, + reinterpret_cast<PBYTE>( + base::WriteInto(property_buffer, property_buffer_length)), + static_cast<DWORD>(property_buffer_length), nullptr)) + return false; + + if (property_reg_data_type != REG_SZ) + return false; + + // Shrink |property_buffer| down to its correct size. + size_t eos = property_buffer->find('\0'); + if (eos != std::string::npos) + property_buffer->resize(eos); + + return true; +} + +} // namespace device
diff --git a/device/core/device_info_query_win.h b/device/core/device_info_query_win.h new file mode 100644 index 0000000..2e399e49 --- /dev/null +++ b/device/core/device_info_query_win.h
@@ -0,0 +1,49 @@ +// Copyright 2015 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 DEVICE_CORE_DEVICE_INFO_QUERY_WIN_H_ +#define DEVICE_CORE_DEVICE_INFO_QUERY_WIN_H_ + +#include <windows.h> +#include <setupapi.h> + +#include <string> + +#include "base/macros.h" +#include "device/core/device_core_export.h" + +namespace device { + +// Wraps HDEVINFO and SP_DEVINFO_DATA into a class that can automatically +// release them. Provides interfaces that can add a device using its +// device path, get device info and get device string property. +class DEVICE_CORE_EXPORT DeviceInfoQueryWin { + public: + DeviceInfoQueryWin(); + ~DeviceInfoQueryWin(); + + // Add a device to |device_info_list_| using its |device_path| so that + // its device info can be retrieved. + bool AddDevice(const char* device_path); + // Get the device info and store it into |device_info_data_|, this function + // should be called at most once. + bool GetDeviceInfo(); + // Get device string property and store it into |property_buffer|. + bool GetDeviceStringProperty(DWORD property, std::string* property_buffer); + + bool device_info_list_valid() { + return device_info_list_ != INVALID_HANDLE_VALUE; + } + + private: + HDEVINFO device_info_list_ = INVALID_HANDLE_VALUE; + // When device_info_data_.cbSize != 0, |device_info_data_| is valid. + SP_DEVINFO_DATA device_info_data_; + + DISALLOW_COPY_AND_ASSIGN(DeviceInfoQueryWin); +}; + +} // namespace device + +#endif // DEVICE_CORE_DEVICE_INFO_QUERY_WIN_H_
diff --git a/device/devices_app/devices_apptest.cc b/device/devices_app/devices_apptest.cc index 4416bda..ff41a1a6 100644 --- a/device/devices_app/devices_apptest.cc +++ b/device/devices_app/devices_apptest.cc
@@ -21,9 +21,7 @@ void SetUp() override { ApplicationTestBase::SetUp(); - mojo::URLRequestPtr request = mojo::URLRequest::New(); - request->url = "mojo:devices"; - application_impl()->ConnectToService(request.Pass(), &usb_device_manager_); + application_impl()->ConnectToService("mojo:devices", &usb_device_manager_); } usb::DeviceManager* usb_device_manager() { return usb_device_manager_.get(); }
diff --git a/device/serial/BUILD.gn b/device/serial/BUILD.gn index 1ee6c5f..f66cedfe 100644 --- a/device/serial/BUILD.gn +++ b/device/serial/BUILD.gn
@@ -45,6 +45,7 @@ public_deps = [ ":serial_mojo", "//base", + "//device/core", ] deps = [ "//mojo/public/cpp/system",
diff --git a/device/serial/serial.gyp b/device/serial/serial.gyp index de18133..98635cb 100644 --- a/device/serial/serial.gyp +++ b/device/serial/serial.gyp
@@ -32,6 +32,7 @@ ['chromeos==1', { 'dependencies': [ '../../chromeos/chromeos.gyp:chromeos', + '../../dbus/dbus.gyp:dbus', ], }], ['use_udev == 1', { @@ -50,6 +51,7 @@ '../../net/net.gyp:net', '../../third_party/mojo/mojo_public.gyp:mojo_cpp_bindings', '../../third_party/re2/re2.gyp:re2', + '../core/core.gyp:device_core', ], 'export_dependent_settings': [ 'device_serial_mojo',
diff --git a/device/serial/serial_io_handler.cc b/device/serial/serial_io_handler.cc index 452f91c1..1cfb1cd 100644 --- a/device/serial/serial_io_handler.cc +++ b/device/serial/serial_io_handler.cc
@@ -44,6 +44,7 @@ DCHECK(file_thread_task_runner_.get()); DCHECK(ui_thread_task_runner_.get()); MergeConnectionOptions(options); + port_ = port; #if defined(OS_CHROMEOS) chromeos::PermissionBrokerClient* client =
diff --git a/device/serial/serial_io_handler.h b/device/serial/serial_io_handler.h index 81d70282..63e6c90a 100644 --- a/device/serial/serial_io_handler.h +++ b/device/serial/serial_io_handler.h
@@ -190,6 +190,16 @@ // Possibly fixes up a serial port path name in a platform-specific manner. static std::string MaybeFixUpPortName(const std::string& port_name); + base::SingleThreadTaskRunner* file_thread_task_runner() const { + return file_thread_task_runner_.get(); + } + + base::SingleThreadTaskRunner* ui_thread_task_runner() const { + return ui_thread_task_runner_.get(); + } + + const std::string& port() const { return port_; } + private: friend class base::RefCounted<SerialIoHandler>; @@ -229,6 +239,8 @@ // On Chrome OS, PermissionBrokerClient should be called on the UI thread. scoped_refptr<base::SingleThreadTaskRunner> ui_thread_task_runner_; + std::string port_; + DISALLOW_COPY_AND_ASSIGN(SerialIoHandler); };
diff --git a/device/serial/serial_io_handler_win.cc b/device/serial/serial_io_handler_win.cc index 56fe93b..2a1e752 100644 --- a/device/serial/serial_io_handler_win.cc +++ b/device/serial/serial_io_handler_win.cc
@@ -2,10 +2,18 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include <windows.h> - #include "device/serial/serial_io_handler_win.h" +#include <windows.h> +#include <setupapi.h> + +#include "base/bind.h" +#include "base/scoped_observer.h" +#include "base/threading/thread_checker.h" +#include "device/core/device_info_query_win.h" +#include "device/core/device_monitor_win.h" +#include "third_party/re2/re2/re2.h" + namespace device { namespace { @@ -130,6 +138,12 @@ } } +// Searches for the COM port in the device's friendly name, assigns its value to +// com_port, and returns whether the operation was successful. +bool GetCOMPort(const std::string friendly_name, std::string* com_port) { + return RE2::PartialMatch(friendly_name, ".* \\((COM[0-9]+)\\)", com_port); +} + } // namespace // static @@ -139,6 +153,81 @@ return new SerialIoHandlerWin(file_thread_task_runner, ui_thread_task_runner); } +class SerialIoHandlerWin::UiThreadHelper : public DeviceMonitorWin::Observer { + public: + UiThreadHelper( + base::WeakPtr<SerialIoHandlerWin> io_handler, + scoped_refptr<base::SingleThreadTaskRunner> io_thread_task_runner) + : device_observer_(this), + io_handler_(io_handler), + io_thread_task_runner_(io_thread_task_runner) {} + + ~UiThreadHelper() { DCHECK(thread_checker_.CalledOnValidThread()); } + + static void Start(UiThreadHelper* self) { + self->thread_checker_.DetachFromThread(); + DeviceMonitorWin* device_monitor = DeviceMonitorWin::GetForAllInterfaces(); + if (device_monitor) + self->device_observer_.Add(device_monitor); + } + + private: + // DeviceMonitorWin::Observer + void OnDeviceRemoved(const GUID& class_guid, + const std::string& device_path) override { + DCHECK(thread_checker_.CalledOnValidThread()); + io_thread_task_runner_->PostTask( + FROM_HERE, base::Bind(&SerialIoHandlerWin::OnDeviceRemoved, io_handler_, + device_path)); + } + + base::ThreadChecker thread_checker_; + ScopedObserver<DeviceMonitorWin, DeviceMonitorWin::Observer> device_observer_; + + // This weak pointer is only valid when checked on this task runner. + base::WeakPtr<SerialIoHandlerWin> io_handler_; + scoped_refptr<base::SingleThreadTaskRunner> io_thread_task_runner_; + + DISALLOW_COPY_AND_ASSIGN(UiThreadHelper); +}; + +void SerialIoHandlerWin::OnDeviceRemoved(const std::string& device_path) { + DCHECK(CalledOnValidThread()); + + DeviceInfoQueryWin device_info_query; + if (!device_info_query.device_info_list_valid()) { + DVPLOG(1) << "Failed to create a device information set"; + return; + } + + // This will add the device so we can query driver info. + if (!device_info_query.AddDevice(device_path.c_str())) { + DVPLOG(1) << "Failed to get device interface data for " << device_path; + return; + } + + if (!device_info_query.GetDeviceInfo()) { + DVPLOG(1) << "Failed to get device info for " << device_path; + return; + } + + std::string friendly_name; + if (!device_info_query.GetDeviceStringProperty(SPDRP_FRIENDLYNAME, + &friendly_name)) { + DVPLOG(1) << "Failed to get device service property"; + return; + } + + std::string com_port; + if (!GetCOMPort(friendly_name, &com_port)) { + DVPLOG(1) << "Failed to get port name from \"" << friendly_name << "\"."; + return; + } + + if (port() == com_port) + CancelRead(serial::RECEIVE_ERROR_DISCONNECTED); +} + bool SerialIoHandlerWin::PostOpen() { DCHECK(!comm_context_); DCHECK(!read_context_); @@ -159,6 +248,13 @@ write_context_->handler = this; memset(&write_context_->overlapped, 0, sizeof(write_context_->overlapped)); + scoped_refptr<base::SingleThreadTaskRunner> io_thread_task_runner = + base::ThreadTaskRunnerHandle::Get(); + helper_ = + new UiThreadHelper(weak_factory_.GetWeakPtr(), io_thread_task_runner); + ui_thread_task_runner()->PostTask( + FROM_HERE, base::Bind(&UiThreadHelper::Start, helper_)); + // A ReadIntervalTimeout of MAXDWORD will cause async reads to complete // immediately with any data that's available, even if there is none. // This is OK because we never issue a read request until WaitCommEvent @@ -271,10 +367,11 @@ scoped_refptr<base::SingleThreadTaskRunner> ui_thread_task_runner) : SerialIoHandler(file_thread_task_runner, ui_thread_task_runner), event_mask_(0), - is_comm_pending_(false) { -} + is_comm_pending_(false), + weak_factory_(this) {} SerialIoHandlerWin::~SerialIoHandlerWin() { + ui_thread_task_runner()->DeleteSoon(FROM_HERE, helper_); } void SerialIoHandlerWin::OnIOCompleted(
diff --git a/device/serial/serial_io_handler_win.h b/device/serial/serial_io_handler_win.h index 7f438b5..831eab6 100644 --- a/device/serial/serial_io_handler_win.h +++ b/device/serial/serial_io_handler_win.h
@@ -32,6 +32,7 @@ bool PostOpen() override; private: + class UiThreadHelper; friend class SerialIoHandler; explicit SerialIoHandlerWin( @@ -44,6 +45,8 @@ DWORD bytes_transfered, DWORD error) override; + void OnDeviceRemoved(const std::string& device_path); + // Context used for asynchronous WaitCommEvent calls. scoped_ptr<base::MessageLoopForIO::IOContext> comm_context_; @@ -61,6 +64,11 @@ // after a corresponding WaitCommEvent has completed. bool is_comm_pending_; + // The helper lives on the UI thread and holds a weak reference back to the + // handler that owns it. + UiThreadHelper* helper_ = nullptr; + base::WeakPtrFactory<SerialIoHandlerWin> weak_factory_; + DISALLOW_COPY_AND_ASSIGN(SerialIoHandlerWin); };
diff --git a/device/usb/BUILD.gn b/device/usb/BUILD.gn index a139092b..6d17f7df 100644 --- a/device/usb/BUILD.gn +++ b/device/usb/BUILD.gn
@@ -84,9 +84,9 @@ ] deps = [ + ":usb", "//base", "//testing/gmock", - ":usb", ] }
diff --git a/device/usb/usb.gyp b/device/usb/usb.gyp index c7bf776..453ba1aa 100644 --- a/device/usb/usb.gyp +++ b/device/usb/usb.gyp
@@ -14,6 +14,7 @@ '../../components/components.gyp:device_event_log_component', '../../net/net.gyp:net', '../../third_party/libusb/libusb.gyp:libusb', + '../core/core.gyp:device_core', ], 'include_dirs': [ '../..',
diff --git a/device/usb/usb_service_impl.cc b/device/usb/usb_service_impl.cc index dd5cc90..97700078 100644 --- a/device/usb/usb_service_impl.cc +++ b/device/usb/usb_service_impl.cc
@@ -27,6 +27,7 @@ #include <usbiodef.h> #include "base/strings/string_util.h" +#include "device/core/device_info_query_win.h" #endif // OS_WIN #if defined(USE_UDEV) @@ -53,96 +54,33 @@ #if defined(OS_WIN) -// Wrapper around a HDEVINFO that automatically destroys it. -class ScopedDeviceInfoList { - public: - explicit ScopedDeviceInfoList(HDEVINFO handle) : handle_(handle) {} - - ~ScopedDeviceInfoList() { - if (valid()) { - SetupDiDestroyDeviceInfoList(handle_); - } - } - - bool valid() { return handle_ != INVALID_HANDLE_VALUE; } - - HDEVINFO get() { return handle_; } - - private: - HDEVINFO handle_; - - DISALLOW_COPY_AND_ASSIGN(ScopedDeviceInfoList); -}; - -// Wrapper around an SP_DEVINFO_DATA that initializes it properly and -// automatically deletes it. -class ScopedDeviceInfo { - public: - ScopedDeviceInfo() { - memset(&dev_info_data_, 0, sizeof(dev_info_data_)); - dev_info_data_.cbSize = sizeof(dev_info_data_); - } - - ~ScopedDeviceInfo() { - if (dev_info_set_ != INVALID_HANDLE_VALUE) { - SetupDiDeleteDeviceInfo(dev_info_set_, &dev_info_data_); - } - } - - // Once the SP_DEVINFO_DATA has been populated it must be freed using the - // HDEVINFO it was created from. - void set_valid(HDEVINFO dev_info_set) { - DCHECK(dev_info_set_ == INVALID_HANDLE_VALUE); - DCHECK(dev_info_set != INVALID_HANDLE_VALUE); - dev_info_set_ = dev_info_set; - } - - PSP_DEVINFO_DATA get() { return &dev_info_data_; } - - private: - HDEVINFO dev_info_set_ = INVALID_HANDLE_VALUE; - SP_DEVINFO_DATA dev_info_data_; -}; - bool IsWinUsbInterface(const std::string& device_path) { - ScopedDeviceInfoList dev_info_list(SetupDiCreateDeviceInfoList(NULL, NULL)); - if (!dev_info_list.valid()) { + DeviceInfoQueryWin device_info_query; + if (!device_info_query.device_info_list_valid()) { USB_PLOG(ERROR) << "Failed to create a device information set"; return false; } - // This will add the device to |dev_info_list| so we can query driver info. - if (!SetupDiOpenDeviceInterfaceA(dev_info_list.get(), device_path.c_str(), 0, - NULL)) { + // This will add the device so we can query driver info. + if (!device_info_query.AddDevice(device_path.c_str())) { USB_PLOG(ERROR) << "Failed to get device interface data for " << device_path; return false; } - ScopedDeviceInfo dev_info; - if (!SetupDiEnumDeviceInfo(dev_info_list.get(), 0, dev_info.get())) { + if (!device_info_query.GetDeviceInfo()) { USB_PLOG(ERROR) << "Failed to get device info for " << device_path; return false; } - dev_info.set_valid(dev_info_list.get()); - DWORD reg_data_type; - BYTE buffer[256]; - if (!SetupDiGetDeviceRegistryPropertyA(dev_info_list.get(), dev_info.get(), - SPDRP_SERVICE, ®_data_type, - &buffer[0], sizeof buffer, NULL)) { + std::string buffer; + if (!device_info_query.GetDeviceStringProperty(SPDRP_SERVICE, &buffer)) { USB_PLOG(ERROR) << "Failed to get device service property"; return false; } - if (reg_data_type != REG_SZ) { - USB_LOG(ERROR) << "Unexpected data type for driver service: " - << reg_data_type; - return false; - } USB_LOG(DEBUG) << "Driver for " << device_path << " is " << buffer << "."; - if (base::StartsWith(reinterpret_cast<const char*>(buffer), "WinUSB", - base::CompareCase::INSENSITIVE_ASCII)) + if (base::StartsWith(buffer, "WinUSB", base::CompareCase::INSENSITIVE_ASCII)) return true; return false; }
diff --git a/extensions/BUILD.gn b/extensions/BUILD.gn index 9aa1ca3..1a86e84 100644 --- a/extensions/BUILD.gn +++ b/extensions/BUILD.gn
@@ -342,13 +342,13 @@ "//testing/gmock", "//testing/gtest", "//testing/perf", + "//third_party/WebKit/public:blink", "//third_party/cacheinvalidation", "//third_party/icu", "//third_party/leveldatabase", "//third_party/libaddressinput", "//third_party/libjingle", "//third_party/safe_browsing:test_support", - "//third_party/WebKit/public:blink", "//third_party/webrtc/modules/desktop_capture", "//third_party/widevine/cdm:version_h", "//ui/accessibility:test_support",
diff --git a/extensions/browser/api/bluetooth/bluetooth_private_api.cc b/extensions/browser/api/bluetooth/bluetooth_private_api.cc index 3ce90e54..d69a08aa 100644 --- a/extensions/browser/api/bluetooth/bluetooth_private_api.cc +++ b/extensions/browser/api/bluetooth/bluetooth_private_api.cc
@@ -108,6 +108,9 @@ (pincode || passkey)) return false; + if (options.response == bt_private::PAIRING_RESPONSE_CANCEL) + return true; + // Check the BluetoothDevice is in expecting the correct response. if (!device->ExpectingConfirmation() && !device->ExpectingPinCode() && !device->ExpectingPasskey())
diff --git a/extensions/browser/api/declarative/rules_registry_service.h b/extensions/browser/api/declarative/rules_registry_service.h index c00ce574..60b720b 100644 --- a/extensions/browser/api/declarative/rules_registry_service.h +++ b/extensions/browser/api/declarative/rules_registry_service.h
@@ -7,6 +7,7 @@ #include <map> #include <string> +#include <tuple> #include <vector> #include "base/callback_forward.h" @@ -43,9 +44,8 @@ RulesRegistryKey(const std::string& event_name, int rules_registry_id) : event_name(event_name), rules_registry_id(rules_registry_id) {} bool operator<(const RulesRegistryKey& other) const { - return (event_name < other.event_name) || - ((event_name == other.event_name) && - (rules_registry_id < other.rules_registry_id)); + return std::tie(event_name, rules_registry_id) < + std::tie(other.event_name, other.rules_registry_id); } };
diff --git a/extensions/browser/api/web_request/web_request_api.cc b/extensions/browser/api/web_request/web_request_api.cc index 3361698..d1a14dd5 100644 --- a/extensions/browser/api/web_request/web_request_api.cc +++ b/extensions/browser/api/web_request/web_request_api.cc
@@ -8,7 +8,6 @@ #include "base/bind.h" #include "base/bind_helpers.h" -#include "base/debug/alias.h" #include "base/json/json_writer.h" #include "base/lazy_instance.h" #include "base/macros.h" @@ -1227,20 +1226,6 @@ base::Time::Now()); } -void ExtensionWebRequestEventRouter::OnURLRequestJobOrphaned( - void* browser_context, - const net::URLRequest* request) { - // See https://crbug.com/289715. While a URLRequest is blocking on an - // extension, it may not orphan jobs unless OnURLRequestDestroyed is called - // first. - // - // TODO(davidben): Remove this when the crash has been diagnosed. - char url_buf[128]; - base::strlcpy(url_buf, request->url().spec().c_str(), arraysize(url_buf)); - base::debug::Alias(url_buf); - CHECK_EQ(0u, blocked_requests_.count(request->identifier())); -} - void ExtensionWebRequestEventRouter::ClearPendingCallbacks( const net::URLRequest* request) { blocked_requests_.erase(request->identifier());
diff --git a/extensions/browser/api/web_request/web_request_api.h b/extensions/browser/api/web_request/web_request_api.h index c9caa65..e0be827 100644 --- a/extensions/browser/api/web_request/web_request_api.h +++ b/extensions/browser/api/web_request/web_request_api.h
@@ -261,10 +261,6 @@ void OnURLRequestDestroyed(void* browser_context, const net::URLRequest* request); - // See https://crbug.com/289715. - void OnURLRequestJobOrphaned(void* browser_context, - const net::URLRequest* request); - // Called when an event listener handles a blocking event and responds. void OnEventHandled(void* browser_context, const std::string& extension_id,
diff --git a/extensions/browser/event_router.cc b/extensions/browser/event_router.cc index 0aeec38..649856d 100644 --- a/extensions/browser/event_router.cc +++ b/extensions/browser/event_router.cc
@@ -4,6 +4,7 @@ #include "extensions/browser/event_router.h" +#include <tuple> #include <utility> #include "base/atomic_sequence_num.h" @@ -95,11 +96,8 @@ : process(process), extension_id(extension_id) {} bool operator<(const ListenerProcess& that) const { - if (process < that.process) - return true; - if (process == that.process && extension_id < that.extension_id) - return true; - return false; + return std::tie(process, extension_id) < + std::tie(that.process, that.extension_id); } };
diff --git a/extensions/browser/notification_types.h b/extensions/browser/notification_types.h index e5ae4ba..b99454cf 100644 --- a/extensions/browser/notification_types.h +++ b/extensions/browser/notification_types.h
@@ -58,13 +58,6 @@ // UpdatedExtensionPermissionsInfo, and the source is a BrowserContext*. NOTIFICATION_EXTENSION_PERMISSIONS_UPDATED, - // Sent immediately before new extensions are installed or existing - // extensions are updated. The details are an InstalledExtensionInfo, and the - // source is a BrowserContext*. - // - // DEPRECATED: Use ExtensionRegistry::AddObserver instead. - NOTIFICATION_EXTENSION_WILL_BE_INSTALLED_DEPRECATED, - // An error occured during extension install. The details are a string with // details about why the install failed. NOTIFICATION_EXTENSION_INSTALL_ERROR,
diff --git a/extensions/browser/process_map.cc b/extensions/browser/process_map.cc index 0850bc6..b3100201 100644 --- a/extensions/browser/process_map.cc +++ b/extensions/browser/process_map.cc
@@ -4,6 +4,8 @@ #include "extensions/browser/process_map.h" +#include <tuple> + #include "content/public/browser/child_process_security_policy.h" #include "extensions/browser/extension_registry.h" #include "extensions/browser/process_map_factory.h" @@ -36,21 +38,9 @@ } bool operator<(const ProcessMap::Item& other) const { - if (extension_id < other.extension_id) - return true; - - if (extension_id == other.extension_id && - process_id < other.process_id) { - return true; - } - - if (extension_id == other.extension_id && - process_id == other.process_id && - site_instance_id < other.site_instance_id) { - return true; - } - - return false; + return std::tie(extension_id, process_id, site_instance_id) < + std::tie(other.extension_id, other.process_id, + other.site_instance_id); } std::string extension_id;
diff --git a/extensions/common/BUILD.gn b/extensions/common/BUILD.gn index a62d1d0..4f5496ad 100644 --- a/extensions/common/BUILD.gn +++ b/extensions/common/BUILD.gn
@@ -56,9 +56,9 @@ "//crypto", "//device/bluetooth", "//device/usb", + "//extensions:extensions_resources", "//extensions/common/api", "//extensions/strings", - "//extensions:extensions_resources", "//ipc", "//net", "//third_party/boringssl",
diff --git a/extensions/common/api/BUILD.gn b/extensions/common/api/BUILD.gn index 0cbce18b..5f259ec 100644 --- a/extensions/common/api/BUILD.gn +++ b/extensions/common/api/BUILD.gn
@@ -26,8 +26,8 @@ # GYP version: extensions/common/api/api.gyp:extensions_api group("api") { public_deps = [ - ":mojom", ":generated_api", + ":mojom", ] }
diff --git a/extensions/common/api/_api_features.json b/extensions/common/api/_api_features.json index 012d906a..878d7ba1 100644 --- a/extensions/common/api/_api_features.json +++ b/extensions/common/api/_api_features.json
@@ -93,6 +93,7 @@ "channel": "stable", "contexts": ["webui"], "matches": [ + "chrome://bluetooth-pairing/*", "chrome://md-settings/*", "chrome://settings/*", "chrome://settings-frame/*" @@ -109,6 +110,7 @@ "channel": "stable", "contexts": ["webui"], "matches": [ + "chrome://bluetooth-pairing/*", "chrome://md-settings/*", "chrome://settings/*", "chrome://settings-frame/*"
diff --git a/extensions/common/api/bluetooth_private.idl b/extensions/common/api/bluetooth_private.idl index e3c60fd8..af6e893 100644 --- a/extensions/common/api/bluetooth_private.idl +++ b/extensions/common/api/bluetooth_private.idl
@@ -91,7 +91,7 @@ bluetooth.Device device; // The response type. - PairingResponse? response; + PairingResponse response; // A 1-16 character alphanumeric set in response to // <code>requestPincode</code>.
diff --git a/extensions/common/api/sockets/sockets_manifest_permission_unittest.cc b/extensions/common/api/sockets/sockets_manifest_permission_unittest.cc index ad5ba16..bccce574 100644 --- a/extensions/common/api/sockets/sockets_manifest_permission_unittest.cc +++ b/extensions/common/api/sockets/sockets_manifest_permission_unittest.cc
@@ -3,6 +3,7 @@ // found in the LICENSE file. #include <set> +#include <tuple> #include "base/json/json_reader.h" #include "base/pickle.h" @@ -67,10 +68,8 @@ // operators <, == are needed by container std::set and algorithms // std::set_includes and std::set_differences. bool operator<(const CheckFormatEntry& rhs) const { - if (operation_type == rhs.operation_type) - return host_pattern < rhs.host_pattern; - - return operation_type < rhs.operation_type; + return std::tie(operation_type, host_pattern) < + std::tie(rhs.operation_type, rhs.host_pattern); } bool operator==(const CheckFormatEntry& rhs) const {
diff --git a/extensions/common/permissions/socket_permission_entry.cc b/extensions/common/permissions/socket_permission_entry.cc index 31ec6b8..926a07b9 100644 --- a/extensions/common/permissions/socket_permission_entry.cc +++ b/extensions/common/permissions/socket_permission_entry.cc
@@ -6,6 +6,7 @@ #include <cstdlib> #include <sstream> +#include <tuple> #include <vector> #include "base/logging.h" @@ -43,24 +44,10 @@ SocketPermissionEntry::~SocketPermissionEntry() {} bool SocketPermissionEntry::operator<(const SocketPermissionEntry& rhs) const { - if (pattern_.type < rhs.pattern_.type) - return true; - if (pattern_.type > rhs.pattern_.type) - return false; - - if (pattern_.host < rhs.pattern_.host) - return true; - if (pattern_.host > rhs.pattern_.host) - return false; - - if (match_subdomains_ < rhs.match_subdomains_) - return true; - if (match_subdomains_ > rhs.match_subdomains_) - return false; - - if (pattern_.port < rhs.pattern_.port) - return true; - return false; + return std::tie(pattern_.type, pattern_.host, match_subdomains_, + pattern_.port) < + std::tie(rhs.pattern_.type, rhs.pattern_.host, rhs.match_subdomains_, + rhs.pattern_.port); } bool SocketPermissionEntry::operator==(const SocketPermissionEntry& rhs) const {
diff --git a/extensions/common/permissions/usb_device_permission_data.cc b/extensions/common/permissions/usb_device_permission_data.cc index 532886d..fbd4428 100644 --- a/extensions/common/permissions/usb_device_permission_data.cc +++ b/extensions/common/permissions/usb_device_permission_data.cc
@@ -5,6 +5,7 @@ #include "extensions/common/permissions/usb_device_permission_data.h" #include <string> +#include <tuple> #include <vector> #include "base/basictypes.h" @@ -90,13 +91,8 @@ bool UsbDevicePermissionData::operator<( const UsbDevicePermissionData& rhs) const { - if (vendor_id_ == rhs.vendor_id_) { - if (product_id_ == rhs.product_id_) - return interface_id_ < rhs.interface_id_; - - return product_id_ < rhs.product_id_; - } - return vendor_id_ < rhs.vendor_id_; + return std::tie(vendor_id_, product_id_, interface_id_) < + std::tie(rhs.vendor_id_, rhs.product_id_, rhs.interface_id_); } bool UsbDevicePermissionData::operator==(
diff --git a/extensions/components/native_app_window/BUILD.gn b/extensions/components/native_app_window/BUILD.gn index 28330bc6..5136e2a0 100644 --- a/extensions/components/native_app_window/BUILD.gn +++ b/extensions/components/native_app_window/BUILD.gn
@@ -10,11 +10,11 @@ deps = [ "//base", - "//skia", - "//ui/views", - "//ui/views/controls/webview", "//content/public/browser", "//extensions/browser", "//extensions/common", + "//skia", + "//ui/views", + "//ui/views/controls/webview", ] }
diff --git a/extensions/renderer/user_script_injector.cc b/extensions/renderer/user_script_injector.cc index 548b4d6..9885b4e 100644 --- a/extensions/renderer/user_script_injector.cc +++ b/extensions/renderer/user_script_injector.cc
@@ -4,6 +4,7 @@ #include "extensions/renderer/user_script_injector.h" +#include <tuple> #include <vector> #include "base/lazy_instance.h" @@ -36,12 +37,8 @@ : routing_id(routing_id), script_id(script_id) {} bool operator<(const RoutingInfoKey& other) const { - if (routing_id != other.routing_id) - return routing_id < other.routing_id; - - if (script_id != other.script_id) - return script_id < other.script_id; - return false; // keys are equal. + return std::tie(routing_id, script_id) < + std::tie(other.routing_id, other.script_id); } };
diff --git a/extensions/shell/BUILD.gn b/extensions/shell/BUILD.gn index 0e31897..829ef00 100644 --- a/extensions/shell/BUILD.gn +++ b/extensions/shell/BUILD.gn
@@ -44,16 +44,16 @@ "//content/shell:content_shell_lib", "//device/core", "//device/hid", - "//extensions/common/api", - "//extensions/common/api:api_registration", + "//extensions:extensions_resources", + "//extensions:shell_and_test_pak", "//extensions/browser", "//extensions/common", + "//extensions/common/api", + "//extensions/common/api:api_registration", "//extensions/renderer", "//extensions/shell/common/api", "//extensions/shell/common/api:api_registration", "//extensions/utility", - "//extensions:extensions_resources", - "//extensions:shell_and_test_pak", "//mojo/environment:chromium", "//skia", "//third_party/WebKit/public:blink",
diff --git a/extensions/shell/browser/shell_extension_system.cc b/extensions/shell/browser/shell_extension_system.cc index b6cff6a..e3a75bf 100644 --- a/extensions/shell/browser/shell_extension_system.cc +++ b/extensions/shell/browser/shell_extension_system.cc
@@ -56,7 +56,7 @@ // * Call PermissionsUpdater::GrantActivePermissions(). // * Call ExtensionService::SatisfyImports(). // * Call ExtensionPrefs::OnExtensionInstalled(). - // * Send NOTIFICATION_EXTENSION_WILL_BE_INSTALLED_DEPRECATED. + // * Call ExtensionRegistryObserver::OnExtensionWillbeInstalled(). ExtensionRegistry::Get(browser_context_)->AddEnabled(extension.get());
diff --git a/gpu/BUILD.gn b/gpu/BUILD.gn index 141b2b2..8244ec63 100644 --- a/gpu/BUILD.gn +++ b/gpu/BUILD.gn
@@ -160,6 +160,9 @@ "//base", "//base/test:test_support", "//base/third_party/dynamic_annotations", + "//gpu/command_buffer/client:gles2_c_lib", + "//gpu/command_buffer/client:gles2_implementation", + "//gpu/command_buffer/common:gles2_utils", "//testing/gmock", "//testing/gtest", "//third_party/angle:translator", @@ -167,9 +170,6 @@ "//ui/gfx:test_support", "//ui/gfx/geometry", "//ui/gl", - "//gpu/command_buffer/common:gles2_utils", - "//gpu/command_buffer/client:gles2_c_lib", - "//gpu/command_buffer/client:gles2_implementation", ] libs = [] @@ -299,18 +299,18 @@ "//base", "//base/test:test_support", "//base/third_party/dynamic_annotations", + "//gpu/command_buffer/client:gles2_c_lib", + "//gpu/command_buffer/client:gles2_implementation", + "//gpu/command_buffer/common:gles2_utils", "//testing/gmock", "//testing/gtest", "//third_party/angle:translator", "//ui/gfx", - "//ui/gfx/geometry", "//ui/gfx:test_support", + "//ui/gfx/geometry", "//ui/gl", "//ui/gl:gl_unittest_utils", "//ui/gl:test_support", - "//gpu/command_buffer/common:gles2_utils", - "//gpu/command_buffer/client:gles2_c_lib", - "//gpu/command_buffer/client:gles2_implementation", ] }
diff --git a/gpu/GLES2/extensions/CHROMIUM/CHROMIUM_sync_point.txt b/gpu/GLES2/extensions/CHROMIUM/CHROMIUM_sync_point.txt index 0a0a808f..3c1f0e7 100644 --- a/gpu/GLES2/extensions/CHROMIUM/CHROMIUM_sync_point.txt +++ b/gpu/GLES2/extensions/CHROMIUM/CHROMIUM_sync_point.txt
@@ -8,7 +8,7 @@ Version - Last Modifed Date: September 8, 2015 + Last Modifed Date: November 20, 2015 Dependencies @@ -63,7 +63,7 @@ InsertFenceSyncCHROMIUM was called. The <sync_token> can be passed and used by any context on the same server, including other context groups. - <sync_token> returns a GL_SYNC_POINT_SIZE_CHROMIUM byte sized name. + <sync_token> returns a GL_SYNC_TOKEN_SIZE_CHROMIUM byte sized name. The command @@ -86,11 +86,11 @@ causes the current context to stop submitting commands until the specified fence sync becomes signaled. This is implemented as a server-side wait. - <sync_token> is a sync token generated by GenSyncPointCHROMIUM. If + <sync_token> is a sync token generated by GenSyncTokenCHROMIUM. If <sync_token> was generated by GenUnverifiedSyncTokenCHROMIUM and the corresponding fence sync context required more than just flush ordering to guarantee synchronization, a INVALID_OPERATION error is generated. If - <sync_token> isn't a valid sync token returned by GenSyncPointCHROMIUM or + <sync_token> isn't a valid sync token returned by GenSyncTokenCHROMIUM or GenUnverifiedSyncTokenCHROMIUM, the result is undefined. New Tokens @@ -102,10 +102,10 @@ Errors INVALID_VALUE is generated if the <fence_sync> parameter of - GenSyncPointCHROMIUM is not a valid local fence sync name. + GenSyncTokenCHROMIUM is not a valid local fence sync name. INVALID_OPERATION is generated if the <fence_sync> parameter of - GenSyncPointCHROMIUM has not been flushed to the server. + GenSyncTokenCHROMIUM has not been flushed to the server. INVALID_OPERATION is generated if the <sync_token> parameter of WaitSyncTokenCHROMIUM was generated using GenUnverifiedSyncTokenCHROMIUM,
diff --git a/gpu/blink/BUILD.gn b/gpu/blink/BUILD.gn index d034c47..8bb98b1 100644 --- a/gpu/blink/BUILD.gn +++ b/gpu/blink/BUILD.gn
@@ -23,18 +23,18 @@ "//base", "//base/third_party/dynamic_annotations", "//cc", + "//gpu/command_buffer/client:gl_in_process_context", + "//gpu/command_buffer/client:gles2_c_lib", + "//gpu/command_buffer/client:gles2_implementation", "//gpu/command_buffer/common", "//gpu/command_buffer/common:gles2_utils", "//gpu/command_buffer/service", - "//gpu/command_buffer/client:gles2_c_lib", - "//gpu/command_buffer/client:gles2_implementation", - "//gpu/command_buffer/client:gl_in_process_context", "//gpu/skia_bindings", "//skia", "//third_party/WebKit/public:blink_minimal", "//third_party/angle:translator", - "//ui/gl", "//ui/gfx", "//ui/gfx/geometry", + "//ui/gl", ] }
diff --git a/gpu/command_buffer/build_gles2_cmd_buffer.py b/gpu/command_buffer/build_gles2_cmd_buffer.py index ea859c91..7f13556 100755 --- a/gpu/command_buffer/build_gles2_cmd_buffer.py +++ b/gpu/command_buffer/build_gles2_cmd_buffer.py
@@ -4141,7 +4141,7 @@ 'WaitSyncTokenCHROMIUM': { 'type': 'Custom', 'impl_func': False, - 'cmd_args': 'GLuint namespace_id, ' + 'cmd_args': 'GLint namespace_id, ' 'GLuint64 command_buffer_id, ' 'GLuint64 release_count', 'client_test': False,
diff --git a/gpu/command_buffer/client/BUILD.gn b/gpu/command_buffer/client/BUILD.gn index bbb7c0b..f114d1f 100644 --- a/gpu/command_buffer/client/BUILD.gn +++ b/gpu/command_buffer/client/BUILD.gn
@@ -182,10 +182,10 @@ deps = [ ":gles2_implementation", - "//gpu", - "//gpu/command_buffer/common:gles2_utils", "//base", "//base/third_party/dynamic_annotations", + "//gpu", + "//gpu/command_buffer/common:gles2_utils", "//ui/gfx/geometry", "//ui/gl", ]
diff --git a/gpu/command_buffer/client/gles2_cmd_helper_autogen.h b/gpu/command_buffer/client/gles2_cmd_helper_autogen.h index 58e8c90..d4693588 100644 --- a/gpu/command_buffer/client/gles2_cmd_helper_autogen.h +++ b/gpu/command_buffer/client/gles2_cmd_helper_autogen.h
@@ -2785,7 +2785,7 @@ } } -void WaitSyncTokenCHROMIUM(GLuint namespace_id, +void WaitSyncTokenCHROMIUM(GLint namespace_id, GLuint64 command_buffer_id, GLuint64 release_count) { gles2::cmds::WaitSyncTokenCHROMIUM* c =
diff --git a/gpu/command_buffer/client/gles2_implementation.cc b/gpu/command_buffer/client/gles2_implementation.cc index 41e5b37c..50b2089 100644 --- a/gpu/command_buffer/client/gles2_implementation.cc +++ b/gpu/command_buffer/client/gles2_implementation.cc
@@ -5493,7 +5493,7 @@ } helper_->WaitSyncTokenCHROMIUM( - static_cast<GLuint>(sync_token_data.namespace_id()), + static_cast<GLint>(sync_token_data.namespace_id()), sync_token_data.command_buffer_id(), sync_token_data.release_count()); } }
diff --git a/gpu/command_buffer/common/gles2_cmd_format_autogen.h b/gpu/command_buffer/common/gles2_cmd_format_autogen.h index 422c9e61..d30befc 100644 --- a/gpu/command_buffer/common/gles2_cmd_format_autogen.h +++ b/gpu/command_buffer/common/gles2_cmd_format_autogen.h
@@ -13591,7 +13591,7 @@ void SetHeader() { header.SetCmd<ValueType>(); } - void Init(GLuint _namespace_id, + void Init(GLint _namespace_id, GLuint64 _command_buffer_id, GLuint64 _release_count) { SetHeader(); @@ -13601,7 +13601,7 @@ } void* Set(void* cmd, - GLuint _namespace_id, + GLint _namespace_id, GLuint64 _command_buffer_id, GLuint64 _release_count) { static_cast<ValueType*>(cmd) @@ -13610,7 +13610,7 @@ } gpu::CommandHeader header; - uint32_t namespace_id; + int32_t namespace_id; uint32_t command_buffer_id; uint32_t release_count; };
diff --git a/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h b/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h index 6ca0897..683ae4d9 100644 --- a/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h +++ b/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h
@@ -4740,12 +4740,12 @@ cmds::WaitSyncTokenCHROMIUM& cmd = *GetBufferAs<cmds::WaitSyncTokenCHROMIUM>(); void* next_cmd = - cmd.Set(&cmd, static_cast<GLuint>(11), static_cast<GLuint64>(12), + cmd.Set(&cmd, static_cast<GLint>(11), static_cast<GLuint64>(12), static_cast<GLuint64>(13)); EXPECT_EQ(static_cast<uint32_t>(cmds::WaitSyncTokenCHROMIUM::kCmdId), cmd.header.command); EXPECT_EQ(sizeof(cmd), cmd.header.size * 4u); - EXPECT_EQ(static_cast<GLuint>(11), cmd.namespace_id); + EXPECT_EQ(static_cast<GLint>(11), cmd.namespace_id); EXPECT_EQ(static_cast<GLuint64>(12), cmd.command_buffer_id); EXPECT_EQ(static_cast<GLuint64>(13), cmd.release_count); CheckBytesWrittenMatchesExpectedSize(next_cmd, sizeof(cmd));
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc index 132e84f6..20b3fb7 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc
@@ -12125,8 +12125,16 @@ const gles2::cmds::WaitSyncTokenCHROMIUM& c = *static_cast<const gles2::cmds::WaitSyncTokenCHROMIUM*>(cmd_data); + const gpu::CommandBufferNamespace kMinNamespaceId = + gpu::CommandBufferNamespace::INVALID; + const gpu::CommandBufferNamespace kMaxNamespaceId = + gpu::CommandBufferNamespace::NUM_COMMAND_BUFFER_NAMESPACES; + const gpu::CommandBufferNamespace namespace_id = - static_cast<gpu::CommandBufferNamespace>(c.namespace_id); + ((c.namespace_id >= static_cast<int32_t>(kMinNamespaceId)) && + (c.namespace_id < static_cast<int32_t>(kMaxNamespaceId))) + ? static_cast<gpu::CommandBufferNamespace>(c.namespace_id) + : gpu::CommandBufferNamespace::INVALID; const uint64_t command_buffer_id = c.command_buffer_id; const uint64_t release = c.release_count; if (wait_fence_sync_callback_.is_null())
diff --git a/gpu/command_buffer/service/program_manager.cc b/gpu/command_buffer/service/program_manager.cc index 83f4e39..233eb4e 100644 --- a/gpu/command_buffer/service/program_manager.cc +++ b/gpu/command_buffer/service/program_manager.cc
@@ -871,6 +871,10 @@ GatherInterfaceBlockInfo(); Update(); if (link) { + // ANGLE updates the translated shader sources on link. + for (auto shader : attached_shaders_) { + shader->RefreshTranslatedShaderSource(); + } if (cache) { cache->SaveLinkedProgram(service_id(), attached_shaders_[0].get(),
diff --git a/gpu/command_buffer/service/shader_manager.cc b/gpu/command_buffer/service/shader_manager.cc index 37cc4f3..342a476 100644 --- a/gpu/command_buffer/service/shader_manager.cc +++ b/gpu/command_buffer/service/shader_manager.cc
@@ -86,23 +86,10 @@ glShaderSource(service_id_, 1, &source_for_driver, NULL); glCompileShader(service_id_); + if (source_type_ == kANGLE) { - GLint max_len = 0; - glGetShaderiv(service_id_, - GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE, - &max_len); - source_for_driver = "\0"; - translated_source_.resize(max_len); - if (max_len) { - GLint len = 0; - glGetTranslatedShaderSourceANGLE( - service_id_, translated_source_.size(), - &len, &translated_source_.at(0)); - DCHECK(max_len == 0 || len < max_len); - DCHECK(len == 0 || translated_source_[len] == '\0'); - translated_source_.resize(len); - source_for_driver = translated_source_.c_str(); - } + RefreshTranslatedShaderSource(); + source_for_driver = translated_source_.c_str(); } GLint status = GL_FALSE; @@ -138,6 +125,23 @@ } } +void Shader::RefreshTranslatedShaderSource() { + if (source_type_ == kANGLE) { + GLint max_len = 0; + glGetShaderiv(service_id_, GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE, + &max_len); + translated_source_.resize(max_len); + if (max_len) { + GLint len = 0; + glGetTranslatedShaderSourceANGLE(service_id_, translated_source_.size(), + &len, &translated_source_.at(0)); + DCHECK(max_len == 0 || len < max_len); + DCHECK(len == 0 || translated_source_[len] == '\0'); + translated_source_.resize(len); + } + } +} + void Shader::IncUseCount() { ++use_count_; }
diff --git a/gpu/command_buffer/service/shader_manager.h b/gpu/command_buffer/service/shader_manager.h index aa115de..3288bff 100644 --- a/gpu/command_buffer/service/shader_manager.h +++ b/gpu/command_buffer/service/shader_manager.h
@@ -41,6 +41,7 @@ TranslatedShaderSourceType type); void DoCompile(); + void RefreshTranslatedShaderSource(); ShaderState shader_state() const { return shader_state_;
diff --git a/gpu/command_buffer/service/sync_point_manager.cc b/gpu/command_buffer/service/sync_point_manager.cc index 3fa7539..8a88c722 100644 --- a/gpu/command_buffer/service/sync_point_manager.cc +++ b/gpu/command_buffer/service/sync_point_manager.cc
@@ -340,14 +340,14 @@ scoped_refptr<SyncPointClientState> SyncPointManager::GetSyncPointClientState( CommandBufferNamespace namespace_id, uint64_t client_id) { - DCHECK_GE(namespace_id, 0); - DCHECK_LT(static_cast<size_t>(namespace_id), arraysize(client_maps_)); - base::AutoLock auto_lock(client_maps_lock_); - - ClientMap& client_map = client_maps_[namespace_id]; - ClientMap::iterator it = client_map.find(client_id); - if (it != client_map.end()) { - return it->second->client_state(); + if (namespace_id >= 0) { + DCHECK_LT(static_cast<size_t>(namespace_id), arraysize(client_maps_)); + base::AutoLock auto_lock(client_maps_lock_); + ClientMap& client_map = client_maps_[namespace_id]; + ClientMap::iterator it = client_map.find(client_id); + if (it != client_map.end()) { + return it->second->client_state(); + } } return nullptr; }
diff --git a/gpu/gles2_conform_support/egl/BUILD.gn b/gpu/gles2_conform_support/egl/BUILD.gn index 32fb870..ee06fbf 100644 --- a/gpu/gles2_conform_support/egl/BUILD.gn +++ b/gpu/gles2_conform_support/egl/BUILD.gn
@@ -24,9 +24,9 @@ deps = [ "//base", + "//gpu", "//gpu/command_buffer/client:gles2_implementation_no_check", "//gpu/command_buffer/service", - "//gpu", "//ui/base", "//ui/gfx", "//ui/gfx/geometry",
diff --git a/gpu/ipc/gpu_command_buffer_traits_multi.h b/gpu/ipc/gpu_command_buffer_traits_multi.h index d82ee5c..d3cafbf5 100644 --- a/gpu/ipc/gpu_command_buffer_traits_multi.h +++ b/gpu/ipc/gpu_command_buffer_traits_multi.h
@@ -16,7 +16,7 @@ IPC_ENUM_TRAITS_MIN_MAX_VALUE( gpu::CommandBufferNamespace, gpu::CommandBufferNamespace::INVALID, - gpu::CommandBufferNamespace::NUM_COMMAND_BUFFER_NAMESPACES) + gpu::CommandBufferNamespace::NUM_COMMAND_BUFFER_NAMESPACES - 1) IPC_STRUCT_TRAITS_BEGIN(gpu::Capabilities::ShaderPrecision) IPC_STRUCT_TRAITS_MEMBER(min_range)
diff --git a/ios/chrome/BUILD.gn b/ios/chrome/BUILD.gn index daa2e2ed..0371de2 100644 --- a/ios/chrome/BUILD.gn +++ b/ios/chrome/BUILD.gn
@@ -42,8 +42,8 @@ deps = [ "//base", - "//base/test:test_support", "//base:prefs_test_support", + "//base/test:test_support", "//components/bookmarks/test", "//components/enhanced_bookmarks:test_support", "//components/favicon_base",
diff --git a/ios/chrome/browser/BUILD.gn b/ios/chrome/browser/BUILD.gn index 829cd49..d7a8a61e 100644 --- a/ios/chrome/browser/BUILD.gn +++ b/ios/chrome/browser/BUILD.gn
@@ -433,6 +433,7 @@ ] deps = [ + ":injected_js", "//base", "//base:prefs", "//breakpad:client", @@ -514,7 +515,6 @@ "//ui/base", "//ui/gfx", "//url", - ":injected_js", # TODO(crbug.com/459705): add support for resource packing and change the # dependency to be on the packed resources instead of the unpacked ones. @@ -533,8 +533,8 @@ if (enable_rlz) { deps += [ - "//components/rlz", ":rlz", + "//components/rlz", ] }
diff --git a/ios/chrome/browser/prefs/browser_prefs.mm b/ios/chrome/browser/prefs/browser_prefs.mm index 39755ad..6776246 100644 --- a/ios/chrome/browser/prefs/browser_prefs.mm +++ b/ios/chrome/browser/prefs/browser_prefs.mm
@@ -7,6 +7,8 @@ #include "base/prefs/pref_service.h" #include "components/autofill/core/browser/autofill_manager.h" #include "components/content_settings/core/browser/host_content_settings_map.h" +#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_prefs.h" +#include "components/data_reduction_proxy/core/common/data_reduction_proxy_pref_names.h" #include "components/dom_distiller/core/distilled_page_prefs.h" #include "components/enhanced_bookmarks/bookmark_server_cluster_service.h" #include "components/gcm_driver/gcm_channel_status_syncer.h" @@ -63,6 +65,13 @@ [OmniboxGeolocationLocalState registerLocalState:registry]; [MemoryDebuggerManager registerLocalState:registry]; + // TODO(crbug.com/557814): data_reduction_proxy::prefs::kDataReductionProxy + // should be registered by data_reduction_proxy::RegisterPrefs() instead of + // here. + registry->RegisterStringPref(data_reduction_proxy::prefs::kDataReductionProxy, + std::string()); + data_reduction_proxy::RegisterPrefs(registry); + // TODO(shreyasv): Remove this in M49 as almost all users would have the // "do not backup" bit set by then. crbug.com/489865. registry->RegisterBooleanPref(prefs::kOTRStashStatePathSystemBackupExcluded,
diff --git a/ios/chrome/ios_chrome.gyp b/ios/chrome/ios_chrome.gyp index e17a037f..ec206af 100644 --- a/ios/chrome/ios_chrome.gyp +++ b/ios/chrome/ios_chrome.gyp
@@ -55,6 +55,7 @@ '../../components/components.gyp:content_settings_core_browser', '../../components/components.gyp:crash_core_browser', '../../components/components.gyp:crash_core_common', + '../../components/components.gyp:data_reduction_proxy_core_browser', '../../components/components.gyp:data_reduction_proxy_core_common', '../../components/components.gyp:dom_distiller_core', '../../components/components.gyp:dom_distiller_ios',
diff --git a/ios/net/BUILD.gn b/ios/net/BUILD.gn index 25403883..d894d7b 100644 --- a/ios/net/BUILD.gn +++ b/ios/net/BUILD.gn
@@ -54,12 +54,12 @@ test("ios_net_unittests") { deps = [ + ":net", "//base", "//base/test:run_all_unittests", "//net:test_support", "//testing/gtest", "//url", - ":net", ] sources = [
diff --git a/ios/net/cookies/cookie_store_ios_unittest.mm b/ios/net/cookies/cookie_store_ios_unittest.mm index 66d5ba5b..9bb977f6 100644 --- a/ios/net/cookies/cookie_store_ios_unittest.mm +++ b/ios/net/cookies/cookie_store_ios_unittest.mm
@@ -42,6 +42,7 @@ static const bool filters_schemes = false; static const bool has_path_prefix_bug = true; static const int creation_time_granularity_in_ms = 1000; + static const bool enforce_strict_secure = false; base::MessageLoop loop_; }; @@ -59,6 +60,7 @@ static const bool has_path_prefix_bug = false; static const int creation_time_granularity_in_ms = 0; static const int enforces_prefixes = true; + static const bool enforce_strict_secure = false; base::MessageLoop loop_; }; @@ -170,6 +172,7 @@ static const bool has_path_prefix_bug = true; static const int creation_time_granularity_in_ms = 1000; static const int enforces_prefixes = true; + static const bool enforce_strict_secure = false; }; } // namespace net
diff --git a/ios/testing/BUILD.gn b/ios/testing/BUILD.gn index 782c2ae..9a1a6bb5 100644 --- a/ios/testing/BUILD.gn +++ b/ios/testing/BUILD.gn
@@ -24,11 +24,11 @@ test("ocmock_support_unittest") { deps = [ + ":ocmock_support", "//base/test:run_all_unittests", "//base/test:test_support", "//testing/gmock", "//testing/gtest", "//third_party/ocmock", - ":ocmock_support", ] }
diff --git a/ios/web/BUILD.gn b/ios/web/BUILD.gn index c2ca4a0e..331d8e7 100644 --- a/ios/web/BUILD.gn +++ b/ios/web/BUILD.gn
@@ -20,6 +20,9 @@ source_set("web") { deps = [ + ":core", + ":js_resources", + ":user_agent", "//base", "//components/url_formatter", "//ios/net", @@ -30,9 +33,6 @@ "//ui/gfx/geometry:geometry", "//ui/resources", "//url", - ":core", - ":js_resources", - ":user_agent", ] sources = [ @@ -195,6 +195,8 @@ "web_state/blocked_popup_info.h", "web_state/blocked_popup_info.mm", "web_state/credential.cc", + "web_state/crw_pass_kit_downloader.h", + "web_state/crw_pass_kit_downloader.mm", "web_state/crw_recurring_task_delegate.h", "web_state/crw_web_view_proxy_impl.h", "web_state/crw_web_view_proxy_impl.mm", @@ -325,12 +327,12 @@ testonly = true deps = [ + ":web", "//ios/testing:ocmock_support", "//ios/third_party/gcdwebserver", "//testing/gmock", "//testing/gtest", "//third_party/ocmock", - ":web", ] sources = [ @@ -374,6 +376,8 @@ test("ios_web_unittests") { deps = [ + ":test_support", + ":web", "//base", "//base/test:test_support", "//ios/testing:ocmock_support", @@ -382,8 +386,6 @@ "//testing/gtest", "//third_party/ocmock", "//ui/base:test_support", - ":test_support", - ":web", ] sources = [ @@ -418,6 +420,7 @@ "url_scheme_util_unittest.mm", "url_util_unittest.cc", "weak_nsobject_counter_unittest.mm", + "web_state/crw_pass_kit_downloader_unittest.mm", "web_state/crw_web_view_scroll_view_proxy_unittest.mm", "web_state/js/common_js_unittest.mm", "web_state/js/core_js_unittest.mm",
diff --git a/ios/web/ios_web.gyp b/ios/web/ios_web.gyp index 814fec5..8475e523 100644 --- a/ios/web/ios_web.gyp +++ b/ios/web/ios_web.gyp
@@ -218,6 +218,8 @@ 'web_state/blocked_popup_info.h', 'web_state/blocked_popup_info.mm', 'web_state/credential.cc', + 'web_state/crw_pass_kit_downloader.h', + 'web_state/crw_pass_kit_downloader.mm', 'web_state/crw_recurring_task_delegate.h', 'web_state/crw_web_view_proxy_impl.h', 'web_state/crw_web_view_proxy_impl.mm',
diff --git a/ios/web/ios_web_unittests.gyp b/ios/web/ios_web_unittests.gyp index ddca72ad..a88f34ae 100644 --- a/ios/web/ios_web_unittests.gyp +++ b/ios/web/ios_web_unittests.gyp
@@ -54,6 +54,7 @@ 'url_scheme_util_unittest.mm', 'url_util_unittest.cc', 'weak_nsobject_counter_unittest.mm', + 'web_state/crw_pass_kit_downloader_unittest.mm', 'web_state/crw_web_view_scroll_view_proxy_unittest.mm', 'web_state/js/common_js_unittest.mm', 'web_state/js/core_js_unittest.mm',
diff --git a/ios/web/public/test/crw_test_js_injection_receiver.mm b/ios/web/public/test/crw_test_js_injection_receiver.mm index 4ef9db7..1d54802 100644 --- a/ios/web/public/test/crw_test_js_injection_receiver.mm +++ b/ios/web/public/test/crw_test_js_injection_receiver.mm
@@ -5,6 +5,7 @@ #import "ios/web/public/test/crw_test_js_injection_receiver.h" #import <UIKit/UIKit.h> +#import <WebKit/WebKit.h> #include "base/ios/weak_nsobject.h" #import "base/mac/scoped_nsobject.h" @@ -58,6 +59,51 @@ @end +// TODO(crbug.com/486840): Replace CRWTestUIWebViewEvaluator with +// CRWTestWKWebViewEvaluator in CRWTestJSInjectionReceiver once UIWebView is +// no longer used. +@interface CRWTestWKWebViewEvaluator : NSObject<CRWJSInjectionEvaluator> { + // Web view for JavaScript evaluation. + base::scoped_nsobject<WKWebView> _webView; + // Set to track injected script managers. + base::scoped_nsobject<NSMutableSet> _injectedScriptManagers; +} +@end + +@implementation CRWTestWKWebViewEvaluator + +- (instancetype)init { + if (self = [super init]) { + _webView.reset([[WKWebView alloc] init]); + _injectedScriptManagers.reset([[NSMutableSet alloc] init]); + } + return self; +} + +- (void)evaluateJavaScript:(NSString*)script + stringResultHandler:(web::JavaScriptCompletion)handler { + [_webView evaluateJavaScript:script completionHandler:handler]; +} + +- (BOOL)scriptHasBeenInjectedForClass:(Class)JSInjectionManagerClass + presenceBeacon:(NSString*)beacon { + return [_injectedScriptManagers containsObject:JSInjectionManagerClass]; +} + +- (void)injectScript:(NSString*)script forClass:(Class)JSInjectionManagerClass { + // Web layer guarantees that __gCrWeb object is always injected first. + NSString* supplementedScript = + [@"window.__gCrWeb = {};" stringByAppendingString:script]; + [_webView evaluateJavaScript:supplementedScript completionHandler:nil]; + [_injectedScriptManagers addObject:JSInjectionManagerClass]; +} + +- (web::WebViewType)webViewType { + return web::WK_WEB_VIEW_TYPE; +} + +@end + @interface CRWTestJSInjectionReceiver () { base::scoped_nsobject<CRWTestUIWebViewEvaluator> evaluator_; }
diff --git a/ios/web/public/web_state/ui/crw_web_delegate.h b/ios/web/public/web_state/ui/crw_web_delegate.h index e9d4411e..753b8dd7 100644 --- a/ios/web/public/web_state/ui/crw_web_delegate.h +++ b/ios/web/public/web_state/ui/crw_web_delegate.h
@@ -258,6 +258,13 @@ // Called when web view process has been terminated. - (void)webControllerWebProcessDidCrash:(CRWWebController*)webController; +// Called when a PassKit file is downloaded. |data| should be the data from a +// PassKit file, but this is not guaranteed, and the delegate is responsible for +// error handling non PassKit data using -[PKPass initWithData:error:]. If the +// download does not successfully complete, |data| will be nil. +- (void)webController:(CRWWebController*)webController + didLoadPassKitObject:(NSData*)data; + @end #endif // IOS_WEB_PUBLIC_WEB_STATE_UI_CRW_WEB_DELEGATE_H_
diff --git a/ios/web/web_state/crw_pass_kit_downloader.h b/ios/web/web_state/crw_pass_kit_downloader.h new file mode 100644 index 0000000..674bb22 --- /dev/null +++ b/ios/web/web_state/crw_pass_kit_downloader.h
@@ -0,0 +1,54 @@ +// Copyright 2015 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 IOS_WEB_WEB_STATE_CRW_PASS_KIT_DOWNLOADER_H_ +#define IOS_WEB_WEB_STATE_CRW_PASS_KIT_DOWNLOADER_H_ + +#import <Foundation/Foundation.h> + +class GURL; + +namespace net { +class URLRequestContextGetter; +} // namespace net + +namespace web { + +// Completion handler called when the download is complete. |data| should be the +// data from a PassKit file, but this is not guaranteed, and the handler is +// responsible for error handling non PassKit data. If the download does not +// successfully complete, |data| will be nil. +typedef void (^PassKitCompletionHandler)(NSData*); + +} // namespace web + +// CRWPassKitDownloader downloads PassKit data and passes it to a completion +// handler. +@interface CRWPassKitDownloader : NSObject + +// Initializes the CRWPassKitDownloader. |getter| must not be null and +// |handler| must not be null. +- (instancetype)initWithContextGetter:(net::URLRequestContextGetter*)getter + completionHandler:(web::PassKitCompletionHandler)handler + NS_DESIGNATED_INITIALIZER; + +- (instancetype)init NS_UNAVAILABLE; + +// Returns whether the given string indicates a MIME type for a PassKit file. +- (BOOL)isMIMETypePassKitType:(NSString*)MIMEType; + +// Downloads a PassKit file and passes the data on to the completion +// handler. +// |URL| is the URL of the PassKit file. The MIME type associated with the +// URL should be for PassKit. If this method is called before a pending +// download completes, the pending download will be cancelled. +- (void)downloadPassKitFileWithURL:(const GURL&)URL; + +// Cancels currently pending download. This method has no effect if called when +// there is no pending download. +- (void)cancelPendingDownload; + +@end + +#endif // IOS_WEB_WEB_STATE_CRW_PASS_KIT_DOWNLOADER_H_
diff --git a/ios/web/web_state/crw_pass_kit_downloader.mm b/ios/web/web_state/crw_pass_kit_downloader.mm new file mode 100644 index 0000000..d988397 --- /dev/null +++ b/ios/web/web_state/crw_pass_kit_downloader.mm
@@ -0,0 +1,201 @@ +// Copyright 2015 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. + +#import "ios/web/web_state/crw_pass_kit_downloader.h" + +#import "base/ios/weak_nsobject.h" +#include "base/mac/scoped_block.h" +#include "base/memory/scoped_ptr.h" +#include "base/metrics/histogram.h" +#include "base/strings/sys_string_conversions.h" +#import "ios/web/crw_network_activity_indicator_manager.h" +#include "net/http/http_response_headers.h" +#include "net/url_request/url_fetcher.h" +#include "net/url_request/url_fetcher_delegate.h" +#include "net/url_request/url_request_context_getter.h" + +using net::URLFetcher; +using net::URLFetcherDelegate; +using net::URLRequestContextGetter; + +namespace { + +// Key of the UMA Download.IOSDownloadPassKitResult histogram. +const char kUMADownloadPassKitResult[] = "Download.IOSDownloadPassKitResult"; + +// Enum for the Download.IOSDownloadPassKitResult UMA histogram to report the +// results of the PassKit download. +// Note: This enum is used to back an UMA histogram, and should be treated as +// append-only. +enum DownloadPassKitResult { + DOWNLOAD_PASS_KIT_SUCCESSFUL = 0, + // PassKit download failed for a reason other than wrong MIME type or 401/403 + // HTTP response. + DOWNLOAD_PASS_KIT_OTHER_FAILURE, + // PassKit download failed due to either a 401 or 403 HTTP response. + DOWNLOAD_PASS_KIT_UNAUTHORIZED_FAILURE, + // PassKit download did not download the correct MIME type. This can happen + // when web server redirects to login page instead of returning PassKit data. + DOWNLOAD_PASS_KIT_WRONG_MIME_TYPE_FAILURE, + DOWNLOAD_PASS_KIT_RESULT_COUNT +}; +} // namespace + +@interface CRWPassKitDownloader () + +// The method called by PassKitFetcherDelegate when the download is complete. +// If data is successfully downloaded, it converts the response to +// NSData and passes the result to |_completionHandler|. +- (void)didFinishDownload; + +// Returns key for CRWNetworkActivityIndicatorManager. +- (NSString*)networkActivityKey; + +// Reports Download.IOSDownloadPassKitResult UMA metric. +- (void)reportUMAPassKitResult:(DownloadPassKitResult)result; + +@end + +namespace { + +// Unique ID for CRWNetworkActivityIndicatorManager. +int g_pass_kit_downloader_class_id = 0; + +// A delegate for the URLFetcher to tell the CRWPassKitDownloader that the +// download is complete. +class PassKitFetcherDelegate : public URLFetcherDelegate { + public: + explicit PassKitFetcherDelegate(CRWPassKitDownloader* owner) + : owner_(owner) {} + void OnURLFetchComplete(const URLFetcher* source) override { + [owner_ didFinishDownload]; + } + + private: + base::WeakNSObject<CRWPassKitDownloader> owner_; + DISALLOW_COPY_AND_ASSIGN(PassKitFetcherDelegate); +}; + +} // namespace + +@implementation CRWPassKitDownloader { + // Completion handler that is called when PassKit data is downloaded. + base::mac::ScopedBlock<web::PassKitCompletionHandler> _completionHandler; + + // URLFetcher with which PassKit data is downloaded. It is initialized + // whenever |downloadPassKitFileWithURL| is called. + scoped_ptr<URLFetcher> _fetcher; + + // Delegate to bridge between URLFetcher callback and CRWPassKitDownlaoder. + scoped_ptr<PassKitFetcherDelegate> _fetcherDelegate; + + // Context getter which is passed to the URLFetcher, as required by + // URLFetcher API. + scoped_refptr<URLRequestContextGetter> _requestContextGetter; + + // Network activity ID for this instance of CRWPassKitDownloader. + int _passKitDownloaderID; +} + +#pragma mark - Public Methods + +- (instancetype)initWithContextGetter:(net::URLRequestContextGetter*)getter + completionHandler:(web::PassKitCompletionHandler)handler { + self = [super init]; + if (self) { + DCHECK(getter); + DCHECK(handler); + _completionHandler.reset([handler copy]); + _fetcherDelegate.reset(new PassKitFetcherDelegate(self)); + _requestContextGetter = getter; + _passKitDownloaderID = g_pass_kit_downloader_class_id++; + } + return self; +} + +- (instancetype)init { + NOTREACHED(); + return nil; +} + +- (void)dealloc { + [[CRWNetworkActivityIndicatorManager sharedInstance] + clearNetworkTasksForGroup:[self networkActivityKey]]; + [super dealloc]; +} + +- (BOOL)isMIMETypePassKitType:(NSString*)MIMEType { + return [MIMEType isEqualToString:@"application/vnd.apple.pkpass"]; +} + +- (void)downloadPassKitFileWithURL:(const GURL&)URL { + _fetcher = URLFetcher::Create(URL, URLFetcher::GET, _fetcherDelegate.get()); + _fetcher->SetRequestContext(_requestContextGetter.get()); + CRWNetworkActivityIndicatorManager* sharedManager = + [CRWNetworkActivityIndicatorManager sharedInstance]; + // Verifies that there are not any network tasks associated with this instance + // before starting another task, so that this method is idempotent. + if (![sharedManager numNetworkTasksForGroup:[self networkActivityKey]]) + [sharedManager startNetworkTaskForGroup:[self networkActivityKey]]; + _fetcher->Start(); +} + +- (void)cancelPendingDownload { + _fetcher.reset(); + CRWNetworkActivityIndicatorManager* sharedManager = + [CRWNetworkActivityIndicatorManager sharedInstance]; + // Verifies that there is a network task associated with this instance + // before stopping a task, so that this method is idempotent. + if ([sharedManager numNetworkTasksForGroup:[self networkActivityKey]]) + [sharedManager stopNetworkTaskForGroup:[self networkActivityKey]]; +} + +#pragma mark - Private Methods + +- (void)didFinishDownload { + [[CRWNetworkActivityIndicatorManager sharedInstance] + stopNetworkTaskForGroup:[self networkActivityKey]]; + int responseCode = _fetcher->GetResponseCode(); + std::string response; + // If the download failed, pass nil to |_completionHandler| and log which + // kind of failure it was. + if (!_fetcher->GetStatus().is_success() || responseCode != 200 || + !_fetcher->GetResponseAsString(&response)) { + DownloadPassKitResult errorType = + (responseCode == 401 || responseCode == 403) + ? DOWNLOAD_PASS_KIT_UNAUTHORIZED_FAILURE + : DOWNLOAD_PASS_KIT_OTHER_FAILURE; + [self reportUMAPassKitResult:errorType]; + _completionHandler.get()(nil); + return; + } + std::string MIMEType; + _fetcher->GetResponseHeaders()->GetMimeType(&MIMEType); + NSString* convertedMIMEType = base::SysUTF8ToNSString(MIMEType); + // Verify for logging purposes that the data actually is PassKit data. The + // completion handler is responsible for displaying the appropriate error + // message if it isn't. This error case can occur when web server redirects to + // another page instead of returning PassKit data. + DownloadPassKitResult successOrFailureLogging = + ([self isMIMETypePassKitType:convertedMIMEType]) + ? DOWNLOAD_PASS_KIT_SUCCESSFUL + : DOWNLOAD_PASS_KIT_WRONG_MIME_TYPE_FAILURE; + [self reportUMAPassKitResult:successOrFailureLogging]; + NSData* data = + [NSData dataWithBytes:response.c_str() length:response.length()]; + _completionHandler.get()(data); +} + +- (NSString*)networkActivityKey { + return [NSString + stringWithFormat:@"PassKitDownloader.NetworkActivityIndicatorKey.%d", + _passKitDownloaderID]; +} + +- (void)reportUMAPassKitResult:(DownloadPassKitResult)result { + UMA_HISTOGRAM_ENUMERATION(kUMADownloadPassKitResult, result, + DOWNLOAD_PASS_KIT_RESULT_COUNT); +} + +@end
diff --git a/ios/web/web_state/crw_pass_kit_downloader_unittest.mm b/ios/web/web_state/crw_pass_kit_downloader_unittest.mm new file mode 100644 index 0000000..c65b238 --- /dev/null +++ b/ios/web/web_state/crw_pass_kit_downloader_unittest.mm
@@ -0,0 +1,156 @@ +// Copyright 2015 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. + +#import "ios/web/web_state/crw_pass_kit_downloader.h" + +#import <Foundation/Foundation.h> + +#import "base/mac/scoped_nsobject.h" +#include "base/memory/scoped_ptr.h" +#import "ios/web/test/web_test.h" +#include "net/base/net_errors.h" +#include "net/http/http_response_headers.h" +#include "net/url_request/test_url_fetcher_factory.h" +#include "net/url_request/url_fetcher_delegate.h" +#include "net/url_request/url_request_test_util.h" +#include "testing/gtest_mac.h" +#include "url/gurl.h" + +using net::HttpResponseHeaders; +using net::URLRequestStatus; + +namespace web { + +// Constant URL to use in tests. +const char kTestUrlString[] = "http://www.example.com"; + +const char kPassKitMimeType[] = "application/vnd.apple.pkpass"; + +// Constant string which is the expected response from the PassKit Downloader. +const char kExpectedString[] = "test string"; + +// Test fixture for testing CRWPassKitDownloader. +class CRWPassKitDownloaderTest : public WebTest { + protected: + void SetUp() override { + WebTest::SetUp(); + completion_handler_success_ = false; + fetcher_factory_.reset(new net::TestURLFetcherFactory()); + downloader_.reset([[CRWPassKitDownloader alloc] + initWithContextGetter:GetBrowserState()->GetRequestContext() + completionHandler:^(NSData* data) { + NSData* expected_data = + [NSData dataWithBytes:kExpectedString + length:strlen(kExpectedString)]; + completion_handler_success_ = [data isEqualToData:expected_data]; + }]); + } + + // Sets up |fetcher|'s request status, HTTP response code, HTTP headers, and + // MIME type. + void SetUpFetcher(net::TestURLFetcher* fetcher, + URLRequestStatus status, + int response_code, + const std::string& mime_type) { + fetcher->set_status(status); + fetcher->set_response_code(response_code); + scoped_refptr<HttpResponseHeaders> headers; + headers = new HttpResponseHeaders("HTTP/1.x 200 OK\0"); + headers->AddHeader("Content-Type: " + mime_type); + fetcher->set_response_headers(headers); + } + + // Test fetcher factory from which we access and control the URLFetcher + // used in CRWPassKitDownloader. + scoped_ptr<net::TestURLFetcherFactory> fetcher_factory_; + + // The CRWPassKitDownloader that is being tested. + base::scoped_nsobject<CRWPassKitDownloader> downloader_; + + // Indicates whether or not the downloader successfully downloaded data. It is + // set from the completion handler based on whether actual data is equal to + // expected data. + bool completion_handler_success_; +}; + +// Tests case where CRWPassKitDownloader successfully downloads data. +TEST_F(CRWPassKitDownloaderTest, TestDownloadPassKitSuccess) { + GURL test_url(kTestUrlString); + [downloader_ downloadPassKitFileWithURL:test_url]; + + UIApplication* shared_app = [UIApplication sharedApplication]; + EXPECT_TRUE([shared_app isNetworkActivityIndicatorVisible]); + + net::TestURLFetcher* fetcher = fetcher_factory_->GetFetcherByID(0); + ASSERT_TRUE(fetcher); + ASSERT_EQ(test_url, fetcher->GetOriginalURL()); + SetUpFetcher(fetcher, URLRequestStatus(), 200, kPassKitMimeType); + fetcher->SetResponseString(kExpectedString); + fetcher->delegate()->OnURLFetchComplete(fetcher); + + EXPECT_FALSE([shared_app isNetworkActivityIndicatorVisible]); + EXPECT_TRUE(completion_handler_success_); +} + +// Tests case where CRWPassKitDownloader fails download due to a bad HTTP +// response code. |completion_handler_success_| should be false. +TEST_F(CRWPassKitDownloaderTest, TestDownloadPassKitBadErrorCodeFailure) { + GURL test_url(kTestUrlString); + [downloader_ downloadPassKitFileWithURL:test_url]; + + UIApplication* shared_app = [UIApplication sharedApplication]; + EXPECT_TRUE([shared_app isNetworkActivityIndicatorVisible]); + + net::TestURLFetcher* fetcher = fetcher_factory_->GetFetcherByID(0); + ASSERT_TRUE(fetcher); + ASSERT_EQ(test_url, fetcher->GetOriginalURL()); + SetUpFetcher(fetcher, URLRequestStatus(), 403, kPassKitMimeType); + fetcher->SetResponseString(kExpectedString); + fetcher->delegate()->OnURLFetchComplete(fetcher); + + EXPECT_FALSE([shared_app isNetworkActivityIndicatorVisible]); + EXPECT_FALSE(completion_handler_success_); +} + +// Tests case where CRWPassKitDownloader fails download with a status set to +// failure. |completion_handler_success_| should be false. +TEST_F(CRWPassKitDownloaderTest, TestDownloadPassKitStatusFailedFailure) { + GURL test_url(kTestUrlString); + [downloader_ downloadPassKitFileWithURL:test_url]; + + UIApplication* shared_app = [UIApplication sharedApplication]; + EXPECT_TRUE([shared_app isNetworkActivityIndicatorVisible]); + + net::TestURLFetcher* fetcher = fetcher_factory_->GetFetcherByID(0); + ASSERT_TRUE(fetcher); + ASSERT_EQ(test_url, fetcher->GetOriginalURL()); + SetUpFetcher(fetcher, URLRequestStatus::FromError(net::ERR_ACCESS_DENIED), + 200, kPassKitMimeType); + fetcher->SetResponseString(kExpectedString); + fetcher->delegate()->OnURLFetchComplete(fetcher); + + EXPECT_FALSE([shared_app isNetworkActivityIndicatorVisible]); + EXPECT_FALSE(completion_handler_success_); +} + +// Tests case where CRWPassKitDownloader fails download with no response data. +// |completion_handler_success_| should be false. +TEST_F(CRWPassKitDownloaderTest, TestDownloadPassKitNoResponseFailure) { + GURL test_url(kTestUrlString); + [downloader_ downloadPassKitFileWithURL:test_url]; + + UIApplication* shared_app = [UIApplication sharedApplication]; + EXPECT_TRUE([shared_app isNetworkActivityIndicatorVisible]); + + net::TestURLFetcher* fetcher = fetcher_factory_->GetFetcherByID(0); + ASSERT_TRUE(fetcher); + ASSERT_EQ(test_url, fetcher->GetOriginalURL()); + SetUpFetcher(fetcher, URLRequestStatus(), 200, kPassKitMimeType); + fetcher->delegate()->OnURLFetchComplete(fetcher); + + EXPECT_FALSE([shared_app isNetworkActivityIndicatorVisible]); + EXPECT_FALSE(completion_handler_success_); +} + +} // namespace
diff --git a/ios/web/web_state/ui/crw_web_controller+protected.h b/ios/web/web_state/ui/crw_web_controller+protected.h index 2a034cd..34f2715 100644 --- a/ios/web/web_state/ui/crw_web_controller+protected.h +++ b/ios/web/web_state/ui/crw_web_controller+protected.h
@@ -214,6 +214,16 @@ - (GURL)URLForHistoryNavigationFromItem:(web::NavigationItem*)fromItem toItem:(web::NavigationItem*)toItem; +// Updates the internal state and informs the delegate that any outstanding load +// operations are cancelled. +- (void)loadCancelled; + +// Called when a load ends in an error. +// TODO(stuartmorgan): Figure out if there's actually enough shared logic that +// this makes sense. At the very least remove inMainFrame since that only makes +// sense for UIWebView. +- (void)handleLoadError:(NSError*)error inMainFrame:(BOOL)inMainFrame; + #pragma mark - Internal methods for use by subclasses // The web view's view of the current URL. During page transitions @@ -271,10 +281,6 @@ // content view. - (void)webViewDidChange; -// Updates the internal state and informs the delegate that any outstanding load -// operations are cancelled. -- (void)loadCancelled; - // Aborts any load for both the web view and web controller. - (void)abortLoad; @@ -333,12 +339,6 @@ referrer:(const web::Referrer&)referrer transition:(ui::PageTransition)transition; -// Called when a load ends in an error. -// TODO(stuartmorgan): Figure out if there's actually enough shared logic that -// this makes sense. At the very least remove inMainFrame since that only makes -// sense for UIWebView. -- (void)handleLoadError:(NSError*)error inMainFrame:(BOOL)inMainFrame; - // Update the appropriate parts of the model and broadcast to the embedder. This // may be called multiple times and thus must be idempotent. - (void)loadCompleteWithSuccess:(BOOL)loadSuccess;
diff --git a/ios/web/web_state/ui/crw_wk_web_view_web_controller.mm b/ios/web/web_state/ui/crw_wk_web_view_web_controller.mm index a254291..8fbeae6 100644 --- a/ios/web/web_state/ui/crw_wk_web_view_web_controller.mm +++ b/ios/web/web_state/ui/crw_wk_web_view_web_controller.mm
@@ -24,6 +24,7 @@ #include "ios/web/navigation/web_load_params.h" #include "ios/web/net/cert_host_pair.h" #import "ios/web/net/crw_cert_verification_controller.h" +#include "ios/web/public/browser_state.h" #include "ios/web/public/cert_store.h" #include "ios/web/public/navigation_item.h" #include "ios/web/public/ssl_status.h" @@ -35,6 +36,7 @@ #import "ios/web/public/web_state/ui/crw_web_view_content_view.h" #import "ios/web/ui_web_view_util.h" #include "ios/web/web_state/blocked_popup_info.h" +#import "ios/web/web_state/crw_pass_kit_downloader.h" #import "ios/web/web_state/error_translation_util.h" #include "ios/web/web_state/frame_info.h" #import "ios/web/web_state/js/crw_js_window_id_manager.h" @@ -182,6 +184,9 @@ // Referrer for the current page. base::scoped_nsobject<NSString> _currentReferrerString; + // Handles downloading PassKit data for WKWebView. Lazy initialized. + base::scoped_nsobject<CRWPassKitDownloader> _passKitDownloader; + // Whether the web page is currently performing window.history.pushState or // window.history.replaceState // Set to YES on window.history.willChangeState message. To NO on @@ -222,6 +227,9 @@ // Identifier used for storing and retrieving certificates. @property(nonatomic, readonly) int certGroupID; +// Downloader for PassKit files. Lazy initialized. +@property(nonatomic, readonly) CRWPassKitDownloader* passKitDownloader; + // Returns the WKWebViewConfigurationProvider associated with the web // controller's BrowserState. - (web::WKWebViewConfigurationProvider&)webViewConfigurationProvider; @@ -673,6 +681,21 @@ // Nothing to do. } +// Override |handleLoadError| to check for PassKit case. +- (void)handleLoadError:(NSError*)error inMainFrame:(BOOL)inMainFrame { + NSString* MIMEType = [_pendingNavigationInfo MIMEType]; + if ([self.passKitDownloader isMIMETypePassKitType:MIMEType]) + return; + [super handleLoadError:error inMainFrame:inMainFrame]; +} + +// Override |loadCancelled| to |cancelPendingDownload| for the +// CRWPassKitDownloader. +- (void)loadCancelled { + [_passKitDownloader cancelPendingDownload]; + [super loadCancelled]; +} + #pragma mark Private methods - (NSDictionary*)wkWebViewObservers { @@ -1326,6 +1349,34 @@ return source != NAVIGATION; } +- (CRWPassKitDownloader*)passKitDownloader { + if (_passKitDownloader) { + return _passKitDownloader.get(); + } + base::WeakNSObject<CRWWKWebViewWebController> weakSelf(self); + web::PassKitCompletionHandler passKitCompletion = ^(NSData* data) { + base::scoped_nsobject<CRWWKWebViewWebController> strongSelf( + [weakSelf retain]); + if (!strongSelf) { + return; + } + // Cancel load to update web state, since the PassKit download happens + // through a separate flow. This follows the same flow as when PassKit is + // downloaded through UIWebView. + [strongSelf loadCancelled]; + SEL didLoadPassKitObject = @selector(webController:didLoadPassKitObject:); + id<CRWWebDelegate> delegate = [strongSelf delegate]; + if ([delegate respondsToSelector:didLoadPassKitObject]) { + [delegate webController:strongSelf didLoadPassKitObject:data]; + } + }; + web::BrowserState* browserState = self.webStateImpl->GetBrowserState(); + _passKitDownloader.reset([[CRWPassKitDownloader alloc] + initWithContextGetter:browserState->GetRequestContext() + completionHandler:passKitCompletion]); + return _passKitDownloader.get(); +} + #pragma mark - #pragma mark CRWWebViewScrollViewProxyObserver @@ -1558,6 +1609,11 @@ [_pendingNavigationInfo setCancelled:YES]; } } + if ([self.passKitDownloader + isMIMETypePassKitType:[_pendingNavigationInfo MIMEType]]) { + GURL URL = net::GURLWithNSURL(navigationResponse.response.URL); + [self.passKitDownloader downloadPassKitFileWithURL:URL]; + } handler(allowNavigation ? WKNavigationResponsePolicyAllow : WKNavigationResponsePolicyCancel);
diff --git a/ios/web/webui/url_data_manager_ios_backend.cc b/ios/web/webui/url_data_manager_ios_backend.cc index d5117c2..cc3e3e9 100644 --- a/ios/web/webui/url_data_manager_ios_backend.cc +++ b/ios/web/webui/url_data_manager_ios_backend.cc
@@ -96,7 +96,7 @@ // net::URLRequestJob implementation. void Start() override; void Kill() override; - int ReadRawData(net::IOBuffer* buf, int buf_size) override; + bool ReadRawData(net::IOBuffer* buf, int buf_size, int* bytes_read) override; bool GetMimeType(std::string* mime_type) const override; int GetResponseCode() const override; void GetResponseInfo(net::HttpResponseInfo* info) override; @@ -142,7 +142,7 @@ // Do the actual copy from data_ (the data we're serving) into |buf|. // Separate from ReadRawData so we can handle async I/O. - int CompleteRead(net::IOBuffer* buf, int buf_size); + void CompleteRead(net::IOBuffer* buf, int buf_size, int* bytes_read); // The actual data we're serving. NULL until it's been fetched. scoped_refptr<base::RefCountedMemory> data_; @@ -291,46 +291,58 @@ void URLRequestChromeJob::DataAvailable(base::RefCountedMemory* bytes) { TRACE_EVENT_ASYNC_END0("browser", "DataManager:Request", this); if (bytes) { + // The request completed, and we have all the data. + // Clear any IO pending status. + SetStatus(net::URLRequestStatus()); + data_ = bytes; + int bytes_read; if (pending_buf_.get()) { CHECK(pending_buf_->data()); - int rv = CompleteRead(pending_buf_.get(), pending_buf_size_); + CompleteRead(pending_buf_.get(), pending_buf_size_, &bytes_read); pending_buf_ = NULL; - ReadRawDataComplete(rv); + NotifyReadComplete(bytes_read); } } else { - ReadRawDataComplete(net::ERR_FAILED); + // The request failed. + NotifyDone( + net::URLRequestStatus(net::URLRequestStatus::FAILED, net::ERR_FAILED)); } } -int URLRequestChromeJob::ReadRawData(net::IOBuffer* buf, int buf_size) { +bool URLRequestChromeJob::ReadRawData(net::IOBuffer* buf, + int buf_size, + int* bytes_read) { if (!data_.get()) { + SetStatus(net::URLRequestStatus(net::URLRequestStatus::IO_PENDING, 0)); DCHECK(!pending_buf_.get()); CHECK(buf->data()); pending_buf_ = buf; pending_buf_size_ = buf_size; - return net::ERR_IO_PENDING; // Tell the caller we're still waiting for - // data. + return false; // Tell the caller we're still waiting for data. } // Otherwise, the data is available. - return CompleteRead(buf, buf_size); + CompleteRead(buf, buf_size, bytes_read); + return true; } -int URLRequestChromeJob::CompleteRead(net::IOBuffer* buf, int buf_size) { +void URLRequestChromeJob::CompleteRead(net::IOBuffer* buf, + int buf_size, + int* bytes_read) { // http://crbug.com/373841 char url_buf[128]; base::strlcpy(url_buf, request_->url().spec().c_str(), arraysize(url_buf)); base::debug::Alias(url_buf); - int remaining = data_->size() - data_offset_; + int remaining = static_cast<int>(data_->size()) - data_offset_; if (buf_size > remaining) buf_size = remaining; if (buf_size > 0) { memcpy(buf->data(), data_->front() + data_offset_, buf_size); data_offset_ += buf_size; } - return buf_size; + *bytes_read = buf_size; } namespace {
diff --git a/ipc/mojo/BUILD.gn b/ipc/mojo/BUILD.gn index ead44ce..29e3a957 100644 --- a/ipc/mojo/BUILD.gn +++ b/ipc/mojo/BUILD.gn
@@ -35,6 +35,7 @@ defines = [ "IPC_MOJO_IMPLEMENTATION" ] deps = [ + ":client_channel", "//base", "//base/third_party/dynamic_annotations", "//ipc", @@ -42,7 +43,6 @@ "//mojo/public/c/environment:environment", "//mojo/public/cpp/bindings", "//third_party/mojo/src/mojo/edk/system", - ":client_channel", ] }
diff --git a/jingle/BUILD.gn b/jingle/BUILD.gn index c6c19e5..10f2b2b 100644 --- a/jingle/BUILD.gn +++ b/jingle/BUILD.gn
@@ -92,11 +92,11 @@ "//third_party/libjingle", ] deps = [ + ":jingle_glue", "//base", "//net", "//third_party/expat", "//url", - ":jingle_glue", ] }
diff --git a/mandoline/BUILD.gn b/mandoline/BUILD.gn index 9022e7d..ff9ff73 100644 --- a/mandoline/BUILD.gn +++ b/mandoline/BUILD.gn
@@ -9,8 +9,8 @@ testonly = true deps = [ - "//mojo", ":tests", + "//mojo", ] if (is_android) {
diff --git a/mandoline/app/android/BUILD.gn b/mandoline/app/android/BUILD.gn index d986ec3..59bbcb4 100644 --- a/mandoline/app/android/BUILD.gn +++ b/mandoline/app/android/BUILD.gn
@@ -101,8 +101,8 @@ java_files = [ "apk/src/org/chromium/mandoline/MandolineActivity.java" ] deps = [ - "//mojo/runner:java", "//base:base_java", + "//mojo/runner:java", ] } @@ -132,9 +132,9 @@ ":copy_mandoline_runner", ":java", ":mandoline_apk_resources", + "//base:base_java", "//mojo/runner:java", "//mojo/runner:resources", - "//base:base_java", "//ui/platform_window/android:platform_window_java", google_play_services_resources, ]
diff --git a/mandoline/app/register_local_aliases.cc b/mandoline/app/register_local_aliases.cc index f71abfa..b9c7375 100644 --- a/mandoline/app/register_local_aliases.cc +++ b/mandoline/app/register_local_aliases.cc
@@ -31,13 +31,6 @@ GURL("mojo:resource_provider"), GURL("mojo:core_services"), "Files"); #endif -#if defined(USE_AURA) - manager->RegisterApplicationPackageAlias(GURL("mojo:desktop_ui"), - GURL("mojo:core_services"), - "Core"); - manager->RegisterApplicationPackageAlias( - GURL("mojo:omnibox"), GURL("mojo:core_services"), "Core"); -#endif manager->RegisterApplicationPackageAlias( GURL("mojo:web_view"), GURL("mojo:core_services"), "Core"); manager->RegisterApplicationPackageAlias(
diff --git a/mandoline/services/core_services/BUILD.gn b/mandoline/services/core_services/BUILD.gn index 0f2fe0602..db14fa26 100644 --- a/mandoline/services/core_services/BUILD.gn +++ b/mandoline/services/core_services/BUILD.gn
@@ -76,13 +76,4 @@ } else { sources += [ "application_delegate_factory_default.cc" ] } - - if (use_aura) { - deps += [ - "//components/mus/public/cpp", - "//mandoline/ui/desktop_ui:lib", - "//mandoline/ui/omnibox:lib", - ] - sources += [ "application_delegate_factory_aura.cc" ] - } }
diff --git a/mandoline/services/core_services/application_delegate_factory.h b/mandoline/services/core_services/application_delegate_factory.h index d92bc68..537d9f9 100644 --- a/mandoline/services/core_services/application_delegate_factory.h +++ b/mandoline/services/core_services/application_delegate_factory.h
@@ -27,11 +27,6 @@ const std::string& url); #endif -#if defined(USE_AURA) -scoped_ptr<mojo::ApplicationDelegate> CreateApplicationDelegateAura( - const std::string& url); -#endif - } // namespace core_services #endif // MANDOLINE_SERVICES_CORE_SERVICES_APPLICATION_DELEGATE_FACTORY_H_
diff --git a/mandoline/services/core_services/application_delegate_factory_aura.cc b/mandoline/services/core_services/application_delegate_factory_aura.cc deleted file mode 100644 index c061bd88..0000000 --- a/mandoline/services/core_services/application_delegate_factory_aura.cc +++ /dev/null
@@ -1,21 +0,0 @@ -// Copyright 2015 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 "mandoline/services/core_services/application_delegate_factory.h" - -#include "mandoline/ui/desktop_ui/browser_manager.h" -#include "mandoline/ui/omnibox/omnibox_application.h" - -namespace core_services { - -scoped_ptr<mojo::ApplicationDelegate> CreateApplicationDelegateAura( - const std::string& url) { - if (url == "mojo://desktop_ui/") - return make_scoped_ptr(new mandoline::BrowserManager); - else if (url == "mojo://omnibox/") - return make_scoped_ptr(new mandoline::OmniboxApplication); - return nullptr; -} - -} // namespace core_services
diff --git a/mandoline/services/core_services/core_services_application_delegate.cc b/mandoline/services/core_services/core_services_application_delegate.cc index 7c970f29..f7fd32a 100644 --- a/mandoline/services/core_services/core_services_application_delegate.cc +++ b/mandoline/services/core_services/core_services_application_delegate.cc
@@ -136,9 +136,6 @@ } else if (url == "mojo://web_view/") { delegate.reset(new web_view::WebViewApplicationDelegate); } else { -#if defined(USE_AURA) - delegate = CreateApplicationDelegateAura(url); -#endif #if !defined(OS_ANDROID) if (!delegate) delegate = CreateApplicationDelegateNotAndroid(url);
diff --git a/mandoline/tools/data/FILES.cfg b/mandoline/tools/data/FILES.cfg index 3f54ab9..74da561 100644 --- a/mandoline/tools/data/FILES.cfg +++ b/mandoline/tools/data/FILES.cfg
@@ -51,6 +51,11 @@ 'platforms': ['win'], }, { + 'filepath': 'omnibox', + 'platforms': ['linux', 'win'], + 'directory': True, + }, + { 'filepath': 'pdf_viewer', 'platforms': ['linux', 'win'], 'directory': True,
diff --git a/mandoline/ui/BUILD.gn b/mandoline/ui/BUILD.gn index 1c7de332..d43dddc6 100644 --- a/mandoline/ui/BUILD.gn +++ b/mandoline/ui/BUILD.gn
@@ -5,13 +5,13 @@ import("//build/config/ui.gni") group("ui") { - deps = [ - "phone_ui", - ] + deps = [] if (use_aura) { deps += [ "desktop_ui", "omnibox", ] + } else if (is_android) { + deps += [ "phone_ui" ] } }
diff --git a/mandoline/ui/desktop_ui/BUILD.gn b/mandoline/ui/desktop_ui/BUILD.gn index e84c565..f5aa86bf 100644 --- a/mandoline/ui/desktop_ui/BUILD.gn +++ b/mandoline/ui/desktop_ui/BUILD.gn
@@ -35,7 +35,6 @@ ] deps = [ - "public/interfaces", "//base", "//components/web_view/public/cpp", "//components/web_view/public/interfaces", @@ -52,6 +51,7 @@ "//ui/views", "//ui/views/mus:for_mojo_application", "//url", + "public/interfaces", ] }
diff --git a/mandoline/ui/desktop_ui/browser_apptest.cc b/mandoline/ui/desktop_ui/browser_apptest.cc index 5f847ce..1673cde 100644 --- a/mandoline/ui/desktop_ui/browser_apptest.cc +++ b/mandoline/ui/desktop_ui/browser_apptest.cc
@@ -16,9 +16,7 @@ // mojo::test::ApplicationTestBase: void SetUp() override { mojo::test::ApplicationTestBase::SetUp(); - mojo::URLRequestPtr request(mojo::URLRequest::New()); - request->url = mojo::String::From("mojo:desktop_ui"); - application_impl()->ConnectToService(request.Pass(), &launch_handler_); + application_impl()->ConnectToService("mojo:desktop_ui", &launch_handler_); ASSERT_TRUE(launch_handler_.is_bound()); }
diff --git a/mandoline/ui/desktop_ui/browser_manager.cc b/mandoline/ui/desktop_ui/browser_manager.cc index 1049472..7eac4d9 100644 --- a/mandoline/ui/desktop_ui/browser_manager.cc +++ b/mandoline/ui/desktop_ui/browser_manager.cc
@@ -51,9 +51,7 @@ app_ = app; tracing_.Initialize(app); - mojo::URLRequestPtr request(mojo::URLRequest::New()); - request->url = "mojo:mus"; - app_->ConnectToService(request.Pass(), &host_factory_); + app_->ConnectToService("mojo:mus", &host_factory_); base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); // Create a Browser for each valid URL in the command line.
diff --git a/mandoline/ui/desktop_ui/browser_window.cc b/mandoline/ui/desktop_ui/browser_window.cc index c049cf2..9c6b051 100644 --- a/mandoline/ui/desktop_ui/browser_window.cc +++ b/mandoline/ui/desktop_ui/browser_window.cc
@@ -141,9 +141,7 @@ void BrowserWindow::ShowOmnibox() { TRACE_EVENT0("desktop_ui", "BrowserWindow::ShowOmnibox"); if (!omnibox_.get()) { - mojo::URLRequestPtr request(mojo::URLRequest::New()); - request->url = mojo::String::From("mojo:omnibox"); - omnibox_connection_ = app_->ConnectToApplication(request.Pass()); + omnibox_connection_ = app_->ConnectToApplication("mojo:omnibox"); omnibox_connection_->AddService<ViewEmbedder>(this); omnibox_connection_->ConnectToService(&omnibox_); omnibox_connection_->SetRemoteServiceProviderConnectionErrorHandler( @@ -242,10 +240,8 @@ if (!recorded_browser_startup_metrics && base::CommandLine::ForCurrentProcess()->HasSwitch( tracing::kEnableStatsCollectionBindings)) { - mojo::URLRequestPtr request(mojo::URLRequest::New()); - request->url = mojo::String::From("mojo:tracing"); tracing::StartupPerformanceDataCollectorPtr collector; - app_->ConnectToService(request.Pass(), &collector); + app_->ConnectToService("mojo:tracing", &collector); collector->SetBrowserWindowDisplayTicks(display_ticks.ToInternalValue()); collector->SetBrowserOpenTabsTimeDelta(open_tabs_delta.ToInternalValue()); collector->SetBrowserMessageLoopStartTicks(
diff --git a/mandoline/ui/phone_ui/BUILD.gn b/mandoline/ui/phone_ui/BUILD.gn index 0f3ddf7..21de6851 100644 --- a/mandoline/ui/phone_ui/BUILD.gn +++ b/mandoline/ui/phone_ui/BUILD.gn
@@ -12,8 +12,8 @@ deps = [ ":lib", - "//mojo/application/public/cpp", "//components/web_view:web_view", + "//mojo/application/public/cpp", ] }
diff --git a/mash/wm/BUILD.gn b/mash/wm/BUILD.gn index fc8d2e86..3aad50e7 100644 --- a/mash/wm/BUILD.gn +++ b/mash/wm/BUILD.gn
@@ -10,8 +10,8 @@ group("wm") { testonly = true deps = [ - ":example_wm", ":apptests", + ":example_wm", ] } @@ -159,8 +159,8 @@ "//testing/gtest", "//third_party/mojo/src/mojo/edk/system", "//ui/events", - "//ui/gfx/geometry", "//ui/gfx:test_support", + "//ui/gfx/geometry", "//ui/mojo/geometry:interfaces", "//ui/mojo/geometry:util", ]
diff --git a/mash/wm/window_manager_apptest.cc b/mash/wm/window_manager_apptest.cc index 37f33f2..f8618c3 100644 --- a/mash/wm/window_manager_apptest.cc +++ b/mash/wm/window_manager_apptest.cc
@@ -19,9 +19,7 @@ protected: void ConnectToWindowManager(mus::mojom::WindowManagerPtr* window_manager) { - mojo::URLRequestPtr request(mojo::URLRequest::New()); - request->url = "mojo:example_wm"; - application_impl()->ConnectToService(request.Pass(), window_manager); + application_impl()->ConnectToService("mojo:example_wm", window_manager); } mus::Window* OpenWindow(mus::mojom::WindowManager* window_manager) {
diff --git a/media/BUILD.gn b/media/BUILD.gn index cf872b5..eb4c38f 100644 --- a/media/BUILD.gn +++ b/media/BUILD.gn
@@ -550,8 +550,8 @@ } public_deps = [ - "//media/base", "//media/audio", + "//media/base", "//third_party/opus", ] @@ -673,16 +673,17 @@ ":test_support", "//base/allocator", "//base/test:test_support", - "//gpu/command_buffer/common", "//gpu:test_support", - "//media/audio:unittests", + "//gpu/command_buffer/common", "//media/audio:test_support", - "//media/base:unittests", + "//media/audio:unittests", "//media/base:test_support", + "//media/base:unittests", "//media/test:pipeline_integration_tests", "//skia", # Direct dependency required to inherit config. "//testing/gmock", "//testing/gtest", + "//third_party/libyuv", "//third_party/widevine/cdm:version_h", "//ui/gfx:test_support", "//url", @@ -897,8 +898,8 @@ "//testing/gmock", "//testing/gtest", "//third_party/ffmpeg", - "//ui/gfx/geometry", "//ui/gfx:test_support", + "//ui/gfx/geometry", ] } }
diff --git a/media/base/BUILD.gn b/media/base/BUILD.gn index b01c488..ee7c518a 100644 --- a/media/base/BUILD.gn +++ b/media/base/BUILD.gn
@@ -209,8 +209,8 @@ defines = [] public_deps = [] deps = [ - "//ui/events:events_base", "//skia", + "//ui/events:events_base", ] libs = [] configs += [ @@ -358,8 +358,8 @@ ] configs += [ "//media:media_config" ] deps = [ - "//testing/gmock", "//media:shared_memory_support", + "//testing/gmock", ] }
diff --git a/media/base/video_util.cc b/media/base/video_util.cc index cddbb9c..414e57b0 100644 --- a/media/base/video_util.cc +++ b/media/base/video_util.cc
@@ -29,47 +29,6 @@ visible_size.height()); } -void CopyPlane(size_t plane, const uint8* source, int stride, int rows, - VideoFrame* frame) { - uint8* dest = frame->data(plane); - int dest_stride = frame->stride(plane); - - // Clamp in case source frame has smaller stride. - int bytes_to_copy_per_row = std::min(frame->row_bytes(plane), stride); - - // Clamp in case source frame has smaller height. - int rows_to_copy = std::min(frame->rows(plane), rows); - - // Copy! - for (int row = 0; row < rows_to_copy; ++row) { - memcpy(dest, source, bytes_to_copy_per_row); - source += stride; - dest += dest_stride; - } -} - -void CopyYPlane(const uint8* source, int stride, int rows, VideoFrame* frame) { - CopyPlane(VideoFrame::kYPlane, source, stride, rows, frame); -} - -void CopyUPlane(const uint8* source, int stride, int rows, VideoFrame* frame) { - CopyPlane(VideoFrame::kUPlane, source, stride, rows, frame); -} - -void CopyVPlane(const uint8* source, int stride, int rows, VideoFrame* frame) { - CopyPlane(VideoFrame::kVPlane, source, stride, rows, frame); -} - -void CopyAPlane(const uint8* source, int stride, int rows, VideoFrame* frame) { - CopyPlane(VideoFrame::kAPlane, source, stride, rows, frame); -} - -void MakeOpaqueAPlane(int stride, int rows, VideoFrame* frame) { - int rows_to_clear = std::min(frame->rows(VideoFrame::kAPlane), rows); - memset(frame->data(VideoFrame::kAPlane), 255, - frame->stride(VideoFrame::kAPlane) * rows_to_clear); -} - void FillYUV(VideoFrame* frame, uint8 y, uint8 u, uint8 v) { // Fill the Y plane. uint8* y_plane = frame->data(VideoFrame::kYPlane);
diff --git a/media/base/video_util.h b/media/base/video_util.h index abbcad4..77c6523c9 100644 --- a/media/base/video_util.h +++ b/media/base/video_util.h
@@ -19,28 +19,6 @@ int aspect_ratio_numerator, int aspect_ratio_denominator); -// Copies a plane of YUV(A) source into a VideoFrame object, taking into account -// source and destinations dimensions. -// -// NOTE: rows is *not* the same as height! -MEDIA_EXPORT void CopyYPlane(const uint8* source, int stride, int rows, - VideoFrame* frame); -MEDIA_EXPORT void CopyUPlane(const uint8* source, int stride, int rows, - VideoFrame* frame); -MEDIA_EXPORT void CopyVPlane(const uint8* source, int stride, int rows, - VideoFrame* frame); -MEDIA_EXPORT void CopyAPlane(const uint8* source, int stride, int rows, - VideoFrame* frame); - -// Sets alpha plane values to be completely opaque (all 255's). -MEDIA_EXPORT void MakeOpaqueAPlane(int stride, int rows, VideoFrame* frame); - -// |plane| is one of VideoFrame::kYPlane, VideoFrame::kUPlane, -// VideoFrame::kVPlane or VideoFrame::kAPlane -MEDIA_EXPORT void CopyPlane(size_t plane, const uint8* source, int stride, - int rows, VideoFrame* frame); - - // Fills |frame| containing YUV data to the given color values. MEDIA_EXPORT void FillYUV(VideoFrame* frame, uint8 y, uint8 u, uint8 v);
diff --git a/media/base/video_util_unittest.cc b/media/base/video_util_unittest.cc index a62f0cb..ba53a58c 100644 --- a/media/base/video_util_unittest.cc +++ b/media/base/video_util_unittest.cc
@@ -42,14 +42,6 @@ PIXEL_FORMAT_YV12, size, gfx::Rect(size), size, base::TimeDelta()); } - void CopyPlanes() { - CopyYPlane(y_plane_.get(), y_stride_, height_, destination_frame_.get()); - CopyUPlane( - u_plane_.get(), u_stride_, height_ / 2, destination_frame_.get()); - CopyVPlane( - v_plane_.get(), v_stride_, height_ / 2, destination_frame_.get()); - } - private: scoped_ptr<uint8[]> y_plane_; scoped_ptr<uint8[]> u_plane_; @@ -94,24 +86,6 @@ EXPECT_EQ(gfx::Size(207, 240), GetNaturalSize(visible_size, 11, 17)); } -TEST_F(VideoUtilTest, CopyPlane_Exact) { - CreateSourceFrame(16, 16, 16, 8, 8); - CreateDestinationFrame(16, 16); - CopyPlanes(); -} - -TEST_F(VideoUtilTest, CopyPlane_SmallerSource) { - CreateSourceFrame(8, 8, 8, 4, 4); - CreateDestinationFrame(16, 16); - CopyPlanes(); -} - -TEST_F(VideoUtilTest, CopyPlane_SmallerDestination) { - CreateSourceFrame(16, 16, 16, 8, 8); - CreateDestinationFrame(8, 8); - CopyPlanes(); -} - namespace { uint8 src6x4[] = {
diff --git a/media/blink/BUILD.gn b/media/blink/BUILD.gn index 3b9365c..3e974486 100644 --- a/media/blink/BUILD.gn +++ b/media/blink/BUILD.gn
@@ -106,8 +106,8 @@ "//testing/gmock", "//testing/gtest", "//third_party/WebKit/public:blink", - "//ui/gfx/geometry", "//ui/gfx:test_support", + "//ui/gfx/geometry", "//url", ]
diff --git a/media/cast/BUILD.gn b/media/cast/BUILD.gn index d0ae8f1..4213a23 100644 --- a/media/cast/BUILD.gn +++ b/media/cast/BUILD.gn
@@ -6,8 +6,8 @@ component("cast") { deps = [ - ":sender", ":receiver", + ":sender", ] }
diff --git a/media/cast/cast_config.h b/media/cast/cast_config.h index 36ed104f..f352186d 100644 --- a/media/cast/cast_config.h +++ b/media/cast/cast_config.h
@@ -94,9 +94,7 @@ // This field is used differently by various encoders. It defaults to 1. // - // For VP8, it should be 1 to operate in single-buffer mode, or 3 to operate - // in multi-buffer mode. See - // http://www.webmproject.org/docs/encoder-parameters/ for details. + // For VP8, this field is ignored. // // For H.264 on Mac or iOS, it controls the max number of frames the encoder // may hold before emitting a frame. A larger window may allow higher encoding
diff --git a/media/cast/sender/audio_sender.cc b/media/cast/sender/audio_sender.cc index 87e4d3cca..5126750 100644 --- a/media/cast/sender/audio_sender.cc +++ b/media/cast/sender/audio_sender.cc
@@ -105,9 +105,6 @@ return RtpDeltaToTimeDelta(samples_in_flight, rtp_timebase()); } -void AudioSender::OnAck(uint32 frame_id) { -} - void AudioSender::OnEncodedAudioFrame( int encoder_bitrate, scoped_ptr<SenderEncodedFrame> encoded_frame,
diff --git a/media/cast/sender/audio_sender.h b/media/cast/sender/audio_sender.h index 78006c6..aa45020 100644 --- a/media/cast/sender/audio_sender.h +++ b/media/cast/sender/audio_sender.h
@@ -47,7 +47,6 @@ protected: int GetNumberOfFramesInEncoder() const final; base::TimeDelta GetInFlightMediaDuration() const final; - void OnAck(uint32 frame_id) final; private: // Called by the |audio_encoder_| with the next EncodedFrame to send.
diff --git a/media/cast/sender/external_video_encoder.cc b/media/cast/sender/external_video_encoder.cc index 196b16e2..876908f 100644 --- a/media/cast/sender/external_video_encoder.cc +++ b/media/cast/sender/external_video_encoder.cc
@@ -556,10 +556,6 @@ key_frame_requested_ = true; } -void ExternalVideoEncoder::LatestFrameIdToReference(uint32 /*frame_id*/) { - // Do nothing. Not supported. -} - void ExternalVideoEncoder::OnCreateVideoEncodeAccelerator( const VideoSenderConfig& video_config, uint32 first_frame_id,
diff --git a/media/cast/sender/external_video_encoder.h b/media/cast/sender/external_video_encoder.h index b884ed9..73f5fed 100644 --- a/media/cast/sender/external_video_encoder.h +++ b/media/cast/sender/external_video_encoder.h
@@ -44,7 +44,6 @@ const FrameEncodedCallback& frame_encoded_callback) final; void SetBitRate(int new_bit_rate) final; void GenerateKeyFrame() final; - void LatestFrameIdToReference(uint32 frame_id) final; private: class VEAClientImpl;
diff --git a/media/cast/sender/fake_software_video_encoder.cc b/media/cast/sender/fake_software_video_encoder.cc index 53cfb6c..88c6cf6 100644 --- a/media/cast/sender/fake_software_video_encoder.cc +++ b/media/cast/sender/fake_software_video_encoder.cc
@@ -18,7 +18,6 @@ : video_config_(video_config), next_frame_is_key_(true), frame_id_(0), - frame_id_to_reference_(0), frame_size_(0) { } @@ -77,10 +76,6 @@ next_frame_is_key_ = true; } -void FakeSoftwareVideoEncoder::LatestFrameIdToReference(uint32 frame_id) { - frame_id_to_reference_ = frame_id; -} - } // namespace cast } // namespace media
diff --git a/media/cast/sender/fake_software_video_encoder.h b/media/cast/sender/fake_software_video_encoder.h index 76336aa..39c0344 100644 --- a/media/cast/sender/fake_software_video_encoder.h +++ b/media/cast/sender/fake_software_video_encoder.h
@@ -24,14 +24,12 @@ SenderEncodedFrame* encoded_frame) final; void UpdateRates(uint32 new_bitrate) final; void GenerateKeyFrame() final; - void LatestFrameIdToReference(uint32 frame_id) final; private: VideoSenderConfig video_config_; gfx::Size last_frame_size_; bool next_frame_is_key_; uint32 frame_id_; - uint32 frame_id_to_reference_; int frame_size_; };
diff --git a/media/cast/sender/frame_sender.cc b/media/cast/sender/frame_sender.cc index 772cf01..e4936c8 100644 --- a/media/cast/sender/frame_sender.cc +++ b/media/cast/sender/frame_sender.cc
@@ -295,8 +295,6 @@ return; // Cannot get an ACK without having first sent a frame. if (cast_feedback.missing_frames_and_packets.empty()) { - OnAck(cast_feedback.ack_frame_id); - if (latest_acked_frame_id_ == cast_feedback.ack_frame_id) { VLOG(1) << SENDER_SSRC << "Received duplicate ACK for frame " << latest_acked_frame_id_;
diff --git a/media/cast/sender/frame_sender.h b/media/cast/sender/frame_sender.h index f264490..d3b925e 100644 --- a/media/cast/sender/frame_sender.h +++ b/media/cast/sender/frame_sender.h
@@ -57,9 +57,6 @@ // of sent, unacknowledged frames. virtual base::TimeDelta GetInFlightMediaDuration() const = 0; - // Called when we get an ACK for a frame. - virtual void OnAck(uint32 frame_id) = 0; - protected: // Schedule and execute periodic sending of RTCP report. void ScheduleNextRtcpReport();
diff --git a/media/cast/sender/h264_vt_encoder.cc b/media/cast/sender/h264_vt_encoder.cc index d02b738..6185a63 100644 --- a/media/cast/sender/h264_vt_encoder.cc +++ b/media/cast/sender/h264_vt_encoder.cc
@@ -628,10 +628,6 @@ encode_next_frame_as_keyframe_ = true; } -void H264VideoToolboxEncoder::LatestFrameIdToReference(uint32 /*frame_id*/) { - // Not supported by VideoToolbox in any meaningful manner. -} - scoped_ptr<VideoFrameFactory> H264VideoToolboxEncoder::CreateVideoFrameFactory() { DCHECK(thread_checker_.CalledOnValidThread());
diff --git a/media/cast/sender/h264_vt_encoder.h b/media/cast/sender/h264_vt_encoder.h index 1f51c23..a152b0af 100644 --- a/media/cast/sender/h264_vt_encoder.h +++ b/media/cast/sender/h264_vt_encoder.h
@@ -44,7 +44,6 @@ const FrameEncodedCallback& frame_encoded_callback) final; void SetBitRate(int new_bit_rate) final; void GenerateKeyFrame() final; - void LatestFrameIdToReference(uint32 frame_id) final; scoped_ptr<VideoFrameFactory> CreateVideoFrameFactory() final; void EmitFrames() final;
diff --git a/media/cast/sender/h264_vt_encoder_unittest.cc b/media/cast/sender/h264_vt_encoder_unittest.cc index 419cbb87..ebdda907 100644 --- a/media/cast/sender/h264_vt_encoder_unittest.cc +++ b/media/cast/sender/h264_vt_encoder_unittest.cc
@@ -132,8 +132,7 @@ : public base::RefCountedThreadSafe<EndToEndFrameChecker> { public: explicit EndToEndFrameChecker(const VideoDecoderConfig& config) - : decoder_(base::MessageLoop::current()->task_runner()), - count_frames_checked_(0) { + : decoder_(), count_frames_checked_(0) { bool decoder_init_result; decoder_.Initialize( config, false, media::SetCdmReadyCB(),
diff --git a/media/cast/sender/size_adaptable_video_encoder_base.cc b/media/cast/sender/size_adaptable_video_encoder_base.cc index 8c6b046..b626760 100644 --- a/media/cast/sender/size_adaptable_video_encoder_base.cc +++ b/media/cast/sender/size_adaptable_video_encoder_base.cc
@@ -77,12 +77,6 @@ encoder_->GenerateKeyFrame(); } -void SizeAdaptableVideoEncoderBase::LatestFrameIdToReference(uint32 frame_id) { - DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); - if (encoder_) - encoder_->LatestFrameIdToReference(frame_id); -} - scoped_ptr<VideoFrameFactory> SizeAdaptableVideoEncoderBase::CreateVideoFrameFactory() { DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
diff --git a/media/cast/sender/size_adaptable_video_encoder_base.h b/media/cast/sender/size_adaptable_video_encoder_base.h index 621c3d07..ee7e1fa2c 100644 --- a/media/cast/sender/size_adaptable_video_encoder_base.h +++ b/media/cast/sender/size_adaptable_video_encoder_base.h
@@ -37,7 +37,6 @@ const FrameEncodedCallback& frame_encoded_callback) final; void SetBitRate(int new_bit_rate) final; void GenerateKeyFrame() final; - void LatestFrameIdToReference(uint32 frame_id) final; scoped_ptr<VideoFrameFactory> CreateVideoFrameFactory() final; void EmitFrames() final;
diff --git a/media/cast/sender/software_video_encoder.h b/media/cast/sender/software_video_encoder.h index 56db81db..98cdf4b 100644 --- a/media/cast/sender/software_video_encoder.h +++ b/media/cast/sender/software_video_encoder.h
@@ -38,9 +38,6 @@ // Set the next frame to be a key frame. virtual void GenerateKeyFrame() = 0; - - // Set the last frame to reference. - virtual void LatestFrameIdToReference(uint32 frame_id) = 0; }; } // namespace cast
diff --git a/media/cast/sender/video_encoder.h b/media/cast/sender/video_encoder.h index ff73c550..1fba17a 100644 --- a/media/cast/sender/video_encoder.h +++ b/media/cast/sender/video_encoder.h
@@ -58,9 +58,6 @@ // Inform the encoder to encode the next frame as a key frame. virtual void GenerateKeyFrame() = 0; - // Inform the encoder to only reference frames older or equal to frame_id; - virtual void LatestFrameIdToReference(uint32 frame_id) = 0; - // Creates a |VideoFrameFactory| object to vend |VideoFrame| object with // encoder affinity (defined as offering some sort of performance benefit). // This is an optional capability and by default returns null.
diff --git a/media/cast/sender/video_encoder_impl.cc b/media/cast/sender/video_encoder_impl.cc index fcfac17..5bc7f448 100644 --- a/media/cast/sender/video_encoder_impl.cc +++ b/media/cast/sender/video_encoder_impl.cc
@@ -39,8 +39,6 @@ if (dynamic_config.key_frame_requested) { encoder->GenerateKeyFrame(); } - encoder->LatestFrameIdToReference( - dynamic_config.latest_frame_id_to_reference); encoder->UpdateRates(dynamic_config.bit_rate); scoped_ptr<SenderEncodedFrame> encoded_frame(new SenderEncodedFrame()); @@ -86,7 +84,6 @@ } dynamic_config_.key_frame_requested = false; - dynamic_config_.latest_frame_id_to_reference = kStartFrameId; dynamic_config_.bit_rate = video_config.start_bitrate; cast_environment_->PostTask( @@ -140,10 +137,5 @@ dynamic_config_.key_frame_requested = true; } -// Inform the encoder to only reference frames older or equal to frame_id; -void VideoEncoderImpl::LatestFrameIdToReference(uint32 frame_id) { - dynamic_config_.latest_frame_id_to_reference = frame_id; -} - } // namespace cast } // namespace media
diff --git a/media/cast/sender/video_encoder_impl.h b/media/cast/sender/video_encoder_impl.h index a8cf207..8c84df18 100644 --- a/media/cast/sender/video_encoder_impl.h +++ b/media/cast/sender/video_encoder_impl.h
@@ -22,7 +22,6 @@ public: struct CodecDynamicConfig { bool key_frame_requested; - uint32 latest_frame_id_to_reference; int bit_rate; }; @@ -42,7 +41,6 @@ const FrameEncodedCallback& frame_encoded_callback) final; void SetBitRate(int new_bit_rate) final; void GenerateKeyFrame() final; - void LatestFrameIdToReference(uint32 frame_id) final; private: scoped_refptr<CastEnvironment> cast_environment_;
diff --git a/media/cast/sender/video_encoder_unittest.cc b/media/cast/sender/video_encoder_unittest.cc index 2c2d480..e308fc4 100644 --- a/media/cast/sender/video_encoder_unittest.cc +++ b/media/cast/sender/video_encoder_unittest.cc
@@ -59,10 +59,9 @@ RunTasksAndAdvanceClock(); } - void CreateEncoder(bool three_buffer_mode) { + void CreateEncoder() { ASSERT_EQ(STATUS_UNINITIALIZED, operational_status_); - video_config_.max_number_of_video_buffers_used = - (three_buffer_mode ? 3 : 1); + video_config_.max_number_of_video_buffers_used = 1; video_encoder_ = VideoEncoder::Create( cast_environment_, video_config_, @@ -280,7 +279,7 @@ // A simple test to encode ten frames of video, expecting to see one key frame // followed by nine delta frames. TEST_P(VideoEncoderTest, GeneratesKeyFrameThenOnlyDeltaFrames) { - CreateEncoder(false); + CreateEncoder(); SetVEAFactoryAutoRespond(true); EXPECT_EQ(0, count_frames_delivered()); @@ -314,44 +313,12 @@ ExpectVEAResponsesForExternalVideoEncoder(1, 3); } -// Tests basic frame dependency rules when using the VP8 encoder in multi-buffer -// mode. -TEST_P(VideoEncoderTest, FramesDoNotDependOnUnackedFramesInMultiBufferMode) { - if (!is_testing_software_vp8_encoder()) - return; // Only test multibuffer mode for the software VP8 encoder. - CreateEncoder(true); - - EXPECT_EQ(0, count_frames_delivered()); - - const gfx::Size frame_size(1280, 720); - EXPECT_TRUE(EncodeAndCheckDelivery(CreateTestVideoFrame(frame_size), 0, 0)); - RunTasksAndAdvanceClock(); - - video_encoder()->LatestFrameIdToReference(0); - EXPECT_TRUE(EncodeAndCheckDelivery(CreateTestVideoFrame(frame_size), 1, 0)); - RunTasksAndAdvanceClock(); - - video_encoder()->LatestFrameIdToReference(1); - EXPECT_TRUE(EncodeAndCheckDelivery(CreateTestVideoFrame(frame_size), 2, 1)); - RunTasksAndAdvanceClock(); - - video_encoder()->LatestFrameIdToReference(2); - - for (uint32 frame_id = 3; frame_id < 10; ++frame_id) { - EXPECT_TRUE(EncodeAndCheckDelivery( - CreateTestVideoFrame(frame_size), frame_id, 2)); - RunTasksAndAdvanceClock(); - } - - EXPECT_EQ(10, count_frames_delivered()); -} - // Tests that the encoder continues to output EncodedFrames as the frame size // changes. See media/cast/receiver/video_decoder_unittest.cc for a complete // encode/decode cycle of varied frame sizes that actually checks the frame // content. TEST_P(VideoEncoderTest, EncodesVariedFrameSizes) { - CreateEncoder(false); + CreateEncoder(); SetVEAFactoryAutoRespond(true); EXPECT_EQ(0, count_frames_delivered()); @@ -416,7 +383,7 @@ // encoders, this tests that the encoder can be safely destroyed before the task // is run that delivers the first EncodedFrame. TEST_P(VideoEncoderTest, CanBeDestroyedBeforeVEAIsCreated) { - CreateEncoder(false); + CreateEncoder(); // Send a frame to spawn creation of the ExternalVideoEncoder instance. EncodeAndCheckDelivery(CreateTestVideoFrame(gfx::Size(1280, 720)), 0, 0);
diff --git a/media/cast/sender/video_sender.cc b/media/cast/sender/video_sender.cc index f8890bb..ff65423 100644 --- a/media/cast/sender/video_sender.cc +++ b/media/cast/sender/video_sender.cc
@@ -271,10 +271,6 @@ } } -void VideoSender::OnAck(uint32 frame_id) { - video_encoder_->LatestFrameIdToReference(frame_id); -} - // static int VideoSender::GetMaximumTargetBitrateForFrame( const media::VideoFrame& frame) {
diff --git a/media/cast/sender/video_sender.h b/media/cast/sender/video_sender.h index 826321c..a75bafb 100644 --- a/media/cast/sender/video_sender.h +++ b/media/cast/sender/video_sender.h
@@ -62,7 +62,6 @@ protected: int GetNumberOfFramesInEncoder() const final; base::TimeDelta GetInFlightMediaDuration() const final; - void OnAck(uint32 frame_id) final; // Return the maximum target bitrate that should be used for the given video // |frame|. This will be provided to CongestionControl as a soft maximum
diff --git a/media/cast/sender/vp8_encoder.cc b/media/cast/sender/vp8_encoder.cc index 771075a..d586fa5 100644 --- a/media/cast/sender/vp8_encoder.cc +++ b/media/cast/sender/vp8_encoder.cc
@@ -28,33 +28,12 @@ Vp8Encoder::Vp8Encoder(const VideoSenderConfig& video_config) : cast_config_(video_config), - use_multiple_video_buffers_( - cast_config_.max_number_of_video_buffers_used == - kNumberOfVp8VideoBuffers), key_frame_requested_(true), bitrate_kbit_(cast_config_.start_bitrate / 1000), last_encoded_frame_id_(kStartFrameId), - last_acked_frame_id_(kStartFrameId), - undroppable_frames_(0), has_seen_zero_length_encoded_frame_(false) { config_.g_timebase.den = 0; // Not initialized. - for (int i = 0; i < kNumberOfVp8VideoBuffers; ++i) { - buffer_state_[i].frame_id = last_encoded_frame_id_; - buffer_state_[i].state = kBufferStartState; - } - - // VP8 have 3 buffers available for prediction, with - // max_number_of_video_buffers_used set to 1 we maximize the coding efficiency - // however in this mode we can not skip frames in the receiver to catch up - // after a temporary network outage; with max_number_of_video_buffers_used - // set to 3 we allow 2 frames to be skipped by the receiver without error - // propagation. - DCHECK(cast_config_.max_number_of_video_buffers_used == 1 || - cast_config_.max_number_of_video_buffers_used == - kNumberOfVp8VideoBuffers) - << "Invalid argument"; - thread_checker_.DetachFromThread(); } @@ -77,8 +56,7 @@ // the old size, in terms of area, the existing encoder instance can // continue. Otherwise, completely tear-down and re-create a new encoder to // avoid a shutdown crash. - if (frame_size.GetArea() <= gfx::Size(config_.g_w, config_.g_h).GetArea() && - !use_multiple_video_buffers_) { + if (frame_size.GetArea() <= gfx::Size(config_.g_w, config_.g_h).GetArea()) { DVLOG(1) << "Continuing to use existing encoder at smaller frame size: " << gfx::Size(config_.g_w, config_.g_h).ToString() << " --> " << frame_size.ToString(); @@ -99,14 +77,6 @@ << frame_size.ToString(); } - // Reset multi-buffer mode state. - last_acked_frame_id_ = last_encoded_frame_id_; - undroppable_frames_ = 0; - for (int i = 0; i < kNumberOfVp8VideoBuffers; ++i) { - buffer_state_[i].frame_id = last_encoded_frame_id_; - buffer_state_[i].state = kBufferStartState; - } - // Populate encoder configuration with default values. CHECK_EQ(vpx_codec_enc_config_default(vpx_codec_vp8_cx(), &config_, 0), VPX_CODEC_OK); @@ -117,11 +87,7 @@ // Set the timebase to match that of base::TimeDelta. config_.g_timebase.num = 1; config_.g_timebase.den = base::Time::kMicrosecondsPerSecond; - if (use_multiple_video_buffers_) { - // We must enable error resilience when we use multiple buffers, due to - // codec requirements. - config_.g_error_resilient = 1; - } + // |g_pass| and |g_lag_in_frames| must be "one pass" and zero, respectively, // in order for VP8 to support changing frame sizes during encoding: config_.g_pass = VPX_RC_ONE_PASS; @@ -183,23 +149,6 @@ if (!is_initialized() || gfx::Size(config_.g_w, config_.g_h) != frame_size) ConfigureForNewFrameSize(frame_size); - uint32 latest_frame_id_to_reference; - Vp8Buffers buffer_to_update; - vpx_codec_flags_t flags = 0; - if (key_frame_requested_) { - flags = VPX_EFLAG_FORCE_KF; - // Self reference. - latest_frame_id_to_reference = last_encoded_frame_id_ + 1; - // We can pick any buffer as buffer_to_update since we update - // them all. - buffer_to_update = kLastBuffer; - } else { - // Reference all acked frames (buffers). - latest_frame_id_to_reference = GetCodecReferenceFlags(&flags); - buffer_to_update = GetNextBufferToUpdate(); - GetCodecUpdateFlags(buffer_to_update, &flags); - } - // Wrapper for vpx_codec_encode() to access the YUV data in the |video_frame|. // Only the VISIBLE rectangle within |video_frame| is exposed to the codec. vpx_image_t vpx_image; @@ -250,11 +199,9 @@ // zero to force the encoder to base its single-frame bandwidth calculations // entirely on |predicted_frame_duration| and the target bitrate setting being // micro-managed via calls to UpdateRates(). - CHECK_EQ(vpx_codec_encode(&encoder_, - &vpx_image, - 0, + CHECK_EQ(vpx_codec_encode(&encoder_, &vpx_image, 0, predicted_frame_duration.InMicroseconds(), - flags, + key_frame_requested_ ? VPX_EFLAG_FORCE_KF : 0, VPX_DL_REALTIME), VPX_CODEC_OK) << "BUG: Invalid arguments passed to vpx_codec_encode()."; @@ -275,7 +222,7 @@ // Frame dependencies could theoretically be relaxed by looking for the // VPX_FRAME_IS_DROPPABLE flag, but in recent testing (Oct 2014), this // flag never seems to be set. - encoded_frame->referenced_frame_id = latest_frame_id_to_reference; + encoded_frame->referenced_frame_id = last_encoded_frame_id_ - 1; } encoded_frame->rtp_timestamp = TimeDeltaToRtpDelta(video_frame->timestamp(), kVideoFrequency); @@ -340,158 +287,6 @@ if (encoded_frame->dependency == EncodedFrame::KEY) { key_frame_requested_ = false; - - for (int i = 0; i < kNumberOfVp8VideoBuffers; ++i) { - buffer_state_[i].state = kBufferSent; - buffer_state_[i].frame_id = encoded_frame->frame_id; - } - } else { - if (buffer_to_update != kNoBuffer) { - buffer_state_[buffer_to_update].state = kBufferSent; - buffer_state_[buffer_to_update].frame_id = encoded_frame->frame_id; - } - } -} - -uint32 Vp8Encoder::GetCodecReferenceFlags(vpx_codec_flags_t* flags) { - if (!use_multiple_video_buffers_) - return last_encoded_frame_id_; - - const uint32 kMagicFrameOffset = 512; - // We set latest_frame_to_reference to an old frame so that - // IsNewerFrameId will work correctly. - uint32 latest_frame_to_reference = - last_encoded_frame_id_ - kMagicFrameOffset; - - // Reference all acked frames. - // TODO(hubbe): We may also want to allow references to the - // last encoded frame, if that frame was assigned to a buffer. - for (int i = 0; i < kNumberOfVp8VideoBuffers; ++i) { - if (buffer_state_[i].state == kBufferAcked) { - if (IsNewerFrameId(buffer_state_[i].frame_id, - latest_frame_to_reference)) { - latest_frame_to_reference = buffer_state_[i].frame_id; - } - } else { - switch (i) { - case kAltRefBuffer: - *flags |= VP8_EFLAG_NO_REF_ARF; - break; - case kGoldenBuffer: - *flags |= VP8_EFLAG_NO_REF_GF; - break; - case kLastBuffer: - *flags |= VP8_EFLAG_NO_REF_LAST; - break; - } - } - } - - if (latest_frame_to_reference == - last_encoded_frame_id_ - kMagicFrameOffset) { - // We have nothing to reference, it's kind of like a key frame, - // but doesn't reset buffers. - latest_frame_to_reference = last_encoded_frame_id_ + 1; - } - - return latest_frame_to_reference; -} - -Vp8Encoder::Vp8Buffers Vp8Encoder::GetNextBufferToUpdate() { - if (!use_multiple_video_buffers_) - return kNoBuffer; - - // The goal here is to make sure that we always keep one ACKed - // buffer while trying to get an ACK for a newer buffer as we go. - // Here are the rules for which buffer to select for update: - // 1. If there is a buffer in state kStartState, use it. - // 2. If there is a buffer other than the oldest buffer - // which is Acked, use the oldest buffer. - // 3. If there are Sent buffers which are older than - // latest_acked_frame_, use the oldest one. - // 4. If all else fails, just overwrite the newest buffer, - // but no more than 3 times in a row. - // TODO(hubbe): Figure out if 3 is optimal. - // Note, rule 1-3 describe cases where there is a "free" buffer - // that we can use. Rule 4 describes what happens when there is - // no free buffer available. - - // Buffers, sorted from oldest frame to newest. - Vp8Encoder::Vp8Buffers buffers[kNumberOfVp8VideoBuffers]; - - for (int i = 0; i < kNumberOfVp8VideoBuffers; ++i) { - Vp8Encoder::Vp8Buffers buffer = static_cast<Vp8Encoder::Vp8Buffers>(i); - - // Rule 1 - if (buffer_state_[buffer].state == kBufferStartState) { - undroppable_frames_ = 0; - return buffer; - } - buffers[buffer] = buffer; - } - - // Sorting three elements with selection sort. - for (int i = 0; i < kNumberOfVp8VideoBuffers - 1; i++) { - for (int j = i + 1; j < kNumberOfVp8VideoBuffers; j++) { - if (IsOlderFrameId(buffer_state_[buffers[j]].frame_id, - buffer_state_[buffers[i]].frame_id)) { - std::swap(buffers[i], buffers[j]); - } - } - } - - // Rule 2 - if (buffer_state_[buffers[1]].state == kBufferAcked || - buffer_state_[buffers[2]].state == kBufferAcked) { - undroppable_frames_ = 0; - return buffers[0]; - } - - // Rule 3 - for (int i = 0; i < kNumberOfVp8VideoBuffers; i++) { - if (buffer_state_[buffers[i]].state == kBufferSent && - IsOlderFrameId(buffer_state_[buffers[i]].frame_id, - last_acked_frame_id_)) { - undroppable_frames_ = 0; - return buffers[i]; - } - } - - // Rule 4 - if (undroppable_frames_ >= 3) { - undroppable_frames_ = 0; - return kNoBuffer; - } else { - undroppable_frames_++; - return buffers[kNumberOfVp8VideoBuffers - 1]; - } -} - -void Vp8Encoder::GetCodecUpdateFlags(Vp8Buffers buffer_to_update, - vpx_codec_flags_t* flags) { - if (!use_multiple_video_buffers_) - return; - - // Update at most one buffer, except for key-frames. - switch (buffer_to_update) { - case kAltRefBuffer: - *flags |= VP8_EFLAG_NO_UPD_GF; - *flags |= VP8_EFLAG_NO_UPD_LAST; - break; - case kLastBuffer: - *flags |= VP8_EFLAG_NO_UPD_GF; - *flags |= VP8_EFLAG_NO_UPD_ARF; - break; - case kGoldenBuffer: - *flags |= VP8_EFLAG_NO_UPD_ARF; - *flags |= VP8_EFLAG_NO_UPD_LAST; - break; - case kNoBuffer: - *flags |= VP8_EFLAG_NO_UPD_ARF; - *flags |= VP8_EFLAG_NO_UPD_GF; - *flags |= VP8_EFLAG_NO_UPD_LAST; - *flags |= VP8_EFLAG_NO_UPD_ENTROPY; - break; } } @@ -515,23 +310,6 @@ VLOG(1) << "VP8 new rc_target_bitrate: " << new_bitrate_kbit << " kbps"; } -void Vp8Encoder::LatestFrameIdToReference(uint32 frame_id) { - DCHECK(thread_checker_.CalledOnValidThread()); - if (!use_multiple_video_buffers_) - return; - - VLOG(2) << "VP8 ok to reference frame:" << static_cast<int>(frame_id); - for (int i = 0; i < kNumberOfVp8VideoBuffers; ++i) { - if (frame_id == buffer_state_[i].frame_id) { - buffer_state_[i].state = kBufferAcked; - break; - } - } - if (IsOlderFrameId(last_acked_frame_id_, frame_id)) { - last_acked_frame_id_ = frame_id; - } -} - void Vp8Encoder::GenerateKeyFrame() { DCHECK(thread_checker_.CalledOnValidThread()); key_frame_requested_ = true;
diff --git a/media/cast/sender/vp8_encoder.h b/media/cast/sender/vp8_encoder.h index 180fbf0..c3d985f 100644 --- a/media/cast/sender/vp8_encoder.h +++ b/media/cast/sender/vp8_encoder.h
@@ -33,29 +33,8 @@ SenderEncodedFrame* encoded_frame) final; void UpdateRates(uint32 new_bitrate) final; void GenerateKeyFrame() final; - void LatestFrameIdToReference(uint32 frame_id) final; private: - enum { kNumberOfVp8VideoBuffers = 3 }; - - enum Vp8Buffers { - kAltRefBuffer = 0, - kGoldenBuffer = 1, - kLastBuffer = 2, - kNoBuffer = 3 // Note: must be last. - }; - - enum Vp8BufferState { - kBufferStartState, - kBufferSent, - kBufferAcked - }; - - struct BufferState { - uint32 frame_id; - Vp8BufferState state; - }; - bool is_initialized() const { // ConfigureForNewFrameSize() sets the timebase denominator value to // non-zero if the encoder is successfully initialized, and it is zero @@ -68,19 +47,7 @@ // |encoder_| instance. void ConfigureForNewFrameSize(const gfx::Size& frame_size); - // Calculate which next Vp8 buffers to update with the next frame. - Vp8Buffers GetNextBufferToUpdate(); - - // Get encoder flags for our referenced encoder buffers. - // Return which previous frame to reference. - uint32 GetCodecReferenceFlags(vpx_codec_flags_t* flags); - - // Get encoder flags for our encoder buffers to update with next frame. - void GetCodecUpdateFlags(Vp8Buffers buffer_to_update, - vpx_codec_flags_t* flags); - const VideoSenderConfig cast_config_; - const bool use_multiple_video_buffers_; // VP8 internal objects. These are valid for use only while is_initialized() // returns true. @@ -101,16 +68,6 @@ // The last encoded frame's ID. uint32 last_encoded_frame_id_; - // Used to track which buffers are old enough to be re-used. - uint32 last_acked_frame_id_; - - // Used by GetNextBufferToUpdate() to track how many consecutive times the - // newest buffer had to be overwritten. - int undroppable_frames_; - - // Tracks the lifecycle and dependency state of each of the three buffers. - BufferState buffer_state_[kNumberOfVp8VideoBuffers]; - // This is bound to the thread where Initialize() is called. base::ThreadChecker thread_checker_;
diff --git a/media/cast/test/end2end_unittest.cc b/media/cast/test/end2end_unittest.cc index b7880c4..863da03 100644 --- a/media/cast/test/end2end_unittest.cc +++ b/media/cast/test/end2end_unittest.cc
@@ -961,45 +961,6 @@ EXPECT_EQ(10, test_receiver_video_callback_->number_times_called()); } -TEST_F(End2EndTest, DropEveryOtherFrame3Buffers) { - Configure(CODEC_VIDEO_VP8, CODEC_AUDIO_OPUS, kDefaultAudioSamplingRate, 3); - int target_delay = 300; - video_sender_config_.max_playout_delay = - base::TimeDelta::FromMilliseconds(target_delay); - audio_sender_config_.max_playout_delay = - base::TimeDelta::FromMilliseconds(target_delay); - video_receiver_config_.rtp_max_delay_ms = target_delay; - Create(); - sender_to_receiver_.DropAllPacketsBelongingToOddFrames(); - - int video_start = kVideoStart; - base::TimeTicks reference_time; - - int i = 0; - for (; i < 20; ++i) { - reference_time = testing_clock_sender_->NowTicks(); - SendVideoFrame(video_start, reference_time); - - if (i % 2 == 0) { - test_receiver_video_callback_->AddExpectedResult( - video_start, - reference_time + base::TimeDelta::FromMilliseconds(target_delay), - i == 0); - - // GetRawVideoFrame will not return the frame until we are close in - // time before we should render the frame. - cast_receiver_->RequestDecodedVideoFrame( - base::Bind(&TestReceiverVideoCallback::CheckVideoFrame, - test_receiver_video_callback_)); - } - RunTasks(kFrameTimerMs); - video_start++; - } - - RunTasks(2 * kFrameTimerMs + target_delay); // Empty the pipeline. - EXPECT_EQ(i / 2, test_receiver_video_callback_->number_times_called()); -} - TEST_F(End2EndTest, CryptoVideo) { Configure(CODEC_VIDEO_VP8, CODEC_AUDIO_PCM16, 32000, 1);
diff --git a/media/cdm/json_web_key.cc b/media/cdm/json_web_key.cc index 5d8c5306..eba4d6a 100644 --- a/media/cdm/json_web_key.cc +++ b/media/cdm/json_web_key.cc
@@ -4,13 +4,14 @@ #include "media/cdm/json_web_key.h" -#include "base/base64.h" +#include "base/base64url.h" #include "base/json/json_reader.h" #include "base/json/json_string_value_serializer.h" #include "base/json/string_escape.h" #include "base/logging.h" #include "base/memory/scoped_ptr.h" #include "base/strings/string_number_conversions.h" +#include "base/strings/string_piece.h" #include "base/strings/string_util.h" #include "base/values.h" @@ -22,71 +23,11 @@ const char kKeyTag[] = "k"; const char kKeyIdTag[] = "kid"; const char kKeyIdsTag[] = "kids"; -const char kBase64Padding = '='; -const char kBase64Plus[] = "+"; -const char kBase64UrlPlusReplacement[] = "-"; -const char kBase64Slash[] = "/"; -const char kBase64UrlSlashReplacement[] = "_"; -const char kBase64UrlInvalid[] = "+/="; const char kTypeTag[] = "type"; const char kTemporarySession[] = "temporary"; const char kPersistentLicenseSession[] = "persistent-license"; const char kPersistentReleaseMessageSession[] = "persistent-release-message"; -// Encodes |input| into a base64url string without padding. -static std::string EncodeBase64Url(const uint8* input, int input_length) { - std::string encoded_text; - base::Base64Encode( - std::string(reinterpret_cast<const char*>(input), input_length), - &encoded_text); - - // Remove any padding characters added by Base64Encode(). - size_t found = encoded_text.find_last_not_of(kBase64Padding); - if (found != std::string::npos) - encoded_text.erase(found + 1); - - // base64url encoding means the characters '-' and '_' must be used - // instead of '+' and '/', respectively. - base::ReplaceChars(encoded_text, kBase64Plus, kBase64UrlPlusReplacement, - &encoded_text); - base::ReplaceChars(encoded_text, kBase64Slash, kBase64UrlSlashReplacement, - &encoded_text); - - return encoded_text; -} - -// Decodes a base64url string. Returns empty string on error. -static std::string DecodeBase64Url(const std::string& encoded_text) { - // EME spec doesn't allow '+', '/', or padding characters. - if (encoded_text.find_first_of(kBase64UrlInvalid) != std::string::npos) { - DVLOG(1) << "Invalid base64url format: " << encoded_text; - return std::string(); - } - - // Since base::Base64Decode() requires padding characters, add them so length - // of |encoded_text| is exactly a multiple of 4. - size_t num_last_grouping_chars = encoded_text.length() % 4; - std::string modified_text = encoded_text; - if (num_last_grouping_chars > 0) - modified_text.append(4 - num_last_grouping_chars, kBase64Padding); - - // base64url encoding means the characters '-' and '_' must be used - // instead of '+' and '/', respectively, so replace them before calling - // base::Base64Decode(). - base::ReplaceChars(modified_text, kBase64UrlPlusReplacement, kBase64Plus, - &modified_text); - base::ReplaceChars(modified_text, kBase64UrlSlashReplacement, kBase64Slash, - &modified_text); - - std::string decoded_text; - if (!base::Base64Decode(modified_text, &decoded_text)) { - DVLOG(1) << "Base64 decoding failed on: " << modified_text; - return std::string(); - } - - return decoded_text; -} - static std::string ShortenTo64Characters(const std::string& input) { // Convert |input| into a string with escaped characters replacing any // non-ASCII characters. Limiting |input| to the first 65 characters so @@ -107,10 +48,18 @@ int key_length, const uint8* key_id, int key_id_length) { + std::string key_string, key_id_string; + base::Base64UrlEncode( + base::StringPiece(reinterpret_cast<const char*>(key), key_length), + base::Base64UrlEncodePolicy::OMIT_PADDING, &key_string); + base::Base64UrlEncode( + base::StringPiece(reinterpret_cast<const char*>(key_id), key_id_length), + base::Base64UrlEncodePolicy::OMIT_PADDING, &key_id_string); + scoped_ptr<base::DictionaryValue> jwk(new base::DictionaryValue()); jwk->SetString(kKeyTypeTag, kKeyTypeOct); - jwk->SetString(kKeyTag, EncodeBase64Url(key, key_length)); - jwk->SetString(kKeyIdTag, EncodeBase64Url(key_id, key_id_length)); + jwk->SetString(kKeyTag, key_string); + jwk->SetString(kKeyIdTag, key_id_string); return jwk.Pass(); } @@ -185,15 +134,21 @@ return false; } - // Key ID and key are base64-encoded strings, so decode them. - std::string raw_key_id = DecodeBase64Url(encoded_key_id); - if (raw_key_id.empty()) { + // Key ID and key are base64url-encoded strings, so decode them. + std::string raw_key_id; + if (!base::Base64UrlDecode(encoded_key_id, + base::Base64UrlDecodePolicy::DISALLOW_PADDING, + &raw_key_id) || + raw_key_id.empty()) { DVLOG(1) << "Invalid '" << kKeyIdTag << "' value: " << encoded_key_id; return false; } - std::string raw_key = DecodeBase64Url(encoded_key); - if (raw_key.empty()) { + std::string raw_key; + if (!base::Base64UrlDecode(encoded_key, + base::Base64UrlDecodePolicy::DISALLOW_PADDING, + &raw_key) || + raw_key.empty()) { DVLOG(1) << "Invalid '" << kKeyTag << "' value: " << encoded_key; return false; } @@ -312,9 +267,12 @@ return false; } - // Key ID is a base64-encoded string, so decode it. - std::string raw_key_id = DecodeBase64Url(encoded_key_id); - if (raw_key_id.empty()) { + // Key ID is a base64url-encoded string, so decode it. + std::string raw_key_id; + if (!base::Base64UrlDecode(encoded_key_id, + base::Base64UrlDecodePolicy::DISALLOW_PADDING, + &raw_key_id) || + raw_key_id.empty()) { error_message->assign("'"); error_message->append(kKeyIdsTag); error_message->append("'["); @@ -341,8 +299,15 @@ // Create the license request. scoped_ptr<base::DictionaryValue> request(new base::DictionaryValue()); scoped_ptr<base::ListValue> list(new base::ListValue()); - for (const auto& key_id : key_ids) - list->AppendString(EncodeBase64Url(&key_id[0], key_id.size())); + for (const auto& key_id : key_ids) { + std::string key_id_string; + base::Base64UrlEncode( + base::StringPiece(reinterpret_cast<const char*>(key_id.data()), + key_id.size()), + base::Base64UrlEncodePolicy::OMIT_PADDING, &key_id_string); + + list->AppendString(key_id_string); + } request->Set(kKeyIdsTag, list.release()); switch (session_type) { @@ -372,8 +337,15 @@ // Create the init_data. scoped_ptr<base::DictionaryValue> dictionary(new base::DictionaryValue()); scoped_ptr<base::ListValue> list(new base::ListValue()); - for (const auto& key_id : key_ids) - list->AppendString(EncodeBase64Url(&key_id[0], key_id.size())); + for (const auto& key_id : key_ids) { + std::string key_id_string; + base::Base64UrlEncode( + base::StringPiece(reinterpret_cast<const char*>(key_id.data()), + key_id.size()), + base::Base64UrlEncodePolicy::OMIT_PADDING, &key_id_string); + + list->AppendString(key_id_string); + } dictionary->Set(kKeyIdsTag, list.release()); // Serialize the dictionary as a string. @@ -423,8 +395,11 @@ return false; } - std::string decoded_string = DecodeBase64Url(encoded_key); - if (decoded_string.empty()) { + std::string decoded_string; + if (!base::Base64UrlDecode(encoded_key, + base::Base64UrlDecodePolicy::DISALLOW_PADDING, + &decoded_string) || + decoded_string.empty()) { DVLOG(1) << "Invalid '" << kKeyIdsTag << "' value: " << encoded_key; return false; }
diff --git a/media/filters/ffmpeg_video_decoder.cc b/media/filters/ffmpeg_video_decoder.cc index 5c419f5f..04350fc0 100644 --- a/media/filters/ffmpeg_video_decoder.cc +++ b/media/filters/ffmpeg_video_decoder.cc
@@ -72,10 +72,10 @@ return avcodec_find_decoder(VideoCodecToCodecID(codec)) != nullptr; } -FFmpegVideoDecoder::FFmpegVideoDecoder( - const scoped_refptr<base::SingleThreadTaskRunner>& task_runner) - : task_runner_(task_runner), state_(kUninitialized), - decode_nalus_(false) {} +FFmpegVideoDecoder::FFmpegVideoDecoder() + : state_(kUninitialized), decode_nalus_(false) { + thread_checker_.DetachFromThread(); +} int FFmpegVideoDecoder::GetVideoBuffer(struct AVCodecContext* codec_context, AVFrame* frame, @@ -168,7 +168,7 @@ const SetCdmReadyCB& /* set_cdm_ready_cb */, const InitCB& init_cb, const OutputCB& output_cb) { - DCHECK(task_runner_->BelongsToCurrentThread()); + DCHECK(thread_checker_.CalledOnValidThread()); DCHECK(config.IsValidConfig()); DCHECK(!output_cb.is_null()); @@ -198,7 +198,7 @@ void FFmpegVideoDecoder::Decode(const scoped_refptr<DecoderBuffer>& buffer, const DecodeCB& decode_cb) { - DCHECK(task_runner_->BelongsToCurrentThread()); + DCHECK(thread_checker_.CalledOnValidThread()); DCHECK(buffer.get()); DCHECK(!decode_cb.is_null()); CHECK_NE(state_, kUninitialized); @@ -258,15 +258,16 @@ } void FFmpegVideoDecoder::Reset(const base::Closure& closure) { - DCHECK(task_runner_->BelongsToCurrentThread()); + DCHECK(thread_checker_.CalledOnValidThread()); avcodec_flush_buffers(codec_context_.get()); state_ = kNormal; - task_runner_->PostTask(FROM_HERE, closure); + // PostTask() to avoid calling |closure| inmediately. + base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, closure); } FFmpegVideoDecoder::~FFmpegVideoDecoder() { - DCHECK(task_runner_->BelongsToCurrentThread()); + DCHECK(thread_checker_.CalledOnValidThread()); if (state_ != kUninitialized) ReleaseFFmpegResources();
diff --git a/media/filters/ffmpeg_video_decoder.h b/media/filters/ffmpeg_video_decoder.h index 8477ad5..54a62beb 100644 --- a/media/filters/ffmpeg_video_decoder.h +++ b/media/filters/ffmpeg_video_decoder.h
@@ -9,6 +9,7 @@ #include "base/callback.h" #include "base/memory/scoped_ptr.h" +#include "base/threading/thread_checker.h" #include "media/base/video_decoder.h" #include "media/base/video_decoder_config.h" #include "media/base/video_frame_pool.h" @@ -29,8 +30,7 @@ public: static bool IsCodecSupported(VideoCodec codec); - explicit FFmpegVideoDecoder( - const scoped_refptr<base::SingleThreadTaskRunner>& task_runner); + FFmpegVideoDecoder(); ~FFmpegVideoDecoder() override; // Allow decoding of individual NALU. Entire frames are required by default. @@ -75,7 +75,7 @@ // and resets them to NULL. void ReleaseFFmpegResources(); - scoped_refptr<base::SingleThreadTaskRunner> task_runner_; + base::ThreadChecker thread_checker_; DecoderState state_;
diff --git a/media/filters/ffmpeg_video_decoder_unittest.cc b/media/filters/ffmpeg_video_decoder_unittest.cc index 307c0f673..e01d8b8 100644 --- a/media/filters/ffmpeg_video_decoder_unittest.cc +++ b/media/filters/ffmpeg_video_decoder_unittest.cc
@@ -49,7 +49,7 @@ class FFmpegVideoDecoderTest : public testing::Test { public: FFmpegVideoDecoderTest() - : decoder_(new FFmpegVideoDecoder(message_loop_.task_runner())), + : decoder_(new FFmpegVideoDecoder()), decode_cb_(base::Bind(&FFmpegVideoDecoderTest::DecodeDone, base::Unretained(this))) { FFmpegGlue::InitializeFFmpeg();
diff --git a/media/filters/vpx_video_decoder.cc b/media/filters/vpx_video_decoder.cc index d006f6f..180c002a 100644 --- a/media/filters/vpx_video_decoder.cc +++ b/media/filters/vpx_video_decoder.cc
@@ -545,9 +545,9 @@ void VpxVideoDecoder::CopyVpxImageToVideoFrame( const struct vpx_image* vpx_image, scoped_refptr<VideoFrame>* video_frame) { - CHECK(vpx_image); - CHECK(vpx_image->fmt == VPX_IMG_FMT_I420 || - vpx_image->fmt == VPX_IMG_FMT_I444); + DCHECK(vpx_image); + DCHECK(vpx_image->fmt == VPX_IMG_FMT_I420 || + vpx_image->fmt == VPX_IMG_FMT_I444); VideoPixelFormat codec_format = PIXEL_FORMAT_YV12; if (vpx_image->fmt == VPX_IMG_FMT_I444)
diff --git a/media/media.gyp b/media/media.gyp index 6dd8100..342a30f 100644 --- a/media/media.gyp +++ b/media/media.gyp
@@ -1187,6 +1187,7 @@ '../skia/skia.gyp:skia', '../testing/gmock.gyp:gmock', '../testing/gtest.gyp:gtest', + '../third_party/libyuv/libyuv.gyp:libyuv', '../third_party/widevine/cdm/widevine_cdm.gyp:widevine_cdm_version_h', '../ui/gfx/gfx.gyp:gfx', '../ui/gfx/gfx.gyp:gfx_geometry',
diff --git a/media/midi/BUILD.gn b/media/midi/BUILD.gn index 29a5080e..01a2e09f 100644 --- a/media/midi/BUILD.gn +++ b/media/midi/BUILD.gn
@@ -117,8 +117,8 @@ defines += [ "EXPORT_USB_MIDI" ] deps += [ - "//base:i18n", ":midi_jni_headers", + "//base:i18n", ] }
diff --git a/media/mojo/services/BUILD.gn b/media/mojo/services/BUILD.gn index 32228fc8..8a6261f 100644 --- a/media/mojo/services/BUILD.gn +++ b/media/mojo/services/BUILD.gn
@@ -141,8 +141,8 @@ ":media_client", "//base", "//media", - "//media/mojo/interfaces", "//media:shared_memory_support", + "//media/mojo/interfaces", "//mojo/common", ] }
diff --git a/media/mojo/services/media_apptest.cc b/media/mojo/services/media_apptest.cc index 129b193..9c995f60 100644 --- a/media/mojo/services/media_apptest.cc +++ b/media/mojo/services/media_apptest.cc
@@ -57,9 +57,7 @@ void SetUp() override { ApplicationTestBase::SetUp(); - mojo::URLRequestPtr request = mojo::URLRequest::New(); - request->url = "mojo:media"; - connection_ = application_impl()->ConnectToApplication(request.Pass()); + connection_ = application_impl()->ConnectToApplication("mojo:media"); connection_->SetRemoteServiceProviderConnectionErrorHandler( base::Bind(&MediaAppTest::ConnectionClosed, base::Unretained(this)));
diff --git a/media/renderers/default_renderer_factory.cc b/media/renderers/default_renderer_factory.cc index c1c2aaa5..4296ba33 100644 --- a/media/renderers/default_renderer_factory.cc +++ b/media/renderers/default_renderer_factory.cc
@@ -82,7 +82,7 @@ #endif #if !defined(MEDIA_DISABLE_FFMPEG) && !defined(DISABLE_FFMPEG_VIDEO_DECODERS) - video_decoders.push_back(new FFmpegVideoDecoder(media_task_runner)); + video_decoders.push_back(new FFmpegVideoDecoder()); #endif scoped_ptr<VideoRenderer> video_renderer(new VideoRendererImpl(
diff --git a/media/renderers/skcanvas_video_renderer_unittest.cc b/media/renderers/skcanvas_video_renderer_unittest.cc index d787bf0..fad340db 100644 --- a/media/renderers/skcanvas_video_renderer_unittest.cc +++ b/media/renderers/skcanvas_video_renderer_unittest.cc
@@ -10,6 +10,7 @@ #include "media/base/video_util.h" #include "media/renderers/skcanvas_video_renderer.h" #include "testing/gtest/include/gtest/gtest.h" +#include "third_party/libyuv/include/libyuv/convert.h" #include "third_party/skia/include/core/SkCanvas.h" #include "third_party/skia/include/gpu/GrContext.h" #include "third_party/skia/include/gpu/gl/GrGLInterface.h" @@ -189,9 +190,13 @@ 107, 107, 107, 107, 21, 21, 21, 21, 107, 107, 107, 107, }; - media::CopyYPlane(cropped_y_plane, 16, 16, cropped_frame().get()); - media::CopyUPlane(cropped_u_plane, 8, 8, cropped_frame().get()); - media::CopyVPlane(cropped_v_plane, 8, 8, cropped_frame().get()); + libyuv::I420Copy(cropped_y_plane, 16, cropped_u_plane, 8, cropped_v_plane, 8, + cropped_frame()->data(VideoFrame::kYPlane), + cropped_frame()->stride(VideoFrame::kYPlane), + cropped_frame()->data(VideoFrame::kUPlane), + cropped_frame()->stride(VideoFrame::kUPlane), + cropped_frame()->data(VideoFrame::kVPlane), + cropped_frame()->stride(VideoFrame::kVPlane), 16, 16); } SkCanvasVideoRendererTest::~SkCanvasVideoRendererTest() {}
diff --git a/media/test/BUILD.gn b/media/test/BUILD.gn index 3ce4648..721c715dd 100644 --- a/media/test/BUILD.gn +++ b/media/test/BUILD.gn
@@ -102,8 +102,8 @@ "//media/mojo/services:renderer_service", "//mojo/application/public/cpp:test_support", "//testing/gtest", - "//ui/gfx/geometry", "//ui/gfx:test_support", + "//ui/gfx/geometry", # TODO(dalecurtis): Required since the gmock header is included in the # header for pipeline_integration_test_base.h. This should be moved
diff --git a/media/test/pipeline_integration_test.cc b/media/test/pipeline_integration_test.cc index b62b5cb8..b19b32c1 100644 --- a/media/test/pipeline_integration_test.cc +++ b/media/test/pipeline_integration_test.cc
@@ -645,14 +645,7 @@ protected: scoped_ptr<Renderer> CreateRenderer() override { - mojo::URLRequestPtr request(mojo::URLRequest::New()); - request->url = mojo::String::From("mojo:media"); - mojo::ServiceProvider* service_provider = - application_impl() - ->ConnectToApplication(request.Pass()) - ->GetServiceProvider(); - - mojo::ConnectToService(service_provider, &media_service_factory_); + application_impl()->ConnectToService("mojo:media", &media_service_factory_); interfaces::RendererPtr mojo_renderer; media_service_factory_->CreateRenderer(mojo::GetProxy(&mojo_renderer));
diff --git a/media/test/pipeline_integration_test_base.cc b/media/test/pipeline_integration_test_base.cc index 9676b50..eb51ca44 100644 --- a/media/test/pipeline_integration_test_base.cc +++ b/media/test/pipeline_integration_test_base.cc
@@ -235,8 +235,7 @@ #endif // !defined(MEDIA_DISABLE_LIBVPX) #if !defined(MEDIA_DISABLE_FFMPEG) - video_decoders.push_back( - new FFmpegVideoDecoder(message_loop_.task_runner())); + video_decoders.push_back(new FFmpegVideoDecoder()); #endif // Simulate a 60Hz rendering sink.
diff --git a/mojo/android/BUILD.gn b/mojo/android/BUILD.gn index d1dce6b..2619bdf 100644 --- a/mojo/android/BUILD.gn +++ b/mojo/android/BUILD.gn
@@ -7,9 +7,9 @@ group("android") { testonly = true deps = [ - ":system_java", ":mojo_javatests", ":mojo_test_apk", + ":system_java", ] } @@ -128,8 +128,8 @@ "//build/config/sanitizers:deps", "//mojo/message_pump", "//mojo/public/cpp/bindings/tests:mojo_public_bindings_test_utils", - "//mojo/public/cpp/test_support:test_utils", "//mojo/public/cpp/environment", + "//mojo/public/cpp/test_support:test_utils", "//third_party/mojo/src/mojo/edk/system", ] defines = [ "UNIT_TEST" ] @@ -138,12 +138,12 @@ android_apk("mojo_test_apk") { testonly = true deps = [ - ":mojo_javatests", ":mojo_java_unittests", + ":mojo_javatests", ":system_java", "//base:base_java", - "//mojo/public/java:bindings", "//mojo/public/interfaces/bindings/tests:test_interfaces", + "//mojo/public/java:bindings", ] native_libs = [ "libmojo_java_unittests.so" ] apk_name = "MojoTest"
diff --git a/mojo/application/public/cpp/BUILD.gn b/mojo/application/public/cpp/BUILD.gn index fb34910b..2ad946d 100644 --- a/mojo/application/public/cpp/BUILD.gn +++ b/mojo/application/public/cpp/BUILD.gn
@@ -5,8 +5,8 @@ # GYP version: mojo/mojo_base.gyp:mojo_application_base source_set("cpp") { public_deps = [ - ":sources", ":init_commandline", + ":sources", ] } @@ -48,6 +48,7 @@ "//base:i18n", "//mojo/application/public/interfaces", "//mojo/common", + "//mojo/converters/network", "//mojo/environment:chromium", "//mojo/message_pump", "//mojo/public/cpp/bindings",
diff --git a/mojo/application/public/cpp/application_impl.h b/mojo/application/public/cpp/application_impl.h index 90e79596..1958461 100644 --- a/mojo/application/public/cpp/application_impl.h +++ b/mojo/application/public/cpp/application_impl.h
@@ -7,6 +7,7 @@ #include <vector> +#include "base/macros.h" #include "base/memory/scoped_vector.h" #include "base/memory/weak_ptr.h" #include "mojo/application/public/cpp/app_lifetime_helper.h" @@ -57,6 +58,25 @@ // class ApplicationImpl : public Application { public: + class ConnectParams { + public: + explicit ConnectParams(const std::string& url); + explicit ConnectParams(URLRequestPtr request); + ~ConnectParams(); + + URLRequestPtr TakeRequest() { return request_.Pass(); } + CapabilityFilterPtr TakeFilter() { return filter_.Pass(); } + void set_filter(CapabilityFilterPtr filter) { + filter_ = filter.Pass(); + } + + private: + URLRequestPtr request_; + CapabilityFilterPtr filter_; + + DISALLOW_COPY_AND_ASSIGN(ConnectParams); + }; + class TestApi { public: explicit TestApi(ApplicationImpl* application) @@ -97,22 +117,22 @@ // or nullptr otherwise. Caller takes ownership. scoped_ptr<ApplicationConnection> ConnectToApplication( const std::string& url); - scoped_ptr<ApplicationConnection> ConnectToApplication(URLRequestPtr request); - scoped_ptr<ApplicationConnection> ConnectToApplicationWithCapabilityFilter( - URLRequestPtr request, - CapabilityFilterPtr filter); + scoped_ptr<ApplicationConnection> ConnectToApplication(ConnectParams* params); // Connect to application identified by |request->url| and connect to the // service implementation of the interface identified by |Interface|. template <typename Interface> - void ConnectToService(mojo::URLRequestPtr request, - InterfacePtr<Interface>* ptr) { - scoped_ptr<ApplicationConnection> connection = - ConnectToApplication(request.Pass()); + void ConnectToService(ConnectParams* params, InterfacePtr<Interface>* ptr) { + scoped_ptr<ApplicationConnection> connection = ConnectToApplication(params); if (!connection.get()) return; connection->ConnectToService(ptr); } + template <typename Interface> + void ConnectToService(const std::string& url, InterfacePtr<Interface>* ptr) { + ConnectParams params(url); + return ConnectToService(¶ms, ptr); + } // Block the calling thread until the Initialize() method is called by the // shell.
diff --git a/mojo/application/public/cpp/lib/application_impl.cc b/mojo/application/public/cpp/lib/application_impl.cc index 6d2fb46..3f98a15c 100644 --- a/mojo/application/public/cpp/lib/application_impl.cc +++ b/mojo/application/public/cpp/lib/application_impl.cc
@@ -10,6 +10,7 @@ #include "base/message_loop/message_loop.h" #include "mojo/application/public/cpp/application_delegate.h" #include "mojo/application/public/cpp/lib/service_registry.h" +#include "mojo/converters/network/network_type_converters.h" #include "mojo/public/cpp/bindings/interface_ptr.h" #include "mojo/public/cpp/environment/logging.h" @@ -25,6 +26,12 @@ } // namespace +ApplicationImpl::ConnectParams::ConnectParams(const std::string& url) + : request_(URLRequest::From(url)) {} +ApplicationImpl::ConnectParams::ConnectParams(URLRequestPtr request) + : request_(request.Pass()) {} +ApplicationImpl::ConnectParams::~ConnectParams() {} + ApplicationImpl::ApplicationImpl(ApplicationDelegate* delegate, InterfaceRequest<Application> request) : ApplicationImpl(delegate, request.Pass(), @@ -47,22 +54,16 @@ scoped_ptr<ApplicationConnection> ApplicationImpl::ConnectToApplication( const std::string& url) { - mojo::URLRequestPtr request(mojo::URLRequest::New()); - request->url = url; - return ConnectToApplication(request.Pass()); -} - -scoped_ptr<ApplicationConnection> ApplicationImpl::ConnectToApplication( - URLRequestPtr request) { - return ConnectToApplicationWithCapabilityFilter(request.Pass(), nullptr); + ConnectParams params(url); + return ConnectToApplication(¶ms); } scoped_ptr<ApplicationConnection> - ApplicationImpl::ConnectToApplicationWithCapabilityFilter( - URLRequestPtr request, - CapabilityFilterPtr filter) { + ApplicationImpl::ConnectToApplication(ConnectParams* params) { if (!shell_) return nullptr; + DCHECK(params); + URLRequestPtr request = params->TakeRequest(); ServiceProviderPtr local_services; InterfaceRequest<ServiceProvider> local_request = GetProxy(&local_services); ServiceProviderPtr remote_services; @@ -79,7 +80,8 @@ application_url, application_url, remote_services.Pass(), local_request.Pass(), allowed)); shell_->ConnectToApplication(request.Pass(), remote_services_proxy.Pass(), - local_services.Pass(), filter.Pass(), + local_services.Pass(), + params->TakeFilter().Pass(), registry->GetConnectToApplicationCallback()); if (!delegate_->ConfigureOutgoingConnection(registry.get())) return nullptr;
diff --git a/mojo/converters/surfaces/BUILD.gn b/mojo/converters/surfaces/BUILD.gn index 08752a0..c95fdba 100644 --- a/mojo/converters/surfaces/BUILD.gn +++ b/mojo/converters/surfaces/BUILD.gn
@@ -30,9 +30,9 @@ "//cc/surfaces:surface_id", "//components/mus/public/interfaces", "//gpu", - "//ui/gfx/geometry", "//mojo/environment:chromium", "//mojo/public/c/system:for_component", "//skia", + "//ui/gfx/geometry", ] }
diff --git a/mojo/converters/surfaces/tests/BUILD.gn b/mojo/converters/surfaces/tests/BUILD.gn index 89e9d26..95cad2b 100644 --- a/mojo/converters/surfaces/tests/BUILD.gn +++ b/mojo/converters/surfaces/tests/BUILD.gn
@@ -21,8 +21,8 @@ "//testing/gtest", "//third_party/mojo/src/mojo/edk/test:run_all_unittests", "//ui/gfx", - "//ui/gfx/geometry", "//ui/gfx:test_support", + "//ui/gfx/geometry", "//ui/mojo/geometry:interfaces", ]
diff --git a/mojo/converters/transform/BUILD.gn b/mojo/converters/transform/BUILD.gn index f97791d..d3e29a1 100644 --- a/mojo/converters/transform/BUILD.gn +++ b/mojo/converters/transform/BUILD.gn
@@ -9,9 +9,9 @@ "//ui/gfx", ] deps = [ - "//skia", "//mojo/environment:chromium", "//mojo/public/c/system:for_component", + "//skia", "//ui/mojo/geometry:interfaces", ]
diff --git a/mojo/edk/embedder/BUILD.gn b/mojo/edk/embedder/BUILD.gn index 4b29824..e307ed1 100644 --- a/mojo/edk/embedder/BUILD.gn +++ b/mojo/edk/embedder/BUILD.gn
@@ -135,10 +135,10 @@ # TODO(use_chrome_edk): temporary since the Mojo wrapper primitives are # declared in third party only for now. - "//third_party/mojo/src/mojo/edk/system", "//mojo/edk/system:test_utils", "//mojo/edk/test:test_support", "//testing/gtest", + "//third_party/mojo/src/mojo/edk/system", # TODO(use_chrome_edk): temporary since the Mojo wrapper primitives are # declared in third party only for now.
diff --git a/mojo/edk/js/BUILD.gn b/mojo/edk/js/BUILD.gn index 9acb481..50f62d9 100644 --- a/mojo/edk/js/BUILD.gn +++ b/mojo/edk/js/BUILD.gn
@@ -12,8 +12,8 @@ testonly = true deps = [ # TODO(use_chrome_edk): remove "2" - "test:js_unittests2", "test:js_integration_tests2", + "test:js_unittests2", ] }
diff --git a/mojo/edk/system/BUILD.gn b/mojo/edk/system/BUILD.gn index 1f04f65..f0c1e82 100644 --- a/mojo/edk/system/BUILD.gn +++ b/mojo/edk/system/BUILD.gn
@@ -79,11 +79,11 @@ all_dependent_configs = [ ":system_config" ] public_deps = [ + "../../../mojo/public/c/system", + "../../../mojo/public/cpp/system", "../embedder", "../embedder:delegates", "../embedder:platform", - "../../../mojo/public/c/system", - "../../../mojo/public/cpp/system", ] deps = [ @@ -103,8 +103,8 @@ testonly = true deps = [ # TODO(use_chrome_edk): remove "2" - ":mojo_system_unittests2", ":mojo_message_pipe_perftests2", + ":mojo_system_unittests2", ] } @@ -161,8 +161,8 @@ ":test_utils", # TODO(use_chrome_edk): remove "2" - "../embedder:embedder_unittests2", "../../../mojo/public/cpp/environment:standalone", + "../embedder:embedder_unittests2", "../test:test_support", "//base", "//base/test:test_support", @@ -187,9 +187,9 @@ deps = [ ":test_utils", - "../test:test_support", - "../test:run_all_perftests", "../../../mojo/public/cpp/environment:standalone", + "../test:run_all_perftests", + "../test:test_support", "//base", "//base/test:test_support", "//testing/gtest",
diff --git a/mojo/mojo_base.gyp b/mojo/mojo_base.gyp index 9c308c6..759bbca 100644 --- a/mojo/mojo_base.gyp +++ b/mojo/mojo_base.gyp
@@ -247,6 +247,7 @@ 'dependencies': [ 'mojo_application_bindings', 'mojo_message_pump_lib', + 'mojo_services.gyp:network_type_converters', ], }, {
diff --git a/mojo/mojo_services.gyp b/mojo/mojo_services.gyp index cb6c2fc9..652b7e6 100644 --- a/mojo/mojo_services.gyp +++ b/mojo/mojo_services.gyp
@@ -50,6 +50,18 @@ ], }, { + # GN version: //mojo/converters/network + 'target_name': 'network_type_converters', + 'type': 'static_library', + 'dependencies': [ + 'network_service_bindings_lib', + ], + 'sources': [ + 'converters/network/network_type_converters.cc', + 'converters/network/network_type_converters.h', + ], + }, + { 'target_name': 'updater_bindings_mojom', 'type': 'none', 'variables': {
diff --git a/mojo/package_manager/BUILD.gn b/mojo/package_manager/BUILD.gn index 3d69ae9..21b878a 100644 --- a/mojo/package_manager/BUILD.gn +++ b/mojo/package_manager/BUILD.gn
@@ -33,8 +33,8 @@ "//mojo/application/public/cpp", "//mojo/shell", "//mojo/shell:test_support", - "//third_party/mojo/src/mojo/edk/test:run_all_unittests", "//testing/gtest", + "//third_party/mojo/src/mojo/edk/test:run_all_unittests", "//url", ] }
diff --git a/mojo/public/BUILD.gn b/mojo/public/BUILD.gn index d7bb448..b917cf1c 100644 --- a/mojo/public/BUILD.gn +++ b/mojo/public/BUILD.gn
@@ -16,8 +16,8 @@ if (is_android) { deps += [ - "java:system", "java:bindings", + "java:system", ] } }
diff --git a/mojo/public/c/gpu/BUILD.gn b/mojo/public/c/gpu/BUILD.gn index 07e00d1..7f076902 100644 --- a/mojo/public/c/gpu/BUILD.gn +++ b/mojo/public/c/gpu/BUILD.gn
@@ -12,8 +12,8 @@ deps = [ ":MGL", - "../../platform/native:mgl_thunks", "../../platform/native:gles2", + "../../platform/native:mgl_thunks", ] }
diff --git a/mojo/public/cpp/bindings/BUILD.gn b/mojo/public/cpp/bindings/BUILD.gn index 2d4064b..60874fe 100644 --- a/mojo/public/cpp/bindings/BUILD.gn +++ b/mojo/public/cpp/bindings/BUILD.gn
@@ -30,6 +30,8 @@ "lib/filter_chain.h", "lib/fixed_buffer.cc", "lib/fixed_buffer.h", + "lib/interface_endpoint_client.cc", + "lib/interface_endpoint_client.h", "lib/interface_id.h", "lib/interface_ptr_internal.h", "lib/map_data_internal.h", @@ -42,6 +44,8 @@ "lib/message_header_validator.cc", "lib/message_header_validator.h", "lib/message_internal.h", + "lib/multiplex_router.cc", + "lib/multiplex_router.h", "lib/no_interface.cc", "lib/pipe_control_message_handler.cc", "lib/pipe_control_message_handler.h", @@ -50,6 +54,8 @@ "lib/pipe_control_message_proxy.h", "lib/router.cc", "lib/router.h", + "lib/scoped_interface_endpoint_handle.cc", + "lib/scoped_interface_endpoint_handle.h", "lib/string_serialization.cc", "lib/string_serialization.h", "lib/union_accessor.h",
diff --git a/mojo/public/cpp/bindings/lib/connector.cc b/mojo/public/cpp/bindings/lib/connector.cc index 5bd94eb..af45bfc 100644 --- a/mojo/public/cpp/bindings/lib/connector.cc +++ b/mojo/public/cpp/bindings/lib/connector.cc
@@ -4,14 +4,42 @@ #include "mojo/public/cpp/bindings/lib/connector.h" -#include "mojo/public/cpp/environment/logging.h" +#include "base/logging.h" +#include "base/macros.h" +#include "base/synchronization/lock.h" namespace mojo { namespace internal { +namespace { + +// Similar to base::AutoLock, except that it does nothing if |lock| passed into +// the constructor is null. +class MayAutoLock { + public: + explicit MayAutoLock(base::Lock* lock) : lock_(lock) { + if (lock_) + lock_->Acquire(); + } + + ~MayAutoLock() { + if (lock_) { + lock_->AssertAcquired(); + lock_->Release(); + } + } + + private: + base::Lock* lock_; + DISALLOW_COPY_AND_ASSIGN(MayAutoLock); +}; + +} // namespace + // ---------------------------------------------------------------------------- Connector::Connector(ScopedMessagePipeHandle message_pipe, + ConnectorConfig config, const MojoAsyncWaiter* waiter) : waiter_(waiter), message_pipe_(message_pipe.Pass()), @@ -21,13 +49,16 @@ drop_writes_(false), enforce_errors_from_incoming_receiver_(true), paused_(false), - destroyed_flag_(nullptr) { + destroyed_flag_(nullptr), + lock_(config == MULTI_THREADED_SEND ? new base::Lock : nullptr) { // Even though we don't have an incoming receiver, we still want to monitor // the message pipe to know if is closed or encounters an error. WaitToReadMore(); } Connector::~Connector() { + DCHECK(thread_checker_.CalledOnValidThread()); + if (destroyed_flag_) *destroyed_flag_ = true; @@ -35,20 +66,30 @@ } void Connector::CloseMessagePipe() { + DCHECK(thread_checker_.CalledOnValidThread()); + CancelWait(); + MayAutoLock locker(lock_.get()); Close(message_pipe_.Pass()); } ScopedMessagePipeHandle Connector::PassMessagePipe() { + DCHECK(thread_checker_.CalledOnValidThread()); + CancelWait(); + MayAutoLock locker(lock_.get()); return message_pipe_.Pass(); } void Connector::RaiseError() { + DCHECK(thread_checker_.CalledOnValidThread()); + HandleError(true, true); } bool Connector::WaitForIncomingMessage(MojoDeadline deadline) { + DCHECK(thread_checker_.CalledOnValidThread()); + if (error_) return false; @@ -69,6 +110,8 @@ } void Connector::PauseIncomingMethodCallProcessing() { + DCHECK(thread_checker_.CalledOnValidThread()); + if (paused_) return; @@ -77,6 +120,8 @@ } void Connector::ResumeIncomingMethodCallProcessing() { + DCHECK(thread_checker_.CalledOnValidThread()); + if (!paused_) return; @@ -85,11 +130,17 @@ } bool Connector::Accept(Message* message) { + DCHECK(lock_ || thread_checker_.CalledOnValidThread()); + + // It shouldn't hurt even if |error_| may be changed by a different thread at + // the same time. The outcome is that we may write into |message_pipe_| after + // encountering an error, which should be fine. if (error_) return false; - MOJO_CHECK(message_pipe_.is_valid()); - if (drop_writes_) + MayAutoLock locker(lock_.get()); + + if (!message_pipe_.is_valid() || drop_writes_) return true; MojoResult rv = @@ -124,10 +175,10 @@ // a data pipe handle in the middle of a two-phase read/write, // regardless of which thread that two-phase read/write is happening // on). - // TODO(vtl): I wonder if this should be a |MOJO_DCHECK()|. (But, until + // TODO(vtl): I wonder if this should be a |DCHECK()|. (But, until // crbug.com/389666, etc. are resolved, this will make tests fail quickly // rather than hanging.) - MOJO_CHECK(false) << "Race condition or other bug detected"; + CHECK(false) << "Race condition or other bug detected"; return false; default: // This particular write was rejected, presumably because of bad input. @@ -144,7 +195,9 @@ } void Connector::OnHandleReady(MojoResult result) { - MOJO_CHECK(async_wait_id_ != 0); + DCHECK(thread_checker_.CalledOnValidThread()); + + CHECK(async_wait_id_ != 0); async_wait_id_ = 0; if (result != MOJO_RESULT_OK) { HandleError(result != MOJO_RESULT_FAILED_PRECONDITION, false); @@ -155,7 +208,7 @@ } void Connector::WaitToReadMore() { - MOJO_CHECK(!async_wait_id_); + CHECK(!async_wait_id_); async_wait_id_ = waiter_->AsyncWait(message_pipe_.get().value(), MOJO_HANDLE_SIGNAL_READABLE, MOJO_DEADLINE_INDEFINITE, @@ -237,7 +290,9 @@ } if (force_pipe_reset) { - CloseMessagePipe(); + CancelWait(); + MayAutoLock locker(lock_.get()); + Close(message_pipe_.Pass()); MessagePipe dummy_pipe; message_pipe_ = dummy_pipe.handle0.Pass(); } else {
diff --git a/mojo/public/cpp/bindings/lib/connector.h b/mojo/public/cpp/bindings/lib/connector.h index 185a984..3978171 100644 --- a/mojo/public/cpp/bindings/lib/connector.h +++ b/mojo/public/cpp/bindings/lib/connector.h
@@ -5,15 +5,19 @@ #ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_CONNECTOR_H_ #define MOJO_PUBLIC_CPP_BINDINGS_LIB_CONNECTOR_H_ +#include "base/memory/scoped_ptr.h" +#include "base/threading/thread_checker.h" #include "mojo/public/c/environment/async_waiter.h" #include "mojo/public/cpp/bindings/callback.h" #include "mojo/public/cpp/bindings/message.h" #include "mojo/public/cpp/environment/environment.h" #include "mojo/public/cpp/system/core.h" -namespace mojo { -class ErrorHandler; +namespace base { +class Lock; +} +namespace mojo { namespace internal { // The Connector class is responsible for performing read/write operations on a @@ -21,13 +25,24 @@ // interface that it subclasses, and it forwards messages it reads through the // MessageReceiver interface assigned as its incoming receiver. // -// NOTE: MessagePipe I/O is non-blocking. -// +// NOTE: +// - MessagePipe I/O is non-blocking. +// - Sending messages can be configured to be thread safe (please see comments +// of the constructor). Other than that, the object should only be accessed +// on the creating thread. class Connector : public MessageReceiver { public: + enum ConnectorConfig { + // Connector::Accept() is only called from a single thread. + SINGLE_THREADED_SEND, + // Connector::Accept() is allowed to be called from multiple threads. + MULTI_THREADED_SEND + }; + // The Connector takes ownership of |message_pipe|. - explicit Connector( + Connector( ScopedMessagePipeHandle message_pipe, + ConnectorConfig config, const MojoAsyncWaiter* waiter = Environment::GetDefaultAsyncWaiter()); ~Connector() override; @@ -35,6 +50,7 @@ // Connector will read messages from the pipe regardless of whether or not an // incoming receiver has been set. void set_incoming_receiver(MessageReceiver* receiver) { + DCHECK(thread_checker_.CalledOnValidThread()); incoming_receiver_ = receiver; } @@ -42,18 +58,23 @@ // state, where no more messages will be processed. This method is used // during testing to prevent that from happening. void set_enforce_errors_from_incoming_receiver(bool enforce) { + DCHECK(thread_checker_.CalledOnValidThread()); enforce_errors_from_incoming_receiver_ = enforce; } // Sets the error handler to receive notifications when an error is // encountered while reading from the pipe or waiting to read from the pipe. void set_connection_error_handler(const Closure& error_handler) { + DCHECK(thread_checker_.CalledOnValidThread()); connection_error_handler_ = error_handler; } // Returns true if an error was encountered while reading from the pipe or // waiting to read from the pipe. - bool encountered_error() const { return error_; } + bool encountered_error() const { + DCHECK(thread_checker_.CalledOnValidThread()); + return error_; + } // Closes the pipe. The connector is put into a quiescent state. // @@ -78,7 +99,10 @@ void RaiseError(); // Is the connector bound to a MessagePipe handle? - bool is_valid() const { return message_pipe_.is_valid(); } + bool is_valid() const { + DCHECK(thread_checker_.CalledOnValidThread()); + return message_pipe_.is_valid(); + } // Waits for the next message on the pipe, blocking until one arrives, // |deadline| elapses, or an error happens. Returns |true| if a message has @@ -92,7 +116,10 @@ // MessageReceiver implementation: bool Accept(Message* message) override; - MessagePipeHandle handle() const { return message_pipe_.get(); } + MessagePipeHandle handle() const { + DCHECK(thread_checker_.CalledOnValidThread()); + return message_pipe_.get(); + } private: static void CallOnHandleReady(void* closure, MojoResult result); @@ -133,6 +160,12 @@ // of dispatching an incoming message. bool* destroyed_flag_; + // If sending messages is allowed from multiple threads, |lock_| is used to + // protect modifications to |message_pipe_| and |drop_writes_|. + scoped_ptr<base::Lock> lock_; + + base::ThreadChecker thread_checker_; + MOJO_DISALLOW_COPY_AND_ASSIGN(Connector); };
diff --git a/mojo/public/cpp/bindings/lib/interface_endpoint_client.cc b/mojo/public/cpp/bindings/lib/interface_endpoint_client.cc new file mode 100644 index 0000000..68d6035 --- /dev/null +++ b/mojo/public/cpp/bindings/lib/interface_endpoint_client.cc
@@ -0,0 +1,218 @@ +// Copyright 2015 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 "mojo/public/cpp/bindings/lib/interface_endpoint_client.h" + +#include "base/bind.h" +#include "base/message_loop/message_loop.h" +#include "base/stl_util.h" +#include "mojo/public/cpp/bindings/lib/multiplex_router.h" + +namespace mojo { +namespace internal { + +// ---------------------------------------------------------------------------- + +namespace { + +// When receiving an incoming message which expects a repsonse, +// InterfaceEndpointClient creates a ResponderThunk object and passes it to the +// incoming message receiver. When the receiver finishes processing the message, +// it can provide a response using this object. +class ResponderThunk : public MessageReceiverWithStatus { + public: + explicit ResponderThunk( + const base::WeakPtr<InterfaceEndpointClient>& endpoint_client) + : endpoint_client_(endpoint_client), accept_was_invoked_(false) {} + ~ResponderThunk() override { + if (!accept_was_invoked_) { + // The Mojo application handled a message that was expecting a response + // but did not send a response. + if (endpoint_client_) { + // We raise an error to signal the calling application that an error + // condition occurred. Without this the calling application would have + // no way of knowing it should stop waiting for a response. + // + // We raise the error asynchronously and only if |endpoint_client_| is + // still alive when the task is run. That way it won't break the case + // where the user abandons the interface endpoint client soon after + // he/she abandons the callback. + base::MessageLoop::current()->PostTask( + FROM_HERE, + base::Bind(&InterfaceEndpointClient::RaiseError, endpoint_client_)); + } + } + } + + // MessageReceiver implementation: + bool Accept(Message* message) override { + accept_was_invoked_ = true; + DCHECK(message->has_flag(kMessageIsResponse)); + + bool result = false; + + if (endpoint_client_) + result = endpoint_client_->Accept(message); + + return result; + } + + // MessageReceiverWithStatus implementation: + bool IsValid() override { + return endpoint_client_ && !endpoint_client_->encountered_error(); + } + + private: + base::WeakPtr<InterfaceEndpointClient> endpoint_client_; + bool accept_was_invoked_; + + DISALLOW_COPY_AND_ASSIGN(ResponderThunk); +}; + +} // namespace + +// ---------------------------------------------------------------------------- + +InterfaceEndpointClient::HandleIncomingMessageThunk::HandleIncomingMessageThunk( + InterfaceEndpointClient* owner) + : owner_(owner) {} + +InterfaceEndpointClient::HandleIncomingMessageThunk:: + ~HandleIncomingMessageThunk() {} + +bool InterfaceEndpointClient::HandleIncomingMessageThunk::Accept( + Message* message) { + return owner_->HandleValidatedMessage(message); +} + +// ---------------------------------------------------------------------------- + +InterfaceEndpointClient::InterfaceEndpointClient( + ScopedInterfaceEndpointHandle handle, + MessageReceiverWithResponderStatus* receiver, + scoped_ptr<MessageFilter> payload_validator) + : handle_(handle.Pass()), + incoming_receiver_(receiver), + payload_validator_(payload_validator.Pass()), + thunk_(this), + next_request_id_(1), + encountered_error_(false), + weak_ptr_factory_(this) { + DCHECK(handle_.is_valid()); + DCHECK(handle_.is_local()); + + // TODO(yzshen): the way to use validator (or message filter in general) + // directly is a little awkward. + payload_validator_->set_sink(&thunk_); + + handle_.router()->AttachEndpointClient(handle_, this); +} + +InterfaceEndpointClient::~InterfaceEndpointClient() { + DCHECK(thread_checker_.CalledOnValidThread()); + + STLDeleteValues(&responders_); + + handle_.router()->DetachEndpointClient(handle_); +} + +ScopedInterfaceEndpointHandle InterfaceEndpointClient::PassHandle() { + DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK(!has_pending_responders()); + + if (!handle_.is_valid()) + return ScopedInterfaceEndpointHandle(); + + handle_.router()->DetachEndpointClient(handle_); + + return handle_.Pass(); +} + +void InterfaceEndpointClient::RaiseError() { + DCHECK(thread_checker_.CalledOnValidThread()); + + handle_.router()->RaiseError(); +} + +bool InterfaceEndpointClient::Accept(Message* message) { + DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK(!message->has_flag(kMessageExpectsResponse)); + + if (encountered_error_) + return false; + + return handle_.router()->SendMessage(handle_, message); +} + +bool InterfaceEndpointClient::AcceptWithResponder(Message* message, + MessageReceiver* responder) { + DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK(message->has_flag(kMessageExpectsResponse)); + + if (encountered_error_) + return false; + + // Reserve 0 in case we want it to convey special meaning in the future. + uint64_t request_id = next_request_id_++; + if (request_id == 0) + request_id = next_request_id_++; + + message->set_request_id(request_id); + + if (!handle_.router()->SendMessage(handle_, message)) + return false; + + // We assume ownership of |responder|. + responders_[request_id] = responder; + return true; +} + +bool InterfaceEndpointClient::HandleIncomingMessage(Message* message) { + DCHECK(thread_checker_.CalledOnValidThread()); + + return payload_validator_->Accept(message); +} + +void InterfaceEndpointClient::NotifyError() { + DCHECK(thread_checker_.CalledOnValidThread()); + + if (encountered_error_) + return; + encountered_error_ = true; + error_handler_.Run(); +} + +bool InterfaceEndpointClient::HandleValidatedMessage(Message* message) { + DCHECK_EQ(handle_.id(), message->interface_id()); + + if (message->has_flag(kMessageExpectsResponse)) { + if (!incoming_receiver_) + return false; + + MessageReceiverWithStatus* responder = + new ResponderThunk(weak_ptr_factory_.GetWeakPtr()); + bool ok = incoming_receiver_->AcceptWithResponder(message, responder); + if (!ok) + delete responder; + return ok; + } else if (message->has_flag(kMessageIsResponse)) { + uint64_t request_id = message->request_id(); + ResponderMap::iterator it = responders_.find(request_id); + if (it == responders_.end()) + return false; + MessageReceiver* responder = it->second; + responders_.erase(it); + bool ok = responder->Accept(message); + delete responder; + return ok; + } else { + if (!incoming_receiver_) + return false; + + return incoming_receiver_->Accept(message); + } +} + +} // namespace internal +} // namespace mojo
diff --git a/mojo/public/cpp/bindings/lib/interface_endpoint_client.h b/mojo/public/cpp/bindings/lib/interface_endpoint_client.h new file mode 100644 index 0000000..b3f3f5a --- /dev/null +++ b/mojo/public/cpp/bindings/lib/interface_endpoint_client.h
@@ -0,0 +1,120 @@ +// Copyright 2015 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 MOJO_PUBLIC_CPP_BINDINGS_LIB_INTERFACE_ENDPOINT_CLIENT_H_ +#define MOJO_PUBLIC_CPP_BINDINGS_LIB_INTERFACE_ENDPOINT_CLIENT_H_ + +#include <map> + +#include "base/logging.h" +#include "base/macros.h" +#include "base/memory/scoped_ptr.h" +#include "base/memory/weak_ptr.h" +#include "base/threading/thread_checker.h" +#include "mojo/public/cpp/bindings/callback.h" +#include "mojo/public/cpp/bindings/lib/scoped_interface_endpoint_handle.h" +#include "mojo/public/cpp/bindings/message.h" +#include "mojo/public/cpp/bindings/message_filter.h" + +namespace mojo { +namespace internal { + +// InterfaceEndpointClient handles message sending and receiving of an interface +// endpoint, either the implementation side or the client side. +// It should only be accessed and destructed on the creating thread. +class InterfaceEndpointClient : public MessageReceiverWithResponder { + public: + // |receiver| is okay to be null. If it is not null, it must outlive this + // object. + InterfaceEndpointClient(ScopedInterfaceEndpointHandle handle, + MessageReceiverWithResponderStatus* receiver, + scoped_ptr<MessageFilter> payload_validator); + ~InterfaceEndpointClient() override; + + // Sets the error handler to receive notifications when an error is + // encountered. + void set_connection_error_handler(const Closure& error_handler) { + DCHECK(thread_checker_.CalledOnValidThread()); + error_handler_ = error_handler; + } + + // Returns true if an error was encountered. + bool encountered_error() const { + DCHECK(thread_checker_.CalledOnValidThread()); + return encountered_error_; + } + + // Returns true if this endpoint has any pending callbacks. + bool has_pending_responders() const { + DCHECK(thread_checker_.CalledOnValidThread()); + return !responders_.empty(); + } + + MultiplexRouter* router() const { return handle_.router(); } + + // After this call the object is in an invalid state and shouldn't be reused. + ScopedInterfaceEndpointHandle PassHandle(); + + // Raises an error on the underlying message pipe. It disconnects the pipe + // and notifies all interfaces running on this pipe. + void RaiseError(); + + // MessageReceiverWithResponder implementation: + bool Accept(Message* message) override; + bool AcceptWithResponder(Message* message, + MessageReceiver* responder) override; + + // The following methods are called by the router. They must be called + // outside of the router's lock. + + // NOTE: |message| must have passed message header validation. + bool HandleIncomingMessage(Message* message); + void NotifyError(); + + private: + using ResponderMap = std::map<uint64_t, MessageReceiver*>; + + // Used as the sink for |payload_validator_| and forwards messages to + // HandleValidatedMessage(). + class HandleIncomingMessageThunk : public MessageReceiver { + public: + explicit HandleIncomingMessageThunk(InterfaceEndpointClient* owner); + ~HandleIncomingMessageThunk() override; + + // MessageReceiver implementation: + bool Accept(Message* message) override; + + private: + InterfaceEndpointClient* const owner_; + + DISALLOW_COPY_AND_ASSIGN(HandleIncomingMessageThunk); + }; + + bool HandleValidatedMessage(Message* message); + + ScopedInterfaceEndpointHandle handle_; + + MessageReceiverWithResponderStatus* const incoming_receiver_; + scoped_ptr<MessageFilter> payload_validator_; + HandleIncomingMessageThunk thunk_; + + // Maps from the ID of a response to the MessageReceiver that handles the + // response. + ResponderMap responders_; + uint64_t next_request_id_; + + Closure error_handler_; + bool encountered_error_; + + base::ThreadChecker thread_checker_; + + base::WeakPtrFactory<InterfaceEndpointClient> weak_ptr_factory_; + + DISALLOW_COPY_AND_ASSIGN(InterfaceEndpointClient); +}; + +} // namespace internal +} // namespace mojo + +#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_INTERFACE_ENDPOINT_CLIENT_H_
diff --git a/mojo/public/cpp/bindings/lib/multiplex_router.cc b/mojo/public/cpp/bindings/lib/multiplex_router.cc new file mode 100644 index 0000000..a2b057be --- /dev/null +++ b/mojo/public/cpp/bindings/lib/multiplex_router.cc
@@ -0,0 +1,519 @@ +// Copyright 2015 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 "mojo/public/cpp/bindings/lib/multiplex_router.h" + +#include "base/bind.h" +#include "base/message_loop/message_loop.h" +#include "base/stl_util.h" +#include "mojo/public/cpp/bindings/lib/interface_endpoint_client.h" + +namespace mojo { +namespace internal { + +// InterfaceEndpoint stores the information of an interface endpoint registered +// with the router. Always accessed under the router's lock. +// No one other than the router's |endpoints_| and |tasks_| should hold refs to +// this object. +class MultiplexRouter::InterfaceEndpoint + : public base::RefCounted<InterfaceEndpoint> { + public: + InterfaceEndpoint(MultiplexRouter* router, InterfaceId id) + : router_lock_(&router->lock_), + id_(id), + closed_(false), + peer_closed_(false), + client_(nullptr) { + router_lock_->AssertAcquired(); + } + + InterfaceId id() const { return id_; } + + bool closed() const { return closed_; } + void set_closed() { + router_lock_->AssertAcquired(); + closed_ = true; + } + + bool peer_closed() const { return peer_closed_; } + void set_peer_closed() { + router_lock_->AssertAcquired(); + peer_closed_ = true; + } + + const scoped_refptr<base::SingleThreadTaskRunner> task_runner() const { + return task_runner_; + } + void set_task_runner( + scoped_refptr<base::SingleThreadTaskRunner> task_runner) { + router_lock_->AssertAcquired(); + task_runner_ = task_runner.Pass(); + } + + InterfaceEndpointClient* client() const { return client_; } + void set_client(InterfaceEndpointClient* client) { + router_lock_->AssertAcquired(); + client_ = client; + } + + private: + friend class base::RefCounted<InterfaceEndpoint>; + + ~InterfaceEndpoint() { + router_lock_->AssertAcquired(); + + DCHECK(!client_); + DCHECK(closed_); + DCHECK(peer_closed_); + } + + base::Lock* const router_lock_; + const InterfaceId id_; + + // Whether the endpoint has been closed. + bool closed_; + // Whether the peer endpoint has been closed. + bool peer_closed_; + + // The task runner on which |client_| can be accessed. + scoped_refptr<base::SingleThreadTaskRunner> task_runner_; + // Not owned. It is null if no client is attached to this endpoint. + InterfaceEndpointClient* client_; + + DISALLOW_COPY_AND_ASSIGN(InterfaceEndpoint); +}; + +struct MultiplexRouter::Task { + public: + // Doesn't take ownership of |message| but takes its contents. + static scoped_ptr<Task> CreateIncomingMessageTask(Message* message) { + Task* task = new Task(); + task->message.reset(new Message); + message->MoveTo(task->message.get()); + return make_scoped_ptr(task); + } + static scoped_ptr<Task> CreateNotifyErrorTask(InterfaceEndpoint* endpoint) { + Task* task = new Task(); + task->endpoint_to_notify = endpoint; + return make_scoped_ptr(task); + } + + ~Task() {} + + bool IsIncomingMessageTask() const { return !!message; } + bool IsNotifyErrorTask() const { return !!endpoint_to_notify; } + + scoped_ptr<Message> message; + scoped_refptr<InterfaceEndpoint> endpoint_to_notify; + + private: + Task() {} +}; + +MultiplexRouter::MultiplexRouter(bool set_interface_id_namesapce_bit, + ScopedMessagePipeHandle message_pipe, + const MojoAsyncWaiter* waiter) + : RefCountedDeleteOnMessageLoop(base::MessageLoop::current() + ->task_runner()), + set_interface_id_namespace_bit_(set_interface_id_namesapce_bit), + header_validator_(this), + connector_(message_pipe.Pass(), Connector::MULTI_THREADED_SEND, waiter), + encountered_error_(false), + control_message_handler_(this), + control_message_proxy_(&connector_), + next_interface_id_value_(1), + testing_mode_(false) { + connector_.set_incoming_receiver(&header_validator_); + connector_.set_connection_error_handler( + [this]() { OnPipeConnectionError(); }); +} + +MultiplexRouter::~MultiplexRouter() { + base::AutoLock locker(lock_); + + tasks_.clear(); + + for (auto iter = endpoints_.begin(); iter != endpoints_.end();) { + InterfaceEndpoint* endpoint = iter->second.get(); + // Increment the iterator before calling UpdateEndpointStateMayRemove() + // because it may remove the corresponding value from the map. + ++iter; + + DCHECK(endpoint->closed()); + UpdateEndpointStateMayRemove(endpoint, PEER_ENDPOINT_CLOSED); + } + + DCHECK(endpoints_.empty()); +} + +void MultiplexRouter::CreateEndpointHandlePair( + ScopedInterfaceEndpointHandle* local_endpoint, + ScopedInterfaceEndpointHandle* remote_endpoint) { + base::AutoLock locker(lock_); + uint32_t id = 0; + do { + if (next_interface_id_value_ >= kInterfaceIdNamespaceMask) + next_interface_id_value_ = 1; + id = next_interface_id_value_++; + if (set_interface_id_namespace_bit_) + id |= kInterfaceIdNamespaceMask; + } while (ContainsKey(endpoints_, id)); + + InterfaceEndpoint* endpoint = new InterfaceEndpoint(this, id); + endpoints_[id] = endpoint; + if (encountered_error_) + UpdateEndpointStateMayRemove(endpoint, PEER_ENDPOINT_CLOSED); + + *local_endpoint = ScopedInterfaceEndpointHandle(id, true, this); + *remote_endpoint = ScopedInterfaceEndpointHandle(id, false, this); +} + +ScopedInterfaceEndpointHandle MultiplexRouter::CreateLocalEndpointHandle( + InterfaceId id) { + if (!IsValidInterfaceId(id)) + return ScopedInterfaceEndpointHandle(); + + base::AutoLock locker(lock_); + if (ContainsKey(endpoints_, id)) { + // If the endpoint already exist, it is because we have received a + // notification that the peer endpoint has closed. + InterfaceEndpoint* endpoint = endpoints_[id].get(); + CHECK(!endpoint->closed()); + CHECK(endpoint->peer_closed()); + } else { + InterfaceEndpoint* endpoint = new InterfaceEndpoint(this, id); + endpoints_[id] = endpoint; + if (encountered_error_) + UpdateEndpointStateMayRemove(endpoint, PEER_ENDPOINT_CLOSED); + } + return ScopedInterfaceEndpointHandle(id, true, this); +} + +void MultiplexRouter::CloseEndpointHandle(InterfaceId id, bool is_local) { + if (!IsValidInterfaceId(id)) + return; + + base::AutoLock locker(lock_); + + if (!is_local) { + DCHECK(ContainsKey(endpoints_, id)); + DCHECK(!IsMasterInterfaceId(id)); + + // We will receive a NotifyPeerEndpointClosed message from the other side. + control_message_proxy_.NotifyEndpointClosedBeforeSent(id); + + return; + } + + DCHECK(ContainsKey(endpoints_, id)); + InterfaceEndpoint* endpoint = endpoints_[id].get(); + DCHECK(!endpoint->client()); + DCHECK(!endpoint->closed()); + UpdateEndpointStateMayRemove(endpoint, ENDPOINT_CLOSED); + + if (!IsMasterInterfaceId(id)) + control_message_proxy_.NotifyPeerEndpointClosed(id); + + ProcessTasks(true); +} + +void MultiplexRouter::AttachEndpointClient( + const ScopedInterfaceEndpointHandle& handle, + InterfaceEndpointClient* client) { + const InterfaceId id = handle.id(); + + DCHECK(IsValidInterfaceId(id)); + DCHECK(client); + + base::AutoLock locker(lock_); + DCHECK(ContainsKey(endpoints_, id)); + + InterfaceEndpoint* endpoint = endpoints_[id].get(); + DCHECK(!endpoint->client()); + DCHECK(!endpoint->closed()); + + endpoint->set_task_runner(base::MessageLoop::current()->task_runner()); + endpoint->set_client(client); + + if (endpoint->peer_closed()) + tasks_.push_back(Task::CreateNotifyErrorTask(endpoint)); + ProcessTasks(true); +} + +void MultiplexRouter::DetachEndpointClient( + const ScopedInterfaceEndpointHandle& handle) { + const InterfaceId id = handle.id(); + + DCHECK(IsValidInterfaceId(id)); + + base::AutoLock locker(lock_); + DCHECK(ContainsKey(endpoints_, id)); + + InterfaceEndpoint* endpoint = endpoints_[id].get(); + DCHECK(endpoint->client()); + DCHECK(endpoint->task_runner()->BelongsToCurrentThread()); + DCHECK(!endpoint->closed()); + + endpoint->set_task_runner(nullptr); + endpoint->set_client(nullptr); +} + +bool MultiplexRouter::SendMessage(const ScopedInterfaceEndpointHandle& handle, + Message* message) { + const InterfaceId id = handle.id(); + + base::AutoLock locker(lock_); + if (!ContainsKey(endpoints_, id)) + return false; + + InterfaceEndpoint* endpoint = endpoints_[id].get(); + if (endpoint->peer_closed()) + return false; + + message->set_interface_id(id); + return connector_.Accept(message); +} + +void MultiplexRouter::RaiseError() { + if (task_runner_->BelongsToCurrentThread()) { + connector_.RaiseError(); + } else { + task_runner_->PostTask(FROM_HERE, + base::Bind(&MultiplexRouter::RaiseError, this)); + } +} + +ScopedMessagePipeHandle MultiplexRouter::PassMessagePipe() { + DCHECK(thread_checker_.CalledOnValidThread()); + { + base::AutoLock locker(lock_); + DCHECK(endpoints_.empty() || (endpoints_.size() == 1 && + ContainsKey(endpoints_, kMasterInterfaceId))); + } + return connector_.PassMessagePipe(); +} + +void MultiplexRouter::EnableTestingMode() { + DCHECK(thread_checker_.CalledOnValidThread()); + base::AutoLock locker(lock_); + + testing_mode_ = true; + connector_.set_enforce_errors_from_incoming_receiver(false); +} + +bool MultiplexRouter::Accept(Message* message) { + DCHECK(thread_checker_.CalledOnValidThread()); + + scoped_refptr<MultiplexRouter> protector(this); + base::AutoLock locker(lock_); + tasks_.push_back(Task::CreateIncomingMessageTask(message)); + ProcessTasks(false); + + // Always return true. If we see errors during message processing, we will + // explicitly call Connector::RaiseError() to disconnect the message pipe. + return true; +} + +bool MultiplexRouter::OnPeerAssociatedEndpointClosed(InterfaceId id) { + lock_.AssertAcquired(); + + if (IsMasterInterfaceId(id)) + return false; + + if (!ContainsKey(endpoints_, id)) + endpoints_[id] = new InterfaceEndpoint(this, id); + + InterfaceEndpoint* endpoint = endpoints_[id].get(); + DCHECK(!endpoint->peer_closed()); + + if (endpoint->client()) + tasks_.push_back(Task::CreateNotifyErrorTask(endpoint)); + UpdateEndpointStateMayRemove(endpoint, PEER_ENDPOINT_CLOSED); + + // No need to trigger a ProcessTasks() because it is already on the stack. + + return true; +} + +bool MultiplexRouter::OnAssociatedEndpointClosedBeforeSent(InterfaceId id) { + lock_.AssertAcquired(); + + if (IsMasterInterfaceId(id)) + return false; + + if (!ContainsKey(endpoints_, id)) + endpoints_[id] = new InterfaceEndpoint(this, id); + + InterfaceEndpoint* endpoint = endpoints_[id].get(); + DCHECK(!endpoint->closed()); + UpdateEndpointStateMayRemove(endpoint, ENDPOINT_CLOSED); + + control_message_proxy_.NotifyPeerEndpointClosed(id); + + return true; +} + +void MultiplexRouter::OnPipeConnectionError() { + DCHECK(thread_checker_.CalledOnValidThread()); + + scoped_refptr<MultiplexRouter> protector(this); + base::AutoLock locker(lock_); + + encountered_error_ = true; + + for (auto iter = endpoints_.begin(); iter != endpoints_.end();) { + InterfaceEndpoint* endpoint = iter->second.get(); + // Increment the iterator before calling UpdateEndpointStateMayRemove() + // because it may remove the corresponding value from the map. + ++iter; + + if (endpoint->client()) + tasks_.push_back(Task::CreateNotifyErrorTask(endpoint)); + + UpdateEndpointStateMayRemove(endpoint, PEER_ENDPOINT_CLOSED); + } + + ProcessTasks(false); +} + +void MultiplexRouter::ProcessTasks(bool force_async) { + lock_.AssertAcquired(); + + while (!tasks_.empty()) { + scoped_ptr<Task> task(tasks_.front().Pass()); + tasks_.pop_front(); + + bool processed = task->IsNotifyErrorTask() + ? ProcessNotifyErrorTask(task.get(), &force_async) + : ProcessIncomingMessageTask(task.get(), &force_async); + + if (!processed) { + tasks_.push_front(task.Pass()); + break; + } + } +} + +bool MultiplexRouter::ProcessNotifyErrorTask(Task* task, bool* force_async) { + lock_.AssertAcquired(); + InterfaceEndpoint* endpoint = task->endpoint_to_notify.get(); + if (!endpoint->client()) + return true; + + if (!endpoint->task_runner()->BelongsToCurrentThread() || *force_async) { + endpoint->task_runner()->PostTask( + FROM_HERE, base::Bind(&MultiplexRouter::LockAndCallProcessTasks, this)); + return false; + } + + *force_async = true; + InterfaceEndpointClient* client = endpoint->client(); + { + // We must unlock before calling into |client| because it may call this + // object within NotifyError(). Holding the lock will lead to deadlock. + // + // It is safe to call into |client| without the lock. Because |client| is + // always accessed on the same thread, including DetachEndpointClient(). + base::AutoUnlock unlocker(lock_); + client->NotifyError(); + } + return true; +} + +bool MultiplexRouter::ProcessIncomingMessageTask(Task* task, + bool* force_async) { + lock_.AssertAcquired(); + Message* message = task->message.get(); + + if (PipeControlMessageHandler::IsPipeControlMessage(message)) { + if (!control_message_handler_.Accept(message)) + RaiseErrorInNonTestingMode(); + return true; + } + + InterfaceId id = message->interface_id(); + DCHECK(IsValidInterfaceId(id)); + + if (!ContainsKey(endpoints_, id)) { + DCHECK(!IsMasterInterfaceId(id)); + + // Currently, it is legitimate to receive messages for an endpoint + // that is not registered. For example, the endpoint is transferred in + // a message that is discarded. Once we add support to specify all + // enclosing endpoints in message header, we should be able to remove + // this. + InterfaceEndpoint* endpoint = new InterfaceEndpoint(this, id); + endpoints_[id] = endpoint; + UpdateEndpointStateMayRemove(endpoint, ENDPOINT_CLOSED); + + control_message_proxy_.NotifyPeerEndpointClosed(id); + return true; + } + + InterfaceEndpoint* endpoint = endpoints_[id].get(); + if (endpoint->closed()) + return true; + + if (!endpoint->client()) { + // We need to wait until a client is attached in order to dispatch further + // messages. + return false; + } + + if (!endpoint->task_runner()->BelongsToCurrentThread() || *force_async) { + endpoint->task_runner()->PostTask( + FROM_HERE, base::Bind(&MultiplexRouter::LockAndCallProcessTasks, this)); + return false; + } + + *force_async = true; + InterfaceEndpointClient* client = endpoint->client(); + scoped_ptr<Message> owned_message = task->message.Pass(); + bool result = false; + { + // We must unlock before calling into |client| because it may call this + // object within HandleIncomingMessage(). Holding the lock will lead to + // deadlock. + // + // It is safe to call into |client| without the lock. Because |client| is + // always accessed on the same thread, including DetachEndpointClient(). + base::AutoUnlock unlocker(lock_); + result = client->HandleIncomingMessage(owned_message.get()); + } + if (!result) + RaiseErrorInNonTestingMode(); + + return true; +} + +void MultiplexRouter::LockAndCallProcessTasks() { + // There is no need to hold a ref to this class in this case because this is + // always called using base::Bind(), which holds a ref. + base::AutoLock locker(lock_); + ProcessTasks(false); +} + +void MultiplexRouter::UpdateEndpointStateMayRemove( + InterfaceEndpoint* endpoint, + EndpointStateUpdateType type) { + switch (type) { + case ENDPOINT_CLOSED: + endpoint->set_closed(); + break; + case PEER_ENDPOINT_CLOSED: + endpoint->set_peer_closed(); + break; + } + if (endpoint->closed() && endpoint->peer_closed()) + endpoints_.erase(endpoint->id()); +} + +void MultiplexRouter::RaiseErrorInNonTestingMode() { + lock_.AssertAcquired(); + if (!testing_mode_) + RaiseError(); +} + +} // namespace internal +} // namespace mojo
diff --git a/mojo/public/cpp/bindings/lib/multiplex_router.h b/mojo/public/cpp/bindings/lib/multiplex_router.h new file mode 100644 index 0000000..d9e7323 --- /dev/null +++ b/mojo/public/cpp/bindings/lib/multiplex_router.h
@@ -0,0 +1,207 @@ +// Copyright 2015 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 MOJO_PUBLIC_CPP_BINDINGS_LIB_MULTIPLEX_ROUTER_H_ +#define MOJO_PUBLIC_CPP_BINDINGS_LIB_MULTIPLEX_ROUTER_H_ + +#include <deque> +#include <map> + +#include "base/logging.h" +#include "base/macros.h" +#include "base/memory/ref_counted.h" +#include "base/memory/ref_counted_delete_on_message_loop.h" +#include "base/memory/scoped_ptr.h" +#include "base/memory/weak_ptr.h" +#include "base/synchronization/lock.h" +#include "base/threading/thread_checker.h" +#include "mojo/public/cpp/bindings/callback.h" +#include "mojo/public/cpp/bindings/lib/connector.h" +#include "mojo/public/cpp/bindings/lib/interface_id.h" +#include "mojo/public/cpp/bindings/lib/message_header_validator.h" +#include "mojo/public/cpp/bindings/lib/pipe_control_message_handler.h" +#include "mojo/public/cpp/bindings/lib/pipe_control_message_handler_delegate.h" +#include "mojo/public/cpp/bindings/lib/pipe_control_message_proxy.h" +#include "mojo/public/cpp/bindings/lib/scoped_interface_endpoint_handle.h" +#include "mojo/public/cpp/environment/environment.h" + +namespace mojo { +namespace internal { + +class InterfaceEndpointClient; + +// MultiplexRouter supports routing messages for multiple interfaces over a +// single message pipe. +// +// It is created on the thread where the master interface of the message pipe +// lives. Although it is ref-counted, it is guarateed to be destructed on the +// same thread. +// Some public methods are only allowed to be called on the creating thread; +// while the others are safe to call from any threads. Please see the method +// comments for more details. +class MultiplexRouter + : public MessageReceiver, + public base::RefCountedDeleteOnMessageLoop<MultiplexRouter>, + public PipeControlMessageHandlerDelegate { + public: + // If |set_interface_id_namespace_bit| is true, the interface IDs generated by + // this router will have the highest bit set. + MultiplexRouter( + bool set_interface_id_namespace_bit, + ScopedMessagePipeHandle message_pipe, + const MojoAsyncWaiter* waiter = Environment::GetDefaultAsyncWaiter()); + + // --------------------------------------------------------------------------- + // The following public methods are safe to call from any threads. + + // Creates a pair of interface endpoint handles. The method generates a new + // interface ID and assigns it to the two handles. |local_endpoint| is used + // locally; while |remote_endpoint| is sent over the message pipe. + void CreateEndpointHandlePair(ScopedInterfaceEndpointHandle* local_endpoint, + ScopedInterfaceEndpointHandle* remote_endpoint); + + // Creates an interface endpoint handle from a given interface ID. The handle + // is used locally. + // Typically, this method is used to (1) create an endpoint handle for the + // master interface; or (2) create an endpoint handle on receiving an + // interface ID from the message pipe. + ScopedInterfaceEndpointHandle CreateLocalEndpointHandle(InterfaceId id); + + // Closes an interface endpoint handle. + void CloseEndpointHandle(InterfaceId id, bool is_local); + + // Attaches an client to the specified endpoint to send and receive messages. + void AttachEndpointClient(const ScopedInterfaceEndpointHandle& handle, + InterfaceEndpointClient* endpoint_client); + // Detaches the client attached to the specified endpoint. It should be called + // on the same thread as the corresponding AttachEndpointClient() call. + void DetachEndpointClient(const ScopedInterfaceEndpointHandle& handle); + + bool SendMessage(const ScopedInterfaceEndpointHandle& handle, + Message* message); + + // Raises an error on the underlying message pipe. It disconnects the pipe + // and notifies all interfaces running on this pipe. + void RaiseError(); + + // --------------------------------------------------------------------------- + // The following public methods are called on the creating thread. + + // Please note that this method shouldn't be called unless it results from an + // explicit request of the user of bindings (e.g., the user sets an + // InterfacePtr to null or closes a Binding). + void CloseMessagePipe() { + DCHECK(thread_checker_.CalledOnValidThread()); + connector_.CloseMessagePipe(); + } + + // Extracts the underlying message pipe. + // + // TODO(yzshen): For now, users need to make sure there is no one holding on + // to associated interface endpoint handles at both sides of the message pipe + // in order to call this method. We need a way to forcefully invalidate + // associated interface endpoint handles. + ScopedMessagePipeHandle PassMessagePipe(); + + // Blocks the current thread until the first incoming message, or |deadline|. + bool WaitForIncomingMessage(MojoDeadline deadline) { + DCHECK(thread_checker_.CalledOnValidThread()); + return connector_.WaitForIncomingMessage(deadline); + } + + // See Binding for details of pause/resume. + void PauseIncomingMethodCallProcessing() { + DCHECK(thread_checker_.CalledOnValidThread()); + connector_.PauseIncomingMethodCallProcessing(); + } + void ResumeIncomingMethodCallProcessing() { + DCHECK(thread_checker_.CalledOnValidThread()); + connector_.ResumeIncomingMethodCallProcessing(); + } + + // Sets this object to testing mode. + // In testing mode, the object doesn't disconnect the underlying message pipe + // when it receives unexpected or invalid messages. + void EnableTestingMode(); + + // Is the router bound to a message pipe handle? + bool is_valid() const { + DCHECK(thread_checker_.CalledOnValidThread()); + return connector_.is_valid(); + } + + private: + friend class base::RefCountedDeleteOnMessageLoop<MultiplexRouter>; + friend class base::DeleteHelper<MultiplexRouter>; + + class InterfaceEndpoint; + struct Task; + + ~MultiplexRouter() override; + + // MessageReceiver implementation: + bool Accept(Message* message) override; + + // PipeControlMessageHandlerDelegate implementation: + bool OnPeerAssociatedEndpointClosed(InterfaceId id) override; + bool OnAssociatedEndpointClosedBeforeSent(InterfaceId id) override; + + void OnPipeConnectionError(); + + // Processes enqueued tasks (incoming messages and error notifications). + // If |force_async| is true, it guarantees not to call any + // InterfaceEndpointClient methods directly. + // + // Note: Because calling into InterfaceEndpointClient may lead to destruction + // of this object, if |force_async| is set to false, the caller needs to hold + // on to a ref outside of |lock_| before calling this method. + void ProcessTasks(bool force_async); + + // Returns true to indicate that |task| has been processed. Otherwise the task + // will be added back to the front of the queue. + // |*force_async| may be set to true to force subsequent tasks being processed + // in an asynchronous manner. + bool ProcessNotifyErrorTask(Task* task, bool* force_async); + bool ProcessIncomingMessageTask(Task* task, bool* force_async); + + void LockAndCallProcessTasks(); + + // Updates the state of |endpoint|. If both the endpoint and its peer have + // been closed, removes it from |endpoints_|. + // NOTE: The method may invalidate |endpoint|. + enum EndpointStateUpdateType { ENDPOINT_CLOSED, PEER_ENDPOINT_CLOSED }; + void UpdateEndpointStateMayRemove(InterfaceEndpoint* endpoint, + EndpointStateUpdateType type); + + void RaiseErrorInNonTestingMode(); + + // Whether to set the namespace bit when generating interface IDs. Please see + // comments of kInterfaceIdNamespaceMask. + const bool set_interface_id_namespace_bit_; + + MessageHeaderValidator header_validator_; + Connector connector_; + bool encountered_error_; + + base::ThreadChecker thread_checker_; + + // Protects the following members. + mutable base::Lock lock_; + PipeControlMessageHandler control_message_handler_; + PipeControlMessageProxy control_message_proxy_; + + std::map<InterfaceId, scoped_refptr<InterfaceEndpoint>> endpoints_; + uint32_t next_interface_id_value_; + + std::deque<scoped_ptr<Task>> tasks_; + + bool testing_mode_; + + DISALLOW_COPY_AND_ASSIGN(MultiplexRouter); +}; + +} // namespace internal +} // namespace mojo + +#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_MULTIPLEX_ROUTER_H_
diff --git a/mojo/public/cpp/bindings/lib/router.cc b/mojo/public/cpp/bindings/lib/router.cc index fff72b4..ee599d6 100644 --- a/mojo/public/cpp/bindings/lib/router.cc +++ b/mojo/public/cpp/bindings/lib/router.cc
@@ -11,6 +11,8 @@ // ---------------------------------------------------------------------------- +namespace { + class ResponderThunk : public MessageReceiverWithStatus { public: explicit ResponderThunk(const SharedData<Router*>& router) @@ -54,6 +56,8 @@ bool accept_was_invoked_; }; +} // namespace + // ---------------------------------------------------------------------------- Router::HandleIncomingMessageThunk::HandleIncomingMessageThunk(Router* router) @@ -74,7 +78,7 @@ const MojoAsyncWaiter* waiter) : thunk_(this), filters_(filters.Pass()), - connector_(message_pipe.Pass(), waiter), + connector_(message_pipe.Pass(), Connector::SINGLE_THREADED_SEND, waiter), weak_self_(this), incoming_receiver_(nullptr), next_request_id_(0),
diff --git a/mojo/public/cpp/bindings/lib/scoped_interface_endpoint_handle.cc b/mojo/public/cpp/bindings/lib/scoped_interface_endpoint_handle.cc new file mode 100644 index 0000000..4a2a47b --- /dev/null +++ b/mojo/public/cpp/bindings/lib/scoped_interface_endpoint_handle.cc
@@ -0,0 +1,75 @@ +// Copyright 2015 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 "mojo/public/cpp/bindings/lib/scoped_interface_endpoint_handle.h" + +#include "base/logging.h" +#include "mojo/public/cpp/bindings/lib/multiplex_router.h" + +namespace mojo { +namespace internal { + +ScopedInterfaceEndpointHandle::ScopedInterfaceEndpointHandle() + : ScopedInterfaceEndpointHandle(kInvalidInterfaceId, true, nullptr) {} + +ScopedInterfaceEndpointHandle::ScopedInterfaceEndpointHandle( + InterfaceId id, + bool is_local, + scoped_refptr<MultiplexRouter> router) + : id_(id), is_local_(is_local), router_(router.Pass()) { + DCHECK(!IsValidInterfaceId(id) || router_); +} + +ScopedInterfaceEndpointHandle::ScopedInterfaceEndpointHandle( + ScopedInterfaceEndpointHandle&& other) + : id_(other.id_), is_local_(other.is_local_) { + router_.swap(other.router_); + other.id_ = kInvalidInterfaceId; +} + +ScopedInterfaceEndpointHandle::~ScopedInterfaceEndpointHandle() { + reset(); +} + +ScopedInterfaceEndpointHandle& ScopedInterfaceEndpointHandle::operator=( + ScopedInterfaceEndpointHandle&& other) { + reset(); + + id_ = other.id_; + is_local_ = other.is_local_; + router_.swap(other.router_); + + other.id_ = kInvalidInterfaceId; + + return *this; +} + +void ScopedInterfaceEndpointHandle::reset() { + if (!IsValidInterfaceId(id_)) + return; + + router_->CloseEndpointHandle(id_, is_local_); + + id_ = kInvalidInterfaceId; + router_ = nullptr; +} + +void ScopedInterfaceEndpointHandle::swap(ScopedInterfaceEndpointHandle& other) { + using std::swap; + swap(other.id_, id_); + swap(other.is_local_, is_local_); + swap(other.router_, router_); +} + +InterfaceId ScopedInterfaceEndpointHandle::release() { + InterfaceId result = id_; + + id_ = kInvalidInterfaceId; + router_ = nullptr; + + return result; +} + +} // namespace internal +} // namespace mojo
diff --git a/mojo/public/cpp/bindings/lib/scoped_interface_endpoint_handle.h b/mojo/public/cpp/bindings/lib/scoped_interface_endpoint_handle.h new file mode 100644 index 0000000..09ee7ca7 --- /dev/null +++ b/mojo/public/cpp/bindings/lib/scoped_interface_endpoint_handle.h
@@ -0,0 +1,63 @@ +// Copyright 2015 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 MOJO_PUBLIC_CPP_BINDINGS_LIB_SCOPED_INTERFACE_ENDPOINT_HANDLE_H_ +#define MOJO_PUBLIC_CPP_BINDINGS_LIB_SCOPED_INTERFACE_ENDPOINT_HANDLE_H_ + +#include "base/macros.h" +#include "base/memory/ref_counted.h" +#include "mojo/public/cpp/bindings/lib/interface_id.h" + +namespace mojo { +namespace internal { + +class MultiplexRouter; + +// ScopedInterfaceEndpointHandle refers to one end of an interface, either the +// implementation side or the client side. +class ScopedInterfaceEndpointHandle { + MOVE_ONLY_TYPE_WITH_MOVE_CONSTRUCTOR_FOR_CPP_03( + ScopedInterfaceEndpointHandle); + + public: + // Creates an invalid endpoint handle. + ScopedInterfaceEndpointHandle(); + + // This is supposed to be used by MultiplexRouter only. + // |id| is the corresponding interface ID. + // If |is_local| is false, this handle is meant to be passed over |router| to + // the remote side. + ScopedInterfaceEndpointHandle(InterfaceId id, + bool is_local, + scoped_refptr<MultiplexRouter> router); + + ScopedInterfaceEndpointHandle(ScopedInterfaceEndpointHandle&& other); + + ~ScopedInterfaceEndpointHandle(); + + ScopedInterfaceEndpointHandle& operator=( + ScopedInterfaceEndpointHandle&& other); + + bool is_valid() const { return IsValidInterfaceId(id_); } + + InterfaceId id() const { return id_; } + bool is_local() const { return is_local_; } + MultiplexRouter* router() const { return router_.get(); } + + void reset(); + void swap(ScopedInterfaceEndpointHandle& other); + + // Releases the handle without closing it. + InterfaceId release(); + + private: + InterfaceId id_; + bool is_local_; + scoped_refptr<MultiplexRouter> router_; +}; + +} // namespace internal +} // namespace mojo + +#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_SCOPED_INTERFACE_ENDPOINT_HANDLE_H_
diff --git a/mojo/public/cpp/bindings/tests/BUILD.gn b/mojo/public/cpp/bindings/tests/BUILD.gn index 30b631ba..5ec5d8d 100644 --- a/mojo/public/cpp/bindings/tests/BUILD.gn +++ b/mojo/public/cpp/bindings/tests/BUILD.gn
@@ -23,7 +23,10 @@ "map_unittest.cc", "message_queue.cc", "message_queue.h", + "multiplex_router_unittest.cc", "request_response_unittest.cc", + "router_test_util.cc", + "router_test_util.h", "router_unittest.cc", "sample_service_unittest.cc", "serialization_warning_unittest.cc",
diff --git a/mojo/public/cpp/bindings/tests/connector_unittest.cc b/mojo/public/cpp/bindings/tests/connector_unittest.cc index febc72e..31125e85 100644 --- a/mojo/public/cpp/bindings/tests/connector_unittest.cc +++ b/mojo/public/cpp/bindings/tests/connector_unittest.cc
@@ -100,8 +100,10 @@ }; TEST_F(ConnectorTest, Basic) { - internal::Connector connector0(handle0_.Pass()); - internal::Connector connector1(handle1_.Pass()); + internal::Connector connector0(handle0_.Pass(), + internal::Connector::SINGLE_THREADED_SEND); + internal::Connector connector1(handle1_.Pass(), + internal::Connector::SINGLE_THREADED_SEND); const char kText[] = "hello world"; @@ -126,8 +128,10 @@ } TEST_F(ConnectorTest, Basic_Synchronous) { - internal::Connector connector0(handle0_.Pass()); - internal::Connector connector1(handle1_.Pass()); + internal::Connector connector0(handle0_.Pass(), + internal::Connector::SINGLE_THREADED_SEND); + internal::Connector connector1(handle1_.Pass(), + internal::Connector::SINGLE_THREADED_SEND); const char kText[] = "hello world"; @@ -152,8 +156,10 @@ } TEST_F(ConnectorTest, Basic_EarlyIncomingReceiver) { - internal::Connector connector0(handle0_.Pass()); - internal::Connector connector1(handle1_.Pass()); + internal::Connector connector0(handle0_.Pass(), + internal::Connector::SINGLE_THREADED_SEND); + internal::Connector connector1(handle1_.Pass(), + internal::Connector::SINGLE_THREADED_SEND); MessageAccumulator accumulator; connector1.set_incoming_receiver(&accumulator); @@ -178,8 +184,10 @@ } TEST_F(ConnectorTest, Basic_TwoMessages) { - internal::Connector connector0(handle0_.Pass()); - internal::Connector connector1(handle1_.Pass()); + internal::Connector connector0(handle0_.Pass(), + internal::Connector::SINGLE_THREADED_SEND); + internal::Connector connector1(handle1_.Pass(), + internal::Connector::SINGLE_THREADED_SEND); const char* kText[] = {"hello", "world"}; @@ -208,8 +216,10 @@ } TEST_F(ConnectorTest, Basic_TwoMessages_Synchronous) { - internal::Connector connector0(handle0_.Pass()); - internal::Connector connector1(handle1_.Pass()); + internal::Connector connector0(handle0_.Pass(), + internal::Connector::SINGLE_THREADED_SEND); + internal::Connector connector1(handle1_.Pass(), + internal::Connector::SINGLE_THREADED_SEND); const char* kText[] = {"hello", "world"}; @@ -238,7 +248,8 @@ } TEST_F(ConnectorTest, WriteToClosedPipe) { - internal::Connector connector0(handle0_.Pass()); + internal::Connector connector0(handle0_.Pass(), + internal::Connector::SINGLE_THREADED_SEND); const char kText[] = "hello world"; @@ -265,8 +276,10 @@ } TEST_F(ConnectorTest, MessageWithHandles) { - internal::Connector connector0(handle0_.Pass()); - internal::Connector connector1(handle1_.Pass()); + internal::Connector connector0(handle0_.Pass(), + internal::Connector::SINGLE_THREADED_SEND); + internal::Connector connector1(handle1_.Pass(), + internal::Connector::SINGLE_THREADED_SEND); const char kText[] = "hello world"; @@ -304,8 +317,10 @@ message_received.mutable_handles()->front() = Handle(); // |smph| now owns this handle. - internal::Connector connector_received(smph.Pass()); - internal::Connector connector_original(pipe.handle1.Pass()); + internal::Connector connector_received( + smph.Pass(), internal::Connector::SINGLE_THREADED_SEND); + internal::Connector connector_original( + pipe.handle1.Pass(), internal::Connector::SINGLE_THREADED_SEND); Message message2; AllocMessage(kText, &message2); @@ -324,15 +339,18 @@ } TEST_F(ConnectorTest, WaitForIncomingMessageWithError) { - internal::Connector connector0(handle0_.Pass()); + internal::Connector connector0(handle0_.Pass(), + internal::Connector::SINGLE_THREADED_SEND); // Close the other end of the pipe. handle1_.reset(); ASSERT_FALSE(connector0.WaitForIncomingMessage(MOJO_DEADLINE_INDEFINITE)); } TEST_F(ConnectorTest, WaitForIncomingMessageWithDeletion) { - internal::Connector connector0(handle0_.Pass()); - internal::Connector* connector1 = new internal::Connector(handle1_.Pass()); + internal::Connector connector0(handle0_.Pass(), + internal::Connector::SINGLE_THREADED_SEND); + internal::Connector* connector1 = new internal::Connector( + handle1_.Pass(), internal::Connector::SINGLE_THREADED_SEND); const char kText[] = "hello world"; @@ -358,8 +376,10 @@ } TEST_F(ConnectorTest, WaitForIncomingMessageWithReentrancy) { - internal::Connector connector0(handle0_.Pass()); - internal::Connector connector1(handle1_.Pass()); + internal::Connector connector0(handle0_.Pass(), + internal::Connector::SINGLE_THREADED_SEND); + internal::Connector connector1(handle1_.Pass(), + internal::Connector::SINGLE_THREADED_SEND); const char* kText[] = {"hello", "world"}; @@ -390,12 +410,14 @@ } TEST_F(ConnectorTest, RaiseError) { - internal::Connector connector0(handle0_.Pass()); + internal::Connector connector0(handle0_.Pass(), + internal::Connector::SINGLE_THREADED_SEND); bool error_handler_called0 = false; connector0.set_connection_error_handler( [&error_handler_called0]() { error_handler_called0 = true; }); - internal::Connector connector1(handle1_.Pass()); + internal::Connector connector1(handle1_.Pass(), + internal::Connector::SINGLE_THREADED_SEND); bool error_handler_called1 = false; connector1.set_connection_error_handler( [&error_handler_called1]() { error_handler_called1 = true; });
diff --git a/mojo/public/cpp/bindings/tests/multiplex_router_unittest.cc b/mojo/public/cpp/bindings/tests/multiplex_router_unittest.cc new file mode 100644 index 0000000..c175a0d7 --- /dev/null +++ b/mojo/public/cpp/bindings/tests/multiplex_router_unittest.cc
@@ -0,0 +1,297 @@ +// Copyright 2015 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 "base/memory/ref_counted.h" +#include "base/message_loop/message_loop.h" +#include "mojo/message_pump/message_pump_mojo.h" +#include "mojo/public/cpp/bindings/lib/interface_endpoint_client.h" +#include "mojo/public/cpp/bindings/lib/multiplex_router.h" +#include "mojo/public/cpp/bindings/lib/scoped_interface_endpoint_handle.h" +#include "mojo/public/cpp/bindings/message.h" +#include "mojo/public/cpp/bindings/message_filter.h" +#include "mojo/public/cpp/bindings/tests/message_queue.h" +#include "mojo/public/cpp/bindings/tests/router_test_util.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace mojo { +namespace test { +namespace { + +using mojo::internal::InterfaceEndpointClient; +using mojo::internal::MultiplexRouter; +using mojo::internal::ScopedInterfaceEndpointHandle; + +class MultiplexRouterTest : public testing::Test { + public: + MultiplexRouterTest() : loop_(common::MessagePumpMojo::Create()) {} + + void SetUp() override { + MessagePipe pipe; + router0_ = new MultiplexRouter(true, pipe.handle0.Pass()); + router1_ = new MultiplexRouter(true, pipe.handle1.Pass()); + router0_->CreateEndpointHandlePair(&endpoint0_, &endpoint1_); + endpoint1_ = + EmulatePassingEndpointHandle(endpoint1_.Pass(), router1_.get()); + } + + void TearDown() override {} + + void PumpMessages() { loop_.RunUntilIdle(); } + + ScopedInterfaceEndpointHandle EmulatePassingEndpointHandle( + ScopedInterfaceEndpointHandle handle, + MultiplexRouter* target) { + CHECK(!handle.is_local()); + + return target->CreateLocalEndpointHandle(handle.release()); + } + + protected: + scoped_refptr<MultiplexRouter> router0_; + scoped_refptr<MultiplexRouter> router1_; + ScopedInterfaceEndpointHandle endpoint0_; + ScopedInterfaceEndpointHandle endpoint1_; + + private: + base::MessageLoop loop_; +}; + +TEST_F(MultiplexRouterTest, BasicRequestResponse) { + InterfaceEndpointClient client0(endpoint0_.Pass(), nullptr, + make_scoped_ptr(new PassThroughFilter())); + ResponseGenerator generator; + InterfaceEndpointClient client1(endpoint1_.Pass(), &generator, + make_scoped_ptr(new PassThroughFilter())); + + Message request; + AllocRequestMessage(1, "hello", &request); + + MessageQueue message_queue; + client0.AcceptWithResponder(&request, new MessageAccumulator(&message_queue)); + + PumpMessages(); + + EXPECT_FALSE(message_queue.IsEmpty()); + + Message response; + message_queue.Pop(&response); + + EXPECT_EQ(std::string("hello world!"), + std::string(reinterpret_cast<const char*>(response.payload()))); + + // Send a second message on the pipe. + Message request2; + AllocRequestMessage(1, "hello again", &request2); + + client0.AcceptWithResponder(&request2, + new MessageAccumulator(&message_queue)); + + PumpMessages(); + + EXPECT_FALSE(message_queue.IsEmpty()); + + message_queue.Pop(&response); + + EXPECT_EQ(std::string("hello again world!"), + std::string(reinterpret_cast<const char*>(response.payload()))); +} + +TEST_F(MultiplexRouterTest, BasicRequestResponse_Synchronous) { + InterfaceEndpointClient client0(endpoint0_.Pass(), nullptr, + make_scoped_ptr(new PassThroughFilter())); + ResponseGenerator generator; + InterfaceEndpointClient client1(endpoint1_.Pass(), &generator, + make_scoped_ptr(new PassThroughFilter())); + + Message request; + AllocRequestMessage(1, "hello", &request); + + MessageQueue message_queue; + client0.AcceptWithResponder(&request, new MessageAccumulator(&message_queue)); + + router1_->WaitForIncomingMessage(MOJO_DEADLINE_INDEFINITE); + router0_->WaitForIncomingMessage(MOJO_DEADLINE_INDEFINITE); + + EXPECT_FALSE(message_queue.IsEmpty()); + + Message response; + message_queue.Pop(&response); + + EXPECT_EQ(std::string("hello world!"), + std::string(reinterpret_cast<const char*>(response.payload()))); + + // Send a second message on the pipe. + Message request2; + AllocRequestMessage(1, "hello again", &request2); + + client0.AcceptWithResponder(&request2, + new MessageAccumulator(&message_queue)); + + router1_->WaitForIncomingMessage(MOJO_DEADLINE_INDEFINITE); + router0_->WaitForIncomingMessage(MOJO_DEADLINE_INDEFINITE); + + EXPECT_FALSE(message_queue.IsEmpty()); + + message_queue.Pop(&response); + + EXPECT_EQ(std::string("hello again world!"), + std::string(reinterpret_cast<const char*>(response.payload()))); +} + +TEST_F(MultiplexRouterTest, RequestWithNoReceiver) { + InterfaceEndpointClient client0(endpoint0_.Pass(), nullptr, + make_scoped_ptr(new PassThroughFilter())); + InterfaceEndpointClient client1(endpoint1_.Pass(), nullptr, + make_scoped_ptr(new PassThroughFilter())); + + // Without an incoming receiver set on client1, we expect client0 to observe + // an error as a result of sending a message. + + Message request; + AllocRequestMessage(1, "hello", &request); + + MessageQueue message_queue; + client0.AcceptWithResponder(&request, new MessageAccumulator(&message_queue)); + + PumpMessages(); + + EXPECT_TRUE(client0.encountered_error()); + EXPECT_TRUE(client1.encountered_error()); + EXPECT_TRUE(message_queue.IsEmpty()); +} + +// Tests MultiplexRouter using the LazyResponseGenerator. The responses will not +// be sent until after the requests have been accepted. +TEST_F(MultiplexRouterTest, LazyResponses) { + InterfaceEndpointClient client0(endpoint0_.Pass(), nullptr, + make_scoped_ptr(new PassThroughFilter())); + LazyResponseGenerator generator; + InterfaceEndpointClient client1(endpoint1_.Pass(), &generator, + make_scoped_ptr(new PassThroughFilter())); + + Message request; + AllocRequestMessage(1, "hello", &request); + + MessageQueue message_queue; + client0.AcceptWithResponder(&request, new MessageAccumulator(&message_queue)); + PumpMessages(); + + // The request has been received but the response has not been sent yet. + EXPECT_TRUE(message_queue.IsEmpty()); + + // Send the response. + EXPECT_TRUE(generator.responder_is_valid()); + generator.CompleteWithResponse(); + PumpMessages(); + + // Check the response. + EXPECT_FALSE(message_queue.IsEmpty()); + Message response; + message_queue.Pop(&response); + EXPECT_EQ(std::string("hello world!"), + std::string(reinterpret_cast<const char*>(response.payload()))); + + // Send a second message on the pipe. + Message request2; + AllocRequestMessage(1, "hello again", &request2); + + client0.AcceptWithResponder(&request2, + new MessageAccumulator(&message_queue)); + PumpMessages(); + + // The request has been received but the response has not been sent yet. + EXPECT_TRUE(message_queue.IsEmpty()); + + // Send the second response. + EXPECT_TRUE(generator.responder_is_valid()); + generator.CompleteWithResponse(); + PumpMessages(); + + // Check the second response. + EXPECT_FALSE(message_queue.IsEmpty()); + message_queue.Pop(&response); + EXPECT_EQ(std::string("hello again world!"), + std::string(reinterpret_cast<const char*>(response.payload()))); +} + +// Tests that if the receiving application destroys the responder_ without +// sending a response, then we trigger connection error at both sides. Moreover, +// both sides still appear to have a valid message pipe handle bound. +TEST_F(MultiplexRouterTest, MissingResponses) { + InterfaceEndpointClient client0(endpoint0_.Pass(), nullptr, + make_scoped_ptr(new PassThroughFilter())); + bool error_handler_called0 = false; + client0.set_connection_error_handler( + [&error_handler_called0]() { error_handler_called0 = true; }); + + LazyResponseGenerator generator; + InterfaceEndpointClient client1(endpoint1_.Pass(), &generator, + make_scoped_ptr(new PassThroughFilter())); + bool error_handler_called1 = false; + client1.set_connection_error_handler( + [&error_handler_called1]() { error_handler_called1 = true; }); + + Message request; + AllocRequestMessage(1, "hello", &request); + + MessageQueue message_queue; + client0.AcceptWithResponder(&request, new MessageAccumulator(&message_queue)); + PumpMessages(); + + // The request has been received but no response has been sent. + EXPECT_TRUE(message_queue.IsEmpty()); + + // Destroy the responder MessagerReceiver but don't send any response. + generator.CompleteWithoutResponse(); + PumpMessages(); + + // Check that no response was received. + EXPECT_TRUE(message_queue.IsEmpty()); + + // Connection error handler is called at both sides. + EXPECT_TRUE(error_handler_called0); + EXPECT_TRUE(error_handler_called1); + + // The error flag is set at both sides. + EXPECT_TRUE(client0.encountered_error()); + EXPECT_TRUE(client1.encountered_error()); + + // The message pipe handle is valid at both sides. + EXPECT_TRUE(router0_->is_valid()); + EXPECT_TRUE(router1_->is_valid()); +} + +TEST_F(MultiplexRouterTest, LateResponse) { + // Test that things won't blow up if we try to send a message to a + // MessageReceiver, which was given to us via AcceptWithResponder, + // after the router has gone away. + + LazyResponseGenerator generator; + { + InterfaceEndpointClient client0(endpoint0_.Pass(), nullptr, + make_scoped_ptr(new PassThroughFilter())); + InterfaceEndpointClient client1(endpoint1_.Pass(), &generator, + make_scoped_ptr(new PassThroughFilter())); + + Message request; + AllocRequestMessage(1, "hello", &request); + + MessageQueue message_queue; + client0.AcceptWithResponder(&request, + new MessageAccumulator(&message_queue)); + + PumpMessages(); + + EXPECT_TRUE(generator.has_responder()); + } + + EXPECT_FALSE(generator.responder_is_valid()); + generator.CompleteWithResponse(); // This should end up doing nothing. +} + +// TODO(yzshen): add more tests. + +} // namespace +} // namespace test +} // namespace mojo
diff --git a/mojo/public/cpp/bindings/tests/router_test_util.cc b/mojo/public/cpp/bindings/tests/router_test_util.cc new file mode 100644 index 0000000..e10db24 --- /dev/null +++ b/mojo/public/cpp/bindings/tests/router_test_util.cc
@@ -0,0 +1,100 @@ +// Copyright 2015 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 "mojo/public/cpp/bindings/tests/router_test_util.h" + +#include <string.h> + +#include "mojo/public/cpp/bindings/lib/message_builder.h" +#include "mojo/public/cpp/bindings/tests/message_queue.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace mojo { +namespace test { + +void AllocRequestMessage(uint32_t name, const char* text, Message* message) { + size_t payload_size = strlen(text) + 1; // Plus null terminator. + internal::RequestMessageBuilder builder(name, payload_size); + memcpy(builder.buffer()->Allocate(payload_size), text, payload_size); + + builder.message()->MoveTo(message); +} + +void AllocResponseMessage(uint32_t name, + const char* text, + uint64_t request_id, + Message* message) { + size_t payload_size = strlen(text) + 1; // Plus null terminator. + internal::ResponseMessageBuilder builder(name, payload_size, request_id); + memcpy(builder.buffer()->Allocate(payload_size), text, payload_size); + + builder.message()->MoveTo(message); +} + +MessageAccumulator::MessageAccumulator(MessageQueue* queue) : queue_(queue) {} + +bool MessageAccumulator::Accept(Message* message) { + queue_->Push(message); + return true; +} + +ResponseGenerator::ResponseGenerator() {} + +bool ResponseGenerator::Accept(Message* message) { + return false; +} + +bool ResponseGenerator::AcceptWithResponder( + Message* message, + MessageReceiverWithStatus* responder) { + EXPECT_TRUE(message->has_flag(internal::kMessageExpectsResponse)); + + bool result = SendResponse(message->name(), message->request_id(), + reinterpret_cast<const char*>(message->payload()), + responder); + EXPECT_TRUE(responder->IsValid()); + delete responder; + return result; +} + +bool ResponseGenerator::SendResponse(uint32_t name, + uint64_t request_id, + const char* request_string, + MessageReceiver* responder) { + Message response; + std::string response_string(request_string); + response_string += " world!"; + AllocResponseMessage(name, response_string.c_str(), request_id, &response); + + return responder->Accept(&response); +} + +LazyResponseGenerator::LazyResponseGenerator() + : responder_(nullptr), name_(0), request_id_(0) {} + +LazyResponseGenerator::~LazyResponseGenerator() { + delete responder_; +} + +bool LazyResponseGenerator::AcceptWithResponder( + Message* message, + MessageReceiverWithStatus* responder) { + name_ = message->name(); + request_id_ = message->request_id(); + request_string_ = + std::string(reinterpret_cast<const char*>(message->payload())); + responder_ = responder; + return true; +} + +void LazyResponseGenerator::Complete(bool send_response) { + if (send_response) { + SendResponse(name_, request_id_, request_string_.c_str(), responder_); + } + delete responder_; + responder_ = nullptr; +} + +} // namespace test +} // namespace mojo
diff --git a/mojo/public/cpp/bindings/tests/router_test_util.h b/mojo/public/cpp/bindings/tests/router_test_util.h new file mode 100644 index 0000000..b40d271 --- /dev/null +++ b/mojo/public/cpp/bindings/tests/router_test_util.h
@@ -0,0 +1,81 @@ +// Copyright 2015 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 MOJO_PUBLIC_CPP_BINDINGS_TESTS_ROUTER_TEST_UTIL_H_ +#define MOJO_PUBLIC_CPP_BINDINGS_TESTS_ROUTER_TEST_UTIL_H_ + +#include <string> + +#include "mojo/public/cpp/bindings/message.h" + +namespace mojo { +namespace test { + +class MessageQueue; + +void AllocRequestMessage(uint32_t name, const char* text, Message* message); +void AllocResponseMessage(uint32_t name, + const char* text, + uint64_t request_id, + Message* message); + +class MessageAccumulator : public MessageReceiver { + public: + explicit MessageAccumulator(MessageQueue* queue); + + bool Accept(Message* message) override; + + private: + MessageQueue* queue_; +}; + +class ResponseGenerator : public MessageReceiverWithResponderStatus { + public: + ResponseGenerator(); + + bool Accept(Message* message) override; + + bool AcceptWithResponder(Message* message, + MessageReceiverWithStatus* responder) override; + + bool SendResponse(uint32_t name, + uint64_t request_id, + const char* request_string, + MessageReceiver* responder); +}; + +class LazyResponseGenerator : public ResponseGenerator { + public: + LazyResponseGenerator(); + + ~LazyResponseGenerator() override; + + bool AcceptWithResponder(Message* message, + MessageReceiverWithStatus* responder) override; + + bool has_responder() const { return !!responder_; } + + bool responder_is_valid() const { return responder_->IsValid(); } + + // Sends the response and delete the responder. + void CompleteWithResponse() { Complete(true); } + + // Deletes the responder without sending a response. + void CompleteWithoutResponse() { Complete(false); } + + private: + // Completes the request handling by deleting responder_. Optionally + // also sends a response. + void Complete(bool send_response); + + MessageReceiverWithStatus* responder_; + uint32_t name_; + uint64_t request_id_; + std::string request_string_; +}; + +} // namespace test +} // namespace mojo + +#endif // MOJO_PUBLIC_CPP_BINDINGS_TESTS_ROUTER_TEST_UTIL_H_
diff --git a/mojo/public/cpp/bindings/tests/router_unittest.cc b/mojo/public/cpp/bindings/tests/router_unittest.cc index c9c9f018..6e6a8ed 100644 --- a/mojo/public/cpp/bindings/tests/router_unittest.cc +++ b/mojo/public/cpp/bindings/tests/router_unittest.cc
@@ -2,14 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include <stdlib.h> -#include <string.h> - #include "base/message_loop/message_loop.h" #include "mojo/message_pump/message_pump_mojo.h" -#include "mojo/public/cpp/bindings/lib/message_builder.h" #include "mojo/public/cpp/bindings/lib/router.h" #include "mojo/public/cpp/bindings/tests/message_queue.h" +#include "mojo/public/cpp/bindings/tests/router_test_util.h" #include "mojo/public/cpp/system/macros.h" #include "testing/gtest/include/gtest/gtest.h" @@ -17,112 +14,6 @@ namespace test { namespace { -void AllocRequestMessage(uint32_t name, const char* text, Message* message) { - size_t payload_size = strlen(text) + 1; // Plus null terminator. - internal::RequestMessageBuilder builder(name, payload_size); - memcpy(builder.buffer()->Allocate(payload_size), text, payload_size); - - builder.message()->MoveTo(message); -} - -void AllocResponseMessage(uint32_t name, - const char* text, - uint64_t request_id, - Message* message) { - size_t payload_size = strlen(text) + 1; // Plus null terminator. - internal::ResponseMessageBuilder builder(name, payload_size, request_id); - memcpy(builder.buffer()->Allocate(payload_size), text, payload_size); - - builder.message()->MoveTo(message); -} - -class MessageAccumulator : public MessageReceiver { - public: - explicit MessageAccumulator(MessageQueue* queue) : queue_(queue) {} - - bool Accept(Message* message) override { - queue_->Push(message); - return true; - } - - private: - MessageQueue* queue_; -}; - -class ResponseGenerator : public MessageReceiverWithResponderStatus { - public: - ResponseGenerator() {} - - bool Accept(Message* message) override { return false; } - - bool AcceptWithResponder(Message* message, - MessageReceiverWithStatus* responder) override { - EXPECT_TRUE(message->has_flag(internal::kMessageExpectsResponse)); - - bool result = SendResponse( - message->name(), message->request_id(), - reinterpret_cast<const char*>(message->payload()), responder); - EXPECT_TRUE(responder->IsValid()); - delete responder; - return result; - } - - bool SendResponse(uint32_t name, - uint64_t request_id, - const char* request_string, - MessageReceiver* responder) { - Message response; - std::string response_string(request_string); - response_string += " world!"; - AllocResponseMessage(name, response_string.c_str(), request_id, &response); - - return responder->Accept(&response); - } -}; - -class LazyResponseGenerator : public ResponseGenerator { - public: - LazyResponseGenerator() : responder_(nullptr), name_(0), request_id_(0) {} - - ~LazyResponseGenerator() override { delete responder_; } - - bool AcceptWithResponder(Message* message, - MessageReceiverWithStatus* responder) override { - name_ = message->name(); - request_id_ = message->request_id(); - request_string_ = - std::string(reinterpret_cast<const char*>(message->payload())); - responder_ = responder; - return true; - } - - bool has_responder() const { return !!responder_; } - - bool responder_is_valid() const { return responder_->IsValid(); } - - // Send the response and delete the responder. - void CompleteWithResponse() { Complete(true); } - - // Delete the responder without sending a response. - void CompleteWithoutResponse() { Complete(false); } - - private: - // Completes the request handling by deleting responder_. Optionally - // also sends a response. - void Complete(bool send_response) { - if (send_response) { - SendResponse(name_, request_id_, request_string_.c_str(), responder_); - } - delete responder_; - responder_ = nullptr; - } - - MessageReceiverWithStatus* responder_; - uint32_t name_; - uint64_t request_id_; - std::string request_string_; -}; - class RouterTest : public testing::Test { public: RouterTest() : loop_(common::MessagePumpMojo::Create()) {}
diff --git a/mojo/public/cpp/bindings/tests/validation_unittest.cc b/mojo/public/cpp/bindings/tests/validation_unittest.cc index fc536c2..2fd98aa 100644 --- a/mojo/public/cpp/bindings/tests/validation_unittest.cc +++ b/mojo/public/cpp/bindings/tests/validation_unittest.cc
@@ -221,7 +221,9 @@ public: TestMessageReceiver(ValidationIntegrationTest* owner, ScopedMessagePipeHandle handle) - : owner_(owner), connector_(handle.Pass()) { + : owner_(owner), + connector_(handle.Pass(), + mojo::internal::Connector::SINGLE_THREADED_SEND) { connector_.set_enforce_errors_from_incoming_receiver(false); } ~TestMessageReceiver() override {}
diff --git a/mojo/public/mojo_application.gni b/mojo/public/mojo_application.gni index 72398b7..972584d49 100644 --- a/mojo/public/mojo_application.gni +++ b/mojo/public/mojo_application.gni
@@ -84,8 +84,8 @@ deps = [ "//mojo/platform_handle:for_shared_library", - "//mojo/public/gles2:for_shared_library", "//mojo/public/c/system:for_shared_library", + "//mojo/public/gles2:for_shared_library", ] deps += mojo_deps
diff --git a/mojo/public/platform/native/BUILD.gn b/mojo/public/platform/native/BUILD.gn index f7d31f5..4efc946 100644 --- a/mojo/public/platform/native/BUILD.gn +++ b/mojo/public/platform/native/BUILD.gn
@@ -39,8 +39,8 @@ configs += [ "//third_party/khronos:khronos_headers" ] deps = [ - "//mojo/public/c/gles2", "//mojo/public/c/environment", + "//mojo/public/c/gles2", "//mojo/public/c/system", ]
diff --git a/mojo/runner/BUILD.gn b/mojo/runner/BUILD.gn index 49efb46..0fe40cbf 100644 --- a/mojo/runner/BUILD.gn +++ b/mojo/runner/BUILD.gn
@@ -102,10 +102,10 @@ ] deps = [ - "//mojo/runner/host:switches", "//base", "//base:base_static", "//base:i18n", + "//mojo/runner/host:switches", ] } @@ -124,8 +124,8 @@ deps = [ ":init", "//base", - "//base/third_party/dynamic_annotations", "//base:base_static", + "//base/third_party/dynamic_annotations", "//components/devtools_service/public/cpp", "//components/devtools_service/public/interfaces", "//components/tracing:startup_tracing",
diff --git a/mojo/runner/child/BUILD.gn b/mojo/runner/child/BUILD.gn index e10de5e..7ba5fb78 100644 --- a/mojo/runner/child/BUILD.gn +++ b/mojo/runner/child/BUILD.gn
@@ -8,8 +8,8 @@ group("child") { testonly = true deps = [ - ":lib", ":apptests", + ":lib", ] }
diff --git a/mojo/runner/child/native_apptest.cc b/mojo/runner/child/native_apptest.cc index 7bb7780a..cc47edb 100644 --- a/mojo/runner/child/native_apptest.cc +++ b/mojo/runner/child/native_apptest.cc
@@ -22,9 +22,7 @@ TEST_F(NativeAppTest, Connect) { test::TestNativeServicePtr native_service; application_impl()->ConnectToService( - mojo::URLRequest::From( - std::string("exe:mojo_runner_child_apptest_native_target")), - &native_service); + "exe:mojo_runner_child_apptest_native_target", &native_service); bool result = false; native_service->Invert(
diff --git a/mojo/runner/host/BUILD.gn b/mojo/runner/host/BUILD.gn index f1890f87..713251e 100644 --- a/mojo/runner/host/BUILD.gn +++ b/mojo/runner/host/BUILD.gn
@@ -66,8 +66,8 @@ "//mojo/gles2", "//mojo/message_pump", "//mojo/platform_handle:platform_handle_impl", - "//mojo/runner/child:interfaces", "//mojo/runner:init", + "//mojo/runner/child:interfaces", "//mojo/shell", "//third_party/mojo/src/mojo/edk/system", ]
diff --git a/mojo/services/network/BUILD.gn b/mojo/services/network/BUILD.gn index 76d6bdc..286760d 100644 --- a/mojo/services/network/BUILD.gn +++ b/mojo/services/network/BUILD.gn
@@ -104,8 +104,8 @@ "//net", "//net:extras", "//net:http_server", - "//url", "//sql/mojo", + "//url", ] }
diff --git a/mojo/services/network/http_server_apptest.cc b/mojo/services/network/http_server_apptest.cc index ce93f04..ae04031 100644 --- a/mojo/services/network/http_server_apptest.cc +++ b/mojo/services/network/http_server_apptest.cc
@@ -552,10 +552,8 @@ void SetUp() override { ApplicationTestBase::SetUp(); - mojo::URLRequestPtr request(mojo::URLRequest::New()); - request->url = mojo::String::From("mojo:network_service"); scoped_ptr<ApplicationConnection> connection = - application_impl()->ConnectToApplication(request.Pass()); + application_impl()->ConnectToApplication("mojo:network_service"); connection->ConnectToService(&network_service_); connection->ConnectToService(&web_socket_factory_); }
diff --git a/mojo/services/network/network_service_delegate.cc b/mojo/services/network/network_service_delegate.cc index 0a439642..d5b90db0 100644 --- a/mojo/services/network/network_service_delegate.cc +++ b/mojo/services/network/network_service_delegate.cc
@@ -93,9 +93,7 @@ // to OpenFileSystem, the entire mojo system hangs to the point where writes // to stderr that previously would have printed to our console aren't. The // apptests are also fairly resistant to being run under gdb on android. - URLRequestPtr request(URLRequest::New()); - request->url = String::From("mojo:filesystem"); - app_->ConnectToService(request.Pass(), &files_); + app_->ConnectToService("mojo:filesystem", &files_); filesystem::FileSystemClientPtr client; binding_.Bind(GetProxy(&client));
diff --git a/mojo/services/network/udp_socket_apptest.cc b/mojo/services/network/udp_socket_apptest.cc index 0c92ede9..d55e32ac 100644 --- a/mojo/services/network/udp_socket_apptest.cc +++ b/mojo/services/network/udp_socket_apptest.cc
@@ -321,13 +321,8 @@ void SetUp() override { ApplicationTestBase::SetUp(); - - mojo::URLRequestPtr request(mojo::URLRequest::New()); - request->url = mojo::String::From("mojo:network_service"); - scoped_ptr<ApplicationConnection> connection = - application_impl()->ConnectToApplication(request.Pass()); - connection->ConnectToService(&network_service_); - + application_impl()->ConnectToService("mojo:network_service", + &network_service_); network_service_->CreateUDPSocket(GetProxy(&socket_)); }
diff --git a/mojo/services/network/url_loader_impl_apptest.cc b/mojo/services/network/url_loader_impl_apptest.cc index 0b9de67..0fe1749 100644 --- a/mojo/services/network/url_loader_impl_apptest.cc +++ b/mojo/services/network/url_loader_impl_apptest.cc
@@ -49,28 +49,32 @@ void Start() override { status_ = STARTED; } - int ReadRawData(net::IOBuffer* buf, int buf_size) override { + bool ReadRawData(net::IOBuffer* buf, int buf_size, int* bytes_read) override { status_ = READING; buf_size_ = buf_size; - return net::ERR_IO_PENDING; + SetStatus(net::URLRequestStatus(net::URLRequestStatus::IO_PENDING, 0)); + return false; } void NotifyHeadersComplete() { net::URLRequestJob::NotifyHeadersComplete(); } void NotifyReadComplete(int bytes_read) { if (bytes_read < 0) { - // Map errors to net::ERR_FAILED. - ReadRawDataComplete(net::ERR_FAILED); + NotifyDone(net::URLRequestStatus( + net::URLRequestStatus::FromError(net::ERR_FAILED))); + net::URLRequestJob::NotifyReadComplete(0); // Set this after calling ReadRawDataComplete since that ends up calling // ReadRawData. status_ = COMPLETED; } else if (bytes_read == 0) { - ReadRawDataComplete(bytes_read); + NotifyDone(net::URLRequestStatus()); + net::URLRequestJob::NotifyReadComplete(bytes_read); // Set this after calling ReadRawDataComplete since that ends up calling // ReadRawData. status_ = COMPLETED; } else { - ReadRawDataComplete(bytes_read); + SetStatus(net::URLRequestStatus()); + net::URLRequestJob::NotifyReadComplete(bytes_read); // Set this after calling ReadRawDataComplete since that ends up calling // ReadRawData. status_ = STARTED;
diff --git a/mojo/services/test_service/test_service_impl.cc b/mojo/services/test_service/test_service_impl.cc index 44d1818d..1f467e5 100644 --- a/mojo/services/test_service/test_service_impl.cc +++ b/mojo/services/test_service/test_service_impl.cc
@@ -43,9 +43,7 @@ void TestServiceImpl::ConnectToAppAndGetTime( const mojo::String& app_url, const mojo::Callback<void(int64_t)>& callback) { - mojo::URLRequestPtr request(mojo::URLRequest::New()); - request->url = mojo::String::From(app_url); - app_impl_->ConnectToService(request.Pass(), &time_service_); + app_impl_->ConnectToService(app_url.get(), &time_service_); if (tracking_) { tracking_->RecordNewRequest(); time_service_->StartTrackingRequests(mojo::Callback<void()>()); @@ -56,9 +54,7 @@ void TestServiceImpl::StartTrackingRequests( const mojo::Callback<void()>& callback) { TestRequestTrackerPtr tracker; - mojo::URLRequestPtr request(mojo::URLRequest::New()); - request->url = mojo::String::From("mojo:test_request_tracker_app"); - app_impl_->ConnectToService(request.Pass(), &tracker); + app_impl_->ConnectToService("mojo:test_request_tracker_app", &tracker); tracking_.reset(new TrackedService(tracker.Pass(), Name_, callback)); }
diff --git a/mojo/services/test_service/test_time_service_impl.cc b/mojo/services/test_service/test_time_service_impl.cc index 5dc90f79a..ae26a8ea 100644 --- a/mojo/services/test_service/test_time_service_impl.cc +++ b/mojo/services/test_service/test_time_service_impl.cc
@@ -23,9 +23,7 @@ void TestTimeServiceImpl::StartTrackingRequests( const mojo::Callback<void()>& callback) { TestRequestTrackerPtr tracker; - mojo::URLRequestPtr request(mojo::URLRequest::New()); - request->url = mojo::String::From("mojo:test_request_tracker_app"); - app_impl_->ConnectToService(request.Pass(), &tracker); + app_impl_->ConnectToService("mojo:test_request_tracker_app", &tracker); tracking_.reset(new TrackedService(tracker.Pass(), Name_, callback)); }
diff --git a/mojo/services/tracing/public/cpp/tracing_impl.cc b/mojo/services/tracing/public/cpp/tracing_impl.cc index 1cffe03..eed10f28b 100644 --- a/mojo/services/tracing/public/cpp/tracing_impl.cc +++ b/mojo/services/tracing/public/cpp/tracing_impl.cc
@@ -51,9 +51,7 @@ // up to something like CoreServices to name its own child threads. base::PlatformThread::SetName(app->url()); - mojo::URLRequestPtr request(mojo::URLRequest::New()); - request->url = mojo::String::From("mojo:tracing"); - connection_ = app->ConnectToApplication(request.Pass()); + connection_ = app->ConnectToApplication("mojo:tracing"); connection_->AddService(this); #ifdef NDEBUG
diff --git a/mojo/shell/BUILD.gn b/mojo/shell/BUILD.gn index 8478000..c1c6aae 100644 --- a/mojo/shell/BUILD.gn +++ b/mojo/shell/BUILD.gn
@@ -54,10 +54,10 @@ "//base/third_party/dynamic_annotations", "//crypto:crypto", "//mojo/application/public/cpp:sources", - "//url", - "//third_party/mojo/src/mojo/edk/system", "//mojo/environment:chromium", "//mojo/util:filename_util", + "//third_party/mojo/src/mojo/edk/system", + "//url", ] } @@ -101,8 +101,8 @@ "//mojo/package_manager", "//mojo/public/cpp/system", "//mojo/util:filename_util", - "//third_party/mojo/src/mojo/edk/test:run_all_unittests", "//testing/gtest", + "//third_party/mojo/src/mojo/edk/test:run_all_unittests", "//url", ] }
diff --git a/mojo/shell/application_manager_apptest.cc b/mojo/shell/application_manager_apptest.cc index c6b14a2..8e01d0d25 100644 --- a/mojo/shell/application_manager_apptest.cc +++ b/mojo/shell/application_manager_apptest.cc
@@ -90,9 +90,8 @@ // 1. Launch a process. (Actually, have the runner launch a process that // launches a process. #becauselinkerrors). mojo::shell::test::mojom::DriverPtr driver; - application_impl()->ConnectToService( - URLRequest::From(std::string("exe:application_manager_apptest_driver")), - &driver); + application_impl()->ConnectToService("exe:application_manager_apptest_driver", + &driver); // 2. Wait for it to connect to us. (via mojo:application_manager_apptests) base::MessageLoop::current()->Run();
diff --git a/mojo/shell/application_manager_apptest_driver.cc b/mojo/shell/application_manager_apptest_driver.cc index 51766cc..290fc32 100644 --- a/mojo/shell/application_manager_apptest_driver.cc +++ b/mojo/shell/application_manager_apptest_driver.cc
@@ -43,8 +43,7 @@ void Initialize(mojo::ApplicationImpl* app) override { app_ = app; mojo::shell::mojom::ApplicationManagerPtr application_manager; - app_->ConnectToService(mojo::URLRequest::From(std::string("mojo:shell")), - &application_manager); + app_->ConnectToService("mojo:shell", &application_manager); base::FilePath target_path; CHECK(base::PathService::Get(base::DIR_EXE, &target_path));
diff --git a/mojo/shell/application_manager_unittest.cc b/mojo/shell/application_manager_unittest.cc index e13f616f..1687ecc 100644 --- a/mojo/shell/application_manager_unittest.cc +++ b/mojo/shell/application_manager_unittest.cc
@@ -246,9 +246,7 @@ TesterContext* test_context, InterfaceRequest<TestA> request) : test_context_(test_context), binding_(this, request.Pass()) { - mojo::URLRequestPtr request2(mojo::URLRequest::New()); - request2->url = mojo::String::From(kTestBURLString); - connection_ = app_impl->ConnectToApplication(request2.Pass()); + connection_ = app_impl->ConnectToApplication(kTestBURLString); connection_->ConnectToService(&b_); }
diff --git a/mojo/shell/capability_filter_test.cc b/mojo/shell/capability_filter_test.cc index b50f7174..1b55759d 100644 --- a/mojo/shell/capability_filter_test.cc +++ b/mojo/shell/capability_filter_test.cc
@@ -118,9 +118,7 @@ app_ = app; // ServiceApplications have no capability filter and can thus connect // directly to the validator application. - URLRequestPtr request(URLRequest::New()); - request->url = String::From("test:validator"); - app_->ConnectToService(request.Pass(), &validator_); + app_->ConnectToService("test:validator", &validator_); } bool ConfigureIncomingConnection(ApplicationConnection* connection) override { AddService<Safe>(connection); @@ -170,16 +168,12 @@ // TestApplications receive their Validator via the inbound connection. connection->ConnectToService(&validator_); - URLRequestPtr request(URLRequest::New()); - request->url = String::From("test:service"); - connection1_ = app_->ConnectToApplication(request.Pass()); + connection1_ = app_->ConnectToApplication("test:service"); connection1_->SetRemoteServiceProviderConnectionErrorHandler( base::Bind(&TestApplication::ConnectionClosed, base::Unretained(this), "test:service")); - URLRequestPtr request2(URLRequest::New()); - request2->url = String::From("test:service2"); - connection2_ = app_->ConnectToApplication(request2.Pass()); + connection2_ = app_->ConnectToApplication("test:service2"); connection2_->SetRemoteServiceProviderConnectionErrorHandler( base::Bind(&TestApplication::ConnectionClosed, base::Unretained(this), "test:service2"));
diff --git a/net/BUILD.gn b/net/BUILD.gn index 62648e4a..0bba8a46 100644 --- a/net/BUILD.gn +++ b/net/BUILD.gn
@@ -1101,8 +1101,8 @@ ":net", ":test_support", "//build/config/sanitizers:deps", - "//testing/gtest", "//testing/gmock", + "//testing/gtest", "//third_party/boringssl", ] } @@ -1158,8 +1158,8 @@ ] deps = [ ":balsa", - ":epoll_server", ":epoll_quic_tools", + ":epoll_server", ":net", ":simple_quic_tools", "//base", @@ -1174,8 +1174,8 @@ ] deps = [ ":balsa", - ":epoll_server", ":epoll_quic_tools", + ":epoll_server", ":net", ":simple_quic_tools", "//base",
diff --git a/net/android/BUILD.gn b/net/android/BUILD.gn index 7cd9b08..df00495 100644 --- a/net/android/BUILD.gn +++ b/net/android/BUILD.gn
@@ -29,9 +29,9 @@ android_library("net_java_test_support") { DEPRECATED_java_in_dir = "../test/android/javatests/src" deps = [ + ":net_java", "//base:base_java", "//third_party/android_tools:legacy_http_javalib", - ":net_java", ] srcjar_deps = [ ":net_java_test_support_enums_srcjar" ] } @@ -44,10 +44,10 @@ android_library("net_javatests") { DEPRECATED_java_in_dir = "javatests/src" deps = [ - "//base:base_java", - "//base:base_java_test_support", ":net_java", ":net_java_test_support", + "//base:base_java", + "//base:base_java_test_support", ] }
diff --git a/net/base/layered_network_delegate.cc b/net/base/layered_network_delegate.cc index 6f8d89a7..e64019c0 100644 --- a/net/base/layered_network_delegate.cc +++ b/net/base/layered_network_delegate.cc
@@ -175,12 +175,6 @@ URLRequest* request) { } -void LayeredNetworkDelegate::OnURLRequestJobOrphaned(URLRequest* request) { - // This hook is only added to debug https://crbug.com/289715, so there is no - // need for a OnURLRequestJobOrphanedInternal hook. - nested_network_delegate_->NotifyURLRequestJobOrphaned(request); -} - void LayeredNetworkDelegate::OnPACScriptError(int line_number, const base::string16& error) { OnPACScriptErrorInternal(line_number, error);
diff --git a/net/base/layered_network_delegate.h b/net/base/layered_network_delegate.h index e6e7dea..9446043 100644 --- a/net/base/layered_network_delegate.h +++ b/net/base/layered_network_delegate.h
@@ -69,7 +69,6 @@ void OnNetworkBytesSent(URLRequest* request, int64_t bytes_sent) final; void OnCompleted(URLRequest* request, bool started) final; void OnURLRequestDestroyed(URLRequest* request) final; - void OnURLRequestJobOrphaned(URLRequest* request) final; void OnPACScriptError(int line_number, const base::string16& error) final; AuthRequiredResponse OnAuthRequired(URLRequest* request, const AuthChallengeInfo& auth_info,
diff --git a/net/base/network_delegate.cc b/net/base/network_delegate.cc index 6cf7c96..200905ec 100644 --- a/net/base/network_delegate.cc +++ b/net/base/network_delegate.cc
@@ -125,12 +125,6 @@ OnURLRequestDestroyed(request); } -void NetworkDelegate::NotifyURLRequestJobOrphaned(URLRequest* request) { - DCHECK(CalledOnValidThread()); - DCHECK(request); - OnURLRequestJobOrphaned(request); -} - void NetworkDelegate::NotifyPACScriptError(int line_number, const base::string16& error) { DCHECK(CalledOnValidThread());
diff --git a/net/base/network_delegate.h b/net/base/network_delegate.h index fa266f5..0636f4e 100644 --- a/net/base/network_delegate.h +++ b/net/base/network_delegate.h
@@ -91,7 +91,6 @@ void NotifyNetworkBytesSent(URLRequest* request, int64_t bytes_sent); void NotifyCompleted(URLRequest* request, bool started); void NotifyURLRequestDestroyed(URLRequest* request); - void NotifyURLRequestJobOrphaned(URLRequest* request); void NotifyPACScriptError(int line_number, const base::string16& error); AuthRequiredResponse NotifyAuthRequired(URLRequest* request, const AuthChallengeInfo& auth_info, @@ -108,8 +107,9 @@ const GURL& first_party_for_cookies) const; // TODO(mkwst): Remove this once we decide whether or not we wish to ship - // first-party cookies and cookie prefixes. https://crbug.com/459154, - // https://crbug.com/541511 + // first-party cookies, cookie prefixes, and setting secure cookies require + // secure scheme. https://crbug.com/459154, https://crbug.com/541511, + // https://crbug.com/546820 bool AreExperimentalCookieFeaturesEnabled() const; bool CancelURLRequestWithPolicyViolatingReferrerHeader( @@ -233,13 +233,6 @@ // a virtual method call. virtual void OnURLRequestDestroyed(URLRequest* request) = 0; - // Called when the current job for |request| is orphaned. This is a temporary - // callback to diagnose https://crbug.com/289715 and may not be used for other - // purposes. Note that it may be called after OnURLRequestDestroyed. - // - // TODO(davidben): Remove this once data has been gathered. - virtual void OnURLRequestJobOrphaned(URLRequest* request) = 0; - // Corresponds to ProxyResolverJSBindings::OnError. virtual void OnPACScriptError(int line_number, const base::string16& error) = 0; @@ -293,12 +286,13 @@ const GURL& url, const GURL& first_party_for_cookies) const = 0; - // Returns true if the embedder has enabled the experimental features, - // and false otherwise. + // Returns true if the embedder has enabled the experimental features, and + // false otherwise. // // TODO(mkwst): Remove this once we decide whether or not we wish to ship - // first-party cookies and cookie prefixes. https://crbug.com/459154, - // https://crbug.com/541511 + // first-party cookies, cookie prefixes, and setting secure cookies require + // secure scheme. https://crbug.com/459154, https://crbug.com/541511, + // https://crbug.com/546820 virtual bool OnAreExperimentalCookieFeaturesEnabled() const = 0; // Called when the |referrer_url| for requesting |target_url| during handling
diff --git a/net/base/network_delegate_impl.cc b/net/base/network_delegate_impl.cc index b5822a16..7548f616 100644 --- a/net/base/network_delegate_impl.cc +++ b/net/base/network_delegate_impl.cc
@@ -68,8 +68,6 @@ void NetworkDelegateImpl::OnURLRequestDestroyed(URLRequest* request) { } -void NetworkDelegateImpl::OnURLRequestJobOrphaned(URLRequest* request) {} - void NetworkDelegateImpl::OnPACScriptError(int line_number, const base::string16& error) { }
diff --git a/net/base/network_delegate_impl.h b/net/base/network_delegate_impl.h index 231a6467..7e9db65 100644 --- a/net/base/network_delegate_impl.h +++ b/net/base/network_delegate_impl.h
@@ -147,13 +147,6 @@ // a virtual method call. void OnURLRequestDestroyed(URLRequest* request) override; - // Called when the current job for |request| is orphaned. This is a temporary - // callback to diagnose https://crbug.com/289715 and may not be used for other - // purposes. Note that it may be called after OnURLRequestDestroyed. - // - // TODO(davidben): Remove this once data has been gathered. - void OnURLRequestJobOrphaned(URLRequest* request) override; - // Corresponds to ProxyResolverJSBindings::OnError. void OnPACScriptError(int line_number, const base::string16& error) override;
diff --git a/net/cookies/canonical_cookie.cc b/net/cookies/canonical_cookie.cc index ddf35e05..bc944542 100644 --- a/net/cookies/canonical_cookie.cc +++ b/net/cookies/canonical_cookie.cc
@@ -47,6 +47,7 @@ #include "base/basictypes.h" #include "base/format_macros.h" #include "base/logging.h" +#include "base/metrics/histogram_macros.h" #include "base/strings/stringprintf.h" #include "net/cookies/cookie_util.h" #include "net/cookies/parsed_cookie.h" @@ -116,21 +117,6 @@ return a.Path().compare(b.Path()); } -// Returns true if the cookie does not violate any constraints imposed -// by the cookie name's prefix, as described in -// https://tools.ietf.org/html/draft-west-cookie-prefixes -bool IsCookiePrefixValid(const GURL& url, const ParsedCookie& parsed_cookie) { - const char kSecurePrefix[] = "$Secure-"; - const char kHostPrefix[] = "$Host-"; - if (parsed_cookie.Name().find(kSecurePrefix) == 0) - return parsed_cookie.IsSecure() && url.SchemeIsCryptographic(); - if (parsed_cookie.Name().find(kHostPrefix) == 0) { - return parsed_cookie.IsSecure() && url.SchemeIsCryptographic() && - !parsed_cookie.HasDomain() && parsed_cookie.Path() == "/"; - } - return true; -} - } // namespace CanonicalCookie::CanonicalCookie() @@ -254,6 +240,17 @@ return NULL; } + // Per 3.2.1 of "Deprecate modification of 'secure' cookies from non-secure + // origins", if the cookie's "secure-only-flag" is "true" and the requesting + // URL does not have a secure scheme, the cookie should be thrown away. + // https://tools.ietf.org/html/draft-west-leave-secure-cookies-alone + if (options.enforce_strict_secure() && parsed_cookie.IsSecure() && + !url.SchemeIsCryptographic()) { + VLOG(kVlogSetCookies) + << "Create() is trying to create a secure cookie from an insecure URL"; + return NULL; + } + std::string cookie_path = CanonicalCookie::CanonPath(url, parsed_cookie); Time server_time(creation_time); if (options.has_server_time()) @@ -263,7 +260,11 @@ creation_time, server_time); - if (options.enforce_prefixes() && !IsCookiePrefixValid(url, parsed_cookie)) { + CookiePrefix prefix = CanonicalCookie::GetCookiePrefix(parsed_cookie.Name()); + bool is_cookie_valid = + CanonicalCookie::IsCookiePrefixValid(prefix, url, parsed_cookie); + CanonicalCookie::RecordCookiePrefixMetrics(prefix, is_cookie_valid); + if (options.enforce_prefixes() && !is_cookie_valid) { VLOG(kVlogSetCookies) << "Create() failed because the cookie violated prefix rules."; return nullptr; @@ -286,6 +287,7 @@ bool secure, bool http_only, bool first_party_only, + bool enforce_strict_secure, CookiePriority priority) { // Expect valid attribute tokens and values, as defined by the ParsedCookie // logic, otherwise don't create the cookie. @@ -305,6 +307,9 @@ return NULL; } + if (enforce_strict_secure && secure && !url.SchemeIsCryptographic()) + return NULL; + std::string parsed_path = ParsedCookie::ParseValueString(path); if (parsed_path != path) return NULL; @@ -469,4 +474,47 @@ return Priority() < other.Priority(); } +// static +CanonicalCookie::CookiePrefix CanonicalCookie::GetCookiePrefix( + const std::string& name) { + const char kSecurePrefix[] = "$Secure-"; + const char kHostPrefix[] = "$Host-"; + if (name.find(kSecurePrefix) == 0) + return CanonicalCookie::COOKIE_PREFIX_SECURE; + if (name.find(kHostPrefix) == 0) + return CanonicalCookie::COOKIE_PREFIX_HOST; + return CanonicalCookie::COOKIE_PREFIX_NONE; +} + +// static +void CanonicalCookie::RecordCookiePrefixMetrics( + CanonicalCookie::CookiePrefix prefix, + bool is_cookie_valid) { + const char kCookiePrefixHistogram[] = "Cookie.CookiePrefix"; + const char kCookiePrefixBlockedHistogram[] = "Cookie.CookiePrefixBlocked"; + UMA_HISTOGRAM_ENUMERATION(kCookiePrefixHistogram, prefix, + CanonicalCookie::COOKIE_PREFIX_LAST); + if (!is_cookie_valid) { + UMA_HISTOGRAM_ENUMERATION(kCookiePrefixBlockedHistogram, prefix, + CanonicalCookie::COOKIE_PREFIX_LAST); + } +} + +// Returns true if the cookie does not violate any constraints imposed +// by the cookie name's prefix, as described in +// https://tools.ietf.org/html/draft-west-cookie-prefixes +// +// static +bool CanonicalCookie::IsCookiePrefixValid(CanonicalCookie::CookiePrefix prefix, + const GURL& url, + const ParsedCookie& parsed_cookie) { + if (prefix == CanonicalCookie::COOKIE_PREFIX_SECURE) + return parsed_cookie.IsSecure() && url.SchemeIsCryptographic(); + if (prefix == CanonicalCookie::COOKIE_PREFIX_HOST) { + return parsed_cookie.IsSecure() && url.SchemeIsCryptographic() && + !parsed_cookie.HasDomain() && parsed_cookie.Path() == "/"; + } + return true; +} + } // namespace net
diff --git a/net/cookies/canonical_cookie.h b/net/cookies/canonical_cookie.h index 30ddcab..bc1cc654 100644 --- a/net/cookies/canonical_cookie.h +++ b/net/cookies/canonical_cookie.h
@@ -9,6 +9,7 @@ #include <vector> #include "base/basictypes.h" +#include "base/gtest_prod_util.h" #include "base/time/time.h" #include "net/base/net_export.h" #include "net/cookies/cookie_constants.h" @@ -51,7 +52,7 @@ // Creates a new |CanonicalCookie| from the |cookie_line| and the // |creation_time|. Canonicalizes and validates inputs. May return NULL if - // an attribut value is invalid. + // an attribute value is invalid. static CanonicalCookie* Create(const GURL& url, const std::string& cookie_line, const base::Time& creation_time, @@ -70,6 +71,7 @@ bool secure, bool http_only, bool first_party_only, + bool enforce_strict_secure, CookiePriority priority); const GURL& Source() const { return source_; } @@ -107,6 +109,18 @@ && path_ == ecc.Path()); } + // Checks if two cookies have the same name and domain-match per RFC 6265. + // Note that this purposefully ignores paths, and that this function is + // guaranteed to return |true| for a superset of the inputs that + // IsEquivalent() above returns |true| for. + // + // This is needed for the updates to RFC6265 as per + // https://tools.ietf.org/html/draft-west-leave-secure-cookies-alone. + bool IsEquivalentForSecureCookieMatching(const CanonicalCookie& ecc) const { + return (name_ == ecc.Name() && (ecc.IsDomainMatch(Source().host()) || + IsDomainMatch(ecc.Source().host()))); + } + void SetLastAccessDate(const base::Time& date) { last_access_date_ = date; } @@ -146,6 +160,32 @@ bool FullCompare(const CanonicalCookie& other) const; private: + FRIEND_TEST_ALL_PREFIXES(CanonicalCookiePrefixHistogramTest, TestHistograms); + + // The special cookie prefixes as defined in + // https://tools.ietf.org/html/draft-west-cookie-prefixes + // + // This enum is being histogrammed; do not reorder or remove values. + enum CookiePrefix { + COOKIE_PREFIX_NONE = 0, + COOKIE_PREFIX_SECURE, + COOKIE_PREFIX_HOST, + COOKIE_PREFIX_LAST + }; + + // Returns the CookiePrefix (or COOKIE_PREFIX_NONE if none) that + // applies to the given cookie |name|. + static CookiePrefix GetCookiePrefix(const std::string& name); + // Records histograms to measure how often cookie prefixes appear in + // the wild and how often they would be blocked. + static void RecordCookiePrefixMetrics(CookiePrefix prefix, + bool is_cookie_valid); + // Returns true if a prefixed cookie does not violate any of the rules + // for that cookie. + static bool IsCookiePrefixValid(CookiePrefix prefix, + const GURL& url, + const ParsedCookie& parsed_cookie); + // The source member of a canonical cookie is the origin of the URL that tried // to set this cookie. This field is not persistent though; its only used in // the in-tab cookies dialog to show the user the source URL. This is used for
diff --git a/net/cookies/canonical_cookie_unittest.cc b/net/cookies/canonical_cookie_unittest.cc index cc0426e..73c7c86 100644 --- a/net/cookies/canonical_cookie_unittest.cc +++ b/net/cookies/canonical_cookie_unittest.cc
@@ -5,6 +5,7 @@ #include "net/cookies/canonical_cookie.h" #include "base/memory/scoped_ptr.h" +#include "base/test/histogram_tester.h" #include "net/cookies/cookie_constants.h" #include "net/cookies/cookie_options.h" #include "testing/gtest/include/gtest/gtest.h" @@ -94,7 +95,7 @@ // string. cookie.reset(CanonicalCookie::Create( url, "A", "2", "www.example.com", "/test", creation_time, base::Time(), - false, false, false, COOKIE_PRIORITY_DEFAULT)); + false, false, false, false, COOKIE_PRIORITY_DEFAULT)); EXPECT_EQ(url.GetOrigin(), cookie->Source()); EXPECT_EQ("A", cookie->Name()); EXPECT_EQ("2", cookie->Value()); @@ -106,7 +107,7 @@ cookie.reset(CanonicalCookie::Create( url, "A", "2", ".www.example.com", "/test", creation_time, base::Time(), - false, false, false, COOKIE_PRIORITY_DEFAULT)); + false, false, false, false, COOKIE_PRIORITY_DEFAULT)); EXPECT_EQ(url.GetOrigin(), cookie->Source()); EXPECT_EQ("A", cookie->Name()); EXPECT_EQ("2", cookie->Value()); @@ -240,6 +241,104 @@ EXPECT_FALSE(cookie->IsEquivalent(*other_cookie)); } +TEST(CanonicalCookieTest, IsEquivalentForSecureCookieMatching) { + GURL url("http://www.example.com/"); + std::string cookie_name = "A"; + std::string cookie_value = "2EDA-EF"; + std::string cookie_domain = ".www.example.com"; + std::string cookie_path = "/"; + base::Time creation_time = base::Time::Now(); + base::Time last_access_time = creation_time; + base::Time expiration_time = creation_time + base::TimeDelta::FromDays(2); + bool secure(false); + bool httponly(false); + bool firstparty(false); + + // Test that a cookie is equivalent to itself. + scoped_ptr<CanonicalCookie> cookie(new CanonicalCookie( + url, cookie_name, cookie_value, cookie_domain, cookie_path, creation_time, + expiration_time, last_access_time, secure, httponly, firstparty, + COOKIE_PRIORITY_MEDIUM)); + EXPECT_TRUE(cookie->IsEquivalentForSecureCookieMatching(*cookie)); + + // Test that two identical cookies are equivalent. + scoped_ptr<CanonicalCookie> other_cookie(new CanonicalCookie( + url, cookie_name, cookie_value, cookie_domain, cookie_path, creation_time, + expiration_time, last_access_time, secure, httponly, firstparty, + COOKIE_PRIORITY_MEDIUM)); + EXPECT_TRUE(cookie->IsEquivalentForSecureCookieMatching(*other_cookie)); + + // Tests that use different variations of attribute values that + // DON'T affect cookie equivalence. Differs from the IsEquivalent tests above + // as follows: + // * Should return true even if paths differ. + // * Should return true if the domains "domain-match" (but are not + // identical). + other_cookie.reset( + new CanonicalCookie(url, cookie_name, "2", cookie_domain, cookie_path, + creation_time, expiration_time, last_access_time, + secure, httponly, firstparty, COOKIE_PRIORITY_HIGH)); + EXPECT_TRUE(cookie->IsEquivalentForSecureCookieMatching(*other_cookie)); + + base::Time other_creation_time = + creation_time + base::TimeDelta::FromMinutes(2); + other_cookie.reset(new CanonicalCookie( + url, cookie_name, "2", cookie_domain, cookie_path, other_creation_time, + expiration_time, last_access_time, secure, httponly, firstparty, + COOKIE_PRIORITY_MEDIUM)); + EXPECT_TRUE(cookie->IsEquivalentForSecureCookieMatching(*other_cookie)); + + other_cookie.reset(new CanonicalCookie( + url, cookie_name, cookie_name, cookie_domain, cookie_path, creation_time, + expiration_time, last_access_time, true, httponly, firstparty, + COOKIE_PRIORITY_LOW)); + EXPECT_TRUE(cookie->IsEquivalentForSecureCookieMatching(*other_cookie)); + + other_cookie.reset(new CanonicalCookie( + url, cookie_name, cookie_name, cookie_domain, cookie_path, creation_time, + expiration_time, last_access_time, secure, true, firstparty, + COOKIE_PRIORITY_LOW)); + EXPECT_TRUE(cookie->IsEquivalentForSecureCookieMatching(*other_cookie)); + + other_cookie.reset(new CanonicalCookie( + url, cookie_name, cookie_name, cookie_domain, cookie_path, creation_time, + expiration_time, last_access_time, secure, httponly, true, + COOKIE_PRIORITY_LOW)); + EXPECT_TRUE(cookie->IsEquivalentForSecureCookieMatching(*other_cookie)); + + // The following 3 tests' expected results differ from their IsEquivalent + // counterparts above. + other_cookie.reset(new CanonicalCookie( + url, cookie_name, cookie_value, cookie_domain, "/test/0", creation_time, + expiration_time, last_access_time, secure, httponly, firstparty, + COOKIE_PRIORITY_MEDIUM)); + EXPECT_TRUE(cookie->IsEquivalentForSecureCookieMatching(*other_cookie)); + + other_cookie.reset(new CanonicalCookie( + url, cookie_name, cookie_value, "www.example.com", cookie_path, + creation_time, expiration_time, last_access_time, secure, httponly, + firstparty, COOKIE_PRIORITY_MEDIUM)); + EXPECT_TRUE(cookie->IsDomainCookie()); + EXPECT_FALSE(other_cookie->IsDomainCookie()); + EXPECT_TRUE(cookie->IsEquivalentForSecureCookieMatching(*other_cookie)); + + other_cookie.reset(new CanonicalCookie( + url, cookie_name, cookie_value, ".example.com", cookie_path, + creation_time, expiration_time, last_access_time, secure, httponly, + firstparty, COOKIE_PRIORITY_MEDIUM)); + EXPECT_TRUE(cookie->IsEquivalentForSecureCookieMatching(*other_cookie)); + + // Tests that use different variations of attribute values that + // DO affect cookie equivalence. Note that unlike the IsEquivalent tests + // above, this does *not* include tests for differing paths or domains that + // "domain-match". + other_cookie.reset(new CanonicalCookie( + url, "B", cookie_value, cookie_domain, cookie_path, creation_time, + expiration_time, last_access_time, secure, httponly, firstparty, + COOKIE_PRIORITY_MEDIUM)); + EXPECT_FALSE(cookie->IsEquivalentForSecureCookieMatching(*other_cookie)); +} + TEST(CanonicalCookieTest, IsDomainMatch) { GURL url("http://www.example.com/test/foo.html"); base::Time creation_time = base::Time::Now(); @@ -538,4 +637,121 @@ creation_time, options))); } +TEST(CanonicalCookieTest, EnforceSecureCookiesRequireSecureScheme) { + GURL http_url("http://www.example.com"); + GURL https_url("https://www.example.com"); + base::Time creation_time = base::Time::Now(); + CookieOptions options; + options.set_enforce_strict_secure(); + + scoped_ptr<CanonicalCookie> http_cookie_no_secure( + CanonicalCookie::Create(http_url, "a=b", creation_time, options)); + scoped_ptr<CanonicalCookie> http_cookie_secure( + CanonicalCookie::Create(http_url, "a=b; Secure", creation_time, options)); + scoped_ptr<CanonicalCookie> https_cookie_no_secure( + CanonicalCookie::Create(https_url, "a=b", creation_time, options)); + scoped_ptr<CanonicalCookie> https_cookie_secure(CanonicalCookie::Create( + https_url, "a=b; Secure", creation_time, options)); + + EXPECT_TRUE(http_cookie_no_secure.get()); + EXPECT_FALSE(http_cookie_secure.get()); + EXPECT_TRUE(https_cookie_no_secure.get()); + EXPECT_TRUE(https_cookie_secure.get()); + + scoped_ptr<CanonicalCookie> http_cookie_no_secure_extended( + CanonicalCookie::Create(http_url, "a", "b", "", "", creation_time, + creation_time, false, false, false, true, + COOKIE_PRIORITY_DEFAULT)); + scoped_ptr<CanonicalCookie> http_cookie_secure_extended( + CanonicalCookie::Create(http_url, "a", "b", "", "", creation_time, + creation_time, true, false, false, true, + COOKIE_PRIORITY_DEFAULT)); + scoped_ptr<CanonicalCookie> https_cookie_no_secure_extended( + CanonicalCookie::Create(https_url, "a", "b", "", "", creation_time, + creation_time, false, false, false, true, + COOKIE_PRIORITY_DEFAULT)); + scoped_ptr<CanonicalCookie> https_cookie_secure_extended( + CanonicalCookie::Create(https_url, "a", "b", "", "", creation_time, + creation_time, true, false, false, true, + COOKIE_PRIORITY_DEFAULT)); + + EXPECT_TRUE(http_cookie_no_secure_extended.get()); + EXPECT_FALSE(http_cookie_secure_extended.get()); + EXPECT_TRUE(https_cookie_no_secure_extended.get()); + EXPECT_TRUE(https_cookie_secure_extended.get()); +} + +namespace { + +class CanonicalCookiePrefixHistogramTest : public testing::TestWithParam<bool> { +}; + +} // namespace + +TEST_P(CanonicalCookiePrefixHistogramTest, TestHistograms) { + base::HistogramTester histograms; + const char kCookiePrefixHistogram[] = "Cookie.CookiePrefix"; + const char kCookiePrefixBlockedHistogram[] = "Cookie.CookiePrefixBlocked"; + GURL https_url("https://www.example.test"); + base::Time creation_time = base::Time::Now(); + CookieOptions options; + if (GetParam()) + options.set_enforce_prefixes(); + + scoped_ptr<CanonicalCookie> cookie1 = make_scoped_ptr( + CanonicalCookie::Create(https_url, "$Host-A=B;", creation_time, options)); + if (GetParam()) + EXPECT_EQ(nullptr, cookie1); + else + EXPECT_NE(nullptr, cookie1); + histograms.ExpectBucketCount(kCookiePrefixHistogram, + CanonicalCookie::COOKIE_PREFIX_HOST, 1); + histograms.ExpectBucketCount(kCookiePrefixBlockedHistogram, + CanonicalCookie::COOKIE_PREFIX_HOST, 1); + + EXPECT_NE(nullptr, make_scoped_ptr(CanonicalCookie::Create( + https_url, "$Host-A=B; Path=/; Secure", creation_time, + options))); + histograms.ExpectBucketCount(kCookiePrefixHistogram, + CanonicalCookie::COOKIE_PREFIX_HOST, 2); + histograms.ExpectBucketCount(kCookiePrefixBlockedHistogram, + CanonicalCookie::COOKIE_PREFIX_HOST, 1); + EXPECT_NE(nullptr, make_scoped_ptr(CanonicalCookie::Create( + https_url, "$HostA=B; Path=/; Secure", creation_time, + options))); + histograms.ExpectBucketCount(kCookiePrefixHistogram, + CanonicalCookie::COOKIE_PREFIX_HOST, 2); + histograms.ExpectBucketCount(kCookiePrefixBlockedHistogram, + CanonicalCookie::COOKIE_PREFIX_HOST, 1); + + scoped_ptr<CanonicalCookie> cookie2 = make_scoped_ptr(CanonicalCookie::Create( + https_url, "$Secure-A=B;", creation_time, options)); + if (GetParam()) + EXPECT_EQ(nullptr, cookie2); + else + EXPECT_NE(nullptr, cookie2); + histograms.ExpectBucketCount(kCookiePrefixHistogram, + CanonicalCookie::COOKIE_PREFIX_SECURE, 1); + histograms.ExpectBucketCount(kCookiePrefixBlockedHistogram, + CanonicalCookie::COOKIE_PREFIX_SECURE, 1); + EXPECT_NE(nullptr, make_scoped_ptr(CanonicalCookie::Create( + https_url, "$Secure-A=B; Path=/; Secure", + creation_time, options))); + histograms.ExpectBucketCount(kCookiePrefixHistogram, + CanonicalCookie::COOKIE_PREFIX_SECURE, 2); + histograms.ExpectBucketCount(kCookiePrefixBlockedHistogram, + CanonicalCookie::COOKIE_PREFIX_SECURE, 1); + EXPECT_NE(nullptr, make_scoped_ptr(CanonicalCookie::Create( + https_url, "$SecureA=B; Path=/; Secure", creation_time, + options))); + histograms.ExpectBucketCount(kCookiePrefixHistogram, + CanonicalCookie::COOKIE_PREFIX_SECURE, 2); + histograms.ExpectBucketCount(kCookiePrefixBlockedHistogram, + CanonicalCookie::COOKIE_PREFIX_SECURE, 1); +} + +INSTANTIATE_TEST_CASE_P(CanonicalCookiePrefixHistogramTests, + CanonicalCookiePrefixHistogramTest, + testing::Values(true, false)); + } // namespace net
diff --git a/net/cookies/cookie_monster.cc b/net/cookies/cookie_monster.cc index 6304eb6c..04479187 100644 --- a/net/cookies/cookie_monster.cc +++ b/net/cookies/cookie_monster.cc
@@ -441,6 +441,7 @@ bool http_only, bool first_party_only, bool enforce_prefixes, + bool enforce_strict_secure, CookiePriority priority, const SetCookiesCallback& callback) : CookieMonsterTask(cookie_monster), @@ -454,6 +455,7 @@ http_only_(http_only), first_party_only_(first_party_only), enforce_prefixes_(enforce_prefixes), + enforce_strict_secure_(enforce_strict_secure), priority_(priority), callback_(callback) {} @@ -474,6 +476,7 @@ bool http_only_; bool first_party_only_; bool enforce_prefixes_; + bool enforce_strict_secure_; CookiePriority priority_; SetCookiesCallback callback_; @@ -483,7 +486,8 @@ void CookieMonster::SetCookieWithDetailsTask::Run() { bool success = this->cookie_monster()->SetCookieWithDetails( url_, name_, value_, domain_, path_, expiration_time_, secure_, - http_only_, first_party_only_, enforce_prefixes_, priority_); + http_only_, first_party_only_, enforce_prefixes_, enforce_strict_secure_, + priority_); if (!callback_.is_null()) { this->InvokeCallback(base::Bind(&SetCookiesCallback::Run, base::Unretained(&callback_), success)); @@ -933,11 +937,13 @@ bool http_only, bool first_party_only, bool enforce_prefixes, + bool enforce_strict_secure, CookiePriority priority, const SetCookiesCallback& callback) { scoped_refptr<SetCookieWithDetailsTask> task = new SetCookieWithDetailsTask( this, url, name, value, domain, path, expiration_time, secure, http_only, - first_party_only, enforce_prefixes, priority, callback); + first_party_only, enforce_prefixes, enforce_strict_secure, priority, + callback); DoCookieTaskForURL(task, url); } @@ -1118,6 +1124,7 @@ bool http_only, bool first_party_only, bool enforce_prefixes, + bool enforce_strict_secure, CookiePriority priority) { base::AutoLock autolock(lock_); @@ -1128,9 +1135,9 @@ last_time_seen_ = creation_time; scoped_ptr<CanonicalCookie> cc; - cc.reset(CanonicalCookie::Create(url, name, value, domain, path, - creation_time, expiration_time, secure, - http_only, first_party_only, priority)); + cc.reset(CanonicalCookie::Create( + url, name, value, domain, path, creation_time, expiration_time, secure, + http_only, first_party_only, enforce_strict_secure, priority)); if (!cc.get()) return false; @@ -1140,6 +1147,8 @@ options.set_include_first_party_only(); if (enforce_prefixes) options.set_enforce_prefixes(); + if (enforce_strict_secure) + options.set_enforce_strict_secure(); return SetCanonicalCookie(&cc, creation_time, options); } @@ -1776,20 +1785,38 @@ bool CookieMonster::DeleteAnyEquivalentCookie(const std::string& key, const CanonicalCookie& ecc, bool skip_httponly, - bool already_expired) { + bool already_expired, + bool enforce_strict_secure) { lock_.AssertAcquired(); bool found_equivalent_cookie = false; bool skipped_httponly = false; + bool skipped_secure_cookie = false; for (CookieMapItPair its = cookies_.equal_range(key); its.first != its.second;) { CookieMap::iterator curit = its.first; CanonicalCookie* cc = curit->second; ++its.first; - if (ecc.IsEquivalent(*cc)) { + // If strict secure cookies is being enforced, then the equivalency + // requirements are looser. If the cookie is being set from an insecure + // scheme, then if a cookie already exists with the same name and it is + // Secure, then the cookie should *not* be updated if they domain-match and + // ignoring the path attribute. + // + // See: https://tools.ietf.org/html/draft-west-leave-secure-cookies-alone + if (enforce_strict_secure && !ecc.Source().SchemeIsCryptographic() && + ecc.IsEquivalentForSecureCookieMatching(*cc) && cc->IsSecure()) { + skipped_secure_cookie = true; + // TODO(jww): We need to add metrics here before we add this as a Finch + // experiment, as our current Cookie.CookieSourceScheme and related + // metrics make very different assumptions from what this now means. + found_equivalent_cookie = true; + } else if (ecc.IsEquivalent(*cc)) { // We should never have more than one equivalent cookie, since they should - // overwrite each other. + // overwrite each other, unless secure cookies require secure scheme is + // being enforced. In that case, cookies with different paths might exist + // and be considered equivalent. CHECK(!found_equivalent_cookie) << "Duplicate equivalent cookies found, cookie store is corrupted."; if (skip_httponly && cc->IsHttpOnly()) { @@ -1802,7 +1829,7 @@ found_equivalent_cookie = true; } } - return skipped_httponly; + return skipped_httponly || skipped_secure_cookie; } CookieMonster::CookieMap::iterator CookieMonster::InternalInsertCookie( @@ -1889,8 +1916,18 @@ bool already_expired = (*cc)->IsExpired(creation_time); if (DeleteAnyEquivalentCookie(key, **cc, options.exclude_httponly(), - already_expired)) { - VLOG(kVlogSetCookies) << "SetCookie() not clobbering httponly cookie"; + already_expired, + options.enforce_strict_secure())) { + std::string error; + if (options.enforce_strict_secure()) { + error = + "SetCookie() not clobbering httponly cookie or secure cookie for " + "insecure scheme"; + } else { + error = "SetCookie() not clobbering httponly cookie"; + } + + VLOG(kVlogSetCookies) << error; return false; } @@ -2006,6 +2043,7 @@ CookieItVector cookie_its; num_deleted += GarbageCollectExpired(current, cookies_.equal_range(key), &cookie_its); + if (cookie_its.size() > kDomainMaxCookies) { VLOG(kVlogGarbageCollection) << "Deep Garbage Collect domain."; size_t purge_goal =
diff --git a/net/cookies/cookie_monster.h b/net/cookies/cookie_monster.h index 44f18b8b..d64534e0 100644 --- a/net/cookies/cookie_monster.h +++ b/net/cookies/cookie_monster.h
@@ -168,6 +168,7 @@ bool http_only, bool first_party, bool enforce_prefixes, + bool enforce_strict_secure, CookiePriority priority, const SetCookiesCallback& callback); @@ -466,6 +467,7 @@ bool http_only, bool first_party, bool enforce_prefixes, + bool enforce_strict_secure, CookiePriority priority); CookieList GetAllCookies(); @@ -563,14 +565,17 @@ // Delete any cookies that are equivalent to |ecc| (same path, domain, etc). // If |skip_httponly| is true, httponly cookies will not be deleted. The - // return value with be true if |skip_httponly| skipped an httponly cookie. - // |key| is the key to find the cookie in cookies_; see the comment before - // the CookieMap typedef for details. + // return value will be true if |skip_httponly| skipped an httponly cookie or + // |enforce_strict_secure| is true and the cookie to + // delete was Secure and the scheme of |ecc| is insecure. |key| is the key to + // find the cookie in cookies_; see the comment before the CookieMap typedef + // for details. // NOTE: There should never be more than a single matching equivalent cookie. bool DeleteAnyEquivalentCookie(const std::string& key, const CanonicalCookie& ecc, bool skip_httponly, - bool already_expired); + bool already_expired, + bool enforce_strict_secure); // Takes ownership of *cc. Returns an iterator that points to the inserted // cookie in cookies_. Guarantee: all iterators to cookies_ remain valid.
diff --git a/net/cookies/cookie_monster_unittest.cc b/net/cookies/cookie_monster_unittest.cc index 4c2fc71..4d222f6 100644 --- a/net/cookies/cookie_monster_unittest.cc +++ b/net/cookies/cookie_monster_unittest.cc
@@ -100,6 +100,22 @@ static const bool filters_schemes = true; static const bool has_path_prefix_bug = false; static const int creation_time_granularity_in_ms = 0; + static const bool enforce_strict_secure = false; +}; + +struct CookieMonsterEnforcingSecureCookiesRequireSecureSchemeTestTraits { + static scoped_refptr<CookieStore> Create() { + return new CookieMonster(NULL, NULL); + } + + static const bool is_cookie_monster = true; + static const bool supports_http_only = true; + static const bool supports_non_dotted_domains = true; + static const bool preserves_trailing_dots = true; + static const bool filters_schemes = true; + static const bool has_path_prefix_bug = false; + static const int creation_time_granularity_in_ms = 0; + static const bool enforce_strict_secure = true; }; INSTANTIATE_TYPED_TEST_CASE_P(CookieMonster, @@ -110,8 +126,21 @@ MultiThreadedCookieStoreTest, CookieMonsterTestTraits); -class CookieMonsterTest : public CookieStoreTest<CookieMonsterTestTraits> { +INSTANTIATE_TYPED_TEST_CASE_P( + CookieMonsterSecureCookiesRequireSecureScheme, + CookieStoreTest, + CookieMonsterEnforcingSecureCookiesRequireSecureSchemeTestTraits); + +template <typename T> +class CookieMonsterTestBase : public CookieStoreTest<T> { + public: + using CookieStoreTest<T>::RunFor; + using CookieStoreTest<T>::SetCookie; + protected: + using CookieStoreTest<T>::http_www_google_; + using CookieStoreTest<T>::https_www_google_; + CookieList GetAllCookies(CookieMonster* cm) { DCHECK(cm); GetCookieListCallback callback; @@ -160,7 +189,8 @@ ResultSavingCookieCallback<bool> callback; cm->SetCookieWithDetailsAsync( url, name, value, domain, path, expiration_time, secure, http_only, - first_party_only, false /* enforce prefixes */, priority, + first_party_only, false /* enforce prefixes */, + false /* enforces strict secure cookies */, priority, base::Bind(&ResultSavingCookieCallback<bool>::Run, base::Unretained(&callback))); RunFor(kTimeout); @@ -575,6 +605,10 @@ } }; +using CookieMonsterTest = CookieMonsterTestBase<CookieMonsterTestTraits>; +using CookieMonsterSecureCookiesRequireSecureSchemeTest = CookieMonsterTestBase< + CookieMonsterEnforcingSecureCookiesRequireSecureSchemeTestTraits>; + // TODO(erikwright): Replace the other callbacks and synchronous helper methods // in this test suite with these Mocks. template <typename T, typename C> @@ -671,7 +705,8 @@ cookie_monster->SetCookieWithDetailsAsync( cc.url, cc.name, cc.value, cc.domain, cc.path, cc.expiration_time, cc.secure, cc.http_only, cc.first_party_only, - false /* enforce prefixes */, cc.priority, callback->AsCallback()); + false /* enforce prefixes */, false /* enforces strict secure cookies */, + cc.priority, callback->AsCallback()); } ACTION_P2(GetAllCookiesAction, cookie_monster, callback) { @@ -2475,7 +2510,8 @@ CookiePriority priority = COOKIE_PRIORITY_DEFAULT; cm->SetCookieWithDetailsAsync( url, name, value, domain, path, expiration_time, secure, http_only, - first_party_only, false /* enforce prefixes */, priority, + first_party_only, false /* enforce prefixes */, + false /* enforces strict secure cookies */, priority, base::Bind(&ResultSavingCookieCallback<bool>::Run, base::Unretained(callback))); } @@ -2966,6 +3002,71 @@ CookieMonster::COOKIE_SOURCE_NONSECURE_COOKIE_NONCRYPTOGRAPHIC_SCHEME, 1); } +TEST_F(CookieMonsterSecureCookiesRequireSecureSchemeTest, SetSecureCookies) { + scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL)); + GURL http_url("http://www.google.com"); + GURL http_superdomain_url("http://google.com"); + GURL https_url("https://www.google.com"); + + // A non-secure cookie can be created from either a URL with a secure or + // insecure scheme. + EXPECT_TRUE(SetCookie(cm.get(), http_url, "A=C;")); + EXPECT_TRUE(SetCookie(cm.get(), https_url, "A=B;")); + + // A secure cookie cannot be created from a URL with an insecure scheme. + EXPECT_FALSE(SetCookie(cm.get(), http_url, "A=B; Secure")); + + // A secure cookie can be created from a URL with a secure scheme. + EXPECT_TRUE(SetCookie(cm.get(), https_url, "A=B; Secure")); + + // If a non-secure cookie is created from a URL with an insecure scheme, and a + // secure cookie with the same name already exists, do not update the cookie. + EXPECT_TRUE(SetCookie(cm.get(), https_url, "A=B; Secure")); + EXPECT_FALSE(SetCookie(cm.get(), http_url, "A=C;")); + + // If a non-secure cookie is created from a URL with an secure scheme, and a + // secure cookie with the same name already exists, update the cookie. + EXPECT_TRUE(SetCookie(cm.get(), https_url, "A=B; Secure")); + EXPECT_TRUE(SetCookie(cm.get(), https_url, "A=C;")); + + // If a non-secure cookie is created from a URL with an insecure scheme, and + // a secure cookie with the same name already exists, no matter what the path + // is, do not update the cookie. + EXPECT_TRUE(SetCookie(cm.get(), https_url, "A=B; Secure")); + EXPECT_FALSE(SetCookie(cm.get(), http_url, "A=C; path=/")); + EXPECT_FALSE(SetCookie(cm.get(), http_url, "A=C; path=/my/path")); + + EXPECT_TRUE(SetCookie(cm.get(), https_url, "A=B; Secure; path=/my/path")); + EXPECT_FALSE(SetCookie(cm.get(), http_url, "A=C")); + EXPECT_FALSE(SetCookie(cm.get(), http_url, "A=C; path=/")); + EXPECT_FALSE(SetCookie(cm.get(), http_url, "A=C; path=/my/path")); + + // If a non-secure cookie is created from a URL with an insecure scheme, and + // a secure cookie with the same name already exists, if the domain strings + // domain-match, do not update the cookie. + EXPECT_TRUE(SetCookie(cm.get(), https_url, "A=B; Secure")); + EXPECT_FALSE(SetCookie(cm.get(), http_url, "A=C; domain=google.com")); + EXPECT_FALSE(SetCookie(cm.get(), http_url, "A=C; domain=www.google.com")); + + // Since A=B was set above with no domain string, set a different cookie here + // so the insecure examples aren't trying to overwrite the one above. + EXPECT_TRUE(SetCookie(cm.get(), https_url, "B=C; Secure; domain=google.com")); + EXPECT_FALSE(SetCookie(cm.get(), http_url, "B=D; domain=google.com")); + EXPECT_FALSE(SetCookie(cm.get(), http_url, "B=D")); + EXPECT_FALSE(SetCookie(cm.get(), http_superdomain_url, "B=D")); + + // Verify that if an httponly version of the cookie exists, adding a Secure + // version of the cookie still does not overwrite it. + CookieOptions include_httponly; + include_httponly.set_include_httponly(); + include_httponly.set_enforce_strict_secure(); + EXPECT_TRUE(SetCookieWithOptions(cm.get(), https_url, "C=D; httponly", + include_httponly)); + // Note that the lack of an explicit options object below uses the default, + // which in this case includes "exclude_httponly = true". + EXPECT_FALSE(SetCookie(cm.get(), https_url, "C=E; Secure")); +} + class CookieMonsterNotificationTest : public CookieMonsterTest { public: CookieMonsterNotificationTest()
diff --git a/net/cookies/cookie_options.cc b/net/cookies/cookie_options.cc index 73b7641..42a228f7 100644 --- a/net/cookies/cookie_options.cc +++ b/net/cookies/cookie_options.cc
@@ -12,6 +12,7 @@ : exclude_httponly_(true), include_first_party_only_(false), enforce_prefixes_(false), + enforce_strict_secure_(false), server_time_() {} } // namespace net
diff --git a/net/cookies/cookie_options.h b/net/cookies/cookie_options.h index 1162c96..1f5cc9f8 100644 --- a/net/cookies/cookie_options.h +++ b/net/cookies/cookie_options.h
@@ -41,6 +41,11 @@ void set_enforce_prefixes() { enforce_prefixes_ = true; } bool enforce_prefixes() const { return enforce_prefixes_; } + // TODO(jww): Remove once we decide wether to ship modifying 'secure' cookies + // only from secure schemes. https://crbug.com/546820 + void set_enforce_strict_secure() { enforce_strict_secure_ = true; } + bool enforce_strict_secure() const { return enforce_strict_secure_; } + // |server_time| indicates what the server sending us the Cookie thought the // current time was when the cookie was produced. This is used to adjust for // clock skew between server and host. @@ -55,6 +60,7 @@ bool include_first_party_only_; url::Origin first_party_; bool enforce_prefixes_; + bool enforce_strict_secure_; base::Time server_time_; };
diff --git a/net/cookies/cookie_store_unittest.h b/net/cookies/cookie_store_unittest.h index 0432463..bb8728c 100644 --- a/net/cookies/cookie_store_unittest.h +++ b/net/cookies/cookie_store_unittest.h
@@ -70,6 +70,8 @@ // // different creation times. // static const int creation_time_granularity_in_ms; // +// // The cookie store enforces secure flag requires a secure scheme. +// static const bool enforce_strict_secure; // }; template <class CookieStoreTestTraits> @@ -156,6 +158,8 @@ CookieOptions options; if (!CookieStoreTestTraits::supports_http_only) options.set_include_httponly(); + if (CookieStoreTestTraits::enforce_strict_secure) + options.set_enforce_strict_secure(); return SetCookieWithOptions(cs, url, cookie_line, options); }
diff --git a/net/data/ftp/dir-listing-ls-33 b/net/data/ftp/dir-listing-ls-33 new file mode 100644 index 0000000..2a2e6a28 --- /dev/null +++ b/net/data/ftp/dir-listing-ls-33
@@ -0,0 +1,4 @@ +total -9560322322989056 +-rw-r--r-- 1 stadmin stgroup 4310450 Nov 17 13:12 01643.001.862.TestPermission-DUP0001.zip +-rw-r--r-- 1 stadmin stgroup 2496430080 Nov 13 14:46 I_Base_01_RSE_R720.iso +-rw-r--r-- 1 stadmin stgroup 478576612 Nov 13 08:11 I_Base_01_RSE_R720.zip
diff --git a/net/data/ftp/dir-listing-ls-33.expected b/net/data/ftp/dir-listing-ls-33.expected new file mode 100644 index 0000000..7a54e70 --- /dev/null +++ b/net/data/ftp/dir-listing-ls-33.expected
@@ -0,0 +1,26 @@ +- +01643.001.862.TestPermission-DUP0001.zip +4310450 +1993 +11 +17 +13 +12 + +- +I_Base_01_RSE_R720.iso +2496430080 +1994 +11 +13 +14 +46 + +- +I_Base_01_RSE_R720.zip +478576612 +1994 +11 +13 +8 +11
diff --git a/net/dns/dns_config_service_posix.cc b/net/dns/dns_config_service_posix.cc index 4300dfc..c189951 100644 --- a/net/dns/dns_config_service_posix.cc +++ b/net/dns/dns_config_service_posix.cc
@@ -266,13 +266,17 @@ class DnsConfigServicePosix::ConfigReader : public SerialWorker { public: explicit ConfigReader(DnsConfigServicePosix* service) - : service_(service), success_(false) {} + : service_(service), success_(false) { + const DnsConfig* test_config = service->dns_config_for_testing_; + if (test_config) + dns_config_for_testing_.reset(new DnsConfig(*test_config)); + } void DoWork() override { base::TimeTicks start_time = base::TimeTicks::Now(); ConfigParsePosixResult result = ReadDnsConfig(&dns_config_); - if (service_->dns_config_for_testing_) { - dns_config_ = *service_->dns_config_for_testing_; + if (dns_config_for_testing_) { + dns_config_ = *dns_config_for_testing_; result = CONFIG_PARSE_POSIX_OK; } switch (result) { @@ -306,7 +310,12 @@ private: ~ConfigReader() override {} - DnsConfigServicePosix* service_; + // Raw pointer to owning DnsConfigService. This must never be accessed inside + // DoWork(), since service may be destroyed while SerialWorker is running + // on worker thread. + DnsConfigServicePosix* const service_; + // Dns config value to always return for testing. + scoped_ptr<const DnsConfig> dns_config_for_testing_; // Written in DoWork, read in OnWorkFinished, no locking necessary. DnsConfig dns_config_; bool success_; @@ -318,15 +327,16 @@ class DnsConfigServicePosix::HostsReader : public SerialWorker { public: explicit HostsReader(DnsConfigServicePosix* service) - : service_(service), success_(false) {} + : service_(service), + file_path_hosts_(service->file_path_hosts_), + success_(false) {} private: ~HostsReader() override {} void DoWork() override { base::TimeTicks start_time = base::TimeTicks::Now(); - success_ = - ParseHostsFile(base::FilePath(service_->file_path_hosts_), &hosts_); + success_ = ParseHostsFile(file_path_hosts_, &hosts_); UMA_HISTOGRAM_BOOLEAN("AsyncDNS.HostParseResult", success_); UMA_HISTOGRAM_TIMES("AsyncDNS.HostsParseDuration", base::TimeTicks::Now() - start_time); @@ -340,7 +350,12 @@ } } - DnsConfigServicePosix* service_; + // Raw pointer to owning DnsConfigService. This must never be accessed inside + // DoWork(), since service may be destroyed while SerialWorker is running + // on worker thread. + DnsConfigServicePosix* const service_; + // Hosts file path to parse. + const base::FilePath file_path_hosts_; // Written in DoWork, read in OnWorkFinished, no locking necessary. DnsHosts hosts_; bool success_; @@ -349,8 +364,8 @@ }; DnsConfigServicePosix::DnsConfigServicePosix() - : file_path_hosts_(kFilePathHosts), - dns_config_for_testing_(nullptr), + : file_path_hosts_(kFilePathHosts), // Must set before |hosts_reader_| + dns_config_for_testing_(nullptr), // Must set before |config_reader_| config_reader_(new ConfigReader(this)), hosts_reader_(new HostsReader(this)) #if defined(OS_ANDROID) @@ -408,6 +423,23 @@ const DnsConfig* dns_config) { DCHECK(CalledOnValidThread()); dns_config_for_testing_ = dns_config; + // Reset ConfigReader to bind new DnsConfig for testing. + config_reader_->Cancel(); + config_reader_ = make_scoped_refptr(new ConfigReader(this)); +} + +void DnsConfigServicePosix::SetHostsFilePathForTesting( + const base::FilePath::CharType* file_path) { + DCHECK(CalledOnValidThread()); + file_path_hosts_ = file_path; + // Reset HostsReader to bind new hosts file path. + hosts_reader_->Cancel(); + hosts_reader_ = make_scoped_refptr(new HostsReader(this)); + // If watching, reset to bind new hosts file path and resume watching. + if (watcher_) { + watcher_.reset(new Watcher(this)); + watcher_->Watch(); + } } #if !defined(OS_ANDROID)
diff --git a/net/dns/dns_config_service_posix.h b/net/dns/dns_config_service_posix.h index 0db525d..b9f5fb75 100644 --- a/net/dns/dns_config_service_posix.h +++ b/net/dns/dns_config_service_posix.h
@@ -48,6 +48,7 @@ #endif void SetDnsConfigForTesting(const DnsConfig* dns_config); + void SetHostsFilePathForTesting(const base::FilePath::CharType* file_path); protected: // DnsConfigService: @@ -55,7 +56,6 @@ bool StartWatching() override; private: - friend class DnsConfigServicePosixTest; class Watcher; class ConfigReader; class HostsReader;
diff --git a/net/dns/dns_config_service_posix_unittest.cc b/net/dns/dns_config_service_posix_unittest.cc index 4d2acdd..03a1391 100644 --- a/net/dns/dns_config_service_posix_unittest.cc +++ b/net/dns/dns_config_service_posix_unittest.cc
@@ -41,6 +41,10 @@ }; #endif +void DummyConfigCallback(const DnsConfig& config) { + // Do nothing +} + // Fills in |res| with sane configuration. void InitializeResState(res_state res) { memset(res, 0, sizeof(*res)); @@ -164,6 +168,16 @@ internal::ConvertResStateToDnsConfig(res, &config)); } +TEST(DnsConfigServicePosixTest, DestroyWhileJobsWorking) { + // Regression test to verify crash does not occur if DnsConfigServicePosix + // instance is destroyed while SerialWorker jobs have posted to worker pool. + scoped_ptr<internal::DnsConfigServicePosix> service( + new internal::DnsConfigServicePosix()); + service->ReadConfig(base::Bind(&DummyConfigCallback)); + service.reset(); + base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(1000)); +} + } // namespace #else // OS_ANDROID @@ -198,6 +212,10 @@ service_->SetDnsConfigForTesting(&test_config_); } + void MockHostsFilePath(const char* file_path) { + service_->SetHostsFilePathForTesting(file_path); + } + void SetUp() override { // TODO(pauljensen): Get rid of GetExternalStorageDirectory() when // crbug.com/475568 is fixed. For now creating a temp file in the @@ -226,7 +244,7 @@ void StartWatching() { creation_time_ = base::Time::Now(); service_.reset(new DnsConfigServicePosix()); - service_->file_path_hosts_ = temp_file_.value().c_str(); + MockHostsFilePath(temp_file_.value().c_str()); MockDNSConfig("8.8.8.8"); seen_config_ = false; service_->WatchConfig(base::Bind(
diff --git a/net/ftp/ftp_directory_listing_parser_ls.cc b/net/ftp/ftp_directory_listing_parser_ls.cc index 96d0dc84..b259cad0 100644 --- a/net/ftp/ftp_directory_listing_parser_ls.cc +++ b/net/ftp/ftp_directory_listing_parser_ls.cc
@@ -142,11 +142,12 @@ if (columns.size() == 2 && !received_total_line) { received_total_line = true; + // Some FTP servers incorrectly return a negative integer for "n". Since + // this value is ignored anyway, just check any valid integer was + // provided. int64 total_number; if (!base::StringToInt64(columns[1], &total_number)) return false; - if (total_number < 0) - return false; continue; }
diff --git a/net/ftp/ftp_directory_listing_parser_unittest.cc b/net/ftp/ftp_directory_listing_parser_unittest.cc index b21c8da3..08abf17 100644 --- a/net/ftp/ftp_directory_listing_parser_unittest.cc +++ b/net/ftp/ftp_directory_listing_parser_unittest.cc
@@ -156,6 +156,7 @@ {"dir-listing-ls-30", OK}, {"dir-listing-ls-31", OK}, {"dir-listing-ls-32", OK}, // busybox + {"dir-listing-ls-33", OK}, {"dir-listing-netware-1", OK}, {"dir-listing-netware-2", OK},
diff --git a/net/http/transport_security_state_static.h b/net/http/transport_security_state_static.h index 070063c..7b584bef 100644 --- a/net/http/transport_security_state_static.h +++ b/net/http/transport_security_state_static.h
@@ -2461,1474 +2461,1486 @@ 0xf9, 0xda, 0x75, 0xff, 0xfc, 0x39, 0xee, 0xe4, 0xb1, 0xb0, 0xdf, 0x0b, 0xac, 0xea, 0xc4, 0x6c, 0xa2, 0x7e, 0x8c, 0xef, 0x91, 0x71, 0x31, 0xd7, 0xd9, 0x3f, 0xf2, 0x3a, 0xa6, 0x3c, 0x46, 0x48, 0x6f, 0xbf, 0x08, 0x60, - 0xea, 0x83, 0xc6, 0x72, 0x4b, 0xb1, 0x93, 0xa8, 0xab, 0xfb, 0x5f, 0x63, - 0x90, 0xb2, 0xa8, 0xaa, 0x2a, 0x8a, 0xa2, 0xaa, 0x47, 0xc0, 0x81, 0x40, - 0x2e, 0xfc, 0x2b, 0x64, 0x2b, 0x60, 0x2a, 0xee, 0xe1, 0x57, 0xf3, 0xbf, - 0xa6, 0x85, 0x95, 0xf0, 0xb5, 0xb3, 0x04, 0xaa, 0x2a, 0x8a, 0xa9, 0x16, - 0x88, 0x15, 0x45, 0x51, 0x54, 0x55, 0x15, 0x45, 0x51, 0x55, 0x39, 0xbc, - 0x08, 0x52, 0x05, 0x00, 0x2b, 0x41, 0x5b, 0x42, 0xa8, 0xaa, 0x2a, 0xa4, - 0x5a, 0x68, 0x2a, 0x8a, 0xa2, 0xa8, 0xaa, 0x2a, 0xa4, 0x6a, 0x00, 0x15, - 0xe0, 0xad, 0x80, 0xaa, 0x2a, 0x8a, 0xa2, 0xa8, 0xaa, 0x9c, 0xd4, 0x28, - 0x15, 0xc0, 0xae, 0x85, 0x59, 0x42, 0xa8, 0xaa, 0x2a, 0x8a, 0xa2, 0xa8, - 0x26, 0xa3, 0x70, 0xa0, 0x05, 0x7e, 0x15, 0x45, 0x51, 0x54, 0x55, 0xfb, - 0xb0, 0x0d, 0x61, 0x54, 0x55, 0x48, 0xf3, 0x9a, 0x15, 0xd0, 0xa7, 0x0a, - 0x01, 0x35, 0x9a, 0x55, 0x15, 0x45, 0x51, 0x54, 0x55, 0x48, 0xd4, 0x6e, - 0x14, 0x81, 0x5b, 0x42, 0xa8, 0xaa, 0x2a, 0x8a, 0xa2, 0xaa, 0x46, 0xa0, - 0x21, 0x5d, 0x0a, 0x10, 0xab, 0x74, 0xaa, 0x2a, 0x8a, 0xb4, 0x8a, 0xa2, - 0xb7, 0x2c, 0x28, 0xaa, 0x2a, 0x8a, 0xa2, 0xaa, 0x73, 0xe6, 0x90, 0x52, - 0x83, 0x4d, 0x1a, 0x98, 0x28, 0x01, 0x5e, 0x0a, 0xb6, 0x15, 0x45, 0x51, - 0x56, 0x91, 0x54, 0x56, 0xe5, 0x85, 0x15, 0x45, 0x54, 0x1e, 0x94, 0x82, - 0x90, 0x6b, 0x83, 0x4b, 0x0a, 0xa2, 0xa8, 0xaa, 0x2a, 0x8a, 0xa2, 0xaa, - 0x0d, 0x96, 0xe1, 0x5c, 0x0a, 0x58, 0x50, 0x85, 0x51, 0x54, 0x55, 0x15, - 0x5c, 0x2f, 0xb4, 0x15, 0xe0, 0xaa, 0x2a, 0x8a, 0xa2, 0xa9, 0x65, 0xf0, - 0x85, 0x78, 0x2a, 0xcb, 0x2a, 0x8a, 0xa2, 0xa8, 0x05, 0xa7, 0xe1, 0x54, - 0x55, 0x15, 0x45, 0x51, 0x55, 0x06, 0xa2, 0x60, 0xae, 0x85, 0x7e, 0x15, - 0x50, 0xbf, 0x4b, 0x3b, 0x8c, 0x8f, 0x42, 0x51, 0x8b, 0x6d, 0x6b, 0xdd, - 0x21, 0x19, 0x98, 0xcf, 0x66, 0x39, 0xe4, 0x22, 0xd6, 0x91, 0xd3, 0x87, - 0x65, 0x01, 0xd0, 0xbb, 0x69, 0x9b, 0xcc, 0x3f, 0xbc, 0xed, 0x65, 0x65, - 0x2f, 0x64, 0xb3, 0xe9, 0x26, 0xc2, 0x4d, 0xfa, 0x43, 0x19, 0xa2, 0xe2, - 0x18, 0x55, 0x35, 0x6b, 0xc9, 0x0b, 0x2e, 0x21, 0x8b, 0xe4, 0x6b, 0xf0, - 0xf8, 0x86, 0x5e, 0x40, 0xe1, 0xf1, 0x0c, 0xb2, 0xbb, 0xa3, 0x0f, 0x88, - 0xfd, 0x28, 0xf1, 0x6d, 0xa3, 0x6b, 0x29, 0xe7, 0xed, 0x28, 0xd2, 0xff, - 0x75, 0x19, 0x0f, 0x22, 0x73, 0xaf, 0x26, 0xd6, 0x09, 0xd5, 0xba, 0x23, - 0xa6, 0x39, 0xf1, 0xa5, 0xfb, 0x32, 0x67, 0xfa, 0x75, 0xc0, 0x83, 0xaf, - 0xee, 0x38, 0xfd, 0x80, 0x1d, 0x73, 0xf0, 0xeb, 0x21, 0xcd, 0x2d, 0x6c, - 0xd3, 0xac, 0xb3, 0xae, 0xd9, 0x55, 0x11, 0x2b, 0xc1, 0x5e, 0xa1, 0x38, - 0xf7, 0xd1, 0x0b, 0xfe, 0xec, 0x2f, 0x26, 0x81, 0x9c, 0xeb, 0xff, 0xbe, - 0x3b, 0x43, 0xd8, 0x06, 0x08, 0x0e, 0xb8, 0x10, 0x75, 0x61, 0xec, 0x81, - 0x12, 0xb1, 0x30, 0xc0, 0x2d, 0x7f, 0x09, 0x1b, 0xff, 0x84, 0x62, 0x71, - 0xc4, 0xdb, 0x1b, 0x27, 0x5e, 0x8d, 0xf4, 0x75, 0x39, 0xf0, 0xe9, 0x16, - 0xf3, 0xf2, 0x0e, 0xbf, 0x26, 0xcb, 0x88, 0x0e, 0xa9, 0x1e, 0x12, 0xc6, - 0xaf, 0xfb, 0xeb, 0x87, 0x58, 0xb8, 0x63, 0x3a, 0xf6, 0x6e, 0xc9, 0xd7, - 0xb7, 0x06, 0x70, 0xf6, 0x44, 0xf2, 0xfb, 0x6e, 0x72, 0x47, 0x5e, 0x0b, - 0x89, 0xd4, 0x86, 0xf5, 0xc8, 0xef, 0xff, 0xa3, 0xe3, 0xf3, 0x8e, 0x08, - 0x55, 0x96, 0x59, 0x3a, 0xa1, 0x35, 0xe7, 0x7b, 0xd3, 0x87, 0xe3, 0xf7, - 0xff, 0x7f, 0xf6, 0x6f, 0x91, 0xf5, 0xdb, 0x1d, 0x3a, 0x98, 0x0d, 0xd2, - 0x5c, 0x39, 0x4e, 0xdf, 0x28, 0xc9, 0x43, 0x09, 0xec, 0x85, 0xb3, 0x63, - 0x48, 0xdd, 0x5d, 0x25, 0x2f, 0xb1, 0xa2, 0xcd, 0x0b, 0xae, 0x1b, 0xae, - 0x30, 0x3e, 0xc2, 0xe1, 0xe9, 0x64, 0xe0, 0x32, 0x18, 0xf2, 0x75, 0x09, - 0x7f, 0x47, 0x83, 0xf4, 0xf6, 0xf2, 0xf4, 0xd3, 0xaf, 0x0b, 0x60, 0xea, - 0xf8, 0x6d, 0x90, 0x72, 0xfe, 0x65, 0xf9, 0xc7, 0xdc, 0xeb, 0xff, 0xf6, - 0xb9, 0xc4, 0x9b, 0x5c, 0x8f, 0x23, 0x50, 0x27, 0x52, 0xd1, 0x4a, 0x24, - 0x4c, 0x97, 0x5f, 0x2f, 0xd1, 0xa3, 0xaf, 0xb8, 0x82, 0xa1, 0xd7, 0xfb, - 0xd1, 0xfb, 0x7a, 0x9c, 0x3a, 0xfe, 0xc6, 0xf6, 0x37, 0x91, 0xd7, 0xf2, - 0xf4, 0x8a, 0x79, 0x93, 0xaf, 0xd1, 0xbf, 0x62, 0x47, 0x57, 0x11, 0xae, - 0x24, 0x3e, 0x33, 0xfa, 0x5b, 0xb0, 0x5f, 0x7f, 0xd9, 0xb8, 0xe7, 0xbd, - 0x93, 0x9d, 0x76, 0xfe, 0x3a, 0xfd, 0x83, 0x3a, 0x70, 0xeb, 0xf7, 0x9c, - 0x7f, 0xc3, 0xaf, 0xf6, 0xb1, 0x69, 0xee, 0xb9, 0xd6, 0x8c, 0x44, 0xa7, - 0x05, 0xc4, 0x9b, 0xc4, 0xd7, 0xbe, 0x2d, 0x0e, 0xb8, 0x56, 0x75, 0x48, - 0xd9, 0x68, 0x76, 0xf6, 0xc7, 0x20, 0xeb, 0xfd, 0xc4, 0x98, 0x73, 0x6b, - 0x9d, 0x76, 0xfa, 0xf8, 0x7e, 0x50, 0x43, 0xc1, 0xeb, 0xfe, 0x18, 0x79, - 0xfb, 0x1c, 0x01, 0xd7, 0xf9, 0x38, 0x3e, 0xf6, 0x4e, 0x75, 0xcf, 0xb4, - 0xeb, 0xfa, 0x42, 0x92, 0xee, 0x1d, 0x7e, 0x9d, 0x39, 0x12, 0x3a, 0x94, - 0x44, 0xdc, 0xc6, 0x5c, 0x17, 0x12, 0xbb, 0xec, 0x0a, 0x28, 0x75, 0xff, - 0xe7, 0x4f, 0x47, 0xb5, 0xd7, 0x4e, 0xfe, 0x75, 0xf0, 0x8f, 0xf2, 0x3a, - 0xff, 0xdd, 0x8e, 0x00, 0x71, 0x97, 0x01, 0xd7, 0xb3, 0x26, 0x3a, 0xd9, - 0xd3, 0xd8, 0x01, 0xed, 0xe8, 0xdd, 0x93, 0xaf, 0xdc, 0xfd, 0x6e, 0x27, - 0x57, 0x8f, 0x13, 0xf1, 0xdb, 0xe5, 0xc6, 0x4e, 0x75, 0xfb, 0x36, 0x8c, - 0x6e, 0x75, 0x21, 0xe4, 0xe8, 0x86, 0xfa, 0x07, 0xcd, 0x3a, 0x82, 0xac, - 0x2b, 0x21, 0xa5, 0xc3, 0xee, 0x90, 0xba, 0x40, 0xbc, 0xe9, 0xaf, 0xcd, - 0x9b, 0x24, 0x37, 0xf8, 0x1f, 0x70, 0x43, 0xd8, 0x3a, 0xa1, 0x17, 0x0f, - 0x08, 0x5b, 0xfb, 0x58, 0xb4, 0xec, 0x1d, 0x7b, 0x79, 0x68, 0xea, 0xdc, - 0xf2, 0x38, 0x57, 0x7b, 0x40, 0x64, 0xea, 0x83, 0xc0, 0xc2, 0x3b, 0xef, - 0xdf, 0x92, 0x3a, 0xfa, 0x3f, 0x60, 0xe8, 0xab, 0xf4, 0x95, 0x65, 0x96, - 0x4e, 0xa1, 0x3d, 0x2f, 0xc9, 0xaf, 0x9f, 0xcb, 0xf1, 0xd4, 0x14, 0x5b, - 0xe3, 0xa0, 0x08, 0xaf, 0xf7, 0xd1, 0x17, 0x65, 0xfa, 0x75, 0x43, 0x24, - 0x33, 0x0c, 0x12, 0x1f, 0x1c, 0x4e, 0x5c, 0x33, 0x1e, 0x1c, 0x80, 0x97, - 0xfe, 0x30, 0xae, 0xfe, 0x1a, 0xec, 0x97, 0xde, 0x62, 0x18, 0x9b, 0x00, - 0xeb, 0xd2, 0x17, 0x3a, 0xdb, 0xb1, 0x07, 0x8b, 0x05, 0x77, 0xbc, 0xe0, - 0x3a, 0xfe, 0x8e, 0x4f, 0x1c, 0x9c, 0xeb, 0xff, 0x40, 0xfb, 0xbf, 0xbc, - 0xa5, 0x07, 0x5f, 0xbf, 0x06, 0x0b, 0x4e, 0xbd, 0xc8, 0x98, 0xeb, 0xe4, - 0x17, 0x98, 0xeb, 0xff, 0x0c, 0x29, 0xd7, 0xf7, 0xdc, 0x01, 0xd7, 0xc9, - 0xae, 0x61, 0xd7, 0xfb, 0xd9, 0xf6, 0x26, 0x4d, 0x1d, 0x53, 0xa6, 0xf9, - 0x21, 0xb0, 0x97, 0x70, 0xf5, 0x64, 0xfd, 0x1c, 0x12, 0x0f, 0x1f, 0xed, - 0x20, 0xbf, 0xe8, 0x4e, 0xc2, 0xe7, 0xc6, 0x4e, 0xbf, 0xa3, 0xa9, 0x3b, - 0x89, 0xd7, 0xfd, 0x38, 0xe4, 0xbb, 0x80, 0xd1, 0xd7, 0xfe, 0xc1, 0xde, - 0x5a, 0xe7, 0xf0, 0x03, 0xaf, 0xd9, 0xed, 0x62, 0x87, 0x52, 0x1f, 0x32, - 0xcf, 0xef, 0xe1, 0xf7, 0xce, 0xe6, 0xc1, 0xd7, 0x83, 0x1b, 0x4e, 0xbf, - 0xfe, 0xc1, 0x18, 0x64, 0x23, 0x1b, 0xc9, 0x04, 0xeb, 0xff, 0xcf, 0xf2, - 0x69, 0x47, 0x27, 0xf8, 0xce, 0x74, 0xea, 0x84, 0x75, 0x04, 0xc7, 0xa3, - 0xa2, 0x99, 0x7f, 0xcb, 0xee, 0x7b, 0x3f, 0xe4, 0xe7, 0x5f, 0xff, 0x28, - 0xfe, 0xd2, 0x0c, 0xd0, 0xde, 0x66, 0xe7, 0x5f, 0xf4, 0x7b, 0x38, 0xd7, - 0x76, 0x9a, 0x2f, 0x8b, 0xf6, 0x72, 0x37, 0x91, 0xd7, 0xbb, 0x0b, 0x69, - 0xf5, 0x79, 0x0e, 0xff, 0xfc, 0x2d, 0xf9, 0xd8, 0x4e, 0x22, 0xd3, 0x66, - 0x16, 0x75, 0xe7, 0xe4, 0xe6, 0x8b, 0xfe, 0xa1, 0x16, 0x78, 0x66, 0xd5, - 0x7b, 0xff, 0xfd, 0xd7, 0xd2, 0x46, 0xbe, 0x7b, 0xb8, 0xbc, 0x6b, 0xf0, - 0xeb, 0xa3, 0x60, 0xeb, 0xed, 0x69, 0xd6, 0x75, 0x75, 0x13, 0x20, 0x60, - 0xf0, 0xc5, 0xf6, 0xf2, 0xf3, 0x9d, 0x7f, 0xfc, 0x16, 0xf5, 0x07, 0x36, - 0xbc, 0xb4, 0x81, 0x3a, 0xd2, 0xc3, 0xf1, 0x72, 0x2b, 0xfe, 0x85, 0xfc, - 0x0e, 0x60, 0x34, 0x75, 0xff, 0x26, 0x08, 0x54, 0x4c, 0xe1, 0xd4, 0x87, - 0xdf, 0xb0, 0x73, 0x7b, 0xd9, 0xb9, 0xd7, 0xf3, 0xf3, 0x79, 0x67, 0x8e, - 0xbf, 0xf7, 0xb4, 0x9c, 0xf0, 0xfe, 0xf2, 0x3a, 0xff, 0xf2, 0xe3, 0x67, - 0x3f, 0x1c, 0xcd, 0xb1, 0xb9, 0xd7, 0xfe, 0x8c, 0xe6, 0x70, 0x0b, 0x4d, - 0x1d, 0x79, 0xf7, 0xd8, 0x3a, 0xfe, 0x7f, 0x6a, 0x32, 0x73, 0xaa, 0x13, - 0x3f, 0xc2, 0xd4, 0x3e, 0x14, 0xdd, 0xa7, 0x8c, 0x8f, 0xdf, 0xf7, 0xf0, - 0xbd, 0x62, 0xe1, 0x8c, 0xeb, 0xff, 0x72, 0x7c, 0x0e, 0x77, 0xb8, 0xc6, - 0x75, 0xff, 0xb0, 0x7d, 0xaf, 0xbb, 0x63, 0x37, 0x3a, 0xb1, 0x10, 0x5a, - 0x41, 0xbf, 0xfe, 0x94, 0x72, 0x7f, 0x22, 0x9a, 0xd3, 0x8c, 0x8e, 0xbf, - 0xa7, 0xd6, 0x2e, 0x18, 0xce, 0xb3, 0x33, 0x22, 0x03, 0xea, 0x85, 0xe4, - 0xea, 0x1d, 0x7d, 0x2e, 0x06, 0x47, 0x5f, 0x2f, 0xc9, 0x39, 0xd5, 0x87, - 0x88, 0x84, 0x57, 0xff, 0x6d, 0xf2, 0x90, 0x32, 0xce, 0xa2, 0xce, 0xba, - 0x7f, 0x1d, 0x7f, 0xb6, 0xf5, 0xe5, 0x18, 0x27, 0x54, 0x1e, 0x4e, 0x0b, - 0xdf, 0xff, 0xa5, 0xd8, 0xe3, 0xfb, 0xff, 0x27, 0xb5, 0xd4, 0x3a, 0xfe, - 0xc6, 0x7e, 0xf5, 0xfc, 0x75, 0xff, 0xfb, 0xdf, 0x65, 0x1b, 0x50, 0x41, - 0xc4, 0x85, 0xe1, 0x57, 0xdd, 0xfb, 0xbf, 0x8e, 0xbf, 0x62, 0xf1, 0x36, - 0x9d, 0x7a, 0x79, 0x98, 0xce, 0xa8, 0x4d, 0x1e, 0x75, 0x5c, 0x2f, 0x6a, - 0xb2, 0x12, 0xfe, 0x4f, 0x77, 0xb0, 0xeb, 0xf7, 0x12, 0x77, 0x59, 0xa6, - 0x13, 0xbe, 0xf7, 0xf0, 0xe6, 0x98, 0x4e, 0xe0, 0x41, 0xa8, 0x13, 0xbf, - 0xc2, 0xea, 0x7a, 0x38, 0x03, 0x50, 0x27, 0x7f, 0xb5, 0x9d, 0x4d, 0x7f, - 0x39, 0xa6, 0x13, 0xbb, 0x02, 0x69, 0x84, 0xee, 0x65, 0x93, 0xcc, 0x27, - 0x58, 0x9a, 0x5e, 0xe6, 0x88, 0x5c, 0xb2, 0x2d, 0x1f, 0xed, 0x41, 0x64, - 0x8a, 0xde, 0x2c, 0xc2, 0x65, 0x4f, 0x9e, 0xc9, 0xba, 0x7e, 0xec, 0xc7, - 0x8f, 0x50, 0xba, 0x3e, 0x85, 0xbd, 0x5e, 0x72, 0x01, 0x84, 0x76, 0xa3, - 0x67, 0xf4, 0xa4, 0xeb, 0xc2, 0x05, 0x9d, 0x7f, 0xd1, 0xff, 0x85, 0x36, - 0xfd, 0x59, 0xd7, 0x87, 0x35, 0x87, 0xaf, 0xc1, 0xbb, 0xc1, 0x04, 0xc7, - 0x54, 0x33, 0xbd, 0xa7, 0x84, 0xf0, 0x63, 0x0b, 0xc3, 0xb5, 0x0e, 0x9b, - 0x1b, 0x6a, 0x43, 0x1e, 0x68, 0x50, 0xf2, 0x12, 0xab, 0x24, 0xec, 0x6b, - 0x62, 0xaf, 0xa8, 0x5e, 0xfa, 0x77, 0x07, 0x6c, 0x33, 0x3e, 0x98, 0xdf, - 0x83, 0x9c, 0x45, 0x0e, 0xbf, 0xbb, 0x1f, 0x47, 0x70, 0x1d, 0x79, 0x11, - 0x43, 0xaf, 0xde, 0xc9, 0x91, 0x67, 0x5f, 0xa3, 0x70, 0x02, 0x0e, 0xa8, - 0x3c, 0xe1, 0x27, 0xbf, 0x46, 0xd8, 0x1f, 0x1d, 0x7e, 0x4d, 0xbe, 0x49, - 0xce, 0xbf, 0x3c, 0xbd, 0x8d, 0x3a, 0xfc, 0x39, 0xf7, 0x26, 0x3a, 0xff, - 0xf8, 0x5a, 0x8b, 0x0f, 0xef, 0xc9, 0x66, 0xfe, 0x3a, 0xff, 0xf6, 0x03, - 0x5d, 0x4f, 0x9b, 0xca, 0x32, 0x73, 0xaf, 0xfb, 0xae, 0xbe, 0xa4, 0x6f, - 0x23, 0xaf, 0xef, 0xa3, 0x2d, 0x97, 0x9c, 0xea, 0x84, 0xc1, 0xa4, 0xa0, - 0x89, 0x80, 0x38, 0xa9, 0xd5, 0x00, 0x04, 0x81, 0xa4, 0xfc, 0x29, 0x12, - 0x6f, 0x46, 0x5d, 0x7f, 0xec, 0x7e, 0xcc, 0x83, 0xdc, 0xdc, 0xeb, 0xf8, - 0x13, 0x4a, 0x3d, 0xa3, 0xaf, 0xff, 0xff, 0xd9, 0xdc, 0x10, 0x60, 0xfb, - 0xb9, 0xd8, 0xc9, 0x93, 0x93, 0x75, 0x37, 0xf1, 0xd7, 0xc3, 0x18, 0xc9, - 0xd7, 0xd1, 0xbe, 0x9c, 0xea, 0x86, 0xd4, 0xf6, 0x78, 0x40, 0x84, 0xe3, - 0x29, 0xe4, 0x29, 0x18, 0xc3, 0x19, 0x3f, 0x0b, 0xde, 0x53, 0x48, 0xaf, - 0xf8, 0xf7, 0xf2, 0xed, 0xb0, 0x81, 0xfa, 0x41, 0x7f, 0xfc, 0x83, 0x8b, - 0x8f, 0xa3, 0xfc, 0x87, 0x16, 0x75, 0xff, 0x05, 0x30, 0x7f, 0x96, 0x68, - 0xeb, 0x7e, 0x75, 0xff, 0x75, 0x25, 0xd7, 0x92, 0x2c, 0xeb, 0xff, 0x69, - 0x07, 0x79, 0x79, 0x34, 0x87, 0x56, 0x1f, 0xa7, 0x8d, 0xef, 0xda, 0x5c, - 0x06, 0x0e, 0xa9, 0x26, 0xa3, 0x89, 0xd3, 0x1b, 0xae, 0x10, 0xbe, 0x21, - 0xbe, 0x18, 0xe4, 0x8e, 0xbf, 0xee, 0xc4, 0x90, 0x47, 0xfd, 0xce, 0xbf, - 0xe8, 0xcf, 0x7d, 0x00, 0x23, 0x73, 0xad, 0xc8, 0x44, 0x96, 0x10, 0x2c, - 0xe2, 0xfe, 0x18, 0x6f, 0x22, 0x47, 0x5f, 0xff, 0x75, 0xd3, 0xd2, 0xfc, - 0x7d, 0xae, 0xbc, 0x8e, 0xfa, 0x6a, 0xef, 0xfd, 0xaf, 0xbe, 0x41, 0xfe, - 0x59, 0xa3, 0xae, 0x0e, 0x8e, 0xa6, 0x34, 0x5b, 0xf5, 0x84, 0x50, 0x2f, - 0xff, 0xec, 0xdf, 0x34, 0xe3, 0xd4, 0x8f, 0x77, 0xf7, 0x59, 0xd5, 0x09, - 0xd0, 0xbc, 0x62, 0xc2, 0x65, 0x7f, 0x0f, 0xeb, 0x4e, 0xc1, 0xd7, 0xff, - 0xe7, 0x1f, 0x3b, 0xf4, 0x63, 0xda, 0x67, 0x3a, 0x75, 0xff, 0xa7, 0x71, - 0xd7, 0xba, 0x91, 0xa3, 0xaf, 0xfa, 0x01, 0xa0, 0xfe, 0xfc, 0x91, 0xd7, - 0xb9, 0xad, 0x1e, 0x20, 0x3b, 0xe6, 0xbb, 0xb4, 0xd1, 0x01, 0xaa, 0x6a, - 0x6f, 0xee, 0x47, 0x63, 0xe6, 0x49, 0x14, 0x1c, 0x62, 0xa7, 0x4c, 0x8f, - 0xec, 0x37, 0x68, 0x09, 0xcf, 0xfa, 0x37, 0x5b, 0xdb, 0x63, 0xa7, 0x56, - 0x2a, 0x12, 0x48, 0xf2, 0xfe, 0x95, 0x5e, 0xeb, 0xb1, 0x9d, 0x7d, 0x00, - 0xd9, 0xc3, 0xa8, 0x07, 0x83, 0xe1, 0xeb, 0xe1, 0xf0, 0x3f, 0x3a, 0xfc, - 0xb6, 0x21, 0x88, 0x62, 0x18, 0xa3, 0xaf, 0xff, 0xe9, 0x66, 0x93, 0x9c, - 0x45, 0xfd, 0xf7, 0x71, 0x9f, 0x1d, 0x58, 0x8b, 0xb4, 0x22, 0x73, 0xcb, - 0xff, 0xcc, 0xe0, 0xfb, 0x06, 0x59, 0xaf, 0xab, 0x3a, 0xff, 0xf4, 0xb3, - 0x79, 0x7d, 0x80, 0x2a, 0xcb, 0x2c, 0x95, 0x7e, 0x5b, 0x38, 0x9b, 0x4e, - 0xbd, 0x2c, 0x19, 0x8f, 0xeb, 0xea, 0x8d, 0x42, 0x3e, 0x5e, 0x18, 0x95, - 0x0a, 0x8a, 0x7b, 0x0d, 0xd1, 0x8c, 0x9a, 0xff, 0x90, 0x65, 0xa6, 0x24, - 0xc5, 0x31, 0x0c, 0x51, 0xd7, 0xd3, 0x6b, 0x26, 0x3a, 0xfc, 0x08, 0xf6, - 0x31, 0x9d, 0x7f, 0xa3, 0x38, 0xd7, 0x76, 0x9a, 0x20, 0x9b, 0xfe, 0x8f, - 0x67, 0x1a, 0xee, 0xd3, 0x45, 0xf3, 0x7e, 0x70, 0xf6, 0x14, 0x3a, 0xf0, - 0xe6, 0x82, 0x8a, 0x76, 0x9e, 0xad, 0x0e, 0x85, 0x31, 0x0d, 0xb0, 0xd0, - 0xbf, 0xfa, 0x3a, 0x8a, 0x67, 0x27, 0x5f, 0xfb, 0x9d, 0x58, 0x9d, 0x22, - 0x46, 0x67, 0xd2, 0xab, 0xfd, 0xff, 0x76, 0x7a, 0x8d, 0xe9, 0xd7, 0xfe, - 0x9d, 0xf7, 0xd9, 0xcf, 0x0b, 0xed, 0x3a, 0xff, 0xfb, 0x3d, 0x03, 0xed, - 0x66, 0x28, 0xa3, 0xc8, 0xeb, 0xff, 0x60, 0x62, 0x51, 0xdc, 0x03, 0x9d, - 0x7f, 0x3c, 0xbf, 0x93, 0x84, 0xeb, 0xcc, 0xb2, 0xc9, 0x57, 0xee, 0xe3, - 0x5f, 0x85, 0x2a, 0x5f, 0xdf, 0xff, 0xe9, 0xb9, 0x1b, 0x7e, 0x28, 0xff, - 0x3e, 0xcd, 0xaf, 0x99, 0xbf, 0x8e, 0xaf, 0x22, 0x97, 0xe9, 0xb5, 0xff, - 0xe4, 0xe2, 0x7b, 0xfc, 0xf3, 0xaf, 0x04, 0xea, 0x9d, 0x51, 0x4b, 0x50, - 0xd6, 0x9c, 0x03, 0xb1, 0x87, 0x8f, 0x89, 0x6f, 0xfc, 0xb8, 0xdf, 0x43, - 0x93, 0xfd, 0x91, 0xd7, 0xff, 0xf9, 0x3a, 0xe3, 0xbc, 0xbe, 0xca, 0x06, - 0x4e, 0xbc, 0x09, 0xd7, 0xff, 0xb3, 0x3a, 0x1e, 0xc6, 0xb3, 0xa8, 0x03, - 0xaf, 0xf2, 0x9f, 0x26, 0x94, 0x73, 0x47, 0x54, 0xe9, 0x8f, 0xc9, 0x04, - 0x2c, 0x08, 0x8f, 0x7f, 0x31, 0xe4, 0xbb, 0x1c, 0x3a, 0xff, 0x7a, 0x13, - 0xaa, 0x46, 0xe7, 0x5f, 0xfe, 0xdc, 0x7e, 0x37, 0xa8, 0x00, 0x47, 0x24, - 0x75, 0x42, 0x2b, 0x90, 0xbf, 0xe9, 0x9d, 0xfc, 0x9a, 0xc0, 0xfd, 0xc3, - 0xaf, 0xdb, 0x08, 0x39, 0xb4, 0xeb, 0xfd, 0xcc, 0x0a, 0x7e, 0xde, 0xb4, - 0xf5, 0xdc, 0xb6, 0xff, 0x68, 0x73, 0x6f, 0x5e, 0x47, 0x5e, 0xd4, 0xb6, - 0x9d, 0x48, 0x7a, 0x2c, 0x66, 0x77, 0xff, 0xa2, 0x7f, 0xbd, 0x8d, 0xfd, - 0x93, 0x88, 0x4e, 0xa4, 0x4c, 0x31, 0xe1, 0x36, 0x24, 0x97, 0xfa, 0x30, - 0x7c, 0xc0, 0x65, 0xa7, 0x5f, 0xee, 0xe6, 0xdf, 0x9a, 0x93, 0x4e, 0xb7, - 0xfa, 0x3e, 0xdf, 0x1b, 0x5f, 0xe7, 0x1f, 0x9f, 0x79, 0xd7, 0x3a, 0xfd, - 0x9c, 0x7d, 0xd9, 0x3a, 0xff, 0xff, 0x4f, 0x8c, 0x8e, 0x07, 0x89, 0xfc, - 0xe1, 0xec, 0x0c, 0xe7, 0x54, 0xe8, 0x8b, 0xd1, 0x45, 0xe6, 0x59, 0x64, - 0xab, 0xfd, 0xf4, 0x10, 0x39, 0xbf, 0x8a, 0x54, 0xbf, 0xbf, 0xff, 0x98, - 0x3f, 0x1b, 0xd4, 0x08, 0x71, 0x9f, 0x9e, 0xd6, 0x4e, 0x75, 0x75, 0x15, - 0x3f, 0xa2, 0x52, 0x26, 0x20, 0xf0, 0xec, 0xa9, 0xd9, 0x68, 0x52, 0x8f, - 0xc4, 0x26, 0xa9, 0x29, 0x83, 0x91, 0xbe, 0xae, 0x1d, 0x9d, 0x8e, 0x4c, - 0x61, 0x41, 0xa2, 0x9f, 0x47, 0xa1, 0x7f, 0xec, 0x41, 0x9d, 0xc7, 0xd8, - 0xb3, 0xaf, 0xff, 0x71, 0x4f, 0xbe, 0x4d, 0x0e, 0x6d, 0x40, 0x9d, 0x7f, - 0xc8, 0xc8, 0x7b, 0x9e, 0xd9, 0xc3, 0xaa, 0x11, 0x11, 0xd4, 0xdb, 0xe1, - 0x7d, 0xfc, 0x75, 0xec, 0x10, 0x1d, 0x7d, 0x9e, 0x9a, 0x47, 0x5f, 0xfd, - 0xb0, 0x31, 0xb1, 0xa7, 0x1f, 0xa0, 0xd1, 0xd5, 0xd3, 0xec, 0x72, 0x2b, - 0xff, 0x67, 0xa3, 0x9a, 0xec, 0x0f, 0x8f, 0x10, 0x45, 0xfd, 0x9c, 0x6b, - 0xbb, 0x4d, 0x10, 0x42, 0xa7, 0x93, 0x7a, 0x02, 0x87, 0x54, 0x1f, 0x26, - 0x92, 0xaf, 0x6d, 0x85, 0x9d, 0x7f, 0x3f, 0x79, 0xc4, 0x64, 0xeb, 0xf9, - 0x8c, 0x2c, 0xb8, 0xc8, 0xea, 0xc3, 0xfa, 0x11, 0xdf, 0xcb, 0x6f, 0xff, - 0xd0, 0x19, 0xa4, 0x83, 0xe8, 0x04, 0xc2, 0x93, 0x1d, 0x53, 0xaa, 0x93, - 0x50, 0x87, 0xb0, 0x86, 0x04, 0x33, 0x86, 0x13, 0x7b, 0x4b, 0xaf, 0xee, - 0xe7, 0xbc, 0x8b, 0x3a, 0xfe, 0xf7, 0xdc, 0xeb, 0xee, 0x75, 0x6e, 0x7b, - 0x62, 0x59, 0x7f, 0x66, 0xfe, 0xe7, 0x20, 0xeb, 0xff, 0xb4, 0x2f, 0xe7, - 0x5f, 0xd8, 0x9f, 0x0e, 0xa0, 0x9f, 0x8e, 0x8b, 0x6a, 0x11, 0x6b, 0xfc, - 0x24, 0xef, 0xec, 0x6f, 0xdd, 0xbd, 0xc3, 0xae, 0x85, 0x0e, 0xb9, 0x04, - 0xeb, 0x32, 0x75, 0x04, 0xd2, 0xfd, 0x14, 0xbc, 0x3f, 0xce, 0x75, 0xfb, - 0xaf, 0x2c, 0x13, 0xaf, 0xe4, 0xf0, 0xe7, 0x50, 0xeb, 0xb3, 0xbf, 0x0f, - 0x3e, 0x09, 0x6e, 0x76, 0x7e, 0x23, 0xe3, 0x0e, 0xfa, 0x47, 0xe6, 0xca, - 0x92, 0x73, 0x58, 0x50, 0x31, 0x94, 0x5f, 0xda, 0x40, 0x87, 0x04, 0xeb, - 0xff, 0xfb, 0xdd, 0xcd, 0x6b, 0x33, 0xfe, 0x4f, 0x9f, 0x8f, 0x8e, 0xbf, - 0xee, 0xc7, 0x3c, 0x31, 0x9b, 0x9d, 0x7f, 0xff, 0xc9, 0x3c, 0x4b, 0x5c, - 0xe2, 0x6f, 0x34, 0x9f, 0x8b, 0xcd, 0xce, 0xbf, 0xd0, 0xf3, 0xbf, 0x1f, - 0xe9, 0xd7, 0xbb, 0x82, 0x14, 0x69, 0xf4, 0xdf, 0xcd, 0x35, 0x89, 0xcd, - 0x21, 0x5f, 0xa3, 0x2f, 0xbf, 0xf3, 0x7b, 0x19, 0xc9, 0x6b, 0xf5, 0x9d, - 0x72, 0x68, 0xeb, 0xfe, 0xc9, 0xdf, 0xc0, 0xfa, 0x32, 0x3a, 0xfe, 0x7f, - 0x7c, 0x89, 0x28, 0x75, 0xfd, 0xf5, 0x7a, 0x65, 0xf7, 0x3a, 0xa1, 0x32, - 0x3c, 0x35, 0x50, 0xff, 0x82, 0xae, 0x75, 0xe2, 0xfb, 0xdc, 0xce, 0x9d, - 0x7b, 0x48, 0xb3, 0xad, 0x1c, 0x36, 0xde, 0x1b, 0xbf, 0xfb, 0xa9, 0x03, - 0xf1, 0xc6, 0x48, 0xb3, 0xaf, 0x92, 0x64, 0x64, 0xeb, 0xff, 0x96, 0xfb, - 0xfd, 0xf2, 0x72, 0x3f, 0x60, 0x9d, 0x7f, 0xfe, 0xfe, 0x71, 0x8c, 0xea, - 0xb1, 0xec, 0xef, 0xfc, 0x3a, 0xfb, 0xda, 0xfb, 0xaf, 0x89, 0x83, 0x05, - 0x0b, 0x08, 0xbe, 0xa5, 0xdf, 0xb4, 0xbc, 0xf6, 0x8e, 0xbf, 0xf9, 0x14, - 0xcf, 0x27, 0x73, 0xd1, 0xc3, 0xaf, 0xcf, 0x21, 0x48, 0x3a, 0xfe, 0x87, - 0x1f, 0x60, 0x9d, 0x52, 0x54, 0x7b, 0x91, 0x96, 0x22, 0xdf, 0x09, 0xd6, - 0x84, 0x24, 0x97, 0xf3, 0x7a, 0x9b, 0x28, 0xa1, 0xd7, 0xff, 0x90, 0x11, - 0xa5, 0xc2, 0x73, 0x88, 0xc9, 0xd7, 0xcc, 0x7d, 0xc9, 0xce, 0xbf, 0xd0, - 0x1c, 0xf2, 0x77, 0xf3, 0xac, 0xb8, 0x3d, 0x70, 0x92, 0xdf, 0xff, 0xf9, - 0x6e, 0x20, 0x92, 0x6b, 0xf5, 0xf5, 0x23, 0xdd, 0xfd, 0xd6, 0x75, 0xff, - 0xf0, 0xff, 0xe9, 0x20, 0x3a, 0xe9, 0xe7, 0x59, 0xd7, 0x7c, 0x63, 0x3a, - 0xff, 0xfc, 0xe9, 0xe4, 0x0e, 0x07, 0x3c, 0x8b, 0x4e, 0x1d, 0x7f, 0xfa, - 0x1a, 0x1c, 0xfb, 0xe4, 0xe4, 0x7e, 0xc1, 0x3a, 0xf7, 0x1f, 0x58, 0x98, - 0x4f, 0x13, 0xba, 0x36, 0x2a, 0x37, 0x27, 0x9d, 0x3c, 0x2f, 0xe3, 0x75, - 0xba, 0x50, 0x75, 0xff, 0xe9, 0xc3, 0xd8, 0xee, 0x6e, 0x0c, 0xf6, 0x8e, - 0xa7, 0x3e, 0x0f, 0xc5, 0x68, 0x2a, 0xdb, 0xf0, 0xc1, 0x21, 0x3e, 0xf1, - 0xf4, 0x8c, 0x25, 0x6f, 0xee, 0x44, 0xe8, 0x3e, 0x3a, 0xf0, 0x7e, 0xac, - 0xeb, 0xf0, 0xc0, 0x72, 0x63, 0xaf, 0xb5, 0xff, 0x14, 0x3a, 0xfd, 0x1d, - 0xf4, 0x48, 0xeb, 0xe0, 0xff, 0xed, 0x41, 0xf8, 0x6e, 0x4c, 0x02, 0x4b, - 0xf0, 0x31, 0x71, 0xd3, 0xaf, 0xef, 0xe3, 0xe7, 0x06, 0x47, 0x5e, 0x60, - 0xf7, 0x0e, 0xa0, 0xa6, 0xed, 0x85, 0x89, 0x08, 0xe1, 0x48, 0xf1, 0x37, - 0xe5, 0xf7, 0xb9, 0xf7, 0x47, 0x5d, 0x0c, 0x3c, 0xeb, 0xff, 0x38, 0xb7, - 0x38, 0xd7, 0x76, 0x9a, 0x21, 0x1b, 0xa5, 0x39, 0xd5, 0x08, 0x98, 0x00, - 0xf7, 0xe3, 0x7b, 0x52, 0x2f, 0xd9, 0x3e, 0x80, 0xe7, 0x5f, 0xff, 0xfe, - 0xee, 0x7f, 0xc5, 0x3a, 0x9b, 0xc7, 0xbf, 0xe8, 0xe6, 0xfe, 0xfd, 0xf4, - 0x75, 0xff, 0xd9, 0xbf, 0xdf, 0x20, 0xff, 0x2c, 0xd1, 0xd7, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xec, 0x19, 0xc5, 0xc3, 0x03, 0x3c, 0x70, 0x38, 0x39, - 0xed, 0x23, 0x70, 0x7e, 0xcf, 0x9c, 0x8d, 0x0b, 0xa9, 0xac, 0x40, 0x03, - 0xf0, 0x0b, 0x86, 0x06, 0x78, 0xe1, 0xd5, 0x09, 0xa7, 0x62, 0x35, 0xff, - 0xde, 0x71, 0x9f, 0x79, 0x0c, 0x66, 0x8e, 0xbf, 0xf7, 0xdc, 0xeb, 0xad, - 0x56, 0x59, 0x64, 0xeb, 0xff, 0xf6, 0x37, 0xb0, 0x21, 0x14, 0x9f, 0x05, - 0x14, 0x3a, 0xe7, 0x79, 0xd1, 0x2d, 0x24, 0x4b, 0xff, 0xfa, 0x61, 0x80, - 0x69, 0xbd, 0x4e, 0x4c, 0x30, 0x0d, 0x1d, 0x7f, 0xf7, 0xba, 0x9b, 0x7a, - 0xf2, 0xe4, 0x28, 0x75, 0xfd, 0xff, 0x93, 0xf1, 0x50, 0xeb, 0xfb, 0x19, - 0xc1, 0xfc, 0x07, 0x5f, 0xa5, 0x9e, 0x80, 0x1d, 0x74, 0x2e, 0x73, 0xd3, - 0xdc, 0xb6, 0xff, 0xff, 0xe0, 0x2d, 0xe5, 0xd7, 0x4f, 0x20, 0x70, 0x39, - 0xe4, 0x5a, 0x70, 0xea, 0xd2, 0x27, 0x7f, 0x2f, 0xbf, 0xff, 0x0e, 0x6b, - 0x3a, 0xfb, 0x0d, 0xea, 0x2e, 0x1a, 0x75, 0xfa, 0x75, 0xc0, 0x60, 0xea, - 0x92, 0xea, 0x98, 0x63, 0xca, 0xdc, 0x8a, 0x68, 0x6c, 0xf0, 0xbb, 0xab, - 0x7a, 0x46, 0xf4, 0x63, 0xfb, 0x49, 0x3e, 0xaa, 0xdf, 0xe8, 0xd6, 0xa2, - 0x7c, 0x64, 0xeb, 0xfd, 0xdc, 0x5e, 0x77, 0xf1, 0x3a, 0x82, 0x7c, 0xbe, - 0x33, 0xbe, 0xce, 0x28, 0x87, 0x54, 0x2f, 0x63, 0xe4, 0xeb, 0xd3, 0xc6, - 0x15, 0xf9, 0x15, 0xe6, 0x59, 0x64, 0xab, 0xfe, 0xc0, 0x3f, 0x33, 0x6e, - 0x04, 0xa5, 0x4b, 0xfb, 0x99, 0x64, 0xab, 0xcc, 0xb2, 0xc9, 0x57, 0xf3, - 0xce, 0x1e, 0xc6, 0x8a, 0x54, 0xbf, 0xa1, 0x45, 0xe3, 0x29, 0x1b, 0x26, - 0xf7, 0xe6, 0xa0, 0x7e, 0xac, 0xa5, 0x4d, 0x9d, 0xe6, 0x59, 0x64, 0xab, - 0xda, 0x8e, 0x14, 0xa9, 0x7f, 0x7c, 0xe3, 0xbf, 0x8e, 0xb0, 0x11, 0x14, - 0xbe, 0x59, 0x64, 0xae, 0xfe, 0x08, 0xc4, 0x9d, 0xa7, 0x5f, 0xb5, 0xfc, - 0xfb, 0x22, 0x75, 0xf8, 0x29, 0xb6, 0x02, 0x75, 0xf6, 0x0e, 0x31, 0x9d, - 0x5c, 0x3c, 0xa5, 0x94, 0x52, 0x22, 0x63, 0xeb, 0xb5, 0xff, 0xdd, 0x79, - 0x0b, 0xa9, 0x30, 0xa4, 0xc7, 0x5f, 0xfd, 0x9c, 0x9e, 0x37, 0xd2, 0x0e, - 0x00, 0xeb, 0xfb, 0xb9, 0xb7, 0x3d, 0xa3, 0xa9, 0xa8, 0xb5, 0x02, 0x27, - 0x90, 0xeb, 0x89, 0xe6, 0x76, 0x18, 0x63, 0x0d, 0x9b, 0xa7, 0xf1, 0xd5, - 0x0a, 0x94, 0xf2, 0x50, 0x10, 0x9d, 0x5e, 0xdd, 0x89, 0x31, 0x47, 0x5f, - 0xfe, 0xc6, 0x37, 0x10, 0x63, 0x63, 0xb0, 0xb3, 0xaf, 0xb5, 0xd4, 0x98, - 0xab, 0xfe, 0x7d, 0xfd, 0x93, 0x7f, 0xc5, 0x0e, 0xb3, 0x50, 0xf7, 0xbf, - 0x22, 0xbf, 0xc3, 0x9b, 0xcb, 0x48, 0xa1, 0xd7, 0xce, 0xfc, 0x50, 0xea, - 0xf8, 0x7a, 0x93, 0x99, 0xdf, 0xf6, 0x63, 0x41, 0x19, 0xbc, 0x8e, 0xbe, - 0x87, 0x5e, 0xd2, 0xaf, 0xfe, 0xea, 0x38, 0x01, 0x00, 0x8e, 0xe8, 0xeb, - 0xfb, 0xb8, 0xb5, 0xbc, 0x8e, 0xbc, 0xcb, 0x2c, 0x95, 0x7f, 0x87, 0xdd, - 0x48, 0x19, 0xca, 0x54, 0xbf, 0xbd, 0x00, 0xc9, 0x22, 0x33, 0x12, 0xeb, - 0xc9, 0x80, 0x7d, 0x86, 0x75, 0xb1, 0xa9, 0xa6, 0xae, 0x32, 0x2b, 0xf8, - 0x10, 0x08, 0xee, 0x8e, 0xbf, 0xd1, 0xf7, 0x9c, 0x4f, 0x68, 0xea, 0x85, - 0x70, 0x72, 0x28, 0xde, 0x14, 0xe8, 0xf9, 0x31, 0x2f, 0x63, 0x84, 0x01, - 0x78, 0x96, 0x5f, 0x81, 0x89, 0xd5, 0x0e, 0xbf, 0xfe, 0xc6, 0xc0, 0xbf, - 0xb4, 0x1f, 0xdf, 0x92, 0x3a, 0xb7, 0x3f, 0x55, 0x93, 0xdf, 0xff, 0xfc, - 0x2e, 0xb8, 0xe3, 0x43, 0xd8, 0xd7, 0xee, 0x92, 0xd7, 0x5e, 0x47, 0x5e, - 0xff, 0xda, 0x3a, 0xf3, 0x63, 0x47, 0x5f, 0xfd, 0xf6, 0x59, 0xd7, 0xea, - 0x73, 0x90, 0x75, 0x61, 0xef, 0x80, 0x6e, 0xfd, 0x1e, 0xd6, 0xdc, 0x3a, - 0xfd, 0xff, 0x14, 0xea, 0x1d, 0x50, 0x9c, 0x0b, 0x91, 0x81, 0xc0, 0x5f, - 0x3c, 0x43, 0xb2, 0x51, 0x7f, 0x85, 0xd9, 0xc1, 0x75, 0x0e, 0xbf, 0xfb, - 0x3d, 0xaf, 0xba, 0x58, 0xc7, 0x20, 0xeb, 0xe4, 0xdb, 0x82, 0x13, 0xf5, - 0x59, 0x8d, 0xff, 0xff, 0x07, 0xa8, 0xce, 0x6c, 0x22, 0xdf, 0xda, 0xfe, - 0x59, 0xbf, 0x8e, 0xac, 0x45, 0x23, 0x9c, 0xdf, 0xf4, 0xcd, 0xea, 0x2e, - 0x38, 0xa1, 0xd7, 0xe9, 0xfe, 0x7f, 0x13, 0x1d, 0x69, 0x1d, 0x7b, 0xe8, - 0xcc, 0x75, 0x48, 0xd7, 0x00, 0x42, 0xb1, 0x16, 0xae, 0x75, 0xa5, 0xaa, - 0x87, 0x74, 0xd9, 0x3c, 0xa8, 0x39, 0x4a, 0x46, 0x0c, 0xaa, 0x2c, 0xa5, - 0xbe, 0xa9, 0x0b, 0x76, 0xc3, 0x0d, 0x25, 0x5a, 0xcd, 0x2c, 0x57, 0x92, - 0xbc, 0x97, 0x2b, 0x27, 0xb2, 0xf2, 0xde, 0x3c, 0xe0, 0x43, 0xcc, 0x67, - 0xc1, 0xb5, 0x38, 0xa5, 0xe9, 0x77, 0x3f, 0xca, 0x73, 0x66, 0x37, 0x1f, - 0xb0, 0xd6, 0xbd, 0xb6, 0x04, 0xeb, 0xff, 0xec, 0x15, 0x7c, 0xa2, 0x6f, - 0xae, 0xe0, 0x1c, 0xea, 0x91, 0xf6, 0x04, 0x72, 0xff, 0x38, 0xb7, 0x3d, - 0xd4, 0x3a, 0xff, 0xff, 0xb3, 0xaf, 0xf7, 0x58, 0xa3, 0x88, 0x20, 0x62, - 0x6e, 0xc1, 0xd6, 0x83, 0xaf, 0xff, 0xd1, 0xce, 0xc2, 0xf6, 0x3f, 0x81, - 0x89, 0xbb, 0x07, 0x5f, 0x93, 0x93, 0x47, 0x78, 0x8c, 0xb0, 0x32, 0x88, - 0x7d, 0x6e, 0x9b, 0x4a, 0xc8, 0xbe, 0xc3, 0xee, 0xcc, 0x3c, 0xeb, 0xff, - 0x38, 0x83, 0xe0, 0x7f, 0x7e, 0x48, 0xeb, 0xe4, 0x19, 0xe0, 0xeb, 0xde, - 0xe4, 0x1d, 0x7f, 0xc3, 0x0b, 0x41, 0xc5, 0xc1, 0xd7, 0x20, 0x70, 0xf3, - 0xe6, 0x1b, 0xa6, 0x34, 0x6e, 0x71, 0x00, 0x5b, 0xe9, 0x89, 0xa6, 0x49, - 0x90, 0xf2, 0xbd, 0x03, 0x39, 0xd7, 0xc9, 0xd4, 0x59, 0xd6, 0xea, 0x1b, - 0xb9, 0x86, 0xef, 0xe8, 0x6c, 0x6b, 0xc8, 0x75, 0xff, 0x47, 0xba, 0xe0, - 0x7d, 0xf4, 0x75, 0x04, 0xf8, 0xc4, 0xae, 0xff, 0xdc, 0x07, 0xce, 0xa3, - 0x7f, 0xe0, 0x0e, 0xbd, 0x37, 0xfc, 0x3a, 0xff, 0xce, 0x9c, 0xcd, 0xd5, - 0x65, 0x96, 0x4e, 0xa8, 0x45, 0x13, 0xa1, 0x68, 0x7a, 0xff, 0xf8, 0x62, - 0x5f, 0x3e, 0xf9, 0x07, 0xf9, 0x66, 0x8e, 0xac, 0x4f, 0x35, 0xb0, 0x8a, - 0xec, 0x30, 0xc0, 0x5d, 0x78, 0x0e, 0xb3, 0xae, 0xc0, 0x1d, 0x78, 0x64, - 0x30, 0x6c, 0x30, 0x6e, 0xff, 0x33, 0xa1, 0xc0, 0x8b, 0x9d, 0x7d, 0xa6, - 0xb5, 0x0e, 0xa8, 0x44, 0x0a, 0x17, 0xb9, 0x8d, 0xfb, 0x9a, 0x18, 0x9c, - 0xeb, 0xff, 0xe6, 0x71, 0xba, 0xcf, 0x4d, 0x8a, 0x0e, 0x00, 0xea, 0xc3, - 0xf7, 0x42, 0x7b, 0xf9, 0xfd, 0xd7, 0x10, 0x1d, 0x7f, 0xe7, 0xf6, 0x4c, - 0xf0, 0x31, 0x31, 0xd7, 0xfe, 0xea, 0x67, 0xdc, 0x99, 0x98, 0xdc, 0xeb, - 0x27, 0x11, 0x51, 0xd2, 0xbd, 0x1e, 0x5c, 0xd6, 0x9a, 0x30, 0x4a, 0x92, - 0x64, 0x0d, 0x86, 0x40, 0x0d, 0x6e, 0xc1, 0x3a, 0xff, 0xf7, 0xa0, 0x5b, - 0x9e, 0xea, 0x70, 0x0d, 0x3a, 0xfc, 0x14, 0xd7, 0x50, 0xeb, 0xf9, 0x07, - 0x3d, 0xd4, 0x3a, 0xd1, 0x87, 0xa1, 0xa2, 0x6a, 0x0a, 0x34, 0xb0, 0x53, - 0xf8, 0x4c, 0x5f, 0xe8, 0x5e, 0xb4, 0xe3, 0x39, 0xd7, 0xfc, 0x0d, 0x49, - 0x3a, 0xe9, 0x39, 0xd7, 0xda, 0xc1, 0xf1, 0xd7, 0xb6, 0x23, 0x87, 0x52, - 0x1f, 0xb3, 0x9c, 0x7e, 0x41, 0x7b, 0xce, 0xc6, 0x75, 0xfe, 0xf7, 0x51, - 0x50, 0x3a, 0x1d, 0x77, 0xe2, 0x75, 0xdf, 0x70, 0xea, 0x0a, 0x71, 0x1d, - 0x35, 0x18, 0x54, 0x78, 0xbb, 0xf1, 0xed, 0x93, 0x2f, 0xa2, 0xd7, 0xe5, - 0x00, 0x93, 0x68, 0xeb, 0xee, 0xa3, 0xc8, 0xeb, 0xc1, 0x79, 0x1d, 0x50, - 0x6e, 0xf0, 0x82, 0xdf, 0xc2, 0x20, 0xc0, 0xc9, 0x79, 0xfd, 0xa3, 0xaf, - 0xf9, 0xb9, 0xe8, 0xda, 0x82, 0x03, 0xaf, 0xff, 0xef, 0xe3, 0xda, 0xc1, - 0xf9, 0xc8, 0x40, 0x8b, 0xc8, 0xeb, 0xf3, 0x7b, 0xbb, 0xb1, 0x9d, 0x7f, - 0xf2, 0x04, 0x7f, 0xf6, 0xa0, 0x63, 0x47, 0x52, 0x23, 0xfc, 0x4e, 0x3f, - 0x5a, 0xda, 0x57, 0x7f, 0xf0, 0x1f, 0x99, 0xb7, 0x03, 0xc1, 0x64, 0xeb, - 0xff, 0xf8, 0x73, 0x5f, 0xfc, 0xce, 0xb8, 0xe4, 0xd2, 0x8d, 0xce, 0xbf, - 0x71, 0xae, 0xed, 0x34, 0x40, 0xd7, 0xf3, 0xce, 0x07, 0x10, 0x92, 0xb0, - 0x7d, 0xec, 0xd7, 0xf8, 0x7d, 0xbb, 0x26, 0x77, 0xba, 0xf2, 0xf8, 0x8f, - 0xf1, 0x86, 0x4d, 0xff, 0x75, 0x30, 0x71, 0xa1, 0xc3, 0xa9, 0x69, 0xd9, - 0xfa, 0x34, 0x4d, 0xa7, 0x57, 0xbd, 0xfc, 0x1d, 0x7f, 0x81, 0xe4, 0x9d, - 0x70, 0xd3, 0xab, 0x73, 0xcf, 0x11, 0xcb, 0xf0, 0x58, 0xb7, 0x0b, 0x16, - 0x75, 0x42, 0xac, 0xcc, 0x8f, 0xc5, 0x21, 0x10, 0xe4, 0x57, 0xfb, 0x37, - 0xf0, 0x73, 0x14, 0x3a, 0xfe, 0xcf, 0x40, 0xa0, 0x0e, 0xbf, 0xe0, 0xf0, - 0x5d, 0x9f, 0xbb, 0xb2, 0x75, 0xe7, 0xe4, 0xe6, 0x8c, 0x16, 0xff, 0xcf, - 0xcc, 0x10, 0x6b, 0xda, 0xdc, 0xeb, 0xff, 0xff, 0xfb, 0x3d, 0xd7, 0x15, - 0x3e, 0x6b, 0x8e, 0xfe, 0xdb, 0x81, 0xf9, 0x8b, 0x71, 0xde, 0x47, 0x88, - 0x2e, 0xff, 0xce, 0xea, 0x35, 0xc3, 0xf1, 0x46, 0x4f, 0x10, 0x5d, 0xff, - 0xdd, 0x4e, 0xa4, 0x0f, 0xbe, 0x28, 0xc9, 0xe2, 0x0b, 0xbf, 0xd0, 0x83, - 0xef, 0x8a, 0x32, 0x78, 0x82, 0xef, 0xe5, 0xe0, 0x7e, 0x28, 0xc9, 0xe2, - 0x0b, 0xbf, 0xff, 0xe7, 0x11, 0x45, 0xfc, 0xd3, 0x7a, 0x9c, 0x45, 0x27, - 0xc6, 0x4f, 0x10, 0x5d, 0xdb, 0xfc, 0x0a, 0x72, 0xed, 0x4f, 0xe2, 0x9b, - 0xa1, 0x09, 0xf5, 0x42, 0xac, 0x7e, 0x9f, 0x0c, 0xa3, 0x1b, 0xfc, 0x90, - 0xa6, 0xbd, 0xad, 0xce, 0xbe, 0x7e, 0x01, 0xce, 0xbf, 0xfb, 0xa9, 0xd4, - 0x81, 0xf7, 0xc5, 0x19, 0x3c, 0x41, 0x77, 0xfd, 0x36, 0x9a, 0x93, 0xfc, - 0x51, 0x93, 0xc4, 0x17, 0x7e, 0xf6, 0xa1, 0x7f, 0x1a, 0x89, 0xff, 0xaa, - 0x77, 0xff, 0xbe, 0x37, 0xa8, 0xd8, 0xf6, 0xbe, 0x28, 0xc9, 0xe2, 0x0b, - 0xbf, 0xff, 0xf8, 0x45, 0x17, 0xf3, 0xfc, 0xf9, 0xa6, 0xf5, 0x38, 0x8a, - 0x4f, 0x8c, 0x9e, 0x20, 0xba, 0xc4, 0xc9, 0x77, 0x44, 0x75, 0xdb, 0xfe, - 0xea, 0x71, 0x14, 0x9f, 0x19, 0x3c, 0x41, 0x77, 0xff, 0xce, 0xfb, 0xcb, - 0x5d, 0x40, 0x86, 0x39, 0x05, 0x5f, 0xfb, 0x25, 0x2f, 0xf5, 0xc1, 0x9f, - 0x64, 0xf1, 0x05, 0xd3, 0x51, 0xcb, 0xc4, 0x7d, 0x27, 0x5f, 0xf9, 0xa9, - 0xcf, 0x38, 0x35, 0xf1, 0x93, 0xc4, 0x17, 0x7f, 0x75, 0x3b, 0xd4, 0x01, - 0xa0, 0x0b, 0xbf, 0x60, 0x3e, 0x28, 0xc9, 0xe2, 0x0b, 0xbb, 0x3c, 0xd3, - 0xf1, 0xe9, 0xcd, 0x6e, 0x8e, 0xcd, 0x42, 0xfe, 0xfe, 0x5e, 0x07, 0xe2, - 0x8c, 0x9e, 0x20, 0xbb, 0xff, 0x37, 0xa9, 0xc4, 0x52, 0x7c, 0x64, 0xf1, - 0x05, 0xdd, 0x9f, 0x1d, 0x11, 0x7a, 0x3e, 0xbf, 0xdf, 0xa2, 0xdc, 0x77, - 0x91, 0xe2, 0x0b, 0xbf, 0xf6, 0x26, 0xdc, 0x1c, 0x0b, 0xc8, 0xf1, 0x05, - 0xac, 0xf0, 0x28, 0x2b, 0xbf, 0xbc, 0x37, 0x01, 0xa0, 0xc7, 0xc9, 0xa8, - 0xc5, 0x7d, 0x18, 0xe7, 0xf0, 0xb4, 0x65, 0xbe, 0xe0, 0x41, 0xa2, 0x0b, - 0x55, 0x11, 0x97, 0x3b, 0x4e, 0xb6, 0x9a, 0xc9, 0xc3, 0x05, 0x25, 0xe7, - 0xc6, 0xb7, 0x4b, 0x60, 0xeb, 0xd1, 0x2d, 0x83, 0xaa, 0x0d, 0xb8, 0x8c, - 0xd4, 0xec, 0xaf, 0x60, 0x99, 0xee, 0x54, 0x0a, 0x50, 0x00, 0xbd, 0x5f, - 0xfd, 0x92, 0x1c, 0xf7, 0x53, 0x37, 0xf1, 0xd7, 0xfa, 0x3a, 0x8c, 0xef, - 0x2d, 0x1d, 0x7e, 0x8f, 0x6b, 0xa8, 0x75, 0xff, 0x6e, 0x38, 0x8b, 0xc1, - 0x01, 0xd7, 0xfe, 0xd4, 0xd2, 0xfc, 0x33, 0x4b, 0xf0, 0x9d, 0x53, 0xa3, - 0x52, 0x46, 0x98, 0x4d, 0xe3, 0x6b, 0xff, 0xa3, 0x79, 0x7d, 0x5e, 0xbd, - 0x1b, 0xb2, 0x75, 0xfa, 0x5b, 0x1b, 0x1f, 0xce, 0x75, 0xba, 0x87, 0xf2, - 0xe9, 0x37, 0xee, 0x46, 0xf2, 0xd1, 0xd5, 0x23, 0xce, 0xe1, 0x35, 0xff, - 0xc0, 0xff, 0x5b, 0x39, 0xc0, 0x2d, 0x34, 0x75, 0xfe, 0x07, 0xfe, 0x18, - 0xf6, 0x8e, 0xa0, 0x1f, 0xde, 0x92, 0x2a, 0x13, 0xc3, 0xc8, 0xc1, 0x1e, - 0x13, 0xb7, 0xf3, 0xca, 0x36, 0xbf, 0x4e, 0xbf, 0xfd, 0x3e, 0x6f, 0xed, - 0x20, 0xc0, 0x1d, 0x67, 0x5f, 0x6f, 0xa8, 0xdc, 0xeb, 0xcb, 0x89, 0x1d, - 0x7e, 0xc0, 0xf7, 0xf6, 0x4e, 0xaf, 0x87, 0xce, 0xe4, 0x62, 0x37, 0x78, - 0x2f, 0xe3, 0xab, 0x87, 0x94, 0xe5, 0xf7, 0x93, 0x67, 0x0e, 0xbc, 0xfc, - 0x01, 0xd6, 0xde, 0x0d, 0xc7, 0x87, 0x6f, 0x99, 0xce, 0xb9, 0xd7, 0xca, - 0x71, 0x19, 0x3a, 0xfd, 0x3b, 0xf6, 0x18, 0xce, 0xa6, 0x28, 0xf3, 0x70, - 0x8e, 0xa1, 0x51, 0xde, 0x16, 0xa4, 0x3e, 0x9d, 0x64, 0x04, 0xe2, 0xdd, - 0x7f, 0xf8, 0x46, 0x27, 0x5f, 0x53, 0x9c, 0x79, 0x1d, 0x7f, 0xa7, 0x9e, - 0x07, 0x7c, 0xf1, 0xd5, 0x87, 0xf8, 0x89, 0x17, 0xff, 0x70, 0x7f, 0xdf, - 0xc3, 0x93, 0xb8, 0x9d, 0x79, 0xf9, 0x39, 0xd7, 0x02, 0x0e, 0xbe, 0x48, - 0x5e, 0x1d, 0x47, 0x5f, 0xce, 0xa7, 0xa3, 0x80, 0x3a, 0x82, 0x6d, 0xc4, - 0x2a, 0xff, 0xff, 0x42, 0x04, 0x63, 0xf6, 0xfb, 0x1a, 0x18, 0x6f, 0xd5, - 0x9d, 0x70, 0x20, 0xeb, 0xa1, 0x43, 0xaf, 0xfb, 0x3d, 0xa8, 0x5f, 0xdc, - 0x98, 0xeb, 0xfd, 0xac, 0xea, 0x6b, 0xf9, 0xce, 0xb9, 0x96, 0x4a, 0xbf, - 0xe1, 0xcd, 0xaf, 0x2d, 0x20, 0x4e, 0xa6, 0xa7, 0xe2, 0x83, 0x9c, 0x15, - 0x5a, 0xb7, 0x48, 0x00, 0xc2, 0xc1, 0x15, 0x11, 0x6d, 0x1d, 0x32, 0x69, - 0xf4, 0x62, 0xf3, 0x2c, 0xb2, 0x55, 0x96, 0x52, 0xa5, 0xfd, 0xf4, 0xce, - 0xfc, 0x29, 0x54, 0x6e, 0xfd, 0x85, 0xed, 0x4e, 0xad, 0x69, 0xe5, 0x89, - 0x5f, 0xde, 0x8c, 0xee, 0x4e, 0x75, 0xd8, 0xb3, 0xab, 0x73, 0xc1, 0xd1, - 0x65, 0x43, 0xa3, 0xa0, 0x94, 0x6b, 0xb9, 0x28, 0xd9, 0x48, 0x7c, 0x6f, - 0x1e, 0x22, 0x4a, 0x90, 0xe4, 0x3c, 0x96, 0x53, 0xd9, 0x7c, 0xcf, 0x4b, - 0x3c, 0x02, 0xc0, 0xca, 0xd9, 0xd4, 0xa7, 0x4f, 0x43, 0x57, 0xf9, 0x6f, - 0x5b, 0x5b, 0x6f, 0xec, 0x00, 0x13, 0x92, 0x3a, 0xe6, 0xe1, 0xd4, 0x13, - 0xc1, 0x72, 0xcb, 0xb1, 0x93, 0xae, 0x8f, 0x1d, 0x53, 0x9a, 0xb6, 0x8b, - 0x59, 0x67, 0x56, 0x1b, 0x2f, 0x11, 0x5f, 0xe9, 0x20, 0xe2, 0xff, 0xe9, - 0xd7, 0xfe, 0xcf, 0x6b, 0xa8, 0xb7, 0xce, 0x1d, 0x50, 0x7d, 0xc2, 0x65, - 0x7d, 0xf3, 0xd1, 0xb4, 0xeb, 0xec, 0x5e, 0x78, 0xeb, 0xde, 0x75, 0x0e, - 0xbf, 0xff, 0xf3, 0xcd, 0xfc, 0xbf, 0x6f, 0xce, 0xa7, 0xbd, 0x1b, 0xc4, - 0xf1, 0xa3, 0xaf, 0xa6, 0xd4, 0x78, 0xea, 0x6a, 0x25, 0x3f, 0x72, 0xbf, - 0xff, 0xe6, 0x31, 0x77, 0xdb, 0x12, 0xec, 0x72, 0x78, 0xf6, 0x9e, 0x47, - 0x5e, 0x4d, 0xe6, 0x3a, 0xfd, 0x99, 0x3f, 0xfa, 0x3a, 0xfb, 0x82, 0x80, - 0x3a, 0xf9, 0x1a, 0xfc, 0x3a, 0xe8, 0x01, 0xd7, 0xdf, 0xcf, 0xfa, 0xbd, - 0x36, 0xbf, 0x48, 0x29, 0x11, 0x29, 0xd5, 0x5b, 0x98, 0xc0, 0x75, 0xff, - 0x75, 0xf5, 0xd4, 0x9d, 0xc4, 0xeb, 0xe7, 0x9f, 0xec, 0x8e, 0xa6, 0x12, - 0xe0, 0xec, 0x3f, 0x4a, 0x11, 0xd8, 0x41, 0xb9, 0x2a, 0x10, 0x72, 0x16, - 0x0e, 0x48, 0x06, 0x9d, 0x0e, 0xfa, 0x17, 0x9f, 0x91, 0x7d, 0x19, 0xd8, - 0x37, 0xbf, 0x87, 0xf0, 0xad, 0xe4, 0x75, 0xe4, 0x9f, 0xf3, 0xaf, 0xd0, - 0x04, 0xdf, 0x0e, 0xb9, 0x7b, 0x4e, 0xb0, 0x60, 0xdf, 0x09, 0x35, 0xff, - 0xe9, 0x0c, 0x7c, 0x58, 0xc2, 0x9e, 0x49, 0xce, 0xbf, 0x3a, 0xf3, 0xab, - 0x3a, 0xb7, 0x3f, 0x1f, 0x25, 0xde, 0xf7, 0x20, 0xeb, 0xfd, 0xaf, 0x6d, - 0xc1, 0xc0, 0x9d, 0x7b, 0xb1, 0xb4, 0xeb, 0xda, 0x94, 0xe7, 0x56, 0x1b, - 0xaf, 0xa3, 0xb5, 0x09, 0xf5, 0xc8, 0xb7, 0x16, 0xd2, 0x12, 0xcb, 0x23, - 0x71, 0xbf, 0x36, 0xde, 0x7f, 0x9f, 0x4e, 0xbd, 0x32, 0x74, 0xeb, 0xfa, - 0x38, 0xf3, 0x27, 0x4e, 0xbf, 0x68, 0x30, 0x33, 0xb9, 0xe4, 0x68, 0x72, - 0xf2, 0xe1, 0x67, 0x56, 0xe7, 0xb2, 0xb3, 0xeb, 0xff, 0xe1, 0x97, 0xcc, - 0x0a, 0x6b, 0x7f, 0x7e, 0xfa, 0x3a, 0xfd, 0xdf, 0xc6, 0x36, 0x9d, 0x7f, - 0x0b, 0xfa, 0x50, 0xa1, 0xd5, 0x07, 0xab, 0xf4, 0xa6, 0xfb, 0x33, 0x79, - 0x1d, 0x7b, 0x49, 0x31, 0xd6, 0x50, 0x4d, 0xee, 0x88, 0x6f, 0xfe, 0x79, - 0xc6, 0x37, 0x40, 0x8c, 0x4e, 0x75, 0x70, 0xfa, 0x84, 0x9e, 0xfd, 0xf3, - 0xb1, 0xc9, 0x1d, 0x5f, 0x15, 0x4f, 0x44, 0x30, 0x30, 0x8d, 0xb0, 0xa7, - 0x78, 0x65, 0x32, 0x43, 0x79, 0x7a, 0x83, 0xaf, 0xe9, 0xe6, 0x93, 0x0b, - 0x93, 0x9d, 0x7c, 0xbc, 0x7e, 0x9d, 0x74, 0xa7, 0x3a, 0xf7, 0x42, 0x87, - 0x5f, 0xbb, 0x89, 0x2d, 0x1d, 0x7f, 0xfd, 0xd8, 0xfa, 0xaf, 0x85, 0xc1, - 0xad, 0x40, 0x0a, 0xbf, 0x71, 0xae, 0xed, 0x3c, 0x40, 0x97, 0xb5, 0x1b, - 0x9d, 0x60, 0x61, 0xe7, 0xee, 0x67, 0x7b, 0xc9, 0x39, 0xd7, 0xa7, 0x71, - 0x3a, 0xa4, 0x99, 0x28, 0x49, 0xb9, 0x0a, 0x05, 0x94, 0x78, 0x72, 0xfe, - 0x16, 0xba, 0x9d, 0x43, 0xae, 0xd8, 0x91, 0xd7, 0xde, 0x9d, 0xc4, 0xeb, - 0xc2, 0xea, 0x1d, 0x79, 0x44, 0xf1, 0xd7, 0xb4, 0xfe, 0x3a, 0x94, 0x36, - 0xfb, 0x8e, 0x5d, 0xf3, 0xa7, 0x5f, 0xcb, 0xf2, 0x07, 0xf8, 0x3a, 0xf2, - 0xfc, 0xd3, 0xad, 0xe8, 0x3c, 0x9c, 0x2d, 0xbf, 0xa1, 0x78, 0xa4, 0x68, - 0xea, 0x9d, 0x36, 0x2c, 0x19, 0x69, 0x0f, 0x54, 0x80, 0x46, 0x2c, 0x3e, - 0x26, 0xbb, 0x9f, 0x9d, 0x7f, 0x85, 0xd9, 0xd6, 0xa0, 0x07, 0x5e, 0xd9, - 0x75, 0x0e, 0xbf, 0xe8, 0x5c, 0xb2, 0x7c, 0xfd, 0x82, 0x75, 0xf3, 0xf9, - 0x83, 0x39, 0xd5, 0x88, 0x82, 0x41, 0xf7, 0x3d, 0xbc, 0xcb, 0x2c, 0x9e, - 0xaf, 0xab, 0xce, 0x21, 0x2d, 0x5f, 0x55, 0x4d, 0x65, 0xf4, 0xbf, 0x85, - 0x0e, 0xb0, 0x0e, 0xac, 0x36, 0x6e, 0x47, 0x50, 0x9d, 0x78, 0x45, 0xf9, - 0x0b, 0x40, 0x2c, 0xf9, 0xb2, 0xf9, 0x7c, 0xfe, 0x73, 0xaf, 0xff, 0x85, - 0x14, 0x57, 0x5e, 0xef, 0xef, 0x29, 0x41, 0xd5, 0x07, 0xeb, 0x84, 0x95, - 0x3a, 0x39, 0x14, 0x86, 0x25, 0xf6, 0x05, 0xe4, 0x75, 0xf9, 0xc4, 0x51, - 0x67, 0x5e, 0x0b, 0xc8, 0xeb, 0xfc, 0x9c, 0xc4, 0x5c, 0x31, 0x9d, 0x58, - 0x79, 0xdd, 0x1b, 0xbf, 0x22, 0xdc, 0x70, 0xea, 0xf8, 0xbf, 0x3a, 0xc4, - 0x0d, 0xc1, 0xac, 0x88, 0x02, 0x2f, 0x91, 0xa0, 0x28, 0xa0, 0x91, 0xc7, - 0x3c, 0xaf, 0x70, 0x15, 0x09, 0x07, 0xee, 0x5b, 0x24, 0x37, 0xf6, 0x77, - 0x1b, 0xfe, 0x1d, 0x7e, 0x4f, 0x47, 0xb4, 0x55, 0xf3, 0x63, 0xda, 0x2a, - 0xe6, 0x59, 0x2a, 0xa4, 0x7b, 0xf8, 0x4c, 0xc9, 0x0d, 0xd8, 0xc9, 0x4a, - 0x9a, 0xfb, 0xe9, 0x85, 0xd9, 0x3a, 0xff, 0xfb, 0xd0, 0xdc, 0xc1, 0xf7, - 0x52, 0x06, 0x73, 0xa8, 0xea, 0xc3, 0xd6, 0xd2, 0x65, 0x4c, 0x9b, 0xd0, - 0x21, 0x74, 0x24, 0xec, 0xbc, 0x5f, 0xfb, 0xda, 0xc6, 0xf5, 0xc7, 0xda, - 0x3a, 0xfd, 0x1b, 0x50, 0x40, 0x77, 0xc3, 0x7b, 0x7e, 0x97, 0x7f, 0x8e, - 0x1d, 0x7f, 0xf3, 0xaf, 0x91, 0xb5, 0x36, 0x8f, 0xfa, 0x3a, 0xb7, 0x3e, - 0xfe, 0x94, 0x5f, 0xb3, 0xf5, 0xc6, 0x8e, 0xa3, 0xae, 0xc9, 0xb8, 0x6c, - 0x74, 0x4f, 0x7f, 0xc9, 0xfb, 0x07, 0xb1, 0xf4, 0x67, 0x3a, 0xff, 0xa2, - 0x78, 0xdf, 0xc3, 0x93, 0x9d, 0x58, 0x8a, 0x56, 0x96, 0xa1, 0xfd, 0xf9, - 0xd6, 0x31, 0xb9, 0xd5, 0x32, 0x69, 0xbc, 0x87, 0xcf, 0x4b, 0xaf, 0xb3, - 0xb9, 0x39, 0xd7, 0xa4, 0xfc, 0x3a, 0xfd, 0x2c, 0xf6, 0x04, 0xab, 0xe8, - 0x11, 0x83, 0xaa, 0x63, 0xdf, 0xf0, 0xdf, 0xd2, 0x6b, 0xe0, 0x69, 0x7c, - 0x3a, 0x94, 0x46, 0xa2, 0x42, 0x03, 0xc6, 0x57, 0xfc, 0x39, 0xdc, 0xf9, - 0xdc, 0x9c, 0xeb, 0xff, 0xff, 0x81, 0x02, 0xd7, 0xf3, 0xee, 0x0d, 0xfc, - 0x8b, 0xd7, 0x63, 0xe8, 0x9d, 0x7f, 0x7e, 0xc1, 0x4e, 0x73, 0x0e, 0xbe, - 0xf2, 0x99, 0xd3, 0xaf, 0xfc, 0x39, 0xef, 0x7f, 0x3f, 0xb1, 0xa7, 0x5b, - 0x47, 0x5c, 0x80, 0x3a, 0xee, 0xa1, 0xd7, 0x7f, 0xaf, 0x86, 0xaa, 0x61, - 0x5a, 0x73, 0xeb, 0x01, 0xd5, 0xc0, 0x83, 0xae, 0x04, 0x1d, 0x7e, 0xfe, - 0x58, 0x2a, 0xa1, 0xaa, 0x00, 0xad, 0x42, 0x6a, 0xaa, 0x11, 0x02, 0x15, - 0x42, 0x97, 0x7f, 0xfd, 0x82, 0xfb, 0xe9, 0x45, 0x1f, 0xe3, 0x56, 0x03, - 0xaf, 0xfe, 0xf7, 0x71, 0x7f, 0x60, 0x19, 0xbf, 0x8e, 0xbf, 0xdb, 0xb5, - 0x39, 0xf6, 0x02, 0x75, 0xf0, 0x16, 0xf2, 0xf8, 0x8c, 0xed, 0x29, 0xf9, - 0x1a, 0xef, 0xfc, 0x75, 0xfc, 0x05, 0xfd, 0xd7, 0xd9, 0xce, 0xbf, 0xb4, - 0x82, 0x31, 0xb9, 0xd7, 0x66, 0xe7, 0x56, 0xe7, 0xe9, 0xe3, 0x3d, 0x92, - 0xbb, 0xe0, 0x71, 0x38, 0x75, 0x42, 0x65, 0x12, 0x49, 0x78, 0x45, 0xb2, - 0x67, 0x7b, 0xfd, 0xfc, 0x75, 0x9c, 0xea, 0xd1, 0xad, 0xf0, 0xf5, 0xd8, - 0xc9, 0xd7, 0xfd, 0x1b, 0xe0, 0x23, 0x6e, 0x4e, 0x75, 0xfc, 0x39, 0xed, - 0x38, 0x0e, 0xae, 0x1f, 0xd8, 0x05, 0xb4, 0x75, 0x7f, 0xe9, 0xa2, 0x7d, - 0x73, 0x1b, 0x13, 0x9d, 0x7f, 0x62, 0xf0, 0x28, 0xc9, 0xd7, 0x2e, 0x0e, - 0xa5, 0x9e, 0x0b, 0x96, 0x5f, 0xc3, 0x93, 0x75, 0x3c, 0x75, 0xf6, 0x67, - 0x74, 0x75, 0x62, 0x3b, 0x9e, 0x10, 0x3e, 0x21, 0xd8, 0x2c, 0xbc, 0xcb, - 0x2c, 0x95, 0x7e, 0xc5, 0x07, 0xfd, 0x14, 0xa9, 0x7f, 0x7c, 0xab, 0x2c, - 0xb2, 0x75, 0xd8, 0x03, 0xab, 0x0d, 0xdf, 0x89, 0xaa, 0x11, 0x27, 0xe7, - 0x3b, 0xe4, 0xe0, 0x34, 0x75, 0xff, 0x6b, 0x91, 0xff, 0x85, 0x36, 0x9d, - 0x7f, 0xe1, 0xcd, 0x37, 0xa8, 0xd8, 0x13, 0xaf, 0xff, 0xf2, 0x8c, 0xbf, - 0x14, 0x57, 0x59, 0x21, 0xfd, 0xf5, 0x82, 0x75, 0x42, 0x36, 0x30, 0xe9, - 0x0e, 0xef, 0x99, 0x71, 0x91, 0xd7, 0xfd, 0xe8, 0xdc, 0x0f, 0xde, 0xa1, - 0xd6, 0xe9, 0xd5, 0x87, 0x90, 0xd3, 0x8b, 0xf0, 0xe7, 0xa3, 0x87, 0x5e, - 0x65, 0x96, 0x4a, 0xbf, 0x3a, 0x9d, 0x4f, 0x14, 0xa9, 0x7f, 0x50, 0x7f, - 0x68, 0x89, 0x7b, 0xc8, 0xc9, 0xd7, 0xb4, 0xfc, 0x3a, 0xb7, 0x36, 0xfe, - 0x1c, 0xbd, 0xd8, 0x09, 0xd4, 0x86, 0xf5, 0xc8, 0xaf, 0xd8, 0x0c, 0xc9, - 0x8e, 0xb6, 0xbe, 0x26, 0xeb, 0xc8, 0x4e, 0x76, 0x12, 0x82, 0x3f, 0x77, - 0xf2, 0x0a, 0xa2, 0xdc, 0x8f, 0x7a, 0xfc, 0xc1, 0xec, 0x4f, 0xf9, 0xd5, - 0x32, 0xbb, 0x7e, 0xc3, 0xe4, 0x65, 0x2d, 0x7e, 0x6f, 0x7a, 0x36, 0xc1, - 0xd4, 0x87, 0xd0, 0x29, 0x97, 0x86, 0x36, 0x9d, 0x73, 0x05, 0x0e, 0xb9, - 0x3a, 0x75, 0x9e, 0x73, 0x5d, 0xc1, 0x9b, 0xef, 0x6b, 0xf6, 0x33, 0xaf, - 0xf4, 0x0c, 0x85, 0x23, 0x73, 0xaa, 0x1b, 0x06, 0x59, 0x42, 0x07, 0x23, - 0xf5, 0x52, 0x30, 0xb6, 0x9a, 0xee, 0x72, 0x8e, 0x7c, 0x8e, 0x1b, 0xb2, - 0x8e, 0x1d, 0xbc, 0x10, 0x9c, 0x18, 0xc7, 0x75, 0x0f, 0x5f, 0x4e, 0x20, - 0xed, 0x20, 0xd9, 0x4a, 0xfa, 0x4f, 0xb0, 0x4d, 0x7e, 0x49, 0xa4, 0x82, - 0x75, 0xcc, 0x52, 0x1d, 0x7f, 0xd3, 0x7b, 0x63, 0x51, 0x37, 0xfc, 0x3a, - 0xff, 0x06, 0x05, 0x70, 0x18, 0x3a, 0xa0, 0xfb, 0xdc, 0xfe, 0xff, 0xec, - 0x4e, 0xc0, 0x7b, 0xfc, 0x6f, 0xa3, 0xaf, 0x05, 0x40, 0x1d, 0x7e, 0x5f, - 0x38, 0xfe, 0x3a, 0xbe, 0x1e, 0x24, 0x0e, 0xdf, 0xfe, 0x6c, 0xce, 0xde, - 0xc4, 0xbc, 0x38, 0xb3, 0xaf, 0xff, 0x91, 0x7b, 0xcb, 0x5f, 0x30, 0x47, - 0x10, 0x07, 0x5e, 0x4e, 0xfe, 0x75, 0x7c, 0x54, 0x5c, 0xc4, 0x13, 0x4a, - 0x11, 0x3c, 0x20, 0xec, 0x22, 0x1c, 0x8f, 0xc9, 0x3b, 0x53, 0xec, 0xab, - 0x15, 0x1c, 0xd8, 0x9b, 0x02, 0x19, 0x2c, 0x5c, 0x6a, 0xac, 0x26, 0xd6, - 0x1f, 0x18, 0xd3, 0x13, 0x8c, 0x51, 0x89, 0x1d, 0x30, 0xca, 0xd1, 0x4e, - 0x8e, 0x9e, 0x75, 0x92, 0x54, 0xaa, 0xc0, 0xd2, 0xcf, 0xb2, 0xdd, 0xd4, - 0x29, 0x2d, 0x75, 0xb4, 0xc0, 0x8d, 0xe9, 0x17, 0x89, 0x4a, 0x7c, 0x63, - 0x8d, 0xee, 0x6a, 0x70, 0x8f, 0x29, 0xe2, 0xeb, 0xa4, 0xbe, 0xf6, 0xb9, - 0x7b, 0x7a, 0xed, 0x88, 0x14, 0xb4, 0x76, 0x0c, 0x3c, 0x46, 0xb6, 0xe6, - 0xd5, 0xbc, 0x98, 0xf5, 0xa7, 0x09, 0xfe, 0x76, 0x2f, 0x6c, 0xac, 0x36, - 0x65, 0x82, 0x6c, 0xd2, 0x01, 0x7e, 0xd6, 0x55, 0xdb, 0x12, 0xd8, 0xe9, - 0x58, 0xe7, 0xab, 0xe5, 0x9c, 0xdd, 0x3d, 0xf9, 0x50, 0x2f, 0x3c, 0x75, - 0xfe, 0x57, 0x38, 0xd7, 0x76, 0x9a, 0x2e, 0x3b, 0xfc, 0xae, 0x71, 0xae, - 0xed, 0x34, 0x5d, 0x77, 0xff, 0x2a, 0xf2, 0x57, 0x38, 0xd7, 0x76, 0x9a, - 0x25, 0x1a, 0x88, 0xe8, 0xfd, 0xe5, 0x0c, 0xc0, 0x94, 0xa9, 0x08, 0xf6, - 0x94, 0x24, 0x74, 0x4c, 0x6e, 0x2f, 0x9c, 0xf8, 0x30, 0x0e, 0xf4, 0x51, - 0xe3, 0xfd, 0x83, 0xfb, 0xff, 0xca, 0xad, 0xe4, 0xae, 0x71, 0xae, 0xed, - 0x34, 0x4b, 0x57, 0xfc, 0xc3, 0xba, 0x8c, 0x6f, 0x1b, 0xec, 0x1d, 0x7e, - 0xe3, 0x5d, 0xda, 0x68, 0x8d, 0xef, 0xfc, 0xf2, 0x57, 0x38, 0xd7, 0x76, - 0x9a, 0x25, 0xfb, 0xfa, 0x3d, 0xf7, 0xaf, 0xe3, 0xaf, 0xf6, 0x7d, 0xe2, - 0x9d, 0xff, 0x47, 0x5f, 0x7f, 0xd4, 0xe1, 0xd7, 0xa6, 0xd7, 0x0e, 0xb2, - 0xac, 0x49, 0x36, 0x5c, 0x44, 0x59, 0x9f, 0x52, 0x84, 0xbb, 0x64, 0xdf, - 0xe9, 0x15, 0xff, 0xed, 0xe5, 0xe4, 0x99, 0x50, 0xa6, 0xd8, 0x09, 0xd7, - 0xf9, 0x5c, 0xe3, 0x5d, 0xda, 0x68, 0xaa, 0xee, 0x4d, 0x83, 0xaf, 0x91, - 0x6f, 0xb4, 0xea, 0x50, 0xdd, 0x78, 0x62, 0xf0, 0xec, 0x32, 0x75, 0xfc, - 0xfd, 0x98, 0x60, 0x27, 0x5f, 0xfd, 0xee, 0xc6, 0x85, 0xff, 0x60, 0xa7, - 0x0e, 0xbd, 0x12, 0xc3, 0xa8, 0x28, 0x8d, 0xdc, 0xb2, 0x64, 0x7b, 0xfe, - 0x53, 0x07, 0x37, 0xf3, 0xac, 0xeb, 0x82, 0x87, 0x5f, 0xd9, 0xc6, 0xbb, - 0xb4, 0xd1, 0x20, 0x57, 0xc3, 0xcd, 0x54, 0x56, 0xfd, 0xa7, 0x17, 0xdc, - 0xeb, 0xbf, 0x83, 0xaa, 0x47, 0xc3, 0xb9, 0x2f, 0x09, 0xaf, 0xf4, 0xa3, - 0x93, 0xc7, 0x27, 0x3a, 0xff, 0x72, 0x75, 0xc0, 0xcb, 0x47, 0x54, 0x1f, - 0x3e, 0x1a, 0x5f, 0x64, 0xee, 0x13, 0xaf, 0xff, 0x64, 0xdd, 0x75, 0xfb, - 0xb1, 0xef, 0xd6, 0x75, 0x4e, 0xac, 0x24, 0x24, 0x59, 0x0a, 0xc5, 0x0c, - 0x9e, 0x1c, 0xc3, 0x09, 0x7f, 0x10, 0x7d, 0x21, 0xbf, 0xf8, 0x72, 0x75, - 0x76, 0x60, 0x47, 0x3c, 0x75, 0x2a, 0x8c, 0x8e, 0x42, 0x0e, 0xff, 0x2b, - 0x9c, 0x6b, 0xbb, 0x4d, 0x16, 0x45, 0xfe, 0x57, 0x38, 0xd7, 0x76, 0x9a, - 0x2d, 0x7b, 0xff, 0xd9, 0xf6, 0x27, 0x57, 0x26, 0xf0, 0x60, 0x4e, 0xbf, - 0xca, 0xe7, 0x1a, 0xee, 0xd3, 0x45, 0xc9, 0x7e, 0xe3, 0x5d, 0xda, 0x68, - 0xbb, 0x2f, 0xfc, 0xf2, 0x57, 0x38, 0xd7, 0x76, 0x9a, 0x28, 0xeb, 0x2b, - 0x87, 0xfa, 0xb3, 0x3b, 0xe1, 0x89, 0x2c, 0xeb, 0xff, 0x30, 0x98, 0x0b, - 0x8e, 0x4b, 0x13, 0x69, 0xd6, 0x91, 0xd7, 0xee, 0x35, 0xdd, 0xa6, 0x8a, - 0x56, 0xff, 0x9b, 0xd4, 0x9b, 0xb1, 0x3e, 0x1d, 0x7f, 0xfb, 0xb1, 0x3c, - 0x75, 0x36, 0xb8, 0x7a, 0x87, 0x2a, 0x6e, 0x6e, 0x92, 0xb8, 0x8c, 0x79, - 0x9b, 0x2b, 0x74, 0xc1, 0xde, 0x1a, 0xf7, 0xfe, 0x74, 0xf4, 0xbf, 0x0b, - 0x88, 0x0e, 0xb2, 0xa1, 0x4f, 0x53, 0x72, 0x05, 0xc6, 0x9d, 0xd2, 0x9a, - 0x9d, 0x95, 0x81, 0x28, 0xef, 0x31, 0xd7, 0x74, 0xe4, 0x9c, 0x4a, 0x59, - 0x48, 0x0f, 0xc4, 0xff, 0x49, 0x9e, 0x85, 0xe6, 0xd8, 0xff, 0x2f, 0xfa, - 0x4a, 0xe7, 0x1a, 0xee, 0xd3, 0x44, 0x71, 0x7f, 0xc8, 0xae, 0x71, 0xae, - 0xed, 0x34, 0x56, 0xb6, 0x55, 0xd1, 0x13, 0xe4, 0x5b, 0xff, 0xca, 0xad, - 0xe4, 0xae, 0x71, 0xae, 0xed, 0x34, 0x4b, 0x77, 0xbf, 0xe0, 0x0e, 0xbb, - 0x37, 0x3a, 0xff, 0x07, 0x16, 0xb8, 0x4d, 0x1d, 0x7b, 0x6f, 0xf2, 0x3a, - 0x9a, 0x88, 0x3d, 0xc7, 0x50, 0x5b, 0x69, 0x8d, 0xee, 0x86, 0x47, 0x5f, - 0xf6, 0x6e, 0x38, 0x00, 0x3c, 0x8e, 0xb9, 0x6d, 0x3a, 0xa0, 0xf3, 0x64, - 0x6f, 0x7c, 0x31, 0xbc, 0x8e, 0xbf, 0xff, 0x3e, 0xe0, 0x0f, 0x5e, 0x59, - 0xa1, 0xfd, 0xfe, 0x9d, 0x4d, 0x3f, 0x8e, 0x90, 0xd9, 0x43, 0xaf, 0xe4, - 0xe0, 0xa7, 0xb4, 0x75, 0xfb, 0x8e, 0x39, 0x07, 0x51, 0xa2, 0x1b, 0x43, - 0xe0, 0xe8, 0x8b, 0x95, 0xdd, 0x02, 0x75, 0xfc, 0x82, 0x1c, 0x40, 0x9d, - 0x50, 0x6f, 0xa4, 0x29, 0x7d, 0x93, 0x4b, 0x0e, 0xbf, 0xf3, 0xc9, 0x5c, - 0xe3, 0x5d, 0xda, 0x68, 0x98, 0x2f, 0x32, 0x80, 0x3a, 0xfb, 0x4e, 0x20, - 0x3a, 0xa6, 0x37, 0x80, 0x1c, 0xbf, 0xdf, 0xef, 0xc4, 0x85, 0xe1, 0xd7, - 0xee, 0xa4, 0x0c, 0xe7, 0x5f, 0xf4, 0x4f, 0xe1, 0x8f, 0xfd, 0xa3, 0xad, - 0xee, 0xa2, 0x4b, 0x46, 0x7b, 0x24, 0xd7, 0xdb, 0xb5, 0x14, 0x3a, 0xb0, - 0xf7, 0x3c, 0x73, 0x7f, 0xb8, 0x9e, 0xc5, 0xc7, 0x4e, 0xbf, 0xda, 0x4e, - 0xa2, 0xf1, 0x43, 0xaf, 0xff, 0x3c, 0xfd, 0x48, 0x1c, 0x99, 0x38, 0x87, - 0x56, 0x22, 0xab, 0xc6, 0x2c, 0x99, 0x5c, 0xdc, 0x3a, 0xef, 0xc0, 0x55, - 0x21, 0xac, 0xe0, 0xad, 0xfe, 0xc0, 0x8e, 0x7b, 0xb8, 0x75, 0xcc, 0x26, - 0x9e, 0x30, 0xab, 0xfa, 0x7f, 0xbb, 0x2e, 0x20, 0x3a, 0xfe, 0xcf, 0x7a, - 0x39, 0xa3, 0xaf, 0xe7, 0x10, 0x4e, 0x0f, 0x1d, 0x50, 0x88, 0xb1, 0x32, - 0xd9, 0x2c, 0xb2, 0xb0, 0xbc, 0xe5, 0x39, 0xf8, 0x5a, 0x72, 0x13, 0x2d, - 0x84, 0x16, 0xef, 0xdc, 0x20, 0x59, 0x0b, 0xc2, 0x18, 0x63, 0x10, 0xd4, - 0x32, 0xfc, 0xb9, 0xb4, 0x81, 0x93, 0x0f, 0xb0, 0xb2, 0xbc, 0xbf, 0xf8, - 0x55, 0xff, 0x9e, 0x4a, 0xe7, 0x1a, 0xee, 0xd3, 0x44, 0xc7, 0x7d, 0x1c, - 0x8d, 0x83, 0xac, 0xaa, 0x22, 0x29, 0x63, 0xbd, 0x4a, 0xbe, 0x89, 0xe3, - 0x87, 0x5f, 0xb2, 0x26, 0x45, 0x9d, 0x48, 0x78, 0xfc, 0x21, 0xbf, 0x82, - 0xb8, 0xcf, 0x68, 0xeb, 0xfd, 0xd8, 0xe4, 0xff, 0x7f, 0x01, 0xd7, 0x3e, - 0x8e, 0xbe, 0xf9, 0xec, 0xe9, 0xd6, 0x8e, 0x9b, 0x8d, 0x0a, 0xde, 0x81, - 0x9c, 0xeb, 0xff, 0xff, 0xe9, 0x6b, 0xb9, 0xfb, 0x3a, 0xee, 0x37, 0x35, - 0xf3, 0x37, 0x96, 0x90, 0x50, 0xeb, 0xce, 0xed, 0x34, 0x56, 0x37, 0xcf, - 0xf6, 0x14, 0x3a, 0x9a, 0x79, 0x5c, 0x27, 0xbf, 0xf6, 0xce, 0x78, 0x73, - 0xf8, 0x1f, 0x1d, 0x4a, 0x26, 0xd8, 0xd2, 0x6d, 0xc6, 0xf9, 0x0c, 0xaf, - 0x11, 0x5f, 0xfc, 0x3e, 0x53, 0xf8, 0x1c, 0x6c, 0x70, 0xeb, 0xfd, 0xc9, - 0xfd, 0xa7, 0xdd, 0xa7, 0x54, 0x1f, 0xc3, 0xa1, 0xdf, 0xd1, 0xb1, 0xec, - 0xde, 0x63, 0xaf, 0xef, 0xf6, 0x5b, 0xd4, 0x60, 0x9d, 0x7f, 0x66, 0xb7, - 0x94, 0x74, 0xeb, 0xa3, 0x69, 0xd6, 0x0f, 0x4f, 0x10, 0x4b, 0x6f, 0xfa, - 0x37, 0x94, 0xd2, 0x7e, 0x4e, 0x75, 0x42, 0x36, 0xf1, 0xe5, 0x09, 0xef, - 0x44, 0xbc, 0x75, 0xff, 0xb0, 0x3c, 0x4f, 0xe7, 0x06, 0xa4, 0x75, 0xf2, - 0xdf, 0x7f, 0x1d, 0x7f, 0xf4, 0xf1, 0xef, 0x9f, 0x5b, 0xf7, 0x63, 0xee, - 0x8e, 0xbf, 0xee, 0x46, 0x9f, 0x83, 0x12, 0x3a, 0xb8, 0x88, 0x7d, 0xaa, - 0x37, 0xa4, 0xf3, 0x9d, 0x7b, 0xe4, 0xeb, 0x3a, 0xe0, 0xf8, 0xea, 0x61, - 0x26, 0x3f, 0x90, 0xa9, 0xdc, 0x95, 0x07, 0x04, 0x7e, 0xff, 0xc2, 0xe1, - 0xec, 0x6d, 0xeb, 0x89, 0xd7, 0xff, 0xfe, 0xfe, 0x7c, 0x6f, 0xc1, 0xff, - 0x63, 0xe6, 0x6f, 0x2c, 0xfc, 0x41, 0xa3, 0xaf, 0xff, 0x4f, 0x9b, 0xfb, - 0x48, 0x30, 0x07, 0x59, 0xd7, 0xfb, 0x71, 0xc0, 0xf5, 0xd9, 0x3a, 0xb0, - 0xff, 0x1d, 0x26, 0x82, 0x9a, 0x80, 0x9e, 0xea, 0x1e, 0x77, 0xf4, 0xf3, - 0x49, 0x85, 0xc9, 0xce, 0xbe, 0x11, 0xcf, 0x1d, 0x7e, 0x46, 0x3e, 0x71, - 0x0e, 0xa6, 0x20, 0xff, 0x60, 0xd7, 0xa3, 0xf7, 0xf4, 0xff, 0x76, 0x5c, - 0x40, 0x75, 0xf3, 0x1c, 0x68, 0x4e, 0xbf, 0xf7, 0x5d, 0x7e, 0xec, 0x7b, - 0xf5, 0x9d, 0x58, 0x7c, 0x53, 0x11, 0xdf, 0xfd, 0x98, 0xa2, 0xe1, 0x39, - 0xc4, 0x64, 0xeb, 0xfe, 0x49, 0x27, 0x7f, 0x5a, 0xd0, 0xea, 0x84, 0xcc, - 0x72, 0x12, 0x9c, 0x22, 0xf2, 0x1d, 0xee, 0xa2, 0xb0, 0xc9, 0xbe, 0x9c, - 0x86, 0x45, 0x99, 0x1e, 0xdb, 0x61, 0x95, 0xc2, 0x0e, 0xc6, 0x18, 0xe5, - 0xa2, 0x37, 0xa8, 0xd7, 0xfd, 0x1d, 0x16, 0xcc, 0x2c, 0xbe, 0xc6, 0xc9, - 0x79, 0x87, 0x6c, 0xb1, 0x07, 0x5d, 0x21, 0x3a, 0xfe, 0xe7, 0x20, 0x38, - 0xb3, 0xaf, 0xa7, 0xe4, 0x4e, 0x75, 0xdf, 0x40, 0x75, 0xee, 0xa2, 0xce, - 0xb4, 0xc7, 0x53, 0x9a, 0xcf, 0xc6, 0xef, 0xce, 0x33, 0xff, 0xa3, 0xaf, - 0xfa, 0x03, 0xdc, 0x0f, 0x1d, 0xa7, 0x52, 0x26, 0x26, 0xe5, 0x80, 0x23, - 0x14, 0x4d, 0x10, 0xf8, 0xa2, 0xdd, 0x3a, 0xf6, 0xbe, 0xe8, 0xeb, 0xed, - 0xe7, 0x85, 0x0e, 0xa9, 0xcf, 0x48, 0x22, 0x1f, 0x8f, 0x5d, 0xe8, 0x3a, - 0xff, 0x6f, 0xc8, 0x49, 0x3e, 0x8e, 0xbe, 0xc1, 0x89, 0x1d, 0x58, 0x7a, - 0x2b, 0x32, 0xbf, 0xd8, 0x0d, 0x67, 0x93, 0x87, 0x5f, 0x7f, 0xec, 0xd1, - 0xd7, 0xd1, 0xc7, 0x13, 0xaf, 0xf3, 0xf2, 0x40, 0x4d, 0xf4, 0x75, 0xf6, - 0xb5, 0x00, 0x3a, 0xa1, 0x1c, 0xf8, 0x42, 0x86, 0x3d, 0x22, 0xfc, 0x7d, - 0x93, 0x3b, 0xf9, 0x04, 0x73, 0x6b, 0x9d, 0x7d, 0x20, 0x7f, 0x23, 0xaf, - 0xb9, 0xf6, 0x00, 0x75, 0x41, 0xe3, 0x21, 0x1d, 0xfe, 0x49, 0xdd, 0x60, - 0x04, 0x1d, 0x7f, 0xc8, 0xde, 0xe4, 0xc3, 0x01, 0x3a, 0xfa, 0x5e, 0xcf, - 0xa7, 0x5e, 0x6c, 0x00, 0xeb, 0xdc, 0x85, 0x9d, 0x4e, 0x7b, 0x3f, 0x91, - 0xb2, 0x37, 0x7e, 0x89, 0xfe, 0xe4, 0xc7, 0x5e, 0x81, 0x91, 0xd4, 0x14, - 0xf1, 0xe6, 0x71, 0xe1, 0x07, 0x4c, 0x86, 0x12, 0x1a, 0x30, 0xf1, 0x55, - 0xff, 0xa3, 0x35, 0xf2, 0x10, 0x3f, 0x64, 0x75, 0xfc, 0x8c, 0xea, 0x7c, - 0x64, 0xea, 0x13, 0xef, 0xf2, 0x05, 0xfa, 0x03, 0xec, 0x69, 0xd7, 0xdd, - 0x81, 0x69, 0xd5, 0x23, 0xe7, 0xd1, 0x0f, 0x89, 0xaf, 0x9c, 0x5e, 0x63, - 0xaf, 0xc9, 0xe1, 0xc9, 0x1d, 0x7d, 0x0c, 0xc4, 0xc7, 0x5d, 0xf5, 0x67, - 0x5f, 0xde, 0x17, 0x06, 0x09, 0xd7, 0xe1, 0x70, 0x60, 0x9d, 0x6f, 0xfe, - 0x1e, 0x77, 0x8a, 0xaa, 0x74, 0x7c, 0x28, 0x40, 0x84, 0xbd, 0x22, 0x16, - 0x6b, 0xfd, 0x0c, 0x87, 0xf7, 0xe4, 0x8e, 0xbf, 0x93, 0x9b, 0xea, 0x24, - 0x75, 0xb6, 0x9d, 0x5c, 0x3f, 0x3e, 0x9a, 0x6c, 0x16, 0xde, 0x14, 0x50, - 0xeb, 0xec, 0x0a, 0x6d, 0x3a, 0xe8, 0x5e, 0x1b, 0xd7, 0x1b, 0xbf, 0xec, - 0x65, 0xf7, 0xec, 0x7d, 0x13, 0xad, 0xa3, 0xa9, 0x0f, 0xd3, 0x85, 0x4e, - 0x75, 0x70, 0x20, 0xab, 0x99, 0x64, 0xaa, 0x43, 0x5a, 0xc8, 0xad, 0xfe, - 0x79, 0x0e, 0x7b, 0xa8, 0x52, 0xa6, 0x86, 0xf3, 0xef, 0xa3, 0xaf, 0xbe, - 0xf5, 0xfc, 0x75, 0x04, 0xdf, 0xf8, 0x72, 0xf4, 0x0c, 0xc7, 0x5c, 0x30, - 0x75, 0xa6, 0x3a, 0xa6, 0x3c, 0x0e, 0x0d, 0xb8, 0xa5, 0xff, 0xca, 0x20, - 0xb7, 0x50, 0xb7, 0xdf, 0xc7, 0x5e, 0x06, 0x6c, 0x1d, 0x4a, 0x1f, 0x17, - 0x11, 0x2f, 0x97, 0xaf, 0xd6, 0x75, 0x94, 0x3a, 0xdb, 0x27, 0x5d, 0xc5, - 0x0e, 0xa8, 0x3d, 0xe4, 0x23, 0xfc, 0x47, 0xe8, 0x9d, 0xff, 0xf7, 0x72, - 0x5a, 0x8f, 0x4b, 0x18, 0xdc, 0x40, 0x75, 0xff, 0xa4, 0x9e, 0xee, 0x6f, - 0xef, 0xe0, 0xeb, 0xb3, 0x47, 0x54, 0x1e, 0xa4, 0x8f, 0xeb, 0x48, 0xc5, - 0xf4, 0x29, 0x2c, 0x03, 0xaf, 0xc9, 0x0b, 0x85, 0x9d, 0x6c, 0x3a, 0x90, - 0xfb, 0x1c, 0xa3, 0x42, 0x1b, 0x24, 0xb5, 0x0a, 0xc7, 0xb1, 0x85, 0x21, - 0x23, 0xd8, 0x40, 0xbc, 0x6d, 0xd7, 0xb5, 0x13, 0x1d, 0x7f, 0x60, 0x73, - 0x6a, 0x70, 0xea, 0x3a, 0xcb, 0x3a, 0xbc, 0x5d, 0x6d, 0x0a, 0xbf, 0x01, - 0x38, 0x8a, 0x1d, 0x73, 0xa8, 0x75, 0x4c, 0x8c, 0x25, 0x8e, 0x75, 0x1c, - 0x04, 0x42, 0x4f, 0x76, 0x70, 0xeb, 0xbd, 0x07, 0x5f, 0xa3, 0xb9, 0xb5, - 0xce, 0xa5, 0x9e, 0x8b, 0x8a, 0x80, 0x56, 0xfe, 0x4f, 0x67, 0x5d, 0x43, - 0xaf, 0xee, 0xfe, 0xf3, 0xf5, 0x0e, 0xbc, 0xcb, 0x2c, 0x95, 0x7f, 0xc1, - 0x89, 0xfe, 0xe7, 0x5f, 0x72, 0x95, 0x2f, 0xee, 0xc9, 0xce, 0xbd, 0x28, - 0x59, 0xd4, 0x14, 0x64, 0xb5, 0x35, 0x12, 0xe6, 0x16, 0xbd, 0x0b, 0x43, - 0xab, 0x0f, 0x5d, 0xa7, 0xb7, 0xc9, 0xcd, 0x80, 0x9d, 0x7e, 0xec, 0x6e, - 0xec, 0x67, 0x5f, 0xff, 0x47, 0xb4, 0x1c, 0xf2, 0x77, 0xfc, 0xdf, 0xc7, - 0x57, 0x4f, 0xeb, 0xc5, 0x56, 0xe1, 0xd7, 0xfb, 0x31, 0xbf, 0x76, 0xf7, - 0x0e, 0xbf, 0xf2, 0x40, 0xf8, 0x73, 0xd0, 0xc9, 0xd7, 0xbd, 0xcf, 0xce, - 0xb6, 0x8e, 0xa1, 0x35, 0xbf, 0x8e, 0xdf, 0xff, 0xb0, 0x31, 0x9b, 0xfd, - 0xf2, 0x0f, 0xf2, 0xcd, 0x1d, 0x72, 0xc0, 0x75, 0xce, 0x27, 0x57, 0x4d, - 0x53, 0x8b, 0x5f, 0x96, 0x9e, 0x03, 0x9d, 0x53, 0xaa, 0x54, 0xc8, 0x4f, - 0x31, 0x91, 0x4c, 0x21, 0xc3, 0x57, 0x68, 0x12, 0x1f, 0x42, 0x03, 0xf2, - 0x0b, 0xee, 0xf9, 0x27, 0x3a, 0xff, 0x35, 0x34, 0x39, 0xb5, 0xce, 0xbe, - 0x89, 0xde, 0x47, 0x5d, 0x9e, 0x3a, 0xfd, 0x93, 0x8e, 0x6e, 0x75, 0x62, - 0x2c, 0x77, 0x22, 0xe1, 0x97, 0x48, 0x44, 0x56, 0xfa, 0x05, 0x18, 0xce, - 0xbd, 0xd8, 0x09, 0xd7, 0x73, 0x47, 0x51, 0xc8, 0x5b, 0x5f, 0xe8, 0x19, - 0x3a, 0xf0, 0x27, 0x5f, 0x79, 0x6b, 0xe1, 0xd7, 0xff, 0x02, 0x05, 0xaf, - 0xe0, 0x7d, 0x19, 0x1d, 0x7a, 0x49, 0xd3, 0xaf, 0xbc, 0x39, 0x23, 0xaf, - 0xd9, 0xfb, 0x07, 0x4e, 0x75, 0xff, 0xe4, 0xd7, 0x70, 0x23, 0x9b, 0x47, - 0x34, 0x75, 0x49, 0x34, 0x45, 0x0c, 0x37, 0x22, 0x99, 0x13, 0x83, 0x62, - 0x41, 0xe2, 0xba, 0x62, 0x1b, 0x6f, 0x56, 0x11, 0x54, 0x46, 0x51, 0x3c, - 0x29, 0xe4, 0x62, 0x18, 0xd3, 0x72, 0x50, 0xee, 0xf1, 0xa0, 0x24, 0x64, - 0xf3, 0x42, 0xf7, 0x90, 0xe3, 0x5b, 0xdf, 0x65, 0xcf, 0x3c, 0x63, 0x40, - 0x84, 0xdb, 0x04, 0xb8, 0x63, 0x4c, 0xd4, 0xa7, 0x5f, 0x46, 0x7d, 0xb5, - 0x25, 0x92, 0x2d, 0x93, 0x1f, 0xb1, 0xae, 0x5f, 0xf2, 0xbe, 0x4c, 0xd8, - 0xd7, 0xf0, 0x75, 0xff, 0xff, 0x7f, 0x0a, 0xfb, 0x49, 0xd7, 0x4f, 0x67, - 0x00, 0xb7, 0x91, 0xd4, 0xaa, 0xa4, 0x79, 0xe3, 0xa5, 0x09, 0xe5, 0xfb, - 0x8d, 0x77, 0x69, 0xa2, 0xb7, 0xbf, 0xf3, 0xc9, 0x5c, 0xe3, 0x5d, 0xda, - 0x68, 0x9c, 0x2c, 0xae, 0x1f, 0xea, 0xcc, 0xee, 0x61, 0x04, 0xeb, 0x74, - 0xeb, 0x68, 0xea, 0xfc, 0xd0, 0x6c, 0x88, 0x5f, 0x35, 0xdd, 0xa6, 0x8b, - 0x46, 0xff, 0xf6, 0x07, 0xae, 0xa4, 0xd3, 0x26, 0xbf, 0x59, 0xd5, 0xc3, - 0xfa, 0xe9, 0x6d, 0xf3, 0x5c, 0x40, 0x75, 0xff, 0x4d, 0x8c, 0x7a, 0xe7, - 0x1f, 0xc7, 0x5f, 0xd0, 0xe3, 0xf8, 0x70, 0xeb, 0x91, 0x43, 0xaf, 0xff, - 0xd3, 0xc7, 0xa0, 0x3c, 0x8e, 0xbe, 0x87, 0x00, 0x75, 0xff, 0xa3, 0x77, - 0x63, 0xe8, 0xbb, 0x1c, 0xe7, 0x5f, 0xfa, 0x38, 0x0c, 0x4c, 0xe7, 0xbf, - 0x3a, 0xa1, 0x1a, 0x9d, 0x53, 0xd2, 0x25, 0xb2, 0x64, 0xc6, 0x75, 0x0e, - 0xab, 0xfd, 0xde, 0xfe, 0xa2, 0xe3, 0x47, 0x5f, 0xff, 0x93, 0x43, 0x9b, - 0x5f, 0xc3, 0x9a, 0xeb, 0xcc, 0x75, 0x62, 0x22, 0x66, 0x35, 0xbe, 0xc0, - 0x3f, 0x4e, 0xbb, 0xba, 0x3a, 0xca, 0xb0, 0x15, 0xd6, 0x31, 0x67, 0x59, - 0x09, 0xf6, 0x91, 0x4c, 0x40, 0xb3, 0xce, 0xc6, 0x89, 0xe8, 0x5c, 0x6c, - 0x91, 0xfd, 0x20, 0xbe, 0x6b, 0xbb, 0x4d, 0x16, 0xd5, 0xff, 0xfd, 0x0f, - 0xe8, 0xec, 0x69, 0x12, 0x49, 0xcc, 0x09, 0xd7, 0xf7, 0x61, 0x70, 0x81, - 0x3a, 0xb8, 0x8a, 0xed, 0x16, 0xf9, 0x5a, 0xff, 0xdd, 0x40, 0xbc, 0x83, - 0xd4, 0x59, 0xd7, 0xfd, 0x98, 0xdd, 0x9f, 0xfa, 0x9c, 0x3a, 0xfa, 0x36, - 0xe2, 0x1d, 0x77, 0x80, 0x75, 0xff, 0x44, 0xa3, 0x93, 0xc7, 0x27, 0x3a, - 0xff, 0xfd, 0xf8, 0xa6, 0xd4, 0xf7, 0x63, 0xda, 0x8d, 0xb0, 0x75, 0xff, - 0x47, 0x3e, 0x6a, 0x3a, 0xe8, 0x75, 0xfe, 0xea, 0x3c, 0xbc, 0x93, 0x9d, - 0x58, 0x9e, 0xcb, 0x4c, 0x26, 0x3d, 0xe1, 0xda, 0xc8, 0x44, 0x5b, 0x47, - 0x2c, 0xab, 0xec, 0x9c, 0x5f, 0xca, 0x3f, 0x03, 0xf8, 0x9d, 0x7f, 0x0e, - 0xca, 0x73, 0x14, 0x3a, 0xfc, 0x93, 0xae, 0x1a, 0x75, 0xf9, 0xf7, 0x97, - 0xdd, 0x1d, 0x7f, 0xe4, 0x9b, 0x5b, 0x5c, 0x67, 0xfc, 0x27, 0x59, 0x55, - 0x11, 0xe0, 0x25, 0xde, 0x2f, 0xda, 0x4f, 0xf4, 0xaa, 0x95, 0x4f, 0x1c, - 0x11, 0xb9, 0x5c, 0xbe, 0x9d, 0x7e, 0xe3, 0x5d, 0xda, 0x68, 0xb9, 0x6c, - 0xa8, 0x4f, 0x27, 0x05, 0xaf, 0xdc, 0x6b, 0xbb, 0x4d, 0x17, 0x6d, 0xff, - 0x24, 0xa4, 0x82, 0x08, 0x91, 0xd7, 0xc9, 0xc7, 0x01, 0xd6, 0x57, 0x11, - 0x12, 0xe6, 0x7a, 0x36, 0xa8, 0x77, 0x08, 0xb3, 0x94, 0xca, 0x7d, 0x30, - 0x31, 0xc1, 0x29, 0x4a, 0x3b, 0x4a, 0xe8, 0xb9, 0x8e, 0x16, 0xfd, 0x97, - 0xa8, 0x33, 0xa0, 0x1a, 0x74, 0xf4, 0x2c, 0x6f, 0xf2, 0xb9, 0xc6, 0xbb, - 0xb4, 0xd1, 0x53, 0xdf, 0x85, 0x5e, 0x6b, 0x47, 0x5d, 0x3a, 0xce, 0xbf, - 0x6e, 0xb7, 0x71, 0x3a, 0x82, 0x6f, 0x7f, 0x17, 0xb7, 0x8e, 0xbf, 0xe8, - 0x79, 0xfe, 0x6f, 0xa8, 0x09, 0xd4, 0x87, 0x96, 0x22, 0x17, 0xcd, 0x77, - 0x69, 0xa2, 0xb9, 0xbf, 0xca, 0xe7, 0x1a, 0xee, 0xd3, 0x45, 0x9d, 0x79, - 0xde, 0x47, 0x5f, 0xc9, 0xac, 0x17, 0x64, 0xea, 0xe2, 0x2c, 0x7a, 0x5a, - 0x27, 0xfe, 0x1a, 0xbf, 0xfd, 0xe8, 0xd7, 0xcf, 0xf5, 0xe8, 0x9a, 0x64, - 0x3a, 0xfe, 0x45, 0xcf, 0xff, 0x24, 0x75, 0xfe, 0x8e, 0xfc, 0x5b, 0x16, - 0xc0, 0xf1, 0xd5, 0x88, 0xbb, 0xea, 0x76, 0xd2, 0xfb, 0xf7, 0x33, 0xc8, - 0xb3, 0xaf, 0x9c, 0x60, 0x27, 0x5f, 0xa6, 0x85, 0xc7, 0xd3, 0xae, 0x92, - 0xce, 0xac, 0x37, 0xe2, 0x53, 0x7e, 0xe3, 0x5d, 0xda, 0x68, 0x90, 0xaf, - 0xfd, 0x8b, 0xc7, 0xe4, 0xff, 0x37, 0x59, 0xd7, 0xfc, 0x9b, 0xeb, 0xc3, - 0x0b, 0xd1, 0xd7, 0x49, 0x5c, 0x45, 0x67, 0x4c, 0xc0, 0x83, 0x7f, 0xf7, - 0x51, 0x79, 0xaf, 0x9b, 0xcb, 0x3c, 0x75, 0xf4, 0xbb, 0xf7, 0x47, 0x54, - 0x1f, 0x56, 0x23, 0x5f, 0x31, 0x7d, 0x85, 0x9d, 0x7f, 0x77, 0x5a, 0xce, - 0x4e, 0x75, 0xd0, 0xc9, 0xd5, 0x87, 0x88, 0x85, 0xd7, 0x97, 0xb6, 0x47, - 0x5f, 0xfe, 0xec, 0x01, 0x6f, 0x2d, 0x7b, 0x31, 0x67, 0x59, 0x59, 0xd7, - 0x5a, 0xc2, 0xdb, 0x90, 0xd1, 0x48, 0x7b, 0xf0, 0xc5, 0x64, 0xdd, 0x5e, - 0x78, 0x65, 0x8c, 0x29, 0xb4, 0x41, 0xe6, 0xaf, 0xc8, 0x3e, 0x8f, 0x5f, - 0xfc, 0xaf, 0x5f, 0x43, 0x9e, 0xf4, 0x00, 0xeb, 0xff, 0xca, 0xad, 0xe4, - 0xae, 0x71, 0xae, 0xed, 0x34, 0x4f, 0x94, 0xd5, 0xf7, 0x94, 0x3f, 0x63, - 0x9d, 0xd0, 0x5c, 0x34, 0x3a, 0x87, 0x72, 0x6e, 0x75, 0xff, 0xf4, 0xa7, - 0x61, 0xa1, 0x8b, 0x9d, 0xbc, 0xf9, 0xf3, 0xbb, 0x27, 0x54, 0x8f, 0xe8, - 0x02, 0xd7, 0xec, 0xe6, 0x64, 0xc7, 0x59, 0x5e, 0x9e, 0x47, 0xd2, 0x2b, - 0xf7, 0x1a, 0xee, 0xd3, 0x45, 0x65, 0x7f, 0xe7, 0x92, 0xb9, 0xc6, 0xbb, - 0xb4, 0xd1, 0x37, 0x59, 0x5c, 0x3f, 0xd5, 0x99, 0xd3, 0x51, 0xa0, 0x90, - 0xa8, 0xbe, 0x6b, 0xbb, 0x4d, 0x12, 0xb5, 0xff, 0xf7, 0x27, 0x18, 0xe3, - 0x84, 0x5f, 0x91, 0xb4, 0xea, 0xe1, 0xfe, 0x7e, 0x5b, 0x7e, 0x18, 0x0b, - 0xf4, 0xeb, 0xf2, 0xab, 0x79, 0x2b, 0x87, 0x90, 0x84, 0x77, 0xfe, 0xf6, - 0x2b, 0x9c, 0x49, 0xdd, 0x67, 0x5f, 0xfe, 0x62, 0x98, 0x86, 0x06, 0xb1, - 0xe4, 0x99, 0xcc, 0x3a, 0xff, 0xc9, 0xaf, 0xd6, 0x29, 0xb7, 0xf7, 0x3a, - 0xfe, 0x81, 0x76, 0xbb, 0x19, 0xd5, 0x23, 0xed, 0x5a, 0x05, 0xc1, 0xe1, - 0xd7, 0xee, 0x35, 0xdd, 0xa6, 0x89, 0x72, 0xff, 0x91, 0xe5, 0xe1, 0x85, - 0xe8, 0xeb, 0xf4, 0xb6, 0x53, 0xae, 0x75, 0xe8, 0xd9, 0x83, 0xaf, 0x20, - 0xc1, 0xd5, 0x23, 0xdf, 0x09, 0x4e, 0xd1, 0xdb, 0xff, 0xf3, 0xf9, 0x3f, - 0x90, 0xa4, 0xa3, 0xc3, 0xfc, 0x8e, 0xbf, 0xa5, 0xdc, 0x1c, 0x69, 0xd7, - 0xa5, 0xdf, 0x1d, 0x77, 0x61, 0x0f, 0x1f, 0xa5, 0x77, 0xff, 0x0a, 0x03, - 0x5c, 0x84, 0x93, 0xe8, 0xea, 0xc3, 0xed, 0x42, 0xcb, 0xcf, 0x25, 0x58, - 0x9a, 0xb1, 0xb8, 0x86, 0x14, 0x88, 0xb0, 0x5b, 0xa6, 0x6f, 0x09, 0x5d, - 0x18, 0xfa, 0x30, 0x8b, 0xff, 0x7e, 0xb5, 0x75, 0x03, 0xec, 0xe1, 0xd6, - 0x55, 0x17, 0x0c, 0x17, 0x2d, 0x67, 0x50, 0x98, 0xbf, 0xf9, 0x57, 0x92, - 0xb9, 0xc6, 0xbb, 0xb4, 0xd1, 0x1d, 0xdf, 0xf7, 0xbb, 0x92, 0x55, 0xc7, - 0x47, 0x5f, 0xcc, 0x21, 0x86, 0xe0, 0x9d, 0x77, 0xfd, 0x3a, 0xfe, 0x60, - 0x0e, 0x75, 0xfc, 0x75, 0xff, 0xfd, 0xe9, 0x20, 0x7a, 0x9b, 0x7e, 0x60, - 0x78, 0x9f, 0xb4, 0xeb, 0xfd, 0x8c, 0xea, 0x07, 0xda, 0x3a, 0xfe, 0x00, - 0xe6, 0xfe, 0xc3, 0xaf, 0xce, 0xa7, 0x70, 0x07, 0x5f, 0xc2, 0x07, 0xe3, - 0xfd, 0x3a, 0xa1, 0x10, 0x1c, 0x2c, 0x72, 0x7b, 0xff, 0x27, 0x3e, 0x68, - 0x71, 0x70, 0xd3, 0xaf, 0xfd, 0x03, 0xff, 0x91, 0xf6, 0xbc, 0x8e, 0xbf, - 0xf0, 0xff, 0x2f, 0x98, 0x83, 0x0b, 0x3a, 0xf9, 0xae, 0xed, 0x34, 0x54, - 0x37, 0xfd, 0x9d, 0xc1, 0x7e, 0x71, 0x0e, 0xa5, 0x13, 0x1c, 0x69, 0xf2, - 0x1f, 0x70, 0xfb, 0x45, 0xb7, 0x98, 0xde, 0x0e, 0xba, 0x58, 0x75, 0xff, - 0x4b, 0xc9, 0xc7, 0x6a, 0x09, 0xd7, 0xd2, 0x06, 0xb0, 0xeb, 0xff, 0xce, - 0xbc, 0xe0, 0xe2, 0x6d, 0x4e, 0x39, 0xd7, 0xff, 0x74, 0x72, 0x6f, 0x77, - 0x38, 0x9a, 0x3a, 0xfd, 0xb8, 0xa2, 0xd0, 0xea, 0x84, 0x58, 0x62, 0x3a, - 0x21, 0xdf, 0xe8, 0xf3, 0xf7, 0xe0, 0x60, 0xeb, 0xff, 0x67, 0xb5, 0xcc, - 0x9b, 0xa8, 0xa1, 0xd7, 0xfd, 0xf1, 0xc7, 0x36, 0x3e, 0x77, 0xf3, 0xa9, - 0x0f, 0xfb, 0xf3, 0xfb, 0xfd, 0x28, 0xe4, 0xf1, 0xc9, 0xce, 0xbf, 0xf6, - 0xb0, 0x7d, 0xac, 0x92, 0x74, 0xeb, 0xfb, 0x59, 0xb4, 0x63, 0x73, 0xab, - 0x47, 0xd5, 0xe3, 0xcb, 0xff, 0xe8, 0x06, 0x0f, 0xc7, 0xf7, 0xce, 0xe0, - 0x1c, 0xeb, 0x86, 0x73, 0xaa, 0x13, 0x26, 0xc8, 0x4f, 0x21, 0x10, 0xa8, - 0x5f, 0xdb, 0x5d, 0x7d, 0x65, 0xce, 0xbf, 0xff, 0xc9, 0x1e, 0x7e, 0xab, - 0xae, 0xe0, 0xfb, 0xe0, 0x25, 0xa3, 0xad, 0x88, 0x89, 0x11, 0x2f, 0xbe, - 0xef, 0xb2, 0x73, 0xaf, 0xd9, 0x3b, 0x8e, 0xd3, 0xaf, 0xff, 0xff, 0xf4, - 0x4b, 0xe7, 0xba, 0x91, 0xaf, 0x99, 0xfb, 0x63, 0x6f, 0xcc, 0xe7, 0x33, - 0x6f, 0xef, 0xd3, 0xaf, 0xba, 0x2f, 0xb0, 0x75, 0x62, 0x60, 0xa2, 0x45, - 0xa2, 0x8f, 0x42, 0x62, 0xff, 0xff, 0xbf, 0x76, 0x34, 0x9f, 0xae, 0x9e, - 0x8e, 0xa7, 0xb5, 0x81, 0x3a, 0xca, 0xb0, 0x19, 0x23, 0xac, 0x59, 0x73, - 0x08, 0x5e, 0x0b, 0xe7, 0x5f, 0x0c, 0x2c, 0xb2, 0x34, 0xa5, 0x12, 0xda, - 0x3b, 0xb8, 0xaa, 0x1b, 0x72, 0x1a, 0x2b, 0x2d, 0xec, 0x2c, 0x46, 0x34, - 0x8d, 0x43, 0x43, 0xd1, 0x95, 0xec, 0xa0, 0xdf, 0x35, 0xdd, 0xa6, 0x8a, - 0xa2, 0xff, 0x72, 0x36, 0xef, 0x2c, 0xf1, 0xd5, 0xc3, 0xe2, 0xfc, 0xb6, - 0xff, 0xcf, 0x25, 0x73, 0x8d, 0x77, 0x69, 0xa2, 0x6b, 0xbe, 0x8e, 0x47, - 0x8e, 0xb9, 0xfc, 0x75, 0x04, 0xda, 0xac, 0x82, 0xca, 0xe2, 0x30, 0xd6, - 0x46, 0xef, 0xf7, 0xee, 0x35, 0xdd, 0xa6, 0x8a, 0xb2, 0xff, 0xa2, 0x51, - 0xc9, 0xe3, 0x93, 0x9d, 0x65, 0x70, 0xfb, 0x04, 0xce, 0xff, 0xbb, 0x1b, - 0xfa, 0x3a, 0xec, 0x67, 0x5f, 0xfc, 0x0c, 0x15, 0x64, 0x0d, 0x4e, 0xe2, - 0x75, 0x2a, 0x7f, 0xf0, 0x77, 0x7f, 0xf2, 0xaf, 0x25, 0x73, 0x8d, 0x77, - 0x69, 0xa2, 0x44, 0xbf, 0x71, 0xae, 0xed, 0x34, 0x5a, 0x57, 0xfe, 0x79, - 0x2b, 0x9c, 0x6b, 0xbb, 0x4d, 0x13, 0xed, 0x95, 0xc3, 0xfd, 0x59, 0x9d, - 0xff, 0xe5, 0x56, 0xf2, 0x57, 0x38, 0xd7, 0x76, 0x9a, 0x28, 0x4b, 0xff, - 0xb1, 0x95, 0x7c, 0xa3, 0xe9, 0x3d, 0x07, 0x5f, 0xbd, 0xfb, 0x5f, 0x47, - 0x5f, 0x24, 0xf1, 0xc3, 0xa9, 0x67, 0x93, 0xd2, 0x8b, 0xf7, 0x1a, 0xee, - 0xd3, 0x45, 0x1f, 0x7f, 0xd1, 0x28, 0xe4, 0xf1, 0xc9, 0xce, 0xbf, 0xff, - 0xff, 0xdf, 0x53, 0x93, 0x47, 0x79, 0x9d, 0x7f, 0xba, 0xc5, 0x1c, 0x41, - 0x03, 0x13, 0x76, 0x0e, 0xbf, 0x3e, 0x93, 0xd0, 0x75, 0xff, 0x44, 0xd0, - 0x31, 0x37, 0x60, 0xea, 0x84, 0x76, 0x29, 0x09, 0x01, 0x25, 0xbf, 0xff, - 0xb0, 0x3d, 0x8f, 0xaa, 0xf8, 0x5c, 0x1a, 0xd4, 0x00, 0xab, 0xcf, 0x25, - 0x61, 0x50, 0x56, 0x11, 0x09, 0x9f, 0xa3, 0x25, 0xd9, 0x34, 0xbf, 0xfb, - 0x3a, 0xaf, 0x94, 0x7d, 0x27, 0xa0, 0xeb, 0x2b, 0x3a, 0xb4, 0x05, 0xca, - 0x98, 0xf3, 0x25, 0x43, 0x6d, 0xd3, 0x3c, 0xe3, 0x7c, 0x91, 0x71, 0x45, - 0x4a, 0x4a, 0xab, 0x65, 0x2c, 0x6f, 0x0a, 0x14, 0x85, 0x34, 0xc4, 0x5d, - 0x86, 0x70, 0x0a, 0x3d, 0x2e, 0x5e, 0xff, 0x2b, 0x9c, 0x6b, 0xbb, 0x4d, - 0x11, 0x15, 0xfd, 0x9c, 0x6b, 0xbb, 0x4d, 0x11, 0x5d, 0xff, 0x31, 0xab, - 0x9c, 0x6b, 0xbb, 0x4d, 0x15, 0xc5, 0x2a, 0x88, 0x07, 0x38, 0xbf, 0xfc, - 0x08, 0x16, 0xaa, 0xfe, 0x07, 0xd1, 0x91, 0xd7, 0xca, 0xcf, 0x33, 0x19, - 0xd6, 0x4d, 0xcf, 0xcc, 0x09, 0x77, 0xd9, 0xd7, 0xf1, 0xd7, 0xfb, 0x13, - 0x80, 0x07, 0xfa, 0x3a, 0xcc, 0x01, 0x3d, 0x3d, 0x10, 0x5f, 0xff, 0xde, - 0xd2, 0x75, 0xd2, 0x48, 0x3e, 0xff, 0xbc, 0xc3, 0xaf, 0xdc, 0x6b, 0xbb, - 0x4d, 0x14, 0xf5, 0xfe, 0x5a, 0x07, 0xf7, 0xe4, 0x8e, 0xb9, 0x68, 0x75, - 0x41, 0xe4, 0x34, 0xce, 0xff, 0xff, 0x4a, 0x3d, 0xaf, 0xd6, 0xd4, 0x04, - 0x67, 0x53, 0xf6, 0x9d, 0x7f, 0xff, 0x73, 0x9f, 0xf3, 0x90, 0x38, 0xa2, - 0x77, 0xb9, 0xf4, 0xeb, 0xff, 0x92, 0x58, 0x20, 0x85, 0xa7, 0x24, 0x75, - 0xfe, 0x94, 0x72, 0x78, 0xe4, 0xe7, 0x5f, 0x7c, 0x17, 0x91, 0xd7, 0xe7, - 0xce, 0xa2, 0xce, 0xad, 0x1e, 0x3e, 0xd2, 0x2a, 0x84, 0x4f, 0xe3, 0xdd, - 0xff, 0x90, 0x61, 0x71, 0x21, 0xc5, 0x9d, 0x7f, 0xd0, 0x2d, 0xcd, 0xb9, - 0xed, 0x1d, 0x7e, 0x79, 0xe3, 0x9f, 0x9d, 0x4c, 0x25, 0x6f, 0x30, 0x57, - 0x8b, 0x2d, 0x7b, 0xdc, 0x85, 0x18, 0x5d, 0x74, 0x61, 0xc1, 0xa2, 0x1d, - 0xa7, 0x5b, 0x27, 0x17, 0xff, 0x9e, 0x4a, 0x84, 0x5d, 0x9d, 0x6a, 0x00, - 0x75, 0xff, 0xe0, 0x03, 0xfd, 0x2b, 0xf4, 0x5d, 0x63, 0x07, 0x5f, 0xfc, - 0x38, 0x07, 0x10, 0x2a, 0xb4, 0x59, 0xd5, 0xc4, 0x47, 0x79, 0x32, 0x95, - 0x4e, 0x7c, 0x30, 0xa4, 0x48, 0x6c, 0x5b, 0x0e, 0xbf, 0x0c, 0x7e, 0xc1, - 0xd1, 0xd7, 0xf2, 0x9c, 0x70, 0xb8, 0x9d, 0x41, 0x3e, 0x6c, 0x0f, 0x72, - 0xbb, 0xff, 0x90, 0x3c, 0x7d, 0xd5, 0xe7, 0x22, 0x73, 0xa9, 0x53, 0xf3, - 0xe9, 0x6d, 0xc1, 0x83, 0xaf, 0xff, 0xdd, 0x8e, 0x64, 0x91, 0xfd, 0x81, - 0x4f, 0xda, 0x55, 0xfa, 0x24, 0x0f, 0xe4, 0x75, 0xf3, 0x5d, 0xda, 0x68, - 0xac, 0xea, 0x63, 0xd5, 0xe1, 0x45, 0xf7, 0x91, 0x7a, 0x3a, 0xfe, 0x9d, - 0x70, 0x32, 0xd1, 0xd7, 0xec, 0xf6, 0xbe, 0xe8, 0xeb, 0xd1, 0x3a, 0x1d, - 0x7e, 0xf0, 0x3e, 0x8c, 0x8e, 0xbd, 0xfb, 0xe8, 0xeb, 0xfe, 0xc9, 0x27, - 0xec, 0x6c, 0x58, 0x16, 0x75, 0xfb, 0x26, 0x9f, 0xf0, 0x1d, 0x65, 0x61, - 0x51, 0x10, 0x45, 0x72, 0x15, 0x1b, 0x91, 0xf0, 0x85, 0x65, 0xbd, 0x29, - 0x71, 0xb1, 0x29, 0xd0, 0xe7, 0xd4, 0x1b, 0xff, 0x75, 0x3c, 0xfc, 0x9e, - 0x10, 0x27, 0x5f, 0xbc, 0x83, 0x8b, 0x3a, 0xfa, 0x4e, 0x2a, 0xe1, 0xf1, - 0x6c, 0x1e, 0xdf, 0xf9, 0xe4, 0xae, 0x71, 0xae, 0xed, 0x34, 0x48, 0xb7, - 0xff, 0xef, 0x77, 0x05, 0x5f, 0x3b, 0xef, 0xa5, 0x14, 0x73, 0xaf, 0xfc, - 0xfe, 0x56, 0x13, 0x89, 0xef, 0xce, 0xa5, 0x51, 0xbf, 0x09, 0x4e, 0xaf, - 0x7f, 0x67, 0x1a, 0xee, 0xd3, 0x45, 0x93, 0x7f, 0xfb, 0xda, 0xfb, 0xa5, - 0x72, 0x74, 0x19, 0x68, 0xea, 0x55, 0x10, 0xb8, 0x71, 0x7f, 0xff, 0x9d, - 0x3d, 0xff, 0x1f, 0x4a, 0xb7, 0xa9, 0xc8, 0x96, 0x8e, 0xbf, 0xb3, 0x8d, - 0x77, 0x69, 0xa2, 0xd8, 0xbf, 0xff, 0x98, 0x1d, 0xf8, 0x39, 0xcf, 0x6b, - 0xb3, 0x7c, 0xf9, 0xdd, 0x93, 0xaf, 0x73, 0xfe, 0x9d, 0x77, 0x95, 0x84, - 0x43, 0xf1, 0xaa, 0x95, 0x47, 0x72, 0x42, 0xfe, 0xf6, 0x6b, 0x0e, 0xbe, - 0x6b, 0xbb, 0x4d, 0x16, 0xdd, 0xf6, 0xa7, 0x7e, 0x1d, 0x5c, 0x3c, 0xff, - 0x16, 0xdf, 0xc9, 0xdf, 0x20, 0x3f, 0x3a, 0xff, 0xa2, 0x51, 0xc9, 0xe3, - 0x93, 0x9d, 0x65, 0x64, 0x8f, 0x1c, 0x69, 0x98, 0x88, 0x4b, 0x6f, 0xff, - 0x60, 0x81, 0x55, 0xb8, 0x73, 0x05, 0x43, 0xaf, 0x30, 0xba, 0x13, 0xaf, - 0x4f, 0xd4, 0x3a, 0xff, 0xcc, 0x26, 0x13, 0x0f, 0xf7, 0x70, 0x60, 0x07, - 0x5f, 0xd0, 0x32, 0x0f, 0xeb, 0x3a, 0xf9, 0xae, 0xed, 0x34, 0x5e, 0x17, - 0xfe, 0x7f, 0x46, 0xde, 0x73, 0x37, 0xd1, 0xd5, 0xc3, 0xed, 0x12, 0xdb, - 0xef, 0x6c, 0xe7, 0x4e, 0xbf, 0x2e, 0x06, 0x4e, 0x75, 0xfd, 0x03, 0xed, - 0xae, 0xd3, 0xaf, 0xe9, 0x46, 0xd8, 0xe6, 0xe7, 0x54, 0x8f, 0x73, 0x0b, - 0x6f, 0xf4, 0x79, 0xfb, 0xf0, 0x30, 0x75, 0xff, 0xbe, 0xaf, 0x79, 0x7b, - 0x07, 0xda, 0x3a, 0xec, 0x50, 0xea, 0x83, 0xd7, 0xc4, 0x1b, 0xe4, 0x9f, - 0x16, 0x75, 0xfb, 0x04, 0x1b, 0x10, 0x75, 0xfa, 0x3e, 0xfe, 0xfa, 0x3a, - 0xff, 0xe5, 0xc3, 0x7e, 0x60, 0xff, 0x2c, 0xd1, 0xd7, 0xff, 0xfe, 0x74, - 0xf3, 0xad, 0xc4, 0x0d, 0xea, 0x72, 0x5f, 0x65, 0x82, 0x75, 0xfd, 0x1b, - 0xef, 0x27, 0xdc, 0xea, 0xc4, 0x6f, 0x75, 0x17, 0xf6, 0xab, 0xff, 0xb3, - 0xbd, 0x79, 0x2d, 0x23, 0x92, 0x3a, 0xe8, 0x01, 0xd5, 0x23, 0xd7, 0xf2, - 0x15, 0x30, 0x17, 0x2a, 0xd8, 0x44, 0x0c, 0x4c, 0x72, 0x74, 0xbc, 0x84, - 0xd6, 0xe4, 0x28, 0x49, 0x34, 0x20, 0x56, 0x43, 0xd8, 0x45, 0x39, 0x00, - 0x08, 0x44, 0xa3, 0x51, 0x83, 0xfa, 0x10, 0xf7, 0xfb, 0x75, 0x70, 0x0f, - 0xcd, 0x1d, 0x7f, 0x80, 0xac, 0xd2, 0x81, 0xf1, 0xd4, 0xaa, 0x6b, 0xd1, - 0x0f, 0x6e, 0x1a, 0x5e, 0x4c, 0xdc, 0xeb, 0xe6, 0xbb, 0xb4, 0xd1, 0x7a, - 0x5f, 0xf9, 0x3d, 0xd1, 0x79, 0x01, 0xc0, 0x75, 0x70, 0xfa, 0x56, 0x5b, - 0x79, 0x69, 0xe3, 0xaf, 0xf9, 0xfd, 0x28, 0x53, 0xc9, 0x39, 0xd4, 0xb3, - 0xd4, 0x11, 0xbb, 0xf6, 0x2f, 0xae, 0x13, 0xa8, 0x29, 0xa0, 0xe4, 0x21, - 0x3e, 0xbb, 0x6c, 0x10, 0xdf, 0xff, 0xed, 0xb8, 0x2a, 0x87, 0x03, 0xdc, - 0x5a, 0xde, 0x58, 0x27, 0x5f, 0xe5, 0x7d, 0x93, 0x49, 0xc2, 0x75, 0x22, - 0x25, 0x3a, 0xc1, 0x4a, 0xa3, 0xf7, 0x21, 0xb7, 0x50, 0xdc, 0x68, 0xcf, - 0x0b, 0xf9, 0x42, 0x5b, 0x27, 0x64, 0xdb, 0x18, 0xa2, 0x4a, 0x45, 0x9a, - 0x30, 0x7e, 0x46, 0x34, 0xb8, 0x5a, 0x74, 0x8c, 0x11, 0xa7, 0x8c, 0x63, - 0x3a, 0x43, 0xfe, 0x79, 0x45, 0x99, 0x4e, 0x97, 0x7f, 0xd3, 0xaf, 0xfe, - 0xfe, 0x26, 0x1c, 0xda, 0xeb, 0x5a, 0x1d, 0x7d, 0x9d, 0x7f, 0x1d, 0x7f, - 0xb1, 0x38, 0x00, 0x7f, 0xa3, 0xac, 0xc0, 0x51, 0x13, 0x02, 0x8b, 0xa2, - 0x0b, 0xef, 0x46, 0xf3, 0x9d, 0x7f, 0xde, 0xd6, 0x6f, 0x2e, 0xfe, 0xa1, - 0xd4, 0x87, 0xbe, 0x24, 0x77, 0xd1, 0xb6, 0x24, 0x75, 0xfb, 0x8d, 0x77, - 0x69, 0xa2, 0x23, 0xbf, 0xfe, 0xef, 0xfa, 0xd6, 0x2c, 0x73, 0x6f, 0xc8, - 0x62, 0x8e, 0xbf, 0xe8, 0x9f, 0x99, 0xef, 0x27, 0x8e, 0xbc, 0x31, 0xb9, - 0xd5, 0x23, 0xd3, 0x09, 0xc5, 0xff, 0x67, 0x33, 0x58, 0xe3, 0x39, 0xd7, - 0xb0, 0x2b, 0x3a, 0xff, 0xff, 0x75, 0xd3, 0xd1, 0xd1, 0xcf, 0x75, 0x3b, - 0x88, 0xc9, 0xd7, 0xff, 0xff, 0xbd, 0xe4, 0x5f, 0x13, 0x37, 0x1f, 0xfd, - 0x1d, 0xf9, 0xb5, 0x3d, 0x34, 0x1d, 0x50, 0x8d, 0x9c, 0x5d, 0xbf, 0xce, - 0xbc, 0xe4, 0xa1, 0x67, 0x5d, 0x3a, 0xca, 0xb9, 0x96, 0x4a, 0xbf, 0xf2, - 0xad, 0xea, 0x4d, 0xd8, 0x9d, 0x50, 0x1a, 0xf6, 0x45, 0xef, 0xb6, 0xc7, - 0xa0, 0xea, 0x91, 0xfe, 0x22, 0xd5, 0xfd, 0x8e, 0xbc, 0xdf, 0xc7, 0x5f, - 0xf7, 0xf1, 0xdc, 0x9a, 0x4f, 0x39, 0xd7, 0xf2, 0xba, 0x4e, 0x38, 0x0e, - 0xac, 0x3e, 0x77, 0x3a, 0xb3, 0x19, 0xd7, 0xfd, 0x19, 0xbc, 0x3c, 0x9e, - 0x47, 0x53, 0x10, 0x79, 0x21, 0x13, 0xbf, 0x98, 0xc7, 0x3a, 0xfe, 0x3a, - 0xfe, 0x85, 0x30, 0x51, 0x43, 0xaf, 0xec, 0xf6, 0xc7, 0xb3, 0xa7, 0x56, - 0x22, 0x24, 0x4b, 0xb4, 0x59, 0x7f, 0xff, 0x35, 0x5e, 0x38, 0xa7, 0x95, - 0xe4, 0x78, 0x5c, 0x07, 0x53, 0x16, 0xbe, 0x0c, 0xc2, 0x85, 0x7c, 0x42, - 0x66, 0x44, 0x18, 0x44, 0xd3, 0x3d, 0xe1, 0x56, 0x84, 0x53, 0x1b, 0x72, - 0x1e, 0x9d, 0x21, 0x78, 0x6e, 0x00, 0x84, 0x61, 0x27, 0xa6, 0x9f, 0x42, - 0xc3, 0x69, 0x75, 0xdb, 0x1d, 0x3a, 0xfd, 0xc6, 0xbb, 0xb4, 0xd1, 0x17, - 0x5f, 0xbc, 0x0f, 0xa3, 0x22, 0xaf, 0xda, 0xf7, 0x60, 0x07, 0x5f, 0x9e, - 0x78, 0xe7, 0xe7, 0x59, 0x59, 0xd1, 0x89, 0x83, 0x2e, 0x67, 0xf9, 0x4e, - 0xc9, 0x3d, 0x2a, 0xa8, 0xb2, 0x51, 0xec, 0x5f, 0xfc, 0xb7, 0x92, 0xb9, - 0xc6, 0xbb, 0xb4, 0xd1, 0x33, 0x5f, 0xcc, 0x33, 0x0f, 0x60, 0x6a, 0x3c, - 0x75, 0xed, 0xe3, 0x47, 0x5e, 0x6a, 0x2c, 0xeb, 0xe6, 0x17, 0x9c, 0x4e, - 0xbb, 0x65, 0x88, 0x3a, 0xec, 0xfc, 0xeb, 0xff, 0xdd, 0x85, 0xbf, 0xb3, - 0x70, 0x2f, 0xef, 0x4e, 0xbe, 0x49, 0xff, 0x13, 0xaf, 0xd9, 0x3e, 0x02, - 0x63, 0xab, 0xe1, 0xe5, 0x78, 0x8a, 0xff, 0x7c, 0xc1, 0x7e, 0x03, 0x64, - 0xeb, 0xff, 0xf2, 0xdf, 0xb9, 0xb8, 0x3a, 0xcb, 0xf6, 0x6e, 0xfe, 0x75, - 0xfd, 0x9a, 0x8f, 0xa3, 0x07, 0x50, 0x51, 0x77, 0x86, 0xdd, 0x59, 0xbb, - 0x58, 0x75, 0xdb, 0x1e, 0x3a, 0xcc, 0x13, 0xac, 0x08, 0x35, 0xbf, 0x8c, - 0xdf, 0xff, 0xf9, 0x06, 0x1a, 0x30, 0xbf, 0x91, 0xce, 0x26, 0xde, 0x3b, - 0x80, 0xea, 0x62, 0x15, 0x56, 0x34, 0x79, 0x05, 0xa6, 0x84, 0xb7, 0x61, - 0xbe, 0xe5, 0xe0, 0x42, 0xf1, 0x3d, 0xfc, 0xcc, 0x08, 0xe7, 0x8e, 0xbe, - 0x7e, 0xa4, 0xc7, 0x5f, 0x76, 0x68, 0x09, 0xd5, 0x87, 0xdc, 0xd2, 0xb7, - 0x21, 0xbf, 0xcd, 0x4c, 0x10, 0xf6, 0x0e, 0xa3, 0xaf, 0xdd, 0x7f, 0x48, - 0x07, 0x5f, 0xfe, 0xf9, 0xd7, 0x4f, 0x03, 0xf1, 0x17, 0x91, 0xd5, 0x88, - 0xab, 0x69, 0x82, 0x05, 0x2c, 0x9e, 0xff, 0xff, 0xff, 0xff, 0xf3, 0x13, - 0x60, 0x63, 0x13, 0x61, 0x30, 0xf6, 0x1e, 0xd6, 0x0c, 0x30, 0xe6, 0x17, - 0x27, 0xd8, 0xcf, 0xc2, 0xc4, 0xa3, 0x67, 0x7f, 0xbd, 0x61, 0x44, 0x30, - 0x98, 0xd8, 0x6f, 0x7c, 0xf9, 0xdd, 0x93, 0xaf, 0xff, 0xc0, 0xde, 0x5d, - 0xfe, 0x38, 0xaf, 0x51, 0xaf, 0xc3, 0xaf, 0xfe, 0xdd, 0x98, 0xf0, 0x51, - 0x8f, 0x50, 0xb3, 0xaf, 0xff, 0xfc, 0x8b, 0x4e, 0x77, 0xfd, 0x4a, 0x36, - 0xf2, 0x07, 0xdd, 0xc9, 0x1d, 0x7f, 0xe4, 0xf2, 0x35, 0x03, 0xec, 0x69, - 0xd5, 0x88, 0xf1, 0xf2, 0x46, 0xc3, 0x6d, 0xf7, 0xb6, 0x73, 0xa7, 0x5f, - 0xff, 0xe7, 0x16, 0x8e, 0x07, 0xbf, 0xfc, 0xec, 0x4b, 0x91, 0x39, 0xd5, - 0x88, 0x86, 0xfc, 0x92, 0xff, 0xff, 0x3a, 0x83, 0x80, 0xff, 0x5f, 0x24, - 0x9d, 0x86, 0x8b, 0x9d, 0x7d, 0xe4, 0xea, 0x1d, 0x7f, 0xcf, 0xc9, 0x7c, - 0xc6, 0x87, 0x0e, 0xa6, 0x12, 0xe0, 0x54, 0x46, 0x59, 0x91, 0xa4, 0xf6, - 0x17, 0x0e, 0x46, 0x2c, 0x3f, 0x90, 0x5b, 0x87, 0x5f, 0xde, 0xc5, 0xef, - 0x8b, 0x3a, 0xdd, 0xc3, 0x7a, 0x82, 0x17, 0xfb, 0xf0, 0xbc, 0xb4, 0x92, - 0x3a, 0xff, 0xfc, 0x14, 0x19, 0xf3, 0x48, 0xfd, 0x55, 0x96, 0x59, 0x2a, - 0xfe, 0xf7, 0x62, 0x7e, 0xfe, 0x75, 0xfd, 0xbc, 0xb4, 0x0f, 0xe6, 0x3a, - 0xff, 0xa7, 0xc0, 0x07, 0xf7, 0xe4, 0x8e, 0xbf, 0x9d, 0xc3, 0xb7, 0x02, - 0x75, 0xe7, 0x76, 0x9a, 0x2c, 0xfb, 0xf8, 0x0e, 0x32, 0x45, 0x9d, 0x53, - 0xa2, 0xe4, 0x27, 0x4d, 0x2d, 0x01, 0x3d, 0xff, 0x93, 0xb1, 0x24, 0xf4, - 0x7b, 0x47, 0x5f, 0xfe, 0xe7, 0x5f, 0xe6, 0x6d, 0x1c, 0xd6, 0x09, 0xd7, - 0xfd, 0x08, 0x1c, 0x5b, 0x39, 0xd3, 0xaf, 0xfe, 0xd7, 0x92, 0x66, 0x5c, - 0x31, 0xbe, 0x8e, 0xa4, 0x46, 0x3b, 0xa5, 0x7e, 0x6f, 0x79, 0x96, 0x59, - 0x2a, 0xff, 0xcf, 0x2d, 0x0e, 0x34, 0x39, 0xc2, 0x95, 0x2f, 0xef, 0xdb, - 0x1f, 0xaf, 0x02, 0x75, 0xfe, 0xf7, 0x73, 0x6f, 0xc9, 0x2c, 0xea, 0xc3, - 0xe2, 0xfc, 0xae, 0xff, 0xdb, 0xc8, 0x7f, 0x07, 0xc6, 0xac, 0x07, 0x5d, - 0x0a, 0x1d, 0x7f, 0xc1, 0x81, 0x80, 0x4b, 0xa8, 0x75, 0x42, 0x23, 0xe7, - 0x43, 0x41, 0x6b, 0xfd, 0xd4, 0x08, 0xbb, 0xcc, 0x75, 0xfe, 0x0f, 0x7f, - 0x70, 0x6c, 0xe1, 0xd5, 0x07, 0xce, 0x86, 0x37, 0xfc, 0x82, 0x1f, 0xa1, - 0xff, 0xda, 0x3a, 0xf4, 0x0a, 0x87, 0x54, 0x97, 0x70, 0xc2, 0x4a, 0xd3, - 0x3d, 0xd6, 0x26, 0x2f, 0xe4, 0x3a, 0x96, 0x7d, 0xd8, 0xc0, 0xc0, 0x9c, - 0x30, 0xae, 0xd4, 0x2c, 0x7d, 0x09, 0x6d, 0xa4, 0x1f, 0x4e, 0xee, 0x06, - 0x8e, 0xbf, 0xef, 0xfd, 0xa1, 0xc9, 0xa1, 0x67, 0x5f, 0xe7, 0x67, 0xa9, - 0x1c, 0x83, 0xa8, 0x28, 0x80, 0x50, 0x5b, 0x87, 0x37, 0xfe, 0xe2, 0x6a, - 0x5f, 0x7b, 0x03, 0x07, 0x5f, 0x71, 0x21, 0x67, 0x5f, 0xff, 0xbc, 0xa7, - 0xf1, 0x81, 0xee, 0x6b, 0x79, 0x47, 0x4e, 0xae, 0x22, 0xd5, 0x67, 0xc2, - 0x41, 0x73, 0xc8, 0xeb, 0xff, 0xff, 0xf8, 0x5d, 0x9f, 0x67, 0x47, 0x3d, - 0xf8, 0x16, 0xf2, 0x70, 0xc0, 0xbf, 0x1e, 0x47, 0x5f, 0xec, 0xef, 0x7f, - 0xf3, 0x89, 0xd7, 0xfc, 0xdc, 0xeb, 0x5f, 0x8f, 0x23, 0xaf, 0x24, 0xda, - 0x3a, 0xa0, 0xf4, 0xd6, 0x6f, 0x64, 0x0a, 0x68, 0x13, 0x0a, 0xf2, 0x10, - 0xab, 0x84, 0x2d, 0xfd, 0xf1, 0x3a, 0xeb, 0x43, 0xaf, 0x6d, 0xc0, 0x9d, - 0x6e, 0x4e, 0x79, 0x53, 0x16, 0xdf, 0xfb, 0x19, 0xd8, 0xe6, 0x6c, 0x0f, - 0xec, 0x9d, 0x50, 0xa9, 0xdf, 0xb1, 0xb7, 0xbc, 0x26, 0x04, 0xaa, 0xff, - 0xff, 0xf8, 0x1a, 0xcc, 0x15, 0x3e, 0xf0, 0x63, 0x3a, 0xae, 0x87, 0x27, - 0x5e, 0x2c, 0xeb, 0xf7, 0xd8, 0x1f, 0xab, 0x3a, 0xb1, 0x15, 0x1e, 0x7e, - 0xbf, 0x6d, 0x7e, 0xc7, 0xd3, 0xaf, 0xff, 0xbf, 0xde, 0x5a, 0x0f, 0x63, - 0x81, 0x77, 0x64, 0xea, 0xc4, 0x4f, 0x21, 0x10, 0x95, 0x5e, 0xd4, 0x4e, - 0x75, 0xff, 0x46, 0x37, 0xa9, 0xb5, 0xf8, 0x75, 0xd9, 0xd3, 0xa8, 0x4f, - 0x37, 0x64, 0xe2, 0xa4, 0x8b, 0xad, 0x16, 0xf9, 0xa6, 0xf7, 0x7f, 0x64, - 0xeb, 0xc0, 0xfd, 0xa7, 0x5e, 0xf6, 0x7d, 0x3a, 0xfe, 0x8d, 0xf5, 0xf3, - 0x90, 0x75, 0xe0, 0xfe, 0xd3, 0xaf, 0x82, 0x31, 0x23, 0xa9, 0x0d, 0xeb, - 0x8e, 0xd0, 0x51, 0xc7, 0xb8, 0xf2, 0x0e, 0xac, 0x77, 0xad, 0x97, 0xf9, - 0x26, 0x71, 0x4d, 0xf4, 0x75, 0xd8, 0xd3, 0xaf, 0xee, 0x26, 0xdc, 0x1d, - 0x1d, 0x7f, 0x6f, 0xec, 0xef, 0xec, 0x67, 0x5f, 0xdc, 0xce, 0xf7, 0xff, - 0x1d, 0x7e, 0xe8, 0xc6, 0x70, 0xcb, 0xfb, 0x39, 0x3f, 0xee, 0x13, 0x44, - 0x1a, 0xa9, 0xa5, 0xb7, 0x27, 0x44, 0xfc, 0x94, 0xea, 0x11, 0xf6, 0x90, - 0xd1, 0xbf, 0x3b, 0x51, 0x70, 0x75, 0xfd, 0x2e, 0x8b, 0xef, 0xe3, 0xa9, - 0xa7, 0xa4, 0x24, 0xb7, 0xdf, 0x45, 0xe7, 0x3a, 0xb0, 0xf1, 0x34, 0x43, - 0x7e, 0x8f, 0x7c, 0x5b, 0x27, 0x5f, 0xe9, 0x22, 0xe3, 0xbf, 0x42, 0x75, - 0xff, 0xe8, 0xc1, 0xdf, 0xd9, 0xc4, 0x9d, 0xd6, 0x75, 0xf9, 0xd9, 0xf6, - 0x77, 0x47, 0xf9, 0xe3, 0x4a, 0xf8, 0xac, 0xc5, 0x8b, 0x32, 0x81, 0x59, - 0x46, 0x51, 0x90, 0xbc, 0xe1, 0x08, 0xc2, 0x9a, 0xf6, 0xb2, 0x47, 0x5f, - 0x90, 0x1d, 0x80, 0x9d, 0x7e, 0x4d, 0xe4, 0x82, 0x75, 0xe4, 0xee, 0x1d, - 0x74, 0x2f, 0x0f, 0x01, 0xa4, 0xd7, 0xf3, 0x38, 0xb8, 0xe2, 0x87, 0x5f, - 0x07, 0x5d, 0x83, 0xaf, 0xc3, 0xc6, 0x5e, 0x73, 0xaa, 0x0f, 0xdf, 0x0b, - 0x9c, 0x86, 0xef, 0xc4, 0xea, 0x84, 0xd9, 0xb0, 0x6d, 0x19, 0xb9, 0x0a, - 0x3d, 0x16, 0x5e, 0xee, 0x09, 0xd7, 0x9f, 0xd0, 0x75, 0xfe, 0x9a, 0x27, - 0x5b, 0xcd, 0x07, 0x5f, 0xff, 0x3a, 0x9e, 0x8e, 0x03, 0x91, 0xe1, 0x70, - 0x1d, 0x7f, 0x0e, 0x03, 0x06, 0x47, 0x5f, 0xff, 0x29, 0xf3, 0xe8, 0xbf, - 0xb4, 0x9b, 0xf5, 0x19, 0x3a, 0xc3, 0x87, 0xfe, 0xe5, 0x55, 0x89, 0xad, - 0x70, 0x69, 0xc6, 0x84, 0xd3, 0xf8, 0x66, 0xdd, 0xad, 0xa7, 0x5f, 0x20, - 0xb8, 0x4e, 0xbf, 0xf2, 0xf3, 0xda, 0xfb, 0xa7, 0x96, 0x1d, 0x7e, 0xd4, - 0x73, 0xd0, 0x72, 0xa6, 0xfe, 0x82, 0x89, 0x5d, 0x2f, 0x5f, 0xbe, 0xcc, - 0xef, 0xc3, 0xaf, 0xbb, 0x89, 0xb4, 0xeb, 0xfb, 0x49, 0xcc, 0xff, 0x87, - 0x5f, 0xff, 0xe8, 0x9b, 0xe2, 0x37, 0xfe, 0x6b, 0xff, 0x8b, 0x4f, 0x75, - 0x0e, 0xac, 0x4e, 0xbd, 0x21, 0x5a, 0xb2, 0x3e, 0x94, 0xf8, 0x8b, 0x60, - 0xb6, 0xe5, 0xb0, 0x0d, 0x17, 0xe5, 0xf6, 0xb9, 0x98, 0x75, 0xff, 0xd2, - 0xf7, 0xf2, 0x92, 0xfd, 0xe8, 0x59, 0xd7, 0xfb, 0xda, 0x89, 0xf3, 0x41, - 0x3a, 0xee, 0xe1, 0xd7, 0xff, 0xdd, 0x80, 0xe3, 0x7e, 0x60, 0xe0, 0x7b, - 0x07, 0x5f, 0xfc, 0x98, 0x39, 0x9a, 0xf9, 0x2d, 0x2c, 0xeb, 0xff, 0x3c, - 0x6f, 0x2f, 0x9a, 0xdc, 0x30, 0x75, 0x05, 0x38, 0x0d, 0xc8, 0x11, 0x19, - 0x8c, 0xce, 0x61, 0x5d, 0x27, 0x79, 0x0e, 0xf2, 0x91, 0xc3, 0xaf, 0xe0, - 0xc0, 0x39, 0x9b, 0x9d, 0x4a, 0x9e, 0x4a, 0xc7, 0x2f, 0xf4, 0x2f, 0x13, - 0x93, 0x48, 0xeb, 0x92, 0x63, 0xaf, 0xff, 0x7a, 0x3a, 0x2f, 0x3c, 0x73, - 0x8f, 0x23, 0xaf, 0x79, 0x27, 0x3a, 0xfc, 0x07, 0xde, 0x26, 0x3a, 0xf0, - 0xc3, 0x4e, 0xbf, 0xf8, 0x29, 0x37, 0x63, 0x9b, 0xca, 0x38, 0x75, 0xff, - 0xe4, 0x17, 0xdf, 0x5a, 0xce, 0x07, 0xb8, 0x75, 0x7c, 0x4d, 0x25, 0x05, - 0x96, 0x90, 0xe3, 0x82, 0x51, 0xa1, 0xad, 0x84, 0x5b, 0x41, 0xd7, 0xba, - 0x9e, 0x3a, 0xdb, 0x70, 0xd5, 0x7d, 0x0f, 0xa8, 0x5d, 0x10, 0x0a, 0xf6, - 0x47, 0x4e, 0x90, 0xb2, 0xe9, 0x1b, 0xc6, 0xf6, 0x08, 0x48, 0xde, 0x5b, - 0xfd, 0x3a, 0xff, 0xb0, 0x64, 0x38, 0xb8, 0x69, 0xd7, 0xee, 0xa6, 0xdc, - 0x09, 0xd7, 0xfe, 0x0c, 0x0e, 0x0f, 0xf2, 0xcd, 0x1d, 0x7e, 0x75, 0xa6, - 0xc6, 0x1d, 0x7b, 0xd1, 0xb9, 0xd5, 0x87, 0x88, 0xe5, 0x17, 0xa1, 0x26, - 0x3a, 0xf0, 0xb1, 0x1b, 0x07, 0x5f, 0xb2, 0x75, 0xc6, 0x8e, 0xbf, 0xff, - 0xf4, 0x75, 0x16, 0xac, 0xd2, 0x7e, 0x7d, 0xea, 0x6f, 0xa6, 0xa4, 0xe7, - 0x54, 0xe9, 0xf8, 0x04, 0x75, 0x43, 0x54, 0x28, 0x9a, 0x10, 0x1d, 0x20, - 0x11, 0xbd, 0x11, 0xec, 0x13, 0xdf, 0x7c, 0x79, 0x31, 0x47, 0x5f, 0xfd, - 0x9b, 0x70, 0x38, 0x3f, 0xcb, 0x34, 0x75, 0xfb, 0x91, 0xdf, 0xa1, 0x3a, - 0xb8, 0x7d, 0xae, 0x89, 0x7d, 0x09, 0x3c, 0x1d, 0x7c, 0xcb, 0xe6, 0x8e, - 0xbf, 0x83, 0x00, 0x1c, 0xdc, 0xeb, 0xfe, 0x92, 0xde, 0x5e, 0xd4, 0x28, - 0x75, 0x42, 0x21, 0xb0, 0x85, 0xcb, 0x2f, 0x69, 0x04, 0xeb, 0xf0, 0xb7, - 0xe6, 0xb7, 0x3a, 0xb0, 0xf1, 0x1c, 0x6a, 0x98, 0xd3, 0xed, 0x78, 0x4a, - 0x80, 0x84, 0x61, 0x4d, 0xfb, 0x8d, 0xd3, 0xc8, 0xeb, 0xc9, 0xd4, 0x3a, - 0xb7, 0x36, 0x3e, 0x17, 0xbe, 0xfb, 0xfb, 0xe8, 0xeb, 0xfe, 0x45, 0x20, - 0x31, 0xb7, 0x3a, 0x75, 0xfd, 0xfe, 0xa2, 0x6f, 0xf8, 0x75, 0xef, 0xf3, - 0x73, 0xab, 0xa7, 0x9b, 0xe3, 0x0b, 0xfd, 0x2f, 0xc6, 0x7d, 0x26, 0xe7, - 0x5f, 0x00, 0x19, 0xb9, 0xd7, 0xf6, 0xc7, 0xb1, 0xc5, 0xa7, 0x5f, 0xf7, - 0xef, 0x20, 0xe6, 0x03, 0x47, 0x5f, 0xe0, 0x26, 0xfb, 0xcb, 0x3c, 0x75, - 0x74, 0xfb, 0x34, 0x71, 0x7e, 0xdf, 0x4b, 0x46, 0x33, 0xaf, 0xff, 0xd9, - 0xaf, 0x9d, 0x74, 0xf0, 0x3f, 0x11, 0x79, 0x1d, 0x50, 0x88, 0x01, 0x2b, - 0xbf, 0x9e, 0x70, 0x38, 0x84, 0xea, 0x9d, 0x54, 0x43, 0x61, 0x0d, 0x31, - 0x17, 0x0d, 0x7a, 0x45, 0xe8, 0x4d, 0x6d, 0x85, 0x16, 0xc9, 0x0d, 0xfe, - 0xfb, 0x0d, 0xd9, 0xce, 0x41, 0xd7, 0xfc, 0x1c, 0xff, 0x93, 0xb5, 0x27, - 0x3a, 0xfe, 0x8e, 0xa7, 0x21, 0x67, 0x57, 0x51, 0x38, 0xe6, 0xde, 0x3b, - 0xa8, 0x5c, 0x00, 0xc9, 0x55, 0x8f, 0x19, 0x2d, 0xd3, 0x7e, 0x75, 0x96, - 0x75, 0x6e, 0x6a, 0x18, 0x23, 0x17, 0xff, 0x47, 0x33, 0x6b, 0xc8, 0x19, - 0x81, 0x3a, 0xfe, 0x7d, 0xe4, 0x30, 0x13, 0xaf, 0xfa, 0x37, 0x92, 0x0a, - 0xdf, 0xc7, 0x53, 0x9f, 0x18, 0x96, 0x5f, 0x9e, 0x59, 0x3c, 0x1d, 0x7f, - 0xf4, 0x6b, 0x58, 0xbf, 0x0c, 0x2f, 0x47, 0x5f, 0xfc, 0x91, 0xa1, 0x79, - 0x7c, 0xd6, 0x70, 0xeb, 0xff, 0xfc, 0x9a, 0x9f, 0x19, 0xc1, 0xff, 0x62, - 0x15, 0xc1, 0x7e, 0x1d, 0x7f, 0xb7, 0x96, 0xa6, 0x94, 0x4e, 0x75, 0x05, - 0x34, 0x46, 0x93, 0x0a, 0x17, 0x90, 0xff, 0x63, 0xbf, 0xff, 0xf7, 0x53, - 0x7f, 0x66, 0xfe, 0xe7, 0x23, 0xc0, 0xfa, 0x32, 0xee, 0x1d, 0x78, 0x2e, - 0x27, 0x5e, 0xe4, 0x6d, 0x3a, 0x82, 0x6d, 0xf8, 0x35, 0x7f, 0xe9, 0x40, - 0xfb, 0x89, 0xb7, 0x02, 0x75, 0xff, 0x9f, 0xda, 0xfe, 0x5f, 0x42, 0x9e, - 0x3a, 0xff, 0xcf, 0xd6, 0xa3, 0xfc, 0xd3, 0xf4, 0xeb, 0xfb, 0xae, 0x3b, - 0xc9, 0x0e, 0xbf, 0xff, 0x68, 0x7e, 0x75, 0xd3, 0xc0, 0xfc, 0x45, 0xe4, - 0x75, 0xfe, 0xea, 0x29, 0xb3, 0xff, 0x14, 0x3a, 0xff, 0xa1, 0x95, 0xf6, - 0x10, 0x67, 0x3a, 0xff, 0xf8, 0x73, 0x58, 0xb8, 0x6e, 0x79, 0x39, 0x87, - 0x5b, 0x1a, 0x8b, 0xcf, 0x1c, 0xed, 0x38, 0xbf, 0xa7, 0xce, 0x23, 0x60, - 0xeb, 0xe1, 0x0c, 0x2c, 0xeb, 0xff, 0xef, 0xc7, 0xda, 0xea, 0x4c, 0x30, - 0xb7, 0x91, 0xd7, 0xd8, 0x3f, 0xb9, 0xd4, 0xb3, 0xef, 0xda, 0x9f, 0x7f, - 0x38, 0x30, 0x2f, 0x23, 0xaa, 0x11, 0xbd, 0x90, 0x8f, 0x42, 0x4a, 0x44, - 0xcf, 0x3b, 0x18, 0x55, 0x42, 0xf6, 0xc4, 0xe4, 0xc1, 0x85, 0x36, 0x46, - 0xc8, 0xd4, 0xb4, 0x85, 0x34, 0xc4, 0x2b, 0x3e, 0xea, 0x0b, 0x9f, 0x00, - 0xb0, 0x63, 0x11, 0xf4, 0x6e, 0x77, 0xff, 0x60, 0x83, 0x33, 0x9a, 0xf4, - 0x61, 0xd7, 0xfd, 0xbf, 0xb3, 0x89, 0x3b, 0xac, 0xeb, 0x60, 0x0f, 0xe4, - 0x50, 0x2f, 0x30, 0x64, 0x87, 0x5f, 0x40, 0xbc, 0x8e, 0xbf, 0x63, 0x1b, - 0x88, 0x3e, 0x1b, 0xee, 0x0f, 0xdf, 0xdb, 0x7a, 0x91, 0xcd, 0x1d, 0x7f, - 0xee, 0xa2, 0xc3, 0x93, 0x46, 0x70, 0xeb, 0xd2, 0x8d, 0xce, 0xbe, 0x80, - 0x3a, 0xce, 0xb8, 0x65, 0x87, 0xf3, 0x31, 0xe8, 0x8e, 0x5f, 0x69, 0x3d, - 0x07, 0x54, 0x1e, 0xcb, 0x9c, 0xdf, 0x37, 0xa9, 0x31, 0xd7, 0xff, 0xe1, - 0xc5, 0x14, 0x40, 0xf5, 0x26, 0xea, 0x6f, 0xe3, 0xaa, 0x0f, 0xe7, 0x08, - 0xaf, 0x35, 0xf8, 0x75, 0xfb, 0x4d, 0x8e, 0x28, 0x75, 0x74, 0xf0, 0xc0, - 0x37, 0x7f, 0xb2, 0x58, 0x81, 0xea, 0x1d, 0x7f, 0xf6, 0x6f, 0xed, 0x20, - 0xc0, 0x1d, 0x67, 0x5e, 0x92, 0xfa, 0x75, 0x4e, 0x7b, 0xde, 0x42, 0xbe, - 0x45, 0x11, 0x93, 0xab, 0x0f, 0x14, 0x48, 0xee, 0xf9, 0x87, 0x5f, 0x68, - 0x61, 0x67, 0x54, 0x1b, 0x7d, 0xc5, 0xef, 0x76, 0x4b, 0x3a, 0xee, 0xa1, - 0xd5, 0x86, 0xc7, 0xc3, 0x95, 0x0b, 0x8b, 0xf2, 0x64, 0xc4, 0x15, 0x23, - 0x00, 0xec, 0x26, 0x5d, 0x8c, 0x48, 0xb5, 0x0d, 0x3f, 0xd5, 0xf6, 0x54, - 0xaf, 0x05, 0x6d, 0x3a, 0xdd, 0x3a, 0xc0, 0x3a, 0xed, 0x48, 0xea, 0x01, - 0xb6, 0xd0, 0x87, 0xe2, 0x17, 0xf4, 0xf3, 0x49, 0x85, 0xc9, 0xce, 0xbc, - 0xf9, 0xc3, 0xaf, 0x0e, 0x78, 0xea, 0xe9, 0xb4, 0x11, 0xab, 0xbc, 0x27, - 0x5e, 0x8d, 0xf4, 0x75, 0xf2, 0x0c, 0xb0, 0xeb, 0xd3, 0xb8, 0x9d, 0x41, - 0x3d, 0x65, 0x8e, 0x78, 0x7e, 0xfd, 0x9e, 0xea, 0x78, 0xeb, 0xf3, 0xef, - 0x9b, 0xf8, 0xeb, 0x29, 0xd3, 0xce, 0xf1, 0x35, 0xc9, 0xc3, 0xaf, 0xe9, - 0xfe, 0x4e, 0xef, 0xd3, 0xa9, 0x88, 0x4f, 0x7e, 0x1a, 0x64, 0x41, 0x8d, - 0x68, 0xfb, 0xd2, 0x97, 0x15, 0xbf, 0xec, 0x08, 0x53, 0x7c, 0xdf, 0xc7, - 0x5f, 0x34, 0x62, 0x47, 0x57, 0x4f, 0x65, 0xce, 0x6f, 0xf4, 0x67, 0xa3, - 0xae, 0x13, 0xaa, 0x73, 0xd1, 0x09, 0x0d, 0xff, 0xc1, 0x80, 0xf2, 0x3c, - 0x8d, 0x40, 0x9d, 0x7d, 0x34, 0x6c, 0x48, 0xeb, 0xfb, 0xcd, 0x08, 0x57, - 0xc3, 0xaf, 0xfa, 0x6d, 0x6d, 0x71, 0x9f, 0xf0, 0x9d, 0x7d, 0x9e, 0xc5, - 0x9d, 0x70, 0xa8, 0x75, 0xb4, 0xe6, 0xdb, 0xf2, 0x0b, 0xfb, 0xbf, 0xcf, - 0x37, 0x50, 0xeb, 0xe1, 0x1c, 0xf1, 0xd5, 0x09, 0xd0, 0x84, 0x8f, 0x10, - 0x94, 0x25, 0x42, 0xe9, 0x9c, 0xfa, 0x4f, 0xe3, 0x0b, 0xfb, 0xe4, 0xd1, - 0xe1, 0xda, 0x75, 0xff, 0xe1, 0x8d, 0xbc, 0x8e, 0x62, 0x76, 0x02, 0x75, - 0xe1, 0x75, 0x9d, 0x52, 0x44, 0x9e, 0x18, 0xa2, 0x45, 0x95, 0x62, 0x1f, - 0x0c, 0xf1, 0x8b, 0x3c, 0x61, 0xe3, 0x8c, 0x48, 0x6e, 0x25, 0x68, 0x4f, - 0x0e, 0xf9, 0x43, 0x60, 0x33, 0x88, 0xb9, 0x3c, 0xf2, 0xa4, 0x6c, 0x2d, - 0x96, 0xbb, 0xbc, 0xa4, 0x74, 0x8c, 0x4e, 0x69, 0x6f, 0x7c, 0x8f, 0x81, - 0x71, 0xd3, 0xf6, 0x7c, 0x35, 0xe5, 0x34, 0x82, 0x53, 0xab, 0x06, 0x11, - 0x03, 0x38, 0x45, 0xa9, 0xf3, 0xdf, 0x4e, 0xd3, 0x7f, 0x09, 0xf6, 0x54, - 0xb6, 0x65, 0x07, 0x7d, 0x95, 0x63, 0xb1, 0x18, 0x25, 0x2a, 0xf8, 0xb9, - 0x9d, 0xbc, 0x38, 0xcb, 0xff, 0xca, 0xad, 0xe4, 0xae, 0x71, 0xae, 0xed, - 0x34, 0x4d, 0x97, 0xf9, 0x5c, 0xe3, 0x5d, 0xda, 0x68, 0xab, 0x6f, 0xf4, - 0xa5, 0xff, 0x86, 0x24, 0x75, 0xf6, 0x75, 0xfc, 0x75, 0x98, 0x18, 0x7a, - 0x62, 0x67, 0x7f, 0xd8, 0x38, 0xb8, 0x97, 0xfc, 0x3a, 0xff, 0x73, 0x1b, - 0x00, 0xfa, 0xb3, 0xaf, 0xfa, 0x3b, 0x13, 0xf2, 0x30, 0x27, 0x53, 0x51, - 0x45, 0xc3, 0x7e, 0x9a, 0x5f, 0xa3, 0x8b, 0xe8, 0x4e, 0xbc, 0x1c, 0x13, - 0xaf, 0x3b, 0xb4, 0xd1, 0x5a, 0x5f, 0x94, 0xdf, 0x5f, 0xee, 0x75, 0x34, - 0xf4, 0xd0, 0x9e, 0xff, 0xf2, 0x7a, 0x50, 0xde, 0xa7, 0xb4, 0xfb, 0x9d, - 0x5c, 0x3e, 0xad, 0xa4, 0x37, 0xff, 0xba, 0x8b, 0x86, 0xe2, 0xf0, 0x7d, - 0xb2, 0x75, 0xff, 0xf3, 0x63, 0x98, 0x07, 0x5b, 0xca, 0x11, 0xa7, 0x5f, - 0xff, 0x4b, 0x58, 0x30, 0xb7, 0xcf, 0x7a, 0x16, 0x75, 0xde, 0xf4, 0x22, - 0x61, 0xd3, 0x2f, 0xff, 0xff, 0x46, 0xd4, 0xf6, 0xb1, 0x46, 0xf5, 0x3d, - 0x93, 0x0c, 0x2e, 0x7c, 0x64, 0xeb, 0xfd, 0x1e, 0x7e, 0xfc, 0x0c, 0x1d, - 0x7d, 0x2f, 0x24, 0xe7, 0x5f, 0xbe, 0xf8, 0x60, 0x07, 0x56, 0xe7, 0x95, - 0xb4, 0x8a, 0xff, 0x3c, 0xbc, 0x93, 0xf5, 0x0e, 0xa8, 0x3d, 0x74, 0x25, - 0xbf, 0x67, 0x53, 0x16, 0x75, 0xff, 0xc2, 0xe8, 0xde, 0xbf, 0xf3, 0xf1, - 0x0e, 0xa9, 0xcf, 0xa3, 0xa4, 0xb7, 0xfa, 0x51, 0xc9, 0xe3, 0x93, 0x9d, - 0x7d, 0x2e, 0x62, 0xce, 0xbd, 0x9c, 0x01, 0xd7, 0xe9, 0xb0, 0x2b, 0x63, - 0x3a, 0xfe, 0x18, 0x67, 0x79, 0x68, 0xea, 0xdd, 0x12, 0xa8, 0x43, 0x30, - 0xde, 0xc1, 0x5d, 0x42, 0x61, 0x59, 0x0c, 0x9b, 0xff, 0xff, 0xfb, 0x11, - 0xb9, 0xe8, 0x1f, 0x6b, 0xe4, 0x20, 0x71, 0x7f, 0x39, 0x09, 0x27, 0xd1, - 0xd7, 0xf6, 0x79, 0xc4, 0x1f, 0x9d, 0x7f, 0x77, 0xe2, 0x4e, 0xe2, 0x75, - 0xfe, 0x85, 0xe8, 0x22, 0xec, 0x9d, 0x52, 0x44, 0x66, 0x16, 0x09, 0x75, - 0x95, 0x61, 0x2f, 0xcc, 0x44, 0x33, 0x27, 0x30, 0x09, 0x3e, 0x43, 0x5d, - 0xa4, 0x89, 0x0e, 0x2e, 0x16, 0xad, 0xeb, 0xb0, 0xd4, 0x78, 0x44, 0x0c, - 0x65, 0xba, 0x27, 0xf4, 0x62, 0x77, 0xee, 0x35, 0xdd, 0xa6, 0x8b, 0x02, - 0xfc, 0xed, 0xfb, 0xd9, 0x8e, 0xb2, 0xb8, 0x7b, 0xba, 0x33, 0xbf, 0x71, - 0xae, 0xed, 0x34, 0x4e, 0xb7, 0xff, 0xfb, 0xb1, 0x38, 0x71, 0x6a, 0xeb, - 0x59, 0xd4, 0xd7, 0xf3, 0x9d, 0x7e, 0x55, 0x6f, 0x25, 0x71, 0x12, 0xf3, - 0x19, 0xde, 0x52, 0x16, 0x75, 0xf3, 0xb7, 0xea, 0xce, 0xbd, 0x2d, 0x2a, - 0xa1, 0xbf, 0xda, 0x39, 0x7e, 0xe3, 0x5d, 0xda, 0x68, 0xb6, 0x6f, 0xef, - 0x3f, 0x7e, 0x06, 0x0e, 0xbf, 0xff, 0xa4, 0xae, 0xa1, 0x30, 0x29, 0x9a, - 0xcf, 0x0c, 0x1d, 0x50, 0x88, 0x57, 0x2e, 0xbf, 0xf0, 0x23, 0x4a, 0xf5, - 0x1a, 0xfc, 0x3a, 0xff, 0xa2, 0x51, 0xc9, 0xe3, 0x93, 0x9d, 0x65, 0x71, - 0x35, 0x05, 0xc2, 0xe1, 0xc8, 0x44, 0xfa, 0xff, 0xc2, 0xaa, 0xff, 0x4f, - 0x0b, 0xec, 0x1d, 0x7f, 0xf7, 0xfa, 0x57, 0x38, 0xfa, 0xeb, 0xc8, 0xeb, - 0x9c, 0x18, 0x88, 0x60, 0x20, 0xdf, 0x35, 0xdd, 0xa6, 0x8b, 0x9a, 0xcb, - 0x3a, 0xb8, 0x6f, 0x59, 0x2d, 0xbf, 0xdc, 0x1c, 0xdc, 0x09, 0x23, 0xae, - 0x99, 0x67, 0x51, 0xd6, 0x57, 0x0f, 0xd5, 0x08, 0x99, 0x32, 0xd9, 0x17, - 0xbf, 0x71, 0xae, 0xed, 0x34, 0x5d, 0xf7, 0xfa, 0x4a, 0xeb, 0x9c, 0x46, - 0x4e, 0xb2, 0xb8, 0x7d, 0x0e, 0x67, 0x7c, 0xaa, 0x81, 0x01, 0xd5, 0x0f, - 0xaa, 0xcd, 0x97, 0x8b, 0xf0, 0xd3, 0x7d, 0xd5, 0xd2, 0x90, 0x55, 0xc8, - 0xd2, 0xd7, 0x0b, 0xf7, 0x84, 0x08, 0x23, 0x87, 0x18, 0x66, 0xea, 0x1b, - 0xfe, 0x85, 0x6f, 0xd2, 0x7b, 0xff, 0x32, 0xe3, 0x3e, 0x90, 0x77, 0x91, - 0xd7, 0xff, 0x64, 0xf8, 0xcf, 0x73, 0x58, 0x82, 0x75, 0xc8, 0xaf, 0x51, - 0x02, 0x27, 0xf7, 0xed, 0x69, 0x6f, 0x23, 0xaf, 0xff, 0xff, 0xfd, 0xd4, - 0xea, 0x40, 0xf8, 0x5d, 0x4c, 0xf7, 0xfe, 0x4f, 0x6b, 0xa9, 0xc8, 0x9d, - 0xf8, 0xd3, 0xae, 0xd4, 0x1d, 0x7f, 0xf6, 0xed, 0xfd, 0xf7, 0xf6, 0x60, - 0xa8, 0x75, 0xe1, 0x75, 0x61, 0x31, 0xa6, 0x93, 0xea, 0x13, 0x1e, 0x15, - 0xbd, 0xfb, 0xac, 0xeb, 0xf6, 0x6c, 0x7a, 0x14, 0x3a, 0xdb, 0x07, 0x54, - 0xe6, 0xf7, 0x0a, 0xab, 0x87, 0xf4, 0x2b, 0x37, 0xfe, 0xd3, 0xa9, 0xd4, - 0x81, 0xfe, 0x0e, 0xbf, 0xf7, 0x5f, 0xcf, 0xdd, 0xe5, 0x9e, 0x3a, 0xb0, - 0xfe, 0xd0, 0xf6, 0xe7, 0x01, 0xd7, 0xff, 0xff, 0x85, 0xd9, 0x1c, 0xf7, - 0xb2, 0x78, 0x17, 0x53, 0x4b, 0x8c, 0x10, 0x9d, 0x7b, 0x3e, 0xe8, 0xea, - 0xc4, 0x53, 0x70, 0x57, 0x61, 0xd2, 0xff, 0x77, 0x02, 0x9b, 0x79, 0x87, - 0x5e, 0x77, 0x69, 0xa2, 0x57, 0xbf, 0xca, 0x38, 0x83, 0xd9, 0xd3, 0xa9, - 0xa7, 0xb2, 0x84, 0xf7, 0xff, 0xbd, 0xdc, 0x93, 0x7a, 0x81, 0x81, 0xf1, - 0xd5, 0x24, 0x7a, 0xf2, 0x11, 0x82, 0x43, 0x7f, 0xff, 0xfd, 0xc7, 0x1f, - 0xb0, 0x0c, 0x97, 0x63, 0x68, 0x61, 0x5c, 0x1f, 0xe5, 0x9a, 0x3a, 0xe9, - 0x4e, 0x75, 0xff, 0xfe, 0x7d, 0xf5, 0x9c, 0xf7, 0x9e, 0x7f, 0xab, 0x0f, - 0x51, 0x43, 0xaf, 0xef, 0xf7, 0xf7, 0x60, 0x07, 0x5f, 0xf8, 0x5d, 0x90, - 0xf6, 0x27, 0xc6, 0x4e, 0xbf, 0xff, 0x62, 0x03, 0x16, 0x9e, 0xd4, 0x2d, - 0xf7, 0xf1, 0xd7, 0xfd, 0x0b, 0xf6, 0x4d, 0x24, 0xf1, 0xd5, 0x24, 0x45, - 0xf9, 0x4e, 0xfb, 0xf7, 0xe4, 0x8e, 0xbf, 0xe8, 0x68, 0xc4, 0xe0, 0x7f, - 0x1d, 0x7f, 0xff, 0x93, 0xce, 0xb7, 0x10, 0x75, 0x97, 0x19, 0xda, 0x93, - 0x9d, 0x41, 0x45, 0xca, 0x11, 0x39, 0xbd, 0xff, 0x7e, 0x05, 0xbc, 0xb5, - 0xc0, 0x9d, 0x7f, 0xff, 0xb1, 0x07, 0xd8, 0x3f, 0x05, 0xc3, 0x03, 0x3c, - 0x70, 0xeb, 0x67, 0x91, 0x2f, 0xb4, 0xea, 0xff, 0xb7, 0x06, 0x73, 0x33, - 0xda, 0x3a, 0x82, 0xab, 0x37, 0x21, 0x95, 0xd8, 0x6e, 0x0c, 0x31, 0x7e, - 0x95, 0x5f, 0xf6, 0x6f, 0xa0, 0xc3, 0x8c, 0xe7, 0x5f, 0xf3, 0xcb, 0x5d, - 0x8e, 0x7d, 0x09, 0xd5, 0x87, 0xe5, 0xe3, 0x8b, 0xff, 0xbc, 0x9b, 0x53, - 0xd3, 0x4a, 0x07, 0xc7, 0x5f, 0xfe, 0x7c, 0x97, 0x71, 0x07, 0x01, 0xb3, - 0x87, 0x5e, 0x79, 0x2b, 0x0c, 0x82, 0xf9, 0x42, 0x70, 0x30, 0xc6, 0xc8, - 0xc9, 0xf8, 0x68, 0xb7, 0xf0, 0x0b, 0x8b, 0x2e, 0xa5, 0x7e, 0x7a, 0x19, - 0xbf, 0x48, 0x76, 0x11, 0x6f, 0xff, 0x67, 0x55, 0x1c, 0x0a, 0x0f, 0xb3, - 0xa7, 0x5e, 0xf4, 0x04, 0xab, 0xff, 0xdd, 0x74, 0xf4, 0x49, 0x39, 0x3f, - 0xe0, 0x2a, 0xff, 0x3b, 0x55, 0x0f, 0x18, 0x2a, 0xc1, 0xf2, 0xe8, 0x6e, - 0xca, 0x85, 0x98, 0x32, 0xd8, 0xd2, 0x17, 0x48, 0xfc, 0xf4, 0x36, 0x76, - 0xc2, 0xb2, 0xff, 0xf2, 0xab, 0x79, 0x2b, 0x9c, 0x6b, 0xbb, 0x4d, 0x13, - 0x0d, 0xff, 0xfd, 0x9b, 0x5c, 0x3d, 0x85, 0x7d, 0xdc, 0x0f, 0xfe, 0xd1, - 0xd7, 0xff, 0xb8, 0xe0, 0x55, 0x4f, 0x49, 0x98, 0xd4, 0x8e, 0xbb, 0x15, - 0x14, 0x55, 0xfd, 0x5e, 0xb9, 0x7b, 0x4e, 0xbf, 0xf9, 0x81, 0x9b, 0xcb, - 0xf7, 0xf0, 0xc4, 0x8e, 0xbf, 0x62, 0xfe, 0x6e, 0xc6, 0x75, 0xfd, 0x0b, - 0xc0, 0x46, 0xd3, 0xa8, 0x27, 0xb5, 0xd2, 0xdb, 0xfd, 0xcc, 0x6c, 0x03, - 0xea, 0xce, 0xbf, 0x76, 0x02, 0x8a, 0x1d, 0x48, 0x7f, 0xbc, 0x22, 0xd8, - 0x34, 0xbf, 0xd0, 0xf3, 0xf9, 0x47, 0xe1, 0xd7, 0xe7, 0xe4, 0x9d, 0x67, - 0x50, 0x9e, 0xcf, 0xe6, 0x77, 0xfb, 0x51, 0x82, 0x1e, 0xc1, 0xd7, 0xf4, - 0x60, 0x87, 0xb0, 0x75, 0xef, 0xf9, 0x37, 0xc3, 0xda, 0xd1, 0x85, 0xff, - 0xee, 0x27, 0xf8, 0xa6, 0x7b, 0xf8, 0xdc, 0x27, 0x5f, 0xff, 0x93, 0x9d, - 0x7f, 0x81, 0xc9, 0x76, 0x36, 0x86, 0x0e, 0xbf, 0xe6, 0x7e, 0xf6, 0x1b, - 0xd4, 0x98, 0xeb, 0xef, 0xd7, 0x81, 0x3a, 0xd9, 0xb9, 0xef, 0x6c, 0x1e, - 0x5f, 0xd1, 0xc8, 0x96, 0xb0, 0xea, 0x6a, 0x71, 0xfc, 0x38, 0xea, 0x60, - 0xc2, 0xd7, 0xc5, 0x77, 0xf2, 0xe3, 0x07, 0xdb, 0x27, 0x5b, 0x47, 0x5f, - 0xa3, 0x07, 0xdb, 0x27, 0x5f, 0xdd, 0x4f, 0x69, 0xf7, 0xf8, 0x7c, 0xd3, - 0x17, 0x2c, 0x42, 0xff, 0x4b, 0xd0, 0xbd, 0xa0, 0x91, 0xd7, 0xff, 0xf9, - 0x9d, 0x8f, 0x67, 0x7e, 0x0e, 0x4e, 0x98, 0x3b, 0xcb, 0x47, 0x5f, 0x99, - 0xf6, 0x75, 0xa7, 0x58, 0x71, 0x11, 0xce, 0xcd, 0x7f, 0xfb, 0xc2, 0xe0, - 0xee, 0x20, 0x7f, 0xf6, 0x8e, 0xbf, 0xe8, 0x9f, 0xec, 0xbb, 0xfb, 0xce, - 0x75, 0x42, 0x21, 0xb8, 0x93, 0x7f, 0xf6, 0x6f, 0x2f, 0x9d, 0x76, 0xc0, - 0x84, 0xeb, 0xfb, 0x6f, 0xdf, 0x0c, 0x00, 0xeb, 0xff, 0xd1, 0xe0, 0x44, - 0xb3, 0x7f, 0x4f, 0xfb, 0x27, 0x5e, 0xd3, 0x80, 0xea, 0x84, 0x4c, 0x21, - 0x87, 0x93, 0x6f, 0xe7, 0x07, 0x38, 0x9c, 0x3a, 0xf7, 0xbe, 0x61, 0xd4, - 0x03, 0xc9, 0xfa, 0x59, 0x7f, 0x69, 0x14, 0x5b, 0xf8, 0xeb, 0xff, 0xff, - 0x73, 0x36, 0xc0, 0xfb, 0xe7, 0xd1, 0x8e, 0xba, 0x7a, 0x3d, 0xa3, 0xaf, - 0xe1, 0xcd, 0x7c, 0x6b, 0x08, 0xea, 0xdd, 0x19, 0xbc, 0x2d, 0xda, 0xdd, - 0x7d, 0xf3, 0x6e, 0xc4, 0xe7, 0x56, 0x1e, 0xea, 0x86, 0x76, 0x63, 0x3a, - 0xef, 0x61, 0xd7, 0xff, 0x98, 0x23, 0x0b, 0x74, 0xeb, 0xfb, 0xb0, 0x75, - 0x41, 0xef, 0xfe, 0x2b, 0x7f, 0xba, 0x93, 0x3b, 0x75, 0x23, 0xaf, 0xe1, - 0xf3, 0xad, 0x3c, 0x75, 0xff, 0x93, 0xdf, 0xf1, 0xf5, 0xf1, 0x7e, 0x3a, - 0xa0, 0xfb, 0x1c, 0xae, 0xff, 0xb1, 0x31, 0x63, 0x93, 0xb9, 0xd7, 0xe8, - 0xf6, 0x81, 0xf9, 0xd4, 0xc4, 0x27, 0x61, 0x8e, 0x4d, 0x22, 0xec, 0x27, - 0xc4, 0x83, 0xc6, 0xb7, 0xff, 0xee, 0x8e, 0x7b, 0xa9, 0x9b, 0xfb, 0x36, - 0xc6, 0x8e, 0xbf, 0xf9, 0xc7, 0xb0, 0x81, 0x4d, 0x64, 0x8e, 0xbd, 0x00, - 0xfa, 0x75, 0xfd, 0x9b, 0x7a, 0x80, 0x98, 0xea, 0xc4, 0x70, 0xba, 0xa8, - 0xa0, 0x68, 0x76, 0xf7, 0xd0, 0xe1, 0xd7, 0x98, 0x3a, 0x61, 0x1d, 0x4e, - 0x78, 0x3a, 0x1d, 0xbe, 0xf8, 0xbf, 0x8d, 0x3a, 0xff, 0x0b, 0xb3, 0x1e, - 0xc9, 0xce, 0xbf, 0x6e, 0xcc, 0xda, 0x83, 0xac, 0xab, 0x10, 0xcd, 0x3a, - 0x61, 0x0c, 0x44, 0x63, 0xe1, 0x84, 0x56, 0x4a, 0x0b, 0x6c, 0x2d, 0x77, - 0x55, 0x9a, 0x18, 0x7c, 0x85, 0x62, 0xc8, 0xbb, 0x0d, 0xd0, 0x3b, 0x8c, - 0x69, 0xda, 0x8f, 0x4b, 0xd1, 0xa0, 0xfe, 0xf6, 0xc9, 0x0e, 0xc9, 0x37, - 0xd3, 0x2b, 0xff, 0xee, 0x26, 0xf2, 0xd2, 0x7b, 0xb1, 0xcf, 0x41, 0xd7, - 0xee, 0x35, 0xdd, 0xa6, 0x8a, 0xba, 0xf7, 0x21, 0x67, 0x5f, 0xe8, 0xe7, - 0xa0, 0x60, 0x07, 0x5f, 0xf4, 0x95, 0xce, 0x35, 0xdd, 0xa6, 0x88, 0xf2, - 0xff, 0xa2, 0x51, 0xc9, 0xe3, 0x93, 0x9d, 0x7f, 0xe8, 0xf2, 0x7e, 0xc1, - 0xc9, 0x4f, 0x31, 0xd7, 0xfd, 0xbb, 0x53, 0x5d, 0x4f, 0x21, 0xd6, 0x54, - 0x29, 0xe3, 0xe2, 0x7f, 0x0c, 0xfa, 0x36, 0xe6, 0x02, 0x8b, 0xa3, 0x9f, - 0x22, 0x5f, 0xb8, 0xd7, 0x76, 0x9a, 0x2c, 0x1b, 0xca, 0x44, 0xe7, 0x5f, - 0xff, 0xc3, 0xfb, 0xce, 0xbc, 0xd9, 0xff, 0x99, 0xc9, 0x7d, 0x91, 0xd7, - 0xec, 0x1c, 0xf6, 0x8e, 0xbf, 0xdc, 0x75, 0xfd, 0xe3, 0xee, 0x75, 0x95, - 0xc4, 0xc3, 0x14, 0x33, 0x68, 0xeb, 0xb1, 0x7d, 0x25, 0xbf, 0xca, 0xe7, - 0x1a, 0xee, 0xd3, 0x45, 0x95, 0x7e, 0xe3, 0x5d, 0xda, 0x68, 0xb4, 0xef, - 0xf9, 0xc3, 0xd7, 0x9b, 0xa8, 0xb3, 0xac, 0xae, 0x1f, 0x5a, 0xcc, 0xef, - 0xcc, 0x3d, 0x89, 0xb1, 0x0c, 0x43, 0x16, 0x75, 0xff, 0x30, 0xba, 0x8c, - 0x85, 0xdd, 0xa7, 0x5f, 0x98, 0x7b, 0x03, 0x59, 0x07, 0x5f, 0xef, 0xab, - 0xcf, 0x69, 0x34, 0x75, 0x90, 0xea, 0x61, 0x1e, 0x1e, 0xc9, 0xa5, 0xff, - 0xfc, 0x9d, 0x71, 0xf4, 0xb3, 0x99, 0x02, 0x39, 0xe3, 0xaf, 0xdb, 0x5c, - 0x38, 0xb3, 0xaf, 0x97, 0x1b, 0xe8, 0xeb, 0xff, 0x93, 0x1c, 0x11, 0x2e, - 0x46, 0x09, 0xd7, 0xc9, 0xb7, 0xbb, 0x4e, 0xa9, 0x26, 0x07, 0x8a, 0xb3, - 0x14, 0x09, 0x16, 0x8f, 0xef, 0xf2, 0xfe, 0xac, 0x0b, 0x40, 0x1d, 0x7e, - 0xf9, 0xce, 0x7f, 0xd3, 0xaf, 0xc8, 0xa4, 0x0b, 0x4e, 0xad, 0x1e, 0x8f, - 0x8a, 0xea, 0x11, 0x51, 0x90, 0x86, 0xbf, 0xfe, 0x16, 0xf5, 0x3a, 0x9c, - 0x89, 0x99, 0xce, 0x9d, 0x7f, 0xe5, 0xad, 0xe5, 0xb3, 0xff, 0x53, 0x87, - 0x5f, 0x9f, 0x5e, 0x80, 0x9d, 0x50, 0x7d, 0x1f, 0xa1, 0x54, 0x23, 0x67, - 0xb0, 0xb7, 0xbe, 0x8f, 0xb1, 0xd3, 0xaf, 0x9a, 0xee, 0xd3, 0x45, 0xb9, - 0x7d, 0x34, 0x07, 0x0e, 0xbf, 0xf6, 0x73, 0x07, 0xe7, 0x73, 0x76, 0x4e, - 0xbf, 0x08, 0x1f, 0x7d, 0x1d, 0x50, 0x7c, 0xee, 0x81, 0x5b, 0xa3, 0xdf, - 0x84, 0x4e, 0x5b, 0xa8, 0x44, 0x5f, 0xe7, 0x10, 0x4c, 0x30, 0xb3, 0xaf, - 0x2c, 0x50, 0xeb, 0x09, 0xd7, 0xfd, 0xdf, 0xdf, 0x59, 0x82, 0xa1, 0xd7, - 0xed, 0x3e, 0xee, 0x13, 0xac, 0x81, 0x3d, 0xff, 0x1c, 0x54, 0x22, 0xbf, - 0x06, 0xba, 0xdd, 0x7f, 0xd0, 0xe3, 0xdc, 0xc1, 0x69, 0xd7, 0xfb, 0xde, - 0x49, 0xd7, 0x02, 0x75, 0x48, 0xf9, 0xb0, 0xd2, 0xff, 0xa0, 0x7f, 0x5c, - 0x6b, 0xc8, 0x75, 0xe8, 0xce, 0x1d, 0x7f, 0xbb, 0x12, 0x4d, 0x9c, 0x59, - 0xd4, 0x13, 0xce, 0xd0, 0xd5, 0xfb, 0xe6, 0xfa, 0x45, 0x0e, 0xb3, 0xce, - 0x79, 0xbb, 0x91, 0x5f, 0xfd, 0x2c, 0xea, 0x70, 0x3d, 0x81, 0x69, 0xd7, - 0xfb, 0x79, 0x40, 0xfb, 0x00, 0x75, 0xf6, 0x80, 0x9e, 0x3a, 0x9d, 0x17, - 0xda, 0x29, 0xfd, 0x0b, 0xe9, 0x95, 0xff, 0xde, 0x40, 0x44, 0x83, 0xd8, - 0x16, 0x9d, 0x7f, 0x7a, 0x59, 0xcc, 0xd1, 0xd4, 0x75, 0xef, 0xdf, 0xc7, - 0x5d, 0xfc, 0x1d, 0x52, 0x36, 0x5e, 0x1c, 0xa3, 0xaf, 0xb7, 0x6a, 0x70, - 0xeb, 0xd0, 0xb5, 0x71, 0x11, 0x3b, 0x9e, 0x2c, 0x87, 0xc1, 0x55, 0x09, - 0xa3, 0x62, 0x12, 0x42, 0xd6, 0xf0, 0xfb, 0x64, 0xeb, 0xdf, 0x18, 0xb6, - 0x2c, 0xeb, 0xfe, 0x92, 0xb9, 0xc6, 0xbb, 0xb4, 0xd1, 0x43, 0xd2, 0x22, - 0x2e, 0x61, 0xe7, 0x28, 0xbf, 0x02, 0x1b, 0x8b, 0x3a, 0xfa, 0x26, 0xc0, - 0x9d, 0x5c, 0x3c, 0x7d, 0x13, 0x5f, 0xf6, 0x40, 0x7b, 0x1b, 0x11, 0x31, - 0xd7, 0xf8, 0x09, 0xde, 0xe0, 0x1c, 0xea, 0x59, 0xf5, 0x80, 0xea, 0xa1, - 0x15, 0xef, 0x08, 0xdb, 0xff, 0x38, 0x60, 0x3d, 0x41, 0x45, 0x9d, 0x7f, - 0xed, 0xaf, 0xcd, 0x3f, 0x75, 0x13, 0x9d, 0x7f, 0xb5, 0xfb, 0x73, 0xc3, - 0x07, 0x52, 0xd1, 0x5b, 0xd3, 0xbf, 0x20, 0x5f, 0xfd, 0xfc, 0xba, 0xfc, - 0xdf, 0xd0, 0x93, 0x9d, 0x7f, 0xa5, 0x1c, 0x9e, 0x39, 0x39, 0xd7, 0xe7, - 0xd6, 0xdc, 0xd1, 0xd5, 0x07, 0xb8, 0x03, 0x4b, 0xf2, 0x7b, 0x4e, 0x87, - 0x5f, 0xf7, 0x01, 0xc7, 0x1f, 0x60, 0x0e, 0xa0, 0x1e, 0xe7, 0xe4, 0xb7, - 0xbe, 0xf2, 0x47, 0x5f, 0xdf, 0x7d, 0xfc, 0x64, 0xe7, 0x54, 0x8f, 0x3a, - 0x61, 0xeb, 0xff, 0x9a, 0x31, 0xe1, 0xcd, 0xb9, 0xc9, 0x1d, 0x7f, 0xdf, - 0x8a, 0x9f, 0x7b, 0xdf, 0xf4, 0x75, 0xfe, 0x11, 0x7f, 0x7d, 0x86, 0x9d, - 0x7c, 0x20, 0x9c, 0x07, 0x56, 0x1e, 0xa2, 0x19, 0x5f, 0xed, 0x7c, 0xf7, - 0xc0, 0xe0, 0x9d, 0x60, 0x1d, 0x64, 0xdc, 0xf1, 0xb8, 0x6d, 0x7e, 0x7d, - 0xf5, 0xe4, 0x3a, 0xa1, 0x3a, 0xdc, 0x23, 0x44, 0x3e, 0xc2, 0x48, 0x59, - 0xb4, 0x51, 0x7e, 0x7f, 0xd4, 0x8f, 0xa7, 0x5f, 0x98, 0x59, 0xc8, 0xd1, - 0xd5, 0x31, 0xea, 0x09, 0x55, 0xff, 0x3e, 0xa2, 0x6d, 0xe5, 0x9b, 0x4e, - 0xbf, 0xff, 0x07, 0xb1, 0xf5, 0x5f, 0x0b, 0x83, 0x5a, 0x80, 0x15, 0x70, - 0x70, 0xeb, 0xf4, 0xf1, 0x3b, 0xe8, 0xea, 0xc4, 0x4a, 0x22, 0xbb, 0x8a, - 0xdc, 0x0f, 0xce, 0xbf, 0x9c, 0x13, 0x0c, 0x04, 0xeb, 0xfe, 0x1c, 0x9c, - 0x3d, 0xc1, 0xf1, 0xd5, 0x07, 0xf5, 0xd1, 0x71, 0x2c, 0xa6, 0x29, 0xb2, - 0xae, 0x62, 0xd0, 0xd8, 0x99, 0xe3, 0x0c, 0xe7, 0x11, 0x96, 0x4a, 0x1e, - 0x41, 0x87, 0xfe, 0x46, 0x3c, 0xa2, 0x13, 0x61, 0xc1, 0xbc, 0x25, 0x10, - 0x86, 0x68, 0xe4, 0x39, 0x1c, 0x2a, 0xe1, 0x7d, 0xd8, 0xc9, 0x5e, 0x1a, - 0x60, 0x30, 0x18, 0x51, 0x69, 0xf7, 0xd2, 0x87, 0xbf, 0x85, 0x6e, 0xd2, - 0x2d, 0x98, 0x67, 0xfd, 0x85, 0x3d, 0xff, 0xf9, 0xaa, 0x83, 0x99, 0xbb, - 0x7a, 0x9e, 0xd3, 0xee, 0x75, 0x2a, 0xa8, 0x77, 0xf8, 0xf1, 0x6f, 0xa3, - 0x92, 0x59, 0xd7, 0x9f, 0x8a, 0x1d, 0x65, 0x67, 0x37, 0xac, 0x90, 0xdf, - 0xe5, 0x73, 0x8d, 0x77, 0x69, 0xa2, 0xf3, 0xa8, 0x75, 0x47, 0x52, 0x70, - 0x0c, 0x60, 0x59, 0x4d, 0x6a, 0xde, 0x58, 0xcf, 0x23, 0x82, 0x5a, 0x9f, - 0x61, 0x54, 0x35, 0xa7, 0x9e, 0x9a, 0xb6, 0x95, 0x5f, 0xe5, 0x73, 0x8d, - 0x77, 0x69, 0xa2, 0x96, 0xbf, 0x71, 0xae, 0xed, 0x34, 0x58, 0x57, 0xff, - 0xe8, 0xc1, 0x0c, 0x76, 0x37, 0xf6, 0x0b, 0xac, 0xeb, 0x68, 0xeb, 0xfb, - 0xfe, 0x24, 0xee, 0xb3, 0xac, 0xae, 0x23, 0x09, 0x66, 0x7a, 0x51, 0xd9, - 0x10, 0xbf, 0xca, 0xe7, 0x1a, 0xee, 0xd3, 0x45, 0x97, 0x77, 0x14, 0x3a, - 0xf9, 0x55, 0x18, 0x66, 0x28, 0xea, 0x2a, 0xf2, 0xbf, 0x56, 0x75, 0x34, - 0xf5, 0xf4, 0x5d, 0xf8, 0x55, 0x0a, 0x27, 0xb4, 0xdd, 0x74, 0x74, 0xeb, - 0x00, 0xeb, 0x94, 0x9c, 0xeb, 0x72, 0x46, 0xa3, 0x04, 0x29, 0xa7, 0xc6, - 0xe7, 0xb7, 0xfc, 0xfb, 0x8e, 0x6f, 0xe8, 0x50, 0xeb, 0xfd, 0x3e, 0xfa, - 0x80, 0xf9, 0x0e, 0xbf, 0x46, 0x6d, 0x8d, 0x1d, 0x68, 0x73, 0xdb, 0x64, - 0xd2, 0x9d, 0x17, 0x63, 0x09, 0x4b, 0xe7, 0x94, 0x82, 0x75, 0xfc, 0xfc, - 0x8f, 0x3f, 0x4e, 0xbc, 0xcb, 0x2c, 0x95, 0x7f, 0xd1, 0x2d, 0xfd, 0xc8, - 0xcd, 0xca, 0x54, 0xbf, 0xbf, 0xef, 0xdf, 0x7c, 0xf2, 0x6e, 0xc9, 0xd7, - 0x46, 0x8e, 0xa0, 0xa6, 0x09, 0xd2, 0x11, 0x4a, 0xd2, 0x4e, 0xd3, 0xbb, - 0x98, 0x66, 0x28, 0xeb, 0xf9, 0x1f, 0x40, 0xd7, 0xe7, 0x5f, 0xfc, 0x92, - 0x7d, 0x38, 0xfe, 0xdc, 0xd1, 0x57, 0xff, 0xf7, 0x53, 0xdd, 0xcd, 0x0e, - 0x2f, 0xfd, 0x75, 0xe4, 0x75, 0xfe, 0x89, 0x79, 0xfa, 0xe1, 0x3a, 0xa1, - 0x19, 0xb8, 0x85, 0xc5, 0xab, 0x48, 0xeb, 0x48, 0xeb, 0x48, 0xea, 0x83, - 0x60, 0xa0, 0x82, 0x08, 0x5f, 0xdf, 0xeb, 0xaf, 0x2c, 0x3a, 0xff, 0xfb, - 0x48, 0xdc, 0x1e, 0x40, 0xe0, 0x71, 0x43, 0xa9, 0x67, 0xf3, 0xe2, 0xdb, - 0x6e, 0x75, 0x94, 0x3a, 0xdf, 0x9d, 0x42, 0x68, 0xb4, 0x23, 0x58, 0x7e, - 0xba, 0x22, 0xf1, 0x9d, 0xda, 0x50, 0xeb, 0x61, 0xd7, 0x7e, 0x08, 0x34, - 0xc1, 0x17, 0xb9, 0x20, 0xeb, 0xf8, 0x61, 0x63, 0x18, 0x75, 0xd2, 0x83, - 0xaa, 0x73, 0xff, 0x09, 0x6c, 0xc2, 0x9f, 0x94, 0xdf, 0xff, 0xff, 0x76, - 0x3d, 0xa4, 0xd6, 0xa3, 0xdd, 0x48, 0xe0, 0x16, 0xf2, 0x97, 0x94, 0x3a, - 0xe4, 0xdc, 0xeb, 0xa1, 0x67, 0x5f, 0xff, 0xa0, 0x7f, 0x94, 0xa3, 0xdd, - 0xc5, 0xfd, 0x80, 0x1d, 0x7f, 0xfc, 0x83, 0xfc, 0xb3, 0x5c, 0x84, 0x93, - 0xe8, 0xaa, 0x92, 0x28, 0xfc, 0xad, 0x73, 0x55, 0x85, 0xfe, 0xa9, 0xe1, - 0x0a, 0x18, 0x6e, 0x64, 0x65, 0x4a, 0x26, 0x34, 0x83, 0x90, 0xfa, 0x75, - 0xe1, 0x8c, 0x6f, 0x50, 0xd3, 0xf1, 0xfe, 0xd7, 0xdd, 0x91, 0x6f, 0xb0, - 0xb8, 0xbf, 0xfc, 0xaa, 0xde, 0x4a, 0xe7, 0x1a, 0xee, 0xd3, 0x45, 0x19, - 0x7e, 0xdb, 0x1c, 0x80, 0x1d, 0x7e, 0x17, 0x04, 0x7d, 0x3a, 0xff, 0xed, - 0xda, 0x9c, 0xee, 0x60, 0xcb, 0x47, 0x59, 0x58, 0x44, 0x97, 0x4a, 0x3c, - 0x4f, 0x52, 0x66, 0x13, 0x72, 0x30, 0x15, 0xa3, 0x3d, 0x23, 0x1f, 0x50, - 0xf9, 0xf4, 0x3a, 0x6f, 0xfe, 0x55, 0xe4, 0xae, 0x71, 0xae, 0xed, 0x34, - 0x47, 0x37, 0xff, 0x95, 0x5b, 0xc9, 0x5c, 0xe3, 0x5d, 0xda, 0x68, 0x9c, - 0xaf, 0xf2, 0xb9, 0xc6, 0xbb, 0xb4, 0xd1, 0x66, 0x5f, 0xf4, 0xb4, 0xeb, - 0x57, 0xbe, 0x01, 0xd7, 0xfc, 0xc3, 0x83, 0x8b, 0x8d, 0xe1, 0x67, 0x5f, - 0xee, 0x47, 0xba, 0xfb, 0xc8, 0xeb, 0xff, 0xff, 0xe8, 0x9b, 0xb1, 0xe8, - 0xfa, 0x9c, 0x9a, 0x3b, 0x9b, 0x73, 0xb8, 0x1d, 0xb8, 0x75, 0x01, 0x16, - 0x82, 0x67, 0x7f, 0xb3, 0x5c, 0xe6, 0x6f, 0xa3, 0xaf, 0xd9, 0xee, 0x62, - 0xce, 0xbf, 0xf2, 0x0c, 0x6a, 0x3d, 0x3e, 0x32, 0x75, 0xfd, 0xc6, 0xf5, - 0xd1, 0x82, 0x75, 0xdb, 0xac, 0xeb, 0x2a, 0xc5, 0x27, 0xe3, 0x10, 0xf2, - 0x91, 0x10, 0x4c, 0xd6, 0x4d, 0xf9, 0xee, 0xc9, 0x85, 0xfe, 0x57, 0x38, - 0xd7, 0x76, 0x9a, 0x2d, 0xdb, 0xf8, 0x5d, 0x5e, 0x4f, 0xd3, 0xaf, 0x26, - 0xe0, 0x3a, 0xfd, 0xc6, 0xbb, 0xb4, 0xd1, 0x48, 0x5f, 0xfb, 0x3a, 0x9b, - 0x7b, 0x98, 0x2d, 0x3a, 0xf3, 0xc9, 0x5c, 0x3f, 0x0d, 0x19, 0xd9, 0x56, - 0xa3, 0xb7, 0x85, 0xcb, 0x84, 0x65, 0xff, 0xca, 0xbc, 0x95, 0xce, 0x35, - 0xdd, 0xa6, 0x89, 0x4a, 0xa7, 0x5d, 0x44, 0x99, 0x45, 0x6a, 0xee, 0x7e, - 0x09, 0x45, 0x62, 0xf3, 0xe8, 0xcb, 0x36, 0x0f, 0x2f, 0xf4, 0x90, 0x7d, - 0x88, 0x13, 0xaf, 0x6b, 0xf5, 0x9d, 0x65, 0x77, 0x3c, 0xd4, 0x30, 0xbc, - 0x2f, 0x23, 0xaf, 0xfc, 0xf2, 0x57, 0x38, 0xd7, 0x76, 0x9a, 0x27, 0x6b, - 0xa7, 0x63, 0x3a, 0xff, 0xfc, 0x81, 0xfd, 0x71, 0xb0, 0xe1, 0x18, 0x1c, - 0x69, 0xd7, 0xfa, 0x51, 0xc9, 0xe3, 0x93, 0x9d, 0x7f, 0xee, 0x8b, 0xcb, - 0xf0, 0x2d, 0xe4, 0x75, 0x41, 0xf9, 0x61, 0xa5, 0x95, 0xc4, 0xd9, 0x56, - 0x35, 0xd4, 0xa7, 0x1a, 0x18, 0x63, 0xdf, 0xff, 0x2b, 0xf7, 0x65, 0xc4, - 0x19, 0xe8, 0x14, 0x01, 0xd7, 0xff, 0x3a, 0xfb, 0x8d, 0x7e, 0xc7, 0xd9, - 0x1d, 0x79, 0x02, 0xe7, 0x5f, 0xfc, 0x39, 0xd7, 0x9f, 0x34, 0x2f, 0xb9, - 0xd7, 0x6c, 0xaa, 0x14, 0x50, 0x75, 0x13, 0x43, 0x55, 0x25, 0x62, 0x8b, - 0x8e, 0x3b, 0x4a, 0x9b, 0x30, 0xf2, 0xbf, 0xff, 0x82, 0xfe, 0x57, 0x35, - 0x03, 0xb8, 0x35, 0xa8, 0x01, 0xd7, 0xee, 0x35, 0xdd, 0xa6, 0x88, 0xb2, - 0xff, 0xcf, 0x25, 0x73, 0x8d, 0x77, 0x69, 0xa2, 0x5d, 0xbf, 0xff, 0xb0, - 0x3d, 0x8f, 0xaa, 0xf8, 0x5c, 0x1a, 0xd4, 0x00, 0xab, 0x2b, 0x88, 0xd9, - 0x59, 0x9e, 0xca, 0x55, 0xff, 0xcb, 0x79, 0x2b, 0x9c, 0x6b, 0xbb, 0x4d, - 0x13, 0x15, 0xff, 0xf6, 0x36, 0x15, 0xeb, 0xa6, 0xca, 0x03, 0x02, 0x75, - 0x2a, 0x8a, 0x0e, 0xa8, 0x5f, 0xb8, 0xd7, 0x76, 0x9a, 0x2a, 0x9b, 0x61, - 0xd5, 0x87, 0x84, 0xa1, 0x9d, 0xff, 0xbf, 0x7e, 0x48, 0x71, 0x97, 0x01, - 0xd7, 0xff, 0x3e, 0xb8, 0x8c, 0xfb, 0xa9, 0xc9, 0x1d, 0x7f, 0xdc, 0x7e, - 0xef, 0x2c, 0xf2, 0xa1, 0x44, 0x17, 0x4f, 0xa9, 0x54, 0x7b, 0xbc, 0x29, - 0x2f, 0xff, 0x2a, 0xb7, 0x92, 0xb9, 0xc6, 0xbb, 0xb4, 0xd1, 0x3a, 0x5f, - 0xe4, 0x7e, 0x44, 0x9f, 0x69, 0xd7, 0xe9, 0xa2, 0x68, 0xd1, 0xd7, 0xf3, - 0x38, 0x9b, 0x70, 0x4e, 0xa4, 0x3d, 0x5d, 0x14, 0x5e, 0x4e, 0xc1, 0xca, - 0x9a, 0x1b, 0xff, 0xbf, 0xd7, 0xa3, 0x75, 0x7f, 0x99, 0x16, 0x75, 0x2c, - 0xfd, 0x3a, 0x57, 0x7f, 0xe7, 0x92, 0xb9, 0xc6, 0xbb, 0xb4, 0xd1, 0x3b, - 0xdf, 0xbd, 0xfb, 0xad, 0x0a, 0xbf, 0xf0, 0xc7, 0xb3, 0x59, 0x9b, 0xc8, - 0xea, 0x0a, 0x7d, 0x79, 0x18, 0xe2, 0xc8, 0x9d, 0x2b, 0xc4, 0xf7, 0xfc, - 0x18, 0x94, 0x2a, 0xce, 0x80, 0x75, 0xfd, 0x0a, 0x80, 0x70, 0x27, 0x52, - 0xa8, 0xb5, 0xc4, 0xf1, 0x3a, 0xbf, 0xfc, 0xaa, 0xde, 0x4a, 0xe7, 0x1a, - 0xee, 0xd3, 0x45, 0x0b, 0x7f, 0xff, 0xfb, 0xbf, 0xad, 0x6f, 0x25, 0x5b, - 0xdf, 0xfd, 0x03, 0x93, 0xa9, 0xfc, 0x4c, 0x75, 0xfb, 0xfd, 0xfc, 0x8d, - 0x3a, 0xfd, 0x80, 0xc7, 0x13, 0xaf, 0xb4, 0x8c, 0xf8, 0xeb, 0xd0, 0x05, - 0x67, 0x3e, 0xf1, 0x29, 0xf1, 0x25, 0x22, 0x65, 0xc3, 0x0e, 0xdb, 0xff, - 0xca, 0xad, 0xe4, 0xae, 0x71, 0xae, 0xed, 0x34, 0x52, 0x57, 0xff, 0xfb, - 0x34, 0xaf, 0xdc, 0x9b, 0xae, 0xbf, 0x76, 0x3d, 0xfa, 0xce, 0xa8, 0x64, - 0x90, 0x4f, 0x19, 0xa4, 0xa1, 0xb2, 0xd8, 0xd7, 0x78, 0x50, 0xb9, 0x5e, - 0xe0, 0x2f, 0xf4, 0x70, 0xbf, 0x93, 0xec, 0xab, 0xdf, 0xe5, 0x73, 0x8d, - 0x77, 0x69, 0xa2, 0x24, 0xbf, 0xfc, 0xaa, 0xde, 0x4a, 0xe7, 0x1a, 0xee, - 0xd3, 0x44, 0xbd, 0x79, 0x8a, 0x58, 0x0e, 0xbe, 0xe7, 0xfe, 0xd1, 0xd7, - 0xee, 0x01, 0x69, 0xa3, 0xaf, 0x40, 0xee, 0x75, 0xfb, 0xdf, 0x56, 0x30, - 0x75, 0x93, 0xa7, 0x86, 0x23, 0x77, 0xff, 0xbb, 0xb6, 0x04, 0x0c, 0x78, - 0x1c, 0xe6, 0xe7, 0x5d, 0x1e, 0x3a, 0xff, 0xf7, 0xe1, 0x4e, 0x7d, 0x9b, - 0x63, 0xf7, 0x19, 0x8e, 0xa9, 0x23, 0x6d, 0x09, 0x80, 0x9d, 0xa1, 0x5b, - 0xf8, 0x1d, 0x8e, 0x22, 0xce, 0xbf, 0xf4, 0xda, 0x8d, 0xaf, 0xd8, 0xde, - 0x63, 0xaa, 0x0f, 0xb9, 0xcb, 0x2f, 0xd9, 0x3e, 0x69, 0x67, 0x5f, 0xfd, - 0x37, 0xcf, 0xa3, 0x1b, 0x5f, 0x6c, 0x4c, 0x75, 0x1d, 0x7e, 0x93, 0xf9, - 0xf6, 0x9d, 0x7e, 0x7d, 0x46, 0xdc, 0x3a, 0xa6, 0x3c, 0xfd, 0xa5, 0x15, - 0x08, 0xca, 0xc4, 0xc7, 0x59, 0xbb, 0x90, 0x75, 0x05, 0x5b, 0x2a, 0x11, - 0xcd, 0x1a, 0x2f, 0x21, 0x54, 0x24, 0x1b, 0x61, 0xe3, 0xb0, 0x5b, 0x76, - 0x09, 0xd7, 0xf7, 0xcd, 0x77, 0x13, 0xc7, 0x50, 0x4f, 0x09, 0x05, 0x2e, - 0x0e, 0xe7, 0x5f, 0xc3, 0xff, 0xa6, 0x85, 0x0e, 0xbc, 0xc1, 0x4e, 0x1d, - 0x64, 0x73, 0xce, 0xfc, 0xbe, 0xfc, 0x39, 0x3f, 0xdd, 0xa7, 0x5f, 0x64, - 0xff, 0x76, 0x9d, 0x7e, 0x0c, 0x6e, 0x17, 0xf8, 0x7a, 0x22, 0x57, 0x7f, - 0xfc, 0x9c, 0xf9, 0xd8, 0x4f, 0x6b, 0xf6, 0xff, 0x07, 0x5f, 0x24, 0xe0, - 0x63, 0x3a, 0xf9, 0xae, 0xed, 0x34, 0x52, 0xf7, 0xc3, 0xe8, 0xe1, 0xd7, - 0xfd, 0x9c, 0x63, 0xc0, 0xe7, 0x37, 0x3a, 0x90, 0xf6, 0xf6, 0x90, 0x54, - 0x93, 0x62, 0x51, 0x02, 0x65, 0x2e, 0x12, 0xf6, 0x11, 0x17, 0xf0, 0x77, - 0x8e, 0x26, 0xe7, 0x5f, 0x7a, 0x7c, 0x64, 0xea, 0x43, 0xd1, 0x12, 0xeb, - 0xff, 0x40, 0xc7, 0x7e, 0x7e, 0x3f, 0xb4, 0xeb, 0xdf, 0xbe, 0x8e, 0xbe, - 0x9b, 0xf7, 0x98, 0xeb, 0xf4, 0x01, 0xf7, 0xd1, 0xd7, 0x85, 0x00, 0x75, - 0xec, 0xf6, 0x8e, 0xa8, 0x36, 0xba, 0x1a, 0xa0, 0xa3, 0xf2, 0x64, 0x0e, - 0x8e, 0x00, 0x93, 0xcb, 0x97, 0xe6, 0x37, 0x10, 0xec, 0x1d, 0x7f, 0xc0, - 0xd7, 0x23, 0x79, 0x22, 0xce, 0xbd, 0xe7, 0xda, 0x75, 0xfa, 0x7f, 0xe6, - 0x86, 0x33, 0xaf, 0xbf, 0x9a, 0x18, 0xce, 0xb9, 0xe7, 0xf8, 0x7a, 0x73, - 0x96, 0xd4, 0x23, 0x69, 0xce, 0x7f, 0x70, 0xbf, 0xe4, 0xd4, 0xc8, 0x3e, - 0x80, 0x1d, 0x7f, 0xf0, 0xfb, 0x6c, 0x73, 0x4e, 0x30, 0xc6, 0x75, 0x49, - 0x15, 0x8b, 0x2f, 0xd1, 0xbd, 0xfe, 0x86, 0x3d, 0x42, 0xdf, 0xc7, 0x5c, - 0xe2, 0x75, 0xff, 0x40, 0x3e, 0x76, 0x16, 0xe2, 0x75, 0x6e, 0x79, 0x9b, - 0x45, 0x2a, 0x48, 0xa5, 0xe4, 0x20, 0x2f, 0xe8, 0x65, 0x3b, 0xfb, 0x19, - 0xd7, 0xf6, 0xf2, 0xd3, 0x8e, 0xe7, 0x54, 0x2b, 0x0e, 0xc8, 0xec, 0x92, - 0x1a, 0xbc, 0x28, 0xfa, 0x63, 0x7b, 0x90, 0xb3, 0xaf, 0xe8, 0x19, 0xbc, - 0x8a, 0x1d, 0x7f, 0xd2, 0xce, 0x4d, 0x83, 0x0b, 0x3a, 0xfc, 0x08, 0x6e, - 0x2c, 0xeb, 0xfd, 0x93, 0xea, 0x26, 0xff, 0x87, 0x52, 0x22, 0x4b, 0x86, - 0xe2, 0x4d, 0x74, 0xb0, 0xeb, 0xee, 0x0c, 0x2c, 0xeb, 0xd0, 0x0d, 0x1d, - 0x50, 0x7f, 0xc1, 0x2e, 0xc1, 0x56, 0x48, 0x2f, 0xdd, 0xfd, 0x4c, 0x13, - 0xaf, 0xfa, 0x3b, 0xa7, 0xf4, 0x73, 0x60, 0xeb, 0xff, 0x2d, 0xc3, 0xf6, - 0x69, 0x40, 0xee, 0x75, 0x04, 0xfe, 0xd0, 0xea, 0xfb, 0x80, 0xfb, 0xb4, - 0xeb, 0xc8, 0xcf, 0x8e, 0xae, 0x9e, 0x16, 0x89, 0xa8, 0x29, 0x94, 0x76, - 0x14, 0x7e, 0x63, 0xbf, 0xc3, 0xec, 0xd2, 0x3f, 0x4e, 0xbf, 0xe0, 0x27, - 0x73, 0x8f, 0x36, 0x8e, 0xbf, 0xff, 0x44, 0x86, 0x27, 0xfb, 0x36, 0xbb, - 0x9b, 0x1c, 0x01, 0xd7, 0xf7, 0xc5, 0xe7, 0x9f, 0xc7, 0x59, 0xa7, 0x5d, - 0xbe, 0xb0, 0xdf, 0x39, 0x75, 0xe8, 0x40, 0x9d, 0x50, 0x9a, 0x3e, 0xe6, - 0x0b, 0x38, 0x78, 0x4c, 0xe8, 0xb2, 0xff, 0x63, 0x32, 0x4d, 0x7e, 0xb3, - 0xae, 0xdb, 0xa3, 0xaf, 0xef, 0xf5, 0x13, 0x7f, 0xc3, 0xaf, 0xd9, 0x3e, - 0x77, 0x47, 0x54, 0x1f, 0x7f, 0x46, 0x04, 0xc2, 0xf6, 0x73, 0x47, 0x53, - 0x4f, 0x23, 0x69, 0x6d, 0xff, 0x02, 0x01, 0xf7, 0x6c, 0x0e, 0xc1, 0xd5, - 0x09, 0xa6, 0xe4, 0x3a, 0xd0, 0x92, 0xff, 0xff, 0xee, 0xc7, 0x37, 0x6a, - 0x6f, 0xf1, 0x47, 0xf9, 0xae, 0xbb, 0x60, 0x42, 0x75, 0xf2, 0x29, 0xb3, - 0x87, 0x5f, 0xdf, 0x7d, 0x13, 0x8e, 0xe7, 0x5e, 0x14, 0x59, 0xd5, 0xc3, - 0xee, 0x01, 0x27, 0x8c, 0x2f, 0xf0, 0xc3, 0x8f, 0xb0, 0x4e, 0xbf, 0xdd, - 0x79, 0x93, 0x91, 0x39, 0xd7, 0x62, 0xce, 0xa0, 0xa7, 0x15, 0x90, 0xe5, - 0x59, 0x7b, 0x97, 0x6d, 0x33, 0xbf, 0x6c, 0x22, 0xe3, 0x47, 0x5f, 0x9f, - 0x6e, 0x73, 0x47, 0x50, 0x4f, 0x45, 0x65, 0x37, 0xee, 0xb8, 0xa2, 0xce, - 0xbe, 0x52, 0x6d, 0x41, 0xd7, 0xf0, 0x37, 0x06, 0x73, 0x0e, 0xbf, 0x9c, - 0x0b, 0x8c, 0xf1, 0xd5, 0x07, 0xb0, 0x85, 0xb7, 0xf9, 0xc1, 0xa8, 0xec, - 0x68, 0xeb, 0xc3, 0x93, 0x9d, 0x50, 0x99, 0x76, 0x11, 0x21, 0x2f, 0x5e, - 0xc4, 0x83, 0x46, 0x37, 0x01, 0xa7, 0x5b, 0x47, 0x5c, 0x8a, 0x68, 0xd3, - 0x7e, 0x2d, 0x78, 0x0e, 0xd3, 0xaf, 0x99, 0x9b, 0x50, 0x75, 0xfd, 0xa1, - 0x79, 0xe3, 0xc7, 0x5f, 0xa7, 0x7d, 0x64, 0x8e, 0xbf, 0xfe, 0x0e, 0x6d, - 0x7e, 0x4d, 0xf6, 0x4f, 0xe7, 0x59, 0xd5, 0x07, 0xf4, 0x84, 0xf7, 0xf3, - 0xee, 0x05, 0xa6, 0x8e, 0xa8, 0x4c, 0xc7, 0x71, 0xb9, 0x88, 0xf9, 0x0a, - 0x6e, 0x90, 0x5f, 0xef, 0x23, 0x2f, 0x34, 0x2c, 0xeb, 0x2a, 0xc5, 0xb6, - 0xf9, 0xb1, 0x2e, 0x1a, 0x78, 0x5e, 0x48, 0x84, 0x2c, 0xb9, 0x1e, 0xd6, - 0xf0, 0xa3, 0x48, 0xc7, 0x26, 0x96, 0xb3, 0xc5, 0x65, 0x8d, 0xf6, 0x33, - 0xd7, 0x8d, 0x8c, 0x11, 0xbe, 0x8c, 0x73, 0x9a, 0x8e, 0xf7, 0xd1, 0xe7, - 0xec, 0xbd, 0x7d, 0x8d, 0x7f, 0x61, 0x46, 0xff, 0x2b, 0x9c, 0x6b, 0xbb, - 0x4d, 0x14, 0xe5, 0xfe, 0x5c, 0x2f, 0x36, 0x23, 0xc7, 0x5f, 0xf9, 0x38, - 0xfa, 0xee, 0x60, 0xb4, 0xeb, 0xf2, 0xf9, 0xcc, 0xd1, 0xd7, 0xff, 0xee, - 0xff, 0xee, 0x47, 0xb5, 0x8d, 0xd4, 0x71, 0xa7, 0x5f, 0xff, 0xde, 0xc9, - 0x85, 0x35, 0xe8, 0xfa, 0x9c, 0x9a, 0x3a, 0x75, 0xfe, 0x45, 0x86, 0x35, - 0xf8, 0x9d, 0x7f, 0x67, 0xb7, 0x94, 0x32, 0x75, 0xff, 0x93, 0x7d, 0x0e, - 0x07, 0xae, 0xc9, 0xd7, 0xff, 0xd9, 0x3e, 0x6f, 0xed, 0x20, 0xc0, 0x1d, - 0x67, 0x52, 0x88, 0x8c, 0xd1, 0xf5, 0xff, 0xb3, 0xb1, 0xcc, 0x55, 0x96, - 0x59, 0x2a, 0xe4, 0x64, 0xeb, 0xa7, 0x56, 0x15, 0x57, 0x84, 0xd3, 0x0e, - 0xda, 0x4e, 0x8a, 0xdd, 0x5c, 0x13, 0x2f, 0x42, 0xeb, 0x64, 0x93, 0x61, - 0x06, 0xfd, 0xc6, 0xbb, 0xb4, 0xd1, 0x5e, 0x5f, 0xff, 0xd8, 0x1e, 0xc7, - 0xd5, 0x7c, 0x2e, 0x0d, 0x6a, 0x00, 0x55, 0x95, 0xc4, 0x47, 0xec, 0x99, - 0xdf, 0xfc, 0xab, 0xc9, 0x5c, 0xe3, 0x5d, 0xda, 0x68, 0x91, 0xef, 0x37, - 0x16, 0x75, 0xe4, 0x04, 0x1d, 0x79, 0xb8, 0xb2, 0x95, 0x2e, 0xaf, 0xdc, - 0x6b, 0xbb, 0x4d, 0x12, 0x45, 0xff, 0xfd, 0x09, 0xc4, 0xd8, 0x81, 0x9e, - 0x3c, 0x9d, 0x79, 0xce, 0xbf, 0xfc, 0x38, 0x0d, 0x9c, 0xe4, 0x4e, 0xfc, - 0x69, 0xd7, 0x49, 0x58, 0x4c, 0x13, 0x0a, 0xfa, 0x67, 0xe5, 0xbb, 0xf6, - 0x75, 0x5c, 0x59, 0xd6, 0x56, 0x13, 0xa9, 0x78, 0xce, 0x7c, 0x93, 0x7f, - 0xf2, 0xaf, 0x25, 0x73, 0x8d, 0x77, 0x69, 0xa2, 0x4a, 0xbf, 0x71, 0xae, - 0xed, 0x34, 0x5e, 0x37, 0xfd, 0x25, 0x73, 0x8d, 0x77, 0x69, 0xa2, 0x4d, - 0xb2, 0xb8, 0x7f, 0x0e, 0x67, 0x73, 0x3d, 0x3a, 0xfc, 0x80, 0xd6, 0x09, - 0xd7, 0xff, 0xdf, 0xbe, 0xf9, 0x8a, 0x28, 0xf2, 0xcd, 0xfc, 0x75, 0x48, - 0xfd, 0xf4, 0x4b, 0x7f, 0xf3, 0x81, 0xbd, 0x4e, 0x0a, 0x7b, 0x47, 0x5c, - 0x33, 0x9d, 0x4e, 0x7b, 0x1f, 0x50, 0xae, 0xe7, 0x8e, 0xbd, 0x30, 0xce, - 0x75, 0xfe, 0xc6, 0x87, 0xf9, 0xfe, 0xac, 0xeb, 0x09, 0xd7, 0x7d, 0xfa, - 0x75, 0x00, 0xd4, 0xfd, 0x0f, 0xbb, 0x65, 0x58, 0x4f, 0x87, 0x21, 0x1d, - 0xd7, 0xa7, 0x23, 0xd0, 0xb7, 0x87, 0x7e, 0xb0, 0x54, 0x3a, 0x3a, 0x09, - 0xcf, 0xe5, 0x5c, 0x12, 0x06, 0x37, 0x24, 0x95, 0xdd, 0x34, 0x66, 0x2b, - 0x2c, 0xec, 0x7f, 0x5e, 0x3c, 0xfe, 0x19, 0x3f, 0x65, 0x04, 0x54, 0x4e, - 0x4b, 0x25, 0x4f, 0x2a, 0x66, 0x53, 0xc0, 0x81, 0x9d, 0xc8, 0xcc, 0x4f, - 0x3b, 0xa9, 0x39, 0x9c, 0xdb, 0xe0, 0x5d, 0xde, 0xb5, 0x18, 0x4a, 0x50, - 0xeb, 0x1c, 0xa2, 0xc9, 0xad, 0xbd, 0xff, 0x2d, 0x41, 0x72, 0xf3, 0xa5, - 0x90, 0xed, 0x2e, 0x41, 0xed, 0xcc, 0x20, 0x29, 0x0a, 0x6c, 0x18, 0xfb, - 0x86, 0xb7, 0xd4, 0xd5, 0x73, 0x55, 0xeb, 0xdf, 0xb4, 0xfe, 0xdb, 0xe2, - 0xed, 0xa6, 0x77, 0xb3, 0x3b, 0x6f, 0xb3, 0x2f, 0x97, 0xed, 0x25, 0xb7, - 0x62, 0xd2, 0x28, 0xd0, + 0xea, 0x83, 0xc6, 0x72, 0x4b, 0xb1, 0x93, 0xa8, 0xb8, 0x86, 0x2f, 0xed, + 0x7d, 0x8e, 0x42, 0xcb, 0x88, 0x62, 0x8b, 0x88, 0x62, 0x8b, 0x88, 0x62, + 0x8b, 0x88, 0x62, 0x8b, 0x88, 0x62, 0xa4, 0x8b, 0x44, 0x18, 0x01, 0xe7, + 0xe3, 0x1b, 0x23, 0x1b, 0x03, 0x17, 0x77, 0x0b, 0x88, 0x62, 0xfe, 0x77, + 0xf4, 0xd0, 0xb2, 0xe2, 0x18, 0xf8, 0x68, 0xec, 0xc1, 0x2e, 0x21, 0x8a, + 0x2e, 0x21, 0x8a, 0x2e, 0x21, 0x8a, 0x91, 0xb0, 0x41, 0x8a, 0x2e, 0x21, + 0x8a, 0x2e, 0x21, 0x8a, 0x2e, 0x21, 0x8a, 0x2e, 0x21, 0x8a, 0x2e, 0x21, + 0x8a, 0x2e, 0x21, 0x8a, 0x9d, 0x12, 0x01, 0x18, 0x41, 0x80, 0x0c, 0x68, + 0x63, 0x68, 0xc5, 0x17, 0x10, 0xc5, 0x17, 0x10, 0xc5, 0x48, 0xd8, 0x68, + 0x62, 0x8b, 0x88, 0x62, 0x8b, 0x88, 0x62, 0x8b, 0x88, 0x62, 0x8b, 0x88, + 0x62, 0xa4, 0x7c, 0x00, 0x18, 0xf0, 0xc6, 0xc0, 0xc5, 0x17, 0x10, 0xc5, + 0x17, 0x10, 0xc5, 0x17, 0x10, 0xc5, 0x17, 0x10, 0xc5, 0x4e, 0x7c, 0x0a, + 0x0c, 0x70, 0x63, 0xa3, 0x16, 0x50, 0xb8, 0x86, 0x28, 0xb8, 0x86, 0x28, + 0xb8, 0x86, 0x28, 0xb8, 0x86, 0x28, 0xb8, 0x86, 0x28, 0x27, 0xc1, 0xb8, + 0xc0, 0x06, 0x3f, 0x18, 0xa2, 0xe2, 0x18, 0xa2, 0xe2, 0x18, 0xa2, 0xe2, + 0x18, 0xbf, 0x76, 0x01, 0xac, 0x2e, 0x21, 0x8a, 0x2e, 0x21, 0x8a, 0x92, + 0x25, 0x1a, 0x31, 0xd1, 0x87, 0x18, 0x01, 0xa5, 0x9a, 0x5c, 0x43, 0x14, + 0x5c, 0x43, 0x14, 0x5c, 0x43, 0x14, 0x5c, 0x43, 0x14, 0x5c, 0x43, 0x15, + 0x23, 0xe0, 0xdc, 0x61, 0x06, 0x36, 0x8c, 0x51, 0x71, 0x0c, 0x51, 0x71, + 0x0c, 0x51, 0x71, 0x0c, 0x51, 0x71, 0x0c, 0x54, 0x8f, 0x80, 0x23, 0x1d, + 0x18, 0x11, 0x8b, 0x74, 0xb8, 0x86, 0x28, 0xb8, 0x86, 0x28, 0xb8, 0x86, + 0x2d, 0x22, 0xe2, 0x18, 0xa2, 0xe2, 0x18, 0xdc, 0xbe, 0xa2, 0xe2, 0x18, + 0xa2, 0xe2, 0x18, 0xa2, 0xe2, 0x18, 0xa2, 0xe2, 0x18, 0xa9, 0xd1, 0xad, + 0x21, 0x85, 0x0d, 0x9a, 0x51, 0x30, 0xc0, 0x06, 0x3c, 0x31, 0x6c, 0x2e, + 0x21, 0x8a, 0x2e, 0x21, 0x8a, 0x2e, 0x21, 0x8b, 0x48, 0xb8, 0x86, 0x28, + 0xb8, 0x86, 0x37, 0x2f, 0xa8, 0xb8, 0x86, 0x28, 0xb8, 0x86, 0x2a, 0x11, + 0x4d, 0x21, 0x84, 0x36, 0xe1, 0x42, 0xc6, 0x28, 0xb8, 0x86, 0x28, 0xb8, + 0x86, 0x28, 0xb8, 0x86, 0x28, 0xb8, 0x86, 0x28, 0xb8, 0x86, 0x2a, 0x0f, + 0xe3, 0x71, 0x8e, 0x0c, 0x2c, 0x60, 0x46, 0x28, 0xb8, 0x86, 0x28, 0xb8, + 0x86, 0x28, 0xb8, 0x86, 0x2b, 0x87, 0x91, 0xa1, 0x8f, 0x0c, 0x51, 0x71, + 0x0c, 0x51, 0x71, 0x0c, 0x51, 0x71, 0x0c, 0x52, 0xcf, 0x20, 0x46, 0x3c, + 0x31, 0x65, 0x97, 0x10, 0xc5, 0x17, 0x10, 0xc5, 0x17, 0x10, 0xc5, 0x00, + 0xd8, 0x7e, 0x31, 0x45, 0xc4, 0x31, 0x45, 0xc4, 0x31, 0x45, 0xc4, 0x31, + 0x45, 0xc4, 0x31, 0x50, 0x7c, 0x13, 0x0c, 0x74, 0x63, 0xf1, 0x8a, 0x86, + 0x5e, 0x34, 0xf0, 0x80, 0x92, 0x60, 0x54, 0xb2, 0x16, 0x0d, 0x84, 0x4e, + 0xf0, 0x81, 0x48, 0x4f, 0xb1, 0x9f, 0x4c, 0xff, 0xc8, 0x69, 0x2d, 0x27, + 0xaf, 0xcf, 0x09, 0xe0, 0x1d, 0x8c, 0x3d, 0x34, 0xcf, 0xe8, 0x61, 0xff, + 0x0c, 0x0d, 0xb0, 0x90, 0x65, 0xdf, 0x64, 0xbb, 0xea, 0x76, 0xc4, 0x20, + 0xaf, 0xd2, 0x18, 0xcd, 0x17, 0x10, 0xc2, 0xa9, 0xc7, 0x5e, 0x48, 0x59, + 0x71, 0x0c, 0x5f, 0x23, 0x5f, 0x87, 0xc4, 0x32, 0xf2, 0x07, 0x0f, 0x88, + 0x65, 0x95, 0xdd, 0x18, 0x7c, 0x47, 0xe9, 0x47, 0x8b, 0x6d, 0x1b, 0x59, + 0xe4, 0xdf, 0x69, 0xdc, 0x37, 0xfb, 0xa8, 0xc8, 0x79, 0x13, 0x9d, 0x79, + 0x36, 0xb0, 0x4e, 0xad, 0xd1, 0x1d, 0x31, 0xcf, 0x8d, 0x2f, 0xd9, 0x93, + 0x3f, 0xd3, 0xae, 0x04, 0x1d, 0x7f, 0x71, 0xc7, 0xec, 0x00, 0xeb, 0x9f, + 0x87, 0x59, 0x0e, 0x69, 0x6b, 0x66, 0x9d, 0x65, 0x9d, 0x76, 0xca, 0xa8, + 0x89, 0x5e, 0x0a, 0xf5, 0x09, 0xc7, 0xbe, 0x88, 0x5f, 0xf7, 0x61, 0x79, + 0x34, 0x0c, 0xe7, 0x5f, 0xfd, 0xf1, 0xda, 0x1e, 0xc0, 0x30, 0x40, 0x75, + 0xc0, 0x83, 0xab, 0x0f, 0x64, 0x08, 0x95, 0x89, 0x86, 0x01, 0x6b, 0xf8, + 0x48, 0xdf, 0xfc, 0x23, 0x13, 0x8e, 0x26, 0xd8, 0xd9, 0x3a, 0xf4, 0x6f, + 0xa3, 0xa9, 0xcf, 0x87, 0x48, 0xb7, 0x9f, 0x90, 0x75, 0xf9, 0x36, 0x5c, + 0x40, 0x75, 0x48, 0xf0, 0x96, 0x35, 0x7f, 0xdf, 0x5c, 0x3a, 0xc5, 0xc3, + 0x19, 0xd7, 0xb3, 0x76, 0x4e, 0xbd, 0xb8, 0x33, 0x87, 0xb2, 0x27, 0x97, + 0xdb, 0x73, 0x92, 0x3a, 0xf0, 0x5c, 0x4e, 0xa4, 0x37, 0xae, 0x47, 0x7f, + 0xfd, 0x1f, 0x1f, 0x9c, 0x70, 0x42, 0xac, 0xb2, 0xc9, 0xd5, 0x09, 0xaf, + 0x3b, 0xde, 0x9c, 0x3f, 0x1f, 0xbf, 0xfb, 0xff, 0xb3, 0x7c, 0x8f, 0xae, + 0xd8, 0xe9, 0xd4, 0xc0, 0x6f, 0xbe, 0x21, 0xca, 0x76, 0xf9, 0x46, 0x4a, + 0x18, 0x4f, 0x64, 0x2d, 0x9b, 0x1a, 0x46, 0xea, 0xe9, 0x29, 0x7d, 0x8d, + 0x16, 0x68, 0x5d, 0x70, 0xdd, 0x71, 0x81, 0xf6, 0x17, 0x0f, 0x4f, 0xd4, + 0x01, 0x90, 0xc7, 0x93, 0xa8, 0x4b, 0xfa, 0x3c, 0x1f, 0xa7, 0xb7, 0x97, + 0xa6, 0x9d, 0x78, 0x5b, 0x07, 0x57, 0xc3, 0x6c, 0x83, 0x97, 0xf3, 0x2f, + 0xce, 0x3e, 0xe7, 0x5f, 0xff, 0xb5, 0xce, 0x24, 0xda, 0xe4, 0x79, 0x1a, + 0x81, 0x3a, 0x96, 0x8a, 0x51, 0x22, 0x64, 0xba, 0xf9, 0x7e, 0x8d, 0x1d, + 0x7d, 0xc4, 0x15, 0x0e, 0xbf, 0xde, 0x8f, 0xdb, 0xd4, 0xe1, 0xd7, 0xf6, + 0x37, 0xb1, 0xbc, 0x8e, 0xbf, 0x97, 0xa4, 0x53, 0xcc, 0x9d, 0x7e, 0x8d, + 0xfb, 0x12, 0x3a, 0xb8, 0x8d, 0x71, 0x21, 0xf1, 0x9f, 0xd2, 0xdd, 0x82, + 0xfb, 0xfe, 0xcd, 0xc7, 0x3d, 0xec, 0x9c, 0xeb, 0xb7, 0xf1, 0xd7, 0xec, + 0x19, 0xd3, 0x87, 0x5f, 0xbc, 0xe3, 0xfe, 0x1d, 0x7f, 0xb5, 0x8b, 0x4f, + 0x75, 0xce, 0xb4, 0x62, 0x25, 0x38, 0x2e, 0x24, 0xde, 0x26, 0xbd, 0xf1, + 0x68, 0x75, 0xc2, 0xb3, 0xaa, 0x46, 0xcb, 0x43, 0xb7, 0xb6, 0x39, 0x07, + 0x5f, 0xee, 0x24, 0xc3, 0x9b, 0x5c, 0xeb, 0xb7, 0xd7, 0xc3, 0xf2, 0x82, + 0x1e, 0x0f, 0x5f, 0xf0, 0xc3, 0xcf, 0xd8, 0xe0, 0x0e, 0xbf, 0xc9, 0xc1, + 0xf7, 0xb2, 0x73, 0xae, 0x7d, 0xa7, 0x5f, 0xd2, 0x14, 0x97, 0x70, 0xeb, + 0xf4, 0xe9, 0xc8, 0x91, 0xd4, 0xa2, 0x26, 0xe6, 0x32, 0xe0, 0xb8, 0x95, + 0xdf, 0x60, 0x51, 0x43, 0xaf, 0xff, 0x3a, 0x7a, 0x3d, 0xae, 0xba, 0x77, + 0xf3, 0xaf, 0x84, 0x7f, 0x91, 0xd7, 0xfe, 0xec, 0x70, 0x03, 0x8c, 0xb8, + 0x0e, 0xbd, 0x99, 0x31, 0xd6, 0xce, 0x9e, 0xc0, 0x0f, 0x6f, 0x46, 0xec, + 0x9d, 0x7e, 0xe7, 0xeb, 0x71, 0x3a, 0xbc, 0x78, 0x9f, 0x8e, 0xdf, 0x2e, + 0x32, 0x73, 0xaf, 0xd9, 0xb4, 0x63, 0x73, 0xa9, 0x0f, 0x27, 0x44, 0x37, + 0xd0, 0x3e, 0x69, 0xd4, 0x15, 0x61, 0x59, 0x0d, 0x2e, 0x1f, 0x74, 0x85, + 0xd2, 0x05, 0xe7, 0x4d, 0x7e, 0x6c, 0xd9, 0x21, 0xbf, 0xc0, 0xfb, 0x82, + 0x1e, 0xc1, 0xd5, 0x08, 0xb8, 0x78, 0x42, 0xdf, 0xda, 0xc5, 0xa7, 0x60, + 0xeb, 0xdb, 0xcb, 0x47, 0x56, 0xe7, 0x91, 0xc2, 0xbb, 0xda, 0x03, 0x27, + 0x54, 0x1e, 0x06, 0x11, 0xdf, 0x7e, 0xfc, 0x91, 0xd7, 0xd1, 0xfb, 0x07, + 0x45, 0x5f, 0xa4, 0xab, 0x2c, 0xb2, 0x75, 0x09, 0xe9, 0x7e, 0x4d, 0x7c, + 0xfe, 0x5f, 0x8e, 0xa0, 0xa2, 0xdf, 0x1d, 0x00, 0x45, 0x7f, 0xbe, 0x88, + 0xbb, 0x2f, 0xd3, 0xaa, 0x19, 0x21, 0x98, 0x60, 0x90, 0xf8, 0xe2, 0x72, + 0xe1, 0x98, 0xf0, 0xe4, 0x04, 0xbf, 0xf1, 0x85, 0x77, 0xf0, 0xd7, 0x64, + 0xbe, 0xf3, 0x10, 0xc4, 0xd8, 0x07, 0x5e, 0x90, 0xb9, 0xd6, 0xdd, 0x88, + 0x3c, 0x58, 0x2b, 0xbd, 0xe7, 0x01, 0xd7, 0xf4, 0x72, 0x78, 0xe4, 0xe7, + 0x5f, 0xfa, 0x07, 0xdd, 0xfd, 0xe5, 0x28, 0x3a, 0xfd, 0xf8, 0x30, 0x5a, + 0x75, 0xee, 0x44, 0xc7, 0x5f, 0x20, 0xbc, 0xc7, 0x5f, 0xf8, 0x61, 0x4e, + 0xbf, 0xbe, 0xe0, 0x0e, 0xbe, 0x4d, 0x73, 0x0e, 0xbf, 0xde, 0xcf, 0xb1, + 0x32, 0x68, 0xea, 0x9d, 0x37, 0xc9, 0x0d, 0x84, 0xbb, 0x87, 0xab, 0x27, + 0xe8, 0xe0, 0x90, 0x78, 0xff, 0x69, 0x05, 0xff, 0x42, 0x76, 0x17, 0x3e, + 0x32, 0x75, 0xfd, 0x1d, 0x49, 0xdc, 0x4e, 0xbf, 0xe9, 0xc7, 0x25, 0xdc, + 0x06, 0x8e, 0xbf, 0xf6, 0x0e, 0xf2, 0xd7, 0x3f, 0x80, 0x1d, 0x7e, 0xcf, + 0x6b, 0x14, 0x3a, 0x90, 0xf9, 0x96, 0x7f, 0x7f, 0x0f, 0xbe, 0x77, 0x36, + 0x0e, 0xbc, 0x18, 0xda, 0x75, 0xff, 0xf6, 0x08, 0xc3, 0x21, 0x18, 0xde, + 0x48, 0x27, 0x5f, 0xfe, 0x7f, 0x93, 0x4a, 0x39, 0x3f, 0xc6, 0x73, 0xa7, + 0x54, 0x23, 0xa8, 0x26, 0x3d, 0x1d, 0x14, 0xcb, 0xfe, 0x5f, 0x73, 0xd9, + 0xff, 0x27, 0x3a, 0xff, 0xf9, 0x47, 0xf6, 0x90, 0x66, 0x86, 0xf3, 0x37, + 0x3a, 0xff, 0xa3, 0xd9, 0xc6, 0xbb, 0xb4, 0xd1, 0x7c, 0x5f, 0xb3, 0x91, + 0xbc, 0x8e, 0xbd, 0xd8, 0x5b, 0x4f, 0xab, 0xc8, 0x77, 0xff, 0xe1, 0x6f, + 0xce, 0xc2, 0x71, 0x16, 0x9b, 0x30, 0xb3, 0xaf, 0x3f, 0x27, 0x34, 0x5f, + 0xf5, 0x08, 0xb3, 0xc3, 0x36, 0xab, 0xdf, 0xff, 0xee, 0xbe, 0x92, 0x35, + 0xf3, 0xdd, 0xc5, 0xe3, 0x5f, 0x87, 0x5d, 0x1b, 0x07, 0x5f, 0x6b, 0x4e, + 0xb3, 0xab, 0xa8, 0x99, 0x03, 0x07, 0x86, 0x2f, 0xb7, 0x97, 0x9c, 0xeb, + 0xff, 0xe0, 0xb7, 0xa8, 0x39, 0xb5, 0xe5, 0xa4, 0x09, 0xd6, 0x96, 0x1f, + 0x8b, 0x91, 0x5f, 0xf4, 0x2f, 0xe0, 0x73, 0x01, 0xa3, 0xaf, 0xf9, 0x30, + 0x42, 0xa2, 0x67, 0x0e, 0xa4, 0x3e, 0xfd, 0x83, 0x9b, 0xde, 0xcd, 0xce, + 0xbf, 0x9f, 0x9b, 0xcb, 0x3c, 0x75, 0xff, 0xbd, 0xa4, 0xe7, 0x87, 0xf7, + 0x91, 0xd7, 0xff, 0x97, 0x1b, 0x39, 0xf8, 0xe6, 0x6d, 0x8d, 0xce, 0xbf, + 0xf4, 0x67, 0x33, 0x80, 0x5a, 0x68, 0xeb, 0xcf, 0xbe, 0xc1, 0xd7, 0xf3, + 0xfb, 0x51, 0x93, 0x9d, 0x50, 0x99, 0xfe, 0x16, 0xa1, 0xf0, 0xa6, 0xed, + 0x3c, 0x64, 0x7e, 0xff, 0xbf, 0x85, 0xeb, 0x17, 0x0c, 0x67, 0x5f, 0xfb, + 0x93, 0xe0, 0x73, 0xbd, 0xc6, 0x33, 0xaf, 0xfd, 0x83, 0xed, 0x7d, 0xdb, + 0x19, 0xb9, 0xd5, 0x88, 0x82, 0xd2, 0x0d, 0xff, 0xf4, 0xa3, 0x93, 0xf9, + 0x14, 0xd6, 0x9c, 0x64, 0x75, 0xfd, 0x3e, 0xb1, 0x70, 0xc6, 0x75, 0x99, + 0x99, 0x10, 0x1f, 0x54, 0x2f, 0x27, 0x50, 0xeb, 0xe9, 0x70, 0x32, 0x3a, + 0xf9, 0x7e, 0x49, 0xce, 0xac, 0x3c, 0x44, 0x22, 0xbf, 0xfb, 0x6f, 0x94, + 0x81, 0x96, 0x75, 0x16, 0x75, 0xd3, 0xf8, 0xeb, 0xfd, 0xb7, 0xaf, 0x28, + 0xc1, 0x3a, 0xa0, 0xf2, 0x70, 0x5e, 0xff, 0xfd, 0x2e, 0xc7, 0x1f, 0xdf, + 0xf9, 0x3d, 0xae, 0xa1, 0xd7, 0xf6, 0x33, 0xf7, 0xaf, 0xe3, 0xaf, 0xff, + 0xde, 0xfb, 0x28, 0xda, 0x82, 0x0e, 0x24, 0x2f, 0x0a, 0xbe, 0xef, 0xdd, + 0xfc, 0x75, 0xfb, 0x17, 0x89, 0xb4, 0xeb, 0xd3, 0xcc, 0xc6, 0x75, 0x42, + 0x68, 0xf3, 0xaa, 0xe1, 0x7b, 0x55, 0x90, 0x97, 0xf2, 0x7b, 0xbd, 0x87, + 0x5f, 0xb8, 0x93, 0xba, 0xcd, 0x30, 0x9d, 0xf7, 0xbf, 0x87, 0x34, 0xc2, + 0x77, 0x02, 0x0d, 0x40, 0x9d, 0xfe, 0x17, 0x53, 0xd1, 0xc0, 0x1a, 0x81, + 0x3b, 0xfd, 0xac, 0xea, 0x6b, 0xf9, 0xcd, 0x30, 0x9d, 0xd8, 0x13, 0x4c, + 0x27, 0x73, 0x2c, 0x9e, 0x61, 0x3a, 0xc4, 0xd2, 0xf7, 0x34, 0x42, 0xe5, + 0x91, 0x68, 0xff, 0x6a, 0x0b, 0x24, 0x56, 0xf1, 0x66, 0x13, 0x2a, 0x7c, + 0xf6, 0x4d, 0xd3, 0xf7, 0x66, 0x3c, 0x7a, 0x85, 0xd1, 0xf4, 0x2d, 0xea, + 0xf3, 0x90, 0x0c, 0x23, 0xb5, 0x1b, 0x3f, 0xa5, 0x27, 0x5e, 0x10, 0x2c, + 0xeb, 0xfe, 0x8f, 0xfc, 0x29, 0xb7, 0xea, 0xce, 0xbc, 0x39, 0xac, 0x3d, + 0x7e, 0x0d, 0xde, 0x08, 0x26, 0x3a, 0xa1, 0x9d, 0xed, 0x3c, 0x27, 0x83, + 0x18, 0x5e, 0x1d, 0xa8, 0x74, 0xd8, 0xdb, 0x52, 0x18, 0xf3, 0x42, 0x87, + 0x90, 0x95, 0x59, 0x27, 0x63, 0x5b, 0x15, 0x7d, 0x42, 0xf7, 0xd3, 0xb8, + 0x3b, 0x61, 0x99, 0xf4, 0xc6, 0xfc, 0x1c, 0xe2, 0x28, 0x75, 0xfd, 0xd8, + 0xfa, 0x3b, 0x80, 0xeb, 0xc8, 0x8a, 0x1d, 0x7e, 0xf6, 0x4c, 0x8b, 0x3a, + 0xfd, 0x1b, 0x80, 0x10, 0x75, 0x41, 0xe7, 0x09, 0x3d, 0xfa, 0x36, 0xc0, + 0xf8, 0xeb, 0xf2, 0x6d, 0xf2, 0x4e, 0x75, 0xf9, 0xe5, 0xec, 0x69, 0xd7, + 0xe1, 0xcf, 0xb9, 0x31, 0xd7, 0xff, 0xc2, 0xd4, 0x58, 0x7f, 0x7e, 0x4b, + 0x37, 0xf1, 0xd7, 0xff, 0xb0, 0x1a, 0xea, 0x7c, 0xde, 0x51, 0x93, 0x9d, + 0x7f, 0xdd, 0x75, 0xf5, 0x23, 0x79, 0x1d, 0x7f, 0x7d, 0x19, 0x6c, 0xbc, + 0xe7, 0x54, 0x26, 0x0d, 0x25, 0x04, 0x4c, 0x01, 0xc5, 0x4e, 0xa8, 0x00, + 0x24, 0x0d, 0x27, 0xe1, 0x48, 0x93, 0x7a, 0x32, 0xeb, 0xff, 0x63, 0xf6, + 0x64, 0x1e, 0xe6, 0xe7, 0x5f, 0xc0, 0x9a, 0x51, 0xed, 0x1d, 0x7f, 0xff, + 0xfe, 0xce, 0xe0, 0x83, 0x07, 0xdd, 0xce, 0xc6, 0x4c, 0x9c, 0x9b, 0xa9, + 0xbf, 0x8e, 0xbe, 0x18, 0xc6, 0x4e, 0xbe, 0x8d, 0xf4, 0xe7, 0x54, 0x36, + 0xa7, 0xb3, 0xc2, 0x04, 0x27, 0x19, 0x4f, 0x21, 0x48, 0xc6, 0x18, 0xc9, + 0xf8, 0x5e, 0xf2, 0x9a, 0x45, 0x7f, 0xc7, 0xbf, 0x97, 0x6d, 0x84, 0x0f, + 0xd2, 0x0b, 0xff, 0xe4, 0x1c, 0x5c, 0x7d, 0x1f, 0xe4, 0x38, 0xb3, 0xaf, + 0xf8, 0x29, 0x83, 0xfc, 0xb3, 0x47, 0x5b, 0xf3, 0xaf, 0xfb, 0xa9, 0x2e, + 0xbc, 0x91, 0x67, 0x5f, 0xfb, 0x48, 0x3b, 0xcb, 0xc9, 0xa4, 0x3a, 0xb0, + 0xfd, 0x3c, 0x6f, 0x7e, 0xd2, 0xe0, 0x30, 0x75, 0x49, 0x35, 0x1c, 0x4e, + 0x98, 0xdd, 0x70, 0x85, 0xf1, 0x0d, 0xf0, 0xc7, 0x24, 0x75, 0xff, 0x76, + 0x24, 0x82, 0x3f, 0xee, 0x75, 0xff, 0x46, 0x7b, 0xe8, 0x01, 0x1b, 0x9d, + 0x6e, 0x42, 0x24, 0xb0, 0x81, 0x67, 0x17, 0xf0, 0xc3, 0x79, 0x12, 0x3a, + 0xff, 0xfb, 0xae, 0x9e, 0x97, 0xe3, 0xed, 0x75, 0xe4, 0x77, 0xd3, 0x57, + 0x7f, 0xed, 0x7d, 0xf2, 0x0f, 0xf2, 0xcd, 0x1d, 0x70, 0x74, 0x75, 0x31, + 0xa2, 0xdf, 0xac, 0x22, 0x81, 0x7f, 0xff, 0x66, 0xf9, 0xa7, 0x1e, 0xa4, + 0x7b, 0xbf, 0xba, 0xce, 0xa8, 0x4e, 0x85, 0xe3, 0x16, 0x13, 0x2b, 0xf8, + 0x7f, 0x5a, 0x76, 0x0e, 0xbf, 0xff, 0x38, 0xf9, 0xdf, 0xa3, 0x1e, 0xd3, + 0x39, 0xd3, 0xaf, 0xfd, 0x3b, 0x8e, 0xbd, 0xd4, 0x8d, 0x1d, 0x7f, 0xd0, + 0x0d, 0x07, 0xf7, 0xe4, 0x8e, 0xbd, 0xcd, 0x68, 0xf1, 0x01, 0xdf, 0x35, + 0xdd, 0xa6, 0x88, 0x0d, 0x53, 0x53, 0x7f, 0x72, 0x3b, 0x1f, 0x32, 0x48, + 0xa0, 0xe3, 0x15, 0x3a, 0x64, 0x7f, 0x61, 0xbb, 0x40, 0x4e, 0x7f, 0xd1, + 0xba, 0xde, 0xdb, 0x1d, 0x3a, 0xb1, 0x50, 0x92, 0x47, 0x97, 0xf4, 0xaa, + 0xf7, 0x5d, 0x8c, 0xeb, 0xe8, 0x06, 0xce, 0x1d, 0x40, 0x3c, 0x1f, 0x0f, + 0x5f, 0x0f, 0x81, 0xf9, 0xd7, 0xe5, 0xb1, 0x0c, 0x43, 0x10, 0xc5, 0x1d, + 0x7f, 0xff, 0x4b, 0x34, 0x9c, 0xe2, 0x2f, 0xef, 0xbb, 0x8c, 0xf8, 0xea, + 0xc4, 0x5d, 0xa1, 0x13, 0x9e, 0x5f, 0xfe, 0x67, 0x07, 0xd8, 0x32, 0xcd, + 0x7d, 0x59, 0xd7, 0xff, 0xa5, 0x9b, 0xcb, 0xec, 0x01, 0x56, 0x59, 0x64, + 0xab, 0xf2, 0xd9, 0xc4, 0xda, 0x75, 0xe9, 0x60, 0xcc, 0x7f, 0x5f, 0x54, + 0x6a, 0x11, 0xf2, 0xf0, 0xc4, 0xa8, 0x54, 0x53, 0xd8, 0x6e, 0x8c, 0x64, + 0xd7, 0xfc, 0x83, 0x2d, 0x31, 0x26, 0x29, 0x88, 0x62, 0x8e, 0xbe, 0x9b, + 0x59, 0x31, 0xd7, 0xe0, 0x47, 0xb1, 0x8c, 0xeb, 0xfd, 0x19, 0xc6, 0xbb, + 0xb4, 0xd1, 0x04, 0xdf, 0xf4, 0x7b, 0x38, 0xd7, 0x76, 0x9a, 0x2f, 0x9b, + 0xf3, 0x87, 0xb0, 0xa1, 0xd7, 0x87, 0x34, 0x14, 0x53, 0xb4, 0xf5, 0x68, + 0x74, 0x29, 0x88, 0x6d, 0x86, 0x85, 0xff, 0xd1, 0xd4, 0x53, 0x39, 0x3a, + 0xff, 0xdc, 0xea, 0xc4, 0xe9, 0x12, 0x33, 0x3e, 0x95, 0x5f, 0xef, 0xfb, + 0xb3, 0xd4, 0x6f, 0x4e, 0xbf, 0xf4, 0xef, 0xbe, 0xce, 0x78, 0x5f, 0x69, + 0xd7, 0xff, 0xd9, 0xe8, 0x1f, 0x6b, 0x31, 0x45, 0x1e, 0x47, 0x5f, 0xfb, + 0x03, 0x12, 0x8e, 0xe0, 0x1c, 0xeb, 0xf9, 0xe5, 0xfc, 0x9c, 0x27, 0x5e, + 0x65, 0x96, 0x4a, 0xbf, 0x77, 0x1a, 0xfc, 0x29, 0x52, 0xfe, 0xff, 0xff, + 0x4d, 0xc8, 0xdb, 0xf1, 0x47, 0xf9, 0xf6, 0x6d, 0x7c, 0xcd, 0xfc, 0x75, + 0x79, 0x14, 0xbf, 0x4d, 0xaf, 0xff, 0x27, 0x13, 0xdf, 0xe7, 0x9d, 0x78, + 0x27, 0x54, 0xea, 0x8a, 0x5a, 0x86, 0xb4, 0xe0, 0x1d, 0x8c, 0x3c, 0x7c, + 0x4b, 0x7f, 0xe5, 0xc6, 0xfa, 0x1c, 0x9f, 0xec, 0x8e, 0xbf, 0xff, 0xc9, + 0xd7, 0x1d, 0xe5, 0xf6, 0x50, 0x32, 0x75, 0xe0, 0x4e, 0xbf, 0xfd, 0x99, + 0xd0, 0xf6, 0x35, 0x9d, 0x40, 0x1d, 0x7f, 0x94, 0xf9, 0x34, 0xa3, 0x9a, + 0x3a, 0xa7, 0x4c, 0x7e, 0x48, 0x21, 0x60, 0x44, 0x7b, 0xf9, 0x8f, 0x25, + 0xd8, 0xe1, 0xd7, 0xfb, 0xd0, 0x9d, 0x52, 0x37, 0x3a, 0xff, 0xf6, 0xe3, + 0xf1, 0xbd, 0x40, 0x02, 0x39, 0x23, 0xaa, 0x11, 0x5c, 0x85, 0xff, 0x4c, + 0xef, 0xe4, 0xd6, 0x07, 0xee, 0x1d, 0x7e, 0xd8, 0x41, 0xcd, 0xa7, 0x5f, + 0xee, 0x60, 0x53, 0xf6, 0xf5, 0xa7, 0xae, 0xe5, 0xb7, 0xfb, 0x43, 0x9b, + 0x7a, 0xf2, 0x3a, 0xf6, 0xa5, 0xb4, 0xea, 0x43, 0xd1, 0x63, 0x33, 0xbf, + 0xfd, 0x13, 0xfd, 0xec, 0x6f, 0xec, 0x9c, 0x42, 0x75, 0x22, 0x61, 0x8f, + 0x09, 0xb1, 0x24, 0xbf, 0xd1, 0x83, 0xe6, 0x03, 0x2d, 0x3a, 0xff, 0x77, + 0x36, 0xfc, 0xd4, 0x9a, 0x75, 0xbf, 0xd1, 0xf6, 0xf8, 0xda, 0xff, 0x38, + 0xfc, 0xfb, 0xce, 0xb9, 0xd7, 0xec, 0xe3, 0xee, 0xc9, 0xd7, 0xff, 0xfa, + 0x7c, 0x64, 0x70, 0x3c, 0x4f, 0xe7, 0x0f, 0x60, 0x67, 0x3a, 0xa7, 0x44, + 0x5e, 0x8a, 0x2f, 0x32, 0xcb, 0x25, 0x5f, 0xef, 0xa0, 0x81, 0xcd, 0xfc, + 0x52, 0xa5, 0xfd, 0xff, 0xfc, 0xc1, 0xf8, 0xde, 0xa0, 0x43, 0x8c, 0xfc, + 0xf6, 0xb2, 0x73, 0xab, 0xa8, 0xa9, 0xfd, 0x12, 0x91, 0x31, 0x07, 0x87, + 0x65, 0x4e, 0xcb, 0x42, 0x94, 0x7e, 0x21, 0x35, 0x49, 0x4c, 0x1c, 0x8d, + 0xf5, 0x70, 0xec, 0xec, 0x72, 0x63, 0x0a, 0x0d, 0x14, 0xfa, 0x3d, 0x0b, + 0xff, 0x62, 0x0c, 0xee, 0x3e, 0xc5, 0x9d, 0x7f, 0xfb, 0x8a, 0x7d, 0xf2, + 0x68, 0x73, 0x6a, 0x04, 0xeb, 0xfe, 0x46, 0x43, 0xdc, 0xf6, 0xce, 0x1d, + 0x50, 0x88, 0x8e, 0xa6, 0xdf, 0x0b, 0xef, 0xe3, 0xaf, 0x60, 0x80, 0xeb, + 0xec, 0xf4, 0xd2, 0x3a, 0xff, 0xed, 0x81, 0x8d, 0x8d, 0x38, 0xfd, 0x06, + 0x8e, 0xae, 0x9f, 0x63, 0x91, 0x5f, 0xfb, 0x3d, 0x1c, 0xd7, 0x60, 0x7c, + 0x78, 0x82, 0x2f, 0xec, 0xe3, 0x5d, 0xda, 0x68, 0x82, 0x15, 0x3c, 0x9b, + 0xd0, 0x14, 0x3a, 0xa0, 0xf9, 0x34, 0x95, 0x7b, 0x6c, 0x2c, 0xeb, 0xf9, + 0xfb, 0xce, 0x23, 0x27, 0x5f, 0xcc, 0x61, 0x65, 0xc6, 0x47, 0x56, 0x1f, + 0xd0, 0x8e, 0xfe, 0x5b, 0x7f, 0xfe, 0x80, 0xcd, 0x24, 0x1f, 0x40, 0x26, + 0x14, 0x98, 0xea, 0x9d, 0x54, 0x9a, 0x84, 0x3d, 0x84, 0x30, 0x21, 0x9c, + 0x30, 0x9b, 0xda, 0x5d, 0x7f, 0x77, 0x3d, 0xe4, 0x59, 0xd7, 0xf7, 0xbe, + 0xe7, 0x5f, 0x73, 0xab, 0x73, 0xdb, 0x12, 0xcb, 0xfb, 0x37, 0xf7, 0x39, + 0x07, 0x5f, 0xfd, 0xa1, 0x7f, 0x3a, 0xfe, 0xc4, 0xf8, 0x75, 0x04, 0xfc, + 0x74, 0x5b, 0x50, 0x8b, 0x5f, 0xe1, 0x27, 0x7f, 0x63, 0x7e, 0xed, 0xee, + 0x1d, 0x74, 0x28, 0x75, 0xc8, 0x27, 0x59, 0x93, 0xa8, 0x26, 0x97, 0xe8, + 0xa5, 0xe1, 0xfe, 0x73, 0xaf, 0xdd, 0x79, 0x60, 0x9d, 0x7f, 0x27, 0x87, + 0x3a, 0x87, 0x5d, 0x9d, 0xf8, 0x79, 0xf0, 0x4b, 0x73, 0xb3, 0xf1, 0x1f, + 0x18, 0x77, 0xd2, 0x3f, 0x36, 0x54, 0x93, 0x9a, 0xc2, 0x81, 0x8c, 0xa2, + 0xfe, 0xd2, 0x04, 0x38, 0x27, 0x5f, 0xff, 0xde, 0xee, 0x6b, 0x59, 0x9f, + 0xf2, 0x7c, 0xfc, 0x7c, 0x75, 0xff, 0x76, 0x39, 0xe1, 0x8c, 0xdc, 0xeb, + 0xff, 0xfe, 0x49, 0xe2, 0x5a, 0xe7, 0x13, 0x79, 0xa4, 0xfc, 0x5e, 0x6e, + 0x75, 0xfe, 0x87, 0x9d, 0xf8, 0xff, 0x4e, 0xbd, 0xdc, 0x10, 0xa3, 0x4f, + 0xa6, 0xfe, 0x69, 0xac, 0x4e, 0x69, 0x0a, 0xfd, 0x19, 0x7d, 0xff, 0x9b, + 0xd8, 0xce, 0x4b, 0x5f, 0xac, 0xeb, 0x93, 0x47, 0x5f, 0xf6, 0x4e, 0xfe, + 0x07, 0xd1, 0x91, 0xd7, 0xf3, 0xfb, 0xe4, 0x49, 0x43, 0xaf, 0xef, 0xab, + 0xd3, 0x2f, 0xb9, 0xd5, 0x09, 0x91, 0xe1, 0xaa, 0x87, 0xfc, 0x15, 0x73, + 0xaf, 0x17, 0xde, 0xe6, 0x74, 0xeb, 0xda, 0x45, 0x9d, 0x68, 0xe1, 0xb6, + 0xf0, 0xdd, 0xff, 0xdd, 0x48, 0x1f, 0x8e, 0x32, 0x45, 0x9d, 0x7c, 0x93, + 0x23, 0x27, 0x5f, 0xfc, 0xb7, 0xdf, 0xef, 0x93, 0x91, 0xfb, 0x04, 0xeb, + 0xff, 0xf7, 0xf3, 0x8c, 0x67, 0x55, 0x8f, 0x67, 0x7f, 0xe1, 0xd7, 0xde, + 0xd7, 0xdd, 0x7c, 0x4c, 0x18, 0x28, 0x58, 0x45, 0xf5, 0x2e, 0xfd, 0xa5, + 0xe7, 0xb4, 0x75, 0xff, 0xc8, 0xa6, 0x79, 0x3b, 0x9e, 0x8e, 0x1d, 0x7e, + 0x79, 0x0a, 0x41, 0xd7, 0xf4, 0x38, 0xfb, 0x04, 0xea, 0x92, 0xa3, 0xdc, + 0x8c, 0xb1, 0x16, 0xf8, 0x4e, 0xb4, 0x21, 0x24, 0xbf, 0x9b, 0xd4, 0xd9, + 0x45, 0x0e, 0xbf, 0xfc, 0x80, 0x8d, 0x2e, 0x13, 0x9c, 0x46, 0x4e, 0xbe, + 0x63, 0xee, 0x4e, 0x75, 0xfe, 0x80, 0xe7, 0x93, 0xbf, 0x9d, 0x65, 0xc1, + 0xeb, 0x84, 0x96, 0xff, 0xff, 0xcb, 0x71, 0x04, 0x93, 0x5f, 0xaf, 0xa9, + 0x1e, 0xef, 0xee, 0xb3, 0xaf, 0xff, 0x87, 0xff, 0x49, 0x01, 0xd7, 0x4f, + 0x3a, 0xce, 0xbb, 0xe3, 0x19, 0xd7, 0xff, 0xe7, 0x4f, 0x20, 0x70, 0x39, + 0xe4, 0x5a, 0x70, 0xeb, 0xff, 0xd0, 0xd0, 0xe7, 0xdf, 0x27, 0x23, 0xf6, + 0x09, 0xd7, 0xb8, 0xfa, 0xc4, 0xc2, 0x78, 0x9d, 0xd1, 0xb1, 0x51, 0xb9, + 0x3c, 0xe9, 0xe1, 0x7f, 0x1b, 0xad, 0xd2, 0x83, 0xaf, 0xff, 0x4e, 0x1e, + 0xc7, 0x73, 0x70, 0x67, 0xb4, 0x75, 0x39, 0xf0, 0x7e, 0x2b, 0x41, 0x56, + 0xdf, 0x86, 0x09, 0x09, 0xf7, 0x8f, 0xa4, 0x61, 0x2b, 0x7f, 0x72, 0x27, + 0x41, 0xf1, 0xd7, 0x83, 0xf5, 0x67, 0x5f, 0x86, 0x03, 0x93, 0x1d, 0x7d, + 0xaf, 0xf8, 0xa1, 0xd7, 0xe8, 0xef, 0xa2, 0x47, 0x5f, 0x07, 0xff, 0x6a, + 0x0f, 0xc3, 0x72, 0x60, 0x12, 0x5f, 0x81, 0x8b, 0x8e, 0x9d, 0x7f, 0x7f, + 0x1f, 0x38, 0x32, 0x3a, 0xf3, 0x07, 0xb8, 0x75, 0x05, 0x37, 0x6c, 0x2c, + 0x48, 0x47, 0x0a, 0x47, 0x89, 0xbf, 0x2f, 0xbd, 0xcf, 0xba, 0x3a, 0xe8, + 0x61, 0xe7, 0x5f, 0xf9, 0xc5, 0xb9, 0xc6, 0xbb, 0xb4, 0xd1, 0x08, 0xdd, + 0x29, 0xce, 0xa8, 0x44, 0xc0, 0x07, 0xbf, 0x1b, 0xda, 0x91, 0x7e, 0xc9, + 0xf4, 0x07, 0x3a, 0xff, 0xff, 0xf7, 0x73, 0xfe, 0x29, 0xd4, 0xde, 0x3d, + 0xff, 0x47, 0x37, 0xf7, 0xef, 0xa3, 0xaf, 0xfe, 0xcd, 0xfe, 0xf9, 0x07, + 0xf9, 0x66, 0x8e, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0x60, 0xce, 0x2e, + 0x18, 0x19, 0xe3, 0x81, 0xc1, 0xcf, 0x69, 0x1b, 0x83, 0xf6, 0x7c, 0xe4, + 0x68, 0x5d, 0x4d, 0x62, 0x00, 0x1f, 0x80, 0x5c, 0x30, 0x33, 0xc7, 0x0e, + 0xa8, 0x4d, 0x3b, 0x11, 0xaf, 0xfe, 0xf3, 0x8c, 0xfb, 0xc8, 0x63, 0x34, + 0x75, 0xff, 0xbe, 0xe7, 0x5d, 0x6a, 0xb2, 0xcb, 0x27, 0x5f, 0xff, 0xb1, + 0xbd, 0x81, 0x08, 0xa4, 0xf8, 0x28, 0xa1, 0xd7, 0x3b, 0xce, 0x89, 0x69, + 0x22, 0x5f, 0xff, 0xd3, 0x0c, 0x03, 0x4d, 0xea, 0x72, 0x61, 0x80, 0x68, + 0xeb, 0xff, 0xbd, 0xd4, 0xdb, 0xd7, 0x97, 0x21, 0x43, 0xaf, 0xef, 0xfc, + 0x9f, 0x8a, 0x87, 0x5f, 0xd8, 0xce, 0x0f, 0xe0, 0x3a, 0xfd, 0x2c, 0xf4, + 0x00, 0xeb, 0xa1, 0x73, 0x9e, 0x9e, 0xe5, 0xb7, 0xff, 0xff, 0x01, 0x6f, + 0x2e, 0xba, 0x79, 0x03, 0x81, 0xcf, 0x22, 0xd3, 0x87, 0x56, 0x91, 0x3b, + 0xf9, 0x7d, 0xff, 0xf8, 0x73, 0x59, 0xd7, 0xd8, 0x6f, 0x51, 0x70, 0xd3, + 0xaf, 0xd3, 0xae, 0x03, 0x07, 0x54, 0x97, 0x54, 0xc3, 0x1e, 0x56, 0xe4, + 0x53, 0x43, 0x67, 0x85, 0xdd, 0x5b, 0xd2, 0x37, 0xa3, 0x1f, 0xda, 0x49, + 0xf5, 0x56, 0xff, 0x46, 0xb5, 0x13, 0xe3, 0x27, 0x5f, 0xee, 0xe2, 0xf3, + 0xbf, 0x89, 0xd4, 0x13, 0xe5, 0xf1, 0x9d, 0xf6, 0x71, 0x44, 0x3a, 0xa1, + 0x7b, 0x1f, 0x27, 0x5e, 0x9e, 0x30, 0xaf, 0xc8, 0xaf, 0x32, 0xcb, 0x25, + 0x5f, 0xf6, 0x01, 0xf9, 0x9b, 0x70, 0x25, 0x2a, 0x5f, 0xdc, 0xcb, 0x25, + 0x5e, 0x65, 0x96, 0x4a, 0xbf, 0x9e, 0x70, 0xf6, 0x34, 0x52, 0xa5, 0xfd, + 0x0a, 0x2f, 0x19, 0x48, 0xd9, 0x37, 0xbf, 0x35, 0x03, 0xf5, 0x65, 0x2a, + 0x6c, 0xef, 0x32, 0xcb, 0x25, 0x5e, 0xd4, 0x70, 0xa5, 0x4b, 0xfb, 0xe7, + 0x1d, 0xfc, 0x75, 0x80, 0x88, 0xa5, 0xf2, 0xcb, 0x25, 0x77, 0xf0, 0x46, + 0x24, 0xed, 0x3a, 0xfd, 0xaf, 0xe7, 0xd9, 0x13, 0xaf, 0xc1, 0x4d, 0xb0, + 0x13, 0xaf, 0xb0, 0x71, 0x8c, 0xea, 0xe1, 0xe5, 0x2c, 0xa2, 0x91, 0x13, + 0x1f, 0x5d, 0xaf, 0xfe, 0xeb, 0xc8, 0x5d, 0x49, 0x85, 0x26, 0x3a, 0xff, + 0xec, 0xe4, 0xf1, 0xbe, 0x90, 0x70, 0x07, 0x5f, 0xdd, 0xcd, 0xb9, 0xed, + 0x1d, 0x4d, 0x45, 0xa8, 0x11, 0x3c, 0x87, 0x5c, 0x4f, 0x33, 0xb0, 0xc3, + 0x18, 0x6c, 0xdd, 0x3f, 0x8e, 0xa8, 0x54, 0xa7, 0x92, 0x80, 0x84, 0xea, + 0xf6, 0xec, 0x49, 0x8a, 0x3a, 0xff, 0xf6, 0x31, 0xb8, 0x83, 0x1b, 0x1d, + 0x85, 0x9d, 0x7d, 0xae, 0xa4, 0xc5, 0x5f, 0xf3, 0xef, 0xec, 0x9b, 0xfe, + 0x28, 0x75, 0x9a, 0x87, 0xbd, 0xf9, 0x15, 0xfe, 0x1c, 0xde, 0x5a, 0x45, + 0x0e, 0xbe, 0x77, 0xe2, 0x87, 0x57, 0xc3, 0xd4, 0x9c, 0xce, 0xff, 0xb3, + 0x1a, 0x08, 0xcd, 0xe4, 0x75, 0xf4, 0x3a, 0xf6, 0x95, 0x7f, 0xf7, 0x51, + 0xc0, 0x08, 0x04, 0x77, 0x47, 0x5f, 0xdd, 0xc5, 0xad, 0xe4, 0x75, 0xe6, + 0x59, 0x64, 0xab, 0xfc, 0x3e, 0xea, 0x40, 0xce, 0x52, 0xa5, 0xfd, 0xe8, + 0x06, 0x49, 0x11, 0x98, 0x97, 0x5e, 0x4c, 0x03, 0xec, 0x33, 0xad, 0x8d, + 0x4d, 0x35, 0x71, 0x91, 0x5f, 0xc0, 0x80, 0x47, 0x74, 0x75, 0xfe, 0x8f, + 0xbc, 0xe2, 0x7b, 0x47, 0x54, 0x2b, 0x83, 0x91, 0x46, 0xf0, 0xa7, 0x47, + 0xc9, 0x89, 0x7b, 0x1c, 0x20, 0x0b, 0xc4, 0xb2, 0xfc, 0x0c, 0x4e, 0xa8, + 0x75, 0xff, 0xf6, 0x36, 0x05, 0xfd, 0xa0, 0xfe, 0xfc, 0x91, 0xd5, 0xb9, + 0xfa, 0xac, 0x9e, 0xff, 0xff, 0xe1, 0x75, 0xc7, 0x1a, 0x1e, 0xc6, 0xbf, + 0x74, 0x96, 0xba, 0xf2, 0x3a, 0xf7, 0xfe, 0xd1, 0xd7, 0x9b, 0x1a, 0x3a, + 0xff, 0xef, 0xb2, 0xce, 0xbf, 0x53, 0x9c, 0x83, 0xab, 0x0f, 0x7c, 0x03, + 0x77, 0xe8, 0xf6, 0xb6, 0xe1, 0xd7, 0xef, 0xf8, 0xa7, 0x50, 0xea, 0x84, + 0xe0, 0x5c, 0x8c, 0x0e, 0x02, 0xf9, 0xe2, 0x1d, 0x92, 0x8b, 0xfc, 0x2e, + 0xce, 0x0b, 0xa8, 0x75, 0xff, 0xd9, 0xed, 0x7d, 0xd2, 0xc6, 0x39, 0x07, + 0x5f, 0x26, 0xdc, 0x10, 0x9f, 0xaa, 0xcc, 0x6f, 0xff, 0xf8, 0x3d, 0x46, + 0x73, 0x61, 0x16, 0xfe, 0xd7, 0xf2, 0xcd, 0xfc, 0x75, 0x62, 0x29, 0x1c, + 0xe6, 0xff, 0xa6, 0x6f, 0x51, 0x71, 0xc5, 0x0e, 0xbf, 0x4f, 0xf3, 0xf8, + 0x98, 0xeb, 0x48, 0xeb, 0xdf, 0x46, 0x63, 0xaa, 0x46, 0xb8, 0x02, 0x15, + 0x88, 0xb5, 0x73, 0xad, 0x2d, 0x54, 0x3b, 0xa6, 0xc9, 0xe5, 0x41, 0xca, + 0x52, 0x30, 0x65, 0x51, 0x65, 0x2d, 0xf5, 0x48, 0x5b, 0xb6, 0x18, 0x69, + 0x2a, 0xd6, 0x69, 0x62, 0xbc, 0x95, 0xe4, 0xb9, 0x59, 0x3d, 0x97, 0x96, + 0xf1, 0xe7, 0x02, 0x1e, 0x63, 0x3e, 0x0d, 0xa9, 0xc5, 0x2f, 0x4b, 0xb9, + 0xfe, 0x53, 0x9b, 0x31, 0xb8, 0xfd, 0x86, 0xb5, 0xed, 0xb0, 0x27, 0x5f, + 0xff, 0x60, 0xab, 0xe5, 0x13, 0x7d, 0x77, 0x00, 0xe7, 0x54, 0x8f, 0xb0, + 0x23, 0x97, 0xf9, 0xc5, 0xb9, 0xee, 0xa1, 0xd7, 0xff, 0xfd, 0x9d, 0x7f, + 0xba, 0xc5, 0x1c, 0x41, 0x03, 0x13, 0x76, 0x0e, 0xb4, 0x1d, 0x7f, 0xfe, + 0x8e, 0x76, 0x17, 0xb1, 0xfc, 0x0c, 0x4d, 0xd8, 0x3a, 0xfc, 0x9c, 0x9a, + 0x3b, 0xc4, 0x65, 0x81, 0x94, 0x43, 0xeb, 0x74, 0xda, 0x56, 0x45, 0xf6, + 0x1f, 0x76, 0x61, 0xe7, 0x5f, 0xf9, 0xc4, 0x1f, 0x03, 0xfb, 0xf2, 0x47, + 0x5f, 0x20, 0xcf, 0x07, 0x5e, 0xf7, 0x20, 0xeb, 0xfe, 0x18, 0x5a, 0x0e, + 0x2e, 0x0e, 0xb9, 0x03, 0x87, 0x9f, 0x30, 0xdd, 0x31, 0xa3, 0x73, 0x88, + 0x02, 0xdf, 0x4c, 0x4d, 0x32, 0x4c, 0x87, 0x95, 0xe8, 0x19, 0xce, 0xbe, + 0x4e, 0xa2, 0xce, 0xb7, 0x50, 0xdd, 0xcc, 0x37, 0x7f, 0x43, 0x63, 0x5e, + 0x43, 0xaf, 0xfa, 0x3d, 0xd7, 0x03, 0xef, 0xa3, 0xa8, 0x27, 0xc6, 0x25, + 0x77, 0xfe, 0xe0, 0x3e, 0x75, 0x1b, 0xff, 0x00, 0x75, 0xe9, 0xbf, 0xe1, + 0xd7, 0xfe, 0x74, 0xe6, 0x6e, 0xab, 0x2c, 0xb2, 0x75, 0x42, 0x28, 0x9d, + 0x0b, 0x43, 0xd7, 0xff, 0xc3, 0x12, 0xf9, 0xf7, 0xc8, 0x3f, 0xcb, 0x34, + 0x75, 0x62, 0x79, 0xad, 0x84, 0x57, 0x61, 0x86, 0x02, 0xeb, 0xc0, 0x75, + 0x9d, 0x76, 0x00, 0xeb, 0xc3, 0x21, 0x83, 0x61, 0x83, 0x77, 0xf9, 0x9d, + 0x0e, 0x04, 0x5c, 0xeb, 0xed, 0x35, 0xa8, 0x75, 0x42, 0x20, 0x50, 0xbd, + 0xcc, 0x6f, 0xdc, 0xd0, 0xc4, 0xe7, 0x5f, 0xff, 0x33, 0x8d, 0xd6, 0x7a, + 0x6c, 0x50, 0x70, 0x07, 0x56, 0x1f, 0xba, 0x13, 0xdf, 0xcf, 0xee, 0xb8, + 0x80, 0xeb, 0xff, 0x3f, 0xb2, 0x67, 0x81, 0x89, 0x8e, 0xbf, 0xf7, 0x53, + 0x3e, 0xe4, 0xcc, 0xc6, 0xe7, 0x59, 0x38, 0x8a, 0x8e, 0x95, 0xe8, 0xf2, + 0xe6, 0xb4, 0xd1, 0x82, 0x54, 0x93, 0x20, 0x6c, 0x32, 0x00, 0x6b, 0x76, + 0x09, 0xd7, 0xff, 0xbd, 0x02, 0xdc, 0xf7, 0x53, 0x80, 0x69, 0xd7, 0xe0, + 0xa6, 0xba, 0x87, 0x5f, 0xc8, 0x39, 0xee, 0xa1, 0xd6, 0x8c, 0x3d, 0x0d, + 0x13, 0x50, 0x51, 0xa5, 0x82, 0x9f, 0xc2, 0x62, 0xff, 0x42, 0xf5, 0xa7, + 0x19, 0xce, 0xbf, 0xe0, 0x6a, 0x49, 0xd7, 0x49, 0xce, 0xbe, 0xd6, 0x0f, + 0x8e, 0xbd, 0xb1, 0x1c, 0x3a, 0x90, 0xfd, 0x9c, 0xe3, 0xf2, 0x0b, 0xde, + 0x76, 0x33, 0xaf, 0xf7, 0xba, 0x8a, 0x81, 0xd0, 0xeb, 0xbf, 0x13, 0xae, + 0xfb, 0x87, 0x50, 0x53, 0x88, 0xe9, 0xa8, 0xc2, 0xa3, 0xc5, 0xdf, 0x8f, + 0x6c, 0x99, 0x7d, 0x16, 0xbf, 0x28, 0x04, 0x9b, 0x47, 0x5f, 0x75, 0x1e, + 0x47, 0x5e, 0x0b, 0xc8, 0xea, 0x83, 0x77, 0x84, 0x16, 0xfe, 0x11, 0x06, + 0x06, 0x4b, 0xcf, 0xed, 0x1d, 0x7f, 0xcd, 0xcf, 0x46, 0xd4, 0x10, 0x1d, + 0x7f, 0xff, 0x7f, 0x1e, 0xd6, 0x0f, 0xce, 0x42, 0x04, 0x5e, 0x47, 0x5f, + 0x9b, 0xdd, 0xdd, 0x8c, 0xeb, 0xff, 0x90, 0x23, 0xff, 0xb5, 0x03, 0x1a, + 0x3a, 0x91, 0x1f, 0xe2, 0x71, 0xfa, 0xd6, 0xd2, 0xbb, 0xff, 0x80, 0xfc, + 0xcd, 0xb8, 0x1e, 0x0b, 0x27, 0x5f, 0xff, 0xc3, 0x9a, 0xff, 0xe6, 0x75, + 0xc7, 0x26, 0x94, 0x6e, 0x75, 0xfb, 0x8d, 0x77, 0x69, 0xa2, 0x06, 0xbf, + 0x9e, 0x70, 0x38, 0x84, 0x95, 0x83, 0xef, 0x66, 0xbf, 0xc3, 0xed, 0xd9, + 0x33, 0xbd, 0xd7, 0x97, 0xc4, 0x7f, 0x8c, 0x32, 0x6f, 0xfb, 0xa9, 0x83, + 0x8d, 0x0e, 0x1d, 0x4b, 0x4e, 0xcf, 0xd1, 0xa2, 0x6d, 0x3a, 0xbd, 0xef, + 0xe0, 0xeb, 0xfc, 0x0f, 0x24, 0xeb, 0x86, 0x9d, 0x5b, 0x9e, 0x78, 0x8e, + 0x5f, 0x82, 0xc5, 0xb8, 0x58, 0xb3, 0xaa, 0x15, 0x66, 0x64, 0x7e, 0x29, + 0x08, 0x87, 0x22, 0xbf, 0xd9, 0xbf, 0x83, 0x98, 0xa1, 0xd7, 0xf6, 0x7a, + 0x05, 0x00, 0x75, 0xff, 0x07, 0x82, 0xec, 0xfd, 0xdd, 0x93, 0xaf, 0x3f, + 0x27, 0x34, 0x60, 0xb7, 0xfe, 0x7e, 0x60, 0x83, 0x5e, 0xd6, 0xe7, 0x5f, + 0xff, 0xff, 0xd9, 0xee, 0xb8, 0xa9, 0xf3, 0x5c, 0x77, 0xf6, 0xdc, 0x0f, + 0xcc, 0x5b, 0x8e, 0xf2, 0x3c, 0x41, 0x77, 0xfe, 0x77, 0x51, 0xae, 0x1f, + 0x8a, 0x32, 0x78, 0x82, 0xef, 0xfe, 0xea, 0x75, 0x20, 0x7d, 0xf1, 0x46, + 0x4f, 0x10, 0x5d, 0xfe, 0x84, 0x1f, 0x7c, 0x51, 0x93, 0xc4, 0x17, 0x7f, + 0x2f, 0x03, 0xf1, 0x46, 0x4f, 0x10, 0x5d, 0xff, 0xff, 0x38, 0x8a, 0x2f, + 0xe6, 0x9b, 0xd4, 0xe2, 0x29, 0x3e, 0x32, 0x78, 0x82, 0xee, 0xdf, 0xe0, + 0x53, 0x97, 0x6a, 0x7f, 0x14, 0xdd, 0x08, 0x4f, 0xaa, 0x15, 0x63, 0xf4, + 0xf8, 0x65, 0x18, 0xdf, 0xe4, 0x85, 0x35, 0xed, 0x6e, 0x75, 0xf3, 0xf0, + 0x0e, 0x75, 0xff, 0xdd, 0x4e, 0xa4, 0x0f, 0xbe, 0x28, 0xc9, 0xe2, 0x0b, + 0xbf, 0xe9, 0xb4, 0xd4, 0x9f, 0xe2, 0x8c, 0x9e, 0x20, 0xbb, 0xf7, 0xb5, + 0x0b, 0xf8, 0xd4, 0x4f, 0xfd, 0x53, 0xbf, 0xfd, 0xf1, 0xbd, 0x46, 0xc7, + 0xb5, 0xf1, 0x46, 0x4f, 0x10, 0x5d, 0xff, 0xff, 0xc2, 0x28, 0xbf, 0x9f, + 0xe7, 0xcd, 0x37, 0xa9, 0xc4, 0x52, 0x7c, 0x64, 0xf1, 0x05, 0xd6, 0x26, + 0x4b, 0xba, 0x23, 0xae, 0xdf, 0xf7, 0x53, 0x88, 0xa4, 0xf8, 0xc9, 0xe2, + 0x0b, 0xbf, 0xfe, 0x77, 0xde, 0x5a, 0xea, 0x04, 0x31, 0xc8, 0x2a, 0xff, + 0xd9, 0x29, 0x7f, 0xae, 0x0c, 0xfb, 0x27, 0x88, 0x2e, 0x9a, 0x8e, 0x5e, + 0x23, 0xe9, 0x3a, 0xff, 0xcd, 0x4e, 0x79, 0xc1, 0xaf, 0x8c, 0x9e, 0x20, + 0xbb, 0xfb, 0xa9, 0xde, 0xa0, 0x0d, 0x00, 0x5d, 0xfb, 0x01, 0xf1, 0x46, + 0x4f, 0x10, 0x5d, 0xd9, 0xe6, 0x9f, 0x8f, 0x4e, 0x6b, 0x74, 0x76, 0x6a, + 0x17, 0xf7, 0xf2, 0xf0, 0x3f, 0x14, 0x64, 0xf1, 0x05, 0xdf, 0xf9, 0xbd, + 0x4e, 0x22, 0x93, 0xe3, 0x27, 0x88, 0x2e, 0xec, 0xf8, 0xe8, 0x8b, 0xd1, + 0xf5, 0xfe, 0xfd, 0x16, 0xe3, 0xbc, 0x8f, 0x10, 0x5d, 0xff, 0xb1, 0x36, + 0xe0, 0xe0, 0x5e, 0x47, 0x88, 0x2d, 0x67, 0x81, 0x41, 0x5d, 0xfd, 0xe1, + 0xb8, 0x0d, 0x06, 0x3e, 0x4d, 0x46, 0x2b, 0xe8, 0xc7, 0x3f, 0x85, 0xa3, + 0x2d, 0xf7, 0x02, 0x0d, 0x10, 0x5a, 0xa8, 0x8c, 0xb9, 0xda, 0x75, 0xb4, + 0xd6, 0x4e, 0x18, 0x29, 0x2f, 0x3e, 0x35, 0xba, 0x5b, 0x07, 0x5e, 0x89, + 0x6c, 0x1d, 0x50, 0x6d, 0xc4, 0x66, 0xa7, 0x65, 0x7b, 0x04, 0xcf, 0x72, + 0xa0, 0x52, 0x80, 0x05, 0xea, 0xff, 0xec, 0x90, 0xe7, 0xba, 0x99, 0xbf, + 0x8e, 0xbf, 0xd1, 0xd4, 0x67, 0x79, 0x68, 0xeb, 0xf4, 0x7b, 0x5d, 0x43, + 0xaf, 0xfb, 0x71, 0xc4, 0x5e, 0x08, 0x0e, 0xbf, 0xf6, 0xa6, 0x97, 0xe1, + 0x9a, 0x5f, 0x84, 0xea, 0x9d, 0x1a, 0x92, 0x34, 0xc2, 0x6f, 0x1b, 0x5f, + 0xfd, 0x1b, 0xcb, 0xea, 0xf5, 0xe8, 0xdd, 0x93, 0xaf, 0xd2, 0xd8, 0xd8, + 0xfe, 0x73, 0xad, 0xd4, 0x3f, 0x97, 0x49, 0xbf, 0x72, 0x37, 0x96, 0x8e, + 0xa9, 0x1e, 0x77, 0x09, 0xaf, 0xfe, 0x07, 0xfa, 0xd9, 0xce, 0x01, 0x69, + 0xa3, 0xaf, 0xf0, 0x3f, 0xf0, 0xc7, 0xb4, 0x75, 0x00, 0xfe, 0xf4, 0x91, + 0x50, 0x9e, 0x1e, 0x46, 0x08, 0xf0, 0x9d, 0xbf, 0x9e, 0x51, 0xb5, 0xfa, + 0x75, 0xff, 0xe9, 0xf3, 0x7f, 0x69, 0x06, 0x00, 0xeb, 0x3a, 0xfb, 0x7d, + 0x46, 0xe7, 0x5e, 0x5c, 0x48, 0xeb, 0xf6, 0x07, 0xbf, 0xb2, 0x75, 0x7c, + 0x3e, 0x77, 0x23, 0x11, 0xbb, 0xc1, 0x7f, 0x1d, 0x5c, 0x3c, 0xa7, 0x2f, + 0xbc, 0x9b, 0x38, 0x75, 0xe7, 0xe0, 0x0e, 0xb6, 0xf0, 0x6e, 0x3c, 0x3b, + 0x7c, 0xce, 0x75, 0xce, 0xbe, 0x53, 0x88, 0xc9, 0xd7, 0xe9, 0xdf, 0xb0, + 0xc6, 0x75, 0x31, 0x47, 0x9b, 0x84, 0x75, 0x0a, 0x8e, 0xf0, 0xb5, 0x21, + 0xf4, 0xeb, 0x20, 0x27, 0x16, 0xeb, 0xff, 0xc2, 0x31, 0x3a, 0xfa, 0x9c, + 0xe3, 0xc8, 0xeb, 0xfd, 0x3c, 0xf0, 0x3b, 0xe7, 0x8e, 0xac, 0x3f, 0xc4, + 0x48, 0xbf, 0xfb, 0x83, 0xfe, 0xfe, 0x1c, 0x9d, 0xc4, 0xeb, 0xcf, 0xc9, + 0xce, 0xb8, 0x10, 0x75, 0xf2, 0x42, 0xf0, 0xea, 0x3a, 0xfe, 0x75, 0x3d, + 0x1c, 0x01, 0xd4, 0x13, 0x6e, 0x21, 0x57, 0xff, 0xfa, 0x10, 0x23, 0x1f, + 0xb7, 0xd8, 0xd0, 0xc3, 0x7e, 0xac, 0xeb, 0x81, 0x07, 0x5d, 0x0a, 0x1d, + 0x7f, 0xd9, 0xed, 0x42, 0xfe, 0xe4, 0xc7, 0x5f, 0xed, 0x67, 0x53, 0x5f, + 0xce, 0x75, 0xcc, 0xb2, 0x55, 0xff, 0x0e, 0x6d, 0x79, 0x69, 0x02, 0x75, + 0x35, 0x3f, 0x14, 0x1c, 0xe0, 0xaa, 0xd5, 0xba, 0x40, 0x06, 0x16, 0x08, + 0xa8, 0x8b, 0x68, 0xe9, 0x93, 0x4f, 0xa3, 0x17, 0x99, 0x65, 0x92, 0xac, + 0xb2, 0x95, 0x2f, 0xef, 0xa6, 0x77, 0xe1, 0x4a, 0xa3, 0x77, 0xec, 0x2f, + 0x6a, 0x75, 0x6b, 0x4f, 0x2c, 0x4a, 0xfe, 0xf4, 0x67, 0x72, 0x73, 0xae, + 0xc5, 0x9d, 0x5b, 0x9e, 0x0e, 0x8b, 0x2a, 0x1d, 0x1d, 0x04, 0xa3, 0x5d, + 0xc9, 0x46, 0xca, 0x43, 0xe3, 0x78, 0xf1, 0x12, 0x54, 0x87, 0x21, 0xe4, + 0xb2, 0x9e, 0xcb, 0xe6, 0x7a, 0x59, 0xe0, 0x16, 0x06, 0x56, 0xce, 0xa5, + 0x3a, 0x7a, 0x1a, 0xbf, 0xcb, 0x7a, 0xda, 0xdb, 0x7f, 0x60, 0x00, 0x9c, + 0x91, 0xd7, 0x37, 0x0e, 0xa0, 0x9e, 0x0b, 0x96, 0x5d, 0x8c, 0x9d, 0x74, + 0x78, 0xea, 0x9c, 0xd5, 0xb4, 0x5a, 0xcb, 0x3a, 0xb0, 0xd9, 0x78, 0x8a, + 0xff, 0x49, 0x07, 0x17, 0xff, 0x4e, 0xbf, 0xf6, 0x7b, 0x5d, 0x45, 0xbe, + 0x70, 0xea, 0x83, 0xee, 0x13, 0x2b, 0xef, 0x9e, 0x8d, 0xa7, 0x5f, 0x62, + 0xf3, 0xc7, 0x5e, 0xf3, 0xa8, 0x75, 0xff, 0xff, 0x9e, 0x6f, 0xe5, 0xfb, + 0x7e, 0x75, 0x3d, 0xe8, 0xde, 0x27, 0x8d, 0x1d, 0x7d, 0x36, 0xa3, 0xc7, + 0x53, 0x51, 0x29, 0xfb, 0x95, 0xff, 0xff, 0x31, 0x8b, 0xbe, 0xd8, 0x97, + 0x63, 0x93, 0xc7, 0xb4, 0xf2, 0x3a, 0xf2, 0x6f, 0x31, 0xd7, 0xec, 0xc9, + 0xff, 0xd1, 0xd7, 0xdc, 0x14, 0x01, 0xd7, 0xc8, 0xd7, 0xe1, 0xd7, 0x40, + 0x0e, 0xbe, 0xfe, 0x7f, 0xd5, 0xe9, 0xb5, 0xfa, 0x41, 0x48, 0x89, 0x4e, + 0xaa, 0xdc, 0xc6, 0x03, 0xaf, 0xfb, 0xaf, 0xae, 0xa4, 0xee, 0x27, 0x5f, + 0x3c, 0xff, 0x64, 0x75, 0x30, 0x97, 0x07, 0x61, 0xfa, 0x50, 0x8e, 0xc2, + 0x0d, 0xc9, 0x50, 0x83, 0x90, 0xb0, 0x72, 0x40, 0x34, 0xe8, 0x77, 0xd0, + 0xbc, 0xfc, 0x8b, 0xe8, 0xce, 0xc1, 0xbd, 0xfc, 0x3f, 0x85, 0x6f, 0x23, + 0xaf, 0x24, 0xff, 0x9d, 0x7e, 0x80, 0x26, 0xf8, 0x75, 0xcb, 0xda, 0x75, + 0x83, 0x06, 0xf8, 0x49, 0xaf, 0xff, 0x48, 0x63, 0xe2, 0xc6, 0x14, 0xf2, + 0x4e, 0x75, 0xf9, 0xd7, 0x9d, 0x59, 0xd5, 0xb9, 0xf8, 0xf9, 0x2e, 0xf7, + 0xb9, 0x07, 0x5f, 0xed, 0x7b, 0x6e, 0x0e, 0x04, 0xeb, 0xdd, 0x8d, 0xa7, + 0x5e, 0xd4, 0xa7, 0x3a, 0xb0, 0xdd, 0x7d, 0x1d, 0xa8, 0x4f, 0xae, 0x45, + 0xb8, 0xb6, 0x90, 0x96, 0x59, 0x1b, 0x8d, 0xf9, 0xb6, 0xf3, 0xfc, 0xfa, + 0x75, 0xe9, 0x93, 0xa7, 0x5f, 0xd1, 0xc7, 0x99, 0x3a, 0x75, 0xfb, 0x41, + 0x81, 0x9d, 0xcf, 0x23, 0x43, 0x97, 0x97, 0x0b, 0x3a, 0xb7, 0x3d, 0x95, + 0x9f, 0x5f, 0xff, 0x0c, 0xbe, 0x60, 0x53, 0x5b, 0xfb, 0xf7, 0xd1, 0xd7, + 0xee, 0xfe, 0x31, 0xb4, 0xeb, 0xf8, 0x5f, 0xd2, 0x85, 0x0e, 0xa8, 0x3d, + 0x5f, 0xa5, 0x37, 0xd9, 0x9b, 0xc8, 0xeb, 0xda, 0x49, 0x8e, 0xb2, 0x82, + 0x6f, 0x74, 0x43, 0x7f, 0xf3, 0xce, 0x31, 0xba, 0x04, 0x62, 0x73, 0xab, + 0x87, 0xd4, 0x24, 0xf7, 0xef, 0x9d, 0x8e, 0x48, 0xea, 0xf8, 0xaa, 0x7a, + 0x21, 0x81, 0x84, 0x6d, 0x85, 0x3b, 0xc3, 0x29, 0x92, 0x1b, 0xcb, 0xd4, + 0x1d, 0x7f, 0x4f, 0x34, 0x98, 0x5c, 0x9c, 0xeb, 0xe5, 0xe3, 0xf4, 0xeb, + 0xa5, 0x39, 0xd7, 0xba, 0x14, 0x3a, 0xfd, 0xdc, 0x49, 0x68, 0xeb, 0xff, + 0xee, 0xc7, 0xd5, 0x7c, 0x2e, 0x0d, 0x6a, 0x00, 0x55, 0xfb, 0x8d, 0x77, + 0x69, 0xe2, 0x04, 0xbd, 0xa8, 0xdc, 0xeb, 0x03, 0x0f, 0x3f, 0x73, 0x3b, + 0xde, 0x49, 0xce, 0xbd, 0x3b, 0x89, 0xd5, 0x24, 0xc9, 0x42, 0x4d, 0xc8, + 0x50, 0x2c, 0xa3, 0xc3, 0x97, 0xf0, 0xb5, 0xd4, 0xea, 0x1d, 0x76, 0xc4, + 0x8e, 0xbe, 0xf4, 0xee, 0x27, 0x5e, 0x17, 0x50, 0xeb, 0xca, 0x27, 0x8e, + 0xbd, 0xa7, 0xf1, 0xd4, 0xa1, 0xb7, 0xdc, 0x72, 0xef, 0x9d, 0x3a, 0xfe, + 0x5f, 0x90, 0x3f, 0xc1, 0xd7, 0x97, 0xe6, 0x9d, 0x6f, 0x41, 0xe4, 0xe1, + 0x6d, 0xfd, 0x0b, 0xc5, 0x23, 0x47, 0x54, 0xe9, 0xb1, 0x60, 0xcb, 0x48, + 0x7a, 0xa4, 0x02, 0x31, 0x61, 0xf1, 0x35, 0xdc, 0xfc, 0xeb, 0xfc, 0x2e, + 0xce, 0xb5, 0x00, 0x3a, 0xf6, 0xcb, 0xa8, 0x75, 0xff, 0x42, 0xe5, 0x93, + 0xe7, 0xec, 0x13, 0xaf, 0x9f, 0xcc, 0x19, 0xce, 0xac, 0x44, 0x12, 0x0f, + 0xb9, 0xed, 0xe6, 0x59, 0x64, 0xf5, 0x7d, 0x5e, 0x71, 0x09, 0x6a, 0xfa, + 0xaa, 0x6b, 0x2f, 0xa5, 0xfc, 0x28, 0x75, 0x80, 0x75, 0x61, 0xb3, 0x72, + 0x3a, 0x84, 0xeb, 0xc2, 0x2f, 0xc8, 0x5a, 0x01, 0x67, 0xcd, 0x97, 0xcb, + 0xe7, 0xf3, 0x9d, 0x7f, 0xfc, 0x28, 0xa2, 0xba, 0xf7, 0x7f, 0x79, 0x4a, + 0x0e, 0xa8, 0x3f, 0x5c, 0x24, 0xa9, 0xd1, 0xc8, 0xa4, 0x31, 0x2f, 0xb0, + 0x2f, 0x23, 0xaf, 0xce, 0x22, 0x8b, 0x3a, 0xf0, 0x5e, 0x47, 0x5f, 0xe4, + 0xe6, 0x22, 0xe1, 0x8c, 0xea, 0xc3, 0xce, 0xe8, 0xdd, 0xf9, 0x16, 0xe3, + 0x87, 0x57, 0xc5, 0xf9, 0xd6, 0x20, 0x6e, 0x0d, 0x64, 0x40, 0x11, 0x7c, + 0x8d, 0x01, 0x45, 0x04, 0x8e, 0x39, 0xe5, 0x7b, 0x80, 0xa8, 0x48, 0x3f, + 0x72, 0xd9, 0x21, 0xbf, 0xb3, 0xb8, 0xdf, 0xf0, 0xeb, 0xf2, 0x7a, 0x3d, + 0xa2, 0xaf, 0x9b, 0x1e, 0xd1, 0x57, 0x32, 0xc9, 0x55, 0x23, 0xdf, 0xc2, + 0x66, 0x48, 0x6e, 0xc6, 0x4a, 0x54, 0xd7, 0xdf, 0x4c, 0x2e, 0xc9, 0xd7, + 0xff, 0xde, 0x86, 0xe6, 0x0f, 0xba, 0x90, 0x33, 0x9d, 0x47, 0x56, 0x1e, + 0xb6, 0x93, 0x2a, 0x64, 0xde, 0x81, 0x0b, 0xa1, 0x27, 0x65, 0xe2, 0xff, + 0xde, 0xd6, 0x37, 0xae, 0x3e, 0xd1, 0xd7, 0xe8, 0xda, 0x82, 0x03, 0xbe, + 0x1b, 0xdb, 0xf4, 0xbb, 0xfc, 0x70, 0xeb, 0xff, 0x9d, 0x7c, 0x8d, 0xa9, + 0xb4, 0x7f, 0xd1, 0xd5, 0xb9, 0xf7, 0xf4, 0xa2, 0xfd, 0x9f, 0xae, 0x34, + 0x75, 0x1d, 0x76, 0x4d, 0xc3, 0x63, 0xa2, 0x7b, 0xfe, 0x4f, 0xd8, 0x3d, + 0x8f, 0xa3, 0x39, 0xd7, 0xfd, 0x13, 0xc6, 0xfe, 0x1c, 0x9c, 0xea, 0xc4, + 0x52, 0xb4, 0xb5, 0x0f, 0xef, 0xce, 0xb1, 0x8d, 0xce, 0xa9, 0x93, 0x4d, + 0xe4, 0x3e, 0x7a, 0x5d, 0x7d, 0x9d, 0xc9, 0xce, 0xbd, 0x27, 0xe1, 0xd7, + 0xe9, 0x67, 0xb0, 0x25, 0x5f, 0x40, 0x8c, 0x1d, 0x53, 0x1e, 0xff, 0x86, + 0xfe, 0x93, 0x5f, 0x03, 0x4b, 0xe1, 0xd4, 0xa2, 0x35, 0x12, 0x10, 0x1e, + 0x32, 0xbf, 0xe1, 0xce, 0xe7, 0xce, 0xe4, 0xe7, 0x5f, 0xff, 0xfc, 0x08, + 0x16, 0xbf, 0x9f, 0x70, 0x6f, 0xe4, 0x5e, 0xbb, 0x1f, 0x44, 0xeb, 0xfb, + 0xf6, 0x0a, 0x73, 0x98, 0x75, 0xf7, 0x94, 0xce, 0x9d, 0x7f, 0xe1, 0xcf, + 0x7b, 0xf9, 0xfd, 0x8d, 0x3a, 0xda, 0x3a, 0xe4, 0x01, 0xd7, 0x75, 0x0e, + 0xbb, 0xfd, 0x7c, 0x35, 0x53, 0x0a, 0xd3, 0x9f, 0x58, 0x0e, 0xae, 0x04, + 0x1d, 0x70, 0x20, 0xeb, 0xf7, 0xf2, 0xc1, 0x55, 0x0d, 0x50, 0x05, 0x6a, + 0x13, 0x55, 0x50, 0x88, 0x10, 0xaa, 0x14, 0xbb, 0xff, 0xec, 0x17, 0xdf, + 0x4a, 0x28, 0xff, 0x1a, 0xb0, 0x1d, 0x7f, 0xf7, 0xbb, 0x8b, 0xfb, 0x00, + 0xcd, 0xfc, 0x75, 0xfe, 0xdd, 0xa9, 0xcf, 0xb0, 0x13, 0xaf, 0x80, 0xb7, + 0x97, 0xc4, 0x67, 0x69, 0x4f, 0xc8, 0xd7, 0x7f, 0xe3, 0xaf, 0xe0, 0x2f, + 0xee, 0xbe, 0xce, 0x75, 0xfd, 0xa4, 0x11, 0x8d, 0xce, 0xbb, 0x37, 0x3a, + 0xb7, 0x3f, 0x4f, 0x19, 0xec, 0x95, 0xdf, 0x03, 0x89, 0xc3, 0xaa, 0x13, + 0x28, 0x92, 0x4b, 0xc2, 0x2d, 0x93, 0x3b, 0xdf, 0xef, 0xe3, 0xac, 0xe7, + 0x56, 0x8d, 0x6f, 0x87, 0xae, 0xc6, 0x4e, 0xbf, 0xe8, 0xdf, 0x01, 0x1b, + 0x72, 0x73, 0xaf, 0xe1, 0xcf, 0x69, 0xc0, 0x75, 0x70, 0xfe, 0xc0, 0x2d, + 0xa3, 0xab, 0xff, 0x4d, 0x13, 0xeb, 0x98, 0xd8, 0x9c, 0xeb, 0xfb, 0x17, + 0x81, 0x46, 0x4e, 0xb9, 0x70, 0x75, 0x2c, 0xf0, 0x5c, 0xb2, 0xfe, 0x1c, + 0x9b, 0xa9, 0xe3, 0xaf, 0xb3, 0x3b, 0xa3, 0xab, 0x11, 0xdc, 0xf0, 0x81, + 0xf1, 0x0e, 0xc1, 0x65, 0xe6, 0x59, 0x64, 0xab, 0xf6, 0x28, 0x3f, 0xe8, + 0xa5, 0x4b, 0xfb, 0xe5, 0x59, 0x65, 0x93, 0xae, 0xc0, 0x1d, 0x58, 0x6e, + 0xfc, 0x4d, 0x50, 0x89, 0x3f, 0x39, 0xdf, 0x27, 0x01, 0xa3, 0xaf, 0xfb, + 0x5c, 0x8f, 0xfc, 0x29, 0xb4, 0xeb, 0xff, 0x0e, 0x69, 0xbd, 0x46, 0xc0, + 0x9d, 0x7f, 0xff, 0x94, 0x65, 0xf8, 0xa2, 0xba, 0xc9, 0x0f, 0xef, 0xac, + 0x13, 0xaa, 0x11, 0xb1, 0x87, 0x48, 0x77, 0x7c, 0xcb, 0x8c, 0x8e, 0xbf, + 0xef, 0x46, 0xe0, 0x7e, 0xf5, 0x0e, 0xb7, 0x4e, 0xac, 0x3c, 0x86, 0x9c, + 0x5f, 0x87, 0x3d, 0x1c, 0x3a, 0xf3, 0x2c, 0xb2, 0x55, 0xf9, 0xd4, 0xea, + 0x78, 0xa5, 0x4b, 0xfa, 0x83, 0xfb, 0x44, 0x4b, 0xde, 0x46, 0x4e, 0xbd, + 0xa7, 0xe1, 0xd5, 0xb9, 0xb7, 0xf0, 0xe5, 0xee, 0xc0, 0x4e, 0xa4, 0x37, + 0xae, 0x45, 0x7e, 0xc0, 0x66, 0x4c, 0x75, 0xb5, 0xf1, 0x37, 0x5e, 0x42, + 0x73, 0xb0, 0x94, 0x11, 0xfb, 0xbf, 0x90, 0x55, 0x16, 0xe4, 0x7b, 0xd7, + 0xe6, 0x0f, 0x62, 0x7f, 0xce, 0xa9, 0x95, 0xdb, 0xf6, 0x1f, 0x23, 0x29, + 0x6b, 0xf3, 0x7b, 0xd1, 0xb6, 0x0e, 0xa4, 0x3e, 0x81, 0x4c, 0xbc, 0x31, + 0xb4, 0xeb, 0x98, 0x28, 0x75, 0xc9, 0xd3, 0xac, 0xf3, 0x9a, 0xee, 0x0c, + 0xdf, 0x7b, 0x5f, 0xb1, 0x9d, 0x7f, 0xa0, 0x64, 0x29, 0x1b, 0x9d, 0x50, + 0xd8, 0x32, 0xca, 0x10, 0x39, 0x1f, 0xaa, 0x91, 0x85, 0xb4, 0xd7, 0x73, + 0x94, 0x73, 0xe4, 0x70, 0xdd, 0x94, 0x70, 0xed, 0xe0, 0x84, 0xe0, 0xc6, + 0x3b, 0xa8, 0x7a, 0xfa, 0x71, 0x07, 0x69, 0x06, 0xca, 0x57, 0xd2, 0x7d, + 0x82, 0x6b, 0xf2, 0x4d, 0x24, 0x13, 0xae, 0x62, 0x90, 0xeb, 0xfe, 0x9b, + 0xdb, 0x1a, 0x89, 0xbf, 0xe1, 0xd7, 0xf8, 0x30, 0x2b, 0x80, 0xc1, 0xd5, + 0x07, 0xde, 0xe7, 0xf7, 0xff, 0x62, 0x76, 0x03, 0xdf, 0xe3, 0x7d, 0x1d, + 0x78, 0x2a, 0x00, 0xeb, 0xf2, 0xf9, 0xc7, 0xf1, 0xd5, 0xf0, 0xf1, 0x20, + 0x76, 0xff, 0xf3, 0x66, 0x76, 0xf6, 0x25, 0xe1, 0xc5, 0x9d, 0x7f, 0xfc, + 0x8b, 0xde, 0x5a, 0xf9, 0x82, 0x38, 0x80, 0x3a, 0xf2, 0x77, 0xf3, 0xab, + 0xe2, 0xa2, 0xe6, 0x20, 0x9a, 0x50, 0x89, 0xe1, 0x07, 0x61, 0x10, 0xe4, + 0x7e, 0x49, 0xda, 0x9f, 0x65, 0x58, 0xa8, 0xe7, 0xf0, 0x18, 0x10, 0xc9, + 0x62, 0xe3, 0x55, 0x61, 0x36, 0xb0, 0xf8, 0xc6, 0x98, 0x9c, 0x62, 0x8c, + 0x48, 0xe9, 0x86, 0x56, 0x8a, 0x74, 0x74, 0xf3, 0xac, 0x92, 0xa5, 0x56, + 0x06, 0x96, 0x7d, 0x96, 0xee, 0xa1, 0x49, 0x6b, 0xad, 0xa6, 0x04, 0x6f, + 0x48, 0xbc, 0x4a, 0x53, 0xe3, 0x1c, 0x6f, 0x73, 0x53, 0x84, 0x79, 0x4f, + 0x17, 0x5d, 0x25, 0xf7, 0xb5, 0xcb, 0xdb, 0xda, 0x00, 0xf0, 0x52, 0xd1, + 0xd8, 0x30, 0xf1, 0x1a, 0xdb, 0x9b, 0x56, 0xf2, 0x63, 0xd6, 0x9c, 0x27, + 0xf9, 0xd8, 0xbd, 0xb2, 0xb0, 0xd9, 0x96, 0x09, 0xb3, 0x48, 0x05, 0xfb, + 0x59, 0x57, 0x6c, 0x4b, 0x63, 0xa5, 0x63, 0xa3, 0x5d, 0x96, 0x74, 0x0a, + 0x97, 0xe5, 0x40, 0xbc, 0xf1, 0xd7, 0xf9, 0x5c, 0xe3, 0x5d, 0xda, 0x68, + 0xb8, 0xef, 0xf2, 0xb9, 0xc6, 0xbb, 0xb4, 0xd1, 0x75, 0xdf, 0xfc, 0xab, + 0xc9, 0x5c, 0xe3, 0x5d, 0xda, 0x68, 0x94, 0x6a, 0x23, 0xa8, 0xa5, 0x94, + 0x33, 0x02, 0x52, 0xa4, 0x23, 0xda, 0x50, 0x91, 0xd1, 0x31, 0xb8, 0xbe, + 0x74, 0x76, 0x80, 0x3b, 0xd1, 0x47, 0x8f, 0xf6, 0x0f, 0xef, 0xff, 0x2a, + 0xb7, 0x92, 0xb9, 0xc6, 0xbb, 0xb4, 0xd1, 0x2d, 0x5f, 0xf3, 0x0e, 0xea, + 0x31, 0xbc, 0x6f, 0xb0, 0x75, 0xfb, 0x8d, 0x77, 0x69, 0xa2, 0x37, 0xbf, + 0xf3, 0xc9, 0x5c, 0xe3, 0x5d, 0xda, 0x68, 0x97, 0xef, 0xe8, 0xf7, 0xde, + 0xbf, 0x8e, 0xbf, 0xd9, 0xf7, 0x8a, 0x77, 0xfd, 0x1d, 0x7d, 0xff, 0x53, + 0x87, 0x5e, 0x9b, 0x5c, 0x3a, 0xca, 0xb1, 0x24, 0xd9, 0x71, 0x11, 0x66, + 0x7d, 0x4a, 0x12, 0xed, 0x93, 0x7f, 0xa4, 0x57, 0xff, 0xb7, 0x97, 0x92, + 0x65, 0x42, 0x9b, 0x60, 0x27, 0x5f, 0xe5, 0x73, 0x8d, 0x77, 0x69, 0xa2, + 0xab, 0xb9, 0x36, 0x0e, 0xbe, 0x45, 0xbe, 0xd3, 0xa9, 0x43, 0x75, 0xe1, + 0x8b, 0xc3, 0xb0, 0xc9, 0xd7, 0xf3, 0xf6, 0x61, 0x80, 0x9d, 0x7f, 0xf7, + 0xbb, 0x1a, 0x17, 0xfd, 0x82, 0x9c, 0x3a, 0xf4, 0x4b, 0x0e, 0xa0, 0xa2, + 0x37, 0x72, 0xc9, 0x91, 0xef, 0xf9, 0x4c, 0x1c, 0xdf, 0xce, 0xb3, 0xae, + 0x0a, 0x1d, 0x7f, 0x67, 0x1a, 0xee, 0xd3, 0x44, 0x81, 0x5f, 0x0f, 0x35, + 0x51, 0x5b, 0xf6, 0x9c, 0x5f, 0x73, 0xae, 0xfe, 0x0e, 0xa9, 0x1f, 0x0e, + 0xe4, 0xbc, 0x26, 0xbf, 0xd2, 0x8e, 0x4f, 0x1c, 0x9c, 0xeb, 0xfd, 0xc9, + 0xd7, 0x03, 0x2d, 0x1d, 0x50, 0x7c, 0xf8, 0x69, 0x7d, 0x93, 0xb8, 0x4e, + 0xbf, 0xfd, 0x93, 0x75, 0xd7, 0xee, 0xc7, 0xbf, 0x59, 0xd5, 0x3a, 0xb0, + 0x90, 0x91, 0x64, 0x2b, 0x14, 0x32, 0x78, 0x73, 0x0c, 0x25, 0xfc, 0x41, + 0xf4, 0x86, 0xff, 0xe1, 0xc9, 0xd5, 0xd9, 0x81, 0x1c, 0xf1, 0xd4, 0xaa, + 0x32, 0x39, 0x08, 0x3b, 0xfc, 0xae, 0x71, 0xae, 0xed, 0x34, 0x59, 0x17, + 0xf9, 0x5c, 0xe3, 0x5d, 0xda, 0x68, 0xb5, 0xef, 0xff, 0x67, 0xd8, 0x9d, + 0x5c, 0x9b, 0xc1, 0x81, 0x3a, 0xff, 0x2b, 0x9c, 0x6b, 0xbb, 0x4d, 0x17, + 0x25, 0xfb, 0x8d, 0x77, 0x69, 0xa2, 0xec, 0xbf, 0xf3, 0xc9, 0x5c, 0xe3, + 0x5d, 0xda, 0x68, 0xa3, 0xac, 0xae, 0x1f, 0xea, 0xcc, 0xef, 0x86, 0x24, + 0xb3, 0xaf, 0xfc, 0xc2, 0x60, 0x2e, 0x39, 0x2c, 0x4d, 0xa7, 0x5a, 0x47, + 0x5f, 0xb8, 0xd7, 0x76, 0x9a, 0x29, 0x5b, 0xfe, 0x6f, 0x52, 0x6e, 0xc4, + 0xf8, 0x75, 0xff, 0xee, 0xc4, 0xf1, 0xd4, 0xda, 0xe1, 0xea, 0x1c, 0xa9, + 0xb9, 0xba, 0x4a, 0xe2, 0x31, 0xe6, 0x6c, 0xad, 0xd3, 0x07, 0x78, 0x6b, + 0xdf, 0xf9, 0xd3, 0xd2, 0xfc, 0x2e, 0x20, 0x3a, 0xca, 0x85, 0x3d, 0x4d, + 0xc8, 0x17, 0x1a, 0x77, 0x4a, 0x6a, 0x76, 0x56, 0x04, 0xa3, 0xbc, 0xc7, + 0x5d, 0xd3, 0x92, 0x71, 0x29, 0x65, 0x20, 0x3f, 0x13, 0xfd, 0x26, 0x7a, + 0x17, 0x9b, 0x63, 0xfc, 0xbf, 0xe9, 0x2b, 0x9c, 0x6b, 0xbb, 0x4d, 0x11, + 0xc5, 0xff, 0x22, 0xb9, 0xc6, 0xbb, 0xb4, 0xd1, 0x5a, 0xd9, 0x57, 0x44, + 0x4f, 0x91, 0x6f, 0xff, 0x2a, 0xb7, 0x92, 0xb9, 0xc6, 0xbb, 0xb4, 0xd1, + 0x2d, 0xde, 0xff, 0x80, 0x3a, 0xec, 0xdc, 0xeb, 0xfc, 0x1c, 0x5a, 0xe1, + 0x34, 0x75, 0xed, 0xbf, 0xc8, 0xea, 0x6a, 0x20, 0xf7, 0x1d, 0x41, 0x6d, + 0xa6, 0x37, 0xba, 0x19, 0x1d, 0x7f, 0xd9, 0xb8, 0xe0, 0x00, 0xf2, 0x3a, + 0xe5, 0xb4, 0xea, 0x83, 0xcd, 0x91, 0xbd, 0xf0, 0xc6, 0xf2, 0x3a, 0xff, + 0xfc, 0xfb, 0x80, 0x3d, 0x79, 0x66, 0x87, 0xf7, 0xfa, 0x75, 0x34, 0xfe, + 0x3a, 0x43, 0x65, 0x0e, 0xbf, 0x93, 0x82, 0x9e, 0xd1, 0xd7, 0xee, 0x38, + 0xe4, 0x1d, 0x46, 0x88, 0x6d, 0x0f, 0x83, 0xa2, 0x2e, 0x57, 0x74, 0x09, + 0xd7, 0xf2, 0x08, 0x71, 0x02, 0x75, 0x41, 0xbe, 0x90, 0xa5, 0xf6, 0x4d, + 0x2c, 0x3a, 0xff, 0xcf, 0x25, 0x73, 0x8d, 0x77, 0x69, 0xa2, 0x60, 0xbc, + 0xca, 0x00, 0xeb, 0xed, 0x38, 0x80, 0xea, 0x98, 0xde, 0x00, 0x72, 0xff, + 0x7f, 0xbf, 0x12, 0x17, 0x87, 0x5f, 0xba, 0x90, 0x33, 0x9d, 0x7f, 0xd1, + 0x3f, 0x86, 0x3f, 0xf6, 0x8e, 0xb7, 0xba, 0x89, 0x2d, 0x19, 0xec, 0x93, + 0x5f, 0x6e, 0xd4, 0x50, 0xea, 0xc3, 0xdc, 0xf1, 0xcd, 0xfe, 0xe2, 0x7b, + 0x17, 0x1d, 0x3a, 0xff, 0x69, 0x3a, 0x8b, 0xc5, 0x0e, 0xbf, 0xfc, 0xf3, + 0xf5, 0x20, 0x72, 0x64, 0xe2, 0x1d, 0x58, 0x8a, 0xaf, 0x18, 0xb2, 0x65, + 0x73, 0x70, 0xeb, 0xbf, 0x01, 0x54, 0x86, 0xb3, 0x82, 0xb7, 0xfb, 0x02, + 0x39, 0xee, 0xe1, 0xd7, 0x30, 0x9a, 0x78, 0xc2, 0xaf, 0xe9, 0xfe, 0xec, + 0xb8, 0x80, 0xeb, 0xfb, 0x3d, 0xe8, 0xe6, 0x8e, 0xbf, 0x9c, 0x41, 0x38, + 0x3c, 0x75, 0x42, 0x22, 0xc4, 0xcb, 0x64, 0xb2, 0xca, 0xc2, 0xf3, 0x94, + 0xe7, 0xe1, 0x69, 0xc8, 0x4c, 0xb6, 0x10, 0x5b, 0xbf, 0x70, 0x81, 0x64, + 0x2f, 0x08, 0x61, 0x8c, 0x43, 0x50, 0xcb, 0xf2, 0xe6, 0xd2, 0x06, 0x4c, + 0x3e, 0xc2, 0xca, 0xf2, 0xff, 0xe1, 0x57, 0xfe, 0x79, 0x2b, 0x9c, 0x6b, + 0xbb, 0x4d, 0x13, 0x1d, 0xf4, 0x72, 0x36, 0x0e, 0xb2, 0xa8, 0x88, 0xa5, + 0x8e, 0xf5, 0x2a, 0xfa, 0x27, 0x8e, 0x1d, 0x7e, 0xc8, 0x99, 0x16, 0x75, + 0x21, 0xe3, 0xf0, 0x86, 0xfe, 0x0a, 0xe3, 0x3d, 0xa3, 0xaf, 0xf7, 0x63, + 0x93, 0xfd, 0xfc, 0x07, 0x5c, 0xfa, 0x3a, 0xfb, 0xe7, 0xb3, 0xa7, 0x5a, + 0x3a, 0x6e, 0x34, 0x2b, 0x7a, 0x06, 0x73, 0xaf, 0xff, 0xff, 0xa5, 0xae, + 0xe7, 0xec, 0xeb, 0xb8, 0xdc, 0xd7, 0xcc, 0xde, 0x5a, 0x41, 0x43, 0xaf, + 0x3b, 0xb4, 0xd1, 0x58, 0xdf, 0x3f, 0xd8, 0x50, 0xea, 0x69, 0xe5, 0x70, + 0x9e, 0xff, 0xdb, 0x39, 0xe1, 0xcf, 0xe0, 0x7c, 0x75, 0x28, 0x9b, 0x63, + 0x49, 0xb7, 0x1b, 0xe4, 0x32, 0xbc, 0x45, 0x7f, 0xf0, 0xf9, 0x4f, 0xe0, + 0x71, 0xb1, 0xc3, 0xaf, 0xf7, 0x27, 0xf6, 0x9f, 0x76, 0x9d, 0x50, 0x7f, + 0x0e, 0x87, 0x7f, 0x46, 0xc7, 0xb3, 0x79, 0x8e, 0xbf, 0xbf, 0xd9, 0x6f, + 0x51, 0x82, 0x75, 0xfd, 0x9a, 0xde, 0x51, 0xd3, 0xae, 0x8d, 0xa7, 0x58, + 0x3d, 0x3c, 0x41, 0x2d, 0xbf, 0xe8, 0xde, 0x53, 0x49, 0xf9, 0x39, 0xd5, + 0x08, 0xdb, 0xc7, 0x94, 0x27, 0xbd, 0x12, 0xf1, 0xd7, 0xfe, 0xc0, 0xf1, + 0x3f, 0x9c, 0x1a, 0x91, 0xd7, 0xcb, 0x7d, 0xfc, 0x75, 0xff, 0xd3, 0xc7, + 0xbe, 0x7d, 0x6f, 0xdd, 0x8f, 0xba, 0x3a, 0xff, 0xb9, 0x1a, 0x7e, 0x0c, + 0x48, 0xea, 0xe2, 0x21, 0xf6, 0xa8, 0xde, 0x93, 0xce, 0x75, 0xef, 0x93, + 0xac, 0xeb, 0x83, 0xe3, 0xa9, 0x84, 0x98, 0xfe, 0x42, 0xa7, 0x72, 0x54, + 0x1c, 0x11, 0xfb, 0xff, 0x0b, 0x87, 0xb1, 0xb7, 0xae, 0x27, 0x5f, 0xff, + 0xfb, 0xf9, 0xf1, 0xbf, 0x07, 0xfd, 0x8f, 0x99, 0xbc, 0xb3, 0xf1, 0x06, + 0x8e, 0xbf, 0xfd, 0x3e, 0x6f, 0xed, 0x20, 0xc0, 0x1d, 0x67, 0x5f, 0xed, + 0xc7, 0x03, 0xd7, 0x64, 0xea, 0xc3, 0xfc, 0x74, 0x9a, 0x0a, 0x6a, 0x02, + 0x7b, 0xa8, 0x79, 0xdf, 0xd3, 0xcd, 0x26, 0x17, 0x27, 0x3a, 0xf8, 0x47, + 0x3c, 0x75, 0xf9, 0x18, 0xf9, 0xc4, 0x3a, 0x98, 0x83, 0xfd, 0x83, 0x5e, + 0x8f, 0xdf, 0xd3, 0xfd, 0xd9, 0x71, 0x01, 0xd7, 0xcc, 0x71, 0xa1, 0x3a, + 0xff, 0xdd, 0x75, 0xfb, 0xb1, 0xef, 0xd6, 0x75, 0x61, 0xf1, 0x4c, 0x47, + 0x7f, 0xf6, 0x62, 0x8b, 0x84, 0xe7, 0x11, 0x93, 0xaf, 0xf9, 0x24, 0x9d, + 0xfd, 0x6b, 0x43, 0xaa, 0x13, 0x31, 0xc8, 0x4a, 0x70, 0x8b, 0xc8, 0x77, + 0xba, 0x8a, 0xc3, 0x26, 0xfa, 0x72, 0x19, 0x16, 0x64, 0x7b, 0x6d, 0x86, + 0x57, 0x08, 0x3b, 0x18, 0x63, 0x96, 0x88, 0xde, 0xa3, 0x5f, 0xf4, 0x74, + 0x5b, 0x30, 0xb2, 0xfb, 0x1b, 0x25, 0xe6, 0x1d, 0xb2, 0xc4, 0x1d, 0x74, + 0x84, 0xeb, 0xfb, 0x9c, 0x80, 0xe2, 0xce, 0xbe, 0x9f, 0x91, 0x39, 0xd7, + 0x7d, 0x01, 0xd7, 0xba, 0x8b, 0x3a, 0xd3, 0x1d, 0x4e, 0x6b, 0x3f, 0x1b, + 0xbf, 0x38, 0xcf, 0xfe, 0x8e, 0xbf, 0xe8, 0x0f, 0x70, 0x3c, 0x76, 0x9d, + 0x48, 0x98, 0x9b, 0x96, 0x00, 0x8c, 0x51, 0x34, 0x43, 0xe2, 0x8b, 0x74, + 0xeb, 0xda, 0xfb, 0xa3, 0xaf, 0xb7, 0x9e, 0x14, 0x3a, 0xa7, 0x3d, 0x20, + 0x88, 0x7e, 0x3d, 0x77, 0xa0, 0xeb, 0xfd, 0xbf, 0x21, 0x24, 0xfa, 0x3a, + 0xfb, 0x06, 0x24, 0x75, 0x61, 0xe8, 0xac, 0xca, 0xff, 0x60, 0x35, 0x9e, + 0x4e, 0x1d, 0x7d, 0xff, 0xb3, 0x47, 0x5f, 0x47, 0x1c, 0x4e, 0xbf, 0xcf, + 0xc9, 0x01, 0x37, 0xd1, 0xd7, 0xda, 0xd4, 0x00, 0xea, 0x84, 0x73, 0xe1, + 0x0a, 0x18, 0xf4, 0x8b, 0xf1, 0xf6, 0x4c, 0xef, 0xe4, 0x11, 0xcd, 0xae, + 0x75, 0xf4, 0x81, 0xfc, 0x8e, 0xbe, 0xe7, 0xd8, 0x01, 0xd5, 0x07, 0x8c, + 0x84, 0x77, 0xf9, 0x27, 0x75, 0x80, 0x10, 0x75, 0xff, 0x23, 0x7b, 0x93, + 0x0c, 0x04, 0xeb, 0xe9, 0x7b, 0x3e, 0x9d, 0x79, 0xb0, 0x03, 0xaf, 0x72, + 0x16, 0x75, 0x39, 0xec, 0xfe, 0x46, 0xc8, 0xdd, 0xfa, 0x27, 0xfb, 0x93, + 0x1d, 0x7a, 0x06, 0x47, 0x50, 0x53, 0xc7, 0x99, 0xc7, 0x84, 0x1d, 0x32, + 0x18, 0x48, 0x68, 0xc3, 0xc5, 0x57, 0xfe, 0x8c, 0xd7, 0xc8, 0x40, 0xfd, + 0x91, 0xd7, 0xf2, 0x33, 0xa9, 0xf1, 0x93, 0xa8, 0x4f, 0xbf, 0xc8, 0x17, + 0xe8, 0x0f, 0xb1, 0xa7, 0x5f, 0x76, 0x05, 0xa7, 0x54, 0x8f, 0x9f, 0x44, + 0x3e, 0x26, 0xbe, 0x71, 0x79, 0x8e, 0xbf, 0x27, 0x87, 0x24, 0x75, 0xf4, + 0x33, 0x13, 0x1d, 0x77, 0xd5, 0x9d, 0x7f, 0x78, 0x5c, 0x18, 0x27, 0x5f, + 0x85, 0xc1, 0x82, 0x75, 0xbf, 0xf8, 0x79, 0xde, 0x2a, 0xa9, 0xd1, 0xf0, + 0xa1, 0x02, 0x12, 0xf4, 0x88, 0x59, 0xaf, 0xf4, 0x32, 0x1f, 0xdf, 0x92, + 0x3a, 0xfe, 0x4e, 0x6f, 0xa8, 0x91, 0xd6, 0xda, 0x75, 0x70, 0xfc, 0xfa, + 0x69, 0xb0, 0x5b, 0x78, 0x51, 0x43, 0xaf, 0xb0, 0x29, 0xb4, 0xeb, 0xa1, + 0x78, 0x6f, 0x5c, 0x6e, 0xff, 0xb1, 0x97, 0xdf, 0xb1, 0xf4, 0x4e, 0xb6, + 0x8e, 0xa4, 0x3f, 0x4e, 0x15, 0x39, 0xd5, 0xc0, 0x82, 0xae, 0x65, 0x92, + 0xa9, 0x0d, 0x6b, 0x22, 0xb7, 0xf9, 0xe4, 0x39, 0xee, 0xa1, 0x4a, 0x9a, + 0x1b, 0xcf, 0xbe, 0x8e, 0xbe, 0xfb, 0xd7, 0xf1, 0xd4, 0x13, 0x7f, 0xe1, + 0xcb, 0xd0, 0x33, 0x1d, 0x70, 0xc1, 0xd6, 0x98, 0xea, 0x98, 0xf0, 0x38, + 0x36, 0xe2, 0x97, 0xff, 0x28, 0x82, 0xdd, 0x42, 0xdf, 0x7f, 0x1d, 0x78, + 0x19, 0xb0, 0x75, 0x28, 0x7c, 0x5c, 0x44, 0xbe, 0x5e, 0xbf, 0x59, 0xd6, + 0x50, 0xeb, 0x6c, 0x9d, 0x77, 0x14, 0x3a, 0xa0, 0xf7, 0x90, 0x8f, 0xf1, + 0x1f, 0xa2, 0x77, 0xff, 0xdd, 0xc9, 0x6a, 0x3d, 0x2c, 0x63, 0x71, 0x01, + 0xd7, 0xfe, 0x92, 0x7b, 0xb9, 0xbf, 0xbf, 0x83, 0xae, 0xcd, 0x1d, 0x50, + 0x7a, 0x92, 0x3f, 0xad, 0x23, 0x17, 0xd0, 0xa4, 0xb0, 0x0e, 0xbf, 0x24, + 0x2e, 0x16, 0x75, 0xb0, 0xea, 0x43, 0xec, 0x72, 0x8d, 0x08, 0x6c, 0x92, + 0xd4, 0x2b, 0x1e, 0xc6, 0x14, 0x84, 0x8f, 0x61, 0x02, 0xf1, 0xb7, 0x5e, + 0xd4, 0x4c, 0x75, 0xfd, 0x81, 0xcd, 0xa9, 0xc3, 0xa8, 0xeb, 0x2c, 0xea, + 0xf1, 0x75, 0xb4, 0x2a, 0xfc, 0x04, 0xe2, 0x28, 0x75, 0xce, 0xa1, 0xd5, + 0x32, 0x30, 0x96, 0x39, 0xd4, 0x70, 0x11, 0x09, 0x3d, 0xd9, 0xc3, 0xae, + 0xf4, 0x1d, 0x7e, 0x8e, 0xe6, 0xd7, 0x3a, 0x96, 0x7a, 0x2e, 0x2a, 0x01, + 0x5b, 0xf9, 0x3d, 0x9d, 0x75, 0x0e, 0xbf, 0xbb, 0xfb, 0xcf, 0xd4, 0x3a, + 0xf3, 0x2c, 0xb2, 0x55, 0xff, 0x06, 0x27, 0xfb, 0x9d, 0x7d, 0xca, 0x54, + 0xbf, 0xbb, 0x27, 0x3a, 0xf4, 0xa1, 0x67, 0x50, 0x51, 0x92, 0xd4, 0xd4, + 0x4b, 0x98, 0x5a, 0xf4, 0x2d, 0x0e, 0xac, 0x3d, 0x76, 0x9e, 0xdf, 0x27, + 0x36, 0x02, 0x75, 0xfb, 0xb1, 0xbb, 0xb1, 0x9d, 0x7f, 0xfd, 0x1e, 0xd0, + 0x73, 0xc9, 0xdf, 0xf3, 0x7f, 0x1d, 0x5d, 0x3f, 0xaf, 0x15, 0x5b, 0x87, + 0x5f, 0xec, 0xc6, 0xfd, 0xdb, 0xdc, 0x3a, 0xff, 0xc9, 0x03, 0xe1, 0xcf, + 0x43, 0x27, 0x5e, 0xf7, 0x3f, 0x3a, 0xda, 0x3a, 0x84, 0xd6, 0xfe, 0x3b, + 0x7f, 0xfe, 0xc0, 0xc6, 0x6f, 0xf7, 0xc8, 0x3f, 0xcb, 0x34, 0x75, 0xcb, + 0x01, 0xd7, 0x38, 0x9d, 0x5d, 0x35, 0x4e, 0x2d, 0x7e, 0x5a, 0x78, 0x0e, + 0x75, 0x4e, 0xa9, 0x53, 0x21, 0x3c, 0xc6, 0x45, 0x30, 0x87, 0x0d, 0x5d, + 0xa0, 0x48, 0x7d, 0x08, 0x0f, 0xc8, 0x2f, 0xbb, 0xe4, 0x9c, 0xeb, 0xfc, + 0xd4, 0xd0, 0xe6, 0xd7, 0x3a, 0xfa, 0x27, 0x79, 0x1d, 0x76, 0x78, 0xeb, + 0xf6, 0x4e, 0x39, 0xb9, 0xd5, 0x88, 0xb1, 0xdc, 0x8b, 0x86, 0x5d, 0x21, + 0x11, 0x5b, 0xe8, 0x14, 0x63, 0x3a, 0xf7, 0x60, 0x27, 0x5d, 0xcd, 0x1d, + 0x47, 0x21, 0x6d, 0x7f, 0xa0, 0x64, 0xeb, 0xc0, 0x9d, 0x7d, 0xe5, 0xaf, + 0x87, 0x5f, 0xfc, 0x08, 0x16, 0xbf, 0x81, 0xf4, 0x64, 0x75, 0xe9, 0x27, + 0x4e, 0xbe, 0xf0, 0xe4, 0x8e, 0xbf, 0x67, 0xec, 0x1d, 0x39, 0xd7, 0xff, + 0x93, 0x5d, 0xc0, 0x8e, 0x6d, 0x1c, 0xd1, 0xd5, 0x24, 0xd1, 0x14, 0x30, + 0xdc, 0x8a, 0x64, 0x4e, 0x0d, 0x89, 0x07, 0x8a, 0xe9, 0x88, 0x6d, 0xbd, + 0x58, 0x45, 0x51, 0x19, 0x44, 0xf0, 0xa7, 0x91, 0x88, 0x63, 0x4d, 0xc9, + 0x43, 0xbb, 0xc6, 0x80, 0x91, 0x93, 0xcd, 0x0b, 0xde, 0x43, 0x8d, 0x6f, + 0x7d, 0x97, 0x3c, 0xf1, 0x8d, 0x02, 0x13, 0x6c, 0x12, 0xe1, 0x8d, 0x33, + 0x52, 0x9d, 0x7d, 0x19, 0xf6, 0xd4, 0x96, 0x48, 0xb6, 0x4c, 0x7e, 0xc6, + 0xb9, 0x7f, 0xca, 0xf9, 0x33, 0x63, 0x5f, 0xc1, 0xd7, 0xff, 0xfd, 0xfc, + 0x2b, 0xed, 0x27, 0x5d, 0x3d, 0x9c, 0x02, 0xde, 0x47, 0x52, 0xaa, 0x91, + 0xe7, 0x8e, 0x94, 0x27, 0x97, 0xee, 0x35, 0xdd, 0xa6, 0x8a, 0xde, 0xff, + 0xcf, 0x25, 0x73, 0x8d, 0x77, 0x69, 0xa2, 0x70, 0xb2, 0xb8, 0x7f, 0xab, + 0x33, 0xb9, 0x84, 0x13, 0xad, 0xd3, 0xad, 0xa3, 0xab, 0xf3, 0x41, 0xb2, + 0x21, 0x7c, 0xd7, 0x76, 0x9a, 0x2d, 0x1b, 0xff, 0xd8, 0x1e, 0xba, 0x93, + 0x4c, 0x9a, 0xfd, 0x67, 0x57, 0x0f, 0xeb, 0xa5, 0xb7, 0xcd, 0x71, 0x01, + 0xd7, 0xfd, 0x36, 0x31, 0xeb, 0x9c, 0x7f, 0x1d, 0x7f, 0x43, 0x8f, 0xe1, + 0xc3, 0xae, 0x45, 0x0e, 0xbf, 0xff, 0x4f, 0x1e, 0x80, 0xf2, 0x3a, 0xfa, + 0x1c, 0x01, 0xd7, 0xfe, 0x8d, 0xdd, 0x8f, 0xa2, 0xec, 0x73, 0x9d, 0x7f, + 0xe8, 0xe0, 0x31, 0x33, 0x9e, 0xfc, 0xea, 0x84, 0x6a, 0x75, 0x4f, 0x48, + 0x96, 0xc9, 0x93, 0x19, 0xd4, 0x3a, 0xaf, 0xf7, 0x7b, 0xfa, 0x8b, 0x8d, + 0x1d, 0x7f, 0xfe, 0x4d, 0x0e, 0x6d, 0x7f, 0x0e, 0x6b, 0xaf, 0x31, 0xd5, + 0x88, 0x89, 0x98, 0xd6, 0xfb, 0x00, 0xfd, 0x3a, 0xee, 0xe8, 0xeb, 0x2a, + 0xc0, 0x57, 0x58, 0xc5, 0x9d, 0x64, 0x27, 0xda, 0x45, 0x31, 0x02, 0xcf, + 0x3b, 0x1a, 0x27, 0xa1, 0x71, 0xb2, 0x47, 0xf4, 0x82, 0xf9, 0xae, 0xed, + 0x34, 0x5b, 0x57, 0xff, 0xf4, 0x3f, 0xa3, 0xb1, 0xa4, 0x49, 0x27, 0x30, + 0x27, 0x5f, 0xdd, 0x85, 0xc2, 0x04, 0xea, 0xe2, 0x2b, 0xb4, 0x5b, 0xe5, + 0x6b, 0xff, 0x75, 0x02, 0xf2, 0x0f, 0x51, 0x67, 0x5f, 0xf6, 0x63, 0x76, + 0x7f, 0xea, 0x70, 0xeb, 0xe8, 0xdb, 0x88, 0x75, 0xde, 0x01, 0xd7, 0xfd, + 0x12, 0x8e, 0x4f, 0x1c, 0x9c, 0xeb, 0xff, 0xf7, 0xe2, 0x9b, 0x53, 0xdd, + 0x8f, 0x6a, 0x36, 0xc1, 0xd7, 0xfd, 0x1c, 0xf9, 0xa8, 0xeb, 0xa1, 0xd7, + 0xfb, 0xa8, 0xf2, 0xf2, 0x4e, 0x75, 0x62, 0x7b, 0x2d, 0x30, 0x98, 0xf7, + 0x87, 0x6b, 0x21, 0x11, 0x6d, 0x1c, 0xb2, 0xaf, 0xb2, 0x71, 0x7f, 0x28, + 0xfc, 0x0f, 0xe2, 0x75, 0xfc, 0x3b, 0x29, 0xcc, 0x50, 0xeb, 0xf2, 0x4e, + 0xb8, 0x69, 0xd7, 0xe7, 0xde, 0x5f, 0x74, 0x75, 0xff, 0x92, 0x6d, 0x6d, + 0x71, 0x9f, 0xf0, 0x9d, 0x65, 0x54, 0x47, 0x80, 0x97, 0x78, 0xbf, 0x69, + 0x3f, 0xd2, 0xaa, 0x55, 0x3c, 0x70, 0x46, 0xe5, 0x72, 0xfa, 0x75, 0xfb, + 0x8d, 0x77, 0x69, 0xa2, 0xe5, 0xb2, 0xa1, 0x3c, 0x9c, 0x16, 0xbf, 0x71, + 0xae, 0xed, 0x34, 0x5d, 0xb7, 0xfc, 0x92, 0x92, 0x08, 0x22, 0x47, 0x5f, + 0x27, 0x1c, 0x07, 0x59, 0x5c, 0x44, 0x4b, 0x99, 0xe8, 0xda, 0xa1, 0xdc, + 0x22, 0xce, 0x53, 0x29, 0xf4, 0xc0, 0xc7, 0x04, 0xa5, 0x28, 0xed, 0x2b, + 0xa2, 0xe6, 0x38, 0x5b, 0xf6, 0x5e, 0xa0, 0xce, 0x80, 0x69, 0xd3, 0xd0, + 0xb1, 0xbf, 0xca, 0xe7, 0x1a, 0xee, 0xd3, 0x45, 0x4f, 0x7e, 0x15, 0x79, + 0xad, 0x1d, 0x74, 0xeb, 0x3a, 0xfd, 0xba, 0xdd, 0xc4, 0xea, 0x09, 0xbd, + 0xfc, 0x5e, 0xde, 0x3a, 0xff, 0xa1, 0xe7, 0xf9, 0xbe, 0xa0, 0x27, 0x52, + 0x1e, 0x58, 0x88, 0x5f, 0x35, 0xdd, 0xa6, 0x8a, 0xe6, 0xff, 0x2b, 0x9c, + 0x6b, 0xbb, 0x4d, 0x16, 0x75, 0xe7, 0x79, 0x1d, 0x7f, 0x26, 0xb0, 0x5d, + 0x93, 0xab, 0x88, 0xb1, 0xe9, 0x68, 0x9f, 0xf8, 0x6a, 0xff, 0xf7, 0xa3, + 0x5f, 0x3f, 0xd7, 0xa2, 0x69, 0x90, 0xeb, 0xf9, 0x17, 0x3f, 0xfc, 0x91, + 0xd7, 0xfa, 0x3b, 0xf1, 0x6c, 0x5b, 0x03, 0xc7, 0x56, 0x22, 0xef, 0xa9, + 0xdb, 0x4b, 0xef, 0xdc, 0xcf, 0x22, 0xce, 0xbe, 0x71, 0x80, 0x9d, 0x7e, + 0x9a, 0x17, 0x1f, 0x4e, 0xba, 0x4b, 0x3a, 0xb0, 0xdf, 0x89, 0x4d, 0xfb, + 0x8d, 0x77, 0x69, 0xa2, 0x42, 0xbf, 0xf6, 0x2f, 0x1f, 0x93, 0xfc, 0xdd, + 0x67, 0x5f, 0xf2, 0x6f, 0xaf, 0x0c, 0x2f, 0x47, 0x5d, 0x25, 0x71, 0x15, + 0x9d, 0x33, 0x02, 0x0d, 0xff, 0xdd, 0x45, 0xe6, 0xbe, 0x6f, 0x2c, 0xf1, + 0xd7, 0xd2, 0xef, 0xdd, 0x1d, 0x50, 0x7d, 0x58, 0x8d, 0x7c, 0xc5, 0xf6, + 0x16, 0x75, 0xfd, 0xdd, 0x6b, 0x39, 0x39, 0xd7, 0x43, 0x27, 0x56, 0x1e, + 0x22, 0x17, 0x5e, 0x5e, 0xd9, 0x1d, 0x7f, 0xfb, 0xb0, 0x05, 0xbc, 0xb5, + 0xec, 0xc5, 0x9d, 0x65, 0x67, 0x5d, 0x6b, 0x0b, 0x6e, 0x43, 0x45, 0x21, + 0xef, 0xc3, 0x15, 0x93, 0x75, 0x79, 0xe1, 0x96, 0x30, 0xa6, 0xd1, 0x07, + 0x9a, 0xbf, 0x20, 0xfa, 0x3d, 0x7f, 0xf2, 0xbd, 0x7d, 0x0e, 0x7b, 0xd0, + 0x03, 0xaf, 0xff, 0x2a, 0xb7, 0x92, 0xb9, 0xc6, 0xbb, 0xb4, 0xd1, 0x3e, + 0x53, 0x57, 0xde, 0x50, 0xfd, 0x8e, 0x77, 0x41, 0x70, 0xd0, 0xea, 0x1d, + 0xc9, 0xb9, 0xd7, 0xff, 0xd2, 0x9d, 0x86, 0x86, 0x2e, 0x76, 0xf3, 0xe7, + 0xce, 0xec, 0x9d, 0x52, 0x3f, 0xa0, 0x0b, 0x5f, 0xb3, 0x99, 0x93, 0x1d, + 0x65, 0x7a, 0x79, 0x1f, 0x48, 0xaf, 0xdc, 0x6b, 0xbb, 0x4d, 0x15, 0x95, + 0xff, 0x9e, 0x4a, 0xe7, 0x1a, 0xee, 0xd3, 0x44, 0xdd, 0x65, 0x70, 0xff, + 0x56, 0x67, 0x4d, 0x46, 0x82, 0x42, 0xa2, 0xf9, 0xae, 0xed, 0x34, 0x4a, + 0xd7, 0xff, 0xdc, 0x9c, 0x63, 0x8e, 0x11, 0x7e, 0x46, 0xd3, 0xab, 0x87, + 0xf9, 0xf9, 0x6d, 0xf8, 0x60, 0x2f, 0xd3, 0xaf, 0xca, 0xad, 0xe4, 0xae, + 0x1e, 0x42, 0x11, 0xdf, 0xfb, 0xd8, 0xae, 0x71, 0x27, 0x75, 0x9d, 0x7f, + 0xf9, 0x8a, 0x62, 0x18, 0x1a, 0xc7, 0x92, 0x67, 0x30, 0xeb, 0xff, 0x26, + 0xbf, 0x58, 0xa6, 0xdf, 0xdc, 0xeb, 0xfa, 0x05, 0xda, 0xec, 0x67, 0x54, + 0x8f, 0xb5, 0x68, 0x17, 0x07, 0x87, 0x5f, 0xb8, 0xd7, 0x76, 0x9a, 0x25, + 0xcb, 0xfe, 0x47, 0x97, 0x86, 0x17, 0xa3, 0xaf, 0xd2, 0xd9, 0x4e, 0xb9, + 0xd7, 0xa3, 0x66, 0x0e, 0xbc, 0x83, 0x07, 0x54, 0x8f, 0x7c, 0x25, 0x3b, + 0x47, 0x6f, 0xff, 0xcf, 0xe4, 0xfe, 0x42, 0x92, 0x8f, 0x0f, 0xf2, 0x3a, + 0xfe, 0x97, 0x70, 0x71, 0xa7, 0x5e, 0x97, 0x7c, 0x75, 0xdd, 0x84, 0x3c, + 0x7e, 0x95, 0xdf, 0xfc, 0x28, 0x0d, 0x72, 0x12, 0x4f, 0xa3, 0xab, 0x0f, + 0xb5, 0x0b, 0x2f, 0x3c, 0x95, 0x62, 0x6a, 0xc6, 0xe2, 0x18, 0x52, 0x22, + 0xc1, 0x6e, 0x99, 0xbc, 0x25, 0x74, 0x63, 0xe8, 0xc2, 0x2f, 0xfd, 0xfa, + 0xd5, 0xd4, 0x0f, 0xb3, 0x87, 0x59, 0x54, 0x5c, 0x30, 0x5c, 0xb5, 0x9d, + 0x42, 0x62, 0xff, 0xe5, 0x5e, 0x4a, 0xe7, 0x1a, 0xee, 0xd3, 0x44, 0x77, + 0x7f, 0xde, 0xee, 0x49, 0x57, 0x1d, 0x1d, 0x7f, 0x30, 0x86, 0x1b, 0x82, + 0x75, 0xdf, 0xf4, 0xeb, 0xf9, 0x80, 0x39, 0xd7, 0xf1, 0xd7, 0xff, 0xf7, + 0xa4, 0x81, 0xea, 0x6d, 0xf9, 0x81, 0xe2, 0x7e, 0xd3, 0xaf, 0xf6, 0x33, + 0xa8, 0x1f, 0x68, 0xeb, 0xf8, 0x03, 0x9b, 0xfb, 0x0e, 0xbf, 0x3a, 0x9d, + 0xc0, 0x1d, 0x7f, 0x08, 0x1f, 0x8f, 0xf4, 0xea, 0x84, 0x40, 0x70, 0xb1, + 0xc9, 0xef, 0xfc, 0x9c, 0xf9, 0xa1, 0xc5, 0xc3, 0x4e, 0xbf, 0xf4, 0x0f, + 0xfe, 0x47, 0xda, 0xf2, 0x3a, 0xff, 0xc3, 0xfc, 0xbe, 0x62, 0x0c, 0x2c, + 0xeb, 0xe6, 0xbb, 0xb4, 0xd1, 0x50, 0xdf, 0xf6, 0x77, 0x05, 0xf9, 0xc4, + 0x3a, 0x94, 0x4c, 0x71, 0xa7, 0xc8, 0x7d, 0xc3, 0xed, 0x16, 0xde, 0x63, + 0x78, 0x3a, 0xe9, 0x61, 0xd7, 0xfd, 0x2f, 0x27, 0x1d, 0xa8, 0x27, 0x5f, + 0x48, 0x1a, 0xc3, 0xaf, 0xff, 0x3a, 0xf3, 0x83, 0x89, 0xb5, 0x38, 0xe7, + 0x5f, 0xfd, 0xd1, 0xc9, 0xbd, 0xdc, 0xe2, 0x68, 0xeb, 0xf6, 0xe2, 0x8b, + 0x43, 0xaa, 0x11, 0x61, 0x88, 0xe8, 0x87, 0x7f, 0xa3, 0xcf, 0xdf, 0x81, + 0x83, 0xaf, 0xfd, 0x9e, 0xd7, 0x32, 0x6e, 0xa2, 0x87, 0x5f, 0xf7, 0xc7, + 0x1c, 0xd8, 0xf9, 0xdf, 0xce, 0xa4, 0x3f, 0xef, 0xcf, 0xef, 0xf4, 0xa3, + 0x93, 0xc7, 0x27, 0x3a, 0xff, 0xda, 0xc1, 0xf6, 0xb2, 0x49, 0xd3, 0xaf, + 0xed, 0x66, 0xd1, 0x8d, 0xce, 0xad, 0x1f, 0x57, 0x8f, 0x2f, 0xff, 0xa0, + 0x18, 0x3f, 0x1f, 0xdf, 0x3b, 0x80, 0x73, 0xae, 0x19, 0xce, 0xa8, 0x4c, + 0x9b, 0x21, 0x3c, 0x84, 0x42, 0xa1, 0x7f, 0x6d, 0x75, 0xf5, 0x97, 0x3a, + 0xff, 0xff, 0x24, 0x79, 0xfa, 0xae, 0xbb, 0x83, 0xef, 0x80, 0x96, 0x8e, + 0xb6, 0x22, 0x24, 0x44, 0xbe, 0xfb, 0xbe, 0xc9, 0xce, 0xbf, 0x64, 0xee, + 0x3b, 0x4e, 0xbf, 0xff, 0xff, 0xd1, 0x2f, 0x9e, 0xea, 0x46, 0xbe, 0x67, + 0xed, 0x8d, 0xbf, 0x33, 0x9c, 0xcd, 0xbf, 0xbf, 0x4e, 0xbe, 0xe8, 0xbe, + 0xc1, 0xd5, 0x89, 0x82, 0x89, 0x16, 0x8a, 0x3d, 0x09, 0x8b, 0xff, 0xfe, + 0xfd, 0xd8, 0xd2, 0x7e, 0xba, 0x7a, 0x3a, 0x9e, 0xd6, 0x04, 0xeb, 0x2a, + 0xc0, 0x64, 0x8e, 0xb1, 0x65, 0xcc, 0x21, 0x78, 0x2f, 0x9d, 0x7c, 0x30, + 0xb2, 0xc8, 0xd2, 0x94, 0x4b, 0x68, 0xee, 0xe2, 0xa8, 0x6d, 0xc8, 0x68, + 0xac, 0xb7, 0xb0, 0xb1, 0x18, 0xd2, 0x35, 0x0d, 0x0f, 0x46, 0x57, 0xb2, + 0x83, 0x7c, 0xd7, 0x76, 0x9a, 0x2a, 0x8b, 0xfd, 0xc8, 0xdb, 0xbc, 0xb3, + 0xc7, 0x57, 0x0f, 0x8b, 0xf2, 0xdb, 0xff, 0x3c, 0x95, 0xce, 0x35, 0xdd, + 0xa6, 0x89, 0xae, 0xfa, 0x39, 0x1e, 0x3a, 0xe7, 0xf1, 0xd4, 0x13, 0x6a, + 0xb2, 0x0b, 0x2b, 0x88, 0xc3, 0x59, 0x1b, 0xbf, 0xdf, 0xb8, 0xd7, 0x76, + 0x9a, 0x2a, 0xcb, 0xfe, 0x89, 0x47, 0x27, 0x8e, 0x4e, 0x75, 0x95, 0xc3, + 0xec, 0x13, 0x3b, 0xfe, 0xec, 0x6f, 0xe8, 0xeb, 0xb1, 0x9d, 0x7f, 0xf0, + 0x30, 0x55, 0x90, 0x35, 0x3b, 0x89, 0xd4, 0xa9, 0xff, 0xc1, 0xdd, 0xff, + 0xca, 0xbc, 0x95, 0xce, 0x35, 0xdd, 0xa6, 0x89, 0x12, 0xfd, 0xc6, 0xbb, + 0xb4, 0xd1, 0x69, 0x5f, 0xf9, 0xe4, 0xae, 0x71, 0xae, 0xed, 0x34, 0x4f, + 0xb6, 0x57, 0x0f, 0xf5, 0x66, 0x77, 0xff, 0x95, 0x5b, 0xc9, 0x5c, 0xe3, + 0x5d, 0xda, 0x68, 0xa1, 0x2f, 0xfe, 0xc6, 0x55, 0xf2, 0x8f, 0xa4, 0xf4, + 0x1d, 0x7e, 0xf7, 0xed, 0x7d, 0x1d, 0x7c, 0x93, 0xc7, 0x0e, 0xa5, 0x9e, + 0x4f, 0x4a, 0x2f, 0xdc, 0x6b, 0xbb, 0x4d, 0x14, 0x7d, 0xff, 0x44, 0xa3, + 0x93, 0xc7, 0x27, 0x3a, 0xff, 0xff, 0xff, 0x7d, 0x4e, 0x4d, 0x1d, 0xe6, + 0x75, 0xfe, 0xeb, 0x14, 0x71, 0x04, 0x0c, 0x4d, 0xd8, 0x3a, 0xfc, 0xfa, + 0x4f, 0x41, 0xd7, 0xfd, 0x13, 0x40, 0xc4, 0xdd, 0x83, 0xaa, 0x11, 0xd8, + 0xa4, 0x24, 0x04, 0x96, 0xff, 0xfe, 0xc0, 0xf6, 0x3e, 0xab, 0xe1, 0x70, + 0x6b, 0x50, 0x02, 0xaf, 0x3c, 0x95, 0x85, 0x41, 0x58, 0x44, 0x26, 0x7e, + 0x8c, 0x97, 0x64, 0xd2, 0xff, 0xec, 0xea, 0xbe, 0x51, 0xf4, 0x9e, 0x83, + 0xac, 0xac, 0xea, 0xd0, 0x17, 0x2a, 0x63, 0xcc, 0x95, 0x0d, 0xb7, 0x4c, + 0xf3, 0x8d, 0xf2, 0x45, 0xc5, 0x15, 0x29, 0x2a, 0xad, 0x94, 0xb1, 0xbc, + 0x28, 0x52, 0x14, 0xd3, 0x11, 0x76, 0x19, 0xc0, 0x28, 0xf4, 0xb9, 0x7b, + 0xfc, 0xae, 0x71, 0xae, 0xed, 0x34, 0x44, 0x57, 0xf6, 0x71, 0xae, 0xed, + 0x34, 0x45, 0x77, 0xfc, 0xc6, 0xae, 0x71, 0xae, 0xed, 0x34, 0x57, 0x14, + 0xaa, 0x20, 0x1c, 0xe2, 0xff, 0xf0, 0x20, 0x5a, 0xab, 0xf8, 0x1f, 0x46, + 0x47, 0x5f, 0x2b, 0x3c, 0xcc, 0x67, 0x59, 0x37, 0x3f, 0x30, 0x25, 0xdf, + 0x67, 0x5f, 0xc7, 0x5f, 0xec, 0x4e, 0x00, 0x1f, 0xe8, 0xeb, 0x30, 0x04, + 0xf4, 0xf4, 0x41, 0x7f, 0xff, 0x7b, 0x49, 0xd7, 0x49, 0x20, 0xfb, 0xfe, + 0xf3, 0x0e, 0xbf, 0x71, 0xae, 0xed, 0x34, 0x53, 0xd7, 0xf9, 0x68, 0x1f, + 0xdf, 0x92, 0x3a, 0xe5, 0xa1, 0xd5, 0x07, 0x90, 0xd3, 0x3b, 0xff, 0xfd, + 0x28, 0xf6, 0xbf, 0x5b, 0x50, 0x11, 0x9d, 0x4f, 0xda, 0x75, 0xff, 0xfd, + 0xce, 0x7f, 0xce, 0x40, 0xe2, 0x89, 0xde, 0xe7, 0xd3, 0xaf, 0xfe, 0x49, + 0x60, 0x82, 0x16, 0x9c, 0x91, 0xd7, 0xfa, 0x51, 0xc9, 0xe3, 0x93, 0x9d, + 0x7d, 0xf0, 0x5e, 0x47, 0x5f, 0x9f, 0x3a, 0x8b, 0x3a, 0xb4, 0x78, 0xfb, + 0x48, 0xaa, 0x11, 0x3f, 0x8f, 0x77, 0xfe, 0x41, 0x85, 0xc4, 0x87, 0x16, + 0x75, 0xff, 0x40, 0xb7, 0x36, 0xe7, 0xb4, 0x75, 0xf9, 0xe7, 0x8e, 0x7e, + 0x75, 0x30, 0x95, 0xbc, 0xc1, 0x5e, 0x2c, 0xb5, 0xef, 0x72, 0x14, 0x61, + 0x75, 0xd1, 0x87, 0x06, 0x88, 0x76, 0x9d, 0x6c, 0x9c, 0x5f, 0xfe, 0x79, + 0x2a, 0x11, 0x76, 0x75, 0xa8, 0x01, 0xd7, 0xff, 0x80, 0x0f, 0xf4, 0xaf, + 0xd1, 0x75, 0x8c, 0x1d, 0x7f, 0xf0, 0xe0, 0x1c, 0x40, 0xaa, 0xd1, 0x67, + 0x57, 0x11, 0x1d, 0xe4, 0xca, 0x55, 0x39, 0xf0, 0xc2, 0x91, 0x21, 0xb1, + 0x6c, 0x3a, 0xfc, 0x31, 0xfb, 0x07, 0x47, 0x5f, 0xca, 0x71, 0xc2, 0xe2, + 0x75, 0x04, 0xf9, 0xb0, 0x3d, 0xca, 0xef, 0xfe, 0x40, 0xf1, 0xf7, 0x57, + 0x9c, 0x89, 0xce, 0xa5, 0x4f, 0xcf, 0xa5, 0xb7, 0x06, 0x0e, 0xbf, 0xff, + 0x76, 0x39, 0x92, 0x47, 0xf6, 0x05, 0x3f, 0x69, 0x57, 0xe8, 0x90, 0x3f, + 0x91, 0xd7, 0xcd, 0x77, 0x69, 0xa2, 0xb3, 0xa9, 0x8f, 0x57, 0x85, 0x17, + 0xde, 0x45, 0xe8, 0xeb, 0xfa, 0x75, 0xc0, 0xcb, 0x47, 0x5f, 0xb3, 0xda, + 0xfb, 0xa3, 0xaf, 0x44, 0xe8, 0x75, 0xfb, 0xc0, 0xfa, 0x32, 0x3a, 0xf7, + 0xef, 0xa3, 0xaf, 0xfb, 0x24, 0x9f, 0xb1, 0xb1, 0x60, 0x59, 0xd7, 0xec, + 0x9a, 0x7f, 0xc0, 0x75, 0x95, 0x85, 0x44, 0x41, 0x15, 0xc8, 0x54, 0x6e, + 0x47, 0xc2, 0x15, 0x96, 0xf4, 0xa5, 0xc6, 0xc4, 0xa7, 0x43, 0x9f, 0x50, + 0x6f, 0xfd, 0xd4, 0xf3, 0xf2, 0x78, 0x40, 0x9d, 0x7e, 0xf2, 0x0e, 0x2c, + 0xeb, 0xe9, 0x38, 0xab, 0x87, 0xc5, 0xb0, 0x7b, 0x7f, 0xe7, 0x92, 0xb9, + 0xc6, 0xbb, 0xb4, 0xd1, 0x22, 0xdf, 0xff, 0xbd, 0xdc, 0x15, 0x7c, 0xef, + 0xbe, 0x94, 0x51, 0xce, 0xbf, 0xf3, 0xf9, 0x58, 0x4e, 0x27, 0xbf, 0x3a, + 0x95, 0x46, 0xfc, 0x25, 0x3a, 0xbd, 0xfd, 0x9c, 0x6b, 0xbb, 0x4d, 0x16, + 0x4d, 0xff, 0xef, 0x6b, 0xee, 0x95, 0xc9, 0xd0, 0x65, 0xa3, 0xa9, 0x54, + 0x42, 0xe1, 0xc5, 0xff, 0xfe, 0x74, 0xf7, 0xfc, 0x7d, 0x2a, 0xde, 0xa7, + 0x22, 0x5a, 0x3a, 0xfe, 0xce, 0x35, 0xdd, 0xa6, 0x8b, 0x62, 0xff, 0xfe, + 0x60, 0x77, 0xe0, 0xe7, 0x3d, 0xae, 0xcd, 0xf3, 0xe7, 0x76, 0x4e, 0xbd, + 0xcf, 0xfa, 0x75, 0xde, 0x56, 0x11, 0x0f, 0xc6, 0xaa, 0x55, 0x1d, 0xc9, + 0x0b, 0xfb, 0xd9, 0xac, 0x3a, 0xf9, 0xae, 0xed, 0x34, 0x5b, 0x77, 0xda, + 0x9d, 0xf8, 0x75, 0x70, 0xf3, 0xfc, 0x5b, 0x7f, 0x27, 0x7c, 0x80, 0xfc, + 0xeb, 0xfe, 0x89, 0x47, 0x27, 0x8e, 0x4e, 0x75, 0x95, 0x92, 0x3c, 0x71, + 0xa6, 0x62, 0x21, 0x2d, 0xbf, 0xfd, 0x82, 0x05, 0x56, 0xe1, 0xcc, 0x15, + 0x0e, 0xbc, 0xc2, 0xe8, 0x4e, 0xbd, 0x3f, 0x50, 0xeb, 0xff, 0x30, 0x98, + 0x4c, 0x3f, 0xdd, 0xc1, 0x80, 0x1d, 0x7f, 0x40, 0xc8, 0x3f, 0xac, 0xeb, + 0xe6, 0xbb, 0xb4, 0xd1, 0x78, 0x5f, 0xf9, 0xfd, 0x1b, 0x79, 0xcc, 0xdf, + 0x47, 0x57, 0x0f, 0xb4, 0x4b, 0x6f, 0xbd, 0xb3, 0x9d, 0x3a, 0xfc, 0xb8, + 0x19, 0x39, 0xd7, 0xf4, 0x0f, 0xb6, 0xbb, 0x4e, 0xbf, 0xa5, 0x1b, 0x63, + 0x9b, 0x9d, 0x52, 0x3d, 0xcc, 0x2d, 0xbf, 0xd1, 0xe7, 0xef, 0xc0, 0xc1, + 0xd7, 0xfe, 0xfa, 0xbd, 0xe5, 0xec, 0x1f, 0x68, 0xeb, 0xb1, 0x43, 0xaa, + 0x0f, 0x5f, 0x10, 0x6f, 0x92, 0x7c, 0x59, 0xd7, 0xec, 0x10, 0x6c, 0x41, + 0xd7, 0xe8, 0xfb, 0xfb, 0xe8, 0xeb, 0xff, 0x97, 0x0d, 0xf9, 0x83, 0xfc, + 0xb3, 0x47, 0x5f, 0xff, 0xf9, 0xd3, 0xce, 0xb7, 0x10, 0x37, 0xa9, 0xc9, + 0x7d, 0x96, 0x09, 0xd7, 0xf4, 0x6f, 0xbc, 0x9f, 0x73, 0xab, 0x11, 0xbd, + 0xd4, 0x5f, 0xda, 0xaf, 0xfe, 0xce, 0xf5, 0xe4, 0xb4, 0x8e, 0x48, 0xeb, + 0xa0, 0x07, 0x54, 0x8f, 0x5f, 0xc8, 0x54, 0xc0, 0x5c, 0xab, 0x61, 0x10, + 0x31, 0x31, 0xc9, 0xd2, 0xf2, 0x13, 0x5b, 0x90, 0xa1, 0x24, 0xd0, 0x81, + 0x59, 0x0f, 0x61, 0x14, 0xe4, 0x00, 0x21, 0x12, 0x8d, 0x46, 0x0f, 0xe8, + 0x43, 0xdf, 0xed, 0xd5, 0xc0, 0x3f, 0x34, 0x75, 0xfe, 0x02, 0xb3, 0x4a, + 0x07, 0xc7, 0x52, 0xa9, 0xaf, 0x44, 0x3d, 0xb8, 0x69, 0x79, 0x33, 0x73, + 0xaf, 0x9a, 0xee, 0xd3, 0x45, 0xe9, 0x7f, 0xe4, 0xf7, 0x45, 0xe4, 0x07, + 0x01, 0xd5, 0xc3, 0xe9, 0x59, 0x6d, 0xe5, 0xa7, 0x8e, 0xbf, 0xe7, 0xf4, + 0xa1, 0x4f, 0x24, 0xe7, 0x52, 0xcf, 0x50, 0x46, 0xef, 0xd8, 0xbe, 0xb8, + 0x4e, 0xa0, 0xa6, 0x83, 0x90, 0x84, 0xfa, 0xed, 0xb0, 0x43, 0x7f, 0xff, + 0xb6, 0xe0, 0xaa, 0x1c, 0x0f, 0x71, 0x6b, 0x79, 0x60, 0x9d, 0x7f, 0x95, + 0xf6, 0x4d, 0x27, 0x09, 0xd4, 0x88, 0x94, 0xeb, 0x05, 0x2a, 0x8f, 0xdc, + 0x86, 0xdd, 0x43, 0x71, 0xa3, 0x3c, 0x2f, 0xe5, 0x09, 0x6c, 0x9d, 0x93, + 0x6c, 0x62, 0x89, 0x29, 0x16, 0x68, 0xc1, 0xf9, 0x18, 0xd2, 0xe1, 0x69, + 0xd2, 0x30, 0x46, 0x9e, 0x31, 0x8c, 0xe9, 0x0f, 0xf9, 0xe5, 0x16, 0x65, + 0x3a, 0x5d, 0xff, 0x4e, 0xbf, 0xfb, 0xf8, 0x98, 0x73, 0x6b, 0xad, 0x68, + 0x75, 0xf6, 0x75, 0xfc, 0x75, 0xfe, 0xc4, 0xe0, 0x01, 0xfe, 0x8e, 0xb3, + 0x01, 0x44, 0x4c, 0x0a, 0x2e, 0x88, 0x2f, 0xbd, 0x1b, 0xce, 0x75, 0xff, + 0x7b, 0x59, 0xbc, 0xbb, 0xfa, 0x87, 0x52, 0x1e, 0xf8, 0x91, 0xdf, 0x46, + 0xd8, 0x91, 0xd7, 0xee, 0x35, 0xdd, 0xa6, 0x88, 0x8e, 0xff, 0xfb, 0xbf, + 0xeb, 0x58, 0xb1, 0xcd, 0xbf, 0x21, 0x8a, 0x3a, 0xff, 0xa2, 0x7e, 0x67, + 0xbc, 0x9e, 0x3a, 0xf0, 0xc6, 0xe7, 0x54, 0x8f, 0x4c, 0x27, 0x17, 0xfd, + 0x9c, 0xcd, 0x63, 0x8c, 0xe7, 0x5e, 0xc0, 0xac, 0xeb, 0xff, 0xfd, 0xd7, + 0x4f, 0x47, 0x47, 0x3d, 0xd4, 0xee, 0x23, 0x27, 0x5f, 0xff, 0xfe, 0xf7, + 0x91, 0x7c, 0x4c, 0xdc, 0x7f, 0xf4, 0x77, 0xe6, 0xd4, 0xf4, 0xd0, 0x75, + 0x42, 0x36, 0x71, 0x76, 0xff, 0x3a, 0xf3, 0x92, 0x85, 0x9d, 0x74, 0xeb, + 0x2a, 0xe6, 0x59, 0x2a, 0xff, 0xca, 0xb7, 0xa9, 0x37, 0x62, 0x75, 0x40, + 0x6b, 0xd9, 0x17, 0xbe, 0xdb, 0x1e, 0x83, 0xaa, 0x47, 0xf8, 0x8b, 0x57, + 0xf6, 0x3a, 0xf3, 0x7f, 0x1d, 0x7f, 0xdf, 0xc7, 0x72, 0x69, 0x3c, 0xe7, + 0x5f, 0xca, 0xe9, 0x38, 0xe0, 0x3a, 0xb0, 0xf9, 0xdc, 0xea, 0xcc, 0x67, + 0x5f, 0xf4, 0x66, 0xf0, 0xf2, 0x79, 0x1d, 0x4c, 0x41, 0xe4, 0x84, 0x4e, + 0xfe, 0x63, 0x1c, 0xeb, 0xf8, 0xeb, 0xfa, 0x14, 0xc1, 0x45, 0x0e, 0xbf, + 0xb3, 0xdb, 0x1e, 0xce, 0x9d, 0x58, 0x88, 0x91, 0x2e, 0xd1, 0x65, 0xff, + 0xfc, 0xd5, 0x78, 0xe2, 0x9e, 0x57, 0x91, 0xe1, 0x70, 0x1d, 0x4c, 0x5a, + 0xf8, 0x33, 0x0a, 0x15, 0xf1, 0x09, 0x99, 0x10, 0x61, 0x13, 0x4c, 0xf7, + 0x85, 0x5a, 0x11, 0x4c, 0x6d, 0xc8, 0x7a, 0x74, 0x85, 0xe1, 0xb8, 0x02, + 0x11, 0x84, 0x9e, 0x9a, 0x7d, 0x0b, 0x0d, 0xa5, 0xd7, 0x6c, 0x74, 0xeb, + 0xf7, 0x1a, 0xee, 0xd3, 0x44, 0x5d, 0x7e, 0xf0, 0x3e, 0x8c, 0x8a, 0xbf, + 0x6b, 0xdd, 0x80, 0x1d, 0x7e, 0x79, 0xe3, 0x9f, 0x9d, 0x65, 0x67, 0x46, + 0x26, 0x0c, 0xb9, 0x9f, 0xe5, 0x3b, 0x24, 0xf4, 0xaa, 0xa2, 0xc9, 0x47, + 0xb1, 0x7f, 0xf2, 0xde, 0x4a, 0xe7, 0x1a, 0xee, 0xd3, 0x44, 0xcd, 0x7f, + 0x30, 0xcc, 0x3d, 0x81, 0xa8, 0xf1, 0xd7, 0xb7, 0x8d, 0x1d, 0x79, 0xa8, + 0xb3, 0xaf, 0x98, 0x5e, 0x71, 0x3a, 0xed, 0x96, 0x20, 0xeb, 0xb3, 0xf3, + 0xaf, 0xff, 0x76, 0x16, 0xfe, 0xcd, 0xc0, 0xbf, 0xbd, 0x3a, 0xf9, 0x27, + 0xfc, 0x4e, 0xbf, 0x64, 0xf8, 0x09, 0x8e, 0xaf, 0x87, 0x95, 0xe2, 0x2b, + 0xfd, 0xf3, 0x05, 0xf8, 0x0d, 0x93, 0xaf, 0xff, 0xcb, 0x7e, 0xe6, 0xe0, + 0xeb, 0x2f, 0xd9, 0xbb, 0xf9, 0xd7, 0xf6, 0x6a, 0x3e, 0x8c, 0x1d, 0x41, + 0x45, 0xde, 0x1b, 0x75, 0x66, 0xed, 0x61, 0xd7, 0x6c, 0x78, 0xeb, 0x30, + 0x4e, 0xb0, 0x20, 0xd6, 0xfe, 0x33, 0x7f, 0xff, 0xe4, 0x18, 0x68, 0xc2, + 0xfe, 0x47, 0x38, 0x9b, 0x78, 0xee, 0x03, 0xa9, 0x88, 0x55, 0x58, 0xd1, + 0xe4, 0x16, 0x9a, 0x12, 0xdd, 0x86, 0xfb, 0x97, 0x81, 0x0b, 0xc4, 0xf7, + 0xf3, 0x30, 0x23, 0x9e, 0x3a, 0xf9, 0xfa, 0x93, 0x1d, 0x7d, 0xd9, 0xa0, + 0x27, 0x56, 0x1f, 0x73, 0x4a, 0xdc, 0x86, 0xff, 0x35, 0x30, 0x43, 0xd8, + 0x3a, 0x8e, 0xbf, 0x75, 0xfd, 0x20, 0x1d, 0x7f, 0xfb, 0xe7, 0x5d, 0x3c, + 0x0f, 0xc4, 0x5e, 0x47, 0x56, 0x22, 0xad, 0xa6, 0x08, 0x14, 0xb2, 0x7b, + 0xff, 0xff, 0xff, 0xff, 0xcc, 0x4d, 0x81, 0x8c, 0x4d, 0x84, 0xc3, 0xd8, + 0x7b, 0x58, 0x30, 0xc3, 0x98, 0x5c, 0x9f, 0x63, 0x3f, 0x0b, 0x12, 0x8d, + 0x9d, 0xfe, 0xf5, 0x85, 0x10, 0xc2, 0x63, 0x61, 0xbd, 0xf3, 0xe7, 0x76, + 0x4e, 0xbf, 0xff, 0x03, 0x79, 0x77, 0xf8, 0xe2, 0xbd, 0x46, 0xbf, 0x0e, + 0xbf, 0xfb, 0x76, 0x63, 0xc1, 0x46, 0x3d, 0x42, 0xce, 0xbf, 0xff, 0xf2, + 0x2d, 0x39, 0xdf, 0xf5, 0x28, 0xdb, 0xc8, 0x1f, 0x77, 0x24, 0x75, 0xff, + 0x93, 0xc8, 0xd4, 0x0f, 0xb1, 0xa7, 0x56, 0x23, 0xc7, 0xc9, 0x1b, 0x0d, + 0xb7, 0xde, 0xd9, 0xce, 0x9d, 0x7f, 0xff, 0x9c, 0x5a, 0x38, 0x1e, 0xff, + 0xf3, 0xb1, 0x2e, 0x44, 0xe7, 0x56, 0x22, 0x1b, 0xf2, 0x4b, 0xff, 0xfc, + 0xea, 0x0e, 0x03, 0xfd, 0x7c, 0x92, 0x76, 0x1a, 0x2e, 0x75, 0xf7, 0x93, + 0xa8, 0x75, 0xff, 0x3f, 0x25, 0xf3, 0x1a, 0x1c, 0x3a, 0x98, 0x4b, 0x81, + 0x51, 0x19, 0x66, 0x46, 0x93, 0xd8, 0x5c, 0x39, 0x18, 0xb0, 0xfe, 0x41, + 0x6e, 0x1d, 0x7f, 0x7b, 0x17, 0xbe, 0x2c, 0xeb, 0x77, 0x0d, 0xea, 0x08, + 0x5f, 0xef, 0xc2, 0xf2, 0xd2, 0x48, 0xeb, 0xff, 0xf0, 0x50, 0x67, 0xcd, + 0x23, 0xf5, 0x56, 0x59, 0x64, 0xab, 0xfb, 0xdd, 0x89, 0xfb, 0xf9, 0xd7, + 0xf6, 0xf2, 0xd0, 0x3f, 0x98, 0xeb, 0xfe, 0x9f, 0x00, 0x1f, 0xdf, 0x92, + 0x3a, 0xfe, 0x77, 0x0e, 0xdc, 0x09, 0xd7, 0x9d, 0xda, 0x68, 0xb3, 0xef, + 0xe0, 0x38, 0xc9, 0x16, 0x75, 0x4e, 0x8b, 0x90, 0x9d, 0x34, 0xb4, 0x04, + 0xf7, 0xfe, 0x4e, 0xc4, 0x93, 0xd1, 0xed, 0x1d, 0x7f, 0xfb, 0x9d, 0x7f, + 0x99, 0xb4, 0x73, 0x58, 0x27, 0x5f, 0xf4, 0x20, 0x71, 0x6c, 0xe7, 0x4e, + 0xbf, 0xfb, 0x5e, 0x49, 0x99, 0x70, 0xc6, 0xfa, 0x3a, 0x91, 0x18, 0xee, + 0x95, 0xf9, 0xbd, 0xe6, 0x59, 0x64, 0xab, 0xff, 0x3c, 0xb4, 0x38, 0xd0, + 0xe7, 0x0a, 0x54, 0xbf, 0xbf, 0x6c, 0x7e, 0xbc, 0x09, 0xd7, 0xfb, 0xdd, + 0xcd, 0xbf, 0x24, 0xb3, 0xab, 0x0f, 0x8b, 0xf2, 0xbb, 0xff, 0x6f, 0x21, + 0xfc, 0x1f, 0x1a, 0xb0, 0x1d, 0x74, 0x28, 0x75, 0xff, 0x06, 0x06, 0x01, + 0x2e, 0xa1, 0xd5, 0x08, 0x8f, 0x9d, 0x0d, 0x05, 0xaf, 0xf7, 0x50, 0x22, + 0xef, 0x31, 0xd7, 0xf8, 0x3d, 0xfd, 0xc1, 0xb3, 0x87, 0x54, 0x1f, 0x3a, + 0x18, 0xdf, 0xf2, 0x08, 0x7e, 0x87, 0xff, 0x68, 0xeb, 0xd0, 0x2a, 0x1d, + 0x52, 0x5d, 0xc3, 0x09, 0x2b, 0x4c, 0xf7, 0x58, 0x98, 0xbf, 0x90, 0xea, + 0x59, 0xf7, 0x63, 0x03, 0x02, 0x70, 0xc2, 0xbb, 0x50, 0xb1, 0xf4, 0x25, + 0xb6, 0x90, 0x7d, 0x3b, 0xb8, 0x1a, 0x3a, 0xff, 0xbf, 0xf6, 0x87, 0x26, + 0x85, 0x9d, 0x7f, 0x9d, 0x9e, 0xa4, 0x72, 0x0e, 0xa0, 0xa2, 0x01, 0x41, + 0x6e, 0x1c, 0xdf, 0xfb, 0x89, 0xa9, 0x7d, 0xec, 0x0c, 0x1d, 0x7d, 0xc4, + 0x85, 0x9d, 0x7f, 0xfe, 0xf2, 0x9f, 0xc6, 0x07, 0xb9, 0xad, 0xe5, 0x1d, + 0x3a, 0xb8, 0x8b, 0x55, 0x9f, 0x09, 0x05, 0xcf, 0x23, 0xaf, 0xff, 0xff, + 0xe1, 0x76, 0x7d, 0x9d, 0x1c, 0xf7, 0xe0, 0x5b, 0xc9, 0xc3, 0x02, 0xfc, + 0x79, 0x1d, 0x7f, 0xb3, 0xbd, 0xff, 0xce, 0x27, 0x5f, 0xf3, 0x73, 0xad, + 0x7e, 0x3c, 0x8e, 0xbc, 0x93, 0x68, 0xea, 0x83, 0xd3, 0x59, 0xbd, 0x90, + 0x29, 0xa0, 0x4c, 0x2b, 0xc8, 0x42, 0xae, 0x10, 0xb7, 0xf7, 0xc4, 0xeb, + 0xad, 0x0e, 0xbd, 0xb7, 0x02, 0x75, 0xb9, 0x39, 0xe5, 0x4c, 0x5b, 0x7f, + 0xec, 0x67, 0x63, 0x99, 0xb0, 0x3f, 0xb2, 0x75, 0x42, 0xa7, 0x7e, 0xc6, + 0xde, 0xf0, 0x98, 0x12, 0xab, 0xff, 0xff, 0xe0, 0x6b, 0x30, 0x54, 0xfb, + 0xc1, 0x8c, 0xea, 0xba, 0x1c, 0x9d, 0x78, 0xb3, 0xaf, 0xdf, 0x60, 0x7e, + 0xac, 0xea, 0xc4, 0x54, 0x79, 0xfa, 0xfd, 0xb5, 0xfb, 0x1f, 0x4e, 0xbf, + 0xfe, 0xff, 0x79, 0x68, 0x3d, 0x8e, 0x05, 0xdd, 0x93, 0xab, 0x11, 0x3c, + 0x84, 0x42, 0x55, 0x7b, 0x51, 0x39, 0xd7, 0xfd, 0x18, 0xde, 0xa6, 0xd7, + 0xe1, 0xd7, 0x67, 0x4e, 0xa1, 0x3c, 0xdd, 0x93, 0x8a, 0x92, 0x2e, 0xb4, + 0x5b, 0xe6, 0x9b, 0xdd, 0xfd, 0x93, 0xaf, 0x03, 0xf6, 0x9d, 0x7b, 0xd9, + 0xf4, 0xeb, 0xfa, 0x37, 0xd7, 0xce, 0x41, 0xd7, 0x83, 0xfb, 0x4e, 0xbe, + 0x08, 0xc4, 0x8e, 0xa4, 0x37, 0xae, 0x3b, 0x41, 0x47, 0x1e, 0xe3, 0xc8, + 0x3a, 0xb1, 0xde, 0xb6, 0x5f, 0xe4, 0x99, 0xc5, 0x37, 0xd1, 0xd7, 0x63, + 0x4e, 0xbf, 0xb8, 0x9b, 0x70, 0x74, 0x75, 0xfd, 0xbf, 0xb3, 0xbf, 0xb1, + 0x9d, 0x7f, 0x73, 0x3b, 0xdf, 0xfc, 0x75, 0xfb, 0xa3, 0x19, 0xc3, 0x2f, + 0xec, 0xe4, 0xff, 0xb8, 0x4d, 0x10, 0x6a, 0xa6, 0x96, 0xdc, 0x9d, 0x13, + 0xf2, 0x53, 0xa8, 0x47, 0xda, 0x43, 0x46, 0xfc, 0xed, 0x45, 0xc1, 0xd7, + 0xf4, 0xba, 0x2f, 0xbf, 0x8e, 0xa6, 0x9e, 0x90, 0x92, 0xdf, 0x7d, 0x17, + 0x9c, 0xea, 0xc3, 0xc4, 0xd1, 0x0d, 0xfa, 0x3d, 0xf1, 0x6c, 0x9d, 0x7f, + 0xa4, 0x8b, 0x8e, 0xfd, 0x09, 0xd7, 0xff, 0xa3, 0x07, 0x7f, 0x67, 0x12, + 0x77, 0x59, 0xd7, 0xe7, 0x67, 0xd9, 0xdd, 0x1f, 0xe7, 0x8d, 0x2b, 0xe2, + 0xb3, 0x16, 0x2c, 0xca, 0x05, 0x65, 0x19, 0x46, 0x42, 0xf3, 0x84, 0x23, + 0x0a, 0x6b, 0xda, 0xc9, 0x1d, 0x7e, 0x40, 0x76, 0x02, 0x75, 0xf9, 0x37, + 0x92, 0x09, 0xd7, 0x93, 0xb8, 0x75, 0xd0, 0xbc, 0x3c, 0x06, 0x93, 0x5f, + 0xcc, 0xe2, 0xe3, 0x8a, 0x1d, 0x7c, 0x1d, 0x76, 0x0e, 0xbf, 0x0f, 0x19, + 0x79, 0xce, 0xa8, 0x3f, 0x7c, 0x2e, 0x72, 0x1b, 0xbf, 0x13, 0xaa, 0x13, + 0x66, 0xc1, 0xb4, 0x66, 0xe4, 0x28, 0xf4, 0x59, 0x7b, 0xb8, 0x27, 0x5e, + 0x7f, 0x41, 0xd7, 0xfa, 0x68, 0x9d, 0x6f, 0x34, 0x1d, 0x7f, 0xfc, 0xea, + 0x7a, 0x38, 0x0e, 0x47, 0x85, 0xc0, 0x75, 0xfc, 0x38, 0x0c, 0x19, 0x1d, + 0x7f, 0xfc, 0xa7, 0xcf, 0xa2, 0xfe, 0xd2, 0x6f, 0xd4, 0x64, 0xeb, 0x0e, + 0x1f, 0xfb, 0x95, 0x56, 0x26, 0xb5, 0xc1, 0xa7, 0x1a, 0x13, 0x4f, 0xe1, + 0x9b, 0x76, 0xb6, 0x9d, 0x7c, 0x82, 0xe1, 0x3a, 0xff, 0xcb, 0xcf, 0x6b, + 0xee, 0x9e, 0x58, 0x75, 0xfb, 0x51, 0xcf, 0x41, 0xca, 0x9b, 0xfa, 0x0a, + 0x25, 0x74, 0xbd, 0x7e, 0xfb, 0x33, 0xbf, 0x0e, 0xbe, 0xee, 0x26, 0xd3, + 0xaf, 0xed, 0x27, 0x33, 0xfe, 0x1d, 0x7f, 0xff, 0xa2, 0x6f, 0x88, 0xdf, + 0xf9, 0xaf, 0xfe, 0x2d, 0x3d, 0xd4, 0x3a, 0xb1, 0x3a, 0xf4, 0x85, 0x6a, + 0xc8, 0xfa, 0x53, 0xe2, 0x2d, 0x82, 0xdb, 0x96, 0xc0, 0x34, 0x5f, 0x97, + 0xda, 0xe6, 0x61, 0xd7, 0xff, 0x4b, 0xdf, 0xca, 0x4b, 0xf7, 0xa1, 0x67, + 0x5f, 0xef, 0x6a, 0x27, 0xcd, 0x04, 0xeb, 0xbb, 0x87, 0x5f, 0xff, 0x76, + 0x03, 0x8d, 0xf9, 0x83, 0x81, 0xec, 0x1d, 0x7f, 0xf2, 0x60, 0xe6, 0x6b, + 0xe4, 0xb4, 0xb3, 0xaf, 0xfc, 0xf1, 0xbc, 0xbe, 0x6b, 0x70, 0xc1, 0xd4, + 0x14, 0xe0, 0x37, 0x20, 0x44, 0x66, 0x33, 0x39, 0x85, 0x74, 0x9d, 0xe4, + 0x3b, 0xca, 0x47, 0x0e, 0xbf, 0x83, 0x00, 0xe6, 0x6e, 0x75, 0x2a, 0x79, + 0x2b, 0x1c, 0xbf, 0xd0, 0xbc, 0x4e, 0x4d, 0x23, 0xae, 0x49, 0x8e, 0xbf, + 0xfd, 0xe8, 0xe8, 0xbc, 0xf1, 0xce, 0x3c, 0x8e, 0xbd, 0xe4, 0x9c, 0xeb, + 0xf0, 0x1f, 0x78, 0x98, 0xeb, 0xc3, 0x0d, 0x3a, 0xff, 0xe0, 0xa4, 0xdd, + 0x8e, 0x6f, 0x28, 0xe1, 0xd7, 0xff, 0x90, 0x5f, 0x7d, 0x6b, 0x38, 0x1e, + 0xe1, 0xd5, 0xf1, 0x34, 0x94, 0x16, 0x5a, 0x43, 0x8e, 0x09, 0x46, 0x86, + 0xb6, 0x11, 0x6d, 0x07, 0x5e, 0xea, 0x78, 0xeb, 0x6d, 0xc3, 0x55, 0xf4, + 0x3e, 0xa1, 0x74, 0x40, 0x2b, 0xd9, 0x1d, 0x3a, 0x42, 0xcb, 0xa4, 0x6f, + 0x1b, 0xd8, 0x21, 0x23, 0x79, 0x6f, 0xf4, 0xeb, 0xfe, 0xc1, 0x90, 0xe2, + 0xe1, 0xa7, 0x5f, 0xba, 0x9b, 0x70, 0x27, 0x5f, 0xf8, 0x30, 0x38, 0x3f, + 0xcb, 0x34, 0x75, 0xf9, 0xd6, 0x9b, 0x18, 0x75, 0xef, 0x46, 0xe7, 0x56, + 0x1e, 0x23, 0x94, 0x5e, 0x84, 0x98, 0xeb, 0xc2, 0xc4, 0x6c, 0x1d, 0x7e, + 0xc9, 0xd7, 0x1a, 0x3a, 0xff, 0xff, 0xd1, 0xd4, 0x5a, 0xb3, 0x49, 0xf9, + 0xf7, 0xa9, 0xbe, 0x9a, 0x93, 0x9d, 0x53, 0xa7, 0xe0, 0x11, 0xd5, 0x0d, + 0x50, 0xa2, 0x68, 0x40, 0x74, 0x80, 0x46, 0xf4, 0x47, 0xb0, 0x4f, 0x7d, + 0xf1, 0xe4, 0xc5, 0x1d, 0x7f, 0xf6, 0x6d, 0xc0, 0xe0, 0xff, 0x2c, 0xd1, + 0xd7, 0xee, 0x47, 0x7e, 0x84, 0xea, 0xe1, 0xf6, 0xba, 0x25, 0xf4, 0x24, + 0xf0, 0x75, 0xf3, 0x2f, 0x9a, 0x3a, 0xfe, 0x0c, 0x00, 0x73, 0x73, 0xaf, + 0xfa, 0x4b, 0x79, 0x7b, 0x50, 0xa1, 0xd5, 0x08, 0x86, 0xc2, 0x17, 0x2c, + 0xbd, 0xa4, 0x13, 0xaf, 0xc2, 0xdf, 0x9a, 0xdc, 0xea, 0xc3, 0xc4, 0x71, + 0xaa, 0x63, 0x4f, 0xb5, 0xe1, 0x2a, 0x02, 0x11, 0x85, 0x37, 0xee, 0x37, + 0x4f, 0x23, 0xaf, 0x27, 0x50, 0xea, 0xdc, 0xd8, 0xf8, 0x5e, 0xfb, 0xef, + 0xef, 0xa3, 0xaf, 0xf9, 0x14, 0x80, 0xc6, 0xdc, 0xe9, 0xd7, 0xf7, 0xfa, + 0x89, 0xbf, 0xe1, 0xd7, 0xbf, 0xcd, 0xce, 0xae, 0x9e, 0x6f, 0x8c, 0x2f, + 0xf4, 0xbf, 0x19, 0xf4, 0x9b, 0x9d, 0x7c, 0x00, 0x66, 0xe7, 0x5f, 0xdb, + 0x1e, 0xc7, 0x16, 0x9d, 0x7f, 0xdf, 0xbc, 0x83, 0x98, 0x0d, 0x1d, 0x7f, + 0x80, 0x9b, 0xef, 0x2c, 0xf1, 0xd5, 0xd3, 0xec, 0xd1, 0xc5, 0xfb, 0x7d, + 0x2d, 0x18, 0xce, 0xbf, 0xff, 0x66, 0xbe, 0x75, 0xd3, 0xc0, 0xfc, 0x45, + 0xe4, 0x75, 0x42, 0x20, 0x04, 0xae, 0xfe, 0x79, 0xc0, 0xe2, 0x13, 0xaa, + 0x75, 0x51, 0x0d, 0x84, 0x34, 0xc4, 0x5c, 0x35, 0xe9, 0x17, 0xa1, 0x35, + 0xb6, 0x14, 0x5b, 0x24, 0x37, 0xfb, 0xec, 0x37, 0x67, 0x39, 0x07, 0x5f, + 0xf0, 0x73, 0xfe, 0x4e, 0xd4, 0x9c, 0xeb, 0xfa, 0x3a, 0x9c, 0x85, 0x9d, + 0x5d, 0x44, 0xe3, 0x9b, 0x78, 0xee, 0xa1, 0x70, 0x03, 0x25, 0x56, 0x3c, + 0x64, 0xb7, 0x4d, 0xf9, 0xd6, 0x59, 0xd5, 0xb9, 0xa8, 0x60, 0x8c, 0x5f, + 0xfd, 0x1c, 0xcd, 0xaf, 0x20, 0x66, 0x04, 0xeb, 0xf9, 0xf7, 0x90, 0xc0, + 0x4e, 0xbf, 0xe8, 0xde, 0x48, 0x2b, 0x7f, 0x1d, 0x4e, 0x7c, 0x62, 0x59, + 0x7e, 0x79, 0x64, 0xf0, 0x75, 0xff, 0xd1, 0xad, 0x62, 0xfc, 0x30, 0xbd, + 0x1d, 0x7f, 0xf2, 0x46, 0x85, 0xe5, 0xf3, 0x59, 0xc3, 0xaf, 0xff, 0xf2, + 0x6a, 0x7c, 0x67, 0x07, 0xfd, 0x88, 0x57, 0x05, 0xf8, 0x75, 0xfe, 0xde, + 0x5a, 0x9a, 0x51, 0x39, 0xd4, 0x14, 0xd1, 0x1a, 0x4c, 0x28, 0x5e, 0x43, + 0xfd, 0x8e, 0xff, 0xff, 0xdd, 0x4d, 0xfd, 0x9b, 0xfb, 0x9c, 0x8f, 0x03, + 0xe8, 0xcb, 0xb8, 0x75, 0xe0, 0xb8, 0x9d, 0x7b, 0x91, 0xb4, 0xea, 0x09, + 0xb7, 0xe0, 0xd5, 0xff, 0xa5, 0x03, 0xee, 0x26, 0xdc, 0x09, 0xd7, 0xfe, + 0x7f, 0x6b, 0xf9, 0x7d, 0x0a, 0x78, 0xeb, 0xff, 0x3f, 0x5a, 0x8f, 0xf3, + 0x4f, 0xd3, 0xaf, 0xee, 0xb8, 0xef, 0x24, 0x3a, 0xff, 0xfd, 0xa1, 0xf9, + 0xd7, 0x4f, 0x03, 0xf1, 0x17, 0x91, 0xd7, 0xfb, 0xa8, 0xa6, 0xcf, 0xfc, + 0x50, 0xeb, 0xfe, 0x86, 0x57, 0xd8, 0x41, 0x9c, 0xeb, 0xff, 0xe1, 0xcd, + 0x62, 0xe1, 0xb9, 0xe4, 0xe6, 0x1d, 0x6c, 0x6a, 0x2f, 0x3c, 0x73, 0xb4, + 0xe2, 0xfe, 0x9f, 0x38, 0x8d, 0x83, 0xaf, 0x84, 0x30, 0xb3, 0xaf, 0xff, + 0xbf, 0x1f, 0x6b, 0xa9, 0x30, 0xc2, 0xde, 0x47, 0x5f, 0x60, 0xfe, 0xe7, + 0x52, 0xcf, 0xbf, 0x6a, 0x7d, 0xfc, 0xe0, 0xc0, 0xbc, 0x8e, 0xa8, 0x46, + 0xf6, 0x42, 0x3d, 0x09, 0x29, 0x13, 0x3c, 0xec, 0x61, 0x55, 0x0b, 0xdb, + 0x13, 0x93, 0x06, 0x14, 0xd9, 0x1b, 0x23, 0x52, 0xd2, 0x14, 0xd3, 0x10, + 0xac, 0xfb, 0xa8, 0x2e, 0x7c, 0x02, 0xc1, 0x8c, 0x47, 0xd1, 0xb9, 0xdf, + 0xfd, 0x82, 0x0c, 0xce, 0x6b, 0xd1, 0x87, 0x5f, 0xf6, 0xfe, 0xce, 0x24, + 0xee, 0xb3, 0xad, 0x80, 0x3f, 0x91, 0x40, 0xbc, 0xc1, 0x92, 0x1d, 0x7d, + 0x02, 0xf2, 0x3a, 0xfd, 0x8c, 0x6e, 0x20, 0xf8, 0x6f, 0xb8, 0x3f, 0x7f, + 0x6d, 0xea, 0x47, 0x34, 0x75, 0xff, 0xba, 0x8b, 0x0e, 0x4d, 0x19, 0xc3, + 0xaf, 0x4a, 0x37, 0x3a, 0xfa, 0x00, 0xeb, 0x3a, 0xe1, 0x96, 0x1f, 0xcc, + 0xc7, 0xa2, 0x39, 0x7d, 0xa4, 0xf4, 0x1d, 0x50, 0x7b, 0x2e, 0x73, 0x7c, + 0xde, 0xa4, 0xc7, 0x5f, 0xff, 0x87, 0x14, 0x51, 0x03, 0xd4, 0x9b, 0xa9, + 0xbf, 0x8e, 0xa8, 0x3f, 0x9c, 0x22, 0xbc, 0xd7, 0xe1, 0xd7, 0xed, 0x36, + 0x38, 0xa1, 0xd5, 0xd3, 0xc3, 0x00, 0xdd, 0xfe, 0xc9, 0x62, 0x07, 0xa8, + 0x75, 0xff, 0xd9, 0xbf, 0xb4, 0x83, 0x00, 0x75, 0x9d, 0x7a, 0x4b, 0xe9, + 0xd5, 0x39, 0xef, 0x79, 0x0a, 0xf9, 0x14, 0x46, 0x4e, 0xac, 0x3c, 0x51, + 0x23, 0xbb, 0xe6, 0x1d, 0x7d, 0xa1, 0x85, 0x9d, 0x50, 0x6d, 0xf7, 0x17, + 0xbd, 0xd9, 0x2c, 0xeb, 0xba, 0x87, 0x56, 0x1b, 0x1f, 0x0e, 0x54, 0x2e, + 0x2f, 0xc9, 0x93, 0x10, 0x54, 0x8c, 0x03, 0xb0, 0x99, 0x76, 0x31, 0x22, + 0xd4, 0x34, 0xff, 0x57, 0xd9, 0x52, 0xbc, 0x15, 0xb4, 0xeb, 0x74, 0xeb, + 0x00, 0xeb, 0xb5, 0x23, 0xa8, 0x06, 0xdb, 0x42, 0x1f, 0x88, 0x5f, 0xd3, + 0xcd, 0x26, 0x17, 0x27, 0x3a, 0xf3, 0xe7, 0x0e, 0xbc, 0x39, 0xe3, 0xab, + 0xa6, 0xd0, 0x46, 0xae, 0xf0, 0x9d, 0x7a, 0x37, 0xd1, 0xd7, 0xc8, 0x32, + 0xc3, 0xaf, 0x4e, 0xe2, 0x75, 0x04, 0xf5, 0x96, 0x39, 0xe1, 0xfb, 0xf6, + 0x7b, 0xa9, 0xe3, 0xaf, 0xcf, 0xbe, 0x6f, 0xe3, 0xac, 0xa7, 0x4f, 0x3b, + 0xc4, 0xd7, 0x27, 0x0e, 0xbf, 0xa7, 0xf9, 0x3b, 0xbf, 0x4e, 0xa6, 0x21, + 0x3d, 0xf8, 0x69, 0x91, 0x06, 0x35, 0xa3, 0xef, 0x4a, 0x5c, 0x56, 0xff, + 0xb0, 0x21, 0x4d, 0xf3, 0x7f, 0x1d, 0x7c, 0xd1, 0x89, 0x1d, 0x5d, 0x3d, + 0x97, 0x39, 0xbf, 0xd1, 0x9e, 0x8e, 0xb8, 0x4e, 0xa9, 0xcf, 0x44, 0x24, + 0x37, 0xff, 0x06, 0x03, 0xc8, 0xf2, 0x35, 0x02, 0x75, 0xf4, 0xd1, 0xb1, + 0x23, 0xaf, 0xef, 0x34, 0x21, 0x5f, 0x0e, 0xbf, 0xe9, 0xb5, 0xb5, 0xc6, + 0x7f, 0xc2, 0x75, 0xf6, 0x7b, 0x16, 0x75, 0xc2, 0xa1, 0xd6, 0xd3, 0x9b, + 0x6f, 0xc8, 0x2f, 0xee, 0xff, 0x3c, 0xdd, 0x43, 0xaf, 0x84, 0x73, 0xc7, + 0x54, 0x27, 0x42, 0x12, 0x3c, 0x42, 0x50, 0x95, 0x0b, 0xa6, 0x73, 0xe9, + 0x3f, 0x8c, 0x2f, 0xef, 0x93, 0x47, 0x87, 0x69, 0xd7, 0xff, 0x86, 0x36, + 0xf2, 0x39, 0x89, 0xd8, 0x09, 0xd7, 0x85, 0xd6, 0x75, 0x49, 0x12, 0x78, + 0x62, 0x89, 0x16, 0x55, 0x88, 0x7c, 0x33, 0xc6, 0x2c, 0xf1, 0x87, 0x8e, + 0x31, 0x21, 0xb8, 0x95, 0xa1, 0x3c, 0x3b, 0xe5, 0x0d, 0x80, 0xce, 0x22, + 0xe4, 0xf3, 0xca, 0x91, 0xb0, 0xb6, 0x5a, 0xee, 0xf2, 0x91, 0xd2, 0x31, + 0x39, 0xa5, 0xbd, 0xf2, 0x3e, 0x05, 0xc7, 0x4f, 0xd9, 0xf0, 0xd7, 0x94, + 0xd2, 0x09, 0x4e, 0xac, 0x18, 0x44, 0x0c, 0xe1, 0x16, 0xa7, 0xcf, 0x7d, + 0x3b, 0x4d, 0xfc, 0x27, 0xd9, 0x52, 0xd9, 0x94, 0x1d, 0xf6, 0x55, 0x8e, + 0xc4, 0x60, 0x94, 0xab, 0xe2, 0xe6, 0x76, 0xf0, 0xe3, 0x2f, 0xff, 0x2a, + 0xb7, 0x92, 0xb9, 0xc6, 0xbb, 0xb4, 0xd1, 0x36, 0x5f, 0xe5, 0x73, 0x8d, + 0x77, 0x69, 0xa2, 0xad, 0xbf, 0xd2, 0x97, 0xfe, 0x18, 0x91, 0xd7, 0xd9, + 0xd7, 0xf1, 0xd6, 0x60, 0x61, 0xe9, 0x89, 0x9d, 0xff, 0x60, 0xe2, 0xe2, + 0x5f, 0xf0, 0xeb, 0xfd, 0xcc, 0x6c, 0x03, 0xea, 0xce, 0xbf, 0xe8, 0xec, + 0x4f, 0xc8, 0xc0, 0x9d, 0x4d, 0x45, 0x17, 0x0d, 0xfa, 0x69, 0x7e, 0x8e, + 0x2f, 0xa1, 0x3a, 0xf0, 0x70, 0x4e, 0xbc, 0xee, 0xd3, 0x45, 0x69, 0x7e, + 0x53, 0x7d, 0x7f, 0xb9, 0xd4, 0xd3, 0xd3, 0x42, 0x7b, 0xff, 0xc9, 0xe9, + 0x43, 0x7a, 0x9e, 0xd3, 0xee, 0x75, 0x70, 0xfa, 0xb6, 0x90, 0xdf, 0xfe, + 0xea, 0x2e, 0x1b, 0x8b, 0xc1, 0xf6, 0xc9, 0xd7, 0xff, 0xcd, 0x8e, 0x60, + 0x1d, 0x6f, 0x28, 0x46, 0x9d, 0x7f, 0xfd, 0x2d, 0x60, 0xc2, 0xdf, 0x3d, + 0xe8, 0x59, 0xd7, 0x7b, 0xd0, 0x89, 0x87, 0x4c, 0xbf, 0xff, 0xfd, 0x1b, + 0x53, 0xda, 0xc5, 0x1b, 0xd4, 0xf6, 0x4c, 0x30, 0xb9, 0xf1, 0x93, 0xaf, + 0xf4, 0x79, 0xfb, 0xf0, 0x30, 0x75, 0xf4, 0xbc, 0x93, 0x9d, 0x7e, 0xfb, + 0xe1, 0x80, 0x1d, 0x5b, 0x9e, 0x56, 0xd2, 0x2b, 0xfc, 0xf2, 0xf2, 0x4f, + 0xd4, 0x3a, 0xa0, 0xf5, 0xd0, 0x96, 0xfd, 0x9d, 0x4c, 0x59, 0xd7, 0xff, + 0x0b, 0xa3, 0x7a, 0xff, 0xcf, 0xc4, 0x3a, 0xa7, 0x3e, 0x8e, 0x92, 0xdf, + 0xe9, 0x47, 0x27, 0x8e, 0x4e, 0x75, 0xf4, 0xb9, 0x8b, 0x3a, 0xf6, 0x70, + 0x07, 0x5f, 0xa6, 0xc0, 0xad, 0x8c, 0xeb, 0xf8, 0x61, 0x9d, 0xe5, 0xa3, + 0xab, 0x74, 0x4a, 0xa1, 0x0c, 0xc3, 0x7b, 0x05, 0x75, 0x09, 0x85, 0x64, + 0x32, 0x6f, 0xff, 0xff, 0xec, 0x46, 0xe7, 0xa0, 0x7d, 0xaf, 0x90, 0x81, + 0xc5, 0xfc, 0xe4, 0x24, 0x9f, 0x47, 0x5f, 0xd9, 0xe7, 0x10, 0x7e, 0x75, + 0xfd, 0xdf, 0x89, 0x3b, 0x89, 0xd7, 0xfa, 0x17, 0xa0, 0x8b, 0xb2, 0x75, + 0x49, 0x11, 0x98, 0x58, 0x25, 0xd6, 0x55, 0x84, 0xbf, 0x31, 0x10, 0xcc, + 0x9c, 0xc0, 0x24, 0xf9, 0x0d, 0x76, 0x92, 0x24, 0x38, 0xb8, 0x5a, 0xb7, + 0xae, 0xc3, 0x51, 0xe1, 0x10, 0x31, 0x96, 0xe8, 0x9f, 0xd1, 0x89, 0xdf, + 0xb8, 0xd7, 0x76, 0x9a, 0x2c, 0x0b, 0xf3, 0xb7, 0xef, 0x66, 0x3a, 0xca, + 0xe1, 0xee, 0xe8, 0xce, 0xfd, 0xc6, 0xbb, 0xb4, 0xd1, 0x3a, 0xdf, 0xff, + 0xee, 0xc4, 0xe1, 0xc5, 0xab, 0xad, 0x67, 0x53, 0x5f, 0xce, 0x75, 0xf9, + 0x55, 0xbc, 0x95, 0xc4, 0x4b, 0xcc, 0x67, 0x79, 0x48, 0x59, 0xd7, 0xce, + 0xdf, 0xab, 0x3a, 0xf4, 0xb4, 0xaa, 0x86, 0xff, 0x68, 0xe5, 0xfb, 0x8d, + 0x77, 0x69, 0xa2, 0xd9, 0xbf, 0xbc, 0xfd, 0xf8, 0x18, 0x3a, 0xff, 0xfe, + 0x92, 0xba, 0x84, 0xc0, 0xa6, 0x6b, 0x3c, 0x30, 0x75, 0x42, 0x21, 0x5c, + 0xba, 0xff, 0xc0, 0x8d, 0x2b, 0xd4, 0x6b, 0xf0, 0xeb, 0xfe, 0x89, 0x47, + 0x27, 0x8e, 0x4e, 0x75, 0x95, 0xc4, 0xd4, 0x17, 0x0b, 0x87, 0x21, 0x13, + 0xeb, 0xff, 0x0a, 0xab, 0xfd, 0x3c, 0x2f, 0xb0, 0x75, 0xff, 0xdf, 0xe9, + 0x5c, 0xe3, 0xeb, 0xaf, 0x23, 0xae, 0x70, 0x62, 0x21, 0x80, 0x83, 0x7c, + 0xd7, 0x76, 0x9a, 0x2e, 0x6b, 0x2c, 0xea, 0xe1, 0xbd, 0x64, 0xb6, 0xff, + 0x70, 0x73, 0x70, 0x24, 0x8e, 0xba, 0x65, 0x9d, 0x47, 0x59, 0x5c, 0x3f, + 0x54, 0x22, 0x64, 0xcb, 0x64, 0x5e, 0xfd, 0xc6, 0xbb, 0xb4, 0xd1, 0x77, + 0xdf, 0xe9, 0x2b, 0xae, 0x71, 0x19, 0x3a, 0xca, 0xe1, 0xf4, 0x39, 0x9d, + 0xf2, 0xaa, 0x04, 0x07, 0x54, 0x3e, 0xab, 0x36, 0x5e, 0x2f, 0xc3, 0x4d, + 0xf7, 0x57, 0x4a, 0x41, 0x57, 0x23, 0x4b, 0x5c, 0x2f, 0xde, 0x10, 0x20, + 0x8e, 0x1c, 0x61, 0x9b, 0xa8, 0x6f, 0xfa, 0x15, 0xbf, 0x49, 0xef, 0xfc, + 0xcb, 0x8c, 0xfa, 0x41, 0xde, 0x47, 0x5f, 0xfd, 0x93, 0xe3, 0x3d, 0xcd, + 0x62, 0x09, 0xd7, 0x22, 0xbd, 0x44, 0x08, 0x9f, 0xdf, 0xb5, 0xa5, 0xbc, + 0x8e, 0xbf, 0xff, 0xff, 0xf7, 0x53, 0xa9, 0x03, 0xe1, 0x75, 0x33, 0xdf, + 0xf9, 0x3d, 0xae, 0xa7, 0x22, 0x77, 0xe3, 0x4e, 0xbb, 0x50, 0x75, 0xff, + 0xdb, 0xb7, 0xf7, 0xdf, 0xd9, 0x82, 0xa1, 0xd7, 0x85, 0xd5, 0x84, 0xc6, + 0x9a, 0x4f, 0xa8, 0x4c, 0x78, 0x56, 0xf7, 0xee, 0xb3, 0xaf, 0xd9, 0xb1, + 0xe8, 0x50, 0xeb, 0x6c, 0x1d, 0x53, 0x9b, 0xdc, 0x2a, 0xae, 0x1f, 0xd0, + 0xac, 0xdf, 0xfb, 0x4e, 0xa7, 0x52, 0x07, 0xf8, 0x3a, 0xff, 0xdd, 0x7f, + 0x3f, 0x77, 0x96, 0x78, 0xea, 0xc3, 0xfb, 0x43, 0xdb, 0x9c, 0x07, 0x5f, + 0xff, 0xfe, 0x17, 0x64, 0x73, 0xde, 0xc9, 0xe0, 0x5d, 0x4d, 0x2e, 0x30, + 0x42, 0x75, 0xec, 0xfb, 0xa3, 0xab, 0x11, 0x4d, 0xc1, 0x5d, 0x87, 0x4b, + 0xfd, 0xdc, 0x0a, 0x6d, 0xe6, 0x1d, 0x79, 0xdd, 0xa6, 0x89, 0x5e, 0xff, + 0x28, 0xe2, 0x0f, 0x67, 0x4e, 0xa6, 0x9e, 0xca, 0x13, 0xdf, 0xfe, 0xf7, + 0x72, 0x4d, 0xea, 0x06, 0x07, 0xc7, 0x54, 0x91, 0xeb, 0xc8, 0x46, 0x09, + 0x0d, 0xff, 0xff, 0xf7, 0x1c, 0x7e, 0xc0, 0x32, 0x5d, 0x8d, 0xa1, 0x85, + 0x70, 0x7f, 0x96, 0x68, 0xeb, 0xa5, 0x39, 0xd7, 0xff, 0xf9, 0xf7, 0xd6, + 0x73, 0xde, 0x79, 0xfe, 0xac, 0x3d, 0x45, 0x0e, 0xbf, 0xbf, 0xdf, 0xdd, + 0x80, 0x1d, 0x7f, 0xe1, 0x76, 0x43, 0xd8, 0x9f, 0x19, 0x3a, 0xff, 0xfd, + 0x88, 0x0c, 0x5a, 0x7b, 0x50, 0xb7, 0xdf, 0xc7, 0x5f, 0xf4, 0x2f, 0xd9, + 0x34, 0x93, 0xc7, 0x54, 0x91, 0x17, 0xe5, 0x3b, 0xef, 0xdf, 0x92, 0x3a, + 0xff, 0xa1, 0xa3, 0x13, 0x81, 0xfc, 0x75, 0xff, 0xfe, 0x4f, 0x3a, 0xdc, + 0x41, 0xd6, 0x5c, 0x67, 0x6a, 0x4e, 0x75, 0x05, 0x17, 0x28, 0x44, 0xe6, + 0xf7, 0xfd, 0xf8, 0x16, 0xf2, 0xd7, 0x02, 0x75, 0xff, 0xfe, 0xc4, 0x1f, + 0x60, 0xfc, 0x17, 0x0c, 0x0c, 0xf1, 0xc3, 0xad, 0x9e, 0x44, 0xbe, 0xd3, + 0xab, 0xfe, 0xdc, 0x19, 0xcc, 0xcf, 0x68, 0xea, 0x0a, 0xac, 0xdc, 0x86, + 0x57, 0x61, 0xb8, 0x30, 0xc5, 0xfa, 0x55, 0x7f, 0xd9, 0xbe, 0x83, 0x0e, + 0x33, 0x9d, 0x7f, 0xcf, 0x2d, 0x76, 0x39, 0xf4, 0x27, 0x56, 0x1f, 0x97, + 0x8e, 0x2f, 0xfe, 0xf2, 0x6d, 0x4f, 0x4d, 0x28, 0x1f, 0x1d, 0x7f, 0xf9, + 0xf2, 0x5d, 0xc4, 0x1c, 0x06, 0xce, 0x1d, 0x79, 0xe4, 0xac, 0x32, 0x0b, + 0xe5, 0x09, 0xc0, 0xc3, 0x1b, 0x23, 0x27, 0xe1, 0xa2, 0xdf, 0xc0, 0x2e, + 0x2c, 0xba, 0x95, 0xf9, 0xe8, 0x66, 0xfd, 0x21, 0xd8, 0x45, 0xbf, 0xfd, + 0x9d, 0x54, 0x70, 0x28, 0x3e, 0xce, 0x9d, 0x7b, 0xd0, 0x12, 0xaf, 0xff, + 0x75, 0xd3, 0xd1, 0x24, 0xe4, 0xff, 0x80, 0xab, 0xfc, 0xed, 0x54, 0x3c, + 0x60, 0xab, 0x07, 0xcb, 0xa1, 0xbb, 0x2a, 0x16, 0x60, 0xcb, 0x63, 0x48, + 0x5d, 0x23, 0xf3, 0xd0, 0xd9, 0xdb, 0x0a, 0xcb, 0xff, 0xca, 0xad, 0xe4, + 0xae, 0x71, 0xae, 0xed, 0x34, 0x4c, 0x37, 0xff, 0xf6, 0x6d, 0x70, 0xf6, + 0x15, 0xf7, 0x70, 0x3f, 0xfb, 0x47, 0x5f, 0xfe, 0xe3, 0x81, 0x55, 0x3d, + 0x26, 0x63, 0x52, 0x3a, 0xec, 0x54, 0x51, 0x57, 0xf5, 0x7a, 0xe5, 0xed, + 0x3a, 0xff, 0xe6, 0x06, 0x6f, 0x2f, 0xdf, 0xc3, 0x12, 0x3a, 0xfd, 0x8b, + 0xf9, 0xbb, 0x19, 0xd7, 0xf4, 0x2f, 0x01, 0x1b, 0x4e, 0xa0, 0x9e, 0xd7, + 0x4b, 0x6f, 0xf7, 0x31, 0xb0, 0x0f, 0xab, 0x3a, 0xfd, 0xd8, 0x0a, 0x28, + 0x75, 0x21, 0xfe, 0xf0, 0x8b, 0x60, 0xd2, 0xff, 0x43, 0xcf, 0xe5, 0x1f, + 0x87, 0x5f, 0x9f, 0x92, 0x75, 0x9d, 0x42, 0x7b, 0x3f, 0x99, 0xdf, 0xed, + 0x46, 0x08, 0x7b, 0x07, 0x5f, 0xd1, 0x82, 0x1e, 0xc1, 0xd7, 0xbf, 0xe4, + 0xdf, 0x0f, 0x6b, 0x46, 0x17, 0xff, 0xb8, 0x9f, 0xe2, 0x99, 0xef, 0xe3, + 0x70, 0x9d, 0x7f, 0xfe, 0x4e, 0x75, 0xfe, 0x07, 0x25, 0xd8, 0xda, 0x18, + 0x3a, 0xff, 0x99, 0xfb, 0xd8, 0x6f, 0x52, 0x63, 0xaf, 0xbf, 0x5e, 0x04, + 0xeb, 0x66, 0xe7, 0xbd, 0xb0, 0x79, 0x7f, 0x47, 0x22, 0x5a, 0xc3, 0xa9, + 0xa9, 0xc7, 0xf0, 0xe3, 0xa9, 0x83, 0x0b, 0x5f, 0x15, 0xdf, 0xcb, 0x8c, + 0x1f, 0x6c, 0x9d, 0x6d, 0x1d, 0x7e, 0x8c, 0x1f, 0x6c, 0x9d, 0x7f, 0x75, + 0x3d, 0xa7, 0xdf, 0xe1, 0xf3, 0x4c, 0x5c, 0xb1, 0x0b, 0xfd, 0x2f, 0x42, + 0xf6, 0x82, 0x47, 0x5f, 0xff, 0xe6, 0x76, 0x3d, 0x9d, 0xf8, 0x39, 0x3a, + 0x60, 0xef, 0x2d, 0x1d, 0x7e, 0x67, 0xd9, 0xd6, 0x9d, 0x61, 0xc4, 0x47, + 0x3b, 0x35, 0xff, 0xef, 0x0b, 0x83, 0xb8, 0x81, 0xff, 0xda, 0x3a, 0xff, + 0xa2, 0x7f, 0xb2, 0xef, 0xef, 0x39, 0xd5, 0x08, 0x86, 0xe2, 0x4d, 0xff, + 0xd9, 0xbc, 0xbe, 0x75, 0xdb, 0x02, 0x13, 0xaf, 0xed, 0xbf, 0x7c, 0x30, + 0x03, 0xaf, 0xff, 0x47, 0x81, 0x12, 0xcd, 0xfd, 0x3f, 0xec, 0x9d, 0x7b, + 0x4e, 0x03, 0xaa, 0x11, 0x30, 0x86, 0x1e, 0x4d, 0xbf, 0x9c, 0x1c, 0xe2, + 0x70, 0xeb, 0xde, 0xf9, 0x87, 0x50, 0x0f, 0x27, 0xe9, 0x65, 0xfd, 0xa4, + 0x51, 0x6f, 0xe3, 0xaf, 0xff, 0xfd, 0xcc, 0xdb, 0x03, 0xef, 0x9f, 0x46, + 0x3a, 0xe9, 0xe8, 0xf6, 0x8e, 0xbf, 0x87, 0x35, 0xf1, 0xac, 0x23, 0xab, + 0x74, 0x66, 0xf0, 0xb7, 0x6b, 0x75, 0xf7, 0xcd, 0xbb, 0x13, 0x9d, 0x58, + 0x7b, 0xaa, 0x19, 0xd9, 0x8c, 0xeb, 0xbd, 0x87, 0x5f, 0xfe, 0x60, 0x8c, + 0x2d, 0xd3, 0xaf, 0xee, 0xc1, 0xd5, 0x07, 0xbf, 0xf8, 0xad, 0xfe, 0xea, + 0x4c, 0xed, 0xd4, 0x8e, 0xbf, 0x87, 0xce, 0xb4, 0xf1, 0xd7, 0xfe, 0x4f, + 0x7f, 0xc7, 0xd7, 0xc5, 0xf8, 0xea, 0x83, 0xec, 0x72, 0xbb, 0xfe, 0xc4, + 0xc5, 0x8e, 0x4e, 0xe7, 0x5f, 0xa3, 0xda, 0x07, 0xe7, 0x53, 0x10, 0x9d, + 0x86, 0x39, 0x34, 0x8b, 0xb0, 0x9f, 0x12, 0x0f, 0x1a, 0xdf, 0xff, 0xba, + 0x39, 0xee, 0xa6, 0x6f, 0xec, 0xdb, 0x1a, 0x3a, 0xff, 0xe7, 0x1e, 0xc2, + 0x05, 0x35, 0x92, 0x3a, 0xf4, 0x03, 0xe9, 0xd7, 0xf6, 0x6d, 0xea, 0x02, + 0x63, 0xab, 0x11, 0xc2, 0xea, 0xa2, 0x81, 0xa1, 0xdb, 0xdf, 0x43, 0x87, + 0x5e, 0x60, 0xe9, 0x84, 0x75, 0x39, 0xe0, 0xe8, 0x76, 0xfb, 0xe2, 0xfe, + 0x34, 0xeb, 0xfc, 0x2e, 0xcc, 0x7b, 0x27, 0x3a, 0xfd, 0xbb, 0x33, 0x6a, + 0x0e, 0xb2, 0xac, 0x43, 0x34, 0xe9, 0x84, 0x31, 0x11, 0x8f, 0x86, 0x11, + 0x59, 0x28, 0x2d, 0xb0, 0xb5, 0xdd, 0x56, 0x68, 0x61, 0xf2, 0x15, 0x8b, + 0x22, 0xec, 0x37, 0x40, 0xee, 0x31, 0xa7, 0x6a, 0x3d, 0x2f, 0x46, 0x83, + 0xfb, 0xdb, 0x24, 0x3b, 0x24, 0xdf, 0x4c, 0xaf, 0xff, 0xb8, 0x9b, 0xcb, + 0x49, 0xee, 0xc7, 0x3d, 0x07, 0x5f, 0xb8, 0xd7, 0x76, 0x9a, 0x2a, 0xeb, + 0xdc, 0x85, 0x9d, 0x7f, 0xa3, 0x9e, 0x81, 0x80, 0x1d, 0x7f, 0xd2, 0x57, + 0x38, 0xd7, 0x76, 0x9a, 0x23, 0xcb, 0xfe, 0x89, 0x47, 0x27, 0x8e, 0x4e, + 0x75, 0xff, 0xa3, 0xc9, 0xfb, 0x07, 0x25, 0x3c, 0xc7, 0x5f, 0xf6, 0xed, + 0x4d, 0x75, 0x3c, 0x87, 0x59, 0x50, 0xa7, 0x8f, 0x89, 0xfc, 0x33, 0xe8, + 0xdb, 0x98, 0x0a, 0x2e, 0x8e, 0x7c, 0x89, 0x7e, 0xe3, 0x5d, 0xda, 0x68, + 0xb0, 0x6f, 0x29, 0x13, 0x9d, 0x7f, 0xff, 0x0f, 0xef, 0x3a, 0xf3, 0x67, + 0xfe, 0x67, 0x25, 0xf6, 0x47, 0x5f, 0xb0, 0x73, 0xda, 0x3a, 0xff, 0x71, + 0xd7, 0xf7, 0x8f, 0xb9, 0xd6, 0x57, 0x13, 0x0c, 0x50, 0xcd, 0xa3, 0xae, + 0xc5, 0xf4, 0x96, 0xff, 0x2b, 0x9c, 0x6b, 0xbb, 0x4d, 0x16, 0x55, 0xfb, + 0x8d, 0x77, 0x69, 0xa2, 0xd3, 0xbf, 0xe7, 0x0f, 0x5e, 0x6e, 0xa2, 0xce, + 0xb2, 0xb8, 0x7d, 0x6b, 0x33, 0xbf, 0x30, 0xf6, 0x26, 0xc4, 0x31, 0x0c, + 0x59, 0xd7, 0xfc, 0xc2, 0xea, 0x32, 0x17, 0x76, 0x9d, 0x7e, 0x61, 0xec, + 0x0d, 0x64, 0x1d, 0x7f, 0xbe, 0xaf, 0x3d, 0xa4, 0xd1, 0xd6, 0x43, 0xa9, + 0x84, 0x78, 0x7b, 0x26, 0x97, 0xff, 0xf2, 0x75, 0xc7, 0xd2, 0xce, 0x64, + 0x08, 0xe7, 0x8e, 0xbf, 0x6d, 0x70, 0xe2, 0xce, 0xbe, 0x5c, 0x6f, 0xa3, + 0xaf, 0xfe, 0x4c, 0x70, 0x44, 0xb9, 0x18, 0x27, 0x5f, 0x26, 0xde, 0xed, + 0x3a, 0xa4, 0x98, 0x1e, 0x2a, 0xcc, 0x50, 0x24, 0x5a, 0x3f, 0xbf, 0xcb, + 0xfa, 0xb0, 0x2d, 0x00, 0x75, 0xfb, 0xe7, 0x39, 0xff, 0x4e, 0xbf, 0x22, + 0x90, 0x2d, 0x3a, 0xb4, 0x7a, 0x3e, 0x2b, 0xa8, 0x45, 0x46, 0x42, 0x1a, + 0xff, 0xf8, 0x5b, 0xd4, 0xea, 0x72, 0x26, 0x67, 0x3a, 0x75, 0xff, 0x96, + 0xb7, 0x96, 0xcf, 0xfd, 0x4e, 0x1d, 0x7e, 0x7d, 0x7a, 0x02, 0x75, 0x41, + 0xf4, 0x7e, 0x85, 0x50, 0x8d, 0x9e, 0xc2, 0xde, 0xfa, 0x3e, 0xc7, 0x4e, + 0xbe, 0x6b, 0xbb, 0x4d, 0x16, 0xe5, 0xf4, 0xd0, 0x1c, 0x3a, 0xff, 0xd9, + 0xcc, 0x1f, 0x9d, 0xcd, 0xd9, 0x3a, 0xfc, 0x20, 0x7d, 0xf4, 0x75, 0x41, + 0xf3, 0xba, 0x05, 0x6e, 0x8f, 0x7e, 0x11, 0x39, 0x6e, 0xa1, 0x11, 0x7f, + 0x9c, 0x41, 0x30, 0xc2, 0xce, 0xbc, 0xb1, 0x43, 0xac, 0x27, 0x5f, 0xf7, + 0x7f, 0x7d, 0x66, 0x0a, 0x87, 0x5f, 0xb4, 0xfb, 0xb8, 0x4e, 0xb2, 0x04, + 0xf7, 0xfc, 0x71, 0x50, 0x8a, 0xfc, 0x1a, 0xeb, 0x75, 0xff, 0x43, 0x8f, + 0x73, 0x05, 0xa7, 0x5f, 0xef, 0x79, 0x27, 0x5c, 0x09, 0xd5, 0x23, 0xe6, + 0xc3, 0x4b, 0xfe, 0x81, 0xfd, 0x71, 0xaf, 0x21, 0xd7, 0xa3, 0x38, 0x75, + 0xfe, 0xec, 0x49, 0x36, 0x71, 0x67, 0x50, 0x4f, 0x3b, 0x43, 0x57, 0xef, + 0x9b, 0xe9, 0x14, 0x3a, 0xcf, 0x39, 0xe6, 0xee, 0x45, 0x7f, 0xf4, 0xb3, + 0xa9, 0xc0, 0xf6, 0x05, 0xa7, 0x5f, 0xed, 0xe5, 0x03, 0xec, 0x01, 0xd7, + 0xda, 0x02, 0x78, 0xea, 0x74, 0x5f, 0x68, 0xa7, 0xf4, 0x2f, 0xa6, 0x57, + 0xff, 0x79, 0x01, 0x12, 0x0f, 0x60, 0x5a, 0x75, 0xfd, 0xe9, 0x67, 0x33, + 0x47, 0x51, 0xd7, 0xbf, 0x7f, 0x1d, 0x77, 0xf0, 0x75, 0x48, 0xd9, 0x78, + 0x72, 0x8e, 0xbe, 0xdd, 0xa9, 0xc3, 0xaf, 0x42, 0xd5, 0xc4, 0x44, 0xee, + 0x78, 0xb2, 0x1f, 0x05, 0x54, 0x26, 0x8d, 0x88, 0x49, 0x0b, 0x5b, 0xc3, + 0xed, 0x93, 0xaf, 0x7c, 0x62, 0xd8, 0xb3, 0xaf, 0xfa, 0x4a, 0xe7, 0x1a, + 0xee, 0xd3, 0x45, 0x0f, 0x48, 0x88, 0xb9, 0x87, 0x9c, 0xa2, 0xfc, 0x08, + 0x6e, 0x2c, 0xeb, 0xe8, 0x9b, 0x02, 0x75, 0x70, 0xf1, 0xf4, 0x4d, 0x7f, + 0xd9, 0x01, 0xec, 0x6c, 0x44, 0xc7, 0x5f, 0xe0, 0x27, 0x7b, 0x80, 0x73, + 0xa9, 0x67, 0xd6, 0x03, 0xaa, 0x84, 0x57, 0xbc, 0x23, 0x6f, 0xfc, 0xe1, + 0x80, 0xf5, 0x05, 0x16, 0x75, 0xff, 0xb6, 0xbf, 0x34, 0xfd, 0xd4, 0x4e, + 0x75, 0xfe, 0xd7, 0xed, 0xcf, 0x0c, 0x1d, 0x4b, 0x45, 0x6f, 0x4e, 0xfc, + 0x81, 0x7f, 0xf7, 0xf2, 0xeb, 0xf3, 0x7f, 0x42, 0x4e, 0x75, 0xfe, 0x94, + 0x72, 0x78, 0xe4, 0xe7, 0x5f, 0x9f, 0x5b, 0x73, 0x47, 0x54, 0x1e, 0xe0, + 0x0d, 0x2f, 0xc9, 0xed, 0x3a, 0x1d, 0x7f, 0xdc, 0x07, 0x1c, 0x7d, 0x80, + 0x3a, 0x80, 0x7b, 0x9f, 0x92, 0xde, 0xfb, 0xc9, 0x1d, 0x7f, 0x7d, 0xf7, + 0xf1, 0x93, 0x9d, 0x52, 0x3c, 0xe9, 0x87, 0xaf, 0xfe, 0x68, 0xc7, 0x87, + 0x36, 0xe7, 0x24, 0x75, 0xff, 0x7e, 0x2a, 0x7d, 0xef, 0x7f, 0xd1, 0xd7, + 0xf8, 0x45, 0xfd, 0xf6, 0x1a, 0x75, 0xf0, 0x82, 0x70, 0x1d, 0x58, 0x7a, + 0x88, 0x65, 0x7f, 0xb5, 0xf3, 0xdf, 0x03, 0x82, 0x75, 0x80, 0x75, 0x93, + 0x73, 0xc6, 0xe1, 0xb5, 0xf9, 0xf7, 0xd7, 0x90, 0xea, 0x84, 0xeb, 0x70, + 0x8d, 0x10, 0xfb, 0x09, 0x21, 0x66, 0xd1, 0x45, 0xf9, 0xff, 0x52, 0x3e, + 0x9d, 0x7e, 0x61, 0x67, 0x23, 0x47, 0x54, 0xc7, 0xa8, 0x25, 0x57, 0xfc, + 0xfa, 0x89, 0xb7, 0x96, 0x6d, 0x3a, 0xff, 0xfc, 0x1e, 0xc7, 0xd5, 0x7c, + 0x2e, 0x0d, 0x6a, 0x00, 0x55, 0xc1, 0xc3, 0xaf, 0xd3, 0xc4, 0xef, 0xa3, + 0xab, 0x11, 0x28, 0x8a, 0xee, 0x2b, 0x70, 0x3f, 0x3a, 0xfe, 0x70, 0x4c, + 0x30, 0x13, 0xaf, 0xf8, 0x72, 0x70, 0xf7, 0x07, 0xc7, 0x54, 0x1f, 0xd7, + 0x45, 0xc4, 0xb2, 0x98, 0xa6, 0xca, 0xb9, 0x8b, 0x43, 0x62, 0x67, 0x8c, + 0x33, 0x9c, 0x46, 0x59, 0x28, 0x79, 0x06, 0x1f, 0xf9, 0x18, 0xf2, 0x88, + 0x4d, 0x87, 0x06, 0xf0, 0x94, 0x42, 0x19, 0xa3, 0x90, 0xe4, 0x70, 0xab, + 0x85, 0xf7, 0x63, 0x25, 0x78, 0x69, 0x80, 0xc0, 0x61, 0x45, 0xa7, 0xdf, + 0x4a, 0x1e, 0xfe, 0x15, 0xbb, 0x48, 0xb6, 0x61, 0x9f, 0xf6, 0x14, 0xf7, + 0xff, 0xe6, 0xaa, 0x0e, 0x66, 0xed, 0xea, 0x7b, 0x4f, 0xb9, 0xd4, 0xaa, + 0xa1, 0xdf, 0xe3, 0xc5, 0xbe, 0x8e, 0x49, 0x67, 0x5e, 0x7e, 0x28, 0x75, + 0x95, 0x9c, 0xde, 0xb2, 0x43, 0x7f, 0x95, 0xce, 0x35, 0xdd, 0xa6, 0x8b, + 0xce, 0xa1, 0xd5, 0x1d, 0x49, 0xc0, 0x31, 0x81, 0x65, 0x35, 0xab, 0x79, + 0x63, 0x3c, 0x8e, 0x09, 0x6a, 0x7d, 0x85, 0x50, 0xd6, 0x9e, 0x7a, 0x6a, + 0xda, 0x55, 0x7f, 0x95, 0xce, 0x35, 0xdd, 0xa6, 0x8a, 0x5a, 0xfd, 0xc6, + 0xbb, 0xb4, 0xd1, 0x61, 0x5f, 0xff, 0xa3, 0x04, 0x31, 0xd8, 0xdf, 0xd8, + 0x2e, 0xb3, 0xad, 0xa3, 0xaf, 0xef, 0xf8, 0x93, 0xba, 0xce, 0xb2, 0xb8, + 0x8c, 0x25, 0x99, 0xe9, 0x47, 0x64, 0x42, 0xff, 0x2b, 0x9c, 0x6b, 0xbb, + 0x4d, 0x16, 0x5d, 0xdc, 0x50, 0xeb, 0xe5, 0x54, 0x61, 0x98, 0xa3, 0xa8, + 0xab, 0xca, 0xfd, 0x59, 0xd4, 0xd3, 0xd7, 0xd1, 0x77, 0xe1, 0x54, 0x28, + 0x9e, 0xd3, 0x75, 0xd1, 0xd3, 0xac, 0x03, 0xae, 0x52, 0x73, 0xad, 0xc9, + 0x1a, 0x8c, 0x10, 0xa6, 0x9f, 0x1b, 0x9e, 0xdf, 0xf3, 0xee, 0x39, 0xbf, + 0xa1, 0x43, 0xaf, 0xf4, 0xfb, 0xea, 0x03, 0xe4, 0x3a, 0xfd, 0x19, 0xb6, + 0x34, 0x75, 0xa1, 0xcf, 0x6d, 0x93, 0x4a, 0x74, 0x5d, 0x8c, 0x25, 0x2f, + 0x9e, 0x52, 0x09, 0xd7, 0xf3, 0xf2, 0x3c, 0xfd, 0x3a, 0xf3, 0x2c, 0xb2, + 0x55, 0xff, 0x44, 0xb7, 0xf7, 0x23, 0x37, 0x29, 0x52, 0xfe, 0xff, 0xbf, + 0x7d, 0xf3, 0xc9, 0xbb, 0x27, 0x5d, 0x1a, 0x3a, 0x82, 0x98, 0x27, 0x48, + 0x45, 0x2b, 0x49, 0x3b, 0x4e, 0xee, 0x61, 0x98, 0xa3, 0xaf, 0xe4, 0x7d, + 0x03, 0x5f, 0x9d, 0x7f, 0xf2, 0x49, 0xf4, 0xe3, 0xfb, 0x73, 0x45, 0x5f, + 0xff, 0xdd, 0x4f, 0x77, 0x34, 0x38, 0xbf, 0xf5, 0xd7, 0x91, 0xd7, 0xfa, + 0x25, 0xe7, 0xeb, 0x84, 0xea, 0x84, 0x66, 0xe2, 0x17, 0x16, 0xad, 0x23, + 0xad, 0x23, 0xad, 0x23, 0xaa, 0x0d, 0x82, 0x82, 0x08, 0x21, 0x7f, 0x7f, + 0xae, 0xbc, 0xb0, 0xeb, 0xff, 0xed, 0x23, 0x70, 0x79, 0x03, 0x81, 0xc5, + 0x0e, 0xa5, 0x9f, 0xcf, 0x8b, 0x6d, 0xb9, 0xd6, 0x50, 0xeb, 0x7e, 0x75, + 0x09, 0xa2, 0xd0, 0x8d, 0x61, 0xfa, 0xe8, 0x8b, 0xc6, 0x77, 0x69, 0x43, + 0xad, 0x87, 0x5d, 0xf8, 0x20, 0xd3, 0x04, 0x5e, 0xe4, 0x83, 0xaf, 0xe1, + 0x85, 0x8c, 0x61, 0xd7, 0x4a, 0x0e, 0xa9, 0xcf, 0xfc, 0x25, 0xb3, 0x0a, + 0x7e, 0x53, 0x7f, 0xff, 0xfd, 0xd8, 0xf6, 0x93, 0x5a, 0x8f, 0x75, 0x23, + 0x80, 0x5b, 0xca, 0x5e, 0x50, 0xeb, 0x93, 0x73, 0xae, 0x85, 0x9d, 0x7f, + 0xfe, 0x81, 0xfe, 0x52, 0x8f, 0x77, 0x17, 0xf6, 0x00, 0x75, 0xff, 0xf2, + 0x0f, 0xf2, 0xcd, 0x72, 0x12, 0x4f, 0xa2, 0xaa, 0x48, 0xa3, 0xf2, 0xb5, + 0xcd, 0x56, 0x17, 0xfa, 0xa7, 0x84, 0x28, 0x61, 0xb9, 0x91, 0x95, 0x28, + 0x98, 0xd2, 0x0e, 0x43, 0xe9, 0xd7, 0x86, 0x31, 0xbd, 0x43, 0x4f, 0xc7, + 0xfb, 0x5f, 0x76, 0x45, 0xbe, 0xc2, 0xe2, 0xff, 0xf2, 0xab, 0x79, 0x2b, + 0x9c, 0x6b, 0xbb, 0x4d, 0x14, 0x65, 0xfb, 0x6c, 0x72, 0x00, 0x75, 0xf8, + 0x5c, 0x11, 0xf4, 0xeb, 0xff, 0xb7, 0x6a, 0x73, 0xb9, 0x83, 0x2d, 0x1d, + 0x65, 0x61, 0x12, 0x5d, 0x28, 0xf1, 0x3d, 0x49, 0x98, 0x4d, 0xc8, 0xc0, + 0x56, 0x8c, 0xf4, 0x8c, 0x7d, 0x43, 0xe7, 0xd0, 0xe9, 0xbf, 0xf9, 0x57, + 0x92, 0xb9, 0xc6, 0xbb, 0xb4, 0xd1, 0x1c, 0xdf, 0xfe, 0x55, 0x6f, 0x25, + 0x73, 0x8d, 0x77, 0x69, 0xa2, 0x72, 0xbf, 0xca, 0xe7, 0x1a, 0xee, 0xd3, + 0x45, 0x99, 0x7f, 0xd2, 0xd3, 0xad, 0x5e, 0xf8, 0x07, 0x5f, 0xf3, 0x0e, + 0x0e, 0x2e, 0x37, 0x85, 0x9d, 0x7f, 0xb9, 0x1e, 0xeb, 0xef, 0x23, 0xaf, + 0xff, 0xff, 0xa2, 0x6e, 0xc7, 0xa3, 0xea, 0x72, 0x68, 0xee, 0x6d, 0xce, + 0xe0, 0x76, 0xe1, 0xd4, 0x04, 0x5a, 0x09, 0x9d, 0xfe, 0xcd, 0x73, 0x99, + 0xbe, 0x8e, 0xbf, 0x67, 0xb9, 0x8b, 0x3a, 0xff, 0xc8, 0x31, 0xa8, 0xf4, + 0xf8, 0xc9, 0xd7, 0xf7, 0x1b, 0xd7, 0x46, 0x09, 0xd7, 0x6e, 0xb3, 0xac, + 0xab, 0x14, 0x9f, 0x8c, 0x43, 0xca, 0x44, 0x41, 0x33, 0x59, 0x37, 0xe7, + 0xbb, 0x26, 0x17, 0xf9, 0x5c, 0xe3, 0x5d, 0xda, 0x68, 0xb7, 0x6f, 0xe1, + 0x75, 0x79, 0x3f, 0x4e, 0xbc, 0x9b, 0x80, 0xeb, 0xf7, 0x1a, 0xee, 0xd3, + 0x45, 0x21, 0x7f, 0xec, 0xea, 0x6d, 0xee, 0x60, 0xb4, 0xeb, 0xcf, 0x25, + 0x70, 0xfc, 0x34, 0x67, 0x65, 0x5a, 0x8e, 0xde, 0x17, 0x2e, 0x11, 0x97, + 0xff, 0x2a, 0xf2, 0x57, 0x38, 0xd7, 0x76, 0x9a, 0x25, 0x2a, 0x9d, 0x75, + 0x12, 0x65, 0x15, 0xab, 0xb9, 0xf8, 0x25, 0x15, 0x8b, 0xcf, 0xa3, 0x2c, + 0xd8, 0x3c, 0xbf, 0xd2, 0x41, 0xf6, 0x20, 0x4e, 0xbd, 0xaf, 0xd6, 0x75, + 0x95, 0xdc, 0xf3, 0x50, 0xc2, 0xf0, 0xbc, 0x8e, 0xbf, 0xf3, 0xc9, 0x5c, + 0xe3, 0x5d, 0xda, 0x68, 0x9d, 0xae, 0x9d, 0x8c, 0xeb, 0xff, 0xf2, 0x07, + 0xf5, 0xc6, 0xc3, 0x84, 0x60, 0x71, 0xa7, 0x5f, 0xe9, 0x47, 0x27, 0x8e, + 0x4e, 0x75, 0xff, 0xba, 0x2f, 0x2f, 0xc0, 0xb7, 0x91, 0xd5, 0x07, 0xe5, + 0x86, 0x96, 0x57, 0x13, 0x65, 0x58, 0xd7, 0x52, 0x9c, 0x68, 0x61, 0x8f, + 0x7f, 0xfc, 0xaf, 0xdd, 0x97, 0x10, 0x67, 0xa0, 0x50, 0x07, 0x5f, 0xfc, + 0xeb, 0xee, 0x35, 0xfb, 0x1f, 0x64, 0x75, 0xe4, 0x0b, 0x9d, 0x7f, 0xf0, + 0xe7, 0x5e, 0x7c, 0xd0, 0xbe, 0xe7, 0x5d, 0xb2, 0xa8, 0x51, 0x41, 0xd4, + 0x4d, 0x0d, 0x54, 0x95, 0x8a, 0x2e, 0x38, 0xed, 0x2a, 0x6c, 0xc3, 0xca, + 0xff, 0xfe, 0x0b, 0xf9, 0x5c, 0xd4, 0x0e, 0xe0, 0xd6, 0xa0, 0x07, 0x5f, + 0xb8, 0xd7, 0x76, 0x9a, 0x22, 0xcb, 0xff, 0x3c, 0x95, 0xce, 0x35, 0xdd, + 0xa6, 0x89, 0x76, 0xff, 0xfe, 0xc0, 0xf6, 0x3e, 0xab, 0xe1, 0x70, 0x6b, + 0x50, 0x02, 0xac, 0xae, 0x23, 0x65, 0x66, 0x7b, 0x29, 0x57, 0xff, 0x2d, + 0xe4, 0xae, 0x71, 0xae, 0xed, 0x34, 0x4c, 0x57, 0xff, 0xd8, 0xd8, 0x57, + 0xae, 0x9b, 0x28, 0x0c, 0x09, 0xd4, 0xaa, 0x28, 0x3a, 0xa1, 0x7e, 0xe3, + 0x5d, 0xda, 0x68, 0xaa, 0x6d, 0x87, 0x56, 0x1e, 0x12, 0x86, 0x77, 0xfe, + 0xfd, 0xf9, 0x21, 0xc6, 0x5c, 0x07, 0x5f, 0xfc, 0xfa, 0xe2, 0x33, 0xee, + 0xa7, 0x24, 0x75, 0xff, 0x71, 0xfb, 0xbc, 0xb3, 0xca, 0x85, 0x10, 0x5d, + 0x3e, 0xa5, 0x51, 0xee, 0xf0, 0xa4, 0xbf, 0xfc, 0xaa, 0xde, 0x4a, 0xe7, + 0x1a, 0xee, 0xd3, 0x44, 0xe9, 0x7f, 0x91, 0xf9, 0x12, 0x7d, 0xa7, 0x5f, + 0xa6, 0x89, 0xa3, 0x47, 0x5f, 0xcc, 0xe2, 0x6d, 0xc1, 0x3a, 0x90, 0xf5, + 0x74, 0x51, 0x79, 0x3b, 0x07, 0x2a, 0x68, 0x6f, 0xfe, 0xff, 0x5e, 0x8d, + 0xd5, 0xfe, 0x64, 0x59, 0xd4, 0xb3, 0xf4, 0xe9, 0x5d, 0xff, 0x9e, 0x4a, + 0xe7, 0x1a, 0xee, 0xd3, 0x44, 0xef, 0x7e, 0xf7, 0xee, 0xb4, 0x2a, 0xff, + 0xc3, 0x1e, 0xcd, 0x66, 0x6f, 0x23, 0xa8, 0x29, 0xf5, 0xe4, 0x63, 0x8b, + 0x22, 0x74, 0xaf, 0x13, 0xdf, 0xf0, 0x62, 0x50, 0xab, 0x3a, 0x01, 0xd7, + 0xf4, 0x2a, 0x01, 0xc0, 0x9d, 0x4a, 0xa2, 0xd7, 0x13, 0xc4, 0xea, 0xff, + 0xf2, 0xab, 0x79, 0x2b, 0x9c, 0x6b, 0xbb, 0x4d, 0x14, 0x2d, 0xff, 0xff, + 0xee, 0xfe, 0xb5, 0xbc, 0x95, 0x6f, 0x7f, 0xf4, 0x0e, 0x4e, 0xa7, 0xf1, + 0x31, 0xd7, 0xef, 0xf7, 0xf2, 0x34, 0xeb, 0xf6, 0x03, 0x1c, 0x4e, 0xbe, + 0xd2, 0x33, 0xe3, 0xaf, 0x40, 0x15, 0x9c, 0xfb, 0xc4, 0xa7, 0xc4, 0x94, + 0x89, 0x97, 0x0c, 0x3b, 0x6f, 0xff, 0x2a, 0xb7, 0x92, 0xb9, 0xc6, 0xbb, + 0xb4, 0xd1, 0x49, 0x5f, 0xff, 0xec, 0xd2, 0xbf, 0x72, 0x6e, 0xba, 0xfd, + 0xd8, 0xf7, 0xeb, 0x3a, 0xa1, 0x92, 0x41, 0x3c, 0x66, 0x92, 0x86, 0xcb, + 0x63, 0x5d, 0xe1, 0x42, 0xe5, 0x7b, 0x80, 0xbf, 0xd1, 0xc2, 0xfe, 0x4f, + 0xb2, 0xaf, 0x7f, 0x95, 0xce, 0x35, 0xdd, 0xa6, 0x88, 0x92, 0xff, 0xf2, + 0xab, 0x79, 0x2b, 0x9c, 0x6b, 0xbb, 0x4d, 0x12, 0xf5, 0xe6, 0x29, 0x60, + 0x3a, 0xfb, 0x9f, 0xfb, 0x47, 0x5f, 0xb8, 0x05, 0xa6, 0x8e, 0xbd, 0x03, + 0xb9, 0xd7, 0xef, 0x7d, 0x58, 0xc1, 0xd6, 0x4e, 0x9e, 0x18, 0x8d, 0xdf, + 0xfe, 0xee, 0xd8, 0x10, 0x31, 0xe0, 0x73, 0x9b, 0x9d, 0x74, 0x78, 0xeb, + 0xff, 0xdf, 0x85, 0x39, 0xf6, 0x6d, 0x8f, 0xdc, 0x66, 0x3a, 0xa4, 0x8d, + 0xb4, 0x26, 0x02, 0x76, 0x85, 0x6f, 0xe0, 0x76, 0x38, 0x8b, 0x3a, 0xff, + 0xd3, 0x6a, 0x36, 0xbf, 0x63, 0x79, 0x8e, 0xa8, 0x3e, 0xe7, 0x2c, 0xbf, + 0x64, 0xf9, 0xa5, 0x9d, 0x7f, 0xf4, 0xdf, 0x3e, 0x8c, 0x6d, 0x7d, 0xb1, + 0x31, 0xd4, 0x75, 0xfa, 0x4f, 0xe7, 0xda, 0x75, 0xf9, 0xf5, 0x1b, 0x70, + 0xea, 0x98, 0xf3, 0xf6, 0x94, 0x54, 0x23, 0x2b, 0x13, 0x1d, 0x66, 0xee, + 0x41, 0xd4, 0x15, 0x6c, 0xa8, 0x47, 0x34, 0x68, 0xbc, 0x85, 0x50, 0x90, + 0x6d, 0x87, 0x8e, 0xc1, 0x6d, 0xd8, 0x27, 0x5f, 0xdf, 0x35, 0xdc, 0x4f, + 0x1d, 0x41, 0x3c, 0x24, 0x14, 0xb8, 0x3b, 0x9d, 0x7f, 0x0f, 0xfe, 0x9a, + 0x14, 0x3a, 0xf3, 0x05, 0x38, 0x75, 0x91, 0xcf, 0x3b, 0xf2, 0xfb, 0xf0, + 0xe4, 0xff, 0x76, 0x9d, 0x7d, 0x93, 0xfd, 0xda, 0x75, 0xf8, 0x31, 0xb8, + 0x5f, 0xe1, 0xe8, 0x89, 0x5d, 0xff, 0xf2, 0x73, 0xe7, 0x61, 0x3d, 0xaf, + 0xdb, 0xfc, 0x1d, 0x7c, 0x93, 0x81, 0x8c, 0xeb, 0xe6, 0xbb, 0xb4, 0xd1, + 0x4b, 0xdf, 0x0f, 0xa3, 0x87, 0x5f, 0xf6, 0x71, 0x8f, 0x03, 0x9c, 0xdc, + 0xea, 0x43, 0xdb, 0xda, 0x41, 0x52, 0x4d, 0x89, 0x44, 0x09, 0x94, 0xb8, + 0x4b, 0xd8, 0x44, 0x5f, 0xc1, 0xde, 0x38, 0x9b, 0x9d, 0x7d, 0xe9, 0xf1, + 0x93, 0xa9, 0x0f, 0x44, 0x4b, 0xaf, 0xfd, 0x03, 0x1d, 0xf9, 0xf8, 0xfe, + 0xd3, 0xaf, 0x7e, 0xfa, 0x3a, 0xfa, 0x6f, 0xde, 0x63, 0xaf, 0xd0, 0x07, + 0xdf, 0x47, 0x5e, 0x14, 0x01, 0xd7, 0xb3, 0xda, 0x3a, 0xa0, 0xda, 0xe8, + 0x6a, 0x82, 0x8f, 0xc9, 0x90, 0x3a, 0x38, 0x02, 0x4f, 0x2e, 0x5f, 0x98, + 0xdc, 0x43, 0xb0, 0x75, 0xff, 0x03, 0x5c, 0x8d, 0xe4, 0x8b, 0x3a, 0xf7, + 0x9f, 0x69, 0xd7, 0xe9, 0xff, 0x9a, 0x18, 0xce, 0xbe, 0xfe, 0x68, 0x63, + 0x3a, 0xe7, 0x9f, 0xe1, 0xe9, 0xce, 0x5b, 0x50, 0x8d, 0xa7, 0x39, 0xfd, + 0xc2, 0xff, 0x93, 0x53, 0x20, 0xfa, 0x00, 0x75, 0xff, 0xc3, 0xed, 0xb1, + 0xcd, 0x38, 0xc3, 0x19, 0xd5, 0x24, 0x56, 0x2c, 0xbf, 0x46, 0xf7, 0xfa, + 0x18, 0xf5, 0x0b, 0x7f, 0x1d, 0x73, 0x89, 0xd7, 0xfd, 0x00, 0xf9, 0xd8, + 0x5b, 0x89, 0xd5, 0xb9, 0xe6, 0x6d, 0x14, 0xa9, 0x22, 0x97, 0x90, 0x80, + 0xbf, 0xa1, 0x94, 0xef, 0xec, 0x67, 0x5f, 0xdb, 0xcb, 0x4e, 0x3b, 0x9d, + 0x50, 0xac, 0x3b, 0x23, 0xb2, 0x48, 0x6a, 0xf0, 0xa3, 0xe9, 0x8d, 0xee, + 0x42, 0xce, 0xbf, 0xa0, 0x66, 0xf2, 0x28, 0x75, 0xff, 0x4b, 0x39, 0x36, + 0x0c, 0x2c, 0xeb, 0xf0, 0x21, 0xb8, 0xb3, 0xaf, 0xf6, 0x4f, 0xa8, 0x9b, + 0xfe, 0x1d, 0x48, 0x89, 0x2e, 0x1b, 0x89, 0x35, 0xd2, 0xc3, 0xaf, 0xb8, + 0x30, 0xb3, 0xaf, 0x40, 0x34, 0x75, 0x41, 0xff, 0x04, 0xbb, 0x05, 0x59, + 0x20, 0xbf, 0x77, 0xf5, 0x30, 0x4e, 0xbf, 0xe8, 0xee, 0x9f, 0xd1, 0xcd, + 0x83, 0xaf, 0xfc, 0xb7, 0x0f, 0xd9, 0xa5, 0x03, 0xb9, 0xd4, 0x13, 0xfb, + 0x43, 0xab, 0xee, 0x03, 0xee, 0xd3, 0xaf, 0x23, 0x3e, 0x3a, 0xba, 0x78, + 0x5a, 0x26, 0xa0, 0xa6, 0x51, 0xd8, 0x51, 0xf9, 0x8e, 0xff, 0x0f, 0xb3, + 0x48, 0xfd, 0x3a, 0xff, 0x80, 0x9d, 0xce, 0x3c, 0xda, 0x3a, 0xff, 0xfd, + 0x12, 0x18, 0x9f, 0xec, 0xda, 0xee, 0x6c, 0x70, 0x07, 0x5f, 0xdf, 0x17, + 0x9e, 0x7f, 0x1d, 0x66, 0x9d, 0x76, 0xfa, 0xc3, 0x7c, 0xe5, 0xd7, 0xa1, + 0x02, 0x75, 0x42, 0x68, 0xfb, 0x98, 0x2c, 0xe1, 0xe1, 0x33, 0xa2, 0xcb, + 0xfd, 0x8c, 0xc9, 0x35, 0xfa, 0xce, 0xbb, 0x6e, 0x8e, 0xbf, 0xbf, 0xd4, + 0x4d, 0xff, 0x0e, 0xbf, 0x64, 0xf9, 0xdd, 0x1d, 0x50, 0x7d, 0xfd, 0x18, + 0x13, 0x0b, 0xd9, 0xcd, 0x1d, 0x4d, 0x3c, 0x8d, 0xa5, 0xb7, 0xfc, 0x08, + 0x07, 0xdd, 0xb0, 0x3b, 0x07, 0x54, 0x26, 0x9b, 0x90, 0xeb, 0x42, 0x4b, + 0xff, 0xff, 0xbb, 0x1c, 0xdd, 0xa9, 0xbf, 0xc5, 0x1f, 0xe6, 0xba, 0xed, + 0x81, 0x09, 0xd7, 0xc8, 0xa6, 0xce, 0x1d, 0x7f, 0x7d, 0xf4, 0x4e, 0x3b, + 0x9d, 0x78, 0x51, 0x67, 0x57, 0x0f, 0xb8, 0x04, 0x9e, 0x30, 0xbf, 0xc3, + 0x0e, 0x3e, 0xc1, 0x3a, 0xff, 0x75, 0xe6, 0x4e, 0x44, 0xe7, 0x5d, 0x8b, + 0x3a, 0x82, 0x9c, 0x56, 0x43, 0x95, 0x65, 0xee, 0x5d, 0xb4, 0xce, 0xfd, + 0xb0, 0x8b, 0x8d, 0x1d, 0x7e, 0x7d, 0xb9, 0xcd, 0x1d, 0x41, 0x3d, 0x15, + 0x94, 0xdf, 0xba, 0xe2, 0x8b, 0x3a, 0xf9, 0x49, 0xb5, 0x07, 0x5f, 0xc0, + 0xdc, 0x19, 0xcc, 0x3a, 0xfe, 0x70, 0x2e, 0x33, 0xc7, 0x54, 0x1e, 0xc2, + 0x16, 0xdf, 0xe7, 0x06, 0xa3, 0xb1, 0xa3, 0xaf, 0x0e, 0x4e, 0x75, 0x42, + 0x65, 0xd8, 0x44, 0x84, 0xbd, 0x7b, 0x12, 0x0d, 0x18, 0xdc, 0x06, 0x9d, + 0x6d, 0x1d, 0x72, 0x29, 0xa3, 0x4d, 0xf8, 0xb5, 0xe0, 0x3b, 0x4e, 0xbe, + 0x66, 0x6d, 0x41, 0xd7, 0xf6, 0x85, 0xe7, 0x8f, 0x1d, 0x7e, 0x9d, 0xf5, + 0x92, 0x3a, 0xff, 0xf8, 0x39, 0xb5, 0xf9, 0x37, 0xd9, 0x3f, 0x9d, 0x67, + 0x54, 0x1f, 0xd2, 0x13, 0xdf, 0xcf, 0xb8, 0x16, 0x9a, 0x3a, 0xa1, 0x33, + 0x1d, 0xc6, 0xe6, 0x23, 0xe4, 0x29, 0xba, 0x41, 0x7f, 0xbc, 0x8c, 0xbc, + 0xd0, 0xb3, 0xac, 0xab, 0x16, 0xdb, 0xe6, 0xc4, 0xb8, 0x69, 0xe1, 0x79, + 0x22, 0x10, 0xb2, 0xe4, 0x7b, 0x5b, 0xc2, 0x8d, 0x23, 0x1c, 0x9a, 0x5a, + 0xcf, 0x15, 0x96, 0x37, 0xd8, 0xcf, 0x5e, 0x36, 0x30, 0x46, 0xfa, 0x31, + 0xce, 0x6a, 0x3b, 0xdf, 0x47, 0x9f, 0xb2, 0xf5, 0xf6, 0x35, 0xfd, 0x85, + 0x1b, 0xfc, 0xae, 0x71, 0xae, 0xed, 0x34, 0x53, 0x97, 0xf9, 0x70, 0xbc, + 0xd8, 0x8f, 0x1d, 0x7f, 0xe4, 0xe3, 0xeb, 0xb9, 0x82, 0xd3, 0xaf, 0xcb, + 0xe7, 0x33, 0x47, 0x5f, 0xff, 0xbb, 0xff, 0xb9, 0x1e, 0xd6, 0x37, 0x51, + 0xc6, 0x9d, 0x7f, 0xff, 0x7b, 0x26, 0x14, 0xd7, 0xa3, 0xea, 0x72, 0x68, + 0xe9, 0xd7, 0xf9, 0x16, 0x18, 0xd7, 0xe2, 0x75, 0xfd, 0x9e, 0xde, 0x50, + 0xc9, 0xd7, 0xfe, 0x4d, 0xf4, 0x38, 0x1e, 0xbb, 0x27, 0x5f, 0xff, 0x64, + 0xf9, 0xbf, 0xb4, 0x83, 0x00, 0x75, 0x9d, 0x4a, 0x22, 0x33, 0x47, 0xd7, + 0xfe, 0xce, 0xc7, 0x31, 0x56, 0x59, 0x64, 0xab, 0x91, 0x93, 0xae, 0x9d, + 0x58, 0x55, 0x5e, 0x13, 0x4c, 0x3b, 0x69, 0x3a, 0x2b, 0x75, 0x70, 0x4c, + 0xbd, 0x0b, 0xad, 0x92, 0x4d, 0x84, 0x1b, 0xf7, 0x1a, 0xee, 0xd3, 0x45, + 0x79, 0x7f, 0xff, 0x60, 0x7b, 0x1f, 0x55, 0xf0, 0xb8, 0x35, 0xa8, 0x01, + 0x56, 0x57, 0x11, 0x1f, 0xb2, 0x67, 0x7f, 0xf2, 0xaf, 0x25, 0x73, 0x8d, + 0x77, 0x69, 0xa2, 0x47, 0xbc, 0xdc, 0x59, 0xd7, 0x90, 0x10, 0x75, 0xe6, + 0xe2, 0xca, 0x54, 0xba, 0xbf, 0x71, 0xae, 0xed, 0x34, 0x49, 0x17, 0xff, + 0xf4, 0x27, 0x13, 0x62, 0x06, 0x78, 0xf2, 0x75, 0xe7, 0x3a, 0xff, 0xf0, + 0xe0, 0x36, 0x73, 0x91, 0x3b, 0xf1, 0xa7, 0x5d, 0x25, 0x61, 0x30, 0x4c, + 0x2b, 0xe9, 0x9f, 0x96, 0xef, 0xd9, 0xd5, 0x71, 0x67, 0x59, 0x58, 0x4e, + 0xa5, 0xe3, 0x39, 0xf2, 0x4d, 0xff, 0xca, 0xbc, 0x95, 0xce, 0x35, 0xdd, + 0xa6, 0x89, 0x2a, 0xfd, 0xc6, 0xbb, 0xb4, 0xd1, 0x78, 0xdf, 0xf4, 0x95, + 0xce, 0x35, 0xdd, 0xa6, 0x89, 0x36, 0xca, 0xe1, 0xfc, 0x39, 0x9d, 0xcc, + 0xf4, 0xeb, 0xf2, 0x03, 0x58, 0x27, 0x5f, 0xff, 0x7e, 0xfb, 0xe6, 0x28, + 0xa3, 0xcb, 0x37, 0xf1, 0xd5, 0x23, 0xf7, 0xd1, 0x2d, 0xff, 0xce, 0x06, + 0xf5, 0x38, 0x29, 0xed, 0x1d, 0x70, 0xce, 0x75, 0x39, 0xec, 0x7d, 0x42, + 0xbb, 0x9e, 0x3a, 0xf4, 0xc3, 0x39, 0xd7, 0xfb, 0x1a, 0x1f, 0xe7, 0xfa, + 0xb3, 0xac, 0x27, 0x5d, 0xf7, 0xe9, 0xd4, 0x03, 0x53, 0xf4, 0x3e, 0xed, + 0x95, 0x61, 0x3e, 0x1c, 0x84, 0x77, 0x5e, 0x9c, 0x8f, 0x42, 0xde, 0x1d, + 0xfa, 0xc1, 0x50, 0xe8, 0xe8, 0x27, 0x3f, 0x95, 0x70, 0x48, 0x18, 0xdc, + 0x92, 0x57, 0x74, 0xd1, 0x98, 0xac, 0xb3, 0xb1, 0xfd, 0x78, 0xf3, 0xf8, + 0x64, 0xfd, 0x94, 0x11, 0x51, 0x39, 0x35, 0xf1, 0x3c, 0xa9, 0x99, 0x4f, + 0x02, 0x06, 0x77, 0x23, 0x31, 0x3c, 0xee, 0xa4, 0xe6, 0x73, 0x6f, 0x81, + 0x77, 0x7a, 0xd4, 0x61, 0x29, 0x43, 0xac, 0x72, 0x8b, 0x26, 0xb6, 0xf7, + 0xfc, 0xb5, 0x05, 0xcb, 0xce, 0xa8, 0xfb, 0xb4, 0xb9, 0x07, 0xb7, 0x30, + 0x80, 0xa4, 0x29, 0xb0, 0x63, 0xee, 0x1a, 0xdf, 0x53, 0x55, 0xcd, 0x57, + 0xaf, 0x7e, 0xd3, 0xfb, 0x6f, 0x8b, 0xb6, 0x99, 0xde, 0xcc, 0xed, 0xbe, + 0xcc, 0xbe, 0x5f, 0xb4, 0x96, 0xdd, 0x8b, 0x48, 0xa3, 0x40, }; -static const unsigned kPreloadedHSTSBits = 306172; +static const unsigned kPreloadedHSTSBits = 307370; -static const unsigned kHSTSRootPosition = 305556; +static const unsigned kHSTSRootPosition = 306754; #endif // NET_HTTP_TRANSPORT_SECURITY_STATE_STATIC_H_
diff --git a/net/http/transport_security_state_static.json b/net/http/transport_security_state_static.json index 6ed2006b..ff8df2d 100644 --- a/net/http/transport_security_state_static.json +++ b/net/http/transport_security_state_static.json
@@ -1295,87 +1295,87 @@ { "name": "zixiao.wang", "include_subdomains": true, "mode": "force-https" }, - { "name": "at.search.yahoo.com", "include_subdomains": false, "mode": "force-https" }, - { "name": "au.search.yahoo.com", "include_subdomains": false, "mode": "force-https" }, - { "name": "az.search.yahoo.com", "include_subdomains": false, "mode": "force-https" }, - { "name": "be.search.yahoo.com", "include_subdomains": false, "mode": "force-https" }, - { "name": "bi.search.yahoo.com", "include_subdomains": false, "mode": "force-https" }, - { "name": "br.search.yahoo.com", "include_subdomains": false, "mode": "force-https" }, - { "name": "ca.search.yahoo.com", "include_subdomains": false, "mode": "force-https" }, - { "name": "cd.search.yahoo.com", "include_subdomains": false, "mode": "force-https" }, - { "name": "cg.search.yahoo.com", "include_subdomains": false, "mode": "force-https" }, - { "name": "chfr.search.yahoo.com", "include_subdomains": false, "mode": "force-https" }, - { "name": "chit.search.yahoo.com", "include_subdomains": false, "mode": "force-https" }, - { "name": "ch.search.yahoo.com", "include_subdomains": false, "mode": "force-https" }, - { "name": "cl.search.yahoo.com", "include_subdomains": false, "mode": "force-https" }, - { "name": "cn.search.yahoo.com", "include_subdomains": false, "mode": "force-https" }, - { "name": "co.search.yahoo.com", "include_subdomains": false, "mode": "force-https" }, - { "name": "cr.search.yahoo.com", "include_subdomains": false, "mode": "force-https" }, - { "name": "ct.search.yahoo.com", "include_subdomains": false, "mode": "force-https" }, - { "name": "de.search.yahoo.com", "include_subdomains": false, "mode": "force-https" }, - { "name": "dk.search.yahoo.com", "include_subdomains": false, "mode": "force-https" }, - { "name": "do.search.yahoo.com", "include_subdomains": false, "mode": "force-https" }, - { "name": "en-maktoob.search.yahoo.com", "include_subdomains": false, "mode": "force-https" }, - { "name": "espanol.search.yahoo.com", "include_subdomains": false, "mode": "force-https" }, - { "name": "es.search.yahoo.com", "include_subdomains": false, "mode": "force-https" }, - { "name": "fi.search.yahoo.com", "include_subdomains": false, "mode": "force-https" }, - { "name": "fj.search.yahoo.com", "include_subdomains": false, "mode": "force-https" }, - { "name": "fr.search.yahoo.com", "include_subdomains": false, "mode": "force-https" }, - { "name": "gl.search.yahoo.com", "include_subdomains": false, "mode": "force-https" }, - { "name": "gm.search.yahoo.com", "include_subdomains": false, "mode": "force-https" }, - { "name": "gr.search.yahoo.com", "include_subdomains": false, "mode": "force-https" }, - { "name": "hk.search.yahoo.com", "include_subdomains": false, "mode": "force-https" }, - { "name": "hn.search.yahoo.com", "include_subdomains": false, "mode": "force-https" }, - { "name": "hu.search.yahoo.com", "include_subdomains": false, "mode": "force-https" }, - { "name": "id.search.yahoo.com", "include_subdomains": false, "mode": "force-https" }, - { "name": "ie.search.yahoo.com", "include_subdomains": false, "mode": "force-https" }, - { "name": "in.search.yahoo.com", "include_subdomains": false, "mode": "force-https" }, - { "name": "it.search.yahoo.com", "include_subdomains": false, "mode": "force-https" }, - { "name": "kr.search.yahoo.com", "include_subdomains": false, "mode": "force-https" }, - { "name": "kz.search.yahoo.com", "include_subdomains": false, "mode": "force-https" }, - { "name": "li.search.yahoo.com", "include_subdomains": false, "mode": "force-https" }, - { "name": "lt.search.yahoo.com", "include_subdomains": false, "mode": "force-https" }, - { "name": "lu.search.yahoo.com", "include_subdomains": false, "mode": "force-https" }, - { "name": "lv.search.yahoo.com", "include_subdomains": false, "mode": "force-https" }, - { "name": "maktoob.search.yahoo.com", "include_subdomains": false, "mode": "force-https" }, - { "name": "malaysia.search.yahoo.com", "include_subdomains": false, "mode": "force-https" }, - { "name": "mt.search.yahoo.com", "include_subdomains": false, "mode": "force-https" }, - { "name": "mu.search.yahoo.com", "include_subdomains": false, "mode": "force-https" }, - { "name": "mw.search.yahoo.com", "include_subdomains": false, "mode": "force-https" }, - { "name": "mx.search.yahoo.com", "include_subdomains": false, "mode": "force-https" }, - { "name": "ni.search.yahoo.com", "include_subdomains": false, "mode": "force-https" }, - { "name": "nl.search.yahoo.com", "include_subdomains": false, "mode": "force-https" }, - { "name": "no.search.yahoo.com", "include_subdomains": false, "mode": "force-https" }, - { "name": "np.search.yahoo.com", "include_subdomains": false, "mode": "force-https" }, - { "name": "nz.search.yahoo.com", "include_subdomains": false, "mode": "force-https" }, - { "name": "pa.search.yahoo.com", "include_subdomains": false, "mode": "force-https" }, - { "name": "pe.search.yahoo.com", "include_subdomains": false, "mode": "force-https" }, - { "name": "ph.search.yahoo.com", "include_subdomains": false, "mode": "force-https" }, - { "name": "pk.search.yahoo.com", "include_subdomains": false, "mode": "force-https" }, - { "name": "pl.search.yahoo.com", "include_subdomains": false, "mode": "force-https" }, - { "name": "pr.search.yahoo.com", "include_subdomains": false, "mode": "force-https" }, - { "name": "py.search.yahoo.com", "include_subdomains": false, "mode": "force-https" }, - { "name": "qc.search.yahoo.com", "include_subdomains": false, "mode": "force-https" }, - { "name": "ro.search.yahoo.com", "include_subdomains": false, "mode": "force-https" }, - { "name": "ru.search.yahoo.com", "include_subdomains": false, "mode": "force-https" }, - { "name": "rw.search.yahoo.com", "include_subdomains": false, "mode": "force-https" }, - { "name": "se.search.yahoo.com", "include_subdomains": false, "mode": "force-https" }, - { "name": "sg.search.yahoo.com", "include_subdomains": false, "mode": "force-https" }, - { "name": "sv.search.yahoo.com", "include_subdomains": false, "mode": "force-https" }, - { "name": "th.search.yahoo.com", "include_subdomains": false, "mode": "force-https" }, - { "name": "tr.search.yahoo.com", "include_subdomains": false, "mode": "force-https" }, - { "name": "tv.search.yahoo.com", "include_subdomains": false, "mode": "force-https" }, - { "name": "tw.search.yahoo.com", "include_subdomains": false, "mode": "force-https" }, - { "name": "ua.search.yahoo.com", "include_subdomains": false, "mode": "force-https" }, - { "name": "uk.search.yahoo.com", "include_subdomains": false, "mode": "force-https" }, + { "name": "at.search.yahoo.com", "include_subdomains": false, "mode": "force-https", "pins": "yahoo" }, + { "name": "au.search.yahoo.com", "include_subdomains": false, "mode": "force-https", "pins": "yahoo" }, + { "name": "az.search.yahoo.com", "include_subdomains": false, "mode": "force-https", "pins": "yahoo" }, + { "name": "be.search.yahoo.com", "include_subdomains": false, "mode": "force-https", "pins": "yahoo" }, + { "name": "bi.search.yahoo.com", "include_subdomains": false, "mode": "force-https", "pins": "yahoo" }, + { "name": "br.search.yahoo.com", "include_subdomains": false, "mode": "force-https", "pins": "yahoo" }, + { "name": "ca.search.yahoo.com", "include_subdomains": false, "mode": "force-https", "pins": "yahoo" }, + { "name": "cd.search.yahoo.com", "include_subdomains": false, "mode": "force-https", "pins": "yahoo" }, + { "name": "cg.search.yahoo.com", "include_subdomains": false, "mode": "force-https", "pins": "yahoo" }, + { "name": "chfr.search.yahoo.com", "include_subdomains": false, "mode": "force-https", "pins": "yahoo" }, + { "name": "chit.search.yahoo.com", "include_subdomains": false, "mode": "force-https", "pins": "yahoo" }, + { "name": "ch.search.yahoo.com", "include_subdomains": false, "mode": "force-https", "pins": "yahoo" }, + { "name": "cl.search.yahoo.com", "include_subdomains": false, "mode": "force-https", "pins": "yahoo" }, + { "name": "cn.search.yahoo.com", "include_subdomains": false, "mode": "force-https", "pins": "yahoo" }, + { "name": "co.search.yahoo.com", "include_subdomains": false, "mode": "force-https", "pins": "yahoo" }, + { "name": "cr.search.yahoo.com", "include_subdomains": false, "mode": "force-https", "pins": "yahoo" }, + { "name": "ct.search.yahoo.com", "include_subdomains": false, "mode": "force-https", "pins": "yahoo" }, + { "name": "de.search.yahoo.com", "include_subdomains": false, "mode": "force-https", "pins": "yahoo" }, + { "name": "dk.search.yahoo.com", "include_subdomains": false, "mode": "force-https", "pins": "yahoo" }, + { "name": "do.search.yahoo.com", "include_subdomains": false, "mode": "force-https", "pins": "yahoo" }, + { "name": "en-maktoob.search.yahoo.com", "include_subdomains": false, "mode": "force-https", "pins": "yahoo" }, + { "name": "espanol.search.yahoo.com", "include_subdomains": false, "mode": "force-https", "pins": "yahoo" }, + { "name": "es.search.yahoo.com", "include_subdomains": false, "mode": "force-https", "pins": "yahoo" }, + { "name": "fi.search.yahoo.com", "include_subdomains": false, "mode": "force-https", "pins": "yahoo" }, + { "name": "fj.search.yahoo.com", "include_subdomains": false, "mode": "force-https", "pins": "yahoo" }, + { "name": "fr.search.yahoo.com", "include_subdomains": false, "mode": "force-https", "pins": "yahoo" }, + { "name": "gl.search.yahoo.com", "include_subdomains": false, "mode": "force-https", "pins": "yahoo" }, + { "name": "gm.search.yahoo.com", "include_subdomains": false, "mode": "force-https", "pins": "yahoo" }, + { "name": "gr.search.yahoo.com", "include_subdomains": false, "mode": "force-https", "pins": "yahoo" }, + { "name": "hk.search.yahoo.com", "include_subdomains": false, "mode": "force-https", "pins": "yahoo" }, + { "name": "hn.search.yahoo.com", "include_subdomains": false, "mode": "force-https", "pins": "yahoo" }, + { "name": "hu.search.yahoo.com", "include_subdomains": false, "mode": "force-https", "pins": "yahoo" }, + { "name": "id.search.yahoo.com", "include_subdomains": false, "mode": "force-https", "pins": "yahoo" }, + { "name": "ie.search.yahoo.com", "include_subdomains": false, "mode": "force-https", "pins": "yahoo" }, + { "name": "in.search.yahoo.com", "include_subdomains": false, "mode": "force-https", "pins": "yahoo" }, + { "name": "it.search.yahoo.com", "include_subdomains": false, "mode": "force-https", "pins": "yahoo" }, + { "name": "kr.search.yahoo.com", "include_subdomains": false, "mode": "force-https", "pins": "yahoo" }, + { "name": "kz.search.yahoo.com", "include_subdomains": false, "mode": "force-https", "pins": "yahoo" }, + { "name": "li.search.yahoo.com", "include_subdomains": false, "mode": "force-https", "pins": "yahoo" }, + { "name": "lt.search.yahoo.com", "include_subdomains": false, "mode": "force-https", "pins": "yahoo" }, + { "name": "lu.search.yahoo.com", "include_subdomains": false, "mode": "force-https", "pins": "yahoo" }, + { "name": "lv.search.yahoo.com", "include_subdomains": false, "mode": "force-https", "pins": "yahoo" }, + { "name": "maktoob.search.yahoo.com", "include_subdomains": false, "mode": "force-https", "pins": "yahoo" }, + { "name": "malaysia.search.yahoo.com", "include_subdomains": false, "mode": "force-https", "pins": "yahoo" }, + { "name": "mt.search.yahoo.com", "include_subdomains": false, "mode": "force-https", "pins": "yahoo" }, + { "name": "mu.search.yahoo.com", "include_subdomains": false, "mode": "force-https", "pins": "yahoo" }, + { "name": "mw.search.yahoo.com", "include_subdomains": false, "mode": "force-https", "pins": "yahoo" }, + { "name": "mx.search.yahoo.com", "include_subdomains": false, "mode": "force-https", "pins": "yahoo" }, + { "name": "ni.search.yahoo.com", "include_subdomains": false, "mode": "force-https", "pins": "yahoo" }, + { "name": "nl.search.yahoo.com", "include_subdomains": false, "mode": "force-https", "pins": "yahoo" }, + { "name": "no.search.yahoo.com", "include_subdomains": false, "mode": "force-https", "pins": "yahoo" }, + { "name": "np.search.yahoo.com", "include_subdomains": false, "mode": "force-https", "pins": "yahoo" }, + { "name": "nz.search.yahoo.com", "include_subdomains": false, "mode": "force-https", "pins": "yahoo" }, + { "name": "pa.search.yahoo.com", "include_subdomains": false, "mode": "force-https", "pins": "yahoo" }, + { "name": "pe.search.yahoo.com", "include_subdomains": false, "mode": "force-https", "pins": "yahoo" }, + { "name": "ph.search.yahoo.com", "include_subdomains": false, "mode": "force-https", "pins": "yahoo" }, + { "name": "pk.search.yahoo.com", "include_subdomains": false, "mode": "force-https", "pins": "yahoo" }, + { "name": "pl.search.yahoo.com", "include_subdomains": false, "mode": "force-https", "pins": "yahoo" }, + { "name": "pr.search.yahoo.com", "include_subdomains": false, "mode": "force-https", "pins": "yahoo" }, + { "name": "py.search.yahoo.com", "include_subdomains": false, "mode": "force-https", "pins": "yahoo" }, + { "name": "qc.search.yahoo.com", "include_subdomains": false, "mode": "force-https", "pins": "yahoo" }, + { "name": "ro.search.yahoo.com", "include_subdomains": false, "mode": "force-https", "pins": "yahoo" }, + { "name": "ru.search.yahoo.com", "include_subdomains": false, "mode": "force-https", "pins": "yahoo" }, + { "name": "rw.search.yahoo.com", "include_subdomains": false, "mode": "force-https", "pins": "yahoo" }, + { "name": "se.search.yahoo.com", "include_subdomains": false, "mode": "force-https", "pins": "yahoo" }, + { "name": "sg.search.yahoo.com", "include_subdomains": false, "mode": "force-https", "pins": "yahoo" }, + { "name": "sv.search.yahoo.com", "include_subdomains": false, "mode": "force-https", "pins": "yahoo" }, + { "name": "th.search.yahoo.com", "include_subdomains": false, "mode": "force-https", "pins": "yahoo" }, + { "name": "tr.search.yahoo.com", "include_subdomains": false, "mode": "force-https", "pins": "yahoo" }, + { "name": "tv.search.yahoo.com", "include_subdomains": false, "mode": "force-https", "pins": "yahoo" }, + { "name": "tw.search.yahoo.com", "include_subdomains": false, "mode": "force-https", "pins": "yahoo" }, + { "name": "ua.search.yahoo.com", "include_subdomains": false, "mode": "force-https", "pins": "yahoo" }, + { "name": "uk.search.yahoo.com", "include_subdomains": false, "mode": "force-https", "pins": "yahoo" }, { "name": "search.yahoo.com", "include_subdomains": false, "mode": "force-https", "pins": "yahoo" }, - { "name": "uy.search.yahoo.com", "include_subdomains": false, "mode": "force-https" }, - { "name": "uz.search.yahoo.com", "include_subdomains": false, "mode": "force-https" }, - { "name": "ve.search.yahoo.com", "include_subdomains": false, "mode": "force-https" }, - { "name": "vn.search.yahoo.com", "include_subdomains": false, "mode": "force-https" }, - { "name": "xa.search.yahoo.com", "include_subdomains": false, "mode": "force-https" }, - { "name": "za.search.yahoo.com", "include_subdomains": false, "mode": "force-https" }, - { "name": "zh.search.yahoo.com", "include_subdomains": false, "mode": "force-https" }, + { "name": "uy.search.yahoo.com", "include_subdomains": false, "mode": "force-https", "pins": "yahoo" }, + { "name": "uz.search.yahoo.com", "include_subdomains": false, "mode": "force-https", "pins": "yahoo" }, + { "name": "ve.search.yahoo.com", "include_subdomains": false, "mode": "force-https", "pins": "yahoo" }, + { "name": "vn.search.yahoo.com", "include_subdomains": false, "mode": "force-https", "pins": "yahoo" }, + { "name": "xa.search.yahoo.com", "include_subdomains": false, "mode": "force-https", "pins": "yahoo" }, + { "name": "za.search.yahoo.com", "include_subdomains": false, "mode": "force-https", "pins": "yahoo" }, + { "name": "zh.search.yahoo.com", "include_subdomains": false, "mode": "force-https", "pins": "yahoo" }, { "name": "login.yahoo.com", "include_subdomains": true, "mode": "force-https", "pins": "yahoo" }, { "name": "mail.yahoo.com", "include_subdomains": false, "mode": "force-https", "pins": "yahoo" }, { "name": "edit.yahoo.com", "include_subdomains": true, "mode": "force-https", "pins": "yahoo" },
diff --git a/net/quic/quic_headers_stream_test.cc b/net/quic/quic_headers_stream_test.cc index 95c923df..33eae0c 100644 --- a/net/quic/quic_headers_stream_test.cc +++ b/net/quic/quic_headers_stream_test.cc
@@ -75,8 +75,6 @@ bool end)); MOCK_METHOD2(OnWindowUpdate, void(SpdyStreamId stream_id, int delta_window_size)); - MOCK_METHOD2(OnCredentialFrameData, bool(const char* credential_data, - size_t len)); MOCK_METHOD1(OnBlocked, void(SpdyStreamId stream_id)); MOCK_METHOD3(OnPushPromise, void(SpdyStreamId stream_id, SpdyStreamId promised_stream_id,
diff --git a/net/socket/socket_test_util.cc b/net/socket/socket_test_util.cc index ddb4c6d4..c2230d7 100644 --- a/net/socket/socket_test_util.cc +++ b/net/socket/socket_test_util.cc
@@ -1001,8 +1001,6 @@ return ERR_IO_PENDING; } - // TODO(rch): remove this once OrderedSocketData and DelayedSocketData - // have been removed. if (write_result.mode == ASYNC) { RunCallbackAsync(callback, write_result.result); return ERR_IO_PENDING;
diff --git a/net/socket/ssl_client_socket_nss.cc b/net/socket/ssl_client_socket_nss.cc index 8293278..032840a 100644 --- a/net/socket/ssl_client_socket_nss.cc +++ b/net/socket/ssl_client_socket_nss.cc
@@ -2780,17 +2780,20 @@ SSL_CipherPrefSet(nss_fd_, *it, PR_FALSE); } - if (!ssl_config_.rc4_enabled) { - const PRUint16* const ssl_ciphers = SSL_GetImplementedCiphers(); - const PRUint16 num_ciphers = SSL_GetNumImplementedCiphers(); - for (int i = 0; i < num_ciphers; i++) { - SSLCipherSuiteInfo info; - if (SSL_GetCipherSuiteInfo(ssl_ciphers[i], &info, sizeof(info)) != - SECSuccess) { - continue; - } - if (info.symCipher == ssl_calg_rc4) - SSL_CipherPrefSet(nss_fd_, ssl_ciphers[i], PR_FALSE); + const PRUint16* const ssl_ciphers = SSL_GetImplementedCiphers(); + const PRUint16 num_ciphers = SSL_GetNumImplementedCiphers(); + for (int i = 0; i < num_ciphers; i++) { + SSLCipherSuiteInfo info; + if (SSL_GetCipherSuiteInfo(ssl_ciphers[i], &info, sizeof(info)) != + SECSuccess) { + continue; + } + if (info.symCipher == ssl_calg_rc4 && !ssl_config_.rc4_enabled) + SSL_CipherPrefSet(nss_fd_, ssl_ciphers[i], PR_FALSE); + if (info.keaType == ssl_kea_dh && + !ssl_config_.deprecated_cipher_suites_enabled) { + // Only offer DHE on the second handshake. https://crbug.com/538690 + SSL_CipherPrefSet(nss_fd_, ssl_ciphers[i], PR_FALSE); } }
diff --git a/net/socket/ssl_client_socket_openssl.cc b/net/socket/ssl_client_socket_openssl.cc index 8575868..a4e39b8 100644 --- a/net/socket/ssl_client_socket_openssl.cc +++ b/net/socket/ssl_client_socket_openssl.cc
@@ -937,6 +937,9 @@ // which cause them to require the version downgrade // (https://crbug.com/433406). command.append(":ECDHE-RSA-AES256-SHA384"); + } else { + // Only offer DHE on the second handshake. https://crbug.com/538690 + command.append(":!kDHE"); } // Remove any disabled ciphers.
diff --git a/net/socket/ssl_client_socket_unittest.cc b/net/socket/ssl_client_socket_unittest.cc index a9f1fde..c048bea 100644 --- a/net/socket/ssl_client_socket_unittest.cc +++ b/net/socket/ssl_client_socket_unittest.cc
@@ -2520,6 +2520,25 @@ EXPECT_EQ(OK, rv); } +// Test that DHE is only enabled if deprecated_cipher_suites_enabled is set. +TEST_F(SSLClientSocketTest, DHEDeprecated) { + SpawnedTestServer::SSLOptions ssl_options; + ssl_options.key_exchanges = + SpawnedTestServer::SSLOptions::KEY_EXCHANGE_DHE_RSA; + ASSERT_TRUE(StartTestServer(ssl_options)); + + // Normal handshakes with DHE do not work. + SSLConfig ssl_config; + int rv; + ASSERT_TRUE(CreateAndConnectSSLClientSocket(ssl_config, &rv)); + EXPECT_EQ(ERR_SSL_VERSION_OR_CIPHER_MISMATCH, rv); + + // Enabling deprecated ciphers works fine. + ssl_config.deprecated_cipher_suites_enabled = true; + ASSERT_TRUE(CreateAndConnectSSLClientSocket(ssl_config, &rv)); + EXPECT_EQ(OK, rv); +} + // Tests that enabling deprecated ciphers shards the session cache. TEST_F(SSLClientSocketTest, DeprecatedShardSessionCache) { ASSERT_TRUE(StartTestServer(SpawnedTestServer::SSLOptions())); @@ -2695,6 +2714,8 @@ client_config.alpn_protos.push_back(kProtoHTTP11); #endif client_config.npn_protos.push_back(kProtoHTTP11); + // DHE is only advertised when deprecated ciphers are enabled. + client_config.deprecated_cipher_suites_enabled = true; ASSERT_NO_FATAL_FAILURE(TestFalseStart(server_options, client_config, false)); }
diff --git a/net/spdy/buffered_spdy_framer.h b/net/spdy/buffered_spdy_framer.h index 0576f416..e75c99f8 100644 --- a/net/spdy/buffered_spdy_framer.h +++ b/net/spdy/buffered_spdy_framer.h
@@ -300,7 +300,6 @@ SpdyPriority priority; SpdyStreamId parent_stream_id; bool exclusive; - uint8 credential_slot; bool fin; bool unidirectional; };
diff --git a/net/spdy/buffered_spdy_framer_unittest.cc b/net/spdy/buffered_spdy_framer_unittest.cc index 8510db7..efd977a 100644 --- a/net/spdy/buffered_spdy_framer_unittest.cc +++ b/net/spdy/buffered_spdy_framer_unittest.cc
@@ -118,11 +118,6 @@ goaway_debug_data_.assign(debug_data.data(), debug_data.size()); } - bool OnCredentialFrameData(const char*, size_t) { - LOG(FATAL) << "Unexpected OnCredentialFrameData call."; - return false; - } - void OnDataFrameHeader(const SpdyFrame* frame) { LOG(FATAL) << "Unexpected OnDataFrameHeader call."; } @@ -147,8 +142,6 @@ return true; } - void OnCredential(const SpdyFrame& frame) {} - // Convenience function which runs a framer simulation with particular input. void SimulateInFramer(const unsigned char* input, size_t size) { buffered_spdy_framer_.set_visitor(this);
diff --git a/net/spdy/spdy_framer.cc b/net/spdy/spdy_framer.cc index faf49b407..3dff08f6 100644 --- a/net/spdy/spdy_framer.cc +++ b/net/spdy/spdy_framer.cc
@@ -237,7 +237,7 @@ if (protocol_version() <= SPDY3) { // Calculated as: // control frame header + 2 * 4 (stream IDs) + 1 (priority) - // + 1 (unused, was credential slot) + // + 1 (unused) return GetControlFrameHeaderSize() + 10; } else { return GetControlFrameHeaderSize() + @@ -497,8 +497,6 @@ return "STREAM_IN_USE"; case RST_STREAM_STREAM_ALREADY_CLOSED: return "STREAM_ALREADY_CLOSED"; - case RST_STREAM_INVALID_CREDENTIALS: - return "INVALID_CREDENTIALS"; case RST_STREAM_FRAME_TOO_LARGE: return "FRAME_TOO_LARGE"; case RST_STREAM_CONNECT_ERROR: @@ -533,8 +531,6 @@ return "HEADERS"; case WINDOW_UPDATE: return "WINDOW_UPDATE"; - case CREDENTIAL: - return "CREDENTIAL"; case PUSH_PROMISE: return "PUSH_PROMISE"; case CONTINUATION: @@ -890,19 +886,6 @@ DCHECK_EQ(SPDY_NO_ERROR, error_code_); DCHECK_LE(GetControlFrameHeaderSize(), current_frame_buffer_.len()); - // TODO(mlavan): Either remove credential frames from the code entirely, - // or add them to parsing + serialization methods for SPDY3. - // Early detection of deprecated frames that we ignore. - if (protocol_version() <= SPDY3) { - if (control_frame_type_field == CREDENTIAL) { - current_frame_type_ = CREDENTIAL; - DCHECK_EQ(SPDY3, protocol_version()); - DVLOG(1) << "CREDENTIAL control frame found. Ignoring."; - CHANGE_STATE(SPDY_IGNORE_REMAINING_PAYLOAD); - return; - } - } - if (!SpdyConstants::IsValidFrameType(protocol_version(), control_frame_type_field)) { if (protocol_version() <= SPDY3) { @@ -1464,7 +1447,7 @@ priority = priority >> 5; } - // Seek past unused byte; used to be credential slot in SPDY 3. + // Seek past unused byte. reader.Seek(1); DCHECK(reader.IsDoneReading()); @@ -2377,7 +2360,7 @@ builder.WriteUInt32(syn_stream.stream_id()); builder.WriteUInt32(syn_stream.associated_to_stream_id()); builder.WriteUInt8(priority << ((protocol_version() <= SPDY2) ? 6 : 5)); - builder.WriteUInt8(0); // Unused byte where credential slot used to be. + builder.WriteUInt8(0); // Unused byte. DCHECK_EQ(GetSynStreamMinimumSize(), builder.length()); SerializeHeaderBlock(&builder, syn_stream);
diff --git a/net/spdy/spdy_framer.h b/net/spdy/spdy_framer.h index 976a364..8e2ce1c 100644 --- a/net/spdy/spdy_framer.h +++ b/net/spdy/spdy_framer.h
@@ -20,8 +20,6 @@ #include "net/spdy/spdy_header_block.h" #include "net/spdy/spdy_protocol.h" -// TODO(akalin): Remove support for CREDENTIAL frames. - typedef struct z_stream_s z_stream; // Forward declaration for zlib. namespace net {
diff --git a/net/spdy/spdy_framer_test.cc b/net/spdy/spdy_framer_test.cc index 70a1122..29bb588 100644 --- a/net/spdy/spdy_framer_test.cc +++ b/net/spdy/spdy_framer_test.cc
@@ -4265,72 +4265,6 @@ EXPECT_EQ(2, visitor.last_window_update_delta_); } -TEST_P(SpdyFramerTest, ReceiveCredentialFrame) { - if (!IsSpdy3()) { - return; - } - SpdyFramer framer(spdy_version_); - const unsigned char kV3FrameData[] = { // Also applies for V2. - 0x80, spdy_version_ch_, 0x00, 0x0A, - 0x00, 0x00, 0x00, 0x33, - 0x00, 0x03, 0x00, 0x00, - 0x00, 0x05, 'p', 'r', - 'o', 'o', 'f', 0x00, - 0x00, 0x00, 0x06, 'a', - ' ', 'c', 'e', 'r', - 't', 0x00, 0x00, 0x00, - 0x0C, 'a', 'n', 'o', - 't', 'h', 'e', 'r', - ' ', 'c', 'e', 'r', - 't', 0x00, 0x00, 0x00, - 0x0A, 'f', 'i', 'n', - 'a', 'l', ' ', 'c', - 'e', 'r', 't', - }; - TestSpdyVisitor visitor(spdy_version_); - visitor.use_compression_ = false; - visitor.SimulateInFramer(kV3FrameData, arraysize(kV3FrameData)); - EXPECT_EQ(0, visitor.error_count_); -} - -TEST_P(SpdyFramerTest, ReadCredentialFrameFollowedByAnotherFrame) { - if (!IsSpdy3()) { - return; - } - SpdyFramer framer(spdy_version_); - const unsigned char kV3FrameData[] = { // Also applies for V2. - 0x80, spdy_version_ch_, 0x00, 0x0A, - 0x00, 0x00, 0x00, 0x33, - 0x00, 0x03, 0x00, 0x00, - 0x00, 0x05, 'p', 'r', - 'o', 'o', 'f', 0x00, - 0x00, 0x00, 0x06, 'a', - ' ', 'c', 'e', 'r', - 't', 0x00, 0x00, 0x00, - 0x0C, 'a', 'n', 'o', - 't', 'h', 'e', 'r', - ' ', 'c', 'e', 'r', - 't', 0x00, 0x00, 0x00, - 0x0A, 'f', 'i', 'n', - 'a', 'l', ' ', 'c', - 'e', 'r', 't', - }; - TestSpdyVisitor visitor(spdy_version_); - visitor.use_compression_ = false; - string multiple_frame_data(reinterpret_cast<const char*>(kV3FrameData), - arraysize(kV3FrameData)); - scoped_ptr<SpdyFrame> control_frame( - framer.SerializeWindowUpdate(SpdyWindowUpdateIR(1, 2))); - multiple_frame_data.append(string(control_frame->data(), - control_frame->size())); - visitor.SimulateInFramer( - reinterpret_cast<unsigned const char*>(multiple_frame_data.data()), - multiple_frame_data.length()); - EXPECT_EQ(0, visitor.error_count_); - EXPECT_EQ(1u, visitor.last_window_update_stream_); - EXPECT_EQ(2, visitor.last_window_update_delta_); -} - TEST_P(SpdyFramerTest, ReadCompressedPushPromise) { if (spdy_version_ <= SPDY3) { return; @@ -4922,8 +4856,6 @@ SpdyFramer::FrameTypeToString(WINDOW_UPDATE)); EXPECT_STREQ("PUSH_PROMISE", SpdyFramer::FrameTypeToString(PUSH_PROMISE)); - EXPECT_STREQ("CREDENTIAL", - SpdyFramer::FrameTypeToString(CREDENTIAL)); EXPECT_STREQ("CONTINUATION", SpdyFramer::FrameTypeToString(CONTINUATION)); }
diff --git a/net/spdy/spdy_network_transaction_unittest.cc b/net/spdy/spdy_network_transaction_unittest.cc index 1b6234f..2cc8bdb 100644 --- a/net/spdy/spdy_network_transaction_unittest.cc +++ b/net/spdy/spdy_network_transaction_unittest.cc
@@ -4084,7 +4084,6 @@ 0, // Associated Stream ID ConvertRequestPriorityToSpdyPriority( LOWEST, spdy_util_.spdy_version()), - kSpdyCredentialSlotUnused, CONTROL_FLAG_NONE, // Control Flags false, // Compressed RST_STREAM_INVALID, // Status @@ -4191,7 +4190,6 @@ 0, // Associated Stream ID ConvertRequestPriorityToSpdyPriority( LOWEST, spdy_util_.spdy_version()), - kSpdyCredentialSlotUnused, CONTROL_FLAG_NONE, // Control Flags false, // Compressed RST_STREAM_INVALID, // Status
diff --git a/net/spdy/spdy_protocol.cc b/net/spdy/spdy_protocol.cc index 9eaf468a..3d16336 100644 --- a/net/spdy/spdy_protocol.cc +++ b/net/spdy/spdy_protocol.cc
@@ -399,8 +399,6 @@ return RST_STREAM_STREAM_IN_USE; case 9: return RST_STREAM_STREAM_ALREADY_CLOSED; - case 10: - return RST_STREAM_INVALID_CREDENTIALS; case 11: return RST_STREAM_FRAME_TOO_LARGE; } @@ -462,8 +460,6 @@ return 8; case RST_STREAM_STREAM_ALREADY_CLOSED: return 9; - case RST_STREAM_INVALID_CREDENTIALS: - return 10; case RST_STREAM_FRAME_TOO_LARGE: return 11; default:
diff --git a/net/spdy/spdy_protocol.h b/net/spdy/spdy_protocol.h index 9abb396..d3f6d122 100644 --- a/net/spdy/spdy_protocol.h +++ b/net/spdy/spdy_protocol.h
@@ -287,7 +287,6 @@ GOAWAY, HEADERS, WINDOW_UPDATE, - CREDENTIAL = 10, // No longer valid. Kept for identifiability. PUSH_PROMISE, CONTINUATION, PRIORITY, @@ -383,7 +382,6 @@ RST_STREAM_FLOW_CONTROL_ERROR = 7, RST_STREAM_STREAM_IN_USE = 8, RST_STREAM_STREAM_ALREADY_CLOSED = 9, - RST_STREAM_INVALID_CREDENTIALS = 10, // FRAME_TOO_LARGE (defined by SPDY versions 3.1 and below), and // FRAME_SIZE_ERROR (defined by HTTP/2) are mapped to the same internal // reset status.
diff --git a/net/spdy/spdy_session.cc b/net/spdy/spdy_session.cc index 28bab83..3810928 100644 --- a/net/spdy/spdy_session.cc +++ b/net/spdy/spdy_session.cc
@@ -417,8 +417,6 @@ return STATUS_CODE_STREAM_IN_USE; case RST_STREAM_STREAM_ALREADY_CLOSED: return STATUS_CODE_STREAM_ALREADY_CLOSED; - case RST_STREAM_INVALID_CREDENTIALS: - return STATUS_CODE_INVALID_CREDENTIALS; case RST_STREAM_FRAME_SIZE_ERROR: return STATUS_CODE_FRAME_SIZE_ERROR; case RST_STREAM_SETTINGS_TIMEOUT: @@ -1069,7 +1067,6 @@ scoped_ptr<SpdyBufferProducer> producer) { DCHECK(frame_type == HEADERS || frame_type == DATA || - frame_type == CREDENTIAL || frame_type == SYN_STREAM); EnqueueWrite(stream->priority(), frame_type, producer.Pass(), stream); }
diff --git a/net/spdy/spdy_session.h b/net/spdy/spdy_session.h index 1acfe1b..9208de2 100644 --- a/net/spdy/spdy_session.h +++ b/net/spdy/spdy_session.h
@@ -85,7 +85,6 @@ SPDY_ERROR_UNSUPPORTED_VERSION = 4, SPDY_ERROR_DECOMPRESS_FAILURE = 5, SPDY_ERROR_COMPRESS_FAILURE = 6, - // SPDY_ERROR_CREDENTIAL_FRAME_CORRUPT = 7, (removed). SPDY_ERROR_GOAWAY_FRAME_CORRUPT = 29, SPDY_ERROR_RST_STREAM_FRAME_CORRUPT = 30, SPDY_ERROR_INVALID_DATA_FRAME_FLAGS = 8, @@ -102,7 +101,6 @@ STATUS_CODE_FLOW_CONTROL_ERROR = 17, STATUS_CODE_STREAM_IN_USE = 18, STATUS_CODE_STREAM_ALREADY_CLOSED = 19, - STATUS_CODE_INVALID_CREDENTIALS = 20, STATUS_CODE_FRAME_SIZE_ERROR = 21, STATUS_CODE_SETTINGS_TIMEOUT = 32, STATUS_CODE_CONNECT_ERROR = 33,
diff --git a/net/spdy/spdy_test_util_common.cc b/net/spdy/spdy_test_util_common.cc index b697f22..f43d098 100644 --- a/net/spdy/spdy_test_util_common.cc +++ b/net/spdy/spdy_test_util_common.cc
@@ -849,7 +849,6 @@ stream_id, associated_stream_id, ConvertRequestPriorityToSpdyPriority(request_priority, spdy_version_), - 0, // credential slot flags, compressed, RST_STREAM_INVALID, // status @@ -1313,7 +1312,6 @@ 1, // Stream ID 0, // Associated stream ID ConvertRequestPriorityToSpdyPriority(LOWEST, spdy_version_), - kSpdyCredentialSlotUnused, CONTROL_FLAG_FIN, // Control Flags false, // Compressed RST_STREAM_INVALID,
diff --git a/net/spdy/spdy_test_util_common.h b/net/spdy/spdy_test_util_common.h index b997c6ac..db6e65c 100644 --- a/net/spdy/spdy_test_util_common.h +++ b/net/spdy/spdy_test_util_common.h
@@ -136,15 +136,12 @@ void OnComplete(SpdyStreamRequest* request, int result); }; -const size_t kSpdyCredentialSlotUnused = 0; - // This struct holds information used to construct spdy control and data frames. struct SpdyHeaderInfo { SpdyFrameType kind; SpdyStreamId id; SpdyStreamId assoc_id; SpdyPriority priority; - size_t credential_slot; // SPDY3 only SpdyControlFlags control_flags; bool compressed; SpdyRstStreamStatus status;
diff --git a/net/test/url_request/url_request_failed_job.cc b/net/test/url_request/url_request_failed_job.cc index d7c479b..e4ac6a6 100644 --- a/net/test/url_request/url_request_failed_job.cc +++ b/net/test/url_request/url_request_failed_job.cc
@@ -97,20 +97,40 @@ } void URLRequestFailedJob::Start() { - base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, - base::Bind(&URLRequestFailedJob::StartAsync, weak_factory_.GetWeakPtr())); + if (phase_ == START) { + if (net_error_ != ERR_IO_PENDING) { + NotifyStartError(URLRequestStatus(URLRequestStatus::FAILED, net_error_)); + return; + } + SetStatus(URLRequestStatus(URLRequestStatus::IO_PENDING, 0)); + return; + } + response_info_.headers = new net::HttpResponseHeaders("HTTP/1.1 200 OK"); + NotifyHeadersComplete(); } -int URLRequestFailedJob::ReadRawData(IOBuffer* buf, int buf_size) { +bool URLRequestFailedJob::ReadRawData(IOBuffer* buf, + int buf_size, + int* bytes_read) { CHECK(phase_ == READ_SYNC || phase_ == READ_ASYNC); - if (net_error_ == ERR_IO_PENDING || phase_ == READ_SYNC) - return net_error_; + if (net_error_ != ERR_IO_PENDING && phase_ == READ_SYNC) { + NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, net_error_)); + return false; + } + + SetStatus(URLRequestStatus(URLRequestStatus::IO_PENDING, 0)); + + if (net_error_ == ERR_IO_PENDING) + return false; + + DCHECK_EQ(READ_ASYNC, phase_); + DCHECK_NE(ERR_IO_PENDING, net_error_); base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, base::Bind(&URLRequestFailedJob::ReadRawDataComplete, - weak_factory_.GetWeakPtr(), net_error_)); - return ERR_IO_PENDING; + FROM_HERE, + base::Bind(&URLRequestFailedJob::NotifyDone, weak_factory_.GetWeakPtr(), + URLRequestStatus(URLRequestStatus::FAILED, net_error_))); + return false; } int URLRequestFailedJob::GetResponseCode() const { @@ -175,17 +195,4 @@ URLRequestFailedJob::~URLRequestFailedJob() { } -void URLRequestFailedJob::StartAsync() { - if (phase_ == START) { - if (net_error_ != ERR_IO_PENDING) { - NotifyStartError(URLRequestStatus(URLRequestStatus::FAILED, net_error_)); - return; - } - SetStatus(URLRequestStatus(URLRequestStatus::IO_PENDING, 0)); - return; - } - response_info_.headers = new net::HttpResponseHeaders("HTTP/1.1 200 OK"); - NotifyHeadersComplete(); -} - } // namespace net
diff --git a/net/test/url_request/url_request_failed_job.h b/net/test/url_request/url_request_failed_job.h index 45b1911..0413111 100644 --- a/net/test/url_request/url_request_failed_job.h +++ b/net/test/url_request/url_request_failed_job.h
@@ -39,7 +39,7 @@ // URLRequestJob implementation: void Start() override; - int ReadRawData(IOBuffer* buf, int buf_size) override; + bool ReadRawData(IOBuffer* buf, int buf_size, int* bytes_read) override; int GetResponseCode() const override; void GetResponseInfo(HttpResponseInfo* info) override; @@ -71,7 +71,6 @@ protected: ~URLRequestFailedJob() override; - void StartAsync(); private: HttpResponseInfo response_info_;
diff --git a/net/test/url_request/url_request_mock_data_job.cc b/net/test/url_request/url_request_mock_data_job.cc index b9ef385b..9549242 100644 --- a/net/test/url_request/url_request_mock_data_job.cc +++ b/net/test/url_request/url_request_mock_data_job.cc
@@ -104,12 +104,15 @@ URLRequestMockDataJob::~URLRequestMockDataJob() { } -int URLRequestMockDataJob::ReadRawData(IOBuffer* buf, int buf_size) { - int bytes_read = - std::min(static_cast<size_t>(buf_size), data_.length() - data_offset_); - memcpy(buf->data(), data_.c_str() + data_offset_, bytes_read); - data_offset_ += bytes_read; - return bytes_read; +bool URLRequestMockDataJob::ReadRawData(IOBuffer* buf, + int buf_size, + int* bytes_read) { + DCHECK(bytes_read); + *bytes_read = static_cast<int>( + std::min(static_cast<size_t>(buf_size), data_.length() - data_offset_)); + memcpy(buf->data(), data_.c_str() + data_offset_, *bytes_read); + data_offset_ += *bytes_read; + return true; } int URLRequestMockDataJob::GetResponseCode() const {
diff --git a/net/test/url_request/url_request_mock_data_job.h b/net/test/url_request/url_request_mock_data_job.h index 14ad665..3d84e37 100644 --- a/net/test/url_request/url_request_mock_data_job.h +++ b/net/test/url_request/url_request_mock_data_job.h
@@ -24,7 +24,7 @@ int data_repeat_count); void Start() override; - int ReadRawData(IOBuffer* buf, int buf_size) override; + bool ReadRawData(IOBuffer* buf, int buf_size, int* bytes_read) override; int GetResponseCode() const override; void GetResponseInfo(HttpResponseInfo* info) override;
diff --git a/net/test/url_request/url_request_slow_download_job.cc b/net/test/url_request/url_request_slow_download_job.cc index 52fd71c..f344feb 100644 --- a/net/test/url_request/url_request_slow_download_job.cc +++ b/net/test/url_request/url_request_slow_download_job.cc
@@ -179,34 +179,39 @@ return REQUEST_COMPLETE; } -int URLRequestSlowDownloadJob::ReadRawData(IOBuffer* buf, int buf_size) { +bool URLRequestSlowDownloadJob::ReadRawData(IOBuffer* buf, + int buf_size, + int* bytes_read) { if (base::LowerCaseEqualsASCII(kFinishDownloadUrl, request_->url().spec().c_str()) || base::LowerCaseEqualsASCII(kErrorDownloadUrl, request_->url().spec().c_str())) { VLOG(10) << __FUNCTION__ << " called w/ kFinish/ErrorDownloadUrl."; - return 0; + *bytes_read = 0; + return true; } VLOG(10) << __FUNCTION__ << " called at position " << bytes_already_sent_ << " in the stream."; - int bytes_read = 0; - ReadStatus status = FillBufferHelper(buf, buf_size, &bytes_read); + ReadStatus status = FillBufferHelper(buf, buf_size, bytes_read); switch (status) { case BUFFER_FILLED: - case REQUEST_COMPLETE: - return bytes_read; + return true; case REQUEST_BLOCKED: buffer_ = buf; buffer_size_ = buf_size; + SetStatus(URLRequestStatus(URLRequestStatus::IO_PENDING, 0)); base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( FROM_HERE, base::Bind(&URLRequestSlowDownloadJob::CheckDoneStatus, weak_factory_.GetWeakPtr()), base::TimeDelta::FromMilliseconds(100)); - return ERR_IO_PENDING; + return false; + case REQUEST_COMPLETE: + *bytes_read = 0; + return true; } NOTREACHED(); - return OK; + return true; } void URLRequestSlowDownloadJob::CheckDoneStatus() { @@ -218,10 +223,12 @@ FillBufferHelper(buffer_.get(), buffer_size_, &bytes_written); DCHECK_EQ(BUFFER_FILLED, status); buffer_ = NULL; // Release the reference. - ReadRawDataComplete(bytes_written); + SetStatus(URLRequestStatus()); + NotifyReadComplete(bytes_written); } else if (should_error_download_) { VLOG(10) << __FUNCTION__ << " called w/ should_finish_ownload_ set."; - ReadRawDataComplete(ERR_CONNECTION_RESET); + NotifyDone( + URLRequestStatus(URLRequestStatus::FAILED, ERR_CONNECTION_RESET)); } else { base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( FROM_HERE, base::Bind(&URLRequestSlowDownloadJob::CheckDoneStatus,
diff --git a/net/test/url_request/url_request_slow_download_job.h b/net/test/url_request/url_request_slow_download_job.h index fcd7f661b..115a6ac 100644 --- a/net/test/url_request/url_request_slow_download_job.h +++ b/net/test/url_request/url_request_slow_download_job.h
@@ -37,7 +37,7 @@ void Start() override; bool GetMimeType(std::string* mime_type) const override; void GetResponseInfo(HttpResponseInfo* info) override; - int ReadRawData(IOBuffer* buf, int buf_size) override; + bool ReadRawData(IOBuffer* buf, int buf_size, int* bytes_read) override; // Returns the current number of URLRequestSlowDownloadJobs that have // not yet completed.
diff --git a/net/url_request/url_request.cc b/net/url_request/url_request.cc index b70dbed..b64f511 100644 --- a/net/url_request/url_request.cc +++ b/net/url_request/url_request.cc
@@ -879,9 +879,6 @@ } void URLRequest::OrphanJob() { - if (network_delegate_) - network_delegate_->NotifyURLRequestJobOrphaned(this); - // When calling this function, please check that URLRequestHttpJob is // not in between calling NetworkDelegate::NotifyHeadersReceived receiving // the call back. This is currently guaranteed by the following strategies:
diff --git a/net/url_request/url_request_file_dir_job.cc b/net/url_request/url_request_file_dir_job.cc index 1dafbf2..114672ea 100644 --- a/net/url_request/url_request_file_dir_job.cc +++ b/net/url_request/url_request_file_dir_job.cc
@@ -13,6 +13,7 @@ #include "base/thread_task_runner_handle.h" #include "base/time/time.h" #include "net/base/io_buffer.h" +#include "net/base/net_errors.h" #include "net/base/net_util.h" #include "net/url_request/url_request_status.h" #include "url/gurl.h" @@ -65,19 +66,24 @@ weak_factory_.InvalidateWeakPtrs(); } -int URLRequestFileDirJob::ReadRawData(IOBuffer* buf, int buf_size) { - if (is_done()) - return 0; +bool URLRequestFileDirJob::ReadRawData(IOBuffer* buf, + int buf_size, + int* bytes_read) { + DCHECK(bytes_read); + *bytes_read = 0; - int bytes_read = 0; - if (FillReadBuffer(buf->data(), buf_size, &bytes_read)) - return bytes_read; + if (is_done()) + return true; + + if (FillReadBuffer(buf->data(), buf_size, bytes_read)) + return true; // We are waiting for more data read_pending_ = true; read_buffer_ = buf; read_buffer_length_ = buf_size; - return ERR_IO_PENDING; + SetStatus(URLRequestStatus(URLRequestStatus::IO_PENDING, 0)); + return false; } bool URLRequestFileDirJob::GetMimeType(std::string* mime_type) const { @@ -126,45 +132,40 @@ data.info.GetLastModifiedTime())); // TODO(darin): coalesce more? - CompleteRead(OK); + CompleteRead(); } void URLRequestFileDirJob::OnListDone(int error) { DCHECK(!canceled_); - DCHECK_LE(error, OK); - if (error == OK) + if (error != OK) { + read_pending_ = false; + NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, error)); + } else { list_complete_ = true; - CompleteRead(static_cast<Error>(error)); + CompleteRead(); + } } URLRequestFileDirJob::~URLRequestFileDirJob() {} -void URLRequestFileDirJob::CompleteRead(Error status) { - DCHECK_LE(status, OK); - DCHECK_NE(status, ERR_IO_PENDING); - - // Do nothing if there is no read pending. - if (!read_pending_) - return; - - int result = status; - if (status == OK) { - int filled_bytes = 0; +void URLRequestFileDirJob::CompleteRead() { + if (read_pending_) { + int bytes_read; if (FillReadBuffer(read_buffer_->data(), read_buffer_length_, - &filled_bytes)) { - result = filled_bytes; + &bytes_read)) { // We completed the read, so reset the read buffer. + read_pending_ = false; read_buffer_ = NULL; read_buffer_length_ = 0; + + SetStatus(URLRequestStatus()); + NotifyReadComplete(bytes_read); } else { NOTREACHED(); // TODO: Better error code. - result = ERR_FAILED; + NotifyDone(URLRequestStatus::FromError(ERR_FAILED)); } } - - read_pending_ = false; - ReadRawDataComplete(result); } bool URLRequestFileDirJob::FillReadBuffer(char* buf, int buf_size,
diff --git a/net/url_request/url_request_file_dir_job.h b/net/url_request/url_request_file_dir_job.h index f7a7b45..067db81e 100644 --- a/net/url_request/url_request_file_dir_job.h +++ b/net/url_request/url_request_file_dir_job.h
@@ -10,7 +10,6 @@ #include "base/files/file_path.h" #include "base/memory/weak_ptr.h" #include "net/base/directory_lister.h" -#include "net/base/net_errors.h" #include "net/url_request/url_request_job.h" namespace net { @@ -30,7 +29,7 @@ // Overridden from URLRequestJob: void Start() override; void Kill() override; - int ReadRawData(IOBuffer* buf, int buf_size) override; + bool ReadRawData(IOBuffer* buf, int buf_size, int* bytes_read) override; bool GetMimeType(std::string* mime_type) const override; bool GetCharset(std::string* charset) override; @@ -46,7 +45,7 @@ // When we have data and a read has been pending, this function // will fill the response buffer and notify the request // appropriately. - void CompleteRead(Error error); + void CompleteRead(); // Fills a buffer with the output. bool FillReadBuffer(char* buf, int buf_size, int* bytes_read); @@ -68,7 +67,6 @@ bool read_pending_; scoped_refptr<IOBuffer> read_buffer_; int read_buffer_length_; - base::WeakPtrFactory<URLRequestFileDirJob> weak_factory_; DISALLOW_COPY_AND_ASSIGN(URLRequestFileDirJob);
diff --git a/net/url_request/url_request_file_job.cc b/net/url_request/url_request_file_job.cc index 2c5cf6a6..06e1ba6b 100644 --- a/net/url_request/url_request_file_job.cc +++ b/net/url_request/url_request_file_job.cc
@@ -33,6 +33,7 @@ #include "net/base/io_buffer.h" #include "net/base/load_flags.h" #include "net/base/mime_util.h" +#include "net/base/net_errors.h" #include "net/filter/filter.h" #include "net/http/http_util.h" #include "net/url_request/url_request_error_job.h" @@ -62,7 +63,6 @@ stream_(new FileStream(file_task_runner)), file_task_runner_(file_task_runner), remaining_bytes_(0), - range_parse_result_(OK), weak_ptr_factory_(this) {} void URLRequestFileJob::Start() { @@ -83,17 +83,22 @@ URLRequestJob::Kill(); } -int URLRequestFileJob::ReadRawData(IOBuffer* dest, int dest_size) { +bool URLRequestFileJob::ReadRawData(IOBuffer* dest, + int dest_size, + int* bytes_read) { DCHECK_NE(dest_size, 0); + DCHECK(bytes_read); DCHECK_GE(remaining_bytes_, 0); if (remaining_bytes_ < dest_size) - dest_size = remaining_bytes_; + dest_size = static_cast<int>(remaining_bytes_); // If we should copy zero bytes because |remaining_bytes_| is zero, short // circuit here. - if (!dest_size) - return 0; + if (!dest_size) { + *bytes_read = 0; + return true; + } int rv = stream_->Read(dest, dest_size, @@ -101,11 +106,20 @@ weak_ptr_factory_.GetWeakPtr(), make_scoped_refptr(dest))); if (rv >= 0) { + // Data is immediately available. + *bytes_read = rv; remaining_bytes_ -= rv; DCHECK_GE(remaining_bytes_, 0); + return true; } - return rv; + // Otherwise, a read error occured. We may just need to wait... + if (rv == ERR_IO_PENDING) { + SetStatus(URLRequestStatus(URLRequestStatus::IO_PENDING, 0)); + } else { + NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, rv)); + } + return false; } bool URLRequestFileJob::IsRedirectResponse(GURL* location, @@ -165,10 +179,7 @@ const HttpRequestHeaders& headers) { std::string range_header; if (headers.GetHeader(HttpRequestHeaders::kRange, &range_header)) { - // This job only cares about the Range header. This method stashes the value - // for later use in DidOpen(), which is responsible for some of the range - // validation as well. NotifyStartError is not legal to call here since - // the job has not started. + // We only care about "Range" header here. std::vector<HttpByteRange> ranges; if (HttpUtil::ParseRangeHeader(range_header, &ranges)) { if (ranges.size() == 1) { @@ -178,7 +189,8 @@ // because we need to do multipart encoding here. // TODO(hclam): decide whether we want to support multiple range // requests. - range_parse_result_ = net::ERR_REQUEST_RANGE_NOT_SATISFIABLE; + NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, + ERR_REQUEST_RANGE_NOT_SATISFIABLE)); } } } @@ -239,19 +251,13 @@ void URLRequestFileJob::DidOpen(int result) { if (result != OK) { - NotifyStartError(URLRequestStatus(URLRequestStatus::FAILED, result)); - return; - } - - if (range_parse_result_ != net::OK) { - NotifyStartError( - URLRequestStatus(URLRequestStatus::FAILED, range_parse_result_)); + NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, result)); return; } if (!byte_range_.ComputeBounds(meta_info_.file_size)) { - NotifyStartError(URLRequestStatus(URLRequestStatus::FAILED, - net::ERR_REQUEST_RANGE_NOT_SATISFIABLE)); + NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, + ERR_REQUEST_RANGE_NOT_SATISFIABLE)); return; } @@ -279,8 +285,8 @@ void URLRequestFileJob::DidSeek(int64 result) { OnSeekComplete(result); if (result != byte_range_.first_byte_position()) { - NotifyStartError(URLRequestStatus(URLRequestStatus::FAILED, - ERR_REQUEST_RANGE_NOT_SATISFIABLE)); + NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, + ERR_REQUEST_RANGE_NOT_SATISFIABLE)); return; } @@ -289,7 +295,8 @@ } void URLRequestFileJob::DidRead(scoped_refptr<IOBuffer> buf, int result) { - if (result >= 0) { + if (result > 0) { + SetStatus(URLRequestStatus()); // Clear the IO_PENDING status remaining_bytes_ -= result; DCHECK_GE(remaining_bytes_, 0); } @@ -297,7 +304,13 @@ OnReadComplete(buf.get(), result); buf = NULL; - ReadRawDataComplete(result); + if (result == 0) { + NotifyDone(URLRequestStatus()); + } else if (result < 0) { + NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, result)); + } + + NotifyReadComplete(result); } } // namespace net
diff --git a/net/url_request/url_request_file_job.h b/net/url_request/url_request_file_job.h index 97c6c21..0436dac5 100644 --- a/net/url_request/url_request_file_job.h +++ b/net/url_request/url_request_file_job.h
@@ -11,7 +11,6 @@ #include "base/files/file_path.h" #include "base/memory/ref_counted.h" #include "base/memory/weak_ptr.h" -#include "net/base/net_errors.h" #include "net/base/net_export.h" #include "net/http/http_byte_range.h" #include "net/url_request/url_request.h" @@ -39,7 +38,7 @@ // URLRequestJob: void Start() override; void Kill() override; - int ReadRawData(IOBuffer* buf, int buf_size) override; + bool ReadRawData(IOBuffer* buf, int buf_size, int* bytes_read) override; bool IsRedirectResponse(GURL* location, int* http_status_code) override; Filter* SetupFilter() const override; bool GetMimeType(std::string* mime_type) const override; @@ -98,12 +97,9 @@ FileMetaInfo meta_info_; const scoped_refptr<base::TaskRunner> file_task_runner_; - std::vector<HttpByteRange> byte_ranges_; HttpByteRange byte_range_; int64 remaining_bytes_; - Error range_parse_result_; - base::WeakPtrFactory<URLRequestFileJob> weak_ptr_factory_; DISALLOW_COPY_AND_ASSIGN(URLRequestFileJob);
diff --git a/net/url_request/url_request_ftp_job.cc b/net/url_request/url_request_ftp_job.cc index e422d03..3a088bd 100644 --- a/net/url_request/url_request_ftp_job.cc +++ b/net/url_request/url_request_ftp_job.cc
@@ -239,7 +239,7 @@ HandleAuthNeededResponse(); return; } else { - NotifyStartError(URLRequestStatus(URLRequestStatus::FAILED, result)); + NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, result)); } } @@ -251,7 +251,15 @@ void URLRequestFtpJob::OnReadCompleted(int result) { read_in_progress_ = false; - ReadRawDataComplete(result); + if (result == 0) { + NotifyDone(URLRequestStatus()); + } else if (result < 0) { + NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, result)); + } else { + // Clear the IO_PENDING status + SetStatus(URLRequestStatus()); + } + NotifyReadComplete(result); } void URLRequestFtpJob::RestartTransactionWithAuth() { @@ -344,12 +352,14 @@ return UploadProgress(); } -int URLRequestFtpJob::ReadRawData(IOBuffer* buf, int buf_size) { +bool URLRequestFtpJob::ReadRawData(IOBuffer* buf, + int buf_size, + int* bytes_read) { DCHECK_NE(buf_size, 0); + DCHECK(bytes_read); DCHECK(!read_in_progress_); int rv; - if (proxy_info_.is_direct()) { rv = ftp_transaction_->Read(buf, buf_size, base::Bind(&URLRequestFtpJob::OnReadCompleted, @@ -360,9 +370,18 @@ base::Unretained(this))); } - if (rv == ERR_IO_PENDING) + if (rv >= 0) { + *bytes_read = rv; + return true; + } + + if (rv == ERR_IO_PENDING) { read_in_progress_ = true; - return rv; + SetStatus(URLRequestStatus(URLRequestStatus::IO_PENDING, 0)); + } else { + NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, rv)); + } + return false; } void URLRequestFtpJob::HandleAuthNeededResponse() {
diff --git a/net/url_request/url_request_ftp_job.h b/net/url_request/url_request_ftp_job.h index 6315d8f..74caf726 100644 --- a/net/url_request/url_request_ftp_job.h +++ b/net/url_request/url_request_ftp_job.h
@@ -71,7 +71,7 @@ // TODO(ibrar): Yet to give another look at this function. UploadProgress GetUploadProgress() const override; - int ReadRawData(IOBuffer* buf, int buf_size) override; + bool ReadRawData(IOBuffer* buf, int buf_size, int* bytes_read) override; void HandleAuthNeededResponse();
diff --git a/net/url_request/url_request_http_job.cc b/net/url_request/url_request_http_job.cc index 0254a5a..a452ec2 100644 --- a/net/url_request/url_request_http_job.cc +++ b/net/url_request/url_request_http_job.cc
@@ -414,6 +414,11 @@ URLRequestJob::NotifyHeadersComplete(); } +void URLRequestHttpJob::NotifyDone(const URLRequestStatus& status) { + DoneWithRequest(FINISHED); + URLRequestJob::NotifyDone(status); +} + void URLRequestHttpJob::DestroyTransaction() { DCHECK(transaction_.get()); @@ -993,16 +998,19 @@ void URLRequestHttpJob::OnReadCompleted(int result) { read_in_progress_ = false; - DCHECK_NE(ERR_IO_PENDING, result); - if (ShouldFixMismatchedContentLength(result)) result = OK; - // EOF or error, done with this job. - if (result <= 0) - DoneWithRequest(FINISHED); + if (result == OK) { + NotifyDone(URLRequestStatus()); + } else if (result < 0) { + NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, result)); + } else { + // Clear the IO_PENDING status + SetStatus(URLRequestStatus()); + } - ReadRawDataComplete(result); + NotifyReadComplete(result); } void URLRequestHttpJob::RestartTransactionWithAuth( @@ -1328,8 +1336,11 @@ return false; } -int URLRequestHttpJob::ReadRawData(IOBuffer* buf, int buf_size) { +bool URLRequestHttpJob::ReadRawData(IOBuffer* buf, + int buf_size, + int* bytes_read) { DCHECK_NE(buf_size, 0); + DCHECK(bytes_read); DCHECK(!read_in_progress_); int rv = transaction_->Read( @@ -1337,15 +1348,23 @@ base::Bind(&URLRequestHttpJob::OnReadCompleted, base::Unretained(this))); if (ShouldFixMismatchedContentLength(rv)) - rv = OK; + rv = 0; - if (rv == 0 || (rv < 0 && rv != ERR_IO_PENDING)) - DoneWithRequest(FINISHED); + if (rv >= 0) { + *bytes_read = rv; + if (!rv) + DoneWithRequest(FINISHED); + return true; + } - if (rv == ERR_IO_PENDING) + if (rv == ERR_IO_PENDING) { read_in_progress_ = true; + SetStatus(URLRequestStatus(URLRequestStatus::IO_PENDING, 0)); + } else { + NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, rv)); + } - return rv; + return false; } void URLRequestHttpJob::StopCaching() {
diff --git a/net/url_request/url_request_http_job.h b/net/url_request/url_request_http_job.h index 62162b5..3d164c3 100644 --- a/net/url_request/url_request_http_job.h +++ b/net/url_request/url_request_http_job.h
@@ -79,6 +79,9 @@ // Shadows URLRequestJob's version of this method so we can grab cookies. void NotifyHeadersComplete(); + // Shadows URLRequestJob's method so we can record histograms. + void NotifyDone(const URLRequestStatus& status); + void DestroyTransaction(); void AddExtraHeaders(); @@ -130,7 +133,7 @@ SSLPrivateKey* client_private_key) override; void ContinueDespiteLastError() override; void ResumeNetworkStart() override; - int ReadRawData(IOBuffer* buf, int buf_size) override; + bool ReadRawData(IOBuffer* buf, int buf_size, int* bytes_read) override; void StopCaching() override; bool GetFullRequestHeaders(HttpRequestHeaders* headers) const override; int64 GetTotalReceivedBytes() const override;
diff --git a/net/url_request/url_request_job.cc b/net/url_request/url_request_job.cc index 9386c5a..39ccf31 100644 --- a/net/url_request/url_request_job.cc +++ b/net/url_request/url_request_job.cc
@@ -101,46 +101,45 @@ request_ = NULL; } -// This function calls ReadRawData to get stream data. If a filter exists, it -// passes the data to the attached filter. It then returns the output from -// filter back to the caller. +// This function calls ReadData to get stream data. If a filter exists, passes +// the data to the attached filter. Then returns the output from filter back to +// the caller. bool URLRequestJob::Read(IOBuffer* buf, int buf_size, int *bytes_read) { + bool rv = false; + DCHECK_LT(buf_size, 1000000); // Sanity check. DCHECK(buf); DCHECK(bytes_read); DCHECK(filtered_read_buffer_.get() == NULL); DCHECK_EQ(0, filtered_read_buffer_len_); - Error error = OK; *bytes_read = 0; // Skip Filter if not present. - if (!filter_) { - error = ReadRawDataHelper(buf, buf_size, bytes_read); + if (!filter_.get()) { + rv = ReadRawDataHelper(buf, buf_size, bytes_read); } else { // Save the caller's buffers while we do IO // in the filter's buffers. filtered_read_buffer_ = buf; filtered_read_buffer_len_ = buf_size; - error = ReadFilteredData(bytes_read); + if (ReadFilteredData(bytes_read)) { + rv = true; // We have data to return. - // Synchronous EOF from the filter. - if (error == OK && *bytes_read == 0) - DoneReading(); + // It is fine to call DoneReading even if ReadFilteredData receives 0 + // bytes from the net, but we avoid making that call if we know for + // sure that's the case (ReadRawDataHelper path). + if (*bytes_read == 0) + DoneReading(); + } else { + rv = false; // Error, or a new IO is pending. + } } - if (error == OK) { - // If URLRequestJob read zero bytes, the job is at EOF. - if (*bytes_read == 0) - NotifyDone(URLRequestStatus()); - } else if (error == ERR_IO_PENDING) { - SetStatus(URLRequestStatus::FromError(ERR_IO_PENDING)); - } else { - NotifyDone(URLRequestStatus::FromError(error)); - *bytes_read = -1; - } - return error == OK; + if (rv && *bytes_read == 0) + NotifyDone(URLRequestStatus()); + return rv; } void URLRequestJob::StopCaching() { @@ -481,21 +480,11 @@ request_->NotifyResponseStarted(); } -void URLRequestJob::ConvertResultToError(int result, Error* error, int* count) { - if (result >= 0) { - *error = OK; - *count = result; - } else { - *error = static_cast<Error>(result); - *count = 0; - } -} - -void URLRequestJob::ReadRawDataComplete(int result) { +void URLRequestJob::NotifyReadComplete(int bytes_read) { // TODO(cbentzel): Remove ScopedTracker below once crbug.com/475755 is fixed. tracked_objects::ScopedTracker tracking_profile( FROM_HERE_WITH_EXPLICIT_FUNCTION( - "475755 URLRequestJob::RawReadCompleted")); + "475755 URLRequestJob::NotifyReadComplete")); if (!request_ || !request_->has_delegate()) return; // The request was destroyed, so there is no more work to do. @@ -508,52 +497,11 @@ // The headers should be complete before reads complete DCHECK(has_handled_response_); - Error error; - int bytes_read; - ConvertResultToError(result, &error, &bytes_read); + OnRawReadComplete(bytes_read); - DCHECK_NE(ERR_IO_PENDING, error); - - // Synchronize the URLRequest state machine with the URLRequestJob state - // machine. If this read succeeded, either the request is at EOF and the - // URLRequest state machine goes to 'finished', or it is not and the - // URLRequest state machine goes to 'success'. If the read failed, the - // URLRequest state machine goes directly to 'finished'. - // - // Update the URLRequest's status first, so that NotifyReadCompleted has an - // accurate view of the request. - if (error == OK && bytes_read > 0) { - SetStatus(URLRequestStatus()); - } else { - NotifyDone(URLRequestStatus::FromError(error)); - } - - GatherRawReadStats(error, bytes_read); - - if (filter_.get() && error == OK) { - int filter_bytes_read = 0; - // Tell the filter that it has more data. - PushInputToFilter(bytes_read); - - // Filter the data. - error = ReadFilteredData(&filter_bytes_read); - - if (!filter_bytes_read) - DoneReading(); - - DVLOG(1) << __FUNCTION__ << "() " - << "\"" << (request_ ? request_->url().spec() : "???") << "\"" - << " pre bytes read = " << bytes_read - << " pre total = " << prefilter_bytes_read_ - << " post total = " << postfilter_bytes_read_; - bytes_read = filter_bytes_read; - } else { - DVLOG(1) << __FUNCTION__ << "() " - << "\"" << (request_ ? request_->url().spec() : "???") << "\"" - << " pre bytes read = " << bytes_read - << " pre total = " << prefilter_bytes_read_ - << " post total = " << postfilter_bytes_read_; - } + // Don't notify if we had an error. + if (!request_->status().is_success()) + return; // When notifying the delegate, the delegate can release the request // (and thus release 'this'). After calling to the delegate, we must @@ -562,10 +510,25 @@ // survival until we can get out of this method. scoped_refptr<URLRequestJob> self_preservation(this); - // NotifyReadCompleted should be called after SetStatus or NotifyDone updates - // the status. - if (error == OK) + if (filter_.get()) { + // Tell the filter that it has more data + FilteredDataRead(bytes_read); + + // Filter the data. + int filter_bytes_read = 0; + if (ReadFilteredData(&filter_bytes_read)) { + if (!filter_bytes_read) + DoneReading(); + request_->NotifyReadCompleted(filter_bytes_read); + } + } else { request_->NotifyReadCompleted(bytes_read); + } + DVLOG(1) << __FUNCTION__ << "() " + << "\"" << (request_ ? request_->url().spec() : "???") << "\"" + << " pre bytes read = " << bytes_read + << " pre total = " << prefilter_bytes_read_ + << " post total = " << postfilter_bytes_read_; } void URLRequestJob::NotifyStartError(const URLRequestStatus &status) { @@ -592,7 +555,7 @@ // the response before getting here. DCHECK(has_handled_response_ || !status.is_success()); - // As with RawReadCompleted, we need to take care to notice if we were + // As with NotifyReadComplete, we need to take care to notice if we were // destroyed during a delegate callback. if (request_) { request_->set_is_pending(false); @@ -675,8 +638,10 @@ request_->OnCallToDelegateComplete(); } -int URLRequestJob::ReadRawData(IOBuffer* buf, int buf_size) { - return 0; +bool URLRequestJob::ReadRawData(IOBuffer* buf, int buf_size, int* bytes_read) { + DCHECK(bytes_read); + *bytes_read = 0; + return true; } void URLRequestJob::DoneReading() { @@ -686,34 +651,38 @@ void URLRequestJob::DoneReadingRedirectResponse() { } -void URLRequestJob::PushInputToFilter(int bytes_read) { +void URLRequestJob::FilteredDataRead(int bytes_read) { DCHECK(filter_); filter_->FlushStreamBuffer(bytes_read); } -Error URLRequestJob::ReadFilteredData(int* bytes_read) { +bool URLRequestJob::ReadFilteredData(int* bytes_read) { DCHECK(filter_); DCHECK(filtered_read_buffer_.get()); DCHECK_GT(filtered_read_buffer_len_, 0); DCHECK_LT(filtered_read_buffer_len_, 1000000); // Sanity check. - DCHECK(!raw_read_buffer_); + DCHECK(!raw_read_buffer_.get()); *bytes_read = 0; - Error error = ERR_FAILED; + bool rv = false; for (;;) { if (is_done()) - return OK; + return true; if (!filter_needs_more_output_space_ && !filter_->stream_data_len()) { // We don't have any raw data to work with, so read from the transaction. int filtered_data_read; - error = ReadRawDataForFilter(&filtered_data_read); - // If ReadRawDataForFilter returned some data, fall through to the case - // below; otherwise, return early. - if (error != OK || filtered_data_read == 0) - return error; - filter_->FlushStreamBuffer(filtered_data_read); + if (ReadRawDataForFilter(&filtered_data_read)) { + if (filtered_data_read > 0) { + // Give data to filter. + filter_->FlushStreamBuffer(filtered_data_read); + } else { + return true; // EOF. + } + } else { + return false; // IO Pending (or error). + } } if ((filter_->stream_data_len() || filter_needs_more_output_space_) && @@ -739,7 +708,7 @@ filter_needs_more_output_space_ = false; *bytes_read = filtered_data_len; postfilter_bytes_read_ += filtered_data_len; - error = OK; + rv = true; break; } case Filter::FILTER_NEED_MORE_DATA: { @@ -752,7 +721,7 @@ if (filtered_data_len > 0) { *bytes_read = filtered_data_len; postfilter_bytes_read_ += filtered_data_len; - error = OK; + rv = true; } else { // Read again since we haven't received enough data yet (e.g., we // may not have a complete gzip header yet). @@ -763,7 +732,7 @@ case Filter::FILTER_OK: { *bytes_read = filtered_data_len; postfilter_bytes_read_ += filtered_data_len; - error = OK; + rv = true; break; } case Filter::FILTER_ERROR: { @@ -771,19 +740,21 @@ << "\"" << (request_ ? request_->url().spec() : "???") << "\"" << " Filter Error"; filter_needs_more_output_space_ = false; - error = ERR_CONTENT_DECODING_FAILED; + NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, + ERR_CONTENT_DECODING_FAILED)); + rv = false; break; } default: { NOTREACHED(); filter_needs_more_output_space_ = false; - error = ERR_FAILED; + rv = false; break; } } // If logging all bytes is enabled, log the filtered bytes read. - if (error == OK && request() && filtered_data_len > 0 && + if (rv && request() && filtered_data_len > 0 && request()->net_log().IsCapturing()) { request()->net_log().AddByteTransferEvent( NetLog::TYPE_URL_REQUEST_JOB_FILTERED_BYTES_READ, filtered_data_len, @@ -791,18 +762,18 @@ } } else { // we are done, or there is no data left. - error = OK; + rv = true; } break; } - if (error == OK) { + if (rv) { // When we successfully finished a read, we no longer need to save the // caller's buffers. Release our reference. filtered_read_buffer_ = NULL; filtered_read_buffer_len_ = 0; } - return error; + return rv; } void URLRequestJob::DestroyFilters() { @@ -835,8 +806,9 @@ request_->proxy_server_ = proxy_server; } -Error URLRequestJob::ReadRawDataForFilter(int* bytes_read) { - Error error = ERR_FAILED; +bool URLRequestJob::ReadRawDataForFilter(int* bytes_read) { + bool rv = false; + DCHECK(bytes_read); DCHECK(filter_.get()); @@ -848,28 +820,30 @@ if (!filter_->stream_data_len() && !is_done()) { IOBuffer* stream_buffer = filter_->stream_buffer(); int stream_buffer_size = filter_->stream_buffer_size(); - error = ReadRawDataHelper(stream_buffer, stream_buffer_size, bytes_read); + rv = ReadRawDataHelper(stream_buffer, stream_buffer_size, bytes_read); } - return error; + return rv; } -Error URLRequestJob::ReadRawDataHelper(IOBuffer* buf, - int buf_size, - int* bytes_read) { - DCHECK(!raw_read_buffer_); +bool URLRequestJob::ReadRawDataHelper(IOBuffer* buf, + int buf_size, + int* bytes_read) { + DCHECK(!request_->status().is_io_pending()); + DCHECK(raw_read_buffer_.get() == NULL); - // Keep a pointer to the read buffer, so we have access to it in - // GatherRawReadStats() in the event that the read completes asynchronously. + // Keep a pointer to the read buffer, so we have access to it in the + // OnRawReadComplete() callback in the event that the read completes + // asynchronously. raw_read_buffer_ = buf; - Error error; - ConvertResultToError(ReadRawData(buf, buf_size), &error, bytes_read); + bool rv = ReadRawData(buf, buf_size, bytes_read); - if (error != ERR_IO_PENDING) { - // If the read completes synchronously, either success or failure, invoke - // GatherRawReadStats so we can account for the completed read. - GatherRawReadStats(error, *bytes_read); + if (!request_->status().is_io_pending()) { + // If the read completes synchronously, either success or failure, + // invoke the OnRawReadComplete callback so we can account for the + // completed read. + OnRawReadComplete(*bytes_read); } - return error; + return rv; } void URLRequestJob::FollowRedirect(const RedirectInfo& redirect_info) { @@ -878,16 +852,9 @@ NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, rv)); } -void URLRequestJob::GatherRawReadStats(Error error, int bytes_read) { - DCHECK(raw_read_buffer_ || bytes_read == 0); - DCHECK_NE(ERR_IO_PENDING, error); - - if (error != OK) { - raw_read_buffer_ = nullptr; - return; - } - // If |filter_| is non-NULL, bytes will be logged after it is applied - // instead. +void URLRequestJob::OnRawReadComplete(int bytes_read) { + DCHECK(raw_read_buffer_.get()); + // If |filter_| is non-NULL, bytes will be logged after it is applied instead. if (!filter_.get() && request() && bytes_read > 0 && request()->net_log().IsCapturing()) { request()->net_log().AddByteTransferEvent( @@ -898,7 +865,7 @@ if (bytes_read > 0) { RecordBytesRead(bytes_read); } - raw_read_buffer_ = nullptr; + raw_read_buffer_ = NULL; } void URLRequestJob::RecordBytesRead(int bytes_read) {
diff --git a/net/url_request/url_request_job.h b/net/url_request/url_request_job.h index 83358f361..f010913 100644 --- a/net/url_request/url_request_job.h +++ b/net/url_request/url_request_job.h
@@ -17,7 +17,6 @@ #include "base/power_monitor/power_observer.h" #include "net/base/host_port_pair.h" #include "net/base/load_states.h" -#include "net/base/net_errors.h" #include "net/base/net_export.h" #include "net/base/request_priority.h" #include "net/base/upload_progress.h" @@ -279,9 +278,23 @@ // Notifies the job that headers have been received. void NotifyHeadersComplete(); + // Notifies the request that the job has completed a Read operation. + void NotifyReadComplete(int bytes_read); + // Notifies the request that a start error has occurred. void NotifyStartError(const URLRequestStatus& status); + // NotifyDone marks when we are done with a request. It is really + // a glorified set_status, but also does internal state checking and + // job tracking. It should be called once per request, when the job is + // finished doing all IO. + void NotifyDone(const URLRequestStatus& status); + + // Some work performed by NotifyDone must be completed on a separate task + // so as to avoid re-entering the delegate. This method exists to perform + // that work. + void CompleteNotifyDone(); + // Used as an asynchronous callback for Kill to notify the URLRequest // that we were canceled. void NotifyCanceled(); @@ -294,19 +307,17 @@ void OnCallToDelegate(); void OnCallToDelegateComplete(); - // Called to read raw (pre-filtered) data from this Job. Reads at most - // |buf_size| bytes into |buf|. - // Possible return values: - // >= 0: Read completed synchronously. Return value is the number of bytes - // read. 0 means eof. - // ERR_IO_PENDING: Read pending asynchronously. - // When the read completes, |ReadRawDataComplete| should be - // called. - // Any other negative number: Read failed synchronously. Return value is a - // network error code. - // This method might hold onto a reference to |buf| (by incrementing the - // refcount) until the method completes or is cancelled. - virtual int ReadRawData(IOBuffer* buf, int buf_size); + // Called to read raw (pre-filtered) data from this Job. + // If returning true, data was read from the job. buf will contain + // the data, and bytes_read will receive the number of bytes read. + // If returning true, and bytes_read is returned as 0, there is no + // additional data to be read. + // If returning false, an error occurred or an async IO is now pending. + // If async IO is pending, the status of the request will be + // URLRequestStatus::IO_PENDING, and buf must remain available until the + // operation is completed. See comments on URLRequest::Read for more + // info. + virtual bool ReadRawData(IOBuffer* buf, int buf_size, int* bytes_read); // Called to tell the job that a filter has successfully reached the end of // the stream. @@ -317,14 +328,14 @@ // bodies are never read. virtual void DoneReadingRedirectResponse(); - // Reads filtered data from the request. Returns OK if immediately successful, - // ERR_IO_PENDING if the request couldn't complete synchronously, and some - // other error code if the request failed synchronously. Note that this - // function can issue new asynchronous requests if needed, in which case it - // returns ERR_IO_PENDING. If this method completes synchronously, - // |*bytes_read| is the number of bytes output by the filter chain if this - // method returns OK, or zero if this method returns an error. - Error ReadFilteredData(int* bytes_read); + // Informs the filter that data has been read into its buffer + void FilteredDataRead(int bytes_read); + + // Reads filtered data from the request. Returns true if successful, + // false otherwise. Note, if there is not enough data received to + // return data, this call can issue a new async IO request under + // the hood. + bool ReadFilteredData(int* bytes_read); // Whether the response is being filtered in this job. // Only valid after NotifyHeadersComplete() has been called. @@ -356,33 +367,19 @@ // reflects bytes read even when there is no filter. int64 postfilter_bytes_read() const { return postfilter_bytes_read_; } - // Turns an integer result code into an Error and a count of bytes read. - // The semantics are: - // |result| >= 0: |*error| == OK, |*count| == |result| - // |result| < 0: |*error| = |result|, |*count| == 0 - static void ConvertResultToError(int result, Error* error, int* count); - - // Completion callback for raw reads. See |ReadRawData| for details. - // |bytes_read| is either >= 0 to indicate a successful read and count of - // bytes read, or < 0 to indicate an error. - void ReadRawDataComplete(int bytes_read); - // The request that initiated this job. This value MAY BE NULL if the // request was released by DetachRequest(). URLRequest* request_; private: // When data filtering is enabled, this function is used to read data - // for the filter. Returns a net error code to indicate if raw data was - // successfully read, an error happened, or the IO is pending. - Error ReadRawDataForFilter(int* bytes_read); - - // Informs the filter chain that data has been read into its buffer. - void PushInputToFilter(int bytes_read); + // for the filter. Returns true if raw data was read. Returns false if + // an error occurred (or we are waiting for IO to complete). + bool ReadRawDataForFilter(int* bytes_read); // Invokes ReadRawData and records bytes read if the read completes // synchronously. - Error ReadRawDataHelper(IOBuffer* buf, int buf_size, int* bytes_read); + bool ReadRawDataHelper(IOBuffer* buf, int buf_size, int* bytes_read); // Called in response to a redirect that was not canceled to follow the // redirect. The current job will be replaced with a new job loading the @@ -391,9 +388,9 @@ // Called after every raw read. If |bytes_read| is > 0, this indicates // a successful read of |bytes_read| unfiltered bytes. If |bytes_read| - // is 0, this indicates that there is no additional data to read. |error| - // specifies whether an error occurred and no bytes were read. - void GatherRawReadStats(Error error, int bytes_read); + // is 0, this indicates that there is no additional data to read. If + // |bytes_read| is < 0, an error occurred and no bytes were read. + void OnRawReadComplete(int bytes_read); // Updates the profiling info and notifies observers that an additional // |bytes_read| unfiltered bytes have been read for this job. @@ -403,16 +400,6 @@ // out. bool FilterHasData(); - // NotifyDone marks that request is done. It is really a glorified - // set_status, but also does internal state checking and job tracking. It - // should be called once per request, when the job is finished doing all IO. - void NotifyDone(const URLRequestStatus& status); - - // Some work performed by NotifyDone must be completed asynchronously so - // as to avoid re-entering URLRequest::Delegate. This method performs that - // work. - void CompleteNotifyDone(); - // Subclasses may implement this method to record packet arrival times. // The default implementation does nothing. Only invoked when bytes have been // read since the last invocation.
diff --git a/net/url_request/url_request_job_unittest.cc b/net/url_request/url_request_job_unittest.cc index e0d19b30..f9ea1fe 100644 --- a/net/url_request/url_request_job_unittest.cc +++ b/net/url_request/url_request_job_unittest.cc
@@ -76,24 +76,6 @@ OK, }; -const MockTransaction kEmptyBodyGzip_Transaction = { - "http://www.google.com/empty_body", - "GET", - base::Time(), - "", - LOAD_NORMAL, - "HTTP/1.1 200 OK", - "Content-Encoding: gzip\n", - base::Time(), - "", - TEST_MODE_NORMAL, - nullptr, - nullptr, - 0, - 0, - OK, -}; - } // namespace TEST(URLRequestJob, TransactionNotifiedWhenDone) { @@ -205,30 +187,4 @@ RemoveMockTransaction(&kGZip_Transaction); } -// Makes sure that ReadRawDataComplete correctly updates request status before -// calling ReadFilteredData. -// Regression test for crbug.com/553300. -TEST(URLRequestJob, EmptyBodySkipFilter) { - MockNetworkLayer network_layer; - TestURLRequestContext context; - context.set_http_transaction_factory(&network_layer); - - TestDelegate d; - scoped_ptr<URLRequest> req(context.CreateRequest( - GURL(kEmptyBodyGzip_Transaction.url), DEFAULT_PRIORITY, &d)); - AddMockTransaction(&kEmptyBodyGzip_Transaction); - - req->set_method("GET"); - req->Start(); - - base::MessageLoop::current()->Run(); - - EXPECT_FALSE(d.request_failed()); - EXPECT_EQ(200, req->GetResponseCode()); - EXPECT_TRUE(d.data_received().empty()); - EXPECT_TRUE(network_layer.done_reading_called()); - - RemoveMockTransaction(&kEmptyBodyGzip_Transaction); -} - } // namespace net
diff --git a/net/url_request/url_request_simple_job.cc b/net/url_request/url_request_simple_job.cc index c12555d4..bc15079 100644 --- a/net/url_request/url_request_simple_job.cc +++ b/net/url_request/url_request_simple_job.cc
@@ -65,20 +65,33 @@ URLRequestSimpleJob::~URLRequestSimpleJob() {} -int URLRequestSimpleJob::ReadRawData(IOBuffer* buf, int buf_size) { - buf_size = std::min(static_cast<int64>(buf_size), - byte_range_.last_byte_position() - next_data_offset_ + 1); - if (buf_size == 0) - return 0; +bool URLRequestSimpleJob::ReadRawData(IOBuffer* buf, + int buf_size, + int* bytes_read) { + DCHECK(bytes_read); + buf_size = static_cast<int>( + std::min(static_cast<int64>(buf_size), + byte_range_.last_byte_position() - next_data_offset_ + 1)); + DCHECK_GE(buf_size, 0); + if (buf_size == 0) { + *bytes_read = 0; + return true; + } // Do memory copy on a background thread. See crbug.com/422489. GetTaskRunner()->PostTaskAndReply( FROM_HERE, base::Bind(&CopyData, make_scoped_refptr(buf), buf_size, data_, next_data_offset_), - base::Bind(&URLRequestSimpleJob::ReadRawDataComplete, + base::Bind(&URLRequestSimpleJob::OnReadCompleted, weak_factory_.GetWeakPtr(), buf_size)); next_data_offset_ += buf_size; - return ERR_IO_PENDING; + SetStatus(URLRequestStatus(URLRequestStatus::IO_PENDING, 0)); + return false; +} + +void URLRequestSimpleJob::OnReadCompleted(int bytes_read) { + SetStatus(URLRequestStatus()); + NotifyReadComplete(bytes_read); } base::TaskRunner* URLRequestSimpleJob::GetTaskRunner() const { @@ -109,8 +122,8 @@ return; if (ranges().size() > 1) { - NotifyStartError(URLRequestStatus(URLRequestStatus::FAILED, - ERR_REQUEST_RANGE_NOT_SATISFIABLE)); + NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, + ERR_REQUEST_RANGE_NOT_SATISFIABLE)); return; } @@ -130,8 +143,8 @@ if (result == OK) { // Notify that the headers are complete if (!byte_range_.ComputeBounds(data_->size())) { - NotifyStartError(URLRequestStatus(URLRequestStatus::FAILED, - ERR_REQUEST_RANGE_NOT_SATISFIABLE)); + NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, + ERR_REQUEST_RANGE_NOT_SATISFIABLE)); return; }
diff --git a/net/url_request/url_request_simple_job.h b/net/url_request/url_request_simple_job.h index 06f718e..6c9d5e8 100644 --- a/net/url_request/url_request_simple_job.h +++ b/net/url_request/url_request_simple_job.h
@@ -28,7 +28,7 @@ void Start() override; void Kill() override; - int ReadRawData(IOBuffer* buf, int buf_size) override; + bool ReadRawData(IOBuffer* buf, int buf_size, int* bytes_read) override; bool GetMimeType(std::string* mime_type) const override; bool GetCharset(std::string* charset) override; @@ -66,6 +66,7 @@ private: void OnGetDataCompleted(int result); + void OnReadCompleted(int bytes_read); HttpByteRange byte_range_; std::string mime_type_;
diff --git a/net/url_request/url_request_status.cc b/net/url_request/url_request_status.cc index 7207df2f..2a6a2fa 100644 --- a/net/url_request/url_request_status.cc +++ b/net/url_request/url_request_status.cc
@@ -46,19 +46,4 @@ } } -Error URLRequestStatus::ToNetError() const { - switch (status_) { - case SUCCESS: - return OK; - case IO_PENDING: - return ERR_IO_PENDING; - case CANCELED: - return ERR_ABORTED; - case FAILED: - return static_cast<Error>(error_); - } - NOTREACHED(); - return ERR_FAILED; -} - } // namespace net
diff --git a/net/url_request/url_request_status.h b/net/url_request/url_request_status.h index 694c5100..44a5d22b 100644 --- a/net/url_request/url_request_status.h +++ b/net/url_request/url_request_status.h
@@ -5,7 +5,6 @@ #ifndef NET_URL_REQUEST_URL_REQUEST_STATUS_H_ #define NET_URL_REQUEST_URL_REQUEST_STATUS_H_ -#include "net/base/net_errors.h" #include "net/base/net_export.h" namespace net { @@ -42,13 +41,6 @@ // deprecated. See https://crbug.com/490311. static URLRequestStatus FromError(int error); - // Returns a Error corresponding to |status_|. - // OK for OK - // ERR_IO_PENDING for IO_PENDING - // ERR_ABORTED for CANCELLED - // Error for FAILED - Error ToNetError() const; - Status status() const { return status_; } int error() const { return error_; }
diff --git a/net/url_request/url_request_test_job.cc b/net/url_request/url_request_test_job.cc index bd1c9052..8a293c38 100644 --- a/net/url_request/url_request_test_job.cc +++ b/net/url_request/url_request_test_job.cc
@@ -210,8 +210,7 @@ // unexpected url, return error // FIXME(brettw) we may want to use WININET errors or have some more types // of errors - NotifyStartError( - URLRequestStatus(URLRequestStatus::FAILED, ERR_INVALID_URL)); + NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, ERR_INVALID_URL)); // FIXME(brettw): this should emulate a network error, and not just fail // initiating a connection return; @@ -223,15 +222,22 @@ this->NotifyHeadersComplete(); } -int URLRequestTestJob::ReadRawData(IOBuffer* buf, int buf_size) { +bool URLRequestTestJob::ReadRawData(IOBuffer* buf, + int buf_size, + int* bytes_read) { if (stage_ == WAITING) { async_buf_ = buf; async_buf_size_ = buf_size; - return ERR_IO_PENDING; + SetStatus(URLRequestStatus(URLRequestStatus::IO_PENDING, 0)); + return false; } - if (offset_ >= static_cast<int>(response_data_.length())) - return 0; // done reading + DCHECK(bytes_read); + *bytes_read = 0; + + if (offset_ >= static_cast<int>(response_data_.length())) { + return true; // done reading + } int to_read = buf_size; if (to_read + offset_ > static_cast<int>(response_data_.length())) @@ -240,7 +246,8 @@ memcpy(buf->data(), &response_data_.c_str()[offset_], to_read); offset_ += to_read; - return to_read; + *bytes_read = to_read; + return true; } void URLRequestTestJob::GetResponseInfo(HttpResponseInfo* info) { @@ -298,15 +305,16 @@ stage_ = DATA_AVAILABLE; // OK if ReadRawData wasn't called yet. if (async_buf_) { - int result = ReadRawData(async_buf_, async_buf_size_); - if (result < 0) - NOTREACHED() << "Reads should not fail in DATA_AVAILABLE."; + int bytes_read; + if (!ReadRawData(async_buf_, async_buf_size_, &bytes_read)) + NOTREACHED() << "This should not return false in DATA_AVAILABLE."; + SetStatus(URLRequestStatus()); // clear the io pending flag if (NextReadAsync()) { // Make all future reads return io pending until the next // ProcessNextOperation(). stage_ = WAITING; } - ReadRawDataComplete(result); + NotifyReadComplete(bytes_read); } break; case DATA_AVAILABLE:
diff --git a/net/url_request/url_request_test_job.h b/net/url_request/url_request_test_job.h index eb1db01..09b31a4 100644 --- a/net/url_request/url_request_test_job.h +++ b/net/url_request/url_request_test_job.h
@@ -111,7 +111,7 @@ // Job functions void SetPriority(RequestPriority priority) override; void Start() override; - int ReadRawData(IOBuffer* buf, int buf_size) override; + bool ReadRawData(IOBuffer* buf, int buf_size, int* bytes_read) override; void Kill() override; bool GetMimeType(std::string* mime_type) const override; void GetResponseInfo(HttpResponseInfo* info) override;
diff --git a/ppapi/host/BUILD.gn b/ppapi/host/BUILD.gn index 51bd0c511..9df23ac 100644 --- a/ppapi/host/BUILD.gn +++ b/ppapi/host/BUILD.gn
@@ -33,10 +33,10 @@ "//base", "//ipc", "//media:shared_memory_support", - "//ppapi/shared_impl", "//ppapi/c", - "//ppapi/proxy:ipc", "//ppapi/proxy", + "//ppapi/proxy:ipc", + "//ppapi/shared_impl", "//ui/events:events_base", "//ui/surface", "//url",
diff --git a/ppapi/native_client/BUILD.gn b/ppapi/native_client/BUILD.gn index 45ee5acb..14138b3 100644 --- a/ppapi/native_client/BUILD.gn +++ b/ppapi/native_client/BUILD.gn
@@ -21,17 +21,17 @@ "//base", "//components/tracing", "//gpu/command_buffer/client", - "//gpu/command_buffer/common", "//gpu/command_buffer/client:gles2_implementation", + "//gpu/command_buffer/common", "//gpu/ipc", "//ipc", "//media:shared_memory_support", - "//native_client/src/untrusted/irt:irt_core_lib", - "//native_client/src/shared/srpc", - "//native_client/src/shared/platform", - "//native_client/src/tools/tls_edit($host_toolchain)", - "//native_client/src/untrusted/nacl:imc_syscalls", "//native_client/src/shared/gio", + "//native_client/src/shared/platform", + "//native_client/src/shared/srpc", + "//native_client/src/tools/tls_edit($host_toolchain)", + "//native_client/src/untrusted/irt:irt_core_lib", + "//native_client/src/untrusted/nacl:imc_syscalls", "//ppapi/native_client/src/untrusted/pnacl_irt_shim:irt", "//ppapi/proxy", "//ppapi/proxy:ipc", @@ -101,15 +101,15 @@ group("irt") { public_deps = [ - ":nacl_irt_debuglink(//build/toolchain/nacl:irt_${target_cpu})", ":nacl_irt_debug(//build/toolchain/nacl:irt_${target_cpu})", + ":nacl_irt_debuglink(//build/toolchain/nacl:irt_${target_cpu})", ] # On 32-bit Windows, we also ship the 64-bit IRT. if (is_win && target_cpu == "x86") { public_deps += [ - ":nacl_irt_debuglink(//build/toolchain/nacl:irt_x64)", ":nacl_irt_debug(//build/toolchain/nacl:irt_x64)", + ":nacl_irt_debuglink(//build/toolchain/nacl:irt_x64)", ] } }
diff --git a/remoting/BUILD.gn b/remoting/BUILD.gn index 613b68f..15a65a93 100644 --- a/remoting/BUILD.gn +++ b/remoting/BUILD.gn
@@ -53,7 +53,6 @@ deps += [ "//remoting:remoting_perftests", "//remoting/host", - "//remoting/host:remoting_native_messaging_manifests", ] @@ -182,8 +181,8 @@ "//net:test_support", "//remoting/base", "//testing/gtest", - "//third_party/webrtc/modules/desktop_capture", "//third_party/libjingle", + "//third_party/webrtc/modules/desktop_capture", ] if (enable_webrtc) {
diff --git a/remoting/host/BUILD.gn b/remoting/host/BUILD.gn index 5489890..23e5fb8 100644 --- a/remoting/host/BUILD.gn +++ b/remoting/host/BUILD.gn
@@ -80,8 +80,8 @@ "//remoting/protocol", "//remoting/resources", "//ui/base", - "//ui/events/platform", "//ui/events:dom_keycode_converter", + "//ui/events/platform", ] if (enable_configuration_policy) { @@ -313,9 +313,9 @@ deps = [ ":host", ":test_support", - "//remoting/host/setup", "//remoting/host/it2me:common", "//remoting/host/native_messaging", + "//remoting/host/setup", "//remoting/proto", "//skia", "//testing/gmock", @@ -518,8 +518,8 @@ ] deps = [ - ":remoting_me2me_host_static", ":credits", + ":remoting_me2me_host_static", "//build/config/sanitizers:deps", ] } @@ -536,8 +536,8 @@ "//base", "//remoting/base:breakpad", "//remoting/host", - "//remoting/host/setup", "//remoting/host/native_messaging", + "//remoting/host/setup", ] configs += [ "//build/config/compiler:wexit_time_destructors" ]
diff --git a/remoting/test/BUILD.gn b/remoting/test/BUILD.gn index d2b64b39..fd014ff 100644 --- a/remoting/test/BUILD.gn +++ b/remoting/test/BUILD.gn
@@ -151,8 +151,8 @@ ] deps = [ - ":test_support", ":ar_test_driver_common", + ":test_support", "//base", "//net:test_support", "//testing/gmock",
diff --git a/remoting/tools/javascript_key_tester/pnacl/BUILD.gn b/remoting/tools/javascript_key_tester/pnacl/BUILD.gn index e500e02..fbd8935 100644 --- a/remoting/tools/javascript_key_tester/pnacl/BUILD.gn +++ b/remoting/tools/javascript_key_tester/pnacl/BUILD.gn
@@ -12,7 +12,7 @@ deps = [ "//build/config/sanitizers:deps", - "//ppapi/native_client:ppapi_lib", "//ppapi/cpp", + "//ppapi/native_client:ppapi_lib", ] }
diff --git a/remoting/webapp/build_template.gni b/remoting/webapp/build_template.gni index 370a1436..ab5d116 100644 --- a/remoting/webapp/build_template.gni +++ b/remoting/webapp/build_template.gni
@@ -217,12 +217,12 @@ ] deps = [ - ":$locales_listfile", ":$background_html", - ":$message_window_html", - ":$wcs_sandbox_html", - ":$public_session_html", + ":$locales_listfile", ":$main_html", + ":$message_window_html", + ":$public_session_html", + ":$wcs_sandbox_html", "//remoting/resources", "//remoting/webapp:credits", ] @@ -511,13 +511,13 @@ ] deps = [ - ":$locales_listfile", ":$background_html", ":$feedback_consent_html", ":$loading_window_html", + ":$locales_listfile", + ":$main_html", ":$message_window_html", ":$wcs_sandbox_html", - ":$main_html", "//remoting/resources", "//remoting/webapp:credits", ]
diff --git a/remoting/webapp/js_proto/chrome_proto.js b/remoting/webapp/js_proto/chrome_proto.js index 8a34617d..3edade2 100644 --- a/remoting/webapp/js_proto/chrome_proto.js +++ b/remoting/webapp/js_proto/chrome_proto.js
@@ -12,12 +12,6 @@ /** @type {{background: Object}} */ chrome.runtime.Manifest.prototype.app; -/** @type {chrome.app.window.Bounds} */ -chrome.app.window.AppWindow.prototype.outerBounds; - -/** @type {chrome.app.window.Bounds} */ -chrome.app.window.AppWindow.prototype.innerBounds; - /** @type {string} */ chrome.app.window.AppWindow.prototype.id; @@ -41,4 +35,4 @@ chrome.socket.SendInfo.prototype.bytesSent; /** @param {function(FileWriter):void} callback */ -Entry.prototype.createWriter = function(callback) {}; \ No newline at end of file +Entry.prototype.createWriter = function(callback) {};
diff --git a/sandbox/linux/BUILD.gn b/sandbox/linux/BUILD.gn index f50efe5..213d954 100644 --- a/sandbox/linux/BUILD.gn +++ b/sandbox/linux/BUILD.gn
@@ -276,9 +276,9 @@ defines = [ "SANDBOX_IMPLEMENTATION" ] deps = [ - "//base", ":sandbox_services", ":seccomp_bpf", + "//base", ] if (is_nacl_nonsfi) { @@ -369,6 +369,8 @@ } if (is_nacl_nonsfi) { + cflags = [ "-fgnu-inline-asm" ] + sources -= [ "services/init_process_reaper.cc", "services/init_process_reaper.h",
diff --git a/sandbox/win/BUILD.gn b/sandbox/win/BUILD.gn index c8bb770..129f065a 100644 --- a/sandbox/win/BUILD.gn +++ b/sandbox/win/BUILD.gn
@@ -280,8 +280,8 @@ libs = [ "comctl32.lib" ] deps = [ - ":sandbox", ":pocdll", + ":sandbox", ] }
diff --git a/skia/BUILD.gn b/skia/BUILD.gn index e7d41ca..40b38ad 100644 --- a/skia/BUILD.gn +++ b/skia/BUILD.gn
@@ -471,9 +471,9 @@ sources += [ "ext/platform_device_linux.cc" ] set_sources_assignment_filter(sources_assignment_filter) deps += [ + "//third_party/android_tools:cpu_features", "//third_party/expat", "//third_party/freetype-android:freetype", - "//third_party/android_tools:cpu_features", ] } @@ -596,11 +596,11 @@ if (current_cpu == "x86" || current_cpu == "x64") { sources = gypi_skia_opts.sse2_sources deps += [ + ":skia_opts_avx", + ":skia_opts_avx2", ":skia_opts_sse3", ":skia_opts_sse41", ":skia_opts_sse42", - ":skia_opts_avx", - ":skia_opts_avx2", ] } else if (current_cpu == "arm") { # The assembly uses the frame pointer register (r7 in Thumb/r11 in
diff --git a/skia/ext/platform_device.cc b/skia/ext/platform_device.cc index 5b64ae3..e13e1dc9 100644 --- a/skia/ext/platform_device.cc +++ b/skia/ext/platform_device.cc
@@ -15,7 +15,6 @@ #if defined(OS_MACOSX) const char kIsPreviewMetafileKey[] = "CrIsPreviewMetafile"; -#endif void SetBoolMetaData(const SkCanvas& canvas, const char* key, bool value) { SkMetaData& meta = skia::getMetaData(canvas); @@ -29,10 +28,12 @@ value = false; return value; } +#endif } // namespace -void SetPlatformDevice(SkBaseDevice* device, PlatformDevice* platform_behaviour) { +void SetPlatformDevice(SkBaseDevice* device, + PlatformDevice* platform_behaviour) { SkMetaData& meta_data = device->getMetaData(); meta_data.setPtr(kDevicePlatformBehaviour, platform_behaviour); }
diff --git a/sql/BUILD.gn b/sql/BUILD.gn index 8d071a3e..d805c654 100644 --- a/sql/BUILD.gn +++ b/sql/BUILD.gn
@@ -30,8 +30,8 @@ deps = [ "//base", - "//third_party/sqlite", "//base/third_party/dynamic_annotations", + "//third_party/sqlite", ] } @@ -100,8 +100,8 @@ configs += [ "//build/config/compiler:no_size_t_to_int_warning" ] deps = [ - ":sql", ":redirection_header", + ":sql", ":test_support", "//base/allocator", "//base/test:test_support",
diff --git a/sql/mojo/sql_test_base.cc b/sql/mojo/sql_test_base.cc index 1074113..3018728 100644 --- a/sql/mojo/sql_test_base.cc +++ b/sql/mojo/sql_test_base.cc
@@ -133,9 +133,7 @@ void SQLTestBase::SetUp() { ApplicationTestBase::SetUp(); - mojo::URLRequestPtr request(mojo::URLRequest::New()); - request->url = mojo::String::From("mojo:filesystem"); - application_impl()->ConnectToService(request.Pass(), &files_); + application_impl()->ConnectToService("mojo:filesystem", &files_); filesystem::FileSystemClientPtr client; binding_.Bind(GetProxy(&client));
diff --git a/sql/mojo/vfs_unittest.cc b/sql/mojo/vfs_unittest.cc index 33c6171..38de192 100644 --- a/sql/mojo/vfs_unittest.cc +++ b/sql/mojo/vfs_unittest.cc
@@ -50,9 +50,7 @@ void SetUp() override { mojo::test::ApplicationTestBase::SetUp(); - mojo::URLRequestPtr request(mojo::URLRequest::New()); - request->url = mojo::String::From("mojo:filesystem"); - application_impl()->ConnectToService(request.Pass(), &files_); + application_impl()->ConnectToService("mojo:filesystem", &files_); filesystem::FileSystemClientPtr client; binding_.Bind(GetProxy(&client));
diff --git a/storage/browser/blob/blob_url_request_job.cc b/storage/browser/blob/blob_url_request_job.cc index deea300..6ec2fe5 100644 --- a/storage/browser/blob/blob_url_request_job.cc +++ b/storage/browser/blob/blob_url_request_job.cc
@@ -75,37 +75,41 @@ weak_factory_.InvalidateWeakPtrs(); } -int BlobURLRequestJob::ReadRawData(net::IOBuffer* dest, int dest_size) { +bool BlobURLRequestJob::ReadRawData(net::IOBuffer* dest, + int dest_size, + int* bytes_read) { TRACE_EVENT_ASYNC_BEGIN1("Blob", "BlobRequest::ReadRawData", this, "uuid", blob_handle_ ? blob_handle_->uuid() : "NotFound"); DCHECK_NE(dest_size, 0); + DCHECK(bytes_read); - // Bail out immediately if we encounter an error. This happens if a previous - // ReadRawData signalled an error to its caller but the caller called - // ReadRawData again anyway. - if (error_) - return 0; + // Bail out immediately if we encounter an error. + if (error_) { + *bytes_read = 0; + return true; + } - int bytes_read = 0; BlobReader::Status read_status = - blob_reader_->Read(dest, dest_size, &bytes_read, + blob_reader_->Read(dest, dest_size, bytes_read, base::Bind(&BlobURLRequestJob::DidReadRawData, weak_factory_.GetWeakPtr())); switch (read_status) { case BlobReader::Status::NET_ERROR: + NotifyFailure(blob_reader_->net_error()); TRACE_EVENT_ASYNC_END1("Blob", "BlobRequest::ReadRawData", this, "uuid", blob_handle_ ? blob_handle_->uuid() : "NotFound"); - return blob_reader_->net_error(); + return false; case BlobReader::Status::IO_PENDING: - return net::ERR_IO_PENDING; + SetStatus(net::URLRequestStatus(net::URLRequestStatus::IO_PENDING, 0)); + return false; case BlobReader::Status::DONE: TRACE_EVENT_ASYNC_END1("Blob", "BlobRequest::ReadRawData", this, "uuid", blob_handle_ ? blob_handle_->uuid() : "NotFound"); - return bytes_read; + return true; } NOTREACHED(); - return 0; + return true; } bool BlobURLRequestJob::GetMimeType(std::string* mime_type) const { @@ -218,7 +222,13 @@ void BlobURLRequestJob::DidReadRawData(int result) { TRACE_EVENT_ASYNC_END1("Blob", "BlobRequest::ReadRawData", this, "uuid", blob_handle_ ? blob_handle_->uuid() : "NotFound"); - ReadRawDataComplete(result); + if (result < 0) { + NotifyFailure(result); + return; + } + // Clear the IO_PENDING status + SetStatus(net::URLRequestStatus()); + NotifyReadComplete(result); } void BlobURLRequestJob::NotifyFailure(int error_code) { @@ -226,7 +236,11 @@ // If we already return the headers on success, we can't change the headers // now. Instead, we just error out. - DCHECK(!response_info_) << "Cannot NotifyFailure after headers."; + if (response_info_) { + NotifyDone( + net::URLRequestStatus(net::URLRequestStatus::FAILED, error_code)); + return; + } net::HttpStatusCode status_code = net::HTTP_INTERNAL_SERVER_ERROR; switch (error_code) {
diff --git a/storage/browser/blob/blob_url_request_job.h b/storage/browser/blob/blob_url_request_job.h index 1f0b9fb4..21baa2c 100644 --- a/storage/browser/blob/blob_url_request_job.h +++ b/storage/browser/blob/blob_url_request_job.h
@@ -44,7 +44,7 @@ // net::URLRequestJob methods. void Start() override; void Kill() override; - int ReadRawData(net::IOBuffer* buf, int buf_size) override; + bool ReadRawData(net::IOBuffer* buf, int buf_size, int* bytes_read) override; bool GetMimeType(std::string* mime_type) const override; void GetResponseInfo(net::HttpResponseInfo* info) override; int GetResponseCode() const override;
diff --git a/storage/browser/fileapi/file_system_dir_url_request_job.cc b/storage/browser/fileapi/file_system_dir_url_request_job.cc index c0537735..fc91f3bc 100644 --- a/storage/browser/fileapi/file_system_dir_url_request_job.cc +++ b/storage/browser/fileapi/file_system_dir_url_request_job.cc
@@ -14,6 +14,7 @@ #include "base/time/time.h" #include "build/build_config.h" #include "net/base/io_buffer.h" +#include "net/base/net_errors.h" #include "net/base/net_util.h" #include "net/url_request/url_request.h" #include "storage/browser/fileapi/file_system_context.h" @@ -43,14 +44,16 @@ FileSystemDirURLRequestJob::~FileSystemDirURLRequestJob() { } -int FileSystemDirURLRequestJob::ReadRawData(net::IOBuffer* dest, - int dest_size) { - int count = std::min(dest_size, base::checked_cast<int>(data_.size())); +bool FileSystemDirURLRequestJob::ReadRawData(net::IOBuffer* dest, + int dest_size, + int* bytes_read) { + int count = std::min(dest_size, static_cast<int>(data_.size())); if (count > 0) { memcpy(dest->data(), data_.data(), count); data_.erase(0, count); } - return count; + *bytes_read = count; + return true; } void FileSystemDirURLRequestJob::Start() { @@ -96,7 +99,8 @@ false); return; } - NotifyStartError(URLRequestStatus::FromError(net::ERR_FILE_NOT_FOUND)); + NotifyDone( + URLRequestStatus(URLRequestStatus::FAILED, net::ERR_FILE_NOT_FOUND)); return; } file_system_context_->operation_runner()->ReadDirectory( @@ -109,7 +113,8 @@ file_system_context_->CrackURL(request_->url()).is_valid()) { StartAsync(); } else { - NotifyStartError(URLRequestStatus::FromError(net::ERR_FILE_NOT_FOUND)); + NotifyDone( + URLRequestStatus(URLRequestStatus::FAILED, net::ERR_FILE_NOT_FOUND)); } } @@ -121,7 +126,7 @@ int rv = net::ERR_FILE_NOT_FOUND; if (result == base::File::FILE_ERROR_INVALID_URL) rv = net::ERR_INVALID_URL; - NotifyStartError(URLRequestStatus::FromError(rv)); + NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, rv)); return; } @@ -170,7 +175,7 @@ int rv = net::ERR_FILE_NOT_FOUND; if (result == base::File::FILE_ERROR_INVALID_URL) rv = net::ERR_INVALID_URL; - NotifyStartError(URLRequestStatus(URLRequestStatus::FAILED, rv)); + NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, rv)); } if (!request_)
diff --git a/storage/browser/fileapi/file_system_dir_url_request_job.h b/storage/browser/fileapi/file_system_dir_url_request_job.h index 93fdd1fe..01bd372 100644 --- a/storage/browser/fileapi/file_system_dir_url_request_job.h +++ b/storage/browser/fileapi/file_system_dir_url_request_job.h
@@ -32,7 +32,7 @@ // URLRequestJob methods: void Start() override; void Kill() override; - int ReadRawData(net::IOBuffer* buf, int buf_size) override; + bool ReadRawData(net::IOBuffer* buf, int buf_size, int* bytes_read) override; bool GetCharset(std::string* charset) override; // FilterContext methods (via URLRequestJob):
diff --git a/storage/browser/fileapi/file_system_url_request_job.cc b/storage/browser/fileapi/file_system_url_request_job.cc index 8edcb3d..8d58f64 100644 --- a/storage/browser/fileapi/file_system_url_request_job.cc +++ b/storage/browser/fileapi/file_system_url_request_job.cc
@@ -62,7 +62,6 @@ file_system_context_(file_system_context), is_directory_(false), remaining_bytes_(0), - range_parse_result_(net::OK), weak_factory_(this) {} FileSystemURLRequestJob::~FileSystemURLRequestJob() {} @@ -80,28 +79,39 @@ weak_factory_.InvalidateWeakPtrs(); } -int FileSystemURLRequestJob::ReadRawData(net::IOBuffer* dest, int dest_size) { +bool FileSystemURLRequestJob::ReadRawData(net::IOBuffer* dest, + int dest_size, + int* bytes_read) { DCHECK_NE(dest_size, 0); + DCHECK(bytes_read); DCHECK_GE(remaining_bytes_, 0); if (reader_.get() == NULL) - return net::ERR_FAILED; + return false; if (remaining_bytes_ < dest_size) - dest_size = remaining_bytes_; + dest_size = static_cast<int>(remaining_bytes_); - if (!dest_size) - return 0; + if (!dest_size) { + *bytes_read = 0; + return true; + } const int rv = reader_->Read(dest, dest_size, base::Bind(&FileSystemURLRequestJob::DidRead, weak_factory_.GetWeakPtr())); if (rv >= 0) { + // Data is immediately available. + *bytes_read = rv; remaining_bytes_ -= rv; DCHECK_GE(remaining_bytes_, 0); + return true; } - - return rv; + if (rv == net::ERR_IO_PENDING) + SetStatus(URLRequestStatus(URLRequestStatus::IO_PENDING, 0)); + else + NotifyFailed(rv); + return false; } bool FileSystemURLRequestJob::GetMimeType(std::string* mime_type) const { @@ -116,12 +126,8 @@ void FileSystemURLRequestJob::SetExtraRequestHeaders( const net::HttpRequestHeaders& headers) { std::string range_header; - // Currently this job only cares about the Range header. Note that validation - // is deferred to DidGetMetaData(), because NotifyStartError is not legal to - // call since the job has not started. if (headers.GetHeader(net::HttpRequestHeaders::kRange, &range_header)) { std::vector<net::HttpByteRange> ranges; - if (net::HttpUtil::ParseRangeHeader(range_header, &ranges)) { if (ranges.size() == 1) { byte_range_ = ranges[0]; @@ -129,7 +135,7 @@ // We don't support multiple range requests in one single URL request. // TODO(adamk): decide whether we want to support multiple range // requests. - range_parse_result_ = net::ERR_REQUEST_RANGE_NOT_SATISFIABLE; + NotifyFailed(net::ERR_REQUEST_RANGE_NOT_SATISFIABLE); } } } @@ -161,7 +167,7 @@ } if (!file_system_context_->CanServeURLRequest(url_)) { // In incognito mode the API is not usable and there should be no data. - NotifyStartError(URLRequestStatus::FromError(net::ERR_FILE_NOT_FOUND)); + NotifyFailed(net::ERR_FILE_NOT_FOUND); return; } file_system_context_->operation_runner()->GetMetadata( @@ -176,7 +182,7 @@ file_system_context_->CrackURL(request_->url()).is_valid()) { StartAsync(); } else { - NotifyStartError(URLRequestStatus::FromError(net::ERR_FILE_NOT_FOUND)); + NotifyFailed(net::ERR_FILE_NOT_FOUND); } } @@ -184,10 +190,9 @@ base::File::Error error_code, const base::File::Info& file_info) { if (error_code != base::File::FILE_OK) { - NotifyStartError(URLRequestStatus::FromError( - error_code == base::File::FILE_ERROR_INVALID_URL - ? net::ERR_INVALID_URL - : net::ERR_FILE_NOT_FOUND)); + NotifyFailed(error_code == base::File::FILE_ERROR_INVALID_URL + ? net::ERR_INVALID_URL + : net::ERR_FILE_NOT_FOUND); return; } @@ -197,14 +202,8 @@ is_directory_ = file_info.is_directory; - if (range_parse_result_ != net::OK) { - NotifyStartError(URLRequestStatus::FromError(range_parse_result_)); - return; - } - if (!byte_range_.ComputeBounds(file_info.size)) { - NotifyStartError( - URLRequestStatus::FromError(net::ERR_REQUEST_RANGE_NOT_SATISFIABLE)); + NotifyFailed(net::ERR_REQUEST_RANGE_NOT_SATISFIABLE); return; } @@ -228,12 +227,17 @@ } void FileSystemURLRequestJob::DidRead(int result) { - if (result >= 0) { - remaining_bytes_ -= result; - DCHECK_GE(remaining_bytes_, 0); - } + if (result > 0) + SetStatus(URLRequestStatus()); // Clear the IO_PENDING status + else if (result == 0) + NotifyDone(URLRequestStatus()); + else + NotifyFailed(result); - ReadRawDataComplete(result); + remaining_bytes_ -= result; + DCHECK_GE(remaining_bytes_, 0); + + NotifyReadComplete(result); } bool FileSystemURLRequestJob::IsRedirectResponse(GURL* location, @@ -253,4 +257,8 @@ return false; } +void FileSystemURLRequestJob::NotifyFailed(int rv) { + NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, rv)); +} + } // namespace storage
diff --git a/storage/browser/fileapi/file_system_url_request_job.h b/storage/browser/fileapi/file_system_url_request_job.h index 308b66c..e442cae3 100644 --- a/storage/browser/fileapi/file_system_url_request_job.h +++ b/storage/browser/fileapi/file_system_url_request_job.h
@@ -11,7 +11,6 @@ #include "base/memory/ref_counted.h" #include "base/memory/scoped_ptr.h" #include "base/memory/weak_ptr.h" -#include "net/base/net_errors.h" #include "net/http/http_byte_range.h" #include "net/url_request/url_request_job.h" #include "storage/browser/fileapi/file_system_url.h" @@ -42,7 +41,7 @@ // URLRequestJob methods: void Start() override; void Kill() override; - int ReadRawData(net::IOBuffer* buf, int buf_size) override; + bool ReadRawData(net::IOBuffer* buf, int buf_size, int* bytes_read) override; bool IsRedirectResponse(GURL* location, int* http_status_code) override; void SetExtraRequestHeaders(const net::HttpRequestHeaders& headers) override; void GetResponseInfo(net::HttpResponseInfo* info) override; @@ -61,6 +60,7 @@ void DidGetMetadata(base::File::Error error_code, const base::File::Info& file_info); void DidRead(int result); + void NotifyFailed(int rv); const std::string storage_domain_; FileSystemContext* file_system_context_; @@ -69,7 +69,6 @@ bool is_directory_; scoped_ptr<net::HttpResponseInfo> response_info_; int64 remaining_bytes_; - net::Error range_parse_result_; net::HttpByteRange byte_range_; base::WeakPtrFactory<FileSystemURLRequestJob> weak_factory_;
diff --git a/storage/browser/quota/quota_database.cc b/storage/browser/quota/quota_database.cc index 36632c6..3a28f02 100644 --- a/storage/browser/quota/quota_database.cc +++ b/storage/browser/quota/quota_database.cc
@@ -4,6 +4,7 @@ #include "storage/browser/quota/quota_database.h" +#include <tuple> #include <vector> #include "base/auto_reset.h" @@ -793,22 +794,14 @@ bool operator<(const QuotaDatabase::QuotaTableEntry& lhs, const QuotaDatabase::QuotaTableEntry& rhs) { - if (lhs.host < rhs.host) return true; - if (rhs.host < lhs.host) return false; - if (lhs.type < rhs.type) return true; - if (rhs.type < lhs.type) return false; - return lhs.quota < rhs.quota; + return std::tie(lhs.host, lhs.type, lhs.quota) < + std::tie(rhs.host, rhs.type, rhs.quota); } bool operator<(const QuotaDatabase::OriginInfoTableEntry& lhs, const QuotaDatabase::OriginInfoTableEntry& rhs) { - if (lhs.origin < rhs.origin) return true; - if (rhs.origin < lhs.origin) return false; - if (lhs.type < rhs.type) return true; - if (rhs.type < lhs.type) return false; - if (lhs.used_count < rhs.used_count) return true; - if (rhs.used_count < lhs.used_count) return false; - return lhs.last_access_time < rhs.last_access_time; + return std::tie(lhs.origin, lhs.type, lhs.used_count, lhs.last_access_time) < + std::tie(rhs.origin, rhs.type, rhs.used_count, rhs.last_access_time); } } // namespace storage
diff --git a/storage/common/BUILD.gn b/storage/common/BUILD.gn index 605fd41..35669e1 100644 --- a/storage/common/BUILD.gn +++ b/storage/common/BUILD.gn
@@ -40,7 +40,7 @@ "//base", "//base/third_party/dynamic_annotations", "//net", - "//url", "//third_party/WebKit/public:blink_headers", + "//url", ] }
diff --git a/sync/BUILD.gn b/sync/BUILD.gn index 9f064b5..664fa462 100644 --- a/sync/BUILD.gn +++ b/sync/BUILD.gn
@@ -25,8 +25,11 @@ "api/attachments/attachment_store.h", "api/attachments/attachment_store_backend.cc", "api/attachments/attachment_store_backend.h", + "api/data_batch.h", "api/entity_data.cc", "api/entity_data.h", + "api/metadata_batch.h", + "api/metadata_changes.h", "api/model_type_change_processor.cc", "api/model_type_change_processor.h", "api/model_type_service.cc", @@ -434,10 +437,10 @@ "//google_apis", "//net", "//sql", + "//sync/protocol", "//third_party/leveldatabase", "//third_party/zlib", "//url", - "//sync/protocol", ] if (is_android) { @@ -529,9 +532,9 @@ public_deps = [ "//base", + "//sync", "//testing/gmock", "//testing/gtest", - "//sync", ] defines = [ "SYNC_TEST" ] @@ -559,10 +562,10 @@ ] public_deps = [ - "//base", - "//testing/gtest", - "//sync", ":test_support_sync_core", + "//base", + "//sync", + "//testing/gtest", ] defines = [ "SYNC_TEST" ] @@ -772,8 +775,8 @@ deps = [ "//base", "//net", - "//testing/gtest", "//sync", + "//testing/gtest", "//url", ] @@ -840,10 +843,10 @@ android_library("sync_java_test_support") { testonly = true deps = [ - "android:sync_java", "//base:base_java", "//base:base_java_test_support", "//third_party/jsr-305:jsr_305_javalib", + "android:sync_java", ] DEPRECATED_java_in_dir = "test/android/javatests/src" }
diff --git a/sync/android/BUILD.gn b/sync/android/BUILD.gn index 48f6760..e7bd9e94 100644 --- a/sync/android/BUILD.gn +++ b/sync/android/BUILD.gn
@@ -9,10 +9,10 @@ deps = [ "//base:base_java", "//net/android:net_java", + "//third_party/android_tools:android_gcm_java", "//third_party/cacheinvalidation:cacheinvalidation_javalib", "//third_party/cacheinvalidation:cacheinvalidation_proto_java", "//third_party/jsr-305:jsr_305_javalib", - "//third_party/android_tools:android_gcm_java", ] srcjar_deps = [ ":java_enums" ] DEPRECATED_java_in_dir = "java/src"
diff --git a/sync/api/data_batch.h b/sync/api/data_batch.h new file mode 100644 index 0000000..63359cf --- /dev/null +++ b/sync/api/data_batch.h
@@ -0,0 +1,21 @@ +// Copyright 2015 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 SYNC_API_DATA_BATCH_H_ +#define SYNC_API_DATA_BATCH_H_ + +#include "sync/base/sync_export.h" + +namespace syncer_v2 { + +// Interface used by the processor and service to communicate about data. +class SYNC_EXPORT DataBatch { + public: + DataBatch() {} + virtual ~DataBatch() {} +}; + +} // namespace syncer_v2 + +#endif // SYNC_API_DATA_BATCH_H_
diff --git a/sync/api/entity_data.h b/sync/api/entity_data.h index 66a6a99..4fe88510 100644 --- a/sync/api/entity_data.h +++ b/sync/api/entity_data.h
@@ -25,6 +25,7 @@ }; typedef syncer::ProtoValuePtr<EntityData, EntityDataTraits> EntityDataPtr; +typedef std::vector<EntityDataPtr> EntityDataList; // A light-weight container for sync entity data which represents either // local data created on the ModelTypeService side or remote data created
diff --git a/sync/api/metadata_batch.h b/sync/api/metadata_batch.h new file mode 100644 index 0000000..56ffffb --- /dev/null +++ b/sync/api/metadata_batch.h
@@ -0,0 +1,21 @@ +// Copyright 2015 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 SYNC_API_METADATA_BATCH_H_ +#define SYNC_API_METADATA_BATCH_H_ + +#include "sync/base/sync_export.h" + +namespace syncer_v2 { + +// Interface used by the processor and service to communicate about metadata. +class SYNC_EXPORT MetadataBatch { + public: + MetadataBatch() {} + virtual ~MetadataBatch() {} +}; + +} // namespace syncer_v2 + +#endif // SYNC_API_METADATA_BATCH_H_
diff --git a/sync/api/metadata_changes.h b/sync/api/metadata_changes.h new file mode 100644 index 0000000..a3d4d3ba --- /dev/null +++ b/sync/api/metadata_changes.h
@@ -0,0 +1,21 @@ +// Copyright 2015 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 SYNC_API_METADATA_CHANGES_H_ +#define SYNC_API_METADATA_CHANGES_H_ + +#include "sync/base/sync_export.h" + +namespace syncer_v2 { + +// Interface used by the processor and service to communicate about metadata. +class SYNC_EXPORT MetadataChanges { + public: + MetadataChanges() {} + virtual ~MetadataChanges() {} +}; + +} // namespace syncer_v2 + +#endif // SYNC_API_METADATA_CHANGES_H_
diff --git a/sync/api/model_type_change_processor.h b/sync/api/model_type_change_processor.h index 85f8d161..7781a0e3 100644 --- a/sync/api/model_type_change_processor.h +++ b/sync/api/model_type_change_processor.h
@@ -5,16 +5,36 @@ #ifndef SYNC_API_MODEL_TYPE_CHANGE_PROCESSOR_H_ #define SYNC_API_MODEL_TYPE_CHANGE_PROCESSOR_H_ +#include <string> + +#include "base/memory/scoped_ptr.h" +#include "sync/api/entity_data.h" #include "sync/base/sync_export.h" +namespace syncer { +class SyncError; +} // namespace syncer + namespace syncer_v2 { +class MetadataChanges; + // Interface used by the ModelTypeService to inform sync of local // changes. class SYNC_EXPORT ModelTypeChangeProcessor { public: ModelTypeChangeProcessor(); virtual ~ModelTypeChangeProcessor(); + + // Inform the processor of a new or updated entity. + virtual void Put(const std::string& client_key, + const std::string& non_unique_name, + const sync_pb::EntitySpecifics& specifics, + MetadataChanges* metadata_changes) = 0; + + // Inform the processor of a deleted entity. + virtual void Delete(const std::string& client_key, + MetadataChanges* metadata_changes) = 0; }; } // namespace syncer_v2
diff --git a/sync/api/model_type_service.cc b/sync/api/model_type_service.cc index 61ea860..759860a7 100644 --- a/sync/api/model_type_service.cc +++ b/sync/api/model_type_service.cc
@@ -10,4 +10,18 @@ ModelTypeService::~ModelTypeService() {} +syncer_v2::ModelTypeChangeProcessor* ModelTypeService::change_processor() { + return change_processor_.get(); +} + +void ModelTypeService::set_change_processor( + scoped_ptr<syncer_v2::ModelTypeChangeProcessor> change_processor) { + DCHECK(!change_processor_); + change_processor_.swap(change_processor); +} + +void ModelTypeService::clear_change_processor() { + change_processor_.reset(); +} + } // namespace syncer_v2
diff --git a/sync/api/model_type_service.h b/sync/api/model_type_service.h index d01dc8718..473c9c172 100644 --- a/sync/api/model_type_service.h +++ b/sync/api/model_type_service.h
@@ -5,17 +5,78 @@ #ifndef SYNC_API_MODEL_TYPE_SERVICE_H_ #define SYNC_API_MODEL_TYPE_SERVICE_H_ +#include <string> +#include <vector> + +#include "base/callback.h" +#include "base/memory/scoped_ptr.h" +#include "sync/api/entity_data.h" +#include "sync/api/model_type_change_processor.h" #include "sync/base/sync_export.h" +namespace syncer { +class SyncError; +} // namespace syncer + namespace syncer_v2 { +class DataBatch; +class MetadataBatch; +class MetadataChanges; + // Interface implemented by model types to receive updates from sync via the // SharedModelTypeProcessor. Provides a way for sync to update the data and // metadata for entities, as well as the model type state. class SYNC_EXPORT ModelTypeService { public: + typedef base::Callback<void(syncer::SyncError, scoped_ptr<DataBatch>)> + DataCallback; + typedef base::Callback<void(syncer::SyncError, scoped_ptr<MetadataBatch>)> + MetadataCallback; + typedef std::vector<std::string> ClientKeyList; + ModelTypeService(); + virtual ~ModelTypeService(); + + // Creates an object used to communicate changes in the sync metadata to the + // model type store. + virtual MetadataChanges* CreateMetadataChanges() = 0; + + // Perform the initial merge of data from the sync server. Should only need + // to be called when sync is first turned on, not on every restart. + virtual syncer::SyncError MergeSyncData(MetadataChanges* metadata_changes, + EntityDataList entity_data_list) = 0; + + // Apply changes from the sync server locally. + // TODO(skym): The change type should be in here somehow. + virtual syncer::SyncError ApplySyncChanges( + MetadataChanges* metadata_changes, + EntityDataList entity_data_list) = 0; + + // Asynchronously retrieve the sync metadata. + virtual void LoadMetadata(MetadataCallback callback) = 0; + + // Asynchronously retrieve the corresponding sync data for |client_keys|. + virtual void GetData(ClientKeyList client_keys, DataCallback callback) = 0; + + // Asynchronously retrieve all of the local sync data. + virtual void GetAllData(DataCallback callback) = 0; + + // Get or generate a client tag for |entity_data|. + virtual std::string GetClientTag(const EntityData* entity_data) = 0; + + // TODO(skym): See crbug/547087, do we need all these accessors? + syncer_v2::ModelTypeChangeProcessor* change_processor(); + + void set_change_processor( + scoped_ptr<syncer_v2::ModelTypeChangeProcessor> change_processor); + + void clear_change_processor(); + + private: + // Recieves ownership in set_change_processor(...). + scoped_ptr<syncer_v2::ModelTypeChangeProcessor> change_processor_; }; } // namespace syncer_v2
diff --git a/sync/internal_api/public/model_type_processor.h b/sync/internal_api/public/model_type_processor.h index 0f1971e..c4ac3431 100644 --- a/sync/internal_api/public/model_type_processor.h +++ b/sync/internal_api/public/model_type_processor.h
@@ -18,7 +18,7 @@ ModelTypeProcessor(); virtual ~ModelTypeProcessor(); - // Callback used to process the handshake response. + // Callback used to process the handshake response from the worker. virtual void OnConnect(scoped_ptr<CommitQueue> commit_queue) = 0; // Informs this object that some of its commit requests have been @@ -35,6 +35,6 @@ const UpdateResponseDataList& pending_updates) = 0; }; -} // namespace syncer +} // namespace syncer_v2 #endif // SYNC_INTERNAL_API_PUBLIC_MODEL_TYPE_PROCESSOR_H_
diff --git a/sync/internal_api/public/shared_model_type_processor.h b/sync/internal_api/public/shared_model_type_processor.h index 6b700785..1c61a00 100644 --- a/sync/internal_api/public/shared_model_type_processor.h +++ b/sync/internal_api/public/shared_model_type_processor.h
@@ -2,8 +2,10 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef SYNC_INTERNAL_API_PUBLIC_MODEL_TYPE_SYNC_PROXY_IMPL_H_ -#define SYNC_INTERNAL_API_PUBLIC_MODEL_TYPE_SYNC_PROXY_IMPL_H_ +#ifndef SYNC_INTERNAL_API_PUBLIC_SHARED_MODEL_TYPE_PROCESSOR_H_ +#define SYNC_INTERNAL_API_PUBLIC_SHARED_MODEL_TYPE_PROCESSOR_H_ + +#include <string> #include "base/containers/scoped_ptr_map.h" #include "base/memory/scoped_ptr.h" @@ -60,29 +62,16 @@ // Another call to Enable() can be used to re-establish this connection. void Disable(); - // Callback used to process the handshake response from the sync thread. - void OnConnect(scoped_ptr<CommitQueue> worker) override; - // Returns true if the handshake with sync thread is complete. bool IsConnected() const; - // Requests that an item be stored in sync. - void Put(const std::string& client_tag, - const sync_pb::EntitySpecifics& specifics); - - // Deletes an item from sync. - void Delete(const std::string& client_tag); - - // Informs this object that some of its commit requests have been - // successfully serviced. - void OnCommitCompleted(const DataTypeState& type_state, - const CommitResponseDataList& response_list) override; - - // Informs this object that there are some incoming updates is should - // handle. - void OnUpdateReceived(const DataTypeState& type_state, - const UpdateResponseDataList& response_list, - const UpdateResponseDataList& pending_updates) override; + // ModelTypeChangeProcessor implementation. + void Put(const std::string& client_key, + const std::string& non_unique_name, + const sync_pb::EntitySpecifics& specifics, + MetadataChanges* metadata_changes) override; + void Delete(const std::string& client_key, + MetadataChanges* metadata_changes) override; // Returns the list of pending updates. // @@ -96,6 +85,14 @@ // ProfileSyncService. base::WeakPtr<SharedModelTypeProcessor> AsWeakPtrForUI(); + // ModelTypeProcessor implementation. + void OnConnect(scoped_ptr<CommitQueue> worker) override; + void OnCommitCompleted(const DataTypeState& type_state, + const CommitResponseDataList& response_list) override; + void OnUpdateReceived(const DataTypeState& type_state, + const UpdateResponseDataList& response_list, + const UpdateResponseDataList& pending_updates) override; + private: typedef base::ScopedPtrMap<std::string, scoped_ptr<ModelTypeEntity>> EntityMap; @@ -155,4 +152,4 @@ } // namespace syncer_v2 -#endif // SYNC_INTERNAL_API_PUBLIC_MODEL_TYPE_SYNC_PROXY_IMPL_H_ +#endif // SYNC_INTERNAL_API_PUBLIC_SHARED_MODEL_TYPE_PROCESSOR_H_
diff --git a/sync/internal_api/shared_model_type_processor.cc b/sync/internal_api/shared_model_type_processor.cc index df96e01..01e43c0 100644 --- a/sync/internal_api/shared_model_type_processor.cc +++ b/sync/internal_api/shared_model_type_processor.cc
@@ -85,7 +85,7 @@ is_enabled_ = true; - // TODO: At some point, this should be loaded from storage. + // TODO(stanisc): At some point, this should be loaded from storage. data_type_state_.progress_marker.set_data_type_id( GetSpecificsFieldNumberFromModelType(type_)); @@ -145,8 +145,14 @@ FlushPendingCommitRequests(); } -void SharedModelTypeProcessor::Put(const std::string& client_tag, - const sync_pb::EntitySpecifics& specifics) { +void SharedModelTypeProcessor::Put( + const std::string& client_tag, + const std::string& non_unique_name, + const sync_pb::EntitySpecifics& specifics, + MetadataChanges* metadata_changes) { + // TODO(skym): Update for new approach. Different objects, different caching, + // different loopups, metadat_changes, etc. + DCHECK_EQ(type_, syncer::GetModelTypeFromSpecifics(specifics)); const std::string client_tag_hash( @@ -165,16 +171,20 @@ FlushPendingCommitRequests(); } -void SharedModelTypeProcessor::Delete(const std::string& client_tag) { +void SharedModelTypeProcessor::Delete(const std::string& client_key, + MetadataChanges* metadata_changes) { + // TODO(skym): Update for new approach. Different caching, different lookup, + // metadata changes. + const std::string client_tag_hash( - syncer::syncable::GenerateSyncableHash(type_, client_tag)); + syncer::syncable::GenerateSyncableHash(type_, client_key)); EntityMap::const_iterator it = entities_.find(client_tag_hash); if (it == entities_.end()) { // That's unusual, but not necessarily a bad thing. // Missing is as good as deleted as far as the model is concerned. DLOG(WARNING) << "Attempted to delete missing item." - << " client tag: " << client_tag; + << " client tag: " << client_key; } else { ModelTypeEntity* entity = it->second; entity->Delete(); @@ -266,7 +276,7 @@ response_data.response_version, data.is_deleted(), data.specifics, data.modification_time, response_data.encryption_key_name); - // TODO: Do something special when conflicts are detected. + // TODO(rlarocque): Do something special when conflicts are detected. } // If the received entity has out of date encryption, we schedule another @@ -313,8 +323,8 @@ // We may have new reasons to commit by the time this function is done. FlushPendingCommitRequests(); - // TODO: Inform the model of the new or updated data. - // TODO: Persist the new data on disk. + // TODO(rlarocque): Inform the model of the new or updated data. + // TODO(rlarocque): Persist the new data on disk. } UpdateResponseDataList SharedModelTypeProcessor::GetPendingUpdates() { @@ -342,4 +352,4 @@ data_type_state_ = DataTypeState(); } -} // namespace syncer +} // namespace syncer_v2
diff --git a/sync/internal_api/shared_model_type_processor_unittest.cc b/sync/internal_api/shared_model_type_processor_unittest.cc index 54475bbb..2b5bc64 100644 --- a/sync/internal_api/shared_model_type_processor_unittest.cc +++ b/sync/internal_api/shared_model_type_processor_unittest.cc
@@ -201,12 +201,12 @@ void SharedModelTypeProcessorTest::WriteItem(const std::string& tag, const std::string& value) { - const std::string tag_hash = GenerateTagHash(tag); - type_processor_->Put(tag, GenerateSpecifics(tag, value)); + sync_pb::EntitySpecifics specifics = GenerateSpecifics(tag, value); + type_processor_->Put(tag, std::string(), specifics, nullptr); } void SharedModelTypeProcessorTest::DeleteItem(const std::string& tag) { - type_processor_->Delete(tag); + type_processor_->Delete(tag, nullptr); } void SharedModelTypeProcessorTest::OnInitialSyncDone() {
diff --git a/sync/sync.gyp b/sync/sync.gyp index 863347984..0690495 100644 --- a/sync/sync.gyp +++ b/sync/sync.gyp
@@ -76,8 +76,11 @@ 'api/attachments/attachment_store.h', 'api/attachments/attachment_store_backend.cc', 'api/attachments/attachment_store_backend.h', + 'api/data_batch.h', 'api/entity_data.cc', 'api/entity_data.h', + 'api/metadata_batch.h', + 'api/metadata_changes.h', 'api/model_type_change_processor.cc', 'api/model_type_change_processor.h', 'api/model_type_service.cc',
diff --git a/testing/android/junit/BUILD.gn b/testing/android/junit/BUILD.gn index d479629..018760ab 100644 --- a/testing/android/junit/BUILD.gn +++ b/testing/android/junit/BUILD.gn
@@ -13,8 +13,8 @@ deps = [ "//third_party/junit", "//third_party/mockito:mockito_java", - "//third_party/robolectric:robolectric_java", "//third_party/robolectric:android-all-4.3_r2-robolectric-0", + "//third_party/robolectric:robolectric_java", ] }
diff --git a/testing/libfuzzer/fuzzers/BUILD.gn b/testing/libfuzzer/fuzzers/BUILD.gn index 60126ff2..740bcef 100644 --- a/testing/libfuzzer/fuzzers/BUILD.gn +++ b/testing/libfuzzer/fuzzers/BUILD.gn
@@ -164,6 +164,7 @@ "url_parse_fuzzer.cc", ] deps = [ + "//base:i18n", "//testing/libfuzzer:libfuzzer_main", "//url:url", ]
diff --git a/testing/libfuzzer/fuzzers/url_parse_fuzzer.cc b/testing/libfuzzer/fuzzers/url_parse_fuzzer.cc index 48df2c8..ce51cee 100644 --- a/testing/libfuzzer/fuzzers/url_parse_fuzzer.cc +++ b/testing/libfuzzer/fuzzers/url_parse_fuzzer.cc
@@ -2,8 +2,21 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "base/at_exit.h" +#include "base/i18n/icu_util.h" #include "url/gurl.h" +struct TestCase { + TestCase() { + CHECK(base::i18n::InitializeICU()); + } + + // used by ICU integration. + base::AtExitManager at_exit_manager; +}; + +TestCase* test_case = new TestCase(); + // Entry point for LibFuzzer. extern "C" int LLVMFuzzerTestOneInput(const unsigned char *data, unsigned long size) {
diff --git a/third_party/WebKit/LayoutTests/OilpanExpectations b/third_party/WebKit/LayoutTests/OilpanExpectations index 9bf81c0..c26a5591 100644 --- a/third_party/WebKit/LayoutTests/OilpanExpectations +++ b/third_party/WebKit/LayoutTests/OilpanExpectations
@@ -39,7 +39,4 @@ crbug.com/501229 fast/forms/associatedFormControls-leak-nodes.html [ Failure ] -crbug.com/506186 accessibility/axobjectcache-leaks-node.html [ Failure ] -crbug.com/506186 fast/spatial-navigation/snav-imagemap-leak-document.html [ Failure ] - crbug.com/417181 http/tests/xmlhttprequest/abort-on-changestate-headers-received.html [ Failure Pass ]
diff --git a/third_party/WebKit/LayoutTests/fast/backgrounds/size/contain-and-cover-zoomed-expected.png b/third_party/WebKit/LayoutTests/fast/backgrounds/size/contain-and-cover-zoomed-expected.png index 510c507..ce057497 100644 --- a/third_party/WebKit/LayoutTests/fast/backgrounds/size/contain-and-cover-zoomed-expected.png +++ b/third_party/WebKit/LayoutTests/fast/backgrounds/size/contain-and-cover-zoomed-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/fast/canvas/canvas-2d-imageData-create-nonfinite-expected.txt b/third_party/WebKit/LayoutTests/fast/canvas/canvas-2d-imageData-create-nonfinite-expected.txt index 316d4f0..b1f07ec 100644 --- a/third_party/WebKit/LayoutTests/fast/canvas/canvas-2d-imageData-create-nonfinite-expected.txt +++ b/third_party/WebKit/LayoutTests/fast/canvas/canvas-2d-imageData-create-nonfinite-expected.txt
@@ -3,13 +3,13 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". -PASS ctx.createImageData(Infinity, Infinity) threw exception TypeError: Failed to execute 'createImageData' on 'CanvasRenderingContext2D': The provided float value is non-finite.. -PASS ctx.createImageData(Infinity, 10) threw exception TypeError: Failed to execute 'createImageData' on 'CanvasRenderingContext2D': The provided float value is non-finite.. -PASS ctx.createImageData(-Infinity, 10) threw exception TypeError: Failed to execute 'createImageData' on 'CanvasRenderingContext2D': The provided float value is non-finite.. -PASS ctx.createImageData(10, Infinity) threw exception TypeError: Failed to execute 'createImageData' on 'CanvasRenderingContext2D': The provided float value is non-finite.. -PASS ctx.createImageData(10, -Infinity) threw exception TypeError: Failed to execute 'createImageData' on 'CanvasRenderingContext2D': The provided float value is non-finite.. -PASS ctx.createImageData(NaN, 10) threw exception TypeError: Failed to execute 'createImageData' on 'CanvasRenderingContext2D': The provided float value is non-finite.. -PASS ctx.createImageData(10, NaN) threw exception TypeError: Failed to execute 'createImageData' on 'CanvasRenderingContext2D': The provided float value is non-finite.. +PASS ctx.createImageData(Infinity, Infinity) threw exception TypeError: Failed to execute 'createImageData' on 'CanvasRenderingContext2D': The provided double value is non-finite.. +PASS ctx.createImageData(Infinity, 10) threw exception TypeError: Failed to execute 'createImageData' on 'CanvasRenderingContext2D': The provided double value is non-finite.. +PASS ctx.createImageData(-Infinity, 10) threw exception TypeError: Failed to execute 'createImageData' on 'CanvasRenderingContext2D': The provided double value is non-finite.. +PASS ctx.createImageData(10, Infinity) threw exception TypeError: Failed to execute 'createImageData' on 'CanvasRenderingContext2D': The provided double value is non-finite.. +PASS ctx.createImageData(10, -Infinity) threw exception TypeError: Failed to execute 'createImageData' on 'CanvasRenderingContext2D': The provided double value is non-finite.. +PASS ctx.createImageData(NaN, 10) threw exception TypeError: Failed to execute 'createImageData' on 'CanvasRenderingContext2D': The provided double value is non-finite.. +PASS ctx.createImageData(10, NaN) threw exception TypeError: Failed to execute 'createImageData' on 'CanvasRenderingContext2D': The provided double value is non-finite.. PASS successfullyParsed is true TEST COMPLETE
diff --git a/third_party/WebKit/LayoutTests/fast/canvas/canvas-getImageData-invalid-expected.txt b/third_party/WebKit/LayoutTests/fast/canvas/canvas-getImageData-invalid-expected.txt index d03efbd..f61dec2 100644 --- a/third_party/WebKit/LayoutTests/fast/canvas/canvas-getImageData-invalid-expected.txt +++ b/third_party/WebKit/LayoutTests/fast/canvas/canvas-getImageData-invalid-expected.txt
@@ -3,18 +3,18 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". -PASS ctx.getImageData(NaN, 10, 10, 10) threw exception TypeError: Failed to execute 'getImageData' on 'CanvasRenderingContext2D': The provided float value is non-finite.. -PASS ctx.getImageData(10, NaN, 10, 10) threw exception TypeError: Failed to execute 'getImageData' on 'CanvasRenderingContext2D': The provided float value is non-finite.. -PASS ctx.getImageData(10, 10, NaN, 10) threw exception TypeError: Failed to execute 'getImageData' on 'CanvasRenderingContext2D': The provided float value is non-finite.. -PASS ctx.getImageData(10, 10, 10, NaN) threw exception TypeError: Failed to execute 'getImageData' on 'CanvasRenderingContext2D': The provided float value is non-finite.. -PASS ctx.getImageData(Infinity, 10, 10, 10) threw exception TypeError: Failed to execute 'getImageData' on 'CanvasRenderingContext2D': The provided float value is non-finite.. -PASS ctx.getImageData(10, Infinity, 10, 10) threw exception TypeError: Failed to execute 'getImageData' on 'CanvasRenderingContext2D': The provided float value is non-finite.. -PASS ctx.getImageData(10, 10, Infinity, 10) threw exception TypeError: Failed to execute 'getImageData' on 'CanvasRenderingContext2D': The provided float value is non-finite.. -PASS ctx.getImageData(10, 10, 10, Infinity) threw exception TypeError: Failed to execute 'getImageData' on 'CanvasRenderingContext2D': The provided float value is non-finite.. -PASS ctx.getImageData(undefined, 10, 10, 10) threw exception TypeError: Failed to execute 'getImageData' on 'CanvasRenderingContext2D': The provided float value is non-finite.. -PASS ctx.getImageData(10, undefined, 10, 10) threw exception TypeError: Failed to execute 'getImageData' on 'CanvasRenderingContext2D': The provided float value is non-finite.. -PASS ctx.getImageData(10, 10, undefined, 10) threw exception TypeError: Failed to execute 'getImageData' on 'CanvasRenderingContext2D': The provided float value is non-finite.. -PASS ctx.getImageData(10, 10, 10, undefined) threw exception TypeError: Failed to execute 'getImageData' on 'CanvasRenderingContext2D': The provided float value is non-finite.. +PASS ctx.getImageData(NaN, 10, 10, 10) threw exception TypeError: Failed to execute 'getImageData' on 'CanvasRenderingContext2D': The provided double value is non-finite.. +PASS ctx.getImageData(10, NaN, 10, 10) threw exception TypeError: Failed to execute 'getImageData' on 'CanvasRenderingContext2D': The provided double value is non-finite.. +PASS ctx.getImageData(10, 10, NaN, 10) threw exception TypeError: Failed to execute 'getImageData' on 'CanvasRenderingContext2D': The provided double value is non-finite.. +PASS ctx.getImageData(10, 10, 10, NaN) threw exception TypeError: Failed to execute 'getImageData' on 'CanvasRenderingContext2D': The provided double value is non-finite.. +PASS ctx.getImageData(Infinity, 10, 10, 10) threw exception TypeError: Failed to execute 'getImageData' on 'CanvasRenderingContext2D': The provided double value is non-finite.. +PASS ctx.getImageData(10, Infinity, 10, 10) threw exception TypeError: Failed to execute 'getImageData' on 'CanvasRenderingContext2D': The provided double value is non-finite.. +PASS ctx.getImageData(10, 10, Infinity, 10) threw exception TypeError: Failed to execute 'getImageData' on 'CanvasRenderingContext2D': The provided double value is non-finite.. +PASS ctx.getImageData(10, 10, 10, Infinity) threw exception TypeError: Failed to execute 'getImageData' on 'CanvasRenderingContext2D': The provided double value is non-finite.. +PASS ctx.getImageData(undefined, 10, 10, 10) threw exception TypeError: Failed to execute 'getImageData' on 'CanvasRenderingContext2D': The provided double value is non-finite.. +PASS ctx.getImageData(10, undefined, 10, 10) threw exception TypeError: Failed to execute 'getImageData' on 'CanvasRenderingContext2D': The provided double value is non-finite.. +PASS ctx.getImageData(10, 10, undefined, 10) threw exception TypeError: Failed to execute 'getImageData' on 'CanvasRenderingContext2D': The provided double value is non-finite.. +PASS ctx.getImageData(10, 10, 10, undefined) threw exception TypeError: Failed to execute 'getImageData' on 'CanvasRenderingContext2D': The provided double value is non-finite.. PASS ctx.getImageData(10, 10, 0, 10) threw exception IndexSizeError: Failed to execute 'getImageData' on 'CanvasRenderingContext2D': The source width is 0.. PASS ctx.getImageData(10, 10, 10, 0) threw exception IndexSizeError: Failed to execute 'getImageData' on 'CanvasRenderingContext2D': The source height is 0.. PASS successfullyParsed is true
diff --git a/third_party/WebKit/LayoutTests/fast/canvas/canvas-putImageData-expected.txt b/third_party/WebKit/LayoutTests/fast/canvas/canvas-putImageData-expected.txt index 80c9c2b5..4ad84d86 100644 --- a/third_party/WebKit/LayoutTests/fast/canvas/canvas-putImageData-expected.txt +++ b/third_party/WebKit/LayoutTests/fast/canvas/canvas-putImageData-expected.txt
@@ -145,24 +145,24 @@ PASS getPixel(1,1) is [0,128,0,255] PASS getPixel(9,9) is [0,128,0,255] PASS context.putImageData({}, 0, 0) threw exception TypeError: Failed to execute 'putImageData' on 'CanvasRenderingContext2D': parameter 1 is not of type 'ImageData'.. -PASS context.putImageData(buffer, NaN, 0, 0, 0, 0, 0) threw exception TypeError: Failed to execute 'putImageData' on 'CanvasRenderingContext2D': The provided float value is non-finite.. -PASS context.putImageData(buffer, 0, NaN, 0, 0, 0, 0) threw exception TypeError: Failed to execute 'putImageData' on 'CanvasRenderingContext2D': The provided float value is non-finite.. -PASS context.putImageData(buffer, 0, 0, NaN, 0, 0, 0) threw exception TypeError: Failed to execute 'putImageData' on 'CanvasRenderingContext2D': The provided float value is non-finite.. -PASS context.putImageData(buffer, 0, 0, 0, NaN, 0, 0) threw exception TypeError: Failed to execute 'putImageData' on 'CanvasRenderingContext2D': The provided float value is non-finite.. -PASS context.putImageData(buffer, 0, 0, 0, 0, NaN, 0) threw exception TypeError: Failed to execute 'putImageData' on 'CanvasRenderingContext2D': The provided float value is non-finite.. -PASS context.putImageData(buffer, 0, 0, 0, 0, 0, NaN) threw exception TypeError: Failed to execute 'putImageData' on 'CanvasRenderingContext2D': The provided float value is non-finite.. -PASS context.putImageData(buffer, Infinity, 0, 0, 0, 0, 0) threw exception TypeError: Failed to execute 'putImageData' on 'CanvasRenderingContext2D': The provided float value is non-finite.. -PASS context.putImageData(buffer, 0, Infinity, 0, 0, 0, 0) threw exception TypeError: Failed to execute 'putImageData' on 'CanvasRenderingContext2D': The provided float value is non-finite.. -PASS context.putImageData(buffer, 0, 0, Infinity, 0, 0, 0) threw exception TypeError: Failed to execute 'putImageData' on 'CanvasRenderingContext2D': The provided float value is non-finite.. -PASS context.putImageData(buffer, 0, 0, 0, Infinity, 0, 0) threw exception TypeError: Failed to execute 'putImageData' on 'CanvasRenderingContext2D': The provided float value is non-finite.. -PASS context.putImageData(buffer, 0, 0, 0, 0, Infinity, 0) threw exception TypeError: Failed to execute 'putImageData' on 'CanvasRenderingContext2D': The provided float value is non-finite.. -PASS context.putImageData(buffer, 0, 0, 0, 0, 0, Infinity) threw exception TypeError: Failed to execute 'putImageData' on 'CanvasRenderingContext2D': The provided float value is non-finite.. -PASS context.putImageData(buffer, undefined, 0, 0, 0, 0, 0) threw exception TypeError: Failed to execute 'putImageData' on 'CanvasRenderingContext2D': The provided float value is non-finite.. -PASS context.putImageData(buffer, 0, undefined, 0, 0, 0, 0) threw exception TypeError: Failed to execute 'putImageData' on 'CanvasRenderingContext2D': The provided float value is non-finite.. -PASS context.putImageData(buffer, 0, 0, undefined, 0, 0, 0) threw exception TypeError: Failed to execute 'putImageData' on 'CanvasRenderingContext2D': The provided float value is non-finite.. -PASS context.putImageData(buffer, 0, 0, 0, undefined, 0, 0) threw exception TypeError: Failed to execute 'putImageData' on 'CanvasRenderingContext2D': The provided float value is non-finite.. -PASS context.putImageData(buffer, 0, 0, 0, 0, undefined, 0) threw exception TypeError: Failed to execute 'putImageData' on 'CanvasRenderingContext2D': The provided float value is non-finite.. -PASS context.putImageData(buffer, 0, 0, 0, 0, 0, undefined) threw exception TypeError: Failed to execute 'putImageData' on 'CanvasRenderingContext2D': The provided float value is non-finite.. +PASS context.putImageData(buffer, NaN, 0, 0, 0, 0, 0) threw exception TypeError: Failed to execute 'putImageData' on 'CanvasRenderingContext2D': The provided double value is non-finite.. +PASS context.putImageData(buffer, 0, NaN, 0, 0, 0, 0) threw exception TypeError: Failed to execute 'putImageData' on 'CanvasRenderingContext2D': The provided double value is non-finite.. +PASS context.putImageData(buffer, 0, 0, NaN, 0, 0, 0) threw exception TypeError: Failed to execute 'putImageData' on 'CanvasRenderingContext2D': The provided double value is non-finite.. +PASS context.putImageData(buffer, 0, 0, 0, NaN, 0, 0) threw exception TypeError: Failed to execute 'putImageData' on 'CanvasRenderingContext2D': The provided double value is non-finite.. +PASS context.putImageData(buffer, 0, 0, 0, 0, NaN, 0) threw exception TypeError: Failed to execute 'putImageData' on 'CanvasRenderingContext2D': The provided double value is non-finite.. +PASS context.putImageData(buffer, 0, 0, 0, 0, 0, NaN) threw exception TypeError: Failed to execute 'putImageData' on 'CanvasRenderingContext2D': The provided double value is non-finite.. +PASS context.putImageData(buffer, Infinity, 0, 0, 0, 0, 0) threw exception TypeError: Failed to execute 'putImageData' on 'CanvasRenderingContext2D': The provided double value is non-finite.. +PASS context.putImageData(buffer, 0, Infinity, 0, 0, 0, 0) threw exception TypeError: Failed to execute 'putImageData' on 'CanvasRenderingContext2D': The provided double value is non-finite.. +PASS context.putImageData(buffer, 0, 0, Infinity, 0, 0, 0) threw exception TypeError: Failed to execute 'putImageData' on 'CanvasRenderingContext2D': The provided double value is non-finite.. +PASS context.putImageData(buffer, 0, 0, 0, Infinity, 0, 0) threw exception TypeError: Failed to execute 'putImageData' on 'CanvasRenderingContext2D': The provided double value is non-finite.. +PASS context.putImageData(buffer, 0, 0, 0, 0, Infinity, 0) threw exception TypeError: Failed to execute 'putImageData' on 'CanvasRenderingContext2D': The provided double value is non-finite.. +PASS context.putImageData(buffer, 0, 0, 0, 0, 0, Infinity) threw exception TypeError: Failed to execute 'putImageData' on 'CanvasRenderingContext2D': The provided double value is non-finite.. +PASS context.putImageData(buffer, undefined, 0, 0, 0, 0, 0) threw exception TypeError: Failed to execute 'putImageData' on 'CanvasRenderingContext2D': The provided double value is non-finite.. +PASS context.putImageData(buffer, 0, undefined, 0, 0, 0, 0) threw exception TypeError: Failed to execute 'putImageData' on 'CanvasRenderingContext2D': The provided double value is non-finite.. +PASS context.putImageData(buffer, 0, 0, undefined, 0, 0, 0) threw exception TypeError: Failed to execute 'putImageData' on 'CanvasRenderingContext2D': The provided double value is non-finite.. +PASS context.putImageData(buffer, 0, 0, 0, undefined, 0, 0) threw exception TypeError: Failed to execute 'putImageData' on 'CanvasRenderingContext2D': The provided double value is non-finite.. +PASS context.putImageData(buffer, 0, 0, 0, 0, undefined, 0) threw exception TypeError: Failed to execute 'putImageData' on 'CanvasRenderingContext2D': The provided double value is non-finite.. +PASS context.putImageData(buffer, 0, 0, 0, 0, 0, undefined) threw exception TypeError: Failed to execute 'putImageData' on 'CanvasRenderingContext2D': The provided double value is non-finite.. PASS context.putImageData(null, 0, 0, 0, 0, 0, 0) threw exception TypeError: Failed to execute 'putImageData' on 'CanvasRenderingContext2D': parameter 1 is not of type 'ImageData'.. PASS context.putImageData(undefined, 0, 0, 0, 0, 0, 0) threw exception TypeError: Failed to execute 'putImageData' on 'CanvasRenderingContext2D': parameter 1 is not of type 'ImageData'.. PASS successfullyParsed is true
diff --git a/third_party/WebKit/LayoutTests/fast/canvas/linearGradient-infinite-values-expected.txt b/third_party/WebKit/LayoutTests/fast/canvas/linearGradient-infinite-values-expected.txt index 4160c66..f257fe3 100644 --- a/third_party/WebKit/LayoutTests/fast/canvas/linearGradient-infinite-values-expected.txt +++ b/third_party/WebKit/LayoutTests/fast/canvas/linearGradient-infinite-values-expected.txt
@@ -3,18 +3,18 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". -PASS ctx.createLinearGradient(0, 0, 100, NaN) threw exception TypeError: Failed to execute 'createLinearGradient' on 'CanvasRenderingContext2D': The provided float value is non-finite.. -PASS ctx.createLinearGradient(0, 0, 100, Infinity) threw exception TypeError: Failed to execute 'createLinearGradient' on 'CanvasRenderingContext2D': The provided float value is non-finite.. -PASS ctx.createLinearGradient(0, 0, 100, -Infinity) threw exception TypeError: Failed to execute 'createLinearGradient' on 'CanvasRenderingContext2D': The provided float value is non-finite.. -PASS ctx.createLinearGradient(0, 0, NaN, 100) threw exception TypeError: Failed to execute 'createLinearGradient' on 'CanvasRenderingContext2D': The provided float value is non-finite.. -PASS ctx.createLinearGradient(0, 0, Infinity, 100) threw exception TypeError: Failed to execute 'createLinearGradient' on 'CanvasRenderingContext2D': The provided float value is non-finite.. -PASS ctx.createLinearGradient(0, 0, -Infinity, 100) threw exception TypeError: Failed to execute 'createLinearGradient' on 'CanvasRenderingContext2D': The provided float value is non-finite.. -PASS ctx.createLinearGradient(0, NaN, 100, 100) threw exception TypeError: Failed to execute 'createLinearGradient' on 'CanvasRenderingContext2D': The provided float value is non-finite.. -PASS ctx.createLinearGradient(0, Infinity, 100, 100) threw exception TypeError: Failed to execute 'createLinearGradient' on 'CanvasRenderingContext2D': The provided float value is non-finite.. -PASS ctx.createLinearGradient(0, -Infinity, 100, 100) threw exception TypeError: Failed to execute 'createLinearGradient' on 'CanvasRenderingContext2D': The provided float value is non-finite.. -PASS ctx.createLinearGradient(NaN, 0, 100, 100) threw exception TypeError: Failed to execute 'createLinearGradient' on 'CanvasRenderingContext2D': The provided float value is non-finite.. -PASS ctx.createLinearGradient(Infinity, 0, 100, 100) threw exception TypeError: Failed to execute 'createLinearGradient' on 'CanvasRenderingContext2D': The provided float value is non-finite.. -PASS ctx.createLinearGradient(-Infinity, 0, 100, 100) threw exception TypeError: Failed to execute 'createLinearGradient' on 'CanvasRenderingContext2D': The provided float value is non-finite.. +PASS ctx.createLinearGradient(0, 0, 100, NaN) threw exception TypeError: Failed to execute 'createLinearGradient' on 'CanvasRenderingContext2D': The provided double value is non-finite.. +PASS ctx.createLinearGradient(0, 0, 100, Infinity) threw exception TypeError: Failed to execute 'createLinearGradient' on 'CanvasRenderingContext2D': The provided double value is non-finite.. +PASS ctx.createLinearGradient(0, 0, 100, -Infinity) threw exception TypeError: Failed to execute 'createLinearGradient' on 'CanvasRenderingContext2D': The provided double value is non-finite.. +PASS ctx.createLinearGradient(0, 0, NaN, 100) threw exception TypeError: Failed to execute 'createLinearGradient' on 'CanvasRenderingContext2D': The provided double value is non-finite.. +PASS ctx.createLinearGradient(0, 0, Infinity, 100) threw exception TypeError: Failed to execute 'createLinearGradient' on 'CanvasRenderingContext2D': The provided double value is non-finite.. +PASS ctx.createLinearGradient(0, 0, -Infinity, 100) threw exception TypeError: Failed to execute 'createLinearGradient' on 'CanvasRenderingContext2D': The provided double value is non-finite.. +PASS ctx.createLinearGradient(0, NaN, 100, 100) threw exception TypeError: Failed to execute 'createLinearGradient' on 'CanvasRenderingContext2D': The provided double value is non-finite.. +PASS ctx.createLinearGradient(0, Infinity, 100, 100) threw exception TypeError: Failed to execute 'createLinearGradient' on 'CanvasRenderingContext2D': The provided double value is non-finite.. +PASS ctx.createLinearGradient(0, -Infinity, 100, 100) threw exception TypeError: Failed to execute 'createLinearGradient' on 'CanvasRenderingContext2D': The provided double value is non-finite.. +PASS ctx.createLinearGradient(NaN, 0, 100, 100) threw exception TypeError: Failed to execute 'createLinearGradient' on 'CanvasRenderingContext2D': The provided double value is non-finite.. +PASS ctx.createLinearGradient(Infinity, 0, 100, 100) threw exception TypeError: Failed to execute 'createLinearGradient' on 'CanvasRenderingContext2D': The provided double value is non-finite.. +PASS ctx.createLinearGradient(-Infinity, 0, 100, 100) threw exception TypeError: Failed to execute 'createLinearGradient' on 'CanvasRenderingContext2D': The provided double value is non-finite.. PASS successfullyParsed is true TEST COMPLETE
diff --git a/third_party/WebKit/LayoutTests/fast/canvas/radialGradient-infinite-values-expected.txt b/third_party/WebKit/LayoutTests/fast/canvas/radialGradient-infinite-values-expected.txt index 60cd772..1294afb 100644 --- a/third_party/WebKit/LayoutTests/fast/canvas/radialGradient-infinite-values-expected.txt +++ b/third_party/WebKit/LayoutTests/fast/canvas/radialGradient-infinite-values-expected.txt
@@ -3,24 +3,24 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". -PASS ctx.createRadialGradient(0, 0, 100, 0, 0, NaN) threw exception TypeError: Failed to execute 'createRadialGradient' on 'CanvasRenderingContext2D': The provided float value is non-finite.. -PASS ctx.createRadialGradient(0, 0, 100, 0, 0, Infinity) threw exception TypeError: Failed to execute 'createRadialGradient' on 'CanvasRenderingContext2D': The provided float value is non-finite.. -PASS ctx.createRadialGradient(0, 0, 100, 0, 0, -Infinity) threw exception TypeError: Failed to execute 'createRadialGradient' on 'CanvasRenderingContext2D': The provided float value is non-finite.. -PASS ctx.createRadialGradient(0, 0, 100, 0, NaN, 100) threw exception TypeError: Failed to execute 'createRadialGradient' on 'CanvasRenderingContext2D': The provided float value is non-finite.. -PASS ctx.createRadialGradient(0, 0, 100, 0, Infinity, 100) threw exception TypeError: Failed to execute 'createRadialGradient' on 'CanvasRenderingContext2D': The provided float value is non-finite.. -PASS ctx.createRadialGradient(0, 0, 100, 0, -Infinity, 100) threw exception TypeError: Failed to execute 'createRadialGradient' on 'CanvasRenderingContext2D': The provided float value is non-finite.. -PASS ctx.createRadialGradient(0, 0, 100, NaN, 0, 100) threw exception TypeError: Failed to execute 'createRadialGradient' on 'CanvasRenderingContext2D': The provided float value is non-finite.. -PASS ctx.createRadialGradient(0, 0, 100, Infinity, 0, 100) threw exception TypeError: Failed to execute 'createRadialGradient' on 'CanvasRenderingContext2D': The provided float value is non-finite.. -PASS ctx.createRadialGradient(0, 0, 100, -Infinity, 0, 100) threw exception TypeError: Failed to execute 'createRadialGradient' on 'CanvasRenderingContext2D': The provided float value is non-finite.. -PASS ctx.createRadialGradient(0, 0, NaN, 0, 0, 100) threw exception TypeError: Failed to execute 'createRadialGradient' on 'CanvasRenderingContext2D': The provided float value is non-finite.. -PASS ctx.createRadialGradient(0, 0, Infinity, 0, 0, 100) threw exception TypeError: Failed to execute 'createRadialGradient' on 'CanvasRenderingContext2D': The provided float value is non-finite.. -PASS ctx.createRadialGradient(0, 0, -Infinity, 0, 0, 100) threw exception TypeError: Failed to execute 'createRadialGradient' on 'CanvasRenderingContext2D': The provided float value is non-finite.. -PASS ctx.createRadialGradient(0, NaN, 100, 0, 0, 100) threw exception TypeError: Failed to execute 'createRadialGradient' on 'CanvasRenderingContext2D': The provided float value is non-finite.. -PASS ctx.createRadialGradient(0, Infinity, 100, 0, 0, 100) threw exception TypeError: Failed to execute 'createRadialGradient' on 'CanvasRenderingContext2D': The provided float value is non-finite.. -PASS ctx.createRadialGradient(0, -Infinity, 100, 0, 0, 100) threw exception TypeError: Failed to execute 'createRadialGradient' on 'CanvasRenderingContext2D': The provided float value is non-finite.. -PASS ctx.createRadialGradient(NaN, 0, 100, 0, 0, 100) threw exception TypeError: Failed to execute 'createRadialGradient' on 'CanvasRenderingContext2D': The provided float value is non-finite.. -PASS ctx.createRadialGradient(Infinity, 0, 100, 0, 0, 100) threw exception TypeError: Failed to execute 'createRadialGradient' on 'CanvasRenderingContext2D': The provided float value is non-finite.. -PASS ctx.createRadialGradient(-Infinity, 0, 100, 0, 0, 100) threw exception TypeError: Failed to execute 'createRadialGradient' on 'CanvasRenderingContext2D': The provided float value is non-finite.. +PASS ctx.createRadialGradient(0, 0, 100, 0, 0, NaN) threw exception TypeError: Failed to execute 'createRadialGradient' on 'CanvasRenderingContext2D': The provided double value is non-finite.. +PASS ctx.createRadialGradient(0, 0, 100, 0, 0, Infinity) threw exception TypeError: Failed to execute 'createRadialGradient' on 'CanvasRenderingContext2D': The provided double value is non-finite.. +PASS ctx.createRadialGradient(0, 0, 100, 0, 0, -Infinity) threw exception TypeError: Failed to execute 'createRadialGradient' on 'CanvasRenderingContext2D': The provided double value is non-finite.. +PASS ctx.createRadialGradient(0, 0, 100, 0, NaN, 100) threw exception TypeError: Failed to execute 'createRadialGradient' on 'CanvasRenderingContext2D': The provided double value is non-finite.. +PASS ctx.createRadialGradient(0, 0, 100, 0, Infinity, 100) threw exception TypeError: Failed to execute 'createRadialGradient' on 'CanvasRenderingContext2D': The provided double value is non-finite.. +PASS ctx.createRadialGradient(0, 0, 100, 0, -Infinity, 100) threw exception TypeError: Failed to execute 'createRadialGradient' on 'CanvasRenderingContext2D': The provided double value is non-finite.. +PASS ctx.createRadialGradient(0, 0, 100, NaN, 0, 100) threw exception TypeError: Failed to execute 'createRadialGradient' on 'CanvasRenderingContext2D': The provided double value is non-finite.. +PASS ctx.createRadialGradient(0, 0, 100, Infinity, 0, 100) threw exception TypeError: Failed to execute 'createRadialGradient' on 'CanvasRenderingContext2D': The provided double value is non-finite.. +PASS ctx.createRadialGradient(0, 0, 100, -Infinity, 0, 100) threw exception TypeError: Failed to execute 'createRadialGradient' on 'CanvasRenderingContext2D': The provided double value is non-finite.. +PASS ctx.createRadialGradient(0, 0, NaN, 0, 0, 100) threw exception TypeError: Failed to execute 'createRadialGradient' on 'CanvasRenderingContext2D': The provided double value is non-finite.. +PASS ctx.createRadialGradient(0, 0, Infinity, 0, 0, 100) threw exception TypeError: Failed to execute 'createRadialGradient' on 'CanvasRenderingContext2D': The provided double value is non-finite.. +PASS ctx.createRadialGradient(0, 0, -Infinity, 0, 0, 100) threw exception TypeError: Failed to execute 'createRadialGradient' on 'CanvasRenderingContext2D': The provided double value is non-finite.. +PASS ctx.createRadialGradient(0, NaN, 100, 0, 0, 100) threw exception TypeError: Failed to execute 'createRadialGradient' on 'CanvasRenderingContext2D': The provided double value is non-finite.. +PASS ctx.createRadialGradient(0, Infinity, 100, 0, 0, 100) threw exception TypeError: Failed to execute 'createRadialGradient' on 'CanvasRenderingContext2D': The provided double value is non-finite.. +PASS ctx.createRadialGradient(0, -Infinity, 100, 0, 0, 100) threw exception TypeError: Failed to execute 'createRadialGradient' on 'CanvasRenderingContext2D': The provided double value is non-finite.. +PASS ctx.createRadialGradient(NaN, 0, 100, 0, 0, 100) threw exception TypeError: Failed to execute 'createRadialGradient' on 'CanvasRenderingContext2D': The provided double value is non-finite.. +PASS ctx.createRadialGradient(Infinity, 0, 100, 0, 0, 100) threw exception TypeError: Failed to execute 'createRadialGradient' on 'CanvasRenderingContext2D': The provided double value is non-finite.. +PASS ctx.createRadialGradient(-Infinity, 0, 100, 0, 0, 100) threw exception TypeError: Failed to execute 'createRadialGradient' on 'CanvasRenderingContext2D': The provided double value is non-finite.. PASS successfullyParsed is true TEST COMPLETE
diff --git a/third_party/WebKit/LayoutTests/fast/events/autoscroll-scrollable-iframe-div-expected.txt b/third_party/WebKit/LayoutTests/fast/events/autoscroll-scrollable-iframe-div-expected.txt new file mode 100644 index 0000000..d392c49 --- /dev/null +++ b/third_party/WebKit/LayoutTests/fast/events/autoscroll-scrollable-iframe-div-expected.txt
@@ -0,0 +1,11 @@ +PASS successfullyParsed is true + +TEST COMPLETE +Starting Autoscroll test on iframe +PASSED : the autoscroll has worked ! +Test for bug 336373. + +To test manually, hold the middle mouse button on the box with scrollbars and scroll by dragging the mouse outside the bounds of the box. If the bug occurs once the cursor leaves the bounds of the box it will remain stuck in the panning state. + + +Click me
diff --git a/third_party/WebKit/LayoutTests/fast/events/autoscroll-scrollable-iframe-div.html b/third_party/WebKit/LayoutTests/fast/events/autoscroll-scrollable-iframe-div.html new file mode 100644 index 0000000..4f81b02 --- /dev/null +++ b/third_party/WebKit/LayoutTests/fast/events/autoscroll-scrollable-iframe-div.html
@@ -0,0 +1,72 @@ +<!DOCTYPE html> +<script src="../../resources/js-test.js"> </script> +<script> +var button_was_clicked = false; + +function test() { + if (window.testRunner) { + testRunner.waitUntilDone(); + testRunner.dumpAsText(); + testRunner.layoutAndPaintAsyncThen( + function() { + var iframe = document.getElementById('ScrollIFrame'); + var iframeDocument = iframe.contentDocument; + var textInIFrame = iframeDocument.getElementById('textInFrame'); + if (window.eventSender) { + debug("Starting Autoscroll test on iframe"); + testRunner.layoutAndPaintAsyncThen( + function() { + var x = iframe.offsetLeft + textInIFrame.offsetLeft + 7; + var y = iframe.offsetTop + textInIFrame.offsetTop + 7; + eventSender.dragMode = false; + eventSender.mouseMoveTo(x, y); + eventSender.mouseDown(1); + eventSender.mouseMoveTo(x + 220, y + 220); + eventSender.mouseUp(1); + testRunner.layoutAndPaintAsyncThen(autoscrollTestPart2); + }); + } + }); + } +} + +function autoscrollTestPart2() { + if (!window.eventSender) + return; + var testCompleted = document.getElementById("testCompletedButton"); + var h = testCompleted.offsetTop - document.scrollingElement.scrollTop + 10; + eventSender.dragMode = false; + eventSender.mouseMoveTo(20, testCompleted.offsetTop); + eventSender.mouseDown(); + eventSender.mouseUp(); + testRunner.runAfterLayoutAndPaint(checkButtonClicked); +} + +function checkButtonClicked() { + if (!button_was_clicked) { + debug("FAILED : the autoscroll has failed !"); + if (window.testRunner) + testRunner.notifyDone(); + } +} + +function testCompleted() { + button_was_clicked = true; + debug("PASSED : the autoscroll has worked !"); + if (window.testRunner) + testRunner.notifyDone(); +} +</script> + +<body onload="test()"> + <p>Test for <a href="http://crbug.com/336373">bug 336373</a>.</p> + <p>To test manually, hold the middle mouse button on the box with scrollbars and scroll by dragging the mouse outside the bounds of the box. If the bug occurs once the cursor leaves the bounds of the box it will remain stuck in the panning state.</p> + + <div id="ScrollableIFrameDiv" style="height: 100px; width: 100px"> + <iframe id="ScrollIFrame" src="resources/iframe-with-overflow-scrollable-div.html" style="height: 100px; width: 100px"> + </iframe> + </div> + + <button id="testCompletedButton" type="button" onclick="testCompleted()"> Click me </button> +</body> +</html> \ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/fast/events/resources/iframe-with-overflow-scrollable-div.html b/third_party/WebKit/LayoutTests/fast/events/resources/iframe-with-overflow-scrollable-div.html new file mode 100644 index 0000000..9d5dc1d --- /dev/null +++ b/third_party/WebKit/LayoutTests/fast/events/resources/iframe-with-overflow-scrollable-div.html
@@ -0,0 +1,17 @@ +<!DOCTYPE html> +<style> +#overflow_div { + border: 1px solid black; + background-color: lightblue; + width: 100px; + height: 100px; + overflow: scroll; +} +</style> + +<body> +<div id="overflow_div" class="overflow_div"> + <span id="textInFrame"> Try to autoscroll this text.<br> </span> +PASSED PASSED PASSED PASSED PASSED PASSED PASSED PASSED PASSED PASSED PASSED PASSED PASSED PASSED PASSED PASSED PASSED PASSED PASSED PASSED PASSED PASSED +</div> +</body>
diff --git a/third_party/WebKit/LayoutTests/fast/mediarecorder/MediaRecorder-audio-video.html b/third_party/WebKit/LayoutTests/fast/mediarecorder/MediaRecorder-audio-video.html new file mode 100644 index 0000000..d65727c --- /dev/null +++ b/third_party/WebKit/LayoutTests/fast/mediarecorder/MediaRecorder-audio-video.html
@@ -0,0 +1,90 @@ +<!DOCTYPE html> +<script src=../../resources/testharness.js></script> +<script src=../../resources/testharnessreport.js></script> +<script> + +// This test attempts to save and verify MediaStream data in the +// ondataavailable event handler of MediaRecorder. + +var checkStreamTracks = function(stream, has_video, has_audio) { + if (has_video) { + assert_equals(stream.getVideoTracks().length, 1); + assert_equals(stream.getVideoTracks()[0].readyState, 'live'); + } else { + assert_equals(stream.getVideoTracks().length, 0); + } + + if (has_audio) { + assert_equals(stream.getAudioTracks().length, 1); + assert_equals(stream.getAudioTracks()[0].readyState, 'live'); + } else { + assert_equals(stream.getAudioTracks().length, 0); + } +}; + +var makeAsyncTest = function(value, expected) { + var recorder; + + async_test(function() { + const recorderOnDataAvailable = this.step_func(function(event) { + if (event) { + assert_greater_than(event.data.size, 0, + 'Recorded data size should be > 0'); + assert_equals(recorder.state, "recording"); + } else { + assert_equals(recorder.state, "inactive"); + } + + // TODO(mcasas): Let the test record for a while. + // TODO(mcasas): Consider storing recorded data and playing it back. + + recorder.onstop = recorderOnStopExpected; + recorder.stop(); + }); + + const recorderOnStopExpected = this.step_func_done(); + + const recorderOnStopUnexpected = this.step_func(function() { + assert_unreached('Recording stopped.'); + }); + + const recorderOnError = this.step_func(function() { + assert_unreached('Recording error.'); + }); + + const gotStream = this.step_func_done(function(stream) { + checkStreamTracks(stream, value['video'], value['audio']); + + try { + recorder = new MediaRecorder(stream); + } catch (e) { + assert_unreached('Exception while creating MediaRecorder: ' + e); + } + + assert_equals(recorder.state, "inactive"); + recorder.ondataavailable = recorderOnDataAvailable; + recorder.onstop = recorderOnStopUnexpected; + recorder.onerror = recorderOnError; + recorder.start(); + + assert_equals(recorder.state, "recording"); + }); + + const onError = this.step_func(function() { + assert_unreached('Error creating MediaRecorder.'); + }); + + try { + navigator.webkitGetUserMedia(value, gotStream, onError); + } catch(e) { + assert_unreached('Exception launching getUserMedia(): ' + e); + } + }); +}; + +generate_tests(makeAsyncTest, + [["video-only", {video: true, audio: false}], + ["audio-only", {video: false, audio: true}], + ["audio-video", {video: true, audio: true}]]); + +</script>
diff --git a/third_party/WebKit/LayoutTests/fast/mediarecorder/MediaRecorder-basic-video.html b/third_party/WebKit/LayoutTests/fast/mediarecorder/MediaRecorder-basic-video.html deleted file mode 100644 index 7021d368..0000000 --- a/third_party/WebKit/LayoutTests/fast/mediarecorder/MediaRecorder-basic-video.html +++ /dev/null
@@ -1,67 +0,0 @@ -<!DOCTYPE html> -<script src=../../resources/testharness.js></script> -<script src=../../resources/testharnessreport.js></script> -<script> - -var test = async_test('checks the video-only MediaRecorder API.'); -var recorder; - -recorderOnDataAvailable = test.step_func(function(event) { - if (event) { - assert_greater_than(event.data.size, 0, 'Recorded data size should be > 0'); - assert_equals(recorder.state, "recording"); - } else { - assert_equals(recorder.state, "inactive"); - } - - // TODO(mcasas): Let the test record for a while. - // TODO(mcasas): Consider storing the recorded data and playing it back. - - recorder.onstop = recorderOnStopExpected; - recorder.stop(); -}); - -recorderOnStopExpected = test.step_func(function() { - test.done(); -}); - -recorderOnStopUnexpected = test.step_func(function() { - assert_unreached('Recording stopped.'); -}); - -recorderOnError = test.step_func(function() { - assert_unreached('Recording error.'); -}); - -gotStream = test.step_func(function(stream) { - assert_equals(stream.getAudioTracks().length, 0); - assert_equals(stream.getVideoTracks().length, 1); - assert_equals(stream.getVideoTracks()[0].readyState, 'live'); - - try { - recorder = new MediaRecorder(stream); - } catch (e) { - assert_unreached('Exception while creating MediaRecorder: ' + e); - } - - assert_equals(recorder.state, "inactive"); - recorder.ondataavailable = recorderOnDataAvailable; - recorder.onstop = recorderOnStopUnexpected; - recorder.onerror = recorderOnError; - recorder.start(); - - assert_equals(recorder.state, "recording"); - test.done(); -}); - -onError = test.step_func(function() { - assert_unreached('Error creating MediaRecorder.'); -}); - -try { - navigator.webkitGetUserMedia({video:true}, gotStream, onError); -} catch(e) { - assert_unreached('Exception launching getUserMedia(): ' + e); -} - -</script>
diff --git a/third_party/WebKit/LayoutTests/fast/mediarecorder/MediaRecorder-canRecordMimeType-expected.txt b/third_party/WebKit/LayoutTests/fast/mediarecorder/MediaRecorder-canRecordMimeType-expected.txt deleted file mode 100644 index 83941ec8..0000000 --- a/third_party/WebKit/LayoutTests/fast/mediarecorder/MediaRecorder-canRecordMimeType-expected.txt +++ /dev/null
@@ -1,8 +0,0 @@ -This is a testharness.js-based test. -PASS check MediaRecorder.canRecordMimeType() with video/invalid -PASS check MediaRecorder.canRecordMimeType() with video/vp8 -PASS check MediaRecorder.canRecordMimeType() with video/vp9 -PASS check MediaRecorder.canRecordMimeType() with audio/invalid -FAIL check MediaRecorder.canRecordMimeType() with audio/opus assert_equals: expected "maybe" but got "" -Harness: the test ran to completion. -
diff --git a/third_party/WebKit/LayoutTests/fast/mediarecorder/MediaRecorder-requestData.html b/third_party/WebKit/LayoutTests/fast/mediarecorder/MediaRecorder-requestData.html index 99395e9..1862c2a4 100644 --- a/third_party/WebKit/LayoutTests/fast/mediarecorder/MediaRecorder-requestData.html +++ b/third_party/WebKit/LayoutTests/fast/mediarecorder/MediaRecorder-requestData.html
@@ -3,58 +3,82 @@ <script src=../../resources/testharnessreport.js></script> <script> -var test = async_test('checks requestData() for video-only MediaRecorder API.'); -var recorder; +// This test verifies we can successfully create a MediaRecorder and +// get data from a MediaStream with it. -recorderOnDataAvailable = test.step_func(function(event) { - assert_equals(event.data.size, 0, 'Recorded data size should be == 0'); - test.done(); -}); - -recorderOnStop = test.step_func(function() { - assert_unreached('Recording stopped.'); -}); - -recorderOnError = test.step_func(function() { - assert_unreached('Recording error.'); -}); - -gotStream = test.step_func(function(stream) { - assert_equals(stream.getAudioTracks().length, 0); - assert_equals(stream.getVideoTracks().length, 1); - assert_equals(stream.getVideoTracks()[0].readyState, 'live'); - - try { - recorder = new MediaRecorder(stream); - } catch (e) { - assert_unreached('Exception while creating MediaRecorder: ' + e); - } - assert_equals(recorder.state, "inactive"); - - try { - recorder.requestData(); - assert_unreached(); - } catch (e) { - assert_equals(e.name, "InvalidStateError"); +var checkStreamTracks = function(stream, has_video, has_audio) { + if (has_video) { + assert_equals(stream.getVideoTracks().length, 1); + assert_equals(stream.getVideoTracks()[0].readyState, 'live'); + } else { + assert_equals(stream.getVideoTracks().length, 0); } - recorder.ondataavailable = recorderOnDataAvailable; - recorder.onstop = recorderOnStop; - recorder.onerror = recorderOnError; - recorder.start(); + if (has_audio) { + assert_equals(stream.getAudioTracks().length, 1); + assert_equals(stream.getAudioTracks()[0].readyState, 'live'); + } else { + assert_equals(stream.getAudioTracks().length, 0); + } +}; - assert_equals(recorder.state, "recording"); - recorder.requestData(); -}); +var makeAsyncTest = function(value, expected) { + var recorder; -onError = test.step_func(function() { - assert_unreached('Error creating MediaRecorder.'); -}); + async_test(function() { + const recorderOnDataAvailable = this.step_func_done(function(event) { + assert_equals(event.data.size, 0, + 'Recorded data size should be == 0'); + }); -try { - navigator.webkitGetUserMedia({video:true}, gotStream, onError); -} catch(e) { - assert_unreached('Exception launching getUserMedia(): ' + e); -} + const recorderOnStop = this.step_func(function() { + assert_unreached('Recording stopped.'); + }); + + const recorderOnError = this.step_func(function() { + assert_unreached('Recording error.'); + }); + + const gotStream = this.step_func_done(function(stream) { + checkStreamTracks(stream, value['video'], value['audio']); + + try { + recorder = new MediaRecorder(stream); + } catch (e) { + assert_unreached('Exception while creating MediaRecorder: ' + e); + } + + try { + recorder.requestData(); + assert_unreached(); + } catch (e) { + assert_equals(e.name, "InvalidStateError"); + } + + recorder.ondataavailable = recorderOnDataAvailable; + recorder.onstop = recorderOnStop; + recorder.onerror = recorderOnError; + recorder.start(); + + assert_equals(recorder.state, "recording"); + recorder.requestData(); + }); + + const onError = this.step_func(function() { + assert_unreached('Error creating MediaRecorder.'); + }); + + try { + navigator.webkitGetUserMedia(value, gotStream, onError); + } catch(e) { + assert_unreached('Exception launching getUserMedia(): ' + e); + } + }); +}; + +generate_tests(makeAsyncTest, + [["video-only", {video: true, audio: false}], + ["audio-only", {video: false, audio: true}], + ["audio-video", {video: true, audio: true}]]); </script>
diff --git a/third_party/WebKit/LayoutTests/fast/multicol/first-line-in-block-below-next-column-top-expected.txt b/third_party/WebKit/LayoutTests/fast/multicol/first-line-in-block-below-next-column-top-expected.txt new file mode 100644 index 0000000..95dfd54 --- /dev/null +++ b/third_party/WebKit/LayoutTests/fast/multicol/first-line-in-block-below-next-column-top-expected.txt
@@ -0,0 +1,6 @@ +When its first is on the other side of a column boundary, test that we push the entire block to the next column. + +There should be a blue square below. + + +PASS
diff --git a/third_party/WebKit/LayoutTests/fast/multicol/first-line-in-block-below-next-column-top.html b/third_party/WebKit/LayoutTests/fast/multicol/first-line-in-block-below-next-column-top.html new file mode 100644 index 0000000..1602e09f --- /dev/null +++ b/third_party/WebKit/LayoutTests/fast/multicol/first-line-in-block-below-next-column-top.html
@@ -0,0 +1,11 @@ +<!DOCTYPE html> +<script src="../../resources/check-layout.js"></script> +<p>When its first is on the other side of a column boundary, test that we push the entire block to the next column.</p> +<p>There should be a blue square below.</p> +<div id="multicol" style="position:relative; -webkit-columns:2; -webkit-column-gap:0; column-fill:auto; width:160px; height:80px; line-height:40px;"> + <div style="height:60px;"></div> + <div data-offset-x="80" data-offset-y="0" style="padding-top:40px; background:blue;"><br></div> +</div> +<script> + checkLayout("#multicol"); +</script>
diff --git a/third_party/WebKit/LayoutTests/fast/multicol/first-line-in-block-with-padding-expected.txt b/third_party/WebKit/LayoutTests/fast/multicol/first-line-in-block-with-padding-expected.txt new file mode 100644 index 0000000..7abc2ed63 --- /dev/null +++ b/third_party/WebKit/LayoutTests/fast/multicol/first-line-in-block-with-padding-expected.txt
@@ -0,0 +1,7 @@ +When its first line needs a column break, test that we push the entire block to the next column. + +There should be a blue square below. + + + +PASS
diff --git a/third_party/WebKit/LayoutTests/fast/multicol/first-line-in-block-with-padding.html b/third_party/WebKit/LayoutTests/fast/multicol/first-line-in-block-with-padding.html new file mode 100644 index 0000000..26753a95 --- /dev/null +++ b/third_party/WebKit/LayoutTests/fast/multicol/first-line-in-block-with-padding.html
@@ -0,0 +1,11 @@ +<!DOCTYPE html> +<script src="../../resources/check-layout.js"></script> +<p>When its first line needs a column break, test that we push the entire block to the next column.</p> +<p>There should be a blue square below.</p> +<div id="multicol" style="position:relative; -webkit-columns:2; -webkit-column-gap:0; column-fill:auto; width:6em; height:3em; line-height:2em;"> + <br> + <div data-offset-y="0" style="padding-top:1em; background:blue;"><br></div> +</div> +<script> + checkLayout("#multicol"); +</script>
diff --git a/third_party/WebKit/LayoutTests/fast/multicol/first-line-in-float-below-next-column-top-expected.txt b/third_party/WebKit/LayoutTests/fast/multicol/first-line-in-float-below-next-column-top-expected.txt new file mode 100644 index 0000000..6b9ddb3 --- /dev/null +++ b/third_party/WebKit/LayoutTests/fast/multicol/first-line-in-float-below-next-column-top-expected.txt
@@ -0,0 +1,6 @@ +When its first is on the other side of a column boundary, test that we push the entire float to the next column. + +There should be a blue square below. It should be right-bottom aligned inside a cyan box. + + +PASS
diff --git a/third_party/WebKit/LayoutTests/fast/multicol/first-line-in-float-below-next-column-top.html b/third_party/WebKit/LayoutTests/fast/multicol/first-line-in-float-below-next-column-top.html new file mode 100644 index 0000000..4bd1a6a4 --- /dev/null +++ b/third_party/WebKit/LayoutTests/fast/multicol/first-line-in-float-below-next-column-top.html
@@ -0,0 +1,11 @@ +<!DOCTYPE html> +<script src="../../resources/check-layout.js"></script> +<p>When its first is on the other side of a column boundary, test that we push the entire float to the next column.</p> +<p>There should be a blue square below. It should be right-bottom aligned inside a cyan box.</p> +<div id="multicol" style="position:relative; -webkit-columns:2; -webkit-column-gap:0; column-fill:auto; width:90px; height:90px; line-height:40px; background:cyan;"> + <div style="height:60px;"></div> + <div data-offset-x="45" data-offset-y="45" style="float:left; width:100%; margin-top:45px; padding-top:5px; background:blue;"><br></div> +</div> +<script> + checkLayout("#multicol"); +</script>
diff --git a/third_party/WebKit/LayoutTests/fast/multicol/first-line-in-float-with-margin-expected.txt b/third_party/WebKit/LayoutTests/fast/multicol/first-line-in-float-with-margin-expected.txt new file mode 100644 index 0000000..efe7d7f0bc --- /dev/null +++ b/third_party/WebKit/LayoutTests/fast/multicol/first-line-in-float-with-margin-expected.txt
@@ -0,0 +1,6 @@ +When its first line needs a column break, test that we push the entire float to the next column. + +There should be a blue square below. It should be right-bottom aligned inside a cyan box. + + +PASS
diff --git a/third_party/WebKit/LayoutTests/fast/multicol/first-line-in-float-with-margin.html b/third_party/WebKit/LayoutTests/fast/multicol/first-line-in-float-with-margin.html new file mode 100644 index 0000000..0d50b11a --- /dev/null +++ b/third_party/WebKit/LayoutTests/fast/multicol/first-line-in-float-with-margin.html
@@ -0,0 +1,11 @@ +<!DOCTYPE html> +<script src="../../resources/check-layout.js"></script> +<p>When its first line needs a column break, test that we push the entire float to the next column.</p> +<p>There should be a blue square below. It should be right-bottom aligned inside a cyan box.</p> +<div id="multicol" style="position:relative; -webkit-columns:2; -webkit-column-gap:0; column-fill:auto; width:80px; height:80px; line-height:40px; background:cyan;"> + <div style="height:40px;"></div> + <div data-offset-y="40" data-offset-x="40" style="float:left; width:100%; margin-top:40px; background:blue;"><br></div> +</div> +<script> + checkLayout("#multicol"); +</script>
diff --git a/third_party/WebKit/LayoutTests/fast/multicol/orphaned-line-at-exact-top-of-column-expected.txt b/third_party/WebKit/LayoutTests/fast/multicol/orphaned-line-at-exact-top-of-column-expected.txt new file mode 100644 index 0000000..308b345 --- /dev/null +++ b/third_party/WebKit/LayoutTests/fast/multicol/orphaned-line-at-exact-top-of-column-expected.txt
@@ -0,0 +1,8 @@ +Make sure that we don't skip orphan checking when a line ends up naturally at the top of a column. + +All three lines should be in the second column. + +line 1 +line 2 +line 3 +PASS
diff --git a/third_party/WebKit/LayoutTests/fast/multicol/orphaned-line-at-exact-top-of-column.html b/third_party/WebKit/LayoutTests/fast/multicol/orphaned-line-at-exact-top-of-column.html new file mode 100644 index 0000000..96d102c --- /dev/null +++ b/third_party/WebKit/LayoutTests/fast/multicol/orphaned-line-at-exact-top-of-column.html
@@ -0,0 +1,15 @@ +<!DOCTYPE html> +<script src="../../resources/check-layout.js"></script> +<p>Make sure that we don't skip orphan checking when a line ends up naturally at the top of a column.</p> +<p>All three lines should be in the second column.</p> +<div id="multicol" style="position:relative; -webkit-columns:2; -webkit-column-rule:1px solid; column-fill:auto; orphans:3; height:8em; line-height:2em; background:yellow;"> + <div style="height:4em;"></div> + <div data-offset-y="0"> + line 1<br> + line 2<br> + line 3<br> + </div> +</div> +<script> + checkLayout("#multicol"); +</script>
diff --git a/third_party/WebKit/LayoutTests/http/tests/cachestorage/window/sandboxed-iframes.html b/third_party/WebKit/LayoutTests/http/tests/cachestorage/window/sandboxed-iframes.html index 8ffac7c..e5f3a0f 100644 --- a/third_party/WebKit/LayoutTests/http/tests/cachestorage/window/sandboxed-iframes.html +++ b/third_party/WebKit/LayoutTests/http/tests/cachestorage/window/sandboxed-iframes.html
@@ -23,7 +23,7 @@ self.addEventListener('message', function listener(e) { if (e.data.id === id) { resolve(e.data); - self.removeEventListener(listener); + self.removeEventListener('message', listener); } }); });
diff --git a/third_party/WebKit/LayoutTests/http/tests/push_messaging/push-subscription-stringification.html b/third_party/WebKit/LayoutTests/http/tests/push_messaging/push-subscription-stringification.html index c901557..4f04954 100644 --- a/third_party/WebKit/LayoutTests/http/tests/push_messaging/push-subscription-stringification.html +++ b/third_party/WebKit/LayoutTests/http/tests/push_messaging/push-subscription-stringification.html
@@ -10,6 +10,12 @@ </head> <body> <script> +// Converts an ArrayBuffer to a base64url encoded string. +function ArrayBufferToBase64UrlEncodedString(buffer) { + var base64 = btoa(String.fromCharCode.apply(null, new Uint8Array(buffer))); + return base64.replace(/\//g, '_').replace(/\+/g, '-'); +} + async_test(function(test) { var workerUrl = 'resources/empty_worker.js'; var workerScope = 'resources/scope/' + location.pathname; @@ -33,13 +39,13 @@ assert_own_property(reflectedObject, 'keys'); assert_own_property(reflectedObject.keys, 'p256dh'); + assert_own_property(reflectedObject.keys, 'auth'); - var key = btoa(String.fromCharCode.apply(null, new Uint8Array(pushSubscription.getKey('p256dh')))); - - // Convert |key| to the base64url alphabet by replacing non-URL safe characters. - key = key.replace(/\//g, '_').replace(/\+/g, '-'); + var key = ArrayBufferToBase64UrlEncodedString(pushSubscription.getKey('p256dh')), + auth = ArrayBufferToBase64UrlEncodedString(pushSubscription.getKey('auth')); assert_equals(reflectedObject.keys.p256dh, key); + assert_equals(reflectedObject.keys.auth, auth); return service_worker_unregister_and_done(test, workerScope); })
diff --git a/third_party/WebKit/LayoutTests/http/tests/push_messaging/subscribe-encryption-public-key.html b/third_party/WebKit/LayoutTests/http/tests/push_messaging/subscribe-encryption-public-key.html index d8ff774..44c1a28 100644 --- a/third_party/WebKit/LayoutTests/http/tests/push_messaging/subscribe-encryption-public-key.html +++ b/third_party/WebKit/LayoutTests/http/tests/push_messaging/subscribe-encryption-public-key.html
@@ -21,11 +21,14 @@ async_test(function(test) { var workerUrl = 'resources/empty_worker.js'; var workerScope = 'resources/scope/' + location.pathname; - var swRegistration, encryptionKey; + var swRegistration, encryptionKey, encryptionAuth; // Length of a NIST P-256 point in uncompressed form per SEC1 2.3.3. var EXPECTED_KEY_LENGTH = 65; + // Minimum length of the authentication information, in bytes. + var MINIMUM_AUTH_LENGTH = 12; + // The first byte in an uncompressed P-256 point per SEC1 2.3.3. var UNCOMPRESSED_POINT_FORM = 0x04; @@ -54,15 +57,23 @@ // The first byte of the key should be the uncompressed point form indicator. assert_equals(new Uint8Array(key)[0], UNCOMPRESSED_POINT_FORM); + // Verify that authentication information is available in the subscription. + var auth = pushSubscription.getKey('auth'); + + assert_not_equals(auth, null); + assert_true(auth.byteLength >= MINIMUM_AUTH_LENGTH); + // Getting a key with an unsupported algorithm should throw an exception. assert_throws(TypeError(), () => pushSubscription.getKey('petercurve9001')); encryptionKey = SerializeArrayBuffer(key); + encryptionAuth = SerializeArrayBuffer(auth); return swRegistration.pushManager.getSubscription(); }) .then(function(pushSubscription) { assert_equals(SerializeArrayBuffer(pushSubscription.getKey('p256dh')), encryptionKey); + assert_equals(SerializeArrayBuffer(pushSubscription.getKey('auth')), encryptionAuth); return service_worker_unregister_and_done(test, workerScope); })
diff --git a/third_party/WebKit/LayoutTests/inspector/console/function-name-in-console-message-stack-expected.txt b/third_party/WebKit/LayoutTests/inspector/console/function-name-in-console-message-stack-expected.txt new file mode 100644 index 0000000..eee1aff --- /dev/null +++ b/third_party/WebKit/LayoutTests/inspector/console/function-name-in-console-message-stack-expected.txt
@@ -0,0 +1,8 @@ +CONSOLE ERROR: line 8: Uncaught Error +Tests exception message contains stack with correct function name. + + function-name-in-console-message-stack.html:8 Uncaught Error +foo.displayName @ function-name-in-console-message-stack.html:8 +bar.displayName @ function-name-in-console-message-stack.html:16 +baz.function.name @ function-name-in-console-message-stack.html:23 +
diff --git a/third_party/WebKit/LayoutTests/inspector/console/function-name-in-console-message-stack.html b/third_party/WebKit/LayoutTests/inspector/console/function-name-in-console-message-stack.html new file mode 100644 index 0000000..d222c304 --- /dev/null +++ b/third_party/WebKit/LayoutTests/inspector/console/function-name-in-console-message-stack.html
@@ -0,0 +1,49 @@ +<html> +<head> +<script src="../../http/tests/inspector/inspector-test.js"></script> +<script src="../../http/tests/inspector/console-test.js"></script> +<script> +var foo = function () +{ + throw new Error(); +} + +foo.displayName = 'foo.displayName'; +Object.defineProperty(foo, 'name', { value: 'foo.function.name' } ); + +var bar = function() +{ + foo(); +} + +bar.displayName = 'bar.displayName'; + +var baz = function() +{ + bar(); +} + +Object.defineProperty(baz, 'name', { value: 'baz.function.name' } ); + +function test() +{ + InspectorTest.waitUntilNthMessageReceived(1, step1); + InspectorTest.evaluateInPage("setTimeout(baz, 0);"); + + function step1() + { + InspectorTest.expandConsoleMessages(step2); + } + + function step2() + { + InspectorTest.dumpConsoleMessagesIgnoreErrorStackFrames(); + InspectorTest.completeTest(); + } +}; +</script> +</head> +<body onload="runTest()"> +<p>Tests exception message contains stack with correct function name.</p> +</body> +</html>
diff --git a/third_party/WebKit/LayoutTests/inspector/sources/debugger-pause/function-name-in-callstack-expected.txt b/third_party/WebKit/LayoutTests/inspector/sources/debugger-pause/function-name-in-callstack-expected.txt new file mode 100644 index 0000000..07494cc --- /dev/null +++ b/third_party/WebKit/LayoutTests/inspector/sources/debugger-pause/function-name-in-callstack-expected.txt
@@ -0,0 +1,11 @@ +Tests that callFrames on pause contains function name taking into account displayName and Function.name. + +Set timer for test function. +Script execution paused. +callFrames.length = 4 +functionName: foo.displayName +functionName: bar.displayName +functionName: baz.function.name +functionName: testFunction +Script execution resumed. +
diff --git a/third_party/WebKit/LayoutTests/inspector/sources/debugger-pause/function-name-in-callstack.html b/third_party/WebKit/LayoutTests/inspector/sources/debugger-pause/function-name-in-callstack.html new file mode 100644 index 0000000..0959900 --- /dev/null +++ b/third_party/WebKit/LayoutTests/inspector/sources/debugger-pause/function-name-in-callstack.html
@@ -0,0 +1,59 @@ +<html> +<head> +<script src="../../../http/tests/inspector/inspector-test.js"></script> +<script src="../../../http/tests/inspector/debugger-test.js"></script> +<script> +var foo = function () +{ + debugger; +} + +foo.displayName = 'foo.displayName'; +Object.defineProperty(foo, 'name', { value: 'foo.function.name' } ); + +var bar = function() +{ + foo(); +} + +bar.displayName = 'bar.displayName'; + +var baz = function() +{ + bar(); +} + +Object.defineProperty(baz, 'name', { value: 'baz.function.name' } ); + +function testFunction() +{ + baz(); +} + +function test() +{ + InspectorTest.startDebuggerTest(step1); + + function step1() + { + InspectorTest.runTestFunctionAndWaitUntilPaused(step2); + } + + function step2(callFrames) + { + InspectorTest.addResult("callFrames.length = " + callFrames.length); + for (var i = 0; i < callFrames.length; ++i) + InspectorTest.addResult("functionName: " + callFrames[i].functionName); + InspectorTest.completeDebuggerTest(); + } +} +</script> +</head> + +<body onload="runTest()"> +<p> +Tests that callFrames on pause contains function name taking into account displayName and Function.name. +</p> + +</body> +</html>
diff --git a/third_party/WebKit/LayoutTests/inspector/sources/debugger/properties-special-expected.txt b/third_party/WebKit/LayoutTests/inspector/sources/debugger/properties-special-expected.txt index 427e428a..bc4d62d 100644 --- a/third_party/WebKit/LayoutTests/inspector/sources/debugger/properties-special-expected.txt +++ b/third_party/WebKit/LayoutTests/inspector/sources/debugger/properties-special-expected.txt
@@ -14,7 +14,7 @@ prototype: Object __proto__: () <function scope> -properties-special.html:12 anonymous() +properties-special.html:12 bound () arguments: (...) caller: (...) length: 1
diff --git a/third_party/WebKit/LayoutTests/media/encrypted-media/encrypted-media-playback-two-videos.html b/third_party/WebKit/LayoutTests/media/encrypted-media/encrypted-media-playback-two-videos.html index 4d1892f..30bb582 100644 --- a/third_party/WebKit/LayoutTests/media/encrypted-media/encrypted-media-playback-two-videos.html +++ b/third_party/WebKit/LayoutTests/media/encrypted-media/encrypted-media-playback-two-videos.html
@@ -53,7 +53,7 @@ // ensures we see both events. if (++encryptedEventCount != 2) return; - video.removeEventListener(listener); + video.removeEventListener('encrypted', listener); var mediaKeySession = video.mediaKeys.createSession(); mediaKeySession.generateRequest(e.initDataType, e.initData).then(function(result) { @@ -75,7 +75,7 @@ video.addEventListener('timeupdate', function listener(e) { if (e.target.currentTime < 0.2) return; - video.removeEventListener(listener); + video.removeEventListener('timeupdate', listener); resolve(e); }); });
diff --git a/third_party/WebKit/LayoutTests/media/encrypted-media/encrypted-media-set-mediakeys-at-same-time.html b/third_party/WebKit/LayoutTests/media/encrypted-media/encrypted-media-set-mediakeys-at-same-time.html index 5fdb0b06..0968e34 100644 --- a/third_party/WebKit/LayoutTests/media/encrypted-media/encrypted-media-set-mediakeys-at-same-time.html +++ b/third_party/WebKit/LayoutTests/media/encrypted-media/encrypted-media-set-mediakeys-at-same-time.html
@@ -15,7 +15,7 @@ { return new Promise(function(resolve) { video.addEventListener('encrypted', function listener(e) { - video.removeEventListener(listener); + video.removeEventListener('encrypted', listener); resolve(); }); });
diff --git a/third_party/WebKit/LayoutTests/media/encrypted-media/encrypted-media-unique-origin.html b/third_party/WebKit/LayoutTests/media/encrypted-media/encrypted-media-unique-origin.html index 08ddead..e51597f 100644 --- a/third_party/WebKit/LayoutTests/media/encrypted-media/encrypted-media-unique-origin.html +++ b/third_party/WebKit/LayoutTests/media/encrypted-media/encrypted-media-unique-origin.html
@@ -26,7 +26,7 @@ return new Promise(function(resolve) { self.addEventListener('message', function listener(e) { resolve(e.data); - self.removeEventListener(listener); + self.removeEventListener('message', listener); }); }); }
diff --git a/third_party/WebKit/LayoutTests/media/encrypted-media/encrypted-media-utils.js b/third_party/WebKit/LayoutTests/media/encrypted-media/encrypted-media-utils.js index 5a4f15af..9bad82e 100644 --- a/third_party/WebKit/LayoutTests/media/encrypted-media/encrypted-media-utils.js +++ b/third_party/WebKit/LayoutTests/media/encrypted-media/encrypted-media-utils.js
@@ -291,7 +291,7 @@ video.addEventListener('timeupdate', function listener(event) { if (event.target.currentTime < duration) return; - video.removeEventListener(listener); + video.removeEventListener('timeupdate', listener); resolve('success'); }); });
diff --git a/third_party/WebKit/LayoutTests/media/encrypted-media/encrypted-media-waiting-for-a-key.html b/third_party/WebKit/LayoutTests/media/encrypted-media/encrypted-media-waiting-for-a-key.html index cdd8905..712557b 100644 --- a/third_party/WebKit/LayoutTests/media/encrypted-media/encrypted-media-waiting-for-a-key.html +++ b/third_party/WebKit/LayoutTests/media/encrypted-media/encrypted-media-waiting-for-a-key.html
@@ -115,7 +115,7 @@ if (++encryptedEventCount != 2) return; - video.removeEventListener(listener); + video.removeEventListener('encrypted', listener); resolve(e); }); }); @@ -137,7 +137,7 @@ // occur once. http://crbug.com/461903 // assert_equals(waitingForKeyEventCount, 1, 'Multiple waitingforkey events'); - video.removeEventListener(listener); + video.removeEventListener('waitingforkey', listener); resolve(e); }); }); @@ -153,7 +153,7 @@ ++debugTimeUpdateEventCount; if (video.currentTime < 0.2) return; - video.removeEventListener(listener); + video.removeEventListener('timeupdate', listener); resolve(e); }); });
diff --git a/third_party/WebKit/LayoutTests/platform/android/fast/backgrounds/size/contain-and-cover-zoomed-expected.png b/third_party/WebKit/LayoutTests/platform/android/fast/backgrounds/size/contain-and-cover-zoomed-expected.png new file mode 100644 index 0000000..510c507 --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/android/fast/backgrounds/size/contain-and-cover-zoomed-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/android/svg/as-background-image/background-image-preserveaspectRatio-support-expected.png b/third_party/WebKit/LayoutTests/platform/android/svg/as-background-image/background-image-preserveaspectRatio-support-expected.png new file mode 100644 index 0000000..a433cb99 --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/android/svg/as-background-image/background-image-preserveaspectRatio-support-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/android/svg/as-image/img-preserveAspectRatio-support-1-expected.png b/third_party/WebKit/LayoutTests/platform/android/svg/as-image/img-preserveAspectRatio-support-1-expected.png new file mode 100644 index 0000000..5f257cb --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/android/svg/as-image/img-preserveAspectRatio-support-1-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/android/svg/repaint/repaint-paintorder-expected.png b/third_party/WebKit/LayoutTests/platform/android/svg/repaint/repaint-paintorder-expected.png new file mode 100644 index 0000000..875da05 --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/android/svg/repaint/repaint-paintorder-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/android/svg/text/text-selection-align-05-b-expected.png b/third_party/WebKit/LayoutTests/platform/android/svg/text/text-selection-align-05-b-expected.png new file mode 100644 index 0000000..fc43939 --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/android/svg/text/text-selection-align-05-b-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/android/svg/zoom/text/zoom-coords-viewattr-01-b-expected.png b/third_party/WebKit/LayoutTests/platform/android/svg/zoom/text/zoom-coords-viewattr-01-b-expected.png new file mode 100644 index 0000000..c025e9d --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/android/svg/zoom/text/zoom-coords-viewattr-01-b-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/svg/as-background-image/background-image-preserveaspectRatio-support-expected.png b/third_party/WebKit/LayoutTests/platform/linux/svg/as-background-image/background-image-preserveaspectRatio-support-expected.png index a433cb99..fa99f24 100644 --- a/third_party/WebKit/LayoutTests/platform/linux/svg/as-background-image/background-image-preserveaspectRatio-support-expected.png +++ b/third_party/WebKit/LayoutTests/platform/linux/svg/as-background-image/background-image-preserveaspectRatio-support-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/svg/as-image/img-preserveAspectRatio-support-1-expected.png b/third_party/WebKit/LayoutTests/platform/linux/svg/as-image/img-preserveAspectRatio-support-1-expected.png index 5f257cb..5aba07df 100644 --- a/third_party/WebKit/LayoutTests/platform/linux/svg/as-image/img-preserveAspectRatio-support-1-expected.png +++ b/third_party/WebKit/LayoutTests/platform/linux/svg/as-image/img-preserveAspectRatio-support-1-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/svg/text/text-selection-align-05-b-expected.png b/third_party/WebKit/LayoutTests/platform/linux/svg/text/text-selection-align-05-b-expected.png index fc43939..94d48469 100644 --- a/third_party/WebKit/LayoutTests/platform/linux/svg/text/text-selection-align-05-b-expected.png +++ b/third_party/WebKit/LayoutTests/platform/linux/svg/text/text-selection-align-05-b-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/svg/zoom/text/zoom-coords-viewattr-01-b-expected.png b/third_party/WebKit/LayoutTests/platform/linux/svg/zoom/text/zoom-coords-viewattr-01-b-expected.png index c025e9d..641c9ea 100644 --- a/third_party/WebKit/LayoutTests/platform/linux/svg/zoom/text/zoom-coords-viewattr-01-b-expected.png +++ b/third_party/WebKit/LayoutTests/platform/linux/svg/zoom/text/zoom-coords-viewattr-01-b-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/fast/css/transformed-mask-expected.png b/third_party/WebKit/LayoutTests/platform/mac/fast/css/transformed-mask-expected.png index 76f50cd..8938927f 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/fast/css/transformed-mask-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac/fast/css/transformed-mask-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/svg/as-background-image/background-image-preserveaspectRatio-support-expected.png b/third_party/WebKit/LayoutTests/platform/mac/svg/as-background-image/background-image-preserveaspectRatio-support-expected.png index 927f6c9..f8b3b87d 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/svg/as-background-image/background-image-preserveaspectRatio-support-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac/svg/as-background-image/background-image-preserveaspectRatio-support-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/svg/as-image/img-preserveAspectRatio-support-1-expected.png b/third_party/WebKit/LayoutTests/platform/mac/svg/as-image/img-preserveAspectRatio-support-1-expected.png index 28b27b1..62685efe3 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/svg/as-image/img-preserveAspectRatio-support-1-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac/svg/as-image/img-preserveAspectRatio-support-1-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/svg/text/text-selection-align-05-b-expected.png b/third_party/WebKit/LayoutTests/platform/mac/svg/text/text-selection-align-05-b-expected.png index f0fe0068..2f23730 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/svg/text/text-selection-align-05-b-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac/svg/text/text-selection-align-05-b-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/svg/zoom/text/zoom-coords-viewattr-01-b-expected.png b/third_party/WebKit/LayoutTests/platform/mac/svg/zoom/text/zoom-coords-viewattr-01-b-expected.png index 58d87f34..22d1b17 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/svg/zoom/text/zoom-coords-viewattr-01-b-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac/svg/zoom/text/zoom-coords-viewattr-01-b-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu/fast/canvas/image-object-in-canvas-expected.png b/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu/fast/canvas/image-object-in-canvas-expected.png index 29a5c34..89124bdd 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu/fast/canvas/image-object-in-canvas-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu/fast/canvas/image-object-in-canvas-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win-xp/svg/repaint/repaint-paintorder-expected.png b/third_party/WebKit/LayoutTests/platform/win-xp/svg/repaint/repaint-paintorder-expected.png new file mode 100644 index 0000000..875da05 --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/win-xp/svg/repaint/repaint-paintorder-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win-xp/svg/zoom/text/zoom-coords-viewattr-01-b-expected.png b/third_party/WebKit/LayoutTests/platform/win-xp/svg/zoom/text/zoom-coords-viewattr-01-b-expected.png index a93ac58..b5daa85 100644 --- a/third_party/WebKit/LayoutTests/platform/win-xp/svg/zoom/text/zoom-coords-viewattr-01-b-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win-xp/svg/zoom/text/zoom-coords-viewattr-01-b-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/fast/css/transformed-mask-expected.png b/third_party/WebKit/LayoutTests/platform/win/fast/css/transformed-mask-expected.png index 2e3bc52..52f2f85 100644 --- a/third_party/WebKit/LayoutTests/platform/win/fast/css/transformed-mask-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win/fast/css/transformed-mask-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/svg/as-background-image/background-image-preserveaspectRatio-support-expected.png b/third_party/WebKit/LayoutTests/platform/win/svg/as-background-image/background-image-preserveaspectRatio-support-expected.png index 803192a..696c80c 100644 --- a/third_party/WebKit/LayoutTests/platform/win/svg/as-background-image/background-image-preserveaspectRatio-support-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win/svg/as-background-image/background-image-preserveaspectRatio-support-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/svg/as-image/img-preserveAspectRatio-support-1-expected.png b/third_party/WebKit/LayoutTests/platform/win/svg/as-image/img-preserveAspectRatio-support-1-expected.png index 122322f..2f071007 100644 --- a/third_party/WebKit/LayoutTests/platform/win/svg/as-image/img-preserveAspectRatio-support-1-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win/svg/as-image/img-preserveAspectRatio-support-1-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/svg/text/text-selection-align-05-b-expected.png b/third_party/WebKit/LayoutTests/platform/win/svg/text/text-selection-align-05-b-expected.png index 8884680d..3c815b2f 100644 --- a/third_party/WebKit/LayoutTests/platform/win/svg/text/text-selection-align-05-b-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win/svg/text/text-selection-align-05-b-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/svg/zoom/text/zoom-coords-viewattr-01-b-expected.png b/third_party/WebKit/LayoutTests/platform/win/svg/zoom/text/zoom-coords-viewattr-01-b-expected.png index 4a24046..0605a0b5 100644 --- a/third_party/WebKit/LayoutTests/platform/win/svg/zoom/text/zoom-coords-viewattr-01-b-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win/svg/zoom/text/zoom-coords-viewattr-01-b-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/virtual/gpu/fast/canvas/image-object-in-canvas-expected.png b/third_party/WebKit/LayoutTests/platform/win/virtual/gpu/fast/canvas/image-object-in-canvas-expected.png index c9a038b1..3f6691b 100644 --- a/third_party/WebKit/LayoutTests/platform/win/virtual/gpu/fast/canvas/image-object-in-canvas-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win/virtual/gpu/fast/canvas/image-object-in-canvas-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/svg/repaint/repaint-paintorder-expected.png b/third_party/WebKit/LayoutTests/svg/repaint/repaint-paintorder-expected.png index 875da05..896e4dd 100644 --- a/third_party/WebKit/LayoutTests/svg/repaint/repaint-paintorder-expected.png +++ b/third_party/WebKit/LayoutTests/svg/repaint/repaint-paintorder-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/virtual/implsidepainting/inspector/tracing/frame-model-instrumentation-expected.txt b/third_party/WebKit/LayoutTests/virtual/implsidepainting/inspector/tracing/frame-model-instrumentation-expected.txt deleted file mode 100644 index eea5ff95..0000000 --- a/third_party/WebKit/LayoutTests/virtual/implsidepainting/inspector/tracing/frame-model-instrumentation-expected.txt +++ /dev/null
@@ -1,4 +0,0 @@ -layerTree: object -mainFrameId: number -paints: present -
diff --git a/third_party/WebKit/Source/bindings/core/BUILD.gn b/third_party/WebKit/Source/bindings/core/BUILD.gn index 2b0dd10..14a8a73a 100644 --- a/third_party/WebKit/Source/bindings/core/BUILD.gn +++ b/third_party/WebKit/Source/bindings/core/BUILD.gn
@@ -17,8 +17,8 @@ component_info_file = "$bindings_core_output_dir/ComponentInfoCore.pickle" deps = [ "//third_party/WebKit/Source/bindings/core:core_global_constructors_idls", - "//third_party/WebKit/Source/core:generated_testing_idls_settings", "//third_party/WebKit/Source/core:generated_testing_idls_internal_runtime_flags", + "//third_party/WebKit/Source/core:generated_testing_idls_settings", ] }
diff --git a/third_party/WebKit/Source/bindings/core/v8/V8GCController.cpp b/third_party/WebKit/Source/bindings/core/v8/V8GCController.cpp index c3b4cc8e..927ec41 100644 --- a/third_party/WebKit/Source/bindings/core/v8/V8GCController.cpp +++ b/third_party/WebKit/Source/bindings/core/v8/V8GCController.cpp
@@ -274,13 +274,17 @@ void V8GCController::gcPrologue(v8::GCType type, v8::GCCallbackFlags flags) { - if (ThreadState::current()) - ThreadState::current()->willStartV8GC(); - if (isMainThread()) { ScriptForbiddenScope::enter(); } + // TODO(haraken): It is not safe to run finalizers in a prologue callback + // because V8AbstractEventListener's destructor cann call into V8. We + // should post a task to schedule willStartV8GC() and avoid running it + // inside the prologue callback. + // if (ThreadState::current()) + // ThreadState::current()->willStartV8GC(); + // TODO(haraken): It would be nice if the GC callbacks passed the Isolate // directly. v8::Isolate* isolate = v8::Isolate::GetCurrent();
diff --git a/third_party/WebKit/Source/bindings/core/v8/V8HiddenValue.cpp b/third_party/WebKit/Source/bindings/core/v8/V8HiddenValue.cpp index 478729e..c0e1cc64 100644 --- a/third_party/WebKit/Source/bindings/core/v8/V8HiddenValue.cpp +++ b/third_party/WebKit/Source/bindings/core/v8/V8HiddenValue.cpp
@@ -25,25 +25,17 @@ v8::Local<v8::Value> V8HiddenValue::getHiddenValue(ScriptState* scriptState, v8::Local<v8::Object> object, v8::Local<v8::String> key) { - v8::Local<v8::Context> context = scriptState->context(); - v8::Local<v8::Private> privateKey = v8::Private::ForApi(scriptState->isolate(), key); - v8::Local<v8::Value> value; - // Callsites interpret an empty handle has absence of a result. - if (!v8CallBoolean(object->HasPrivate(context, privateKey))) - return v8::Local<v8::Value>(); - if (object->GetPrivate(context, privateKey).ToLocal(&value)) - return value; - return v8::Local<v8::Value>(); + return object->GetHiddenValue(key); } bool V8HiddenValue::setHiddenValue(ScriptState* scriptState, v8::Local<v8::Object> object, v8::Local<v8::String> key, v8::Local<v8::Value> value) { - return v8CallBoolean(object->SetPrivate(scriptState->context(), v8::Private::ForApi(scriptState->isolate(), key), value)); + return object->SetHiddenValue(key, value); } bool V8HiddenValue::deleteHiddenValue(ScriptState* scriptState, v8::Local<v8::Object> object, v8::Local<v8::String> key) { - return v8CallBoolean(object->DeletePrivate(scriptState->context(), v8::Private::ForApi(scriptState->isolate(), key))); + return object->DeleteHiddenValue(key); } v8::Local<v8::Value> V8HiddenValue::getHiddenValueFromMainWorldWrapper(ScriptState* scriptState, ScriptWrappable* wrappable, v8::Local<v8::String> key)
diff --git a/third_party/WebKit/Source/bindings/core/v8/WindowProxyManager.cpp b/third_party/WebKit/Source/bindings/core/v8/WindowProxyManager.cpp index 391ebf8..970faaf3 100644 --- a/third_party/WebKit/Source/bindings/core/v8/WindowProxyManager.cpp +++ b/third_party/WebKit/Source/bindings/core/v8/WindowProxyManager.cpp
@@ -29,16 +29,6 @@ #endif } -Frame* WindowProxyManager::frame() const -{ - return m_frame.get(); -} - -WindowProxy* WindowProxyManager::mainWorldProxy() const -{ - return m_windowProxy.get(); -} - WindowProxy* WindowProxyManager::windowProxy(DOMWrapperWorld& world) { WindowProxy* windowProxy = nullptr;
diff --git a/third_party/WebKit/Source/bindings/core/v8/WindowProxyManager.h b/third_party/WebKit/Source/bindings/core/v8/WindowProxyManager.h index 59c6d125..439b0f3 100644 --- a/third_party/WebKit/Source/bindings/core/v8/WindowProxyManager.h +++ b/third_party/WebKit/Source/bindings/core/v8/WindowProxyManager.h
@@ -27,9 +27,9 @@ ~WindowProxyManager(); DECLARE_TRACE(); - Frame* frame() const; + Frame* frame() const { return m_frame.get(); } v8::Isolate* isolate() const { return m_isolate; } - WindowProxy* mainWorldProxy() const; + WindowProxy* mainWorldProxy() const { return m_windowProxy.get(); } WindowProxy* windowProxy(DOMWrapperWorld&);
diff --git a/third_party/WebKit/Source/bindings/modules/BUILD.gn b/third_party/WebKit/Source/bindings/modules/BUILD.gn index 5ecac1cc..e84cd69 100644 --- a/third_party/WebKit/Source/bindings/modules/BUILD.gn +++ b/third_party/WebKit/Source/bindings/modules/BUILD.gn
@@ -13,10 +13,10 @@ # GYP version: Source/bindings/modules/generated.gyp:bindings_modules_generated group("bindings_modules_generated") { public_deps = [ - ":modules_bindings_generated_event_interfaces", ":bindings_modules_generated_event_modules_factory", ":bindings_modules_generated_event_modules_names", ":bindings_modules_generated_event_target_modules_names", + ":modules_bindings_generated_event_interfaces", ] }
diff --git a/third_party/WebKit/Source/bindings/scripts/scripts.gni b/third_party/WebKit/Source/bindings/scripts/scripts.gni index 7022af29..5655ed7c 100644 --- a/third_party/WebKit/Source/bindings/scripts/scripts.gni +++ b/third_party/WebKit/Source/bindings/scripts/scripts.gni
@@ -182,9 +182,8 @@ "//third_party/WebKit/Source/bindings/modules:interfaces_info", "//third_party/WebKit/Source/bindings/modules:modules_core_global_constructors_idls", "//third_party/WebKit/Source/bindings/modules:modules_global_constructors_idls", - - "//third_party/WebKit/Source/bindings/scripts:cached_lex_yacc_tables", "//third_party/WebKit/Source/bindings/scripts:cached_jinja_templates", + "//third_party/WebKit/Source/bindings/scripts:cached_lex_yacc_tables", "//third_party/WebKit/Source/core:generated_testing_idls", ] } @@ -237,8 +236,8 @@ "//third_party/WebKit/Source/bindings/core:interfaces_info_individual_core", "//third_party/WebKit/Source/bindings/modules:interfaces_info", "//third_party/WebKit/Source/bindings/modules:interfaces_info_individual_modules", - "//third_party/WebKit/Source/bindings/scripts:cached_lex_yacc_tables", "//third_party/WebKit/Source/bindings/scripts:cached_jinja_templates", + "//third_party/WebKit/Source/bindings/scripts:cached_lex_yacc_tables", ] } }
diff --git a/third_party/WebKit/Source/core/BUILD.gn b/third_party/WebKit/Source/core/BUILD.gn index 4a6d874e..b80e959b 100644 --- a/third_party/WebKit/Source/core/BUILD.gn +++ b/third_party/WebKit/Source/core/BUILD.gn
@@ -49,10 +49,9 @@ deps = [ ":make_core_generated", ":prerequisites", - "inspector:protocol_sources", - "inspector:instrumentation_sources", "//gin", "//skia", + "//third_party/WebKit/Source/bindings/core/v8:bindings_core_v8_generated", "//third_party/iccjpeg", "//third_party/libpng", "//third_party/libwebp", @@ -61,7 +60,8 @@ "//third_party/npapi", "//third_party/qcms", "//third_party/sqlite", - "//third_party/WebKit/Source/bindings/core/v8:bindings_core_v8_generated", + "inspector:instrumentation_sources", + "inspector:protocol_sources", # FIXME: don't depend on bindings/modules http://crbug.com/358074 "//third_party/WebKit/Source/bindings/modules:bindings_modules_generated", @@ -76,9 +76,9 @@ # GYP version: WebKit/Source/core/core.gyp:webcore_prerequisites source_set("prerequisites") { public_deps = [ - "//third_party/WebKit/Source/wtf", "//gpu/command_buffer/client:gles2_c_lib", "//skia", + "//third_party/WebKit/Source/wtf", "//third_party/angle:translator", "//third_party/iccjpeg", "//third_party/icu", @@ -97,9 +97,9 @@ ] deps = [ ":make_core_generated", - "inspector:protocol_sources", - "inspector:instrumentation_sources", "//third_party/WebKit/Source/bindings/core/v8:bindings_core_v8_generated", + "inspector:instrumentation_sources", + "inspector:protocol_sources", # FIXME: don't depend on bindings_modules http://crbug.com/358074 "//third_party/WebKit/Source/bindings/modules/v8:bindings_modules_generated", @@ -137,10 +137,10 @@ public_deps = [ ":core_generated", "//skia", - "//third_party/npapi", - "//third_party/qcms", "//third_party/WebKit/Source/platform", "//third_party/WebKit/Source/wtf", + "//third_party/npapi", + "//third_party/qcms", "//url", "//v8", ] @@ -423,10 +423,9 @@ public_deps = [ ":make_core_generated", ":prerequisites", - "inspector:protocol_sources", - "inspector:instrumentation_sources", "//gin", "//skia", + "//third_party/WebKit/Source/bindings/core/v8:bindings_core_v8_generated", "//third_party/iccjpeg", "//third_party/libpng", "//third_party/libwebp", @@ -435,7 +434,8 @@ "//third_party/npapi", "//third_party/qcms", "//third_party/sqlite", - "//third_party/WebKit/Source/bindings/core/v8:bindings_core_v8_generated", + "inspector:instrumentation_sources", + "inspector:protocol_sources", # FIXME: don't depend on bindings/modules http://crbug.com/358074 "//third_party/WebKit/Source/bindings/modules:bindings_modules_generated", @@ -496,8 +496,8 @@ group("generated_testing_idls") { public_deps = [ ":generated_settings_macros", - ":generated_testing_idls_settings", ":generated_testing_idls_internal_runtime_flags", + ":generated_testing_idls_settings", ] } @@ -572,36 +572,36 @@ # GYP version: WebKit/Source/core/core_generated.gyp:make_core_generated group("make_core_generated") { public_deps = [ - ":make_core_generated_private_script", - ":make_core_generated_private_script_for_testing", - ":make_core_generated_html_entity_table", + ":make_core_generated_bison", + ":make_core_generated_css_property_metadata", ":make_core_generated_css_property_names", ":make_core_generated_css_tokenizer_codepoints", - ":make_core_generated_media_feature_names", - ":make_core_generated_media_features", - ":make_core_generated_media_type_names", - ":make_core_generated_style_property_shorthand", - ":make_core_generated_style_builder", - ":make_core_generated_css_property_metadata", ":make_core_generated_css_value_keywords", - ":make_core_generated_html_element_factory", - ":make_core_generated_html_element_type_helpers", - ":make_core_generated_svg_names", - ":make_core_generated_svg_element_type_helpers", ":make_core_generated_event_factory", ":make_core_generated_event_names", ":make_core_generated_event_target_names", - ":make_core_generated_math_ml_names", - ":make_core_generated_fetch_initiator_type_names", ":make_core_generated_event_type_names", + ":make_core_generated_fetch_initiator_type_names", + ":make_core_generated_html_element_factory", + ":make_core_generated_html_element_lookup_trie", + ":make_core_generated_html_element_type_helpers", + ":make_core_generated_html_entity_table", ":make_core_generated_html_tokenizer_names", ":make_core_generated_input_type_names", - ":make_core_generated_xlink_names", - ":make_core_generated_xml_ns_names", - ":make_core_generated_xml_names", ":make_core_generated_make_token_matcher_for_viewport", - ":make_core_generated_html_element_lookup_trie", - ":make_core_generated_bison", + ":make_core_generated_math_ml_names", + ":make_core_generated_media_feature_names", + ":make_core_generated_media_features", + ":make_core_generated_media_type_names", + ":make_core_generated_private_script", + ":make_core_generated_private_script_for_testing", + ":make_core_generated_style_builder", + ":make_core_generated_style_property_shorthand", + ":make_core_generated_svg_element_type_helpers", + ":make_core_generated_svg_names", + ":make_core_generated_xlink_names", + ":make_core_generated_xml_names", + ":make_core_generated_xml_ns_names", ] }
diff --git a/third_party/WebKit/Source/core/animation/AnimationEffect.cpp b/third_party/WebKit/Source/core/animation/AnimationEffect.cpp index a1c02dd..3d64889 100644 --- a/third_party/WebKit/Source/core/animation/AnimationEffect.cpp +++ b/third_party/WebKit/Source/core/animation/AnimationEffect.cpp
@@ -95,37 +95,6 @@ specifiedTimingChanged(); } -bool AnimationEffect::requiresIterationEvents() const -{ - return m_eventDelegate && m_eventDelegate->requiresIterationEvents(*this); -} - -void AnimationEffect::clearEventDelegate() -{ - m_eventDelegate = nullptr; -} - -void AnimationEffect::attach(Animation* animation) -{ - m_animation = animation; -} - -void AnimationEffect::detach() -{ - ASSERT(m_animation); - m_animation = nullptr; -} - -const Animation* AnimationEffect::animation() const -{ - return m_animation; -} - -Animation* AnimationEffect::animation() -{ - return m_animation; -} - void AnimationEffect::computedTiming(ComputedTimingProperties& computedTiming) { // ComputedTimingProperties members.
diff --git a/third_party/WebKit/Source/core/animation/AnimationEffect.h b/third_party/WebKit/Source/core/animation/AnimationEffect.h index 9c6c880f..41de54a 100644 --- a/third_party/WebKit/Source/core/animation/AnimationEffect.h +++ b/third_party/WebKit/Source/core/animation/AnimationEffect.h
@@ -98,8 +98,8 @@ double activeDurationInternal() const; double endTimeInternal() const { return specifiedTiming().startDelay + activeDurationInternal() + specifiedTiming().endDelay; } - const Animation* animation() const; - Animation* animation(); + const Animation* animation() const { return m_animation; } + Animation* animation() { return m_animation; } const Timing& specifiedTiming() const { return m_timing; } AnimationEffectTiming* timing(); void updateSpecifiedTiming(const Timing&); @@ -118,13 +118,21 @@ // When AnimationEffect receives a new inherited time via updateInheritedTime // it will (if necessary) recalculate timings and (if necessary) call // updateChildrenAndEffects. - void updateInheritedTime(double, TimingUpdateReason) const; + void updateInheritedTime(double inheritedTime, TimingUpdateReason) const; void invalidate() const { m_needsUpdate = true; } - bool requiresIterationEvents() const; - void clearEventDelegate(); + bool requiresIterationEvents() const { return m_eventDelegate && m_eventDelegate->requiresIterationEvents(*this); } + void clearEventDelegate() { m_eventDelegate = nullptr; } - virtual void attach(Animation*); - virtual void detach(); + virtual void attach(Animation* animation) + { + m_animation = animation; + } + + virtual void detach() + { + ASSERT(m_animation); + m_animation = nullptr; + } double repeatedDuration() const;
diff --git a/third_party/WebKit/Source/core/animation/CompositorAnimationsTestHelper.h b/third_party/WebKit/Source/core/animation/CompositorAnimationsTestHelper.h index 384f4cc2..687fa04 100644 --- a/third_party/WebKit/Source/core/animation/CompositorAnimationsTestHelper.h +++ b/third_party/WebKit/Source/core/animation/CompositorAnimationsTestHelper.h
@@ -26,7 +26,7 @@ #define CompositorAnimationsTestHelper_h #include "core/animation/CompositorAnimations.h" -#include "public/platform/Platform.h" +#include "platform/testing/TestingPlatformSupport.h" #include "public/platform/WebCompositorAnimationPlayer.h" #include "public/platform/WebCompositorAnimationTimeline.h" #include "public/platform/WebCompositorSupport.h" @@ -152,31 +152,13 @@ }; private: - class PlatformProxy : public Platform { + class PlatformProxy : public TestingPlatformSupport { public: - PlatformProxy(WebCompositorSupportMock** compositor) : m_platform(Platform::current()), m_compositor(compositor) { } - - ~PlatformProxy() - { - blink::Platform::initialize(m_platform); - } - - virtual void cryptographicallyRandomValues(unsigned char* buffer, size_t length) { ASSERT_NOT_REACHED(); } - const unsigned char* getTraceCategoryEnabledFlag(const char* categoryName) override - { - static const unsigned char tracingIsDisabled = 0; - return &tracingIsDisabled; - } - - WebThread* currentThread() override - { - return m_platform->currentThread(); - } - + explicit PlatformProxy(WebCompositorSupportMock** compositor) : m_compositor(compositor) { } private: - blink::Platform* m_platform; // Not owned. - WebCompositorSupportMock** m_compositor; WebCompositorSupport* compositorSupport() override { return *m_compositor; } + + WebCompositorSupportMock** m_compositor; }; WebCompositorSupportMock* m_mockCompositor;
diff --git a/third_party/WebKit/Source/core/animation/InterpolationEnvironment.h b/third_party/WebKit/Source/core/animation/InterpolationEnvironment.h index 10101cc..490619b 100644 --- a/third_party/WebKit/Source/core/animation/InterpolationEnvironment.h +++ b/third_party/WebKit/Source/core/animation/InterpolationEnvironment.h
@@ -5,14 +5,14 @@ #ifndef InterpolationEnvironment_h #define InterpolationEnvironment_h -#include "core/svg/SVGElement.h" -#include "core/svg/properties/SVGProperty.h" #include "platform/heap/Handle.h" #include "wtf/Allocator.h" namespace blink { class StyleResolverState; +class SVGPropertyBase; +class SVGElement; class InterpolationEnvironment { STACK_ALLOCATED();
diff --git a/third_party/WebKit/Source/core/clipboard/DataTransferItem.cpp b/third_party/WebKit/Source/core/clipboard/DataTransferItem.cpp index 2788f57..84a94b7 100644 --- a/third_party/WebKit/Source/core/clipboard/DataTransferItem.cpp +++ b/third_party/WebKit/Source/core/clipboard/DataTransferItem.cpp
@@ -85,16 +85,6 @@ return m_item->getAsFile(); } -DataTransfer* DataTransferItem::dataTransfer() const -{ - return m_dataTransfer; -} - -DataObjectItem* DataTransferItem::dataObjectItem() const -{ - return m_item; -} - DataTransferItem::DataTransferItem(DataTransfer* dataTransfer, DataObjectItem* item) : m_dataTransfer(dataTransfer) , m_item(item)
diff --git a/third_party/WebKit/Source/core/clipboard/DataTransferItem.h b/third_party/WebKit/Source/core/clipboard/DataTransferItem.h index b627bdb..2e1da11a 100644 --- a/third_party/WebKit/Source/core/clipboard/DataTransferItem.h +++ b/third_party/WebKit/Source/core/clipboard/DataTransferItem.h
@@ -58,8 +58,8 @@ void getAsString(ExecutionContext*, StringCallback*) const; Blob* getAsFile() const; - DataTransfer* dataTransfer() const; - DataObjectItem* dataObjectItem() const; + DataTransfer* dataTransfer() { return m_dataTransfer.get(); } + DataObjectItem* dataObjectItem() { return m_item.get(); } DECLARE_TRACE();
diff --git a/third_party/WebKit/Source/core/css/CSSDefaultStyleSheets.cpp b/third_party/WebKit/Source/core/css/CSSDefaultStyleSheets.cpp index 01a17a70..ad829bc1 100644 --- a/third_party/WebKit/Source/core/css/CSSDefaultStyleSheets.cpp +++ b/third_party/WebKit/Source/core/css/CSSDefaultStyleSheets.cpp
@@ -103,21 +103,6 @@ m_defaultQuirksStyle->addRulesFromSheet(quirksStyleSheet(), screenEval()); } -RuleSet* CSSDefaultStyleSheets::defaultStyle() const -{ - return m_defaultStyle.get(); -} - -RuleSet* CSSDefaultStyleSheets::defaultQuirksStyle() const -{ - return m_defaultQuirksStyle.get(); -} - -RuleSet* CSSDefaultStyleSheets::defaultPrintStyle() const -{ - return m_defaultPrintStyle.get(); -} - RuleSet* CSSDefaultStyleSheets::defaultViewSourceStyle() { if (!m_defaultViewSourceStyle) { @@ -140,36 +125,6 @@ return m_defaultXHTMLMobileProfileStyle.get(); } -StyleSheetContents* CSSDefaultStyleSheets::defaultStyleSheet() const -{ - return m_defaultStyleSheet.get(); -} - -StyleSheetContents* CSSDefaultStyleSheets::quirksStyleSheet() const -{ - return m_quirksStyleSheet.get(); -} - -StyleSheetContents* CSSDefaultStyleSheets::svgStyleSheet() const -{ - return m_svgStyleSheet.get(); -} - -StyleSheetContents* CSSDefaultStyleSheets::mathmlStyleSheet() const -{ - return m_mathmlStyleSheet.get(); -} - -StyleSheetContents* CSSDefaultStyleSheets::mediaControlsStyleSheet() const -{ - return m_mediaControlsStyleSheet.get(); -} - -StyleSheetContents* CSSDefaultStyleSheets::fullscreenStyleSheet() const -{ - return m_fullscreenStyleSheet.get(); -} - RuleSet* CSSDefaultStyleSheets::defaultMobileViewportStyle() { if (!m_defaultMobileViewportStyle) {
diff --git a/third_party/WebKit/Source/core/css/CSSDefaultStyleSheets.h b/third_party/WebKit/Source/core/css/CSSDefaultStyleSheets.h index e44cf7f..eaecf4a8 100644 --- a/third_party/WebKit/Source/core/css/CSSDefaultStyleSheets.h +++ b/third_party/WebKit/Source/core/css/CSSDefaultStyleSheets.h
@@ -40,21 +40,21 @@ void ensureDefaultStyleSheetsForElement(const Element&, bool& changedDefaultStyle); - RuleSet* defaultStyle() const; - RuleSet* defaultQuirksStyle() const; - RuleSet* defaultPrintStyle() const; + RuleSet* defaultStyle() { return m_defaultStyle.get(); } + RuleSet* defaultQuirksStyle() { return m_defaultQuirksStyle.get(); } + RuleSet* defaultPrintStyle() { return m_defaultPrintStyle.get(); } RuleSet* defaultViewSourceStyle(); RuleSet* defaultMobileViewportStyle(); // FIXME: Remove WAP support. RuleSet* defaultXHTMLMobileProfileStyle(); - StyleSheetContents* defaultStyleSheet() const; - StyleSheetContents* quirksStyleSheet() const; - StyleSheetContents* svgStyleSheet() const; - StyleSheetContents* mathmlStyleSheet() const; - StyleSheetContents* mediaControlsStyleSheet() const; - StyleSheetContents* fullscreenStyleSheet() const; + StyleSheetContents* defaultStyleSheet() { return m_defaultStyleSheet.get(); } + StyleSheetContents* quirksStyleSheet() { return m_quirksStyleSheet.get(); } + StyleSheetContents* svgStyleSheet() { return m_svgStyleSheet.get(); } + StyleSheetContents* mathmlStyleSheet() { return m_mathmlStyleSheet.get(); } + StyleSheetContents* mediaControlsStyleSheet() { return m_mediaControlsStyleSheet.get(); } + StyleSheetContents* fullscreenStyleSheet() { return m_fullscreenStyleSheet.get(); } DECLARE_TRACE();
diff --git a/third_party/WebKit/Source/core/css/CSSFontFaceSource.cpp b/third_party/WebKit/Source/core/css/CSSFontFaceSource.cpp index 6aa92898..e0a7cf4c 100644 --- a/third_party/WebKit/Source/core/css/CSSFontFaceSource.cpp +++ b/third_party/WebKit/Source/core/css/CSSFontFaceSource.cpp
@@ -43,11 +43,6 @@ { } -void CSSFontFaceSource::setFontFace(CSSFontFace* face) -{ - m_face = face; -} - PassRefPtr<SimpleFontData> CSSFontFaceSource::getFontData(const FontDescription& fontDescription) { // If the font hasn't loaded or an error occurred, then we've got nothing.
diff --git a/third_party/WebKit/Source/core/css/CSSFontFaceSource.h b/third_party/WebKit/Source/core/css/CSSFontFaceSource.h index 478bb4c..c9819bb 100644 --- a/third_party/WebKit/Source/core/css/CSSFontFaceSource.h +++ b/third_party/WebKit/Source/core/css/CSSFontFaceSource.h
@@ -49,7 +49,7 @@ virtual bool isValid() const { return true; } virtual FontResource* resource() { return nullptr; } - void setFontFace(CSSFontFace*); + void setFontFace(CSSFontFace* face) { m_face = face; } PassRefPtr<SimpleFontData> getFontData(const FontDescription&);
diff --git a/third_party/WebKit/Source/core/css/CSSImageValue.cpp b/third_party/WebKit/Source/core/css/CSSImageValue.cpp index 4f9be98..f63bae4 100644 --- a/third_party/WebKit/Source/core/css/CSSImageValue.cpp +++ b/third_party/WebKit/Source/core/css/CSSImageValue.cpp
@@ -46,12 +46,6 @@ { } -StyleFetchedImage* CSSImageValue::cachedImage() const -{ - ASSERT(!isCachePending()); - return m_cachedImage.get(); -} - StyleFetchedImage* CSSImageValue::cacheImage(Document* document, const ResourceLoaderOptions& options) { ASSERT(document); @@ -113,11 +107,6 @@ return m_cachedImage ? m_cachedImage->knownToBeOpaque(layoutObject) : false; } -PassRefPtrWillBeRawPtr<CSSImageValue> CSSImageValue::valueWithURLMadeAbsolute() -{ - return create(KURL(ParsedURLString, m_absoluteURL), m_cachedImage.get()); -} - DEFINE_TRACE_AFTER_DISPATCH(CSSImageValue) { visitor->trace(m_cachedImage);
diff --git a/third_party/WebKit/Source/core/css/CSSImageValue.h b/third_party/WebKit/Source/core/css/CSSImageValue.h index ef962ca..5ec97cd 100644 --- a/third_party/WebKit/Source/core/css/CSSImageValue.h +++ b/third_party/WebKit/Source/core/css/CSSImageValue.h
@@ -51,7 +51,7 @@ ~CSSImageValue(); bool isCachePending() const { return m_isCachePending; } - StyleFetchedImage* cachedImage() const; + StyleFetchedImage* cachedImage() const { ASSERT(!isCachePending()); return m_cachedImage.get(); } StyleFetchedImage* cacheImage(Document*, const ResourceLoaderOptions&); StyleFetchedImage* cacheImage(Document* document) { return cacheImage(document, ResourceFetcher::defaultResourceOptions()); } @@ -70,7 +70,10 @@ bool knownToBeOpaque(const LayoutObject*) const; - PassRefPtrWillBeRawPtr<CSSImageValue> valueWithURLMadeAbsolute(); + PassRefPtrWillBeRawPtr<CSSImageValue> valueWithURLMadeAbsolute() + { + return create(KURL(ParsedURLString, m_absoluteURL), m_cachedImage.get()); + } void setInitiator(const AtomicString& name) { m_initiatorName = name; }
diff --git a/third_party/WebKit/Source/core/css/CSSRuleList.cpp b/third_party/WebKit/Source/core/css/CSSRuleList.cpp index d393f574..5a2e44a5 100644 --- a/third_party/WebKit/Source/core/css/CSSRuleList.cpp +++ b/third_party/WebKit/Source/core/css/CSSRuleList.cpp
@@ -50,11 +50,6 @@ } #endif -CSSRule* StaticCSSRuleList::item(unsigned index) const -{ - return index < m_rules.size() ? m_rules[index].get() : nullptr; -} - DEFINE_TRACE(StaticCSSRuleList) { visitor->trace(m_rules);
diff --git a/third_party/WebKit/Source/core/css/CSSRuleList.h b/third_party/WebKit/Source/core/css/CSSRuleList.h index 3d102ef..78c660b 100644 --- a/third_party/WebKit/Source/core/css/CSSRuleList.h +++ b/third_party/WebKit/Source/core/css/CSSRuleList.h
@@ -79,7 +79,7 @@ ~StaticCSSRuleList() override; unsigned length() const override { return m_rules.size(); } - CSSRule* item(unsigned index) const override; + CSSRule* item(unsigned index) const override { return index < m_rules.size() ? m_rules[index].get() : nullptr; } WillBeHeapVector<RefPtrWillBeMember<CSSRule>> m_rules; #if !ENABLE(OILPAN)
diff --git a/third_party/WebKit/Source/core/css/CSSStyleSheet.cpp b/third_party/WebKit/Source/core/css/CSSStyleSheet.cpp index bcda22d9..b7461c1 100644 --- a/third_party/WebKit/Source/core/css/CSSStyleSheet.cpp +++ b/third_party/WebKit/Source/core/css/CSSStyleSheet.cpp
@@ -409,11 +409,6 @@ return root->ownerNode() ? &root->ownerNode()->document() : nullptr; } -MediaQuerySet* CSSStyleSheet::mediaQueries() const -{ - return m_mediaQueries.get(); -} - void CSSStyleSheet::setAllowRuleAccessFromOrigin(PassRefPtr<SecurityOrigin> allowedOrigin) { m_allowRuleAccessFromOrigin = allowedOrigin; @@ -424,11 +419,6 @@ m_childRuleCSSOMWrappers.clear(); } -StyleSheetContents* CSSStyleSheet::contents() const -{ - return m_contents.get(); -} - bool CSSStyleSheet::sheetLoaded() { ASSERT(m_ownerNode);
diff --git a/third_party/WebKit/Source/core/css/CSSStyleSheet.h b/third_party/WebKit/Source/core/css/CSSStyleSheet.h index d055aba..0f8ebc9 100644 --- a/third_party/WebKit/Source/core/css/CSSStyleSheet.h +++ b/third_party/WebKit/Source/core/css/CSSStyleSheet.h
@@ -86,7 +86,7 @@ void clearOwnerRule() { m_ownerRule = nullptr; } Document* ownerDocument() const; - MediaQuerySet* mediaQueries() const; + MediaQuerySet* mediaQueries() const { return m_mediaQueries.get(); } void setMediaQueries(PassRefPtrWillBeRawPtr<MediaQuerySet>); void setTitle(const String& title) { m_title = title; } // Set by LinkStyle iff CORS-enabled fetch of stylesheet succeeded from this origin. @@ -110,7 +110,7 @@ void clearChildRuleCSSOMWrappers(); - StyleSheetContents* contents() const; + StyleSheetContents* contents() const { return m_contents.get(); } bool isInline() const { return m_isInlineStylesheet; } TextPosition startPositionInSource() const { return m_startPosition; }
diff --git a/third_party/WebKit/Source/core/css/FontFace.cpp b/third_party/WebKit/Source/core/css/FontFace.cpp index 447703cd..6aedc0b 100644 --- a/third_party/WebKit/Source/core/css/FontFace.cpp +++ b/third_party/WebKit/Source/core/css/FontFace.cpp
@@ -528,11 +528,6 @@ return FontTraits(style, variant, weight, stretch); } -CSSFontFace* FontFace::cssFontFace() const -{ - return m_cssFontFace.get(); -} - static PassOwnPtrWillBeRawPtr<CSSFontFace> createCSSFontFace(FontFace* fontFace, CSSValue* unicodeRange) { Vector<CSSFontFace::UnicodeRange> ranges;
diff --git a/third_party/WebKit/Source/core/css/FontFace.h b/third_party/WebKit/Source/core/css/FontFace.h index 24981b8..d0f5d4b 100644 --- a/third_party/WebKit/Source/core/css/FontFace.h +++ b/third_party/WebKit/Source/core/css/FontFace.h
@@ -94,7 +94,7 @@ void setError(DOMException* = nullptr); DOMException* error() const { return m_error; } FontTraits traits() const; - CSSFontFace* cssFontFace() const; + CSSFontFace* cssFontFace() { return m_cssFontFace.get(); } DECLARE_VIRTUAL_TRACE();
diff --git a/third_party/WebKit/Source/core/css/PropertySetCSSStyleDeclaration.cpp b/third_party/WebKit/Source/core/css/PropertySetCSSStyleDeclaration.cpp index 417d46f..3abfbc33 100644 --- a/third_party/WebKit/Source/core/css/PropertySetCSSStyleDeclaration.cpp +++ b/third_party/WebKit/Source/core/css/PropertySetCSSStyleDeclaration.cpp
@@ -349,11 +349,6 @@ PropertySetCSSStyleDeclaration::trace(visitor); } -InlineCSSStyleDeclaration::InlineCSSStyleDeclaration(Element* parentElement) - : m_parentElement(parentElement) -{ -} - MutableStylePropertySet& InlineCSSStyleDeclaration::propertySet() const { return m_parentElement->ensureMutableInlineStyle(); @@ -378,11 +373,6 @@ return m_parentElement ? &m_parentElement->document().elementSheet() : nullptr; } -Element* InlineCSSStyleDeclaration::parentElement() const -{ - return m_parentElement; -} - #if !ENABLE(OILPAN) void InlineCSSStyleDeclaration::ref() {
diff --git a/third_party/WebKit/Source/core/css/PropertySetCSSStyleDeclaration.h b/third_party/WebKit/Source/core/css/PropertySetCSSStyleDeclaration.h index 120d298..c25c05af 100644 --- a/third_party/WebKit/Source/core/css/PropertySetCSSStyleDeclaration.h +++ b/third_party/WebKit/Source/core/css/PropertySetCSSStyleDeclaration.h
@@ -41,7 +41,7 @@ class AbstractPropertySetCSSStyleDeclaration : public CSSStyleDeclaration { public: - virtual Element* parentElement() const { return nullptr; } + virtual Element* parentElement() const { return 0; } StyleSheetContents* contextStyleSheet() const; DECLARE_VIRTUAL_TRACE(); @@ -127,7 +127,10 @@ class InlineCSSStyleDeclaration final : public AbstractPropertySetCSSStyleDeclaration { public: - explicit InlineCSSStyleDeclaration(Element* parentElement); + explicit InlineCSSStyleDeclaration(Element* parentElement) + : m_parentElement(parentElement) + { + } DECLARE_VIRTUAL_TRACE(); @@ -138,7 +141,7 @@ void deref() override; #endif CSSStyleSheet* parentStyleSheet() const override; - Element* parentElement() const override; + Element* parentElement() const override { return m_parentElement; } void didMutate(MutationType) override;
diff --git a/third_party/WebKit/Source/core/css/StyleRuleImport.cpp b/third_party/WebKit/Source/core/css/StyleRuleImport.cpp index 5f597fe..90eddf98 100644 --- a/third_party/WebKit/Source/core/css/StyleRuleImport.cpp +++ b/third_party/WebKit/Source/core/css/StyleRuleImport.cpp
@@ -68,32 +68,6 @@ StyleRuleBase::traceAfterDispatch(visitor); } -StyleSheetContents* StyleRuleImport::parentStyleSheet() const -{ - return m_parentStyleSheet; -} - -void StyleRuleImport::setParentStyleSheet(StyleSheetContents* sheet) -{ - ASSERT(sheet); - m_parentStyleSheet = sheet; -} - -void StyleRuleImport::clearParentStyleSheet() -{ - m_parentStyleSheet = nullptr; -} - -StyleSheetContents* StyleRuleImport::styleSheet() const -{ - return m_styleSheet.get(); -} - -MediaQuerySet* StyleRuleImport::mediaQueries() const -{ - return m_mediaQueries.get(); -} - void StyleRuleImport::setCSSStyleSheet(const String& href, const KURL& baseURL, const String& charset, const CSSStyleSheetResource* cachedStyleSheet) { if (m_styleSheet)
diff --git a/third_party/WebKit/Source/core/css/StyleRuleImport.h b/third_party/WebKit/Source/core/css/StyleRuleImport.h index fbd48c5..2c795e1 100644 --- a/third_party/WebKit/Source/core/css/StyleRuleImport.h +++ b/third_party/WebKit/Source/core/css/StyleRuleImport.h
@@ -40,15 +40,15 @@ ~StyleRuleImport(); - StyleSheetContents* parentStyleSheet() const; - void setParentStyleSheet(StyleSheetContents*); - void clearParentStyleSheet(); + StyleSheetContents* parentStyleSheet() const { return m_parentStyleSheet; } + void setParentStyleSheet(StyleSheetContents* sheet) { ASSERT(sheet); m_parentStyleSheet = sheet; } + void clearParentStyleSheet() { m_parentStyleSheet = nullptr; } String href() const { return m_strHref; } - StyleSheetContents* styleSheet() const; + StyleSheetContents* styleSheet() const { return m_styleSheet.get(); } bool isLoading() const; - MediaQuerySet* mediaQueries() const; + MediaQuerySet* mediaQueries() { return m_mediaQueries.get(); } void requestStyleSheet();
diff --git a/third_party/WebKit/Source/core/css/resolver/AnimatedStyleBuilder.cpp b/third_party/WebKit/Source/core/css/resolver/AnimatedStyleBuilder.cpp index 4873fece..bd881bd 100644 --- a/third_party/WebKit/Source/core/css/resolver/AnimatedStyleBuilder.cpp +++ b/third_party/WebKit/Source/core/css/resolver/AnimatedStyleBuilder.cpp
@@ -59,7 +59,8 @@ #include "core/css/resolver/StyleResolverState.h" #include "core/style/ComputedStyle.h" #include "wtf/MathExtras.h" -#include "wtf/TypeTraits.h" + +#include <type_traits> namespace blink { @@ -95,7 +96,7 @@ template<typename T> T animatableValueClampTo(const AnimatableValue* value, T min = defaultMinimumForClamp<T>(), T max = defaultMaximumForClamp<T>()) { - static_assert(WTF::IsInteger<T>::value, "should use integral type T when rounding values"); + static_assert(std::is_integral<T>::value, "should use integral type T when rounding values"); return clampTo<T>(roundForImpreciseConversion<T>(toAnimatableDouble(value)->toDouble()), min, max); }
diff --git a/third_party/WebKit/Source/core/css/resolver/StyleResolver.cpp b/third_party/WebKit/Source/core/css/resolver/StyleResolver.cpp index 9bc94f1..35ab44b 100644 --- a/third_party/WebKit/Source/core/css/resolver/StyleResolver.cpp +++ b/third_party/WebKit/Source/core/css/resolver/StyleResolver.cpp
@@ -1524,11 +1524,6 @@ } } -ViewportStyleResolver* StyleResolver::viewportStyleResolver() const -{ - return m_viewportStyleResolver.get(); -} - void StyleResolver::addMediaQueryResults(const MediaQueryResultList& list) { for (size_t i = 0; i < list.size(); ++i)
diff --git a/third_party/WebKit/Source/core/css/resolver/StyleResolver.h b/third_party/WebKit/Source/core/css/resolver/StyleResolver.h index c2a7da86..59e73e1 100644 --- a/third_party/WebKit/Source/core/css/resolver/StyleResolver.h +++ b/third_party/WebKit/Source/core/css/resolver/StyleResolver.h
@@ -137,7 +137,7 @@ void computeFont(ComputedStyle*, const StylePropertySet&); - ViewportStyleResolver* viewportStyleResolver() const; + ViewportStyleResolver* viewportStyleResolver() { return m_viewportStyleResolver.get(); } void addMediaQueryResults(const MediaQueryResultList&); MediaQueryResultList* viewportDependentMediaQueryResults() { return &m_viewportDependentMediaQueryResults; }
diff --git a/third_party/WebKit/Source/core/dom/Document.cpp b/third_party/WebKit/Source/core/dom/Document.cpp index 56bf7f9f..310aa41 100644 --- a/third_party/WebKit/Source/core/dom/Document.cpp +++ b/third_party/WebKit/Source/core/dom/Document.cpp
@@ -659,11 +659,6 @@ styleEngine().clearResolver(); } -DocumentType* Document::doctype() const -{ - return m_docType.get(); -} - DOMImplementation& Document::implementation() { if (!m_implementation) @@ -671,11 +666,6 @@ return *m_implementation; } -Element* Document::documentElement() const -{ - return m_documentElement.get(); -} - bool Document::hasAppCacheManifest() const { return isHTMLHtmlElement(documentElement()) && documentElement()->hasAttribute(manifestAttr); @@ -792,11 +782,6 @@ return constructorBuilder.bindingsReturnValue(); } -CustomElementRegistrationContext* Document::registrationContext() const -{ - return m_registrationContext.get(); -} - CustomElementMicrotaskRunQueue* Document::customElementMicrotaskRunQueue() { if (!m_customElementMicrotaskRunQueue) @@ -990,8 +975,7 @@ if (source->isFrameOwnerElement()) { HTMLFrameOwnerElement* frameOwnerElement = toHTMLFrameOwnerElement(source.get()); - // FIXME(kenrb): the downcast can be removed when the FrameTree supports RemoteFrames. - if (frame() && frame()->tree().isDescendantOf(toLocalFrameTemporary(frameOwnerElement->contentFrame()))) { + if (frame() && frame()->tree().isDescendantOf(frameOwnerElement->contentFrame())) { exceptionState.throwDOMException(HierarchyRequestError, "The node provided is a frame which contains this document."); return nullptr; } @@ -1335,11 +1319,6 @@ updateTitle(toSVGTitleElement(m_titleElement)->textContent()); } -Element* Document::titleElement() const -{ - return m_titleElement.get(); -} - void Document::removeTitle(Element* titleElement) { if (m_titleElement != titleElement) @@ -2003,11 +1982,6 @@ m_clearFocusedElementTimer.startOneShot(0, BLINK_FROM_HERE); } -Element* Document::focusedElement() const -{ - return m_focusedElement.get(); -} - void Document::clearFocusedElementTimerFired(Timer<Document>*) { updateLayoutTreeIfNeeded(); @@ -3045,10 +3019,6 @@ frame()->script().disableEval(errorMessage); } -ElementDataCache* Document::elementDataCache() const -{ - return m_elementDataCache.get(); -} void Document::didLoadAllImports() { @@ -3368,12 +3338,6 @@ return m_styleSheetList.get(); } -StyleEngine& Document::styleEngine() -{ - ASSERT(m_styleEngine.get()); - return *m_styleEngine.get(); -} - String Document::preferredStylesheetSet() const { return m_styleEngine->preferredStylesheetSetName(); @@ -3449,16 +3413,6 @@ m_activeHoverElement = newActiveElement; } -Element* Document::activeHoverElement() const -{ - return m_activeHoverElement.get(); -} - -Node* Document::hoverNode() const -{ - return m_hoverNode.get(); -} - void Document::removeFocusedElementOfSubtree(Node* node, bool amongChildrenOnly) { if (!m_focusedElement) @@ -4494,11 +4448,6 @@ return KURL(); } -HTMLScriptElement* Document::currentScript() const -{ - return !m_currentScriptStack.isEmpty() ? m_currentScriptStack.last().get() : nullptr; -} - void Document::pushCurrentScript(PassRefPtrWillBeRawPtr<HTMLScriptElement> newCurrentScript) { ASSERT(newCurrentScript); @@ -4570,11 +4519,6 @@ return nullptr; } -ScriptRunner* Document::scriptRunner() const -{ - return m_scriptRunner.get(); -} - PassRefPtrWillBeRawPtr<Attr> Document::createAttribute(const AtomicString& name, ExceptionState& exceptionState) { if (isHTMLDocument() && name != name.lower()) @@ -5643,11 +5587,6 @@ m_taskRunner->postTask(BLINK_FROM_HERE, AutofocusTask::create()); } -Element* Document::autofocusElement() const -{ - return m_autofocusElement.get(); -} - Element* Document::activeElement() const { if (Element* element = adjustedFocusedElement())
diff --git a/third_party/WebKit/Source/core/dom/Document.h b/third_party/WebKit/Source/core/dom/Document.h index 2a46a46..926d796 100644 --- a/third_party/WebKit/Source/core/dom/Document.h +++ b/third_party/WebKit/Source/core/dom/Document.h
@@ -39,21 +39,15 @@ #include "core/dom/DocumentLifecycle.h" #include "core/dom/DocumentLifecycleNotifier.h" #include "core/dom/DocumentLifecycleObserver.h" -#include "core/dom/DocumentParser.h" #include "core/dom/DocumentTiming.h" -#include "core/dom/DocumentType.h" -#include "core/dom/ElementData.h" -#include "core/dom/ElementDataCache.h" #include "core/dom/ExecutionContext.h" #include "core/dom/MutationObserver.h" -#include "core/dom/ScriptRunner.h" #include "core/dom/TextLinkColors.h" #include "core/dom/TreeScope.h" #include "core/dom/UserActionElementSet.h" #include "core/dom/ViewportDescription.h" #include "core/dom/custom/CustomElement.h" #include "core/fetch/ClientHintsPreferences.h" -#include "core/fetch/ResourceFetcher.h" #include "core/frame/DOMTimerCoordinator.h" #include "core/frame/LocalDOMWindow.h" #include "core/frame/OriginsUsingFeatures.h" @@ -96,9 +90,12 @@ class DocumentLoader; class DocumentMarkerController; class DocumentNameCollection; +class DocumentParser; class DocumentState; +class DocumentType; class DocumentVisibilityObserver; class Element; +class ElementDataCache; class ElementRegistrationOptions; class Event; class EventFactoryBase; @@ -147,8 +144,10 @@ class QualifiedName; class Range; class LayoutView; +class ResourceFetcher; class SVGDocumentExtensions; class SVGUseElement; +class ScriptRunner; class ScriptableDocumentParser; class ScriptedAnimationController; class ScriptedIdleTaskController; @@ -269,11 +268,14 @@ String outgoingOrigin() const; void setDoctype(PassRefPtrWillBeRawPtr<DocumentType>); - DocumentType* doctype() const; + DocumentType* doctype() const { return m_docType.get(); } DOMImplementation& implementation(); - Element* documentElement() const; + Element* documentElement() const + { + return m_documentElement.get(); + } // Returns whether the Document has an AppCache manifest. bool hasAppCacheManifest() const; @@ -380,7 +382,7 @@ // This is a DOM function. StyleSheetList* styleSheets(); - StyleEngine& styleEngine(); + StyleEngine& styleEngine() { ASSERT(m_styleEngine.get()); return *m_styleEngine.get(); } bool gotoAnchorNeededAfterStylesheetsLoad() { return m_gotoAnchorNeededAfterStylesheetsLoad; } void setGotoAnchorNeededAfterStylesheetsLoad(bool b) { m_gotoAnchorNeededAfterStylesheetsLoad = b; } @@ -584,17 +586,17 @@ bool setFocusedElement(PassRefPtrWillBeRawPtr<Element>, const FocusParams&); void clearFocusedElement(); - Element* focusedElement() const; + Element* focusedElement() const { return m_focusedElement.get(); } UserActionElementSet& userActionElements() { return m_userActionElements; } const UserActionElementSet& userActionElements() const { return m_userActionElements; } void setNeedsFocusedElementCheck(); void setAutofocusElement(Element*); - Element* autofocusElement() const; + Element* autofocusElement() const { return m_autofocusElement.get(); } void setActiveHoverElement(PassRefPtrWillBeRawPtr<Element>); - Element* activeHoverElement() const; + Element* activeHoverElement() const { return m_activeHoverElement.get(); } - Node* hoverNode() const; + Node* hoverNode() const { return m_hoverNode.get(); } void removeFocusedElementOfSubtree(Node*, bool amongChildrenOnly = false); void hoveredNodeDetached(Element&); @@ -687,7 +689,7 @@ String title() const { return m_title; } void setTitle(const String&); - Element* titleElement() const; + Element* titleElement() const { return m_titleElement.get(); } void setTitleElement(Element*); void removeTitle(Element* titleElement); @@ -772,9 +774,9 @@ Document& topDocument() const; WeakPtrWillBeRawPtr<Document> contextDocument(); - ScriptRunner* scriptRunner() const; + ScriptRunner* scriptRunner() { return m_scriptRunner.get(); } - HTMLScriptElement* currentScript() const; + HTMLScriptElement* currentScript() const { return !m_currentScriptStack.isEmpty() ? m_currentScriptStack.last().get() : nullptr; } void pushCurrentScript(PassRefPtrWillBeRawPtr<HTMLScriptElement>); void popCurrentScript(); @@ -925,7 +927,7 @@ PassRefPtrWillBeRawPtr<Element> createElement(const AtomicString& localName, const AtomicString& typeExtension, ExceptionState&); PassRefPtrWillBeRawPtr<Element> createElementNS(const AtomicString& namespaceURI, const AtomicString& qualifiedName, const AtomicString& typeExtension, ExceptionState&); ScriptValue registerElement(ScriptState*, const AtomicString& name, const ElementRegistrationOptions&, ExceptionState&, CustomElement::NameSet validNames = CustomElement::StandardNames); - CustomElementRegistrationContext* registrationContext() const; + CustomElementRegistrationContext* registrationContext() { return m_registrationContext.get(); } CustomElementMicrotaskRunQueue* customElementMicrotaskRunQueue(); void setImportsController(HTMLImportsController*); @@ -946,7 +948,7 @@ void setContextFeatures(ContextFeatures&); ContextFeatures& contextFeatures() const { return *m_contextFeatures; } - ElementDataCache* elementDataCache() const; + ElementDataCache* elementDataCache() { return m_elementDataCache.get(); } void didLoadAllScriptBlockingResources(); void didRemoveAllPendingStylesheet();
diff --git a/third_party/WebKit/Source/core/dom/DocumentOrderedMap.cpp b/third_party/WebKit/Source/core/dom/DocumentOrderedMap.cpp index 6e72133..c13bfb3 100644 --- a/third_party/WebKit/Source/core/dom/DocumentOrderedMap.cpp +++ b/third_party/WebKit/Source/core/dom/DocumentOrderedMap.cpp
@@ -179,12 +179,6 @@ return get<keyMatchesLabelForAttribute>(key, scope); } -DocumentOrderedMap::MapEntry::MapEntry(Element* firstElement) - : element(firstElement) - , count(1) -{ -} - DEFINE_TRACE(DocumentOrderedMap) { #if ENABLE(OILPAN)
diff --git a/third_party/WebKit/Source/core/dom/DocumentOrderedMap.h b/third_party/WebKit/Source/core/dom/DocumentOrderedMap.h index db75cd6..e4c31163 100644 --- a/third_party/WebKit/Source/core/dom/DocumentOrderedMap.h +++ b/third_party/WebKit/Source/core/dom/DocumentOrderedMap.h
@@ -68,7 +68,11 @@ class MapEntry : public NoBaseWillBeGarbageCollected<MapEntry> { public: - explicit MapEntry(Element*); + explicit MapEntry(Element* firstElement) + : element(firstElement) + , count(1) + { + } DECLARE_TRACE();
diff --git a/third_party/WebKit/Source/core/dom/Element.cpp b/third_party/WebKit/Source/core/dom/Element.cpp index 23f1204..cdd3038 100644 --- a/third_party/WebKit/Source/core/dom/Element.cpp +++ b/third_party/WebKit/Source/core/dom/Element.cpp
@@ -42,6 +42,7 @@ #include "core/css/CSSStyleSheet.h" #include "core/css/CSSValuePool.h" #include "core/css/PropertySetCSSStyleDeclaration.h" +#include "core/css/StylePropertySet.h" #include "core/css/parser/CSSParser.h" #include "core/css/resolver/StyleResolver.h" #include "core/css/resolver/StyleResolverParentScope.h"
diff --git a/third_party/WebKit/Source/core/dom/Element.h b/third_party/WebKit/Source/core/dom/Element.h index 78c7e865..b4b5cbb 100644 --- a/third_party/WebKit/Source/core/dom/Element.h +++ b/third_party/WebKit/Source/core/dom/Element.h
@@ -30,16 +30,13 @@ #include "core/HTMLNames.h" #include "core/css/CSSPrimitiveValue.h" #include "core/css/CSSSelector.h" -#include "core/css/StylePropertySet.h" #include "core/dom/AXObjectCache.h" #include "core/dom/Attribute.h" -#include "core/dom/AttributeCollection.h" #include "core/dom/ContainerNode.h" #include "core/dom/Document.h" #include "core/dom/ElementData.h" #include "core/dom/SpaceSplitString.h" #include "core/html/CollectionType.h" -#include "core/input/InputDeviceCapabilities.h" #include "platform/heap/Handle.h" #include "public/platform/WebFocusType.h" @@ -47,6 +44,7 @@ class ElementAnimations; class Attr; +class Attribute; class CSSStyleDeclaration; class ClientRect; class ClientRectList; @@ -68,6 +66,7 @@ class ScrollToOptions; class ShadowRoot; class ShadowRootInit; +class StylePropertySet; enum SpellcheckAttributeState { SpellcheckAttributeTrue,
diff --git a/third_party/WebKit/Source/core/dom/ElementData.cpp b/third_party/WebKit/Source/core/dom/ElementData.cpp index f316a12..29dc6f3 100644 --- a/third_party/WebKit/Source/core/dom/ElementData.cpp +++ b/third_party/WebKit/Source/core/dom/ElementData.cpp
@@ -50,18 +50,6 @@ return sizeof(ShareableElementData) + sizeof(Attribute) * count; } -const StylePropertySet* ElementData::inlineStyle() const -{ - return m_inlineStyle.get(); -} - -const StylePropertySet* ElementData::presentationAttributeStyle() const -{ - if (!m_isUnique) - return nullptr; - return toUniqueElementData(this)->m_presentationAttributeStyle.get(); -} - ElementData::ElementData() : m_isUnique(true) , m_arraySize(0)
diff --git a/third_party/WebKit/Source/core/dom/ElementData.h b/third_party/WebKit/Source/core/dom/ElementData.h index 0dbbf04..f31a094 100644 --- a/third_party/WebKit/Source/core/dom/ElementData.h +++ b/third_party/WebKit/Source/core/dom/ElementData.h
@@ -66,7 +66,7 @@ const AtomicString& idForStyleResolution() const { return m_idForStyleResolution; } void setIdForStyleResolution(const AtomicString& newId) const { m_idForStyleResolution = newId; } - const StylePropertySet* inlineStyle() const; + const StylePropertySet* inlineStyle() const { return m_inlineStyle.get(); } const StylePropertySet* presentationAttributeStyle() const; @@ -194,6 +194,13 @@ } #endif +inline const StylePropertySet* ElementData::presentationAttributeStyle() const +{ + if (!m_isUnique) + return 0; + return toUniqueElementData(this)->m_presentationAttributeStyle.get(); +} + inline AttributeCollection ElementData::attributes() const { if (isUnique())
diff --git a/third_party/WebKit/Source/core/dom/Node.cpp b/third_party/WebKit/Source/core/dom/Node.cpp index 833a280..adf0c2f 100644 --- a/third_party/WebKit/Source/core/dom/Node.cpp +++ b/third_party/WebKit/Source/core/dom/Node.cpp
@@ -1012,12 +1012,6 @@ return toElement(parent); } -void Node::setParentOrShadowHostNode(ContainerNode* parent) -{ - ASSERT(isMainThread()); - m_parentOrShadowHostNode = parent; -} - ContainerNode* Node::parentOrShadowHostOrTemplateHostNode() const { if (isDocumentFragment() && toDocumentFragment(this)->isTemplateContent())
diff --git a/third_party/WebKit/Source/core/dom/Node.h b/third_party/WebKit/Source/core/dom/Node.h index 5a83d1bc..e7ab471e 100644 --- a/third_party/WebKit/Source/core/dom/Node.h +++ b/third_party/WebKit/Source/core/dom/Node.h
@@ -833,6 +833,12 @@ } m_data; }; +inline void Node::setParentOrShadowHostNode(ContainerNode* parent) +{ + ASSERT(isMainThread()); + m_parentOrShadowHostNode = parent; +} + inline ContainerNode* Node::parentOrShadowHostNode() const { ASSERT(isMainThread());
diff --git a/third_party/WebKit/Source/core/dom/PendingScript.cpp b/third_party/WebKit/Source/core/dom/PendingScript.cpp index 17956db1..81cd667 100644 --- a/third_party/WebKit/Source/core/dom/PendingScript.cpp +++ b/third_party/WebKit/Source/core/dom/PendingScript.cpp
@@ -108,11 +108,6 @@ m_watchingForLoad = false; } -Element* PendingScript::element() const -{ - return m_element.get(); -} - void PendingScript::setElement(Element* element) { m_element = element;
diff --git a/third_party/WebKit/Source/core/dom/PendingScript.h b/third_party/WebKit/Source/core/dom/PendingScript.h index 32b2f7f..4f42d09 100644 --- a/third_party/WebKit/Source/core/dom/PendingScript.h +++ b/third_party/WebKit/Source/core/dom/PendingScript.h
@@ -67,7 +67,7 @@ void watchForLoad(ScriptResourceClient*); void stopWatchingForLoad(ScriptResourceClient*); - Element* element() const; + Element* element() const { return m_element.get(); } void setElement(Element*); PassRefPtrWillBeRawPtr<Element> releaseElementAndClear();
diff --git a/third_party/WebKit/Source/core/dom/ProcessingInstruction.cpp b/third_party/WebKit/Source/core/dom/ProcessingInstruction.cpp index 7536353f..d540c302 100644 --- a/third_party/WebKit/Source/core/dom/ProcessingInstruction.cpp +++ b/third_party/WebKit/Source/core/dom/ProcessingInstruction.cpp
@@ -103,11 +103,6 @@ return create(document(), m_target, m_data); } -StyleSheet* ProcessingInstruction::sheet() const -{ - return m_sheet.get(); -} - void ProcessingInstruction::didAttributeChanged() { if (m_sheet)
diff --git a/third_party/WebKit/Source/core/dom/ProcessingInstruction.h b/third_party/WebKit/Source/core/dom/ProcessingInstruction.h index aa68f616..2d97897 100644 --- a/third_party/WebKit/Source/core/dom/ProcessingInstruction.h +++ b/third_party/WebKit/Source/core/dom/ProcessingInstruction.h
@@ -45,7 +45,7 @@ void setCreatedByParser(bool createdByParser) { m_createdByParser = createdByParser; } const String& localHref() const { return m_localHref; } - StyleSheet* sheet() const; + StyleSheet* sheet() const { return m_sheet.get(); } bool isCSS() const { return m_isCSS; } bool isXSL() const { return m_isXSL; }
diff --git a/third_party/WebKit/Source/core/dom/ScriptRunnerTest.cpp b/third_party/WebKit/Source/core/dom/ScriptRunnerTest.cpp index b9668ec..09e5579 100644 --- a/third_party/WebKit/Source/core/dom/ScriptRunnerTest.cpp +++ b/third_party/WebKit/Source/core/dom/ScriptRunnerTest.cpp
@@ -10,6 +10,7 @@ #include "core/dom/ScriptLoader.h" #include "platform/heap/Handle.h" #include "platform/scheduler/CancellableTaskFactory.h" +#include "platform/testing/TestingPlatformSupport.h" #include "public/platform/Platform.h" #include "public/platform/WebViewScheduler.h" #include "testing/gmock/include/gmock/gmock.h" @@ -95,7 +96,7 @@ Deque<OwnPtr<WebTaskRunner::Task>>* m_tasks; // NOT OWNED }; -class MockPlatform : public Platform, public WebScheduler { +class MockPlatform : public TestingPlatformSupport, public WebScheduler { public: MockPlatform() : m_mockWebThread(this) @@ -103,17 +104,6 @@ { } - void cryptographicallyRandomValues(unsigned char* buffer, size_t length) override - { - RELEASE_ASSERT_NOT_REACHED(); - } - - const unsigned char* getTraceCategoryEnabledFlag(const char* categoryName) override - { - static const unsigned char tracingIsDisabled = 0; - return &tracingIsDisabled; - } - WebThread* currentThread() override { return &m_mockWebThread; } void runSingleTask() @@ -163,16 +153,14 @@ class ScriptRunnerTest : public testing::Test { public: + ScriptRunnerTest() + : m_document(Document::create()) + , m_element(m_document->createElement("foo", ASSERT_NO_EXCEPTION)) + { + } + void SetUp() override { - m_document = Document::create(); - m_element = m_document->createElement("foo", ASSERT_NO_EXCEPTION); - - m_oldPlatform = Platform::current(); - - // Force Platform::initialize to create a new one pointing at MockPlatform. - Platform::initialize(&m_platform); - // We have to create ScriptRunner after initializing platform, because we need // Platform::current()->currentThread()->scheduler()->loadingTaskRunner() // to be initialized before creating ScriptRunner to save it in constructor. @@ -182,15 +170,13 @@ void TearDown() override { m_scriptRunner.release(); - Platform::initialize(m_oldPlatform); } RefPtrWillBePersistent<Document> m_document; RefPtrWillBePersistent<Element> m_element; + MockPlatform m_platform; OwnPtrWillBePersistent<ScriptRunner> m_scriptRunner; WTF::Vector<int> m_order; - MockPlatform m_platform; - Platform* m_oldPlatform; // NOT OWNED }; TEST_F(ScriptRunnerTest, QueueSingleScript_Async)
diff --git a/third_party/WebKit/Source/core/dom/SecurityContext.cpp b/third_party/WebKit/Source/core/dom/SecurityContext.cpp index 0938ac1..764ecf9 100644 --- a/third_party/WebKit/Source/core/dom/SecurityContext.cpp +++ b/third_party/WebKit/Source/core/dom/SecurityContext.cpp
@@ -60,11 +60,6 @@ m_contentSecurityPolicy = contentSecurityPolicy; } -ContentSecurityPolicy* SecurityContext::contentSecurityPolicy() const -{ - return m_contentSecurityPolicy.get(); -} - bool SecurityContext::isSecureTransitionTo(const KURL& url) const { // If we haven't initialized our security origin by now, this is probably
diff --git a/third_party/WebKit/Source/core/dom/SecurityContext.h b/third_party/WebKit/Source/core/dom/SecurityContext.h index 7ffb18cc..035ecaf 100644 --- a/third_party/WebKit/Source/core/dom/SecurityContext.h +++ b/third_party/WebKit/Source/core/dom/SecurityContext.h
@@ -57,7 +57,7 @@ }; SecurityOrigin* securityOrigin() const { return m_securityOrigin.get(); } - ContentSecurityPolicy* contentSecurityPolicy() const; + ContentSecurityPolicy* contentSecurityPolicy() const { return m_contentSecurityPolicy.get(); } bool isSecureTransitionTo(const KURL&) const;
diff --git a/third_party/WebKit/Source/core/dom/StyleEngine.cpp b/third_party/WebKit/Source/core/dom/StyleEngine.cpp index 0855b46..4fde5b99 100644 --- a/third_party/WebKit/Source/core/dom/StyleEngine.cpp +++ b/third_party/WebKit/Source/core/dom/StyleEngine.cpp
@@ -613,11 +613,6 @@ document().setNeedsStyleRecalc(SubtreeStyleChange, StyleChangeReasonForTracing::create(StyleChangeReason::Fonts)); } -CSSFontSelector* StyleEngine::fontSelector() const -{ - return m_fontSelector.get(); -} - void StyleEngine::setFontSelector(PassRefPtrWillBeRawPtr<CSSFontSelector> fontSelector) { #if !ENABLE(OILPAN)
diff --git a/third_party/WebKit/Source/core/dom/StyleEngine.h b/third_party/WebKit/Source/core/dom/StyleEngine.h index eb3da78..d801886 100644 --- a/third_party/WebKit/Source/core/dom/StyleEngine.h +++ b/third_party/WebKit/Source/core/dom/StyleEngine.h
@@ -151,7 +151,7 @@ StyleInvalidator& styleInvalidator() { return m_styleInvalidator; } - CSSFontSelector* fontSelector() const; + CSSFontSelector* fontSelector() { return m_fontSelector.get(); } void setFontSelector(PassRefPtrWillBeRawPtr<CSSFontSelector>); void removeFontFaceRules(const WillBeHeapVector<RawPtrWillBeMember<const StyleRuleFontFace>>&);
diff --git a/third_party/WebKit/Source/core/dom/TreeScope.cpp b/third_party/WebKit/Source/core/dom/TreeScope.cpp index 921c286..fe8f2ff 100644 --- a/third_party/WebKit/Source/core/dom/TreeScope.cpp +++ b/third_party/WebKit/Source/core/dom/TreeScope.cpp
@@ -132,11 +132,6 @@ } #endif -void TreeScope::setDocument(Document& document) -{ - m_document = &document; -} - void TreeScope::setParentTreeScope(TreeScope& newParentScope) { // A document node cannot be re-parented. @@ -151,11 +146,6 @@ setDocument(newParentScope.document()); } -ScopedStyleResolver* TreeScope::scopedStyleResolver() const -{ - return m_scopedStyleResolver.get(); -} - ScopedStyleResolver& TreeScope::ensureScopedStyleResolver() { RELEASE_ASSERT(this); @@ -204,12 +194,6 @@ m_idTargetObserverRegistry->notifyObservers(elementId); } -Document& TreeScope::document() const -{ - ASSERT(m_document); - return *m_document; -} - Node* TreeScope::ancestorInThisScope(Node* node) const { while (node) { @@ -435,11 +419,6 @@ adopter.execute(); } -IdTargetObserverRegistry& TreeScope::idTargetObserverRegistry() const -{ - return *m_idTargetObserverRegistry.get(); -} - Element* TreeScope::adjustedFocusedElement() const { Document& document = rootNode().document();
diff --git a/third_party/WebKit/Source/core/dom/TreeScope.h b/third_party/WebKit/Source/core/dom/TreeScope.h index 663e46d..88a3a756 100644 --- a/third_party/WebKit/Source/core/dom/TreeScope.h +++ b/third_party/WebKit/Source/core/dom/TreeScope.h
@@ -64,7 +64,11 @@ void addElementById(const AtomicString& elementId, Element*); void removeElementById(const AtomicString& elementId, Element*); - Document& document() const; + Document& document() const + { + ASSERT(m_document); + return *m_document; + } Node* ancestorInThisScope(Node*) const; @@ -97,7 +101,7 @@ ContainerNode& rootNode() const { return *m_rootNode; } - IdTargetObserverRegistry& idTargetObserverRegistry() const; + IdTargetObserverRegistry& idTargetObserverRegistry() const { return *m_idTargetObserverRegistry.get(); } #if !ENABLE(OILPAN) // Nodes belonging to this scope hold guard references - @@ -135,7 +139,7 @@ DECLARE_VIRTUAL_TRACE(); - ScopedStyleResolver* scopedStyleResolver() const; + ScopedStyleResolver* scopedStyleResolver() const { return m_scopedStyleResolver.get(); } ScopedStyleResolver& ensureScopedStyleResolver(); void clearScopedStyleResolver(); @@ -148,7 +152,7 @@ void destroyTreeScopeData(); #endif - void setDocument(Document&); + void setDocument(Document& document) { m_document = &document; } void setParentTreeScope(TreeScope&); #if !ENABLE(OILPAN)
diff --git a/third_party/WebKit/Source/core/editing/Editor.cpp b/third_party/WebKit/Source/core/editing/Editor.cpp index 67642683..efec60f7 100644 --- a/third_party/WebKit/Source/core/editing/Editor.cpp +++ b/third_party/WebKit/Source/core/editing/Editor.cpp
@@ -146,11 +146,6 @@ return emptyEditorClient(); } -CompositeEditCommand* Editor::lastEditCommand() const -{ - return m_lastEditCommand.get(); -} - UndoStack* Editor::undoStack() const { if (Page* page = frame().page())
diff --git a/third_party/WebKit/Source/core/editing/Editor.h b/third_party/WebKit/Source/core/editing/Editor.h index 93da9668..dc631f1 100644 --- a/third_party/WebKit/Source/core/editing/Editor.h +++ b/third_party/WebKit/Source/core/editing/Editor.h
@@ -68,7 +68,7 @@ EditorClient& client() const; - CompositeEditCommand* lastEditCommand() const; + CompositeEditCommand* lastEditCommand() { return m_lastEditCommand.get(); } void handleKeyboardEvent(KeyboardEvent*); bool handleTextEvent(TextEvent*);
diff --git a/third_party/WebKit/Source/core/events/PopStateEvent.cpp b/third_party/WebKit/Source/core/events/PopStateEvent.cpp index b1155cd7..50075b6 100644 --- a/third_party/WebKit/Source/core/events/PopStateEvent.cpp +++ b/third_party/WebKit/Source/core/events/PopStateEvent.cpp
@@ -73,11 +73,6 @@ return adoptRefWillBeNoop(new PopStateEvent(type, initializer)); } -History* PopStateEvent::history() const -{ - return m_history.get(); -} - const AtomicString& PopStateEvent::interfaceName() const { return EventNames::PopStateEvent;
diff --git a/third_party/WebKit/Source/core/events/PopStateEvent.h b/third_party/WebKit/Source/core/events/PopStateEvent.h index 9c276ec..4316bfb 100644 --- a/third_party/WebKit/Source/core/events/PopStateEvent.h +++ b/third_party/WebKit/Source/core/events/PopStateEvent.h
@@ -51,7 +51,7 @@ ASSERT(!m_serializedState); m_serializedState = state; } - History* history() const; + History* history() const { return m_history.get(); } const AtomicString& interfaceName() const override;
diff --git a/third_party/WebKit/Source/core/events/TextEvent.cpp b/third_party/WebKit/Source/core/events/TextEvent.cpp index 38ae55e..ce2cfe15 100644 --- a/third_party/WebKit/Source/core/events/TextEvent.cpp +++ b/third_party/WebKit/Source/core/events/TextEvent.cpp
@@ -103,11 +103,6 @@ return EventNames::TextEvent; } -DocumentFragment* TextEvent::pastingFragment() const -{ - return m_pastingFragment.get(); -} - DEFINE_TRACE(TextEvent) { visitor->trace(m_pastingFragment);
diff --git a/third_party/WebKit/Source/core/events/TextEvent.h b/third_party/WebKit/Source/core/events/TextEvent.h index 4a1ce29..8b37094 100644 --- a/third_party/WebKit/Source/core/events/TextEvent.h +++ b/third_party/WebKit/Source/core/events/TextEvent.h
@@ -58,7 +58,7 @@ bool shouldSmartReplace() const { return m_shouldSmartReplace; } bool shouldMatchStyle() const { return m_shouldMatchStyle; } - DocumentFragment* pastingFragment() const; + DocumentFragment* pastingFragment() const { return m_pastingFragment.get(); } DECLARE_VIRTUAL_TRACE();
diff --git a/third_party/WebKit/Source/core/events/TreeScopeEventContext.cpp b/third_party/WebKit/Source/core/events/TreeScopeEventContext.cpp index f68958e6..ee5a34f6 100644 --- a/third_party/WebKit/Source/core/events/TreeScopeEventContext.cpp +++ b/third_party/WebKit/Source/core/events/TreeScopeEventContext.cpp
@@ -75,11 +75,6 @@ return *m_eventPath; } -TouchEventContext* TreeScopeEventContext::touchEventContext() const -{ - return m_touchEventContext.get(); -} - TouchEventContext* TreeScopeEventContext::ensureTouchEventContext() { if (!m_touchEventContext)
diff --git a/third_party/WebKit/Source/core/events/TreeScopeEventContext.h b/third_party/WebKit/Source/core/events/TreeScopeEventContext.h index 244735a6..3487d012 100644 --- a/third_party/WebKit/Source/core/events/TreeScopeEventContext.h +++ b/third_party/WebKit/Source/core/events/TreeScopeEventContext.h
@@ -60,7 +60,7 @@ EventTarget* relatedTarget() const { return m_relatedTarget.get(); } void setRelatedTarget(PassRefPtrWillBeRawPtr<EventTarget>); - TouchEventContext* touchEventContext() const; + TouchEventContext* touchEventContext() const { return m_touchEventContext.get(); } TouchEventContext* ensureTouchEventContext(); WillBeHeapVector<RefPtrWillBeMember<EventTarget>>& ensureEventPath(EventPath&);
diff --git a/third_party/WebKit/Source/core/fetch/CachingCorrectnessTest.cpp b/third_party/WebKit/Source/core/fetch/CachingCorrectnessTest.cpp index 99066f6..ac0c261 100644 --- a/third_party/WebKit/Source/core/fetch/CachingCorrectnessTest.cpp +++ b/third_party/WebKit/Source/core/fetch/CachingCorrectnessTest.cpp
@@ -38,6 +38,7 @@ #include "core/fetch/ResourceFetcher.h" #include "core/fetch/ResourcePtr.h" #include "platform/network/ResourceRequest.h" +#include "platform/testing/TestingPlatformSupport.h" #include "public/platform/Platform.h" #include "testing/gtest/include/gtest/gtest.h" #include "wtf/OwnPtr.h" @@ -55,8 +56,6 @@ const char kOneDayBeforeOriginalRequest[] = "Wed, 24 May 1977 18:30:00 GMT"; const char kOneDayAfterOriginalRequest[] = "Fri, 26 May 1977 18:30:00 GMT"; -const unsigned char kAConstUnsignedCharZero = 0; - class MockFetchContext : public FetchContext { public: static MockFetchContext* create() @@ -120,25 +119,15 @@ private: // A simple platform that mocks out the clock, for cache freshness testing. - class ProxyPlatform : public blink::Platform { + class ProxyPlatform : public TestingPlatformSupport { public: - ProxyPlatform() : m_platform(blink::Platform::current()), m_elapsedSeconds(0.) { } - - ~ProxyPlatform() - { - blink::Platform::initialize(m_platform); - } + ProxyPlatform() : m_elapsedSeconds(0.) { } void advanceClock(double seconds) { m_elapsedSeconds += seconds; } - WebThread* currentThread() override - { - return m_platform->currentThread(); - } - private: // From blink::Platform: double currentTimeSeconds() override @@ -146,24 +135,11 @@ return kOriginalRequestDateAsDouble + m_elapsedSeconds; } - // These blink::Platform methods must be overriden to make a usable object. - virtual void cryptographicallyRandomValues(unsigned char* buffer, size_t length) - { - RELEASE_ASSERT_NOT_REACHED(); - } - virtual const unsigned char* getTraceCategoryEnabledFlag(const char* categoryName) - { - return &kAConstUnsignedCharZero; - } - - blink::Platform* m_platform; // Not owned. double m_elapsedSeconds; }; virtual void SetUp() { - blink::Platform::initialize(&m_proxyPlatform); - // Save the global memory cache to restore it upon teardown. m_globalMemoryCache = replaceMemoryCacheForTesting(MemoryCache::create());
diff --git a/third_party/WebKit/Source/core/fetch/DocumentResource.cpp b/third_party/WebKit/Source/core/fetch/DocumentResource.cpp index 505e4ec7..a73798c9 100644 --- a/third_party/WebKit/Source/core/fetch/DocumentResource.cpp +++ b/third_party/WebKit/Source/core/fetch/DocumentResource.cpp
@@ -57,11 +57,6 @@ Resource::trace(visitor); } -Document* DocumentResource::document() const -{ - return m_document.get(); -} - void DocumentResource::setEncoding(const String& chs) { m_decoder->setEncoding(chs, TextResourceDecoder::EncodingFromHTTPHeader);
diff --git a/third_party/WebKit/Source/core/fetch/DocumentResource.h b/third_party/WebKit/Source/core/fetch/DocumentResource.h index 7bfbdfb6..bdfc19a 100644 --- a/third_party/WebKit/Source/core/fetch/DocumentResource.h +++ b/third_party/WebKit/Source/core/fetch/DocumentResource.h
@@ -42,7 +42,7 @@ ~DocumentResource() override; DECLARE_VIRTUAL_TRACE(); - Document* document() const; + Document* document() const { return m_document.get(); } void setEncoding(const String&) override; String encoding() const override;
diff --git a/third_party/WebKit/Source/core/fetch/Resource.h b/third_party/WebKit/Source/core/fetch/Resource.h index 2f7ff13..9377f52 100644 --- a/third_party/WebKit/Source/core/fetch/Resource.h +++ b/third_party/WebKit/Source/core/fetch/Resource.h
@@ -25,7 +25,6 @@ #include "core/CoreExport.h" #include "core/fetch/CachedMetadataHandler.h" -#include "core/fetch/ResourceLoader.h" #include "core/fetch/ResourceLoaderOptions.h" #include "platform/Timer.h" #include "platform/network/ResourceError.h" @@ -54,6 +53,7 @@ class ResourceFetcher; class ResourceTimingInfo; class InspectorResource; +class ResourceLoader; class SecurityOrigin; class SharedBuffer;
diff --git a/third_party/WebKit/Source/core/fetch/ResourceFetcher.h b/third_party/WebKit/Source/core/fetch/ResourceFetcher.h index f703ed9..f74b5eb 100644 --- a/third_party/WebKit/Source/core/fetch/ResourceFetcher.h +++ b/third_party/WebKit/Source/core/fetch/ResourceFetcher.h
@@ -36,7 +36,6 @@ #include "core/fetch/ResourcePtr.h" #include "core/fetch/SubstituteData.h" #include "platform/Timer.h" -#include "platform/mhtml/ArchiveResourceCollection.h" #include "platform/network/ResourceError.h" #include "platform/network/ResourceLoadPriority.h" #include "wtf/HashMap.h"
diff --git a/third_party/WebKit/Source/core/fetch/ResourceLoaderOptionsTest.cpp b/third_party/WebKit/Source/core/fetch/ResourceLoaderOptionsTest.cpp index c166ffe0f..1780d2c9 100644 --- a/third_party/WebKit/Source/core/fetch/ResourceLoaderOptionsTest.cpp +++ b/third_party/WebKit/Source/core/fetch/ResourceLoaderOptionsTest.cpp
@@ -6,7 +6,7 @@ #include "core/fetch/ResourceLoaderOptions.h" #include "testing/gtest/include/gtest/gtest.h" -#include "wtf/TypeTraits.h" +#include <type_traits> namespace blink { @@ -16,13 +16,13 @@ { // Check that the fields of ResourceLoaderOptions are enums, // except for initiatorInfo and securityOrigin. - static_assert(WTF::IsEnum<DataBufferingPolicy>::value, "DataBufferingPolicy should be an enum"); - static_assert(WTF::IsEnum<StoredCredentials>::value, "StoredCredentials should be an enum"); - static_assert(WTF::IsEnum<CredentialRequest>::value, "CredentialRequest should be an enum"); - static_assert(WTF::IsEnum<ContentSecurityPolicyDisposition>::value, "ContentSecurityPolicyDisposition should be an enum"); - static_assert(WTF::IsEnum<RequestInitiatorContext>::value, "RequestInitiatorContext should be an enum"); - static_assert(WTF::IsEnum<SynchronousPolicy>::value, "SynchronousPolicy should be an enum"); - static_assert(WTF::IsEnum<CORSEnabled>::value, "CORSEnabled should be an enum"); + static_assert(std::is_enum<DataBufferingPolicy>::value, "DataBufferingPolicy should be an enum"); + static_assert(std::is_enum<StoredCredentials>::value, "StoredCredentials should be an enum"); + static_assert(std::is_enum<CredentialRequest>::value, "CredentialRequest should be an enum"); + static_assert(std::is_enum<ContentSecurityPolicyDisposition>::value, "ContentSecurityPolicyDisposition should be an enum"); + static_assert(std::is_enum<RequestInitiatorContext>::value, "RequestInitiatorContext should be an enum"); + static_assert(std::is_enum<SynchronousPolicy>::value, "SynchronousPolicy should be an enum"); + static_assert(std::is_enum<CORSEnabled>::value, "CORSEnabled should be an enum"); ResourceLoaderOptions original; RefPtr<SecurityOrigin> securityOrigin = SecurityOrigin::createFromString("http://www.google.com");
diff --git a/third_party/WebKit/Source/core/fetch/ResourceTest.cpp b/third_party/WebKit/Source/core/fetch/ResourceTest.cpp index 143d942f..3a100eff 100644 --- a/third_party/WebKit/Source/core/fetch/ResourceTest.cpp +++ b/third_party/WebKit/Source/core/fetch/ResourceTest.cpp
@@ -8,6 +8,7 @@ #include "core/fetch/ResourcePtr.h" #include "platform/network/ResourceRequest.h" #include "platform/network/ResourceResponse.h" +#include "platform/testing/TestingPlatformSupport.h" #include "platform/testing/URLTestHelpers.h" #include "public/platform/Platform.h" #include "testing/gtest/include/gtest/gtest.h" @@ -17,9 +18,9 @@ namespace { -class MockPlatform final : public Platform { +class MockPlatform final : public TestingPlatformSupport { public: - MockPlatform() : m_oldPlatform(Platform::current()) { } + MockPlatform() { } ~MockPlatform() override { } // From blink::Platform: @@ -33,45 +34,10 @@ return m_cachedURLs; } - WebThread* currentThread() override - { - return m_oldPlatform->currentThread(); - } - - // These blink::Platform methods must be overriden to make a usable object. - void cryptographicallyRandomValues(unsigned char* buffer, size_t length) override - { - ASSERT_NOT_REACHED(); - } - - const unsigned char* getTraceCategoryEnabledFlag(const char* categoryName) override - { - static const unsigned char tracingIsDisabled = 0; - return &tracingIsDisabled; - } - private: - Platform* m_oldPlatform; // Not owned. Vector<WebURL> m_cachedURLs; }; -class AutoInstallMockPlatform { -public: - AutoInstallMockPlatform() - { - m_oldPlatform = Platform::current(); - Platform::initialize(&m_mockPlatform); - } - ~AutoInstallMockPlatform() - { - Platform::initialize(m_oldPlatform); - } - MockPlatform* platform() { return &m_mockPlatform; } -private: - MockPlatform m_mockPlatform; - Platform* m_oldPlatform; -}; - PassOwnPtr<ResourceResponse> createTestResourceResponse() { OwnPtr<ResourceResponse> response = adoptPtr(new ResourceResponse); @@ -93,19 +59,19 @@ TEST(ResourceTest, SetCachedMetadata_SendsMetadataToPlatform) { - AutoInstallMockPlatform mock; + MockPlatform mock; OwnPtr<ResourceResponse> response(createTestResourceResponse()); createTestResourceAndSetCachedMetadata(response.get()); - EXPECT_EQ(1u, mock.platform()->cachedURLs().size()); + EXPECT_EQ(1u, mock.cachedURLs().size()); } TEST(ResourceTest, SetCachedMetadata_DoesNotSendMetadataToPlatformWhenFetchedViaServiceWorker) { - AutoInstallMockPlatform mock; + MockPlatform mock; OwnPtr<ResourceResponse> response(createTestResourceResponse()); response->setWasFetchedViaServiceWorker(true); createTestResourceAndSetCachedMetadata(response.get()); - EXPECT_EQ(0u, mock.platform()->cachedURLs().size()); + EXPECT_EQ(0u, mock.cachedURLs().size()); } } // namespace blink
diff --git a/third_party/WebKit/Source/core/frame/Frame.h b/third_party/WebKit/Source/core/frame/Frame.h index 141bb16..24909d3d 100644 --- a/third_party/WebKit/Source/core/frame/Frame.h +++ b/third_party/WebKit/Source/core/frame/Frame.h
@@ -29,7 +29,6 @@ #define Frame_h #include "core/CoreExport.h" -#include "core/frame/FrameOwner.h" #include "core/frame/FrameTypes.h" #include "core/loader/FrameLoaderTypes.h" #include "core/page/FrameTree.h" @@ -45,6 +44,7 @@ class Document; class FrameClient; class FrameHost; +class FrameOwner; class HTMLFrameOwnerElement; class LayoutPart; class KURL;
diff --git a/third_party/WebKit/Source/core/frame/FrameView.cpp b/third_party/WebKit/Source/core/frame/FrameView.cpp index 0c4d9697..d6cf526 100644 --- a/third_party/WebKit/Source/core/frame/FrameView.cpp +++ b/third_party/WebKit/Source/core/frame/FrameView.cpp
@@ -2333,11 +2333,6 @@ m_nodeToDraw = node; } -Node* FrameView::nodeToDraw() const -{ - return m_nodeToDraw.get(); -} - void FrameView::updateWidgetPositionsIfNeeded() { if (!m_needsUpdateWidgetPositions)
diff --git a/third_party/WebKit/Source/core/frame/FrameView.h b/third_party/WebKit/Source/core/frame/FrameView.h index a8fefd7..febffe1f 100644 --- a/third_party/WebKit/Source/core/frame/FrameView.h +++ b/third_party/WebKit/Source/core/frame/FrameView.h
@@ -222,7 +222,7 @@ bool isPainting() const; void setNodeToDraw(Node*); - Node* nodeToDraw() const; + Node* nodeToDraw() const { return m_nodeToDraw.get(); } Color documentBackgroundColor() const;
diff --git a/third_party/WebKit/Source/core/frame/ImageBitmap.cpp b/third_party/WebKit/Source/core/frame/ImageBitmap.cpp index 60f71c7..137ab66 100644 --- a/third_party/WebKit/Source/core/frame/ImageBitmap.cpp +++ b/third_party/WebKit/Source/core/frame/ImageBitmap.cpp
@@ -8,12 +8,6 @@ #include "core/html/HTMLCanvasElement.h" #include "core/html/HTMLVideoElement.h" #include "core/html/ImageData.h" -#include "platform/graphics/GraphicsContext.h" -#include "platform/graphics/ImageBuffer.h" -#include "platform/graphics/StaticBitmapImage.h" -#include "platform/graphics/paint/DrawingRecorder.h" -#include "platform/graphics/paint/SkPictureBuilder.h" -#include "third_party/skia/include/core/SkScalar.h" #include "third_party/skia/include/core/SkSurface.h" #include "wtf/RefPtr.h" @@ -27,9 +21,34 @@ std::max(rect.height(), -rect.height())); } +static PassRefPtr<StaticBitmapImage> cropImage(StaticBitmapImage* image, const IntRect& cropRect) +{ + ASSERT(image); + + IntRect imgRect(IntPoint(), IntSize(image->width(), image->height())); + const IntRect srcRect = intersection(imgRect, cropRect); + + if (cropRect == srcRect) + return StaticBitmapImage::create(adoptRef(image->imageForCurrentFrame()->newSubset(srcRect))); + + RefPtr<SkSurface> surface = adoptRef(SkSurface::NewRasterN32Premul(cropRect.width(), cropRect.height())); + + if (srcRect.isEmpty()) + return StaticBitmapImage::create(adoptRef(surface->newImageSnapshot())); + + SkScalar dstLeft = std::min(0, -cropRect.x()); + SkScalar dstTop = std::min(0, -cropRect.y()); + if (cropRect.x() < 0) + dstLeft = -cropRect.x(); + if (cropRect.y() < 0) + dstTop = -cropRect.y(); + surface->getCanvas()->drawImage(image->imageForCurrentFrame().get(), dstLeft, dstTop); + return StaticBitmapImage::create(adoptRef(surface->newImageSnapshot())); +} + ImageBitmap::ImageBitmap(HTMLImageElement* image, const IntRect& cropRect) { - m_image = cropImage(image->cachedImage()->image()->imageForCurrentFrame(), cropRect); + m_image = cropImage(static_cast<StaticBitmapImage*>(image->cachedImage()->image()), cropRect); } ImageBitmap::ImageBitmap(HTMLVideoElement* video, const IntRect& cropRect) @@ -46,13 +65,13 @@ IntPoint dstPoint = IntPoint(std::max(0, -cropRect.x()), std::max(0, -cropRect.y())); video->paintCurrentFrame(buffer->canvas(), IntRect(dstPoint, srcRect.size()), nullptr); - m_image = buffer->newSkImageSnapshot(PreferNoAcceleration); + m_image = StaticBitmapImage::create(buffer->newSkImageSnapshot(PreferNoAcceleration)); } ImageBitmap::ImageBitmap(HTMLCanvasElement* canvas, const IntRect& cropRect) { ASSERT(canvas->isPaintable()); - m_image = cropImage(canvas->copiedImage(BackBuffer, PreferAcceleration)->imageForCurrentFrame(), cropRect); + m_image = cropImage(static_cast<StaticBitmapImage*>(canvas->copiedImage(BackBuffer, PreferAcceleration).get()), cropRect); } ImageBitmap::ImageBitmap(ImageData* data, const IntRect& cropRect) @@ -64,7 +83,7 @@ return; if (srcRect.isEmpty()) { - m_image = buffer->newSkImageSnapshot(PreferNoAcceleration); + m_image = StaticBitmapImage::create(buffer->newSkImageSnapshot(PreferNoAcceleration)); return; } @@ -74,17 +93,17 @@ if (cropRect.y() < 0) dstPoint.setY(-cropRect.y()); buffer->putByteArray(Unmultiplied, data->data()->data(), data->size(), srcRect, dstPoint); - m_image = buffer->newSkImageSnapshot(PreferNoAcceleration); + m_image = StaticBitmapImage::create(buffer->newSkImageSnapshot(PreferNoAcceleration)); } ImageBitmap::ImageBitmap(ImageBitmap* bitmap, const IntRect& cropRect) { - m_image = cropImage(bitmap->skImage(), cropRect); + m_image = cropImage(bitmap->bitmapImage(), cropRect); } ImageBitmap::ImageBitmap(Image* image, const IntRect& cropRect) { - m_image = cropImage(image->imageForCurrentFrame(), cropRect); + m_image = cropImage(static_cast<StaticBitmapImage*>(image), cropRect); } ImageBitmap::~ImageBitmap() @@ -127,31 +146,6 @@ return adoptRefWillBeNoop(new ImageBitmap(image, normalizedCropRect)); } -PassRefPtr<SkImage> ImageBitmap::cropImage(PassRefPtr<SkImage> image, const IntRect& cropRect) -{ - ASSERT(image); - - IntRect imgRect = IntRect(IntPoint(), IntSize(image->width(), image->height())); - const IntRect srcRect = intersection(imgRect, cropRect); - - if (cropRect == srcRect) - return adoptRef(image->newSubset(srcRect)); - - RefPtr<SkSurface> surface = adoptRef(SkSurface::NewRasterN32Premul(cropRect.width(), cropRect.height())); - - if (srcRect.isEmpty()) - return adoptRef(surface->newImageSnapshot()); - - SkScalar dstLeft = std::min(0, -cropRect.x()); - SkScalar dstTop = std::min(0, -cropRect.y()); - if (cropRect.x() < 0) - dstLeft = -cropRect.x(); - if (cropRect.y() < 0) - dstTop = -cropRect.y(); - surface->getCanvas()->drawImage(image.get(), dstLeft, dstTop); - return adoptRef(surface->newImageSnapshot()); -} - unsigned long ImageBitmap::width() const { if (!m_image) @@ -183,12 +177,11 @@ PassRefPtr<Image> ImageBitmap::getSourceImageForCanvas(SourceImageStatus* status, AccelerationHint) const { *status = NormalSourceImageStatus; - return m_image ? StaticBitmapImage::create(m_image) : nullptr; + return m_image ? m_image : nullptr; } void ImageBitmap::adjustDrawRects(FloatRect* srcRect, FloatRect* dstRect) const { - } FloatSize ImageBitmap::elementSize() const
diff --git a/third_party/WebKit/Source/core/frame/ImageBitmap.h b/third_party/WebKit/Source/core/frame/ImageBitmap.h index 41f6ec4..ed4e543f 100644 --- a/third_party/WebKit/Source/core/frame/ImageBitmap.h +++ b/third_party/WebKit/Source/core/frame/ImageBitmap.h
@@ -12,8 +12,8 @@ #include "platform/geometry/IntRect.h" #include "platform/graphics/Image.h" #include "platform/graphics/ImageBuffer.h" +#include "platform/graphics/StaticBitmapImage.h" #include "platform/heap/Handle.h" -#include "third_party/skia/include/core/SkImage.h" #include "wtf/PassRefPtr.h" #include "wtf/RefCounted.h" @@ -34,7 +34,7 @@ static PassRefPtrWillBeRawPtr<ImageBitmap> create(ImageBitmap*, const IntRect&); static PassRefPtrWillBeRawPtr<ImageBitmap> create(Image*, const IntRect&); - SkImage* skImage() const { return (m_image) ? m_image.get() : nullptr; } + StaticBitmapImage* bitmapImage() const { return (m_image) ? m_image.get() : nullptr; } unsigned long width() const; unsigned long height() const; IntSize size() const; @@ -57,13 +57,11 @@ ImageBitmap(ImageBitmap*, const IntRect&); ImageBitmap(Image*, const IntRect&); - PassRefPtr<SkImage> cropImage(PassRefPtr<SkImage>, const IntRect&); - // ImageLoaderClient void notifyImageSourceChanged() override; bool requestsHighLiveResourceCachePriority() override { return true; } - RefPtr<SkImage> m_image; + RefPtr<StaticBitmapImage> m_image; }; } // namespace blink
diff --git a/third_party/WebKit/Source/core/frame/ImageBitmapTest.cpp b/third_party/WebKit/Source/core/frame/ImageBitmapTest.cpp index 64a96d1..0f8e49a 100644 --- a/third_party/WebKit/Source/core/frame/ImageBitmapTest.cpp +++ b/third_party/WebKit/Source/core/frame/ImageBitmapTest.cpp
@@ -94,14 +94,12 @@ RefPtrWillBeRawPtr<ImageBitmap> imageBitmapOutsideCrop = ImageBitmap::create(imageElement.get(), IntRect(-m_image->width(), -m_image->height(), m_image->width(), m_image->height())); - // Now that we use SkImage::newSubset() to crop the image, the ImageBitmap::skImage() is not necessary the same - // as the source imageElement. See SkImage::newSubset() for details. - ASSERT_EQ(imageBitmapNoCrop->skImage(), imageElement->cachedImage()->image()->imageForCurrentFrame().get()); - ASSERT_NE(imageBitmapInteriorCrop->skImage(), imageElement->cachedImage()->image()->imageForCurrentFrame().get()); - ASSERT_NE(imageBitmapExteriorCrop->skImage(), imageElement->cachedImage()->image()->imageForCurrentFrame().get()); + ASSERT_EQ(imageBitmapNoCrop->bitmapImage()->imageForCurrentFrame(), imageElement->cachedImage()->image()->imageForCurrentFrame()); + ASSERT_NE(imageBitmapInteriorCrop->bitmapImage()->imageForCurrentFrame(), imageElement->cachedImage()->image()->imageForCurrentFrame()); + ASSERT_NE(imageBitmapExteriorCrop->bitmapImage()->imageForCurrentFrame(), imageElement->cachedImage()->image()->imageForCurrentFrame()); - SkImage* emptyImage = imageBitmapOutsideCrop->skImage(); - ASSERT_NE(emptyImage, imageElement->cachedImage()->image()->imageForCurrentFrame()); + StaticBitmapImage* emptyImage = imageBitmapOutsideCrop->bitmapImage(); + ASSERT_NE(emptyImage->imageForCurrentFrame(), imageElement->cachedImage()->image()->imageForCurrentFrame()); } // Verifies that HTMLImageElements are given an elevated CacheLiveResourcePriority when used to construct an ImageBitmap. @@ -191,7 +189,7 @@ RefPtrWillBeRawPtr<ImageBitmap> imageBitmap = ImageBitmap::create(image.get(), IntRect(0, 0, m_image->width(), m_image->height())); - ASSERT_EQ(imageBitmap->skImage(), originalImageResource->image()->imageForCurrentFrame().get()); + ASSERT_EQ(imageBitmap->bitmapImage()->imageForCurrentFrame(), originalImageResource->image()->imageForCurrentFrame()); ResourcePtr<ImageResource> newImageResource = new ImageResource( StaticBitmapImage::create(m_image2).get()); @@ -199,8 +197,8 @@ // The ImageBitmap should contain the same data as the original cached image { - ASSERT_EQ(imageBitmap->skImage(), originalImageResource->image()->imageForCurrentFrame().get()); - SkImage* image1 = imageBitmap->skImage(); + ASSERT_EQ(imageBitmap->bitmapImage()->imageForCurrentFrame(), originalImageResource->image()->imageForCurrentFrame()); + SkImage* image1 = imageBitmap->bitmapImage()->imageForCurrentFrame().get(); ASSERT_NE(image1, nullptr); SkImage* image2 = originalImageResource->image()->imageForCurrentFrame().get(); ASSERT_NE(image2, nullptr); @@ -208,8 +206,8 @@ } { - ASSERT_NE(imageBitmap->skImage(), newImageResource->image()->imageForCurrentFrame().get()); - SkImage* image1 = imageBitmap->skImage(); + ASSERT_NE(imageBitmap->bitmapImage()->imageForCurrentFrame(), newImageResource->image()->imageForCurrentFrame()); + SkImage* image1 = imageBitmap->bitmapImage()->imageForCurrentFrame().get(); ASSERT_NE(image1, nullptr); SkImage* image2 = newImageResource->image()->imageForCurrentFrame().get(); ASSERT_NE(image2, nullptr);
diff --git a/third_party/WebKit/Source/core/frame/LocalDOMWindow.h b/third_party/WebKit/Source/core/frame/LocalDOMWindow.h index 9f1d839..318e84d0 100644 --- a/third_party/WebKit/Source/core/frame/LocalDOMWindow.h +++ b/third_party/WebKit/Source/core/frame/LocalDOMWindow.h
@@ -35,7 +35,6 @@ #include "core/frame/DOMWindowLifecycleObserver.h" #include "core/frame/LocalFrame.h" #include "core/frame/LocalFrameLifecycleObserver.h" -#include "core/loader/appcache/ApplicationCache.h" #include "platform/Supplementable.h" #include "platform/heap/Handle.h"
diff --git a/third_party/WebKit/Source/core/frame/LocalFrame.cpp b/third_party/WebKit/Source/core/frame/LocalFrame.cpp index 43b9d1d..455246e4 100644 --- a/third_party/WebKit/Source/core/frame/LocalFrame.cpp +++ b/third_party/WebKit/Source/core/frame/LocalFrame.cpp
@@ -440,16 +440,6 @@ m_pagePopupOwner = &owner; } -Element* LocalFrame::pagePopupOwner() const -{ - return m_pagePopupOwner.get(); -} - -LocalDOMWindow* LocalFrame::localDOMWindow() const -{ - return m_domWindow.get(); -} - LayoutView* LocalFrame::contentLayoutObject() const { return document() ? document()->layoutView() : nullptr;
diff --git a/third_party/WebKit/Source/core/frame/LocalFrame.h b/third_party/WebKit/Source/core/frame/LocalFrame.h index 8278062..6d72fb89 100644 --- a/third_party/WebKit/Source/core/frame/LocalFrame.h +++ b/third_party/WebKit/Source/core/frame/LocalFrame.h
@@ -31,12 +31,9 @@ #include "core/CoreExport.h" #include "core/dom/WeakIdentifierMap.h" #include "core/frame/Frame.h" -#include "core/frame/FrameView.h" #include "core/frame/LocalFrameLifecycleNotifier.h" #include "core/frame/LocalFrameLifecycleObserver.h" -#include "core/inspector/InstrumentingAgents.h" #include "core/loader/FrameLoader.h" -#include "core/loader/NavigationScheduler.h" #include "core/page/FrameTree.h" #include "core/paint/PaintPhase.h" #include "platform/Supplementable.h" @@ -59,11 +56,14 @@ class FloatSize; class FrameConsole; class FrameSelection; +class FrameView; class HTMLPlugInElement; class InputMethodController; class IntPoint; class IntSize; +class InstrumentingAgents; class LocalDOMWindow; +class NavigationScheduler; class Node; class NodeTraversal; class Range; @@ -110,7 +110,7 @@ FrameView* view() const; Document* document() const; void setPagePopupOwner(Element&); - Element* pagePopupOwner() const; + Element* pagePopupOwner() const { return m_pagePopupOwner.get(); } LayoutView* contentLayoutObject() const; // Root of the layout tree for the document contained in this frame. @@ -262,6 +262,11 @@ m_loader.init(); } +inline LocalDOMWindow* LocalFrame::localDOMWindow() const +{ + return m_domWindow.get(); +} + inline FrameLoader& LocalFrame::loader() const { return m_loader; @@ -341,9 +346,4 @@ } // namespace blink -// During refactoring, there are some places where we need to do type conversions that -// will not be needed once all instances of LocalFrame and RemoteFrame are sorted out. -// At that time this #define will be removed and all the uses of it will need to be corrected. -#define toLocalFrameTemporary toLocalFrame - #endif // LocalFrame_h
diff --git a/third_party/WebKit/Source/core/frame/Location.cpp b/third_party/WebKit/Source/core/frame/Location.cpp index df159f0..e0922ef 100644 --- a/third_party/WebKit/Source/core/frame/Location.cpp +++ b/third_party/WebKit/Source/core/frame/Location.cpp
@@ -52,16 +52,6 @@ visitor->trace(m_frame); } -Frame* Location::frame() const -{ - return m_frame.get(); -} - -void Location::reset() -{ - m_frame = nullptr; -} - inline const KURL& Location::url() const { const KURL& url = toLocalFrame(m_frame)->document()->url();
diff --git a/third_party/WebKit/Source/core/frame/Location.h b/third_party/WebKit/Source/core/frame/Location.h index 7099031..6c6b79c 100644 --- a/third_party/WebKit/Source/core/frame/Location.h +++ b/third_party/WebKit/Source/core/frame/Location.h
@@ -57,8 +57,8 @@ return adoptRefWillBeNoop(new Location(frame)); } - Frame* frame() const; - void reset(); + Frame* frame() const { return m_frame.get(); } + void reset() { m_frame = nullptr; } void setHref(LocalDOMWindow* callingWindow, LocalDOMWindow* enteredWindow, const String&); String href() const;
diff --git a/third_party/WebKit/Source/core/frame/RemoteFrame.cpp b/third_party/WebKit/Source/core/frame/RemoteFrame.cpp index bdb1b249..1d8a4ca0 100644 --- a/third_party/WebKit/Source/core/frame/RemoteFrame.cpp +++ b/third_party/WebKit/Source/core/frame/RemoteFrame.cpp
@@ -166,11 +166,6 @@ return static_cast<RemoteFrameClient*>(client()); } -WindowProxyManager* RemoteFrame::windowProxyManager() const -{ - return m_windowProxyManager.get(); -} - void RemoteFrame::setRemotePlatformLayer(WebLayer* layer) { if (m_remotePlatformLayer) @@ -183,9 +178,4 @@ toHTMLFrameOwnerElement(owner())->setNeedsCompositingUpdate(); } -RemoteFrameView* RemoteFrame::view() const -{ - return m_view.get(); -} - } // namespace blink
diff --git a/third_party/WebKit/Source/core/frame/RemoteFrame.h b/third_party/WebKit/Source/core/frame/RemoteFrame.h index 2d7d7e4..c12ec4b 100644 --- a/third_party/WebKit/Source/core/frame/RemoteFrame.h +++ b/third_party/WebKit/Source/core/frame/RemoteFrame.h
@@ -59,7 +59,7 @@ RemoteFrame(RemoteFrameClient*, FrameHost*, FrameOwner*); // Internal Frame helper overrides: - WindowProxyManager* windowProxyManager() const override; + WindowProxyManager* windowProxyManager() const override { return m_windowProxyManager.get(); } RemoteFrameClient* remoteFrameClient() const; @@ -70,6 +70,11 @@ WebLayer* m_remotePlatformLayer; }; +inline RemoteFrameView* RemoteFrame::view() const +{ + return m_view.get(); +} + DEFINE_TYPE_CASTS(RemoteFrame, Frame, remoteFrame, remoteFrame->isRemoteFrame(), remoteFrame.isRemoteFrame()); } // namespace blink
diff --git a/third_party/WebKit/Source/core/html/FormAssociatedElement.cpp b/third_party/WebKit/Source/core/html/FormAssociatedElement.cpp index 00acd8a..d98ae0a 100644 --- a/third_party/WebKit/Source/core/html/FormAssociatedElement.cpp +++ b/third_party/WebKit/Source/core/html/FormAssociatedElement.cpp
@@ -130,11 +130,6 @@ return element->findFormAncestor(); } -HTMLFormElement* FormAssociatedElement::form() const -{ - return m_form.get(); -} - void FormAssociatedElement::formRemovedFromTree(const Node& formRoot) { ASSERT(m_form);
diff --git a/third_party/WebKit/Source/core/html/FormAssociatedElement.h b/third_party/WebKit/Source/core/html/FormAssociatedElement.h index 0c76fdf..73ce908 100644 --- a/third_party/WebKit/Source/core/html/FormAssociatedElement.h +++ b/third_party/WebKit/Source/core/html/FormAssociatedElement.h
@@ -50,7 +50,7 @@ #endif static HTMLFormElement* findAssociatedForm(const HTMLElement*); - HTMLFormElement* form() const; + HTMLFormElement* form() const { return m_form.get(); } ValidityState* validity(); virtual bool isFormControlElement() const = 0;
diff --git a/third_party/WebKit/Source/core/html/FormData.cpp b/third_party/WebKit/Source/core/html/FormData.cpp index 14aef74..aac1c6f2 100644 --- a/third_party/WebKit/Source/core/html/FormData.cpp +++ b/third_party/WebKit/Source/core/html/FormData.cpp
@@ -323,39 +323,11 @@ // ---------------------------------------------------------------- -FormData::Entry::Entry(const CString& name, const CString& value) - : m_name(name) - , m_value(value) -{ -} - -FormData::Entry::Entry(const CString& name, Blob* blob, const String& filename) - : m_name(name) - , m_blob(blob) - , m_filename(filename) -{ -} - DEFINE_TRACE(FormData::Entry) { visitor->trace(m_blob); } -bool FormData::Entry::isString() const -{ - return !m_blob; -} - -bool FormData::Entry::isFile() const -{ - return m_blob; -} - -Blob* FormData::Entry::blob() const -{ - return m_blob.get(); -} - File* FormData::Entry::file() const { ASSERT(blob());
diff --git a/third_party/WebKit/Source/core/html/FormData.h b/third_party/WebKit/Source/core/html/FormData.h index 0142183..503c5d7 100644 --- a/third_party/WebKit/Source/core/html/FormData.h +++ b/third_party/WebKit/Source/core/html/FormData.h
@@ -101,17 +101,17 @@ // Represents entry, which is a pair of a name and a value. // https://xhr.spec.whatwg.org/#concept-formdata-entry // Entry objects are immutable. -class CORE_EXPORT FormData::Entry : public GarbageCollectedFinalized<FormData::Entry> { +class FormData::Entry : public GarbageCollectedFinalized<FormData::Entry> { public: - Entry(const CString&, const CString&); - Entry(const CString&, Blob*, const String&); + Entry(const CString& name, const CString& value) : m_name(name), m_value(value) { } + Entry(const CString& name, Blob* blob, const String& filename) : m_name(name), m_blob(blob), m_filename(filename) { } DECLARE_TRACE(); - bool isString() const; - bool isFile() const; + bool isString() const { return !m_blob; } + bool isFile() const { return m_blob; } const CString& name() const { return m_name; } const CString& value() const { return m_value; } - Blob* blob() const; + Blob* blob() const { return m_blob.get(); } File* file() const; const String& filename() const { return m_filename; }
diff --git a/third_party/WebKit/Source/core/html/HTMLCanvasElement.cpp b/third_party/WebKit/Source/core/html/HTMLCanvasElement.cpp index c9624691..47dfe42 100644 --- a/third_party/WebKit/Source/core/html/HTMLCanvasElement.cpp +++ b/third_party/WebKit/Source/core/html/HTMLCanvasElement.cpp
@@ -48,6 +48,7 @@ #include "platform/MIMETypeRegistry.h" #include "platform/RuntimeEnabledFeatures.h" #include "platform/graphics/Canvas2DImageBufferSurface.h" +#include "platform/graphics/CanvasMetrics.h" #include "platform/graphics/ExpensiveCanvasHeuristicParameters.h" #include "platform/graphics/ImageBuffer.h" #include "platform/graphics/RecordingImageBufferSurface.h" @@ -117,6 +118,7 @@ , m_imageBufferIsClear(false) { setHasCustomStyleCallbacks(); + CanvasMetrics::countCanvasContextUsage(CanvasMetrics::CanvasCreated); } DEFINE_NODE_FACTORY(HTMLCanvasElement) @@ -653,20 +655,30 @@ if (document().settings()) *msaaSampleCount = document().settings()->accelerated2dCanvasMSAASampleCount(); OwnPtr<ImageBufferSurface> surface = adoptPtr(new Canvas2DImageBufferSurface(deviceSize, *msaaSampleCount, opacityMode, Canvas2DLayerBridge::EnableAcceleration)); - if (surface->isValid()) + if (surface->isValid()) { + CanvasMetrics::countCanvasContextUsage(CanvasMetrics::GPUAccelerated2DCanvasImageBufferCreated); return surface.release(); + } + CanvasMetrics::countCanvasContextUsage(CanvasMetrics::GPUAccelerated2DCanvasImageBufferCreationFailed); } OwnPtr<RecordingImageBufferFallbackSurfaceFactory> surfaceFactory = adoptPtr(new UnacceleratedSurfaceFactory()); if (shouldUseDisplayList(deviceSize)) { OwnPtr<ImageBufferSurface> surface = adoptPtr(new RecordingImageBufferSurface(deviceSize, surfaceFactory.release(), opacityMode)); - if (surface->isValid()) + if (surface->isValid()) { + CanvasMetrics::countCanvasContextUsage(CanvasMetrics::DisplayList2DCanvasImageBufferCreated); return surface.release(); + } surfaceFactory = adoptPtr(new UnacceleratedSurfaceFactory()); // recreate because previous one was released } - - return surfaceFactory->createSurface(deviceSize, opacityMode); + auto surface = surfaceFactory->createSurface(deviceSize, opacityMode); + if (!surface->isValid()) { + CanvasMetrics::countCanvasContextUsage(CanvasMetrics::Unaccelerated2DCanvasImageBufferCreationFailed); + } else { + CanvasMetrics::countCanvasContextUsage(CanvasMetrics::Unaccelerated2DCanvasImageBufferCreated); + } + return surface; } void HTMLCanvasElement::createImageBuffer() @@ -786,11 +798,6 @@ return m_imageBuffer->canvas(); } -CanvasRenderingContext* HTMLCanvasElement::renderingContext() const -{ - return m_context.get(); -} - ImageBuffer* HTMLCanvasElement::buffer() const { ASSERT(m_context);
diff --git a/third_party/WebKit/Source/core/html/HTMLCanvasElement.h b/third_party/WebKit/Source/core/html/HTMLCanvasElement.h index 57d22a4..a8fdc174 100644 --- a/third_party/WebKit/Source/core/html/HTMLCanvasElement.h +++ b/third_party/WebKit/Source/core/html/HTMLCanvasElement.h
@@ -111,7 +111,7 @@ SkCanvas* existingDrawingCanvas() const; void setRenderingContext(PassOwnPtrWillBeRawPtr<CanvasRenderingContext>); - CanvasRenderingContext* renderingContext() const; + CanvasRenderingContext* renderingContext() const { return m_context.get(); } void ensureUnacceleratedImageBuffer(); ImageBuffer* buffer() const;
diff --git a/third_party/WebKit/Source/core/html/HTMLInputElement.cpp b/third_party/WebKit/Source/core/html/HTMLInputElement.cpp index e8827d0..38a24f3 100644 --- a/third_party/WebKit/Source/core/html/HTMLInputElement.cpp +++ b/third_party/WebKit/Source/core/html/HTMLInputElement.cpp
@@ -147,11 +147,6 @@ HTMLTextFormControlElement::trace(visitor); } -HTMLImageLoader* HTMLInputElement::imageLoader() const -{ - return m_imageLoader.get(); -} - HTMLImageLoader& HTMLInputElement::ensureImageLoader() { if (!m_imageLoader)
diff --git a/third_party/WebKit/Source/core/html/HTMLInputElement.h b/third_party/WebKit/Source/core/html/HTMLInputElement.h index 7518733..fec9689 100644 --- a/third_party/WebKit/Source/core/html/HTMLInputElement.h +++ b/third_party/WebKit/Source/core/html/HTMLInputElement.h
@@ -244,7 +244,7 @@ void setRangeText(const String& replacement, ExceptionState&) final; void setRangeText(const String& replacement, unsigned start, unsigned end, const String& selectionMode, ExceptionState&) final; - HTMLImageLoader* imageLoader() const; + HTMLImageLoader* imageLoader() const { return m_imageLoader.get(); } HTMLImageLoader& ensureImageLoader(); bool setupDateTimeChooserParameters(DateTimeChooserParameters&);
diff --git a/third_party/WebKit/Source/core/html/HTMLMediaElement.cpp b/third_party/WebKit/Source/core/html/HTMLMediaElement.cpp index 3bae974..f3c4ad3 100644 --- a/third_party/WebKit/Source/core/html/HTMLMediaElement.cpp +++ b/third_party/WebKit/Source/core/html/HTMLMediaElement.cpp
@@ -3452,11 +3452,6 @@ } #if ENABLE(WEB_AUDIO) -AudioSourceProviderClient* HTMLMediaElement::audioSourceNode() -{ - return m_audioSourceNode; -} - void HTMLMediaElement::setAudioSourceNode(AudioSourceProviderClient* sourceNode) { ASSERT(isMainThread()); @@ -3666,11 +3661,6 @@ m_webAudioSourceProvider->provideInput(webAudioData, framesToProcess); } -HTMLMediaElement::AudioClientImpl::AudioClientImpl(AudioSourceProviderClient* client) - : m_client(client) -{ -} - void HTMLMediaElement::AudioClientImpl::setFormat(size_t numberOfChannels, float sampleRate) { if (m_client)
diff --git a/third_party/WebKit/Source/core/html/HTMLMediaElement.h b/third_party/WebKit/Source/core/html/HTMLMediaElement.h index 66ec3be..980f33a 100644 --- a/third_party/WebKit/Source/core/html/HTMLMediaElement.h +++ b/third_party/WebKit/Source/core/html/HTMLMediaElement.h
@@ -234,7 +234,7 @@ bool hasPendingActivity() const final; #if ENABLE(WEB_AUDIO) - AudioSourceProviderClient* audioSourceNode(); + AudioSourceProviderClient* audioSourceNode() { return m_audioSourceNode; } void setAudioSourceNode(AudioSourceProviderClient*); AudioSourceProvider& audioSourceProvider() { return m_audioSourceProvider; } @@ -574,7 +574,11 @@ // When the audio format is known, Chromium calls setFormat(). class AudioClientImpl final : public GarbageCollectedFinalized<AudioClientImpl>, public WebAudioSourceProviderClient { public: - explicit AudioClientImpl(AudioSourceProviderClient*); + explicit AudioClientImpl(AudioSourceProviderClient* client) + : m_client(client) + { + } + ~AudioClientImpl() override { } // WebAudioSourceProviderClient
diff --git a/third_party/WebKit/Source/core/html/HTMLOptionElement.cpp b/third_party/WebKit/Source/core/html/HTMLOptionElement.cpp index a98df9b..099b5a4f 100644 --- a/third_party/WebKit/Source/core/html/HTMLOptionElement.cpp +++ b/third_party/WebKit/Source/core/html/HTMLOptionElement.cpp
@@ -362,18 +362,14 @@ void HTMLOptionElement::didNotifySubtreeInsertionsToDocument() { - if (HTMLSelectElement* select = ownerSelectElement()) { - select->setRecalcListItems(); + if (HTMLSelectElement* select = ownerSelectElement()) select->optionInserted(*this, m_isSelected); - } } void HTMLOptionElement::removedFrom(ContainerNode* insertionPoint) { - if (HTMLSelectElement* select = Traversal<HTMLSelectElement>::firstAncestorOrSelf(*insertionPoint)) { - select->setRecalcListItems(); + if (HTMLSelectElement* select = Traversal<HTMLSelectElement>::firstAncestorOrSelf(*insertionPoint)) select->optionRemoved(*this); - } HTMLElement::removedFrom(insertionPoint); }
diff --git a/third_party/WebKit/Source/core/html/HTMLSelectElement.cpp b/third_party/WebKit/Source/core/html/HTMLSelectElement.cpp index 0e1df0a..bfe8ee31 100644 --- a/third_party/WebKit/Source/core/html/HTMLSelectElement.cpp +++ b/third_party/WebKit/Source/core/html/HTMLSelectElement.cpp
@@ -972,12 +972,14 @@ void HTMLSelectElement::optionInserted(const HTMLOptionElement& option, bool optionIsSelected) { ASSERT(option.ownerSelectElement() == this); + setRecalcListItems(); if (optionIsSelected) selectOption(option.index()); } void HTMLSelectElement::optionRemoved(const HTMLOptionElement& option) { + setRecalcListItems(); if (m_lastOnChangeOption == &option) m_lastOnChangeOption.clear(); if (m_optionToScrollTo == &option) @@ -1983,11 +1985,6 @@ m_popup->hide(); } -PopupMenu* HTMLSelectElement::popup() const -{ - return m_popup.get(); -} - void HTMLSelectElement::didRecalcStyle(StyleRecalcChange change) { HTMLFormControlElementWithState::didRecalcStyle(change);
diff --git a/third_party/WebKit/Source/core/html/HTMLSelectElement.h b/third_party/WebKit/Source/core/html/HTMLSelectElement.h index c54751c..d288f1ad0 100644 --- a/third_party/WebKit/Source/core/html/HTMLSelectElement.h +++ b/third_party/WebKit/Source/core/html/HTMLSelectElement.h
@@ -151,7 +151,7 @@ int optionIndexToBeShown() const; void showPopup(); void hidePopup(); - PopupMenu* popup() const; + PopupMenu* popup() const { return m_popup.get(); } void resetTypeAheadSessionForTesting();
diff --git a/third_party/WebKit/Source/core/html/canvas/CanvasRenderingContext.h b/third_party/WebKit/Source/core/html/canvas/CanvasRenderingContext.h index 34e4cf1..1288688 100644 --- a/third_party/WebKit/Source/core/html/canvas/CanvasRenderingContext.h +++ b/third_party/WebKit/Source/core/html/canvas/CanvasRenderingContext.h
@@ -103,7 +103,7 @@ virtual bool is2d() const { return false; } virtual void restoreCanvasMatrixClipStack(SkCanvas*) const { } virtual void reset() { } - virtual void clearRect(float x, float y, float width, float height) { } + virtual void clearRect(double x, double y, double width, double height) { } virtual void didSetSurfaceSize() { } virtual void setShouldAntialias(bool) { } virtual unsigned hitRegionsCount() const { return 0; }
diff --git a/third_party/WebKit/Source/core/html/forms/InputTypeView.cpp b/third_party/WebKit/Source/core/html/forms/InputTypeView.cpp index 0361eb80b..76f135d 100644 --- a/third_party/WebKit/Source/core/html/forms/InputTypeView.cpp +++ b/third_party/WebKit/Source/core/html/forms/InputTypeView.cpp
@@ -40,11 +40,6 @@ return adoptRefWillBeNoop(new InputTypeView(input)); } -InputTypeView::InputTypeView(HTMLInputElement& element) - : m_element(&element) -{ -} - InputTypeView::~InputTypeView() { } @@ -232,11 +227,6 @@ return nullptr; } -HTMLInputElement& InputTypeView::element() const -{ - return *m_element; -} - DEFINE_TRACE(ClickHandlingState) { visitor->trace(checkedRadioButton);
diff --git a/third_party/WebKit/Source/core/html/forms/InputTypeView.h b/third_party/WebKit/Source/core/html/forms/InputTypeView.h index 692cfbd..86948c1 100644 --- a/third_party/WebKit/Source/core/html/forms/InputTypeView.h +++ b/third_party/WebKit/Source/core/html/forms/InputTypeView.h
@@ -125,8 +125,8 @@ virtual bool hasFallbackContent() const { return false; } protected: - explicit InputTypeView(HTMLInputElement&); - HTMLInputElement& element() const; + InputTypeView(HTMLInputElement& element) : m_element(&element) { } + HTMLInputElement& element() const { return *m_element; } private: // Not a RefPtr because the HTMLInputElement object owns this InputTypeView
diff --git a/third_party/WebKit/Source/core/html/imports/HTMLImportLoader.cpp b/third_party/WebKit/Source/core/html/imports/HTMLImportLoader.cpp index 57fedfe..a31d1c17 100644 --- a/third_party/WebKit/Source/core/html/imports/HTMLImportLoader.cpp +++ b/third_party/WebKit/Source/core/html/imports/HTMLImportLoader.cpp
@@ -193,11 +193,6 @@ m_imports.insert(0, import); } -Document* HTMLImportLoader::document() const -{ - return m_document.get(); -} - void HTMLImportLoader::addImport(HTMLImportChild* import) { ASSERT(kNotFound == m_imports.find(import));
diff --git a/third_party/WebKit/Source/core/html/imports/HTMLImportLoader.h b/third_party/WebKit/Source/core/html/imports/HTMLImportLoader.h index 4c1e0f3e..bf92a7da 100644 --- a/third_party/WebKit/Source/core/html/imports/HTMLImportLoader.h +++ b/third_party/WebKit/Source/core/html/imports/HTMLImportLoader.h
@@ -74,7 +74,7 @@ ~HTMLImportLoader() override; void dispose(); - Document* document() const; + Document* document() const { return m_document.get(); } void addImport(HTMLImportChild*); void removeImport(HTMLImportChild*);
diff --git a/third_party/WebKit/Source/core/html/imports/HTMLImportsController.cpp b/third_party/WebKit/Source/core/html/imports/HTMLImportsController.cpp index ed4b077..e3b7d2e 100644 --- a/third_party/WebKit/Source/core/html/imports/HTMLImportsController.cpp +++ b/third_party/WebKit/Source/core/html/imports/HTMLImportsController.cpp
@@ -89,11 +89,6 @@ m_loaders.clear(); } -HTMLImportTreeRoot* HTMLImportsController::root() const -{ - return m_root.get(); -} - static bool makesCycle(HTMLImport* parent, const KURL& url) { for (HTMLImport* ancestor = parent; ancestor; ancestor = ancestor->parent()) { @@ -166,16 +161,6 @@ return m_loaders.last().get(); } -size_t HTMLImportsController::loaderCount() const -{ - return m_loaders.size(); -} - -HTMLImportLoader* HTMLImportsController::loaderAt(size_t i) const -{ - return m_loaders[i].get(); -} - HTMLImportLoader* HTMLImportsController::loaderFor(const Document& document) const { for (size_t i = 0; i < m_loaders.size(); ++i) {
diff --git a/third_party/WebKit/Source/core/html/imports/HTMLImportsController.h b/third_party/WebKit/Source/core/html/imports/HTMLImportsController.h index 563c70b3..37c4e69 100644 --- a/third_party/WebKit/Source/core/html/imports/HTMLImportsController.h +++ b/third_party/WebKit/Source/core/html/imports/HTMLImportsController.h
@@ -57,7 +57,7 @@ explicit HTMLImportsController(Document&); virtual ~HTMLImportsController(); - HTMLImportTreeRoot* root() const; + HTMLImportTreeRoot* root() const { return m_root.get(); } bool shouldBlockScriptExecution(const Document&) const; HTMLImportChild* load(HTMLImport* parent, HTMLImportChildClient*, FetchRequest); @@ -66,8 +66,8 @@ HTMLImportLoader* createLoader(); - size_t loaderCount() const; - HTMLImportLoader* loaderAt(size_t) const; + size_t loaderCount() const { return m_loaders.size(); } + HTMLImportLoader* loaderAt(size_t i) const { return m_loaders[i].get(); } Document* loaderDocumentAt(size_t) const; HTMLImportLoader* loaderFor(const Document&) const;
diff --git a/third_party/WebKit/Source/core/html/parser/HTMLConstructionSite.cpp b/third_party/WebKit/Source/core/html/parser/HTMLConstructionSite.cpp index 4d7fa39b..b8b8cba6 100644 --- a/third_party/WebKit/Source/core/html/parser/HTMLConstructionSite.cpp +++ b/third_party/WebKit/Source/core/html/parser/HTMLConstructionSite.cpp
@@ -376,11 +376,6 @@ m_form = form; } -HTMLFormElement* HTMLConstructionSite::form() const -{ - return m_form.get(); -} - PassRefPtrWillBeRawPtr<HTMLFormElement> HTMLConstructionSite::takeForm() { return m_form.release();
diff --git a/third_party/WebKit/Source/core/html/parser/HTMLConstructionSite.h b/third_party/WebKit/Source/core/html/parser/HTMLConstructionSite.h index cc0a1f7..812b072 100644 --- a/third_party/WebKit/Source/core/html/parser/HTMLConstructionSite.h +++ b/third_party/WebKit/Source/core/html/parser/HTMLConstructionSite.h
@@ -196,7 +196,7 @@ HTMLStackItem* headStackItem() const { return m_head.get(); } void setForm(HTMLFormElement*); - HTMLFormElement* form() const; + HTMLFormElement* form() const { return m_form.get(); } PassRefPtrWillBeRawPtr<HTMLFormElement> takeForm(); ParserContentPolicy parserContentPolicy() { return m_parserContentPolicy; }
diff --git a/third_party/WebKit/Source/core/html/parser/HTMLDocumentParser.cpp b/third_party/WebKit/Source/core/html/parser/HTMLDocumentParser.cpp index fb024ff..4bd762f 100644 --- a/third_party/WebKit/Source/core/html/parser/HTMLDocumentParser.cpp +++ b/third_party/WebKit/Source/core/html/parser/HTMLDocumentParser.cpp
@@ -602,11 +602,6 @@ TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "UpdateCounters", TRACE_EVENT_SCOPE_THREAD, "data", InspectorUpdateCountersEvent::data()); } -HTMLTreeBuilder* HTMLDocumentParser::treeBuilder() const -{ - return m_treeBuilder.get(); -} - void HTMLDocumentParser::forcePlaintextForTextDocument() { if (shouldUseThreading()) {
diff --git a/third_party/WebKit/Source/core/html/parser/HTMLDocumentParser.h b/third_party/WebKit/Source/core/html/parser/HTMLDocumentParser.h index b86e860..3d49274c 100644 --- a/third_party/WebKit/Source/core/html/parser/HTMLDocumentParser.h +++ b/third_party/WebKit/Source/core/html/parser/HTMLDocumentParser.h
@@ -120,7 +120,7 @@ HTMLDocumentParser(HTMLDocument&, bool reportErrors, ParserSynchronizationPolicy); HTMLDocumentParser(DocumentFragment*, Element* contextElement, ParserContentPolicy); - HTMLTreeBuilder* treeBuilder() const; + HTMLTreeBuilder* treeBuilder() const { return m_treeBuilder.get(); } void forcePlaintextForTextDocument();
diff --git a/third_party/WebKit/Source/core/html/track/TrackBase.cpp b/third_party/WebKit/Source/core/html/track/TrackBase.cpp index f019855d..f8901994 100644 --- a/third_party/WebKit/Source/core/html/track/TrackBase.cpp +++ b/third_party/WebKit/Source/core/html/track/TrackBase.cpp
@@ -58,16 +58,6 @@ #endif } -void TrackBase::setMediaElement(HTMLMediaElement* mediaElement) -{ - m_mediaElement = mediaElement; -} - -HTMLMediaElement* TrackBase::mediaElement() const -{ - return m_mediaElement; -} - Node* TrackBase::owner() const { return m_mediaElement;
diff --git a/third_party/WebKit/Source/core/html/track/TrackBase.h b/third_party/WebKit/Source/core/html/track/TrackBase.h index 8bfa437..28db2a6 100644 --- a/third_party/WebKit/Source/core/html/track/TrackBase.h +++ b/third_party/WebKit/Source/core/html/track/TrackBase.h
@@ -57,8 +57,8 @@ String id() const { return m_id; } void setId(const String& id) { m_id = id; } - void setMediaElement(HTMLMediaElement*); - HTMLMediaElement* mediaElement() const; + void setMediaElement(HTMLMediaElement* mediaElement) { m_mediaElement = mediaElement; } + HTMLMediaElement* mediaElement() const { return m_mediaElement; } Node* owner() const; DECLARE_VIRTUAL_TRACE();
diff --git a/third_party/WebKit/Source/core/inspector/CodeGeneratorInspector.py b/third_party/WebKit/Source/core/inspector/CodeGeneratorInspector.py index 446a2ea9..8a707bccc 100755 --- a/third_party/WebKit/Source/core/inspector/CodeGeneratorInspector.py +++ b/third_party/WebKit/Source/core/inspector/CodeGeneratorInspector.py
@@ -1705,7 +1705,7 @@ Generator.method_name_enum_list.append(" %s," % cmd_enum_name) Generator.method_handler_list.append(" &InspectorBackendDispatcherImpl::%s_%s," % (domain_name, json_command_name)) - Generator.backend_method_declaration_list.append(" void %s_%s(int callId, JSONObject* requestMessageObject, JSONArray* protocolErrors);" % (domain_name, json_command_name)) + Generator.backend_method_declaration_list.append(" void %s_%s(int sessionId, int callId, JSONObject* requestMessageObject, JSONArray* protocolErrors);" % (domain_name, json_command_name)) backend_agent_interface_list = [] if "redirect" in json_command else Generator.backend_agent_interface_list @@ -1786,7 +1786,7 @@ callback_writer.newline("class " + callback_name + " : public CallbackBase {\n") callback_writer.newline("public:\n") - callback_writer.newline(" " + callback_name + "(PassRefPtrWillBeRawPtr<InspectorBackendDispatcherImpl>, int id);\n") + callback_writer.newline(" " + callback_name + "(PassRefPtrWillBeRawPtr<InspectorBackendDispatcherImpl>, int sessionId, int id);\n") callback_writer.newline(" CORE_EXPORT void sendSuccess(" + ", ".join(decl_parameter_list) + ");\n") error_part_writer = callback_writer.insert_writer("") callback_writer.newline("};\n") @@ -1807,7 +1807,7 @@ ad_hoc_type_output.append(callback_output) - method_out_code += " RefPtrWillBeRawPtr<" + agent_interface_name + "::" + callback_name + "> callback = adoptRefWillBeNoop(new " + agent_interface_name + "::" + callback_name + "(this, callId));\n" + method_out_code += " RefPtrWillBeRawPtr<" + agent_interface_name + "::" + callback_name + "> callback = adoptRefWillBeNoop(new " + agent_interface_name + "::" + callback_name + "(this, sessionId, callId));\n" agent_call_param_list.append("callback") normal_response_cook_text += " if (!error.length()) \n" normal_response_cook_text += " return;\n"
diff --git a/third_party/WebKit/Source/core/inspector/CodeGeneratorInspectorStrings.py b/third_party/WebKit/Source/core/inspector/CodeGeneratorInspectorStrings.py index e20c806b..03e46f91 100644 --- a/third_party/WebKit/Source/core/inspector/CodeGeneratorInspectorStrings.py +++ b/third_party/WebKit/Source/core/inspector/CodeGeneratorInspectorStrings.py
@@ -43,19 +43,19 @@ """) backend_method = ( -"""void InspectorBackendDispatcherImpl::${domainName}_$methodName(int callId, JSONObject*$requestMessageObject, JSONArray* protocolErrors) +"""void InspectorBackendDispatcherImpl::${domainName}_$methodName(int sessionId, int callId, JSONObject*$requestMessageObject, JSONArray* protocolErrors) { if (!$agentField) protocolErrors->pushString("${domainName} handler is not available."); $methodCode if (protocolErrors->length()) { - reportProtocolError(callId, InvalidParams, String::format(InvalidParamsFormatString, commandName($commandNameIndex)), protocolErrors); + reportProtocolError(sessionId, callId, InvalidParams, String::format(InvalidParamsFormatString, commandName($commandNameIndex)), protocolErrors); return; } $agentCallParamsDeclaration $agentField->$methodName($agentCallParams); $responseCook - sendResponse(callId, $sendResponseCallParams); + sendResponse(sessionId, callId, $sendResponseCallParams); } """) @@ -69,7 +69,7 @@ """) callback_main_methods = ( -"""InspectorBackendDispatcher::$agentName::$callbackName::$callbackName(PassRefPtrWillBeRawPtr<InspectorBackendDispatcherImpl> backendImpl, int id) : CallbackBase(backendImpl, id) {} +"""InspectorBackendDispatcher::$agentName::$callbackName::$callbackName(PassRefPtrWillBeRawPtr<InspectorBackendDispatcherImpl> backendImpl, int sessionId, int id) : CallbackBase(backendImpl, sessionId, id) {} void InspectorBackendDispatcher::$agentName::$callbackName::sendSuccess($parameters) { @@ -150,7 +150,7 @@ class CORE_EXPORT CallbackBase: public RefCountedWillBeGarbageCollectedFinalized<CallbackBase> { public: - CallbackBase(PassRefPtrWillBeRawPtr<InspectorBackendDispatcherImpl> backendImpl, int id); + CallbackBase(PassRefPtrWillBeRawPtr<InspectorBackendDispatcherImpl> backendImpl, int sessionId, int id); virtual ~CallbackBase(); DECLARE_VIRTUAL_TRACE(); void sendFailure(const ErrorString&); @@ -163,6 +163,7 @@ void disable() { m_alreadySent = true; } RefPtrWillBeMember<InspectorBackendDispatcherImpl> m_backendImpl; + int m_sessionId; int m_id; bool m_alreadySent; @@ -184,9 +185,9 @@ LastEntry, }; - void reportProtocolError(int callId, CommonErrorCode, const String& errorMessage) const; - virtual void reportProtocolError(int callId, CommonErrorCode, const String& errorMessage, PassRefPtr<JSONValue> data) const = 0; - virtual void dispatch(const String& message) = 0; + void reportProtocolError(int sessionId, int callId, CommonErrorCode, const String& errorMessage) const; + virtual void reportProtocolError(int sessionId, int callId, CommonErrorCode, const String& errorMessage, PassRefPtr<JSONValue> data) const = 0; + virtual void dispatch(int sessionId, const String& message) = 0; static bool getCommandName(const String& message, String* result); enum MethodNames { @@ -258,16 +259,16 @@ } virtual void clearFrontend() { m_inspectorFrontendChannel = 0; } - virtual void dispatch(const String& message); - virtual void reportProtocolError(int callId, CommonErrorCode, const String& errorMessage, PassRefPtr<JSONValue> data) const; + virtual void dispatch(int sessionId, const String& message); + virtual void reportProtocolError(int sessionId, int callId, CommonErrorCode, const String& errorMessage, PassRefPtr<JSONValue> data) const; using InspectorBackendDispatcher::reportProtocolError; - void sendResponse(int callId, const ErrorString& invocationError, PassRefPtr<JSONValue> errorData, PassRefPtr<JSONObject> result); + void sendResponse(int sessionId, int callId, const ErrorString& invocationError, PassRefPtr<JSONValue> errorData, PassRefPtr<JSONObject> result); bool isActive() { return m_inspectorFrontendChannel; } $setters private: - using CallHandler = void (InspectorBackendDispatcherImpl::*)(int callId, JSONObject* messageObject, JSONArray* protocolErrors); + using CallHandler = void (InspectorBackendDispatcherImpl::*)(int sessionId, int callId, JSONObject* messageObject, JSONArray* protocolErrors); using DispatchMap = HashMap<String, CallHandler>; $methodDeclarations @@ -285,13 +286,13 @@ static PassRefPtr<JSONObject> getObject(JSONObject* object, const char* name, bool* valueFound, JSONArray* protocolErrors); static PassRefPtr<JSONArray> getArray(JSONObject* object, const char* name, bool* valueFound, JSONArray* protocolErrors); - void sendResponse(int callId, ErrorString invocationError, PassRefPtr<JSONObject> result) + void sendResponse(int sessionId, int callId, ErrorString invocationError, PassRefPtr<JSONObject> result) { - sendResponse(callId, invocationError, RefPtr<JSONValue>(), result); + sendResponse(sessionId, callId, invocationError, RefPtr<JSONValue>(), result); } - void sendResponse(int callId, ErrorString invocationError) + void sendResponse(int sessionId, int callId, ErrorString invocationError) { - sendResponse(callId, invocationError, RefPtr<JSONValue>(), JSONObject::create()); + sendResponse(sessionId, callId, invocationError, RefPtr<JSONValue>(), JSONObject::create()); } static const char InvalidParamsFormatString[]; @@ -309,7 +310,7 @@ } -void InspectorBackendDispatcherImpl::dispatch(const String& message) +void InspectorBackendDispatcherImpl::dispatch(int sessionId, const String& message) { RefPtrWillBeRawPtr<InspectorBackendDispatcher> protect(this); int callId = 0; @@ -329,18 +330,18 @@ HashMap<String, CallHandler>::iterator it = m_dispatchMap.find(method); if (it == m_dispatchMap.end()) { - reportProtocolError(callId, MethodNotFound, "'" + method + "' wasn't found"); + reportProtocolError(sessionId, callId, MethodNotFound, "'" + method + "' wasn't found"); return; } RefPtr<JSONArray> protocolErrors = JSONArray::create(); - ((*this).*it->value)(callId, messageObject.get(), protocolErrors.get()); + ((*this).*it->value)(sessionId, callId, messageObject.get(), protocolErrors.get()); } -void InspectorBackendDispatcherImpl::sendResponse(int callId, const ErrorString& invocationError, PassRefPtr<JSONValue> errorData, PassRefPtr<JSONObject> result) +void InspectorBackendDispatcherImpl::sendResponse(int sessionId, int callId, const ErrorString& invocationError, PassRefPtr<JSONValue> errorData, PassRefPtr<JSONObject> result) { if (invocationError.length()) { - reportProtocolError(callId, ServerError, invocationError, errorData); + reportProtocolError(sessionId, callId, ServerError, invocationError, errorData); return; } @@ -348,15 +349,15 @@ responseMessage->setNumber("id", callId); responseMessage->setObject("result", result); if (m_inspectorFrontendChannel) - m_inspectorFrontendChannel->sendProtocolResponse(callId, responseMessage.release()); + m_inspectorFrontendChannel->sendProtocolResponse(sessionId, callId, responseMessage.release()); } -void InspectorBackendDispatcher::reportProtocolError(int callId, CommonErrorCode code, const String& errorMessage) const +void InspectorBackendDispatcher::reportProtocolError(int sessionId, int callId, CommonErrorCode code, const String& errorMessage) const { - reportProtocolError(callId, code, errorMessage, PassRefPtr<JSONValue>()); + reportProtocolError(sessionId, callId, code, errorMessage, PassRefPtr<JSONValue>()); } -void InspectorBackendDispatcherImpl::reportProtocolError(int callId, CommonErrorCode code, const String& errorMessage, PassRefPtr<JSONValue> data) const +void InspectorBackendDispatcherImpl::reportProtocolError(int sessionId, int callId, CommonErrorCode code, const String& errorMessage, PassRefPtr<JSONValue> data) const { ASSERT(code >=0); ASSERT((unsigned)code < m_commonErrors.size()); @@ -371,7 +372,7 @@ message->setObject("error", error); message->setNumber("id", callId); if (m_inspectorFrontendChannel) - m_inspectorFrontendChannel->sendProtocolResponse(callId, message.release()); + m_inspectorFrontendChannel->sendProtocolResponse(sessionId, callId, message.release()); } template<typename R, typename V, typename V0> @@ -464,8 +465,8 @@ return true; } -InspectorBackendDispatcher::CallbackBase::CallbackBase(PassRefPtrWillBeRawPtr<InspectorBackendDispatcherImpl> backendImpl, int id) - : m_backendImpl(backendImpl), m_id(id), m_alreadySent(false) {} +InspectorBackendDispatcher::CallbackBase::CallbackBase(PassRefPtrWillBeRawPtr<InspectorBackendDispatcherImpl> backendImpl, int sessionId, int id) + : m_backendImpl(backendImpl), m_sessionId(sessionId), m_id(id), m_alreadySent(false) {} InspectorBackendDispatcher::CallbackBase::~CallbackBase() {} @@ -489,7 +490,7 @@ { if (m_alreadySent) return; - m_backendImpl->sendResponse(m_id, invocationError, errorData, partialMessage); + m_backendImpl->sendResponse(m_sessionId, m_id, invocationError, errorData, partialMessage); m_alreadySent = true; }
diff --git a/third_party/WebKit/Source/core/inspector/CodeGeneratorInstrumentation.py b/third_party/WebKit/Source/core/inspector/CodeGeneratorInstrumentation.py index 54d82dd6..741029c 100755 --- a/third_party/WebKit/Source/core/inspector/CodeGeneratorInstrumentation.py +++ b/third_party/WebKit/Source/core/inspector/CodeGeneratorInstrumentation.py
@@ -145,20 +145,9 @@ #endif // !defined(InstrumentingAgentsInl_h) """) -template_instrumenting_agent_accessor_prompt = string.Template(""" - ${class_name}* ${getter_name}() const; - void set${class_name}(${class_name}* agent);""") - -template_instrumenting_agent_accessor_impl = string.Template(""" -${class_name}* InstrumentingAgents::${getter_name}() const -{ - return ${member_name}; -} - -void InstrumentingAgents::set${class_name}(${class_name}* agent) -{ - ${member_name} = agent; -}""") +template_instrumenting_agent_accessor = string.Template(""" + ${class_name}* ${getter_name}() const { return ${member_name}; } + void set${class_name}(${class_name}* agent) { ${member_name} = agent; }""") template_instrumenting_agents_cpp = string.Template(""" InstrumentingAgents::InstrumentingAgents() @@ -174,9 +163,7 @@ void InstrumentingAgents::reset() { $reset_list -} - -${accessor_list}""") +}""") @@ -465,7 +452,6 @@ forward_list = [] accessor_list = [] - accessor_impl_list = [] member_list = [] init_list = [] trace_list = [] @@ -476,11 +462,7 @@ member_name = "m_" + getter_name forward_list.append("class %s;" % class_name) - accessor_list.append(template_instrumenting_agent_accessor_prompt.substitute( - None, - class_name=class_name, - getter_name=getter_name)) - accessor_impl_list.append(template_instrumenting_agent_accessor_impl.substitute( + accessor_list.append(template_instrumenting_agent_accessor.substitute( None, class_name=class_name, getter_name=getter_name, @@ -492,7 +474,6 @@ forward_list.sort() accessor_list.sort() - accessor_impl_list.sort() member_list.sort() init_list.sort() trace_list.sort() @@ -508,8 +489,7 @@ None, init_list="\n , ".join(init_list), trace_list="\n ".join(trace_list), - reset_list="\n ".join(reset_list), - accessor_list="\n".join(accessor_impl_list)) + reset_list="\n ".join(reset_list)) return header_lines, cpp_lines
diff --git a/third_party/WebKit/Source/core/inspector/DebuggerScript.js b/third_party/WebKit/Source/core/inspector/DebuggerScript.js index 9eb62854..fd1b976 100644 --- a/third_party/WebKit/Source/core/inspector/DebuggerScript.js +++ b/third_party/WebKit/Source/core/inspector/DebuggerScript.js
@@ -87,7 +87,7 @@ return null; var result = { "function": funcMirror.value(), - "functionName": DebuggerScript._displayFunctionName(funcMirror) || "", + "functionName": funcMirror.debugName(), "status": mirror.status() }; var script = funcMirror.script(); @@ -362,17 +362,6 @@ return (script.compilationType() === Debug.ScriptCompilationType.Eval); } -DebuggerScript._displayFunctionName = function(funcMirror) -{ - if (!funcMirror.resolved()) - return undefined - var displayName; - var valueMirror = funcMirror.property("displayName").value(); - if (valueMirror && valueMirror.isString()) - displayName = valueMirror.value(); - return displayName || funcMirror.name() || funcMirror.inferredName(); -} - // NOTE: This function is performance critical, as it can be run on every // statement that generates an async event (like addEventListener) to support // asynchronous call stacks. Thus, when possible, initialize the data lazily. @@ -485,7 +474,7 @@ function functionName() { - return DebuggerScript._displayFunctionName(ensureFuncMirror()); + return ensureFuncMirror().debugName(); } function functionLine()
diff --git a/third_party/WebKit/Source/core/inspector/InjectedScriptHost.h b/third_party/WebKit/Source/core/inspector/InjectedScriptHost.h index efd2f3be..87fe9db 100644 --- a/third_party/WebKit/Source/core/inspector/InjectedScriptHost.h +++ b/third_party/WebKit/Source/core/inspector/InjectedScriptHost.h
@@ -33,10 +33,6 @@ #include "bindings/core/v8/ScriptState.h" #include "core/InspectorTypeBuilder.h" #include "core/inspector/InjectedScriptHostClient.h" -#include "core/inspector/InspectorConsoleAgent.h" -#include "core/inspector/v8/V8Debugger.h" -#include "core/inspector/v8/V8DebuggerAgent.h" -#include "platform/JSONValues.h" #include "wtf/Functional.h" #include "wtf/PassOwnPtr.h" #include "wtf/RefCounted.h" @@ -46,11 +42,15 @@ namespace blink { -class EventListenerInfo; class EventTarget; class InjectedScriptHostClient; +class InspectorConsoleAgent; class JSONValue; class ScriptValue; +class V8DebuggerAgent; +class V8Debugger; + +class EventListenerInfo; // SECURITY NOTE: Although the InjectedScriptHost is intended for use solely by the inspector, // a reference to the InjectedScriptHost may be leaked to the page being inspected. Thus, the
diff --git a/third_party/WebKit/Source/core/inspector/InspectorDOMAgent.cpp b/third_party/WebKit/Source/core/inspector/InspectorDOMAgent.cpp index 1c9bafd8..9309d9f 100644 --- a/third_party/WebKit/Source/core/inspector/InspectorDOMAgent.cpp +++ b/third_party/WebKit/Source/core/inspector/InspectorDOMAgent.cpp
@@ -1447,11 +1447,6 @@ result = object; } -InspectorHistory* InspectorDOMAgent::history() const -{ - return m_history.get(); -} - void InspectorDOMAgent::getAttributes(ErrorString* errorString, int nodeId, RefPtr<TypeBuilder::Array<String> >& result) { Element* element = assertElement(errorString, nodeId);
diff --git a/third_party/WebKit/Source/core/inspector/InspectorDOMAgent.h b/third_party/WebKit/Source/core/inspector/InspectorDOMAgent.h index 918e03d0..6dbeb79 100644 --- a/third_party/WebKit/Source/core/inspector/InspectorDOMAgent.h +++ b/third_party/WebKit/Source/core/inspector/InspectorDOMAgent.h
@@ -189,7 +189,7 @@ PassRefPtr<TypeBuilder::Runtime::RemoteObject> resolveNode(Node*, const String& objectGroup); - InspectorHistory* history() const; + InspectorHistory* history() { return m_history.get(); } // We represent embedded doms as a part of the same hierarchy. Hence we treat children of frame owners differently. // We also skip whitespace text nodes conditionally. Following methods encapsulate these specifics.
diff --git a/third_party/WebKit/Source/core/inspector/InspectorFrontendChannel.h b/third_party/WebKit/Source/core/inspector/InspectorFrontendChannel.h index 8b687d1..580a12d3 100644 --- a/third_party/WebKit/Source/core/inspector/InspectorFrontendChannel.h +++ b/third_party/WebKit/Source/core/inspector/InspectorFrontendChannel.h
@@ -34,7 +34,7 @@ class InspectorFrontendChannel { public: virtual ~InspectorFrontendChannel() { } - virtual void sendProtocolResponse(int callId, PassRefPtr<JSONObject> message) = 0; + virtual void sendProtocolResponse(int sessionId, int callId, PassRefPtr<JSONObject> message) = 0; virtual void sendProtocolNotification(PassRefPtr<JSONObject> message) = 0; virtual void flush() = 0; };
diff --git a/third_party/WebKit/Source/core/inspector/InspectorPageAgent.cpp b/third_party/WebKit/Source/core/inspector/InspectorPageAgent.cpp index 8109767..eb017f0 100644 --- a/third_party/WebKit/Source/core/inspector/InspectorPageAgent.cpp +++ b/third_party/WebKit/Source/core/inspector/InspectorPageAgent.cpp
@@ -754,7 +754,7 @@ return result; } -void InspectorPageAgent::startScreencast(ErrorString*, const String* format, const int* quality, const int* maxWidth, const int* maxHeight) +void InspectorPageAgent::startScreencast(ErrorString*, const String* format, const int* quality, const int* maxWidth, const int* maxHeight, const int* everyNthFrame) { m_state->setBoolean(PageAgentState::screencastEnabled, true); }
diff --git a/third_party/WebKit/Source/core/inspector/InspectorPageAgent.h b/third_party/WebKit/Source/core/inspector/InspectorPageAgent.h index 1f4f4e5..83d5c67 100644 --- a/third_party/WebKit/Source/core/inspector/InspectorPageAgent.h +++ b/third_party/WebKit/Source/core/inspector/InspectorPageAgent.h
@@ -103,7 +103,7 @@ void getResourceContent(ErrorString*, const String& frameId, const String& url, PassRefPtrWillBeRawPtr<GetResourceContentCallback>) override; void searchInResource(ErrorString*, const String& frameId, const String& url, const String& query, const bool* optionalCaseSensitive, const bool* optionalIsRegex, PassRefPtrWillBeRawPtr<SearchInResourceCallback>) override; void setDocumentContent(ErrorString*, const String& frameId, const String& html) override; - void startScreencast(ErrorString*, const String* format, const int* quality, const int* maxWidth, const int* maxHeight) override; + void startScreencast(ErrorString*, const String* format, const int* quality, const int* maxWidth, const int* maxHeight, const int* everyNthFrame) override; void stopScreencast(ErrorString*) override; void setOverlayMessage(ErrorString*, const String*) override;
diff --git a/third_party/WebKit/Source/core/inspector/InspectorStyleSheet.cpp b/third_party/WebKit/Source/core/inspector/InspectorStyleSheet.cpp index 7db98f3..cc8485a 100644 --- a/third_party/WebKit/Source/core/inspector/InspectorStyleSheet.cpp +++ b/third_party/WebKit/Source/core/inspector/InspectorStyleSheet.cpp
@@ -1257,11 +1257,6 @@ } } -CSSStyleSheet* InspectorStyleSheet::pageStyleSheet() const -{ - return m_pageStyleSheet.get(); -} - PassRefPtr<TypeBuilder::CSS::CSSStyleSheetHeader> InspectorStyleSheet::buildObjectForStyleSheetInfo() { CSSStyleSheet* styleSheet = pageStyleSheet();
diff --git a/third_party/WebKit/Source/core/inspector/InspectorStyleSheet.h b/third_party/WebKit/Source/core/inspector/InspectorStyleSheet.h index c5cd723f7..a07e152d 100644 --- a/third_party/WebKit/Source/core/inspector/InspectorStyleSheet.h +++ b/third_party/WebKit/Source/core/inspector/InspectorStyleSheet.h
@@ -134,7 +134,7 @@ RefPtrWillBeRawPtr<CSSStyleRule> addRule(const String& ruleText, const SourceRange& location, SourceRange* addedRange, ExceptionState&); bool deleteRule(const SourceRange&, ExceptionState&); - CSSStyleSheet* pageStyleSheet() const; + CSSStyleSheet* pageStyleSheet() { return m_pageStyleSheet.get(); } PassRefPtr<TypeBuilder::CSS::CSSStyleSheetHeader> buildObjectForStyleSheetInfo(); PassRefPtr<TypeBuilder::CSS::CSSRule> buildObjectForRuleWithoutMedia(CSSStyleRule*);
diff --git a/third_party/WebKit/Source/core/inspector/WorkerInspectorController.cpp b/third_party/WebKit/Source/core/inspector/WorkerInspectorController.cpp index 13101cc..5480497 100644 --- a/third_party/WebKit/Source/core/inspector/WorkerInspectorController.cpp +++ b/third_party/WebKit/Source/core/inspector/WorkerInspectorController.cpp
@@ -109,7 +109,7 @@ { } - void sendProtocolResponse(int callId, PassRefPtr<JSONObject> message) override + void sendProtocolResponse(int sessionId, int callId, PassRefPtr<JSONObject> message) override { // Worker messages are wrapped, no need to handle callId. m_workerGlobalScope->thread()->workerReportingProxy().postMessageToPageInspector(message->toJSONString()); @@ -212,8 +212,10 @@ void WorkerInspectorController::dispatchMessageFromFrontend(const String& message) { InspectorTaskRunner::IgnoreInterruptsScope scope(m_inspectorTaskRunner.get()); - if (m_backendDispatcher) - m_backendDispatcher->dispatch(message); + if (m_backendDispatcher) { + // sessionId will be overwritten by WebDevToolsAgent::sendProtocolNotifications call. + m_backendDispatcher->dispatch(0, message); + } } void WorkerInspectorController::dispose()
diff --git a/third_party/WebKit/Source/core/inspector/v8/V8InjectedScriptHost.cpp b/third_party/WebKit/Source/core/inspector/v8/V8InjectedScriptHost.cpp index f1298a2..c6d33dcb 100644 --- a/third_party/WebKit/Source/core/inspector/v8/V8InjectedScriptHost.cpp +++ b/third_party/WebKit/Source/core/inspector/v8/V8InjectedScriptHost.cpp
@@ -66,18 +66,9 @@ static v8::Local<v8::String> functionDisplayName(v8::Local<v8::Function> function) { - v8::Local<v8::Value> value = function->GetDisplayName(); + v8::Local<v8::Value> value = function->GetDebugName(); if (value->IsString() && v8::Local<v8::String>::Cast(value)->Length()) return v8::Local<v8::String>::Cast(value); - - value = function->GetName(); - if (value->IsString() && v8::Local<v8::String>::Cast(value)->Length()) - return v8::Local<v8::String>::Cast(value); - - value = function->GetInferredName(); - if (value->IsString() && v8::Local<v8::String>::Cast(value)->Length()) - return v8::Local<v8::String>::Cast(value); - return v8::Local<v8::String>(); }
diff --git a/third_party/WebKit/Source/core/layout/LayoutBlockFlow.cpp b/third_party/WebKit/Source/core/layout/LayoutBlockFlow.cpp index 796ecfb..bd4bf8a 100644 --- a/third_party/WebKit/Source/core/layout/LayoutBlockFlow.cpp +++ b/third_party/WebKit/Source/core/layout/LayoutBlockFlow.cpp
@@ -737,7 +737,7 @@ return newLogicalTop; } -static inline bool shouldSetStrutOnBlock(const LayoutBlockFlow& block, const RootInlineBox& lineBox, LayoutUnit lineLogicalOffset, int lineIndex, LayoutUnit remainingLogicalHeight) +static bool shouldSetStrutOnBlock(const LayoutBlockFlow& block, const RootInlineBox& lineBox, LayoutUnit lineLogicalOffset, int lineIndex, LayoutUnit remainingLogicalHeight) { bool wantsStrutOnBlock = false; if (!block.style()->hasAutoOrphans() && block.style()->orphans() >= lineIndex) { @@ -762,6 +762,14 @@ return wantsStrutOnBlock && block.allowsPaginationStrut(); } +static LayoutUnit calculateStrutForPropagation(const LayoutBlockFlow& blockFlow, LayoutUnit lineLogicalOffset) +{ + LayoutUnit paginationStrut = std::max<LayoutUnit>(LayoutUnit(), lineLogicalOffset); + if (blockFlow.isFloating()) + paginationStrut += blockFlow.marginBefore(); // Floats' margins do not collapse with page or column boundaries. + return paginationStrut; +} + void LayoutBlockFlow::adjustLinePositionForPagination(RootInlineBox& lineBox, LayoutUnit& delta) { // TODO(mstensho): Pay attention to line overflow. It should be painted in the same column as @@ -805,10 +813,7 @@ // content-less portions (struts) at the beginning of a block before a break, if it can // be avoided. After all, that's the reason for setting struts on blocks and not lines // in the first place. - LayoutUnit paginationStrut = remainingLogicalHeight + std::max<LayoutUnit>(0, logicalOffset); - if (isFloating()) - paginationStrut += marginBefore(); // Floats' margins do not collapse with page or column boundaries. - setPaginationStrutPropagatedFromChild(paginationStrut); + setPaginationStrutPropagatedFromChild(calculateStrutForPropagation(*this, remainingLogicalHeight + logicalOffset)); } else { logicalOffset += remainingLogicalHeight; delta += remainingLogicalHeight; @@ -819,6 +824,27 @@ // We're at the very top of a page or column. if (lineBox != firstRootBox()) lineBox.setIsFirstAfterPageBreak(true); + // If this is the first line in the block, and the block has a top border, padding, or (in + // case it's a float) margin, we may want to set a strut on the block, so that everything + // ends up in the next column or page. Setting a strut on the block is also important when + // it comes to satisfying orphan requirements. + if (shouldSetStrutOnBlock(*this, lineBox, logicalOffset, lineIndex, remainingLogicalHeight)) + setPaginationStrutPropagatedFromChild(calculateStrutForPropagation(*this, logicalOffset)); + } else if (lineBox == firstRootBox() && allowsPaginationStrut()) { + // This is the first line in the block. The block may still start in the previous column or + // page, and if that's the case, attempt to pull it over to where this line is, so that we + // don't split the top border, padding, or (in case it's a float) margin. + LayoutUnit totalLogicalOffset = logicalOffset; + if (isFloating()) + totalLogicalOffset += marginBefore(); // Floats' margins do not collapse with page or column boundaries. + LayoutUnit strut = remainingLogicalHeight + totalLogicalOffset - pageLogicalHeight; + if (strut > 0) { + // The block starts in a previous column or page. Set a strut on the block if there's + // room for the top border, padding and (if it's a float) margin and the line in one + // column or page. + if (totalLogicalOffset + lineHeight <= pageLogicalHeight) + setPaginationStrutPropagatedFromChild(strut); + } } paginatedContentWasLaidOut(logicalOffset);
diff --git a/third_party/WebKit/Source/core/layout/LayoutImageResource.cpp b/third_party/WebKit/Source/core/layout/LayoutImageResource.cpp index 80677b6..e19a029 100644 --- a/third_party/WebKit/Source/core/layout/LayoutImageResource.cpp +++ b/third_party/WebKit/Source/core/layout/LayoutImageResource.cpp
@@ -94,7 +94,7 @@ { if (!m_cachedImage) return LayoutSize(); - LayoutSize size = m_cachedImage->imageSizeForLayoutObject(m_layoutObject, multiplier, ImageResource::IntrinsicSize); + LayoutSize size = m_cachedImage->imageSizeForLayoutObject(m_layoutObject, multiplier); if (m_layoutObject && m_layoutObject->isLayoutImage() && size.width() && size.height()) size.scale(toLayoutImage(m_layoutObject)->imageDevicePixelRatio()); return size;
diff --git a/third_party/WebKit/Source/core/layout/api/LineLayoutBlockFlow.h b/third_party/WebKit/Source/core/layout/api/LineLayoutBlockFlow.h index 030fa546..1c0d8508 100644 --- a/third_party/WebKit/Source/core/layout/api/LineLayoutBlockFlow.h +++ b/third_party/WebKit/Source/core/layout/api/LineLayoutBlockFlow.h
@@ -30,6 +30,8 @@ ASSERT(!item || item.isLayoutBlockFlow()); } + explicit LineLayoutBlockFlow(std::nullptr_t) : LineLayoutBox(nullptr) { } + LineLayoutBlockFlow() { } LineLayoutItem firstChild() const
diff --git a/third_party/WebKit/Source/core/layout/api/LineLayoutBox.h b/third_party/WebKit/Source/core/layout/api/LineLayoutBox.h index b9c6249..3d53826 100644 --- a/third_party/WebKit/Source/core/layout/api/LineLayoutBox.h +++ b/third_party/WebKit/Source/core/layout/api/LineLayoutBox.h
@@ -27,6 +27,8 @@ ASSERT(!item || item.isBox()); } + explicit LineLayoutBox(std::nullptr_t) : LineLayoutBoxModel(nullptr) { } + LineLayoutBox() { } LayoutPoint location() const
diff --git a/third_party/WebKit/Source/core/layout/api/LineLayoutBoxModel.h b/third_party/WebKit/Source/core/layout/api/LineLayoutBoxModel.h index b579df4..775fa68 100644 --- a/third_party/WebKit/Source/core/layout/api/LineLayoutBoxModel.h +++ b/third_party/WebKit/Source/core/layout/api/LineLayoutBoxModel.h
@@ -26,6 +26,8 @@ ASSERT(!item || item.isBoxModelObject()); } + explicit LineLayoutBoxModel(std::nullptr_t) : LineLayoutItem(nullptr) { } + LineLayoutBoxModel() { } PaintLayer* layer() const
diff --git a/third_party/WebKit/Source/core/layout/api/LineLayoutInline.h b/third_party/WebKit/Source/core/layout/api/LineLayoutInline.h index fb354290..a0f28d4 100644 --- a/third_party/WebKit/Source/core/layout/api/LineLayoutInline.h +++ b/third_party/WebKit/Source/core/layout/api/LineLayoutInline.h
@@ -28,6 +28,8 @@ ASSERT(!item || item.isLayoutInline()); } + explicit LineLayoutInline(std::nullptr_t) : LineLayoutBoxModel(nullptr) { } + LineLayoutInline() { } LineLayoutItem firstChild() const
diff --git a/third_party/WebKit/Source/core/layout/api/LineLayoutListMarker.h b/third_party/WebKit/Source/core/layout/api/LineLayoutListMarker.h index 68d6ca1..d115c8f0 100644 --- a/third_party/WebKit/Source/core/layout/api/LineLayoutListMarker.h +++ b/third_party/WebKit/Source/core/layout/api/LineLayoutListMarker.h
@@ -23,6 +23,8 @@ ASSERT(!item || item.isListMarker()); } + explicit LineLayoutListMarker(std::nullptr_t) : LineLayoutBox(nullptr) { } + LineLayoutListMarker() { } bool isInside() const
diff --git a/third_party/WebKit/Source/core/layout/api/LineLayoutRubyRun.h b/third_party/WebKit/Source/core/layout/api/LineLayoutRubyRun.h index 777a745c9c..1fdfab9 100644 --- a/third_party/WebKit/Source/core/layout/api/LineLayoutRubyRun.h +++ b/third_party/WebKit/Source/core/layout/api/LineLayoutRubyRun.h
@@ -23,6 +23,8 @@ ASSERT(!item || item.isRubyRun()); } + explicit LineLayoutRubyRun(std::nullptr_t) : LineLayoutBlockFlow(nullptr) { } + LineLayoutRubyRun() { } void getOverhang(bool firstLine, LineLayoutItem startLayoutItem, LineLayoutItem endLayoutItem, int& startOverhang, int& endOverhang) const
diff --git a/third_party/WebKit/Source/core/layout/api/LineLayoutSVGInlineText.h b/third_party/WebKit/Source/core/layout/api/LineLayoutSVGInlineText.h index 204cd21..02496d4 100644 --- a/third_party/WebKit/Source/core/layout/api/LineLayoutSVGInlineText.h +++ b/third_party/WebKit/Source/core/layout/api/LineLayoutSVGInlineText.h
@@ -23,6 +23,8 @@ ASSERT(!item || item.isSVGInlineText()); } + explicit LineLayoutSVGInlineText(std::nullptr_t) : LineLayoutText(nullptr) { } + LineLayoutSVGInlineText() { } SVGTextLayoutAttributes* layoutAttributes() const
diff --git a/third_party/WebKit/Source/core/layout/api/LineLayoutText.h b/third_party/WebKit/Source/core/layout/api/LineLayoutText.h index 1eac45e..7f5fe02 100644 --- a/third_party/WebKit/Source/core/layout/api/LineLayoutText.h +++ b/third_party/WebKit/Source/core/layout/api/LineLayoutText.h
@@ -25,6 +25,8 @@ ASSERT(!item || item.isText()); } + explicit LineLayoutText(std::nullptr_t) : LineLayoutItem(nullptr) { } + LineLayoutText() { } InlineTextBox* firstTextBox() const
diff --git a/third_party/WebKit/Source/core/layout/api/LineLayoutTextCombine.h b/third_party/WebKit/Source/core/layout/api/LineLayoutTextCombine.h index 84d7756..b0f7186 100644 --- a/third_party/WebKit/Source/core/layout/api/LineLayoutTextCombine.h +++ b/third_party/WebKit/Source/core/layout/api/LineLayoutTextCombine.h
@@ -23,6 +23,8 @@ ASSERT(!item || item.isCombineText()); } + explicit LineLayoutTextCombine(std::nullptr_t) : LineLayoutText(nullptr) { } + LineLayoutTextCombine() { } bool isCombined() const
diff --git a/third_party/WebKit/Source/core/layout/compositing/CompositedLayerMapping.cpp b/third_party/WebKit/Source/core/layout/compositing/CompositedLayerMapping.cpp index f187ba0..1e088dd 100644 --- a/third_party/WebKit/Source/core/layout/compositing/CompositedLayerMapping.cpp +++ b/third_party/WebKit/Source/core/layout/compositing/CompositedLayerMapping.cpp
@@ -2192,28 +2192,42 @@ // cc::DisplayListRecordingSource::UpdateAndExpandInvalidation() before we keep only one copy of the algorithm. static const int kPixelDistanceToRecord = 4000; -IntRect CompositedLayerMapping::recomputeInterestRect(const GraphicsLayer* graphicsLayer, LayoutObject* owningLayoutObject) +IntRect CompositedLayerMapping::recomputeInterestRect(const GraphicsLayer* graphicsLayer) const { FloatRect graphicsLayerBounds(FloatPoint(), graphicsLayer->size()); - // Start with the bounds of the graphics layer in the space of the owning LayoutObject. + IntSize offsetFromAnchorLayoutObject; + const LayoutBoxModelObject* anchorLayoutObject; + if (graphicsLayer == m_squashingLayer) { + // All squashed layers have the same clip and transform space, so we can use the first squashed layer's + // layoutObject to map the squashing layer's bounds into viewport space, with offsetFromAnchorLayoutObject + // to translate squashing layer's bounds into the first squashed layer's space. + anchorLayoutObject = m_squashedLayers[0].paintLayer->layoutObject(); + offsetFromAnchorLayoutObject = m_squashedLayers[0].offsetFromLayoutObject; + } else { + ASSERT(graphicsLayer == m_graphicsLayer || graphicsLayer == m_scrollingContentsLayer); + anchorLayoutObject = m_owningLayer.layoutObject(); + offsetFromAnchorLayoutObject = graphicsLayer->offsetFromLayoutObject(); + } + + // Start with the bounds of the graphics layer in the space of the anchor LayoutObject. FloatRect graphicsLayerBoundsInObjectSpace(graphicsLayerBounds); - graphicsLayerBoundsInObjectSpace.move(graphicsLayer->offsetFromLayoutObject()); + graphicsLayerBoundsInObjectSpace.move(offsetFromAnchorLayoutObject); // Now map the bounds to its visible content rect in screen space, including applying clips along the way. LayoutRect visibleContentRect(graphicsLayerBoundsInObjectSpace); - LayoutView* rootView = owningLayoutObject->view(); + LayoutView* rootView = anchorLayoutObject->view(); while (rootView->frame()->ownerLayoutObject()) rootView = rootView->frame()->ownerLayoutObject()->view(); - owningLayoutObject->mapRectToPaintInvalidationBacking(rootView, visibleContentRect, 0); + anchorLayoutObject->mapRectToPaintInvalidationBacking(rootView, visibleContentRect, 0); visibleContentRect.intersect(LayoutRect(rootView->frameView()->visibleContentRect())); // Map the visible content rect from screen space to local graphics layer space. IntRect localInterestRect; // If the visible content rect is empty, then it makes no sense to map it back since there is nothing to map. if (!visibleContentRect.isEmpty()) { - localInterestRect = owningLayoutObject->absoluteToLocalQuad(FloatRect(visibleContentRect), UseTransforms).enclosingBoundingBox(); - localInterestRect.move(-graphicsLayer->offsetFromLayoutObject()); + localInterestRect = anchorLayoutObject->absoluteToLocalQuad(FloatRect(visibleContentRect), UseTransforms).enclosingBoundingBox(); + localInterestRect.move(-offsetFromAnchorLayoutObject); } // Expand by interest rect padding amount. localInterestRect.inflate(kPixelDistanceToRecord); @@ -2261,10 +2275,11 @@ { // Paint the whole layer if "mainFrameClipsContent" is false, meaning that WebPreferences::record_whole_document is true. bool shouldPaintWholePage = !m_owningLayer.layoutObject()->document().settings()->mainFrameClipsContent(); - if (shouldPaintWholePage || (graphicsLayer != m_graphicsLayer && graphicsLayer != m_squashingLayer)) + if (shouldPaintWholePage + || (graphicsLayer != m_graphicsLayer && graphicsLayer != m_squashingLayer && graphicsLayer != m_squashingLayer && graphicsLayer != m_scrollingContentsLayer)) return IntRect(IntPoint(), expandedIntSize(graphicsLayer->size())); - IntRect newInterestRect = recomputeInterestRect(graphicsLayer, m_owningLayer.layoutObject()); + IntRect newInterestRect = recomputeInterestRect(graphicsLayer); if (interestRectChangedEnoughToRepaint(previousInterestRect, newInterestRect, expandedIntSize(graphicsLayer->size()))) return newInterestRect; return previousInterestRect;
diff --git a/third_party/WebKit/Source/core/layout/compositing/CompositedLayerMapping.h b/third_party/WebKit/Source/core/layout/compositing/CompositedLayerMapping.h index 8e9bb8b0..6cf26aa 100644 --- a/third_party/WebKit/Source/core/layout/compositing/CompositedLayerMapping.h +++ b/third_party/WebKit/Source/core/layout/compositing/CompositedLayerMapping.h
@@ -215,7 +215,7 @@ String debugName() const { return "CompositedLayerMapping for " + owningLayer().debugName(); } private: - static IntRect recomputeInterestRect(const GraphicsLayer*, LayoutObject* owningLayoutObject); + IntRect recomputeInterestRect(const GraphicsLayer*) const; static bool interestRectChangedEnoughToRepaint(const IntRect& previousInterestRect, const IntRect& newInterestRect, const IntSize& layerSize); static const GraphicsLayerPaintInfo* containingSquashedLayer(const LayoutObject*, const Vector<GraphicsLayerPaintInfo>& layers, unsigned maxSquashedLayerIndex);
diff --git a/third_party/WebKit/Source/core/layout/compositing/CompositedLayerMappingTest.cpp b/third_party/WebKit/Source/core/layout/compositing/CompositedLayerMappingTest.cpp index d2f2e5e..d6c7a4e 100644 --- a/third_party/WebKit/Source/core/layout/compositing/CompositedLayerMappingTest.cpp +++ b/third_party/WebKit/Source/core/layout/compositing/CompositedLayerMappingTest.cpp
@@ -20,9 +20,9 @@ : m_originalSlimmingPaintSynchronizedPaintingEnabled(RuntimeEnabledFeatures::slimmingPaintSynchronizedPaintingEnabled()) { } protected: - IntRect recomputeInterestRect(const GraphicsLayer* graphicsLayer, LayoutObject* owningLayoutObject) + IntRect recomputeInterestRect(const GraphicsLayer* graphicsLayer) { - return CompositedLayerMapping::recomputeInterestRect(graphicsLayer, owningLayoutObject); + return static_cast<CompositedLayerMapping*>(graphicsLayer->client())->recomputeInterestRect(graphicsLayer); } IntRect computeInterestRect(const CompositedLayerMapping* compositedLayerMapping, GraphicsLayer* graphicsLayer, IntRect previousInterestRect) @@ -75,7 +75,7 @@ Element* element = document().getElementById("target"); PaintLayer* paintLayer = toLayoutBoxModelObject(element->layoutObject())->layer(); ASSERT_TRUE(!!paintLayer->graphicsLayerBacking()); - EXPECT_RECT_EQ(IntRect(0, 0, 200, 200), recomputeInterestRect(paintLayer->graphicsLayerBacking(), paintLayer->layoutObject())); + EXPECT_RECT_EQ(IntRect(0, 0, 200, 200), recomputeInterestRect(paintLayer->graphicsLayerBacking())); } TEST_F(CompositedLayerMappingTest, TallLayerInterestRect) @@ -88,7 +88,7 @@ ASSERT_TRUE(paintLayer->graphicsLayerBacking()); // Screen-space visible content rect is [8, 8, 200, 600]. Mapping back to local, adding 4000px in all directions, then // clipping, yields this rect. - EXPECT_RECT_EQ(IntRect(0, 0, 200, 4592), recomputeInterestRect(paintLayer->graphicsLayerBacking(), paintLayer->layoutObject())); + EXPECT_RECT_EQ(IntRect(0, 0, 200, 4592), recomputeInterestRect(paintLayer->graphicsLayerBacking())); } TEST_F(CompositedLayerMappingTest, TallLayerWholeDocumentInterestRect) @@ -103,7 +103,7 @@ ASSERT_TRUE(paintLayer->graphicsLayerBacking()); ASSERT_TRUE(paintLayer->compositedLayerMapping()); // recomputeInterestRect computes the interest rect; computeInterestRect applies the extra setting to paint everything. - EXPECT_RECT_EQ(IntRect(0, 0, 200, 4592), recomputeInterestRect(paintLayer->graphicsLayerBacking(), paintLayer->layoutObject())); + EXPECT_RECT_EQ(IntRect(0, 0, 200, 4592), recomputeInterestRect(paintLayer->graphicsLayerBacking())); EXPECT_RECT_EQ(IntRect(0, 0, 200, 10000), computeInterestRect(paintLayer->compositedLayerMapping(), paintLayer->graphicsLayerBacking(), IntRect())); } @@ -117,7 +117,7 @@ Element* element = document().getElementById("target"); PaintLayer* paintLayer = toLayoutBoxModelObject(element->layoutObject())->layer(); ASSERT_TRUE(!!paintLayer->graphicsLayerBacking()); - EXPECT_RECT_EQ(IntRect(0, 0, 200, 200), recomputeInterestRect(paintLayer->graphicsLayerBacking(), paintLayer->layoutObject())); + EXPECT_RECT_EQ(IntRect(0, 0, 200, 200), recomputeInterestRect(paintLayer->graphicsLayerBacking())); } TEST_F(CompositedLayerMappingTest, 3D90DegRotatedTallInterestRect) @@ -131,7 +131,7 @@ Element* element = document().getElementById("target"); PaintLayer* paintLayer = toLayoutBoxModelObject(element->layoutObject())->layer(); ASSERT_TRUE(!!paintLayer->graphicsLayerBacking()); - EXPECT_RECT_EQ(IntRect(0, 0, 200, 4000), recomputeInterestRect(paintLayer->graphicsLayerBacking(), paintLayer->layoutObject())); + EXPECT_RECT_EQ(IntRect(0, 0, 200, 4000), recomputeInterestRect(paintLayer->graphicsLayerBacking())); } TEST_F(CompositedLayerMappingTest, 3D45DegRotatedTallInterestRect) @@ -143,7 +143,7 @@ Element* element = document().getElementById("target"); PaintLayer* paintLayer = toLayoutBoxModelObject(element->layoutObject())->layer(); ASSERT_TRUE(!!paintLayer->graphicsLayerBacking()); - EXPECT_RECT_EQ(IntRect(0, 0, 200, 4592), recomputeInterestRect(paintLayer->graphicsLayerBacking(), paintLayer->layoutObject())); + EXPECT_RECT_EQ(IntRect(0, 0, 200, 4592), recomputeInterestRect(paintLayer->graphicsLayerBacking())); } TEST_F(CompositedLayerMappingTest, RotatedTallInterestRect) @@ -155,7 +155,7 @@ Element* element = document().getElementById("target"); PaintLayer* paintLayer = toLayoutBoxModelObject(element->layoutObject())->layer(); ASSERT_TRUE(!!paintLayer->graphicsLayerBacking()); - EXPECT_RECT_EQ(IntRect(0, 0, 200, 4000), recomputeInterestRect(paintLayer->graphicsLayerBacking(), paintLayer->layoutObject())); + EXPECT_RECT_EQ(IntRect(0, 0, 200, 4000), recomputeInterestRect(paintLayer->graphicsLayerBacking())); } TEST_F(CompositedLayerMappingTest, WideLayerInterestRect) @@ -168,7 +168,7 @@ ASSERT_TRUE(!!paintLayer->graphicsLayerBacking()); // Screen-space visible content rect is [8, 8, 800, 200] (the screen is 800x600). // Mapping back to local, adding 4000px in all directions, then clipping, yields this rect. - EXPECT_RECT_EQ(IntRect(0, 0, 4792, 200), recomputeInterestRect(paintLayer->graphicsLayerBacking(), paintLayer->layoutObject())); + EXPECT_RECT_EQ(IntRect(0, 0, 4792, 200), recomputeInterestRect(paintLayer->graphicsLayerBacking())); } TEST_F(CompositedLayerMappingTest, FixedPositionInterestRect) @@ -180,7 +180,7 @@ Element* element = document().getElementById("target"); PaintLayer* paintLayer = toLayoutBoxModelObject(element->layoutObject())->layer(); ASSERT_TRUE(!!paintLayer->graphicsLayerBacking()); - EXPECT_RECT_EQ(IntRect(0, 0, 300, 400), recomputeInterestRect(paintLayer->graphicsLayerBacking(), paintLayer->layoutObject())); + EXPECT_RECT_EQ(IntRect(0, 0, 300, 400), recomputeInterestRect(paintLayer->graphicsLayerBacking())); } TEST_F(CompositedLayerMappingTest, LayerOffscreenInterestRect) @@ -194,7 +194,7 @@ PaintLayer* paintLayer = toLayoutBoxModelObject(element->layoutObject())->layer(); ASSERT_TRUE(!!paintLayer->graphicsLayerBacking()); // Offscreen layers are painted as usual. - EXPECT_RECT_EQ(IntRect(0, 0, 200, 200), recomputeInterestRect(paintLayer->graphicsLayerBacking(), paintLayer->layoutObject())); + EXPECT_RECT_EQ(IntRect(0, 0, 200, 200), recomputeInterestRect(paintLayer->graphicsLayerBacking())); } TEST_F(CompositedLayerMappingTest, ScrollingLayerInterestRect) @@ -210,7 +210,7 @@ ASSERT_TRUE(paintLayer->graphicsLayerBacking()); // Offscreen layers are painted as usual. ASSERT_TRUE(paintLayer->compositedLayerMapping()->scrollingLayer()); - EXPECT_RECT_EQ(IntRect(0, 0, 195, 4592), recomputeInterestRect(paintLayer->graphicsLayerBackingForScrolling(), paintLayer->layoutObject())); + EXPECT_RECT_EQ(IntRect(0, 0, 195, 4592), recomputeInterestRect(paintLayer->graphicsLayerBackingForScrolling())); } TEST_F(CompositedLayerMappingTest, ClippedBigLayer) @@ -224,7 +224,7 @@ PaintLayer* paintLayer = toLayoutBoxModelObject(element->layoutObject())->layer(); ASSERT_TRUE(paintLayer->graphicsLayerBacking()); // Offscreen layers are painted as usual. - EXPECT_RECT_EQ(IntRect(0, 0, 4001, 4001), recomputeInterestRect(paintLayer->graphicsLayerBacking(), paintLayer->layoutObject())); + EXPECT_RECT_EQ(IntRect(0, 0, 4001, 4001), recomputeInterestRect(paintLayer->graphicsLayerBacking())); } TEST_F(CompositedLayerMappingTest, ClippingMaskLayer) @@ -325,8 +325,11 @@ EXPECT_TRUE(interestRectChangedEnoughToRepaint(previousInterestRect, newInterestRect, layerSize)); } -TEST_F(CompositedLayerMappingTest, InterestRectChangeOnScroll) +TEST_F(CompositedLayerMappingTest, InterestRectChangeOnViewportScroll) { + if (document().frame()->settings()->rootLayerScrolls()) + return; + setBodyInnerHTML( "<style>" " ::-webkit-scrollbar { width: 0; height: 0; }" @@ -341,57 +344,144 @@ document().view()->setScrollPosition(IntPoint(0, 300), ProgrammaticScroll); document().view()->updateAllLifecyclePhases(); // Still use the previous interest rect because the recomputed rect hasn't changed enough. - EXPECT_RECT_EQ(IntRect(0, 0, 800, 4900), recomputeInterestRect(rootScrollingLayer, document().layoutView())); + EXPECT_RECT_EQ(IntRect(0, 0, 800, 4900), recomputeInterestRect(rootScrollingLayer)); EXPECT_RECT_EQ(IntRect(0, 0, 800, 4600), previousInterestRect(rootScrollingLayer)); document().view()->setScrollPosition(IntPoint(0, 600), ProgrammaticScroll); document().view()->updateAllLifecyclePhases(); // Use recomputed interest rect because it changed enough. - EXPECT_RECT_EQ(IntRect(0, 0, 800, 5200), recomputeInterestRect(rootScrollingLayer, document().layoutView())); + EXPECT_RECT_EQ(IntRect(0, 0, 800, 5200), recomputeInterestRect(rootScrollingLayer)); EXPECT_RECT_EQ(IntRect(0, 0, 800, 5200), previousInterestRect(rootScrollingLayer)); document().view()->setScrollPosition(IntPoint(0, 5400), ProgrammaticScroll); document().view()->updateAllLifecyclePhases(); - EXPECT_RECT_EQ(IntRect(0, 1400, 800, 8600), recomputeInterestRect(rootScrollingLayer, document().layoutView())); + EXPECT_RECT_EQ(IntRect(0, 1400, 800, 8600), recomputeInterestRect(rootScrollingLayer)); EXPECT_RECT_EQ(IntRect(0, 1400, 800, 8600), previousInterestRect(rootScrollingLayer)); document().view()->setScrollPosition(IntPoint(0, 9000), ProgrammaticScroll); document().view()->updateAllLifecyclePhases(); // Still use the previous interest rect because it contains the recomputed interest rect. - EXPECT_RECT_EQ(IntRect(0, 5000, 800, 5000), recomputeInterestRect(rootScrollingLayer, document().layoutView())); + EXPECT_RECT_EQ(IntRect(0, 5000, 800, 5000), recomputeInterestRect(rootScrollingLayer)); EXPECT_RECT_EQ(IntRect(0, 1400, 800, 8600), previousInterestRect(rootScrollingLayer)); document().view()->setScrollPosition(IntPoint(0, 2000), ProgrammaticScroll); // Use recomputed interest rect because it changed enough. document().view()->updateAllLifecyclePhases(); - EXPECT_RECT_EQ(IntRect(0, 0, 800, 6600), recomputeInterestRect(rootScrollingLayer, document().layoutView())); + EXPECT_RECT_EQ(IntRect(0, 0, 800, 6600), recomputeInterestRect(rootScrollingLayer)); EXPECT_RECT_EQ(IntRect(0, 0, 800, 6600), previousInterestRect(rootScrollingLayer)); } -TEST_F(CompositedLayerMappingTest, InterestRectShouldNotChangeOnPaintInvalidation) +TEST_F(CompositedLayerMappingTest, InterestRectChangeOnScroll) { + document().frame()->settings()->setPreferCompositingToLCDTextEnabled(true); + setBodyInnerHTML( "<style>" " ::-webkit-scrollbar { width: 0; height: 0; }" " body { margin: 0; }" "</style>" - "<div id='div' style='width: 100px; height: 10000px'>Text</div>"); + "<div id='scroller' style='width: 400px; height: 400px; overflow: scroll'>" + " <div id='content' style='width: 100px; height: 10000px'>Text</div>" + "</div"); - GraphicsLayer* rootScrollingLayer = document().layoutView()->layer()->graphicsLayerBackingForScrolling(); - - document().view()->setScrollPosition(IntPoint(0, 5400), ProgrammaticScroll); document().view()->updateAllLifecyclePhases(); - document().view()->setScrollPosition(IntPoint(0, 9400), ProgrammaticScroll); + Element* scroller = document().getElementById("scroller"); + GraphicsLayer* scrollingLayer = scroller->layoutBox()->layer()->graphicsLayerBackingForScrolling(); + EXPECT_RECT_EQ(IntRect(0, 0, 400, 4600), previousInterestRect(scrollingLayer)); + + scroller->setScrollTop(300); + document().view()->updateAllLifecyclePhases(); + // Still use the previous interest rect because the recomputed rect hasn't changed enough. + EXPECT_RECT_EQ(IntRect(0, 0, 400, 4900), recomputeInterestRect(scrollingLayer)); + EXPECT_RECT_EQ(IntRect(0, 0, 400, 4600), previousInterestRect(scrollingLayer)); + + scroller->setScrollTop(600); + document().view()->updateAllLifecyclePhases(); + // Use recomputed interest rect because it changed enough. + EXPECT_RECT_EQ(IntRect(0, 0, 400, 5200), recomputeInterestRect(scrollingLayer)); + EXPECT_RECT_EQ(IntRect(0, 0, 400, 5200), previousInterestRect(scrollingLayer)); + + scroller->setScrollTop(5400); + document().view()->updateAllLifecyclePhases(); + EXPECT_RECT_EQ(IntRect(0, 1400, 400, 8600), recomputeInterestRect(scrollingLayer)); + EXPECT_RECT_EQ(IntRect(0, 1400, 400, 8600), previousInterestRect(scrollingLayer)); + + scroller->setScrollTop(9000); + document().view()->updateAllLifecyclePhases(); + // Still use the previous interest rect because it contains the recomputed interest rect. + EXPECT_RECT_EQ(IntRect(0, 5000, 400, 5000), recomputeInterestRect(scrollingLayer)); + EXPECT_RECT_EQ(IntRect(0, 1400, 400, 8600), previousInterestRect(scrollingLayer)); + + scroller->setScrollTop(2000); + // Use recomputed interest rect because it changed enough. + document().view()->updateAllLifecyclePhases(); + EXPECT_RECT_EQ(IntRect(0, 0, 400, 6600), recomputeInterestRect(scrollingLayer)); + EXPECT_RECT_EQ(IntRect(0, 0, 400, 6600), previousInterestRect(scrollingLayer)); +} + +TEST_F(CompositedLayerMappingTest, InterestRectShouldNotChangeOnPaintInvalidation) +{ + document().frame()->settings()->setPreferCompositingToLCDTextEnabled(true); + + setBodyInnerHTML( + "<style>" + " ::-webkit-scrollbar { width: 0; height: 0; }" + " body { margin: 0; }" + "</style>" + "<div id='scroller' style='width: 400px; height: 400px; overflow: scroll'>" + " <div id='content' style='width: 100px; height: 10000px'>Text</div>" + "</div"); + + document().view()->updateAllLifecyclePhases(); + Element* scroller = document().getElementById("scroller"); + GraphicsLayer* scrollingLayer = scroller->layoutBox()->layer()->graphicsLayerBackingForScrolling(); + + scroller->setScrollTop(5400); + document().view()->updateAllLifecyclePhases(); + scroller->setScrollTop(9400); // The above code creates an interest rect bigger than the interest rect if recomputed now. document().view()->updateAllLifecyclePhases(); - EXPECT_RECT_EQ(IntRect(0, 5400, 800, 4600), recomputeInterestRect(rootScrollingLayer, document().layoutView())); - EXPECT_RECT_EQ(IntRect(0, 1400, 800, 8600), previousInterestRect(rootScrollingLayer)); + EXPECT_RECT_EQ(IntRect(0, 5400, 400, 4600), recomputeInterestRect(scrollingLayer)); + EXPECT_RECT_EQ(IntRect(0, 1400, 400, 8600), previousInterestRect(scrollingLayer)); // Paint invalidation and repaint should not change previous paint interest rect. - document().getElementById("div")->setTextContent("Change"); + document().getElementById("content")->setTextContent("Change"); document().view()->updateAllLifecyclePhases(); - EXPECT_RECT_EQ(IntRect(0, 5400, 800, 4600), recomputeInterestRect(rootScrollingLayer, document().layoutView())); - EXPECT_RECT_EQ(IntRect(0, 1400, 800, 8600), previousInterestRect(rootScrollingLayer)); + EXPECT_RECT_EQ(IntRect(0, 5400, 400, 4600), recomputeInterestRect(scrollingLayer)); + EXPECT_RECT_EQ(IntRect(0, 1400, 400, 8600), previousInterestRect(scrollingLayer)); +} + +TEST_F(CompositedLayerMappingTest, InterestRectOfSquashingLayerWithNegativeOverflow) +{ + setBodyInnerHTML( + "<style>body { margin: 0 }</style>" + "<div style='position: absolute; top: -500px; width: 200px; height: 700px; will-change: transform'></div>" + "<div id='squashed' style='position: absolute; top: 190px'>" + " <div style='width: 100px; height: 100px; text-indent: -10000px'>text</div>" + "</div>"); + + CompositedLayerMapping* groupedMapping = document().getElementById("squashed")->layoutBox()->layer()->groupedMapping(); + // The squashing layer is at (-10000, 190, 10100, 100) in viewport coordinates. + // The following rect is at (-4000, 190, 4100, 100) in viewport coordinates. + EXPECT_RECT_EQ(IntRect(6000, 0, 4100, 100), groupedMapping->computeInterestRect(groupedMapping->squashingLayer(), IntRect())); +} + +TEST_F(CompositedLayerMappingTest, InterestRectOfSquashingLayerWithAncestorClip) +{ + setBodyInnerHTML( + "<style>body { margin: 0; }</style>" + "<div style='overflow: hidden; width: 400px; height: 400px'>" + " <div style='position: relative; backface-visibility: hidden'>" + " <div style='position: absolute; top: -500px; width: 200px; height: 700px; backface-visibility: hidden'></div>" + // Above overflow:hidden div and two composited layers make the squashing layer a child of an ancestor clipping layer. + " <div id='squashed' style='height: 1000px; width: 10000px; right: 0; position: absolute'></div>" + " </div>" + "</div>"); + + CompositedLayerMapping* groupedMapping = document().getElementById("squashed")->layoutBox()->layer()->groupedMapping(); + // The squashing layer is at (-9600, 0, 10000, 1000) in viewport coordinates. + // The following rect is at (-4000, 0, 4400, 1000) in viewport coordinates. + EXPECT_RECT_EQ(IntRect(5600, 0, 4400, 1000), groupedMapping->computeInterestRect(groupedMapping->squashingLayer(), IntRect())); } } // namespace blink
diff --git a/third_party/WebKit/Source/core/layout/svg/SVGTextLayoutAttributesBuilder.cpp b/third_party/WebKit/Source/core/layout/svg/SVGTextLayoutAttributesBuilder.cpp index 62d6100f..3ca248c 100644 --- a/third_party/WebKit/Source/core/layout/svg/SVGTextLayoutAttributesBuilder.cpp +++ b/third_party/WebKit/Source/core/layout/svg/SVGTextLayoutAttributesBuilder.cpp
@@ -232,13 +232,6 @@ } } -SVGTextLayoutAttributesBuilder::TextPosition::TextPosition(SVGTextPositioningElement* newElement, unsigned newStart, unsigned newLength) - : element(newElement) - , start(newStart) - , length(newLength) -{ -} - DEFINE_TRACE(SVGTextLayoutAttributesBuilder::TextPosition) { visitor->trace(element);
diff --git a/third_party/WebKit/Source/core/layout/svg/SVGTextLayoutAttributesBuilder.h b/third_party/WebKit/Source/core/layout/svg/SVGTextLayoutAttributesBuilder.h index d0a055d..f05c55f 100644 --- a/third_party/WebKit/Source/core/layout/svg/SVGTextLayoutAttributesBuilder.h +++ b/third_party/WebKit/Source/core/layout/svg/SVGTextLayoutAttributesBuilder.h
@@ -58,7 +58,12 @@ struct TextPosition { DISALLOW_NEW_EXCEPT_PLACEMENT_NEW(); public: - TextPosition(SVGTextPositioningElement* = nullptr, unsigned newStart = 0, unsigned newLength = 0); + TextPosition(SVGTextPositioningElement* newElement = nullptr, unsigned newStart = 0, unsigned newLength = 0) + : element(newElement) + , start(newStart) + , length(newLength) + { + } DECLARE_TRACE();
diff --git a/third_party/WebKit/Source/core/loader/DocumentLoader.cpp b/third_party/WebKit/Source/core/loader/DocumentLoader.cpp index b02ba68..01b2985 100644 --- a/third_party/WebKit/Source/core/loader/DocumentLoader.cpp +++ b/third_party/WebKit/Source/core/loader/DocumentLoader.cpp
@@ -154,11 +154,6 @@ return m_request; } -ResourceFetcher* DocumentLoader::fetcher() const -{ - return m_fetcher.get(); -} - const KURL& DocumentLoader::url() const { return m_request.url();
diff --git a/third_party/WebKit/Source/core/loader/DocumentLoader.h b/third_party/WebKit/Source/core/loader/DocumentLoader.h index bc595de..ff2d375 100644 --- a/third_party/WebKit/Source/core/loader/DocumentLoader.h +++ b/third_party/WebKit/Source/core/loader/DocumentLoader.h
@@ -42,7 +42,6 @@ #include "core/loader/DocumentWriter.h" #include "core/loader/FrameLoaderTypes.h" #include "core/loader/NavigationPolicy.h" -#include "core/loader/appcache/ApplicationCacheHost.h" #include "platform/SharedBuffer.h" #include "platform/network/ResourceError.h" #include "platform/network/ResourceRequest.h" @@ -52,6 +51,7 @@ namespace blink { +class ApplicationCacheHost; class ResourceFetcher; class DocumentInit; class LocalFrame; @@ -83,7 +83,7 @@ const ResourceRequest& request() const; - ResourceFetcher* fetcher() const; + ResourceFetcher* fetcher() const { return m_fetcher.get(); } const SubstituteData& substituteData() const { return m_substituteData; }
diff --git a/third_party/WebKit/Source/core/loader/FormSubmission.h b/third_party/WebKit/Source/core/loader/FormSubmission.h index b8278ba..0c612ec 100644 --- a/third_party/WebKit/Source/core/loader/FormSubmission.h +++ b/third_party/WebKit/Source/core/loader/FormSubmission.h
@@ -31,7 +31,6 @@ #ifndef FormSubmission_h #define FormSubmission_h -#include "core/events/Event.h" #include "platform/heap/Handle.h" #include "platform/weborigin/KURL.h" #include "platform/weborigin/Referrer.h" @@ -40,6 +39,7 @@ namespace blink { class EncodedFormData; +class Event; struct FrameLoadRequest; class HTMLFormElement;
diff --git a/third_party/WebKit/Source/core/loader/FrameLoader.h b/third_party/WebKit/Source/core/loader/FrameLoader.h index bff0ff71..b12caa89 100644 --- a/third_party/WebKit/Source/core/loader/FrameLoader.h +++ b/third_party/WebKit/Source/core/loader/FrameLoader.h
@@ -38,7 +38,6 @@ #include "core/dom/SecurityContext.h" #include "core/fetch/ResourceLoaderOptions.h" #include "core/frame/FrameTypes.h" -#include "core/loader/DocumentLoader.h" #include "core/loader/FrameLoaderStateMachine.h" #include "core/loader/FrameLoaderTypes.h" #include "core/loader/HistoryItem.h" @@ -51,6 +50,7 @@ namespace blink { +class DocumentLoader; class Frame; class FrameLoaderClient; class ProgressTracker;
diff --git a/third_party/WebKit/Source/core/page/AutoscrollController.cpp b/third_party/WebKit/Source/core/page/AutoscrollController.cpp index 38650aaf..a3f79c5 100644 --- a/third_party/WebKit/Source/core/page/AutoscrollController.cpp +++ b/third_party/WebKit/Source/core/page/AutoscrollController.cpp
@@ -131,7 +131,12 @@ while (layoutObject && !(layoutObject->isBox() && toLayoutBox(layoutObject)->canAutoscroll())) layoutObject = layoutObject->parent(); - m_autoscrollLayoutObject = layoutObject && layoutObject->isBox() ? toLayoutBox(layoutObject) : nullptr; + + LayoutBox* autoscrollLayoutObject = layoutObject && layoutObject->isBox() ? toLayoutBox(layoutObject) : nullptr; + if (m_autoscrollLayoutObject && !autoscrollLayoutObject) + stopAutoscrollIfNeeded(m_autoscrollLayoutObject); + + m_autoscrollLayoutObject = autoscrollLayoutObject; } void AutoscrollController::updateDragAndDrop(Node* dropTargetNode, const IntPoint& eventPosition, double eventTime)
diff --git a/third_party/WebKit/Source/core/page/DragData.h b/third_party/WebKit/Source/core/page/DragData.h index 0466dfa6..8673f08 100644 --- a/third_party/WebKit/Source/core/page/DragData.h +++ b/third_party/WebKit/Source/core/page/DragData.h
@@ -27,7 +27,6 @@ #define DragData_h #include "core/CoreExport.h" -#include "core/clipboard/DataObject.h" #include "core/page/DragActions.h" #include "platform/geometry/IntPoint.h" #include "platform/heap/Handle.h" @@ -37,6 +36,7 @@ namespace blink { +class DataObject; class DocumentFragment; class LocalFrame; class Range; @@ -84,4 +84,4 @@ } -#endif // DragData_h +#endif // !DragData_h
diff --git a/third_party/WebKit/Source/core/page/Page.cpp b/third_party/WebKit/Source/core/page/Page.cpp index db2f708..a282c4c 100644 --- a/third_party/WebKit/Source/core/page/Page.cpp +++ b/third_party/WebKit/Source/core/page/Page.cpp
@@ -274,13 +274,6 @@ return m_pluginData.get(); } -static Frame* incrementFrame(Frame* curr, bool forward, bool wrapFlag) -{ - return forward - ? curr->tree().traverseNextWithWrap(wrapFlag) - : curr->tree().traversePreviousWithWrap(wrapFlag); -} - void Page::unmarkAllTextMatches() { if (!mainFrame()) @@ -290,7 +283,7 @@ do { if (frame->isLocalFrame()) toLocalFrame(frame)->document()->markers().removeMarkers(DocumentMarker::TextMatch); - frame = incrementFrame(frame, true, false); + frame = frame->tree().traverseNextWithWrap(false); } while (frame); }
diff --git a/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.cpp b/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.cpp index 04079d8..e226295a 100644 --- a/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.cpp +++ b/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.cpp
@@ -114,8 +114,6 @@ if (context.paintOffset == LayoutPoint() || !shouldCreatePaintOffsetTranslationNode) return nullptr; - TransformationMatrix matrix; - matrix.translate(context.paintOffset.x(), context.paintOffset.y()); RefPtr<TransformPaintPropertyNode> newTransformNodeForPaintOffsetTranslation = TransformPaintPropertyNode::create( TransformationMatrix().translate(context.paintOffset.x(), context.paintOffset.y()), FloatPoint3D(), context.currentTransform);
diff --git a/third_party/WebKit/Source/core/svg/SVGAnimatedInteger.cpp b/third_party/WebKit/Source/core/svg/SVGAnimatedInteger.cpp index 67d0bc4..eaa4e71 100644 --- a/third_party/WebKit/Source/core/svg/SVGAnimatedInteger.cpp +++ b/third_party/WebKit/Source/core/svg/SVGAnimatedInteger.cpp
@@ -46,11 +46,6 @@ SVGAnimatedProperty<SVGInteger>::synchronizeAttribute(); } -void SVGAnimatedInteger::setParentOptionalInteger(SVGAnimatedIntegerOptionalInteger* numberOptionalInteger) -{ - m_parentIntegerOptionalInteger = numberOptionalInteger; -} - DEFINE_TRACE(SVGAnimatedInteger) { visitor->trace(m_parentIntegerOptionalInteger);
diff --git a/third_party/WebKit/Source/core/svg/SVGAnimatedInteger.h b/third_party/WebKit/Source/core/svg/SVGAnimatedInteger.h index e985293..12d276b 100644 --- a/third_party/WebKit/Source/core/svg/SVGAnimatedInteger.h +++ b/third_party/WebKit/Source/core/svg/SVGAnimatedInteger.h
@@ -50,7 +50,10 @@ void synchronizeAttribute() override; - void setParentOptionalInteger(SVGAnimatedIntegerOptionalInteger* numberOptionalInteger); + void setParentOptionalInteger(SVGAnimatedIntegerOptionalInteger* numberOptionalInteger) + { + m_parentIntegerOptionalInteger = numberOptionalInteger; + } DECLARE_VIRTUAL_TRACE();
diff --git a/third_party/WebKit/Source/core/svg/SVGAnimatedNumber.cpp b/third_party/WebKit/Source/core/svg/SVGAnimatedNumber.cpp index 255704c..0258283 100644 --- a/third_party/WebKit/Source/core/svg/SVGAnimatedNumber.cpp +++ b/third_party/WebKit/Source/core/svg/SVGAnimatedNumber.cpp
@@ -47,11 +47,6 @@ SVGAnimatedProperty<SVGNumber>::synchronizeAttribute(); } -void SVGAnimatedNumber::setParentOptionalNumber(SVGAnimatedNumberOptionalNumber* numberOptionalNumber) -{ - m_parentNumberOptionalNumber = numberOptionalNumber; -} - DEFINE_TRACE(SVGAnimatedNumber) { visitor->trace(m_parentNumberOptionalNumber);
diff --git a/third_party/WebKit/Source/core/svg/SVGAnimatedNumber.h b/third_party/WebKit/Source/core/svg/SVGAnimatedNumber.h index 13fbb32..500de2a 100644 --- a/third_party/WebKit/Source/core/svg/SVGAnimatedNumber.h +++ b/third_party/WebKit/Source/core/svg/SVGAnimatedNumber.h
@@ -50,7 +50,10 @@ void synchronizeAttribute() override; - void setParentOptionalNumber(SVGAnimatedNumberOptionalNumber*); + void setParentOptionalNumber(SVGAnimatedNumberOptionalNumber* numberOptionalNumber) + { + m_parentNumberOptionalNumber = numberOptionalNumber; + } DECLARE_VIRTUAL_TRACE();
diff --git a/third_party/WebKit/Source/core/svg/SVGElement.cpp b/third_party/WebKit/Source/core/svg/SVGElement.cpp index 5b8399e..5024d32 100644 --- a/third_party/WebKit/Source/core/svg/SVGElement.cpp +++ b/third_party/WebKit/Source/core/svg/SVGElement.cpp
@@ -157,17 +157,6 @@ return m_SVGRareData.get(); } -bool SVGElement::hasSVGRareData() const -{ - return m_SVGRareData; -} - -SVGElementRareData* SVGElement::svgRareData() const -{ - ASSERT(m_SVGRareData); - return m_SVGRareData.get(); -} - bool SVGElement::isOutermostSVGSVGElement() const { if (!isSVGSVGElement(*this)) @@ -692,11 +681,6 @@ m_attributeToPropertyMap.set(attributeName, property.release()); } -SVGAnimatedString* SVGElement::className() -{ - return m_className.get(); -} - PassRefPtrWillBeRawPtr<SVGAnimatedPropertyBase> SVGElement::propertyFromAttribute(const QualifiedName& attributeName) { AttributeToPropertyMap::iterator it = m_attributeToPropertyMap.find<SVGAttributeHashTranslator>(attributeName);
diff --git a/third_party/WebKit/Source/core/svg/SVGElement.h b/third_party/WebKit/Source/core/svg/SVGElement.h index 19f46717..3a9f8f9 100644 --- a/third_party/WebKit/Source/core/svg/SVGElement.h +++ b/third_party/WebKit/Source/core/svg/SVGElement.h
@@ -146,7 +146,7 @@ void addToPropertyMap(PassRefPtrWillBeRawPtr<SVGAnimatedPropertyBase>); - SVGAnimatedString* className(); + SVGAnimatedString* className() { return m_className.get(); } bool inUseShadowTree() const; @@ -208,8 +208,12 @@ virtual bool selfHasRelativeLengths() const { return false; } SVGElementRareData* ensureSVGRareData(); - bool hasSVGRareData() const; - SVGElementRareData* svgRareData() const; + inline bool hasSVGRareData() const { return m_SVGRareData; } + inline SVGElementRareData* svgRareData() const + { + ASSERT(m_SVGRareData); + return m_SVGRareData.get(); + } // SVGFitToViewBox::parseAttribute uses reportAttributeParsingError. friend class SVGFitToViewBox;
diff --git a/third_party/WebKit/Source/core/svg/SVGElementRareData.cpp b/third_party/WebKit/Source/core/svg/SVGElementRareData.cpp index f9edbfd..e3119af 100644 --- a/third_party/WebKit/Source/core/svg/SVGElementRareData.cpp +++ b/third_party/WebKit/Source/core/svg/SVGElementRareData.cpp
@@ -13,26 +13,6 @@ namespace blink { -SVGCursorElement* SVGElementRareData::cursorElement() const -{ - return m_cursorElement; -} - -void SVGElementRareData::setCursorElement(SVGCursorElement* cursorElement) -{ - m_cursorElement = cursorElement; -} - -CSSCursorImageValue* SVGElementRareData::cursorImageValue() const -{ - return m_cursorImageValue; -} - -void SVGElementRareData::setCursorImageValue(CSSCursorImageValue* cursorImageValue) -{ - m_cursorImageValue = cursorImageValue; -} - MutableStylePropertySet* SVGElementRareData::ensureAnimatedSMILStyleProperties() { if (!m_animatedSMILStyleProperties)
diff --git a/third_party/WebKit/Source/core/svg/SVGElementRareData.h b/third_party/WebKit/Source/core/svg/SVGElementRareData.h index 74a5e82..8c3a1ac 100644 --- a/third_party/WebKit/Source/core/svg/SVGElementRareData.h +++ b/third_party/WebKit/Source/core/svg/SVGElementRareData.h
@@ -60,14 +60,14 @@ bool instanceUpdatesBlocked() const { return m_instancesUpdatesBlocked; } void setInstanceUpdatesBlocked(bool value) { m_instancesUpdatesBlocked = value; } - SVGCursorElement* cursorElement() const; - void setCursorElement(SVGCursorElement*); + SVGCursorElement* cursorElement() const { return m_cursorElement; } + void setCursorElement(SVGCursorElement* cursorElement) { m_cursorElement = cursorElement; } SVGElement* correspondingElement() const { return m_correspondingElement.get(); } void setCorrespondingElement(SVGElement* correspondingElement) { m_correspondingElement = correspondingElement; } - CSSCursorImageValue* cursorImageValue() const; - void setCursorImageValue(CSSCursorImageValue*); + CSSCursorImageValue* cursorImageValue() const { return m_cursorImageValue; } + void setCursorImageValue(CSSCursorImageValue* cursorImageValue) { m_cursorImageValue = cursorImageValue; } MutableStylePropertySet* animatedSMILStyleProperties() const { return m_animatedSMILStyleProperties.get(); } MutableStylePropertySet* ensureAnimatedSMILStyleProperties();
diff --git a/third_party/WebKit/Source/core/svg/SVGSVGElement.cpp b/third_party/WebKit/Source/core/svg/SVGSVGElement.cpp index 796eb9f..ebcd2f6c 100644 --- a/third_party/WebKit/Source/core/svg/SVGSVGElement.cpp +++ b/third_party/WebKit/Source/core/svg/SVGSVGElement.cpp
@@ -559,11 +559,6 @@ SVGGraphicsElement::removedFrom(rootParent); } -SMILTimeContainer* SVGSVGElement::timeContainer() const -{ - return m_timeContainer.get(); -} - void SVGSVGElement::pauseAnimations() { ASSERT(RuntimeEnabledFeatures::smilEnabled());
diff --git a/third_party/WebKit/Source/core/svg/SVGSVGElement.h b/third_party/WebKit/Source/core/svg/SVGSVGElement.h index 5160293..7b90b426 100644 --- a/third_party/WebKit/Source/core/svg/SVGSVGElement.h +++ b/third_party/WebKit/Source/core/svg/SVGSVGElement.h
@@ -72,7 +72,7 @@ void setCurrentTranslate(const FloatPoint&); PassRefPtrWillBeRawPtr<SVGPointTearOff> currentTranslateFromJavascript(); - SMILTimeContainer* timeContainer() const; + SMILTimeContainer* timeContainer() const { return m_timeContainer.get(); } void pauseAnimations(); void unpauseAnimations();
diff --git a/third_party/WebKit/Source/core/svg/SVGScriptElement.cpp b/third_party/WebKit/Source/core/svg/SVGScriptElement.cpp index e7f5a6a..af89b97 100644 --- a/third_party/WebKit/Source/core/svg/SVGScriptElement.cpp +++ b/third_party/WebKit/Source/core/svg/SVGScriptElement.cpp
@@ -39,11 +39,6 @@ { } -ScriptLoader* SVGScriptElement::loader() const -{ - return m_loader.get(); -} - PassRefPtrWillBeRawPtr<SVGScriptElement> SVGScriptElement::create(Document& document, bool insertedByParser) { return adoptRefWillBeNoop(new SVGScriptElement(document, insertedByParser, false));
diff --git a/third_party/WebKit/Source/core/svg/SVGScriptElement.h b/third_party/WebKit/Source/core/svg/SVGScriptElement.h index b623adbb..1f8a64b 100644 --- a/third_party/WebKit/Source/core/svg/SVGScriptElement.h +++ b/third_party/WebKit/Source/core/svg/SVGScriptElement.h
@@ -42,7 +42,7 @@ public: static PassRefPtrWillBeRawPtr<SVGScriptElement> create(Document&, bool wasInsertedByParser); - ScriptLoader* loader() const; + ScriptLoader* loader() const { return m_loader.get(); } #if ENABLE(ASSERT) bool isAnimatableAttribute(const QualifiedName&) const override;
diff --git a/third_party/WebKit/Source/core/svg/SVGURIReference.h b/third_party/WebKit/Source/core/svg/SVGURIReference.h index 7174a3b..b676bd3 100644 --- a/third_party/WebKit/Source/core/svg/SVGURIReference.h +++ b/third_party/WebKit/Source/core/svg/SVGURIReference.h
@@ -41,6 +41,11 @@ static inline bool isExternalURIReference(const String& uri, const Document& document) { + // Fragment-only URIs are always internal if the baseURL is same as the document URL. + // This is common case, so check that first to avoid resolving URL (which is relatively expensive). See crbug.com/557979 + if (document.baseURL() == document.url() && uri.startsWith('#')) + return false; + // If the URI matches our documents URL, we're dealing with a local reference. KURL url = document.completeURL(uri); return !equalIgnoringFragmentIdentifier(url, document.url());
diff --git a/third_party/WebKit/Source/core/svg/animation/SVGSMILElement.cpp b/third_party/WebKit/Source/core/svg/animation/SVGSMILElement.cpp index e06318d..fd7c8a4 100644 --- a/third_party/WebKit/Source/core/svg/animation/SVGSMILElement.cpp +++ b/third_party/WebKit/Source/core/svg/animation/SVGSMILElement.cpp
@@ -177,11 +177,6 @@ { } -ConditionEventListener* SVGSMILElement::Condition::eventListener() const -{ - return m_eventListener.get(); -} - SVGSMILElement::SVGSMILElement(const QualifiedName& tagName, Document& doc) : SVGElement(tagName, doc) , SVGTests(this) @@ -1296,11 +1291,6 @@ addEndTime(elapsed, elapsed + condition->offset()); } -SMILTimeContainer* SVGSMILElement::timeContainer() const -{ - return m_timeContainer.get(); -} - void SVGSMILElement::beginByLinkActivation() { SMILTime elapsed = this->elapsed();
diff --git a/third_party/WebKit/Source/core/svg/animation/SVGSMILElement.h b/third_party/WebKit/Source/core/svg/animation/SVGSMILElement.h index 9da262ae..6921045 100644 --- a/third_party/WebKit/Source/core/svg/animation/SVGSMILElement.h +++ b/third_party/WebKit/Source/core/svg/animation/SVGSMILElement.h
@@ -59,7 +59,7 @@ virtual bool hasValidAttributeName(); virtual void animationAttributeChanged() = 0; - SMILTimeContainer* timeContainer() const; + SMILTimeContainer* timeContainer() const { return m_timeContainer.get(); } SVGElement* targetElement() const { return m_targetElement; } const QualifiedName& attributeName() const { return m_attributeName; } @@ -199,7 +199,7 @@ int repeat() const { return m_repeat; } SVGSMILElement* syncBase() const { return m_syncBase.get(); } void setSyncBase(SVGSMILElement* element) { m_syncBase = element; } - ConditionEventListener* eventListener() const; + ConditionEventListener* eventListener() const { return m_eventListener.get(); } void setEventListener(PassRefPtrWillBeRawPtr<ConditionEventListener>); private:
diff --git a/third_party/WebKit/Source/core/workers/WorkerGlobalScope.cpp b/third_party/WebKit/Source/core/workers/WorkerGlobalScope.cpp index 18b8662..4a34b6a 100644 --- a/third_party/WebKit/Source/core/workers/WorkerGlobalScope.cpp +++ b/third_party/WebKit/Source/core/workers/WorkerGlobalScope.cpp
@@ -157,16 +157,6 @@ return &m_timers; } -WorkerInspectorController* WorkerGlobalScope::workerInspectorController() const -{ - return m_workerInspectorController.get(); -} - -WorkerClients* WorkerGlobalScope::clients() const -{ - return m_workerClients.get(); -} - WorkerLocation* WorkerGlobalScope::location() const { if (!m_location)
diff --git a/third_party/WebKit/Source/core/workers/WorkerGlobalScope.h b/third_party/WebKit/Source/core/workers/WorkerGlobalScope.h index bcf1ccc..51da5e3 100644 --- a/third_party/WebKit/Source/core/workers/WorkerGlobalScope.h +++ b/third_party/WebKit/Source/core/workers/WorkerGlobalScope.h
@@ -121,13 +121,13 @@ double timerAlignmentInterval() const final; DOMTimerCoordinator* timers() final; - WorkerInspectorController* workerInspectorController() const; + WorkerInspectorController* workerInspectorController() { return m_workerInspectorController.get(); } bool isClosing() { return m_closing; } double timeOrigin() const { return m_timeOrigin; } - WorkerClients* clients() const; + WorkerClients* clients() { return m_workerClients.get(); } using SecurityContext::securityOrigin; using SecurityContext::contentSecurityPolicy;
diff --git a/third_party/WebKit/Source/core/xml/XPathParser.cpp b/third_party/WebKit/Source/core/xml/XPathParser.cpp index fabfb94..d3a4d72 100644 --- a/third_party/WebKit/Source/core/xml/XPathParser.cpp +++ b/third_party/WebKit/Source/core/xml/XPathParser.cpp
@@ -116,11 +116,6 @@ return nodeTypeNames.contains(name); } -XPathNSResolver* Parser::resolver() const -{ - return m_resolver; -} - // Returns whether the current token can possibly be a binary operator, given // the previous token. Necessary to disambiguate some of the operators // (* (multiply), div, and, or, mod) in the [32] Operator rule
diff --git a/third_party/WebKit/Source/core/xml/XPathParser.h b/third_party/WebKit/Source/core/xml/XPathParser.h index f6fd5ef..7e9228a 100644 --- a/third_party/WebKit/Source/core/xml/XPathParser.h +++ b/third_party/WebKit/Source/core/xml/XPathParser.h
@@ -66,7 +66,7 @@ Parser(); ~Parser(); - XPathNSResolver* resolver() const; + XPathNSResolver* resolver() const { return m_resolver.get(); } bool expandQName(const String& qName, AtomicString& localName, AtomicString& namespaceURI); Expression* parseStatement(const String& statement, XPathNSResolver*, ExceptionState&);
diff --git a/third_party/WebKit/Source/core/xml/parser/XMLDocumentParserScope.cpp b/third_party/WebKit/Source/core/xml/parser/XMLDocumentParserScope.cpp index 0cd8494..90f0875 100644 --- a/third_party/WebKit/Source/core/xml/parser/XMLDocumentParserScope.cpp +++ b/third_party/WebKit/Source/core/xml/parser/XMLDocumentParserScope.cpp
@@ -26,8 +26,6 @@ #include "config.h" #include "core/xml/parser/XMLDocumentParserScope.h" -#include "core/dom/Document.h" - namespace blink { Document* XMLDocumentParserScope::currentDocument = 0;
diff --git a/third_party/WebKit/Source/devtools/BUILD.gn b/third_party/WebKit/Source/devtools/BUILD.gn index c50d3202b..81290148 100644 --- a/third_party/WebKit/Source/devtools/BUILD.gn +++ b/third_party/WebKit/Source/devtools/BUILD.gn
@@ -75,13 +75,13 @@ group("devtools_frontend_resources") { public_deps = [ + ":build_applications", ":copy_compatibility_scripts", - ":copy_inspector_images", ":copy_emulated_devices_images", + ":copy_inspector_images", ":devtools_extension_api", ":frontend_protocol_sources", ":supported_css_properties", - ":build_applications", ] if (!debug_devtools) { @@ -265,8 +265,8 @@ ] deps = [ - ":supported_css_properties", ":frontend_protocol_sources", + ":supported_css_properties", ] if (debug_devtools) { @@ -324,9 +324,9 @@ # Debug: copy non-module directories and core into resources_out_dir as-is. group("copy_debug_non_modules") { public_deps = [ - ":copy_runtime_core", ":copy_acorn_js_files", ":copy_codemirror_files", + ":copy_runtime_core", ] }
diff --git a/third_party/WebKit/Source/devtools/OWNERS b/third_party/WebKit/Source/devtools/OWNERS index 77d375746..69f3c58c 100644 --- a/third_party/WebKit/Source/devtools/OWNERS +++ b/third_party/WebKit/Source/devtools/OWNERS
@@ -1,5 +1,5 @@ dgozman@chromium.org pfeldman@chromium.org yurys@chromium.org -per-file devtools.gyp*=sergeyv@chromium.org -per-file BUILD.gn=sergeyv@chromium.org +per-file devtools.gyp*=* +per-file BUILD.gn=*
diff --git a/third_party/WebKit/Source/devtools/front_end/OWNERS b/third_party/WebKit/Source/devtools/front_end/OWNERS index d8ffb77a..87277be 100644 --- a/third_party/WebKit/Source/devtools/front_end/OWNERS +++ b/third_party/WebKit/Source/devtools/front_end/OWNERS
@@ -4,4 +4,4 @@ lushnikov@chromium.org pfeldman@chromium.org sergeyv@chromium.org -yurys@chromium.org +samli@chromium.org
diff --git a/third_party/WebKit/Source/devtools/front_end/components_lazy/CookiesTable.js b/third_party/WebKit/Source/devtools/front_end/components_lazy/CookiesTable.js index 3619ffa..30aef63 100644 --- a/third_party/WebKit/Source/devtools/front_end/components_lazy/CookiesTable.js +++ b/third_party/WebKit/Source/devtools/front_end/components_lazy/CookiesTable.js
@@ -30,14 +30,14 @@ /** * @constructor - * @extends {WebInspector.VBox} + * @extends {WebInspector.DataGridContainerWidget} * @param {boolean} expandable * @param {function()=} refreshCallback * @param {function()=} selectedCallback */ WebInspector.CookiesTable = function(expandable, refreshCallback, selectedCallback) { - WebInspector.VBox.call(this); + WebInspector.DataGridContainerWidget.call(this); var readOnly = expandable; this._refreshCallback = refreshCallback; @@ -67,7 +67,7 @@ this._nextSelectedCookie = /** @type {?WebInspector.Cookie} */ (null); - this._dataGrid.asWidget().show(this.element); + this.appendDataGrid(this._dataGrid); this._data = []; } @@ -285,5 +285,5 @@ this._refreshCallback(); }, - __proto__: WebInspector.VBox.prototype + __proto__: WebInspector.DataGridContainerWidget.prototype }
diff --git a/third_party/WebKit/Source/devtools/front_end/emulation/DeviceModeModel.js b/third_party/WebKit/Source/devtools/front_end/emulation/DeviceModeModel.js index deca907..be06593c7 100644 --- a/third_party/WebKit/Source/devtools/front_end/emulation/DeviceModeModel.js +++ b/third_party/WebKit/Source/devtools/front_end/emulation/DeviceModeModel.js
@@ -25,8 +25,8 @@ this._widthSetting.addChangeListener(this._widthSettingChanged, this); this._heightSetting = WebInspector.settings.createSetting("emulation.deviceHeight", 700); this._heightSetting.addChangeListener(this._heightSettingChanged, this); - this._mobileSetting = WebInspector.settings.createSetting("emulation.deviceMobile", true); - this._mobileSetting.addChangeListener(this._mobileSettingChanged, this); + this._uaSetting = WebInspector.settings.createSetting("emulation.deviceUA", WebInspector.DeviceModeModel.UA.Mobile); + this._uaSetting.addChangeListener(this._uaSettingChanged, this); this._deviceScaleFactorSetting = WebInspector.settings.createSetting("emulation.deviceScaleFactor", 0); this._deviceScaleFactorSetting.addChangeListener(this._deviceScaleFactorSettingChanged, this); @@ -57,6 +57,13 @@ Device: "Device" } +/** @enum {string} */ +WebInspector.DeviceModeModel.UA = { + Mobile: "Mobile", + Desktop: "Desktop", + DesktopTouch: "DesktopTouch" +} + WebInspector.DeviceModeModel.MaxDeviceSize = 10000; /** @@ -215,9 +222,9 @@ /** * @return {!WebInspector.Setting} */ - mobileSetting: function() + uaSetting: function() { - return this._mobileSetting; + return this._uaSetting; }, /** @@ -234,7 +241,7 @@ defaultDeviceScaleFactor: function() { if (this._type === WebInspector.DeviceModeModel.Type.Responsive) - return this._mobileSetting.get() ? WebInspector.DeviceModeModel._defaultMobileScaleFactor : this._currentDeviceScaleFactor; + return this._uaSetting.get() === WebInspector.DeviceModeModel.UA.Mobile ? WebInspector.DeviceModeModel._defaultMobileScaleFactor : this._currentDeviceScaleFactor; else if (this._type === WebInspector.DeviceModeModel.Type.Device) return this._device.deviceScaleFactor; else @@ -247,7 +254,7 @@ this._scaleSetting.set(0); this._widthSetting.set(400); this._heightSetting.set(700); - this._mobileSetting.set(true); + this._uaSetting.set(WebInspector.DeviceModeModel.UA.Mobile); }, /** @@ -279,7 +286,7 @@ else if (this._type === WebInspector.DeviceModeModel.Type.None) this._applyTouch(false, false); else if (this._type === WebInspector.DeviceModeModel.Type.Responsive) - this._applyTouch(this._mobileSetting.get(), this._mobileSetting.get()); + this._applyTouch(this._uaSetting.get() !== WebInspector.DeviceModeModel.UA.Desktop, this._uaSetting.get() === WebInspector.DeviceModeModel.UA.Mobile); }, /** @@ -307,7 +314,7 @@ this._calculateAndEmulate(false); }, - _mobileSettingChanged: function() + _uaSettingChanged: function() { this._calculateAndEmulate(true); }, @@ -340,10 +347,11 @@ var screenWidth = this._widthSetting.get(); var screenHeight = this._heightSetting.get(); var scale = this._calculateScale(screenWidth, screenHeight); - var mobile = this._mobileSetting.get(); - this._applyDeviceMetrics(new Size(screenWidth, screenHeight), new Insets(0, 0, 0, 0), scale, this._deviceScaleFactorSetting.get() || WebInspector.DeviceModeModel._defaultMobileScaleFactor, mobile, resetScrollAndPageScale); + var mobile = this._uaSetting.get() === WebInspector.DeviceModeModel.UA.Mobile; + var defaultDeviceScaleFactor = mobile ? WebInspector.DeviceModeModel._defaultMobileScaleFactor : 0; + this._applyDeviceMetrics(new Size(screenWidth, screenHeight), new Insets(0, 0, 0, 0), scale, this._deviceScaleFactorSetting.get() || defaultDeviceScaleFactor, mobile, resetScrollAndPageScale); this._applyUserAgent(mobile ? WebInspector.DeviceModeModel._defaultMobileUserAgent : ""); - this._applyTouch(mobile, mobile); + this._applyTouch(this._uaSetting.get() !== WebInspector.DeviceModeModel.UA.Desktop, mobile); this._applyScreenOrientation(screenHeight >= screenWidth ? "portraitPrimary" : "landscapePrimary"); } this._updateCallback.call(null); @@ -387,6 +395,8 @@ */ _applyDeviceMetrics: function(screenSize, insets, scale, deviceScaleFactor, mobile, resetScrollAndPageScale) { + screenSize.width = Math.max(1, Math.floor(screenSize.width)); + screenSize.height = Math.max(1, Math.floor(screenSize.height)); var pageWidth = screenSize.width - insets.left - insets.right; var pageHeight = screenSize.height - insets.top - insets.bottom; var positionX = insets.left;
diff --git a/third_party/WebKit/Source/devtools/front_end/emulation/DeviceModeView.js b/third_party/WebKit/Source/devtools/front_end/emulation/DeviceModeView.js index 70a0e53..db9895a 100644 --- a/third_party/WebKit/Source/devtools/front_end/emulation/DeviceModeView.js +++ b/third_party/WebKit/Source/devtools/front_end/emulation/DeviceModeView.js
@@ -348,7 +348,7 @@ */ _appendMenuItems: function(contextMenu) { - var disabled = this._model.type() === WebInspector.DeviceModeModel.Type.None; + var zoomDisabled = this._model.type() === WebInspector.DeviceModeModel.Type.None; var zoomSubmenu = contextMenu.appendSubMenuItem(WebInspector.UIString("Zoom"), false); var scaleSetting = this._model.scaleSetting(); appendScaleItem(WebInspector.UIString("Fit"), 0); @@ -365,31 +365,41 @@ */ function appendScaleItem(title, value) { - zoomSubmenu.appendCheckboxItem(title, scaleSetting.set.bind(scaleSetting, value), scaleSetting.get() === value, disabled); + zoomSubmenu.appendCheckboxItem(title, scaleSetting.set.bind(scaleSetting, value), scaleSetting.get() === value, zoomDisabled); } - disabled = this._model.type() !== WebInspector.DeviceModeModel.Type.Responsive; - var mobileSetting = this._model.mobileSetting(); - var mobileSubmenu = contextMenu.appendSubMenuItem(WebInspector.UIString("User agent type"), false); - mobileSubmenu.appendCheckboxItem(WebInspector.UIString("Mobile"), mobileSetting.set.bind(mobileSetting, true), mobileSetting.get(), disabled); - mobileSubmenu.appendCheckboxItem(WebInspector.UIString("Desktop"), mobileSetting.set.bind(mobileSetting, false), !mobileSetting.get(), disabled); + var uaDisabled = this._model.type() !== WebInspector.DeviceModeModel.Type.Responsive; + var uaSetting = this._model.uaSetting(); + var uaSubmenu = contextMenu.appendSubMenuItem(WebInspector.UIString("User agent type"), false); + appendUAItem(WebInspector.UIString("Mobile"), WebInspector.DeviceModeModel.UA.Mobile); + appendUAItem(WebInspector.UIString("Desktop"), WebInspector.DeviceModeModel.UA.Desktop); + appendUAItem(WebInspector.UIString("Desktop with touch"), WebInspector.DeviceModeModel.UA.DesktopTouch); - disabled = this._model.type() !== WebInspector.DeviceModeModel.Type.Responsive; - var dprSubmenu = contextMenu.appendSubMenuItem(WebInspector.UIString("Device pixel ratio"), false); + /** + * @param {string} title + * @param {!WebInspector.DeviceModeModel.UA} value + */ + function appendUAItem(title, value) + { + uaSubmenu.appendCheckboxItem(title, uaSetting.set.bind(uaSetting, value), uaSetting.get() === value, uaDisabled); + } + + var deviceScaleFactorDisabled = this._model.type() !== WebInspector.DeviceModeModel.Type.Responsive; + var deviceScaleFactorSubmenu = contextMenu.appendSubMenuItem(WebInspector.UIString("Device pixel ratio"), false); var deviceScaleFactorSetting = this._model.deviceScaleFactorSetting(); - appendScaleFactorItem(WebInspector.UIString("Default: %f", this._model.defaultDeviceScaleFactor()), 0); - dprSubmenu.appendSeparator(); - appendScaleFactorItem(WebInspector.UIString("1"), 1); - appendScaleFactorItem(WebInspector.UIString("2"), 2); - appendScaleFactorItem(WebInspector.UIString("3"), 3); + appendDeviceScaleFactorItem(WebInspector.UIString("Default: %f", this._model.defaultDeviceScaleFactor()), 0); + deviceScaleFactorSubmenu.appendSeparator(); + appendDeviceScaleFactorItem(WebInspector.UIString("1"), 1); + appendDeviceScaleFactorItem(WebInspector.UIString("2"), 2); + appendDeviceScaleFactorItem(WebInspector.UIString("3"), 3); /** * @param {string} title * @param {number} value */ - function appendScaleFactorItem(title, value) + function appendDeviceScaleFactorItem(title, value) { - dprSubmenu.appendCheckboxItem(title, deviceScaleFactorSetting.set.bind(deviceScaleFactorSetting, value), deviceScaleFactorSetting.get() === value, disabled); + deviceScaleFactorSubmenu.appendCheckboxItem(title, deviceScaleFactorSetting.set.bind(deviceScaleFactorSetting, value), deviceScaleFactorSetting.get() === value, deviceScaleFactorDisabled); } contextMenu.appendItem(WebInspector.UIString("Reset to defaults"), this._model.reset.bind(this._model), this._model.type() !== WebInspector.DeviceModeModel.Type.Responsive); @@ -637,7 +647,8 @@ } } - var showDeviceScale = !!this._model.deviceScaleFactorSetting().get() || this._model.type() === WebInspector.DeviceModeModel.Type.Device; + var showDeviceScale = this._model.type() !== WebInspector.DeviceModeModel.Type.None && + (!!this._model.deviceScaleFactorSetting().get() || this._model.type() === WebInspector.DeviceModeModel.Type.Device); if (showDeviceScale !== this._cachedShowDeviceScale) { this._deviceScaleFactorItem.setVisible(showDeviceScale); this._cachedShowDeviceScale = showDeviceScale; @@ -687,12 +698,14 @@ } if (updatePersistence) { - this._persistenceSetting.set({ - type: this._cachedModelType, - device: this._cachedModelDevice ? this._cachedModelDevice.title : "", - orientation: this._cachedModelMode ? this._cachedModelMode.orientation : "", - mode: this._cachedModelMode ? this._cachedModelMode.title : "" - }); + var value = this._persistenceSetting.get(); + value.type = this._cachedModelType; + if (this._cachedModelDevice) { + value.device = this._cachedModelDevice.title; + value.orientation = this._cachedModelMode ? this._cachedModelMode.orientation : ""; + value.mode = this._cachedModelMode ? this._cachedModelMode.title : ""; + } + this._persistenceSetting.set(value); } }, @@ -702,38 +715,38 @@ return; this._restored = true; - var type = this._persistenceSetting.get().type; - if (type === WebInspector.DeviceModeModel.Type.Responsive) { - this._model.emulate(WebInspector.DeviceModeModel.Type.Responsive, null, null); - } else if (type === WebInspector.DeviceModeModel.Type.Device) { - var device = null; - for (var i = 0; i < this._deviceSelect.options.length; ++i) { - if (this._deviceSelect.options[i].device && this._deviceSelect.options[i].device.title === this._persistenceSetting.get().device) - device = this._deviceSelect.options[i].device; - } - if (device) { - var mode = null; - for (var i = 0; i < device.modes.length; ++i) { - if (device.modes[i].orientation === this._persistenceSetting.get().orientation && device.modes[i].title === this._persistenceSetting.get().mode) - mode = device.modes[i]; - } - this._model.emulate(WebInspector.DeviceModeModel.Type.Device, device, mode || device.modes[0]); - } else { - this._model.emulate(WebInspector.DeviceModeModel.Type.None, null, null); + + for (var i = 0; i < this._deviceSelect.options.length; ++i) { + if (this._deviceSelect.options[i].device && this._deviceSelect.options[i].device.title === this._persistenceSetting.get().device) + this._lastDevice = this._deviceSelect.options[i].device; + } + if (this._lastDevice) { + for (var i = 0; i < this._lastDevice.modes.length; ++i) { + if (this._lastDevice.modes[i].orientation === this._persistenceSetting.get().orientation && this._lastDevice.modes[i].title === this._persistenceSetting.get().mode) + this._lastMode.set(this._lastDevice, this._lastDevice.modes[i]); } } else { this._model.emulate(WebInspector.DeviceModeModel.Type.None, null, null); } + + this._applyType(/** @type {!WebInspector.DeviceModeModel.Type} */ (this._persistenceSetting.get().type)); }, _toggleType: function() { - var previousType = this._model.type() === WebInspector.DeviceModeModel.Type.None ? (this._previousModelType || WebInspector.DeviceModeModel.Type.Responsive) : WebInspector.DeviceModeModel.Type.None; - if (previousType === WebInspector.DeviceModeModel.Type.Responsive) + this._applyType(this._model.type() === WebInspector.DeviceModeModel.Type.None ? (this._previousModelType || WebInspector.DeviceModeModel.Type.Responsive) : WebInspector.DeviceModeModel.Type.None); + }, + + /** + * @param {!WebInspector.DeviceModeModel.Type} type + */ + _applyType: function(type) + { + if (type === WebInspector.DeviceModeModel.Type.Responsive) this._responsiveButtonClick(); - else if (previousType === WebInspector.DeviceModeModel.Type.Device) + else if (type === WebInspector.DeviceModeModel.Type.Device) this._deviceButtonClick(); - else if (previousType === WebInspector.DeviceModeModel.Type.None) + else this._noneButtonClick(); } }
diff --git a/third_party/WebKit/Source/devtools/front_end/emulation/DevicesSettingsTab.js b/third_party/WebKit/Source/devtools/front_end/emulation/DevicesSettingsTab.js index 26ba0e8..015a8e74 100644 --- a/third_party/WebKit/Source/devtools/front_end/emulation/DevicesSettingsTab.js +++ b/third_party/WebKit/Source/devtools/front_end/emulation/DevicesSettingsTab.js
@@ -104,7 +104,6 @@ checkbox.checked = device.show(); element.createChild("div", "devices-list-title").textContent = device.title; element.addEventListener("click", onItemClicked.bind(this), false); - element.classList.toggle("device-list-item-show", device.show()); return element; /** @@ -117,7 +116,6 @@ device.setShow(show); this._muteAndSaveDeviceList(editable); checkbox.checked = show; - element.classList.toggle("device-list-item-show", show); event.consume(); } },
diff --git a/third_party/WebKit/Source/devtools/front_end/emulation/devicesSettingsTab.css b/third_party/WebKit/Source/devtools/front_end/emulation/devicesSettingsTab.css index e0115c10..eb3cf1d7 100644 --- a/third_party/WebKit/Source/devtools/front_end/emulation/devicesSettingsTab.css +++ b/third_party/WebKit/Source/devtools/front_end/emulation/devicesSettingsTab.css
@@ -57,10 +57,6 @@ text-overflow: ellipsis; flex: auto; -webkit-user-select: none; - color: #aaa; -} - -.device-list-item-show .devices-list-title { color: #222; }
diff --git a/third_party/WebKit/Source/devtools/front_end/host/ResourceLoader.js b/third_party/WebKit/Source/devtools/front_end/host/ResourceLoader.js index 4f90cae8..501eb38 100644 --- a/third_party/WebKit/Source/devtools/front_end/host/ResourceLoader.js +++ b/third_party/WebKit/Source/devtools/front_end/host/ResourceLoader.js
@@ -57,32 +57,6 @@ } /** - * @type {string} - */ -WebInspector.ResourceLoader.targetUserAgent = ""; - -/** - * @param {string} url - * @param {?Object.<string, string>} headers - * @param {function(number, !Object.<string, string>, string)} callback - */ -WebInspector.ResourceLoader.loadUsingTargetUA = function(url, headers, callback) -{ - if (!WebInspector.ResourceLoader.targetUserAgent) { - WebInspector.ResourceLoader.load(url, headers, callback); - return; - } - - var headersWithUA = {}; - if (headers) { - for (var header in headers) - headersWithUA[header] = headers[header]; - } - headersWithUA["User-Agent"] = WebInspector.ResourceLoader.targetUserAgent; - WebInspector.ResourceLoader.load(url, headersWithUA, callback); -} - -/** * @param {string} url * @param {?Object.<string, string>} headers * @param {!WebInspector.OutputStream} stream
diff --git a/third_party/WebKit/Source/devtools/front_end/inspectorStyle.css b/third_party/WebKit/Source/devtools/front_end/inspectorStyle.css index 4beee86..08a6006 100644 --- a/third_party/WebKit/Source/devtools/front_end/inspectorStyle.css +++ b/third_party/WebKit/Source/devtools/front_end/inspectorStyle.css
@@ -46,6 +46,10 @@ color: #222; } +body.dark-theme { + -webkit-filter: invert(100%) hue-rotate(180deg) saturate(80%); +} + .platform-linux { color: rgb(48, 57, 66); font-family: Ubuntu, Arial, sans-serif; @@ -554,6 +558,10 @@ bottom: 0; } +body.dark-theme .root-view { + background: white; +} + .viewport-control-gap-element { color: transparent; }
diff --git a/third_party/WebKit/Source/devtools/front_end/main/Main.js b/third_party/WebKit/Source/devtools/front_end/main/Main.js index 1a9a6fb..92d133a1 100644 --- a/third_party/WebKit/Source/devtools/front_end/main/Main.js +++ b/third_party/WebKit/Source/devtools/front_end/main/Main.js
@@ -107,6 +107,7 @@ Runtime.experiments.register("applyCustomStylesheet", "Allow custom UI themes"); Runtime.experiments.register("blackboxJSFramesOnTimeline", "Blackbox JavaScript frames on Timeline", true); Runtime.experiments.register("colorContrastRatio", "Contrast ratio line in color picker", true); + Runtime.experiments.register("darkTheme", "Dark theme", true); Runtime.experiments.register("deviceMode", "Device mode", true); Runtime.experiments.register("emptySourceMapAutoStepping", "Empty sourcemap auto-stepping"); Runtime.experiments.register("fileSystemInspection", "FileSystem inspection"); @@ -167,6 +168,9 @@ WebInspector.initializeUIUtils(window); WebInspector.installComponentRootStyles(/** @type {!Element} */ (document.body)); + if (Runtime.experiments.isEnabled("darkTheme")) { + document.body.classList.add("dark-theme"); + } this._addMainEventListeners(document);
diff --git a/third_party/WebKit/Source/devtools/front_end/network/EventSourceMessagesView.js b/third_party/WebKit/Source/devtools/front_end/network/EventSourceMessagesView.js index 5cfeb48..0830a7c 100644 --- a/third_party/WebKit/Source/devtools/front_end/network/EventSourceMessagesView.js +++ b/third_party/WebKit/Source/devtools/front_end/network/EventSourceMessagesView.js
@@ -4,12 +4,12 @@ /** * @constructor - * @extends {WebInspector.VBox} + * @extends {WebInspector.DataGridContainerWidget} * @param {!WebInspector.NetworkRequest} request */ WebInspector.EventSourceMessagesView = function(request) { - WebInspector.VBox.call(this); + WebInspector.DataGridContainerWidget.call(this); this.registerRequiredCSS("network/eventSourceMessagesView.css"); this.element.classList.add("event-source-messages-view"); this._request = request; @@ -28,7 +28,7 @@ this._dataGrid.addEventListener(WebInspector.DataGrid.Events.SortingChanged, this._sortItems, this); this._dataGrid.setName("EventSourceMessagesView"); - this._dataGrid.asWidget().show(this.element); + this.appendDataGrid(this._dataGrid); } WebInspector.EventSourceMessagesView.prototype = { @@ -67,7 +67,7 @@ this._dataGrid.sortNodes(comparator, !this._dataGrid.isSortOrderAscending()); }, - __proto__: WebInspector.VBox.prototype + __proto__: WebInspector.DataGridContainerWidget.prototype } /**
diff --git a/third_party/WebKit/Source/devtools/front_end/network/NetworkLogView.js b/third_party/WebKit/Source/devtools/front_end/network/NetworkLogView.js index 55f33aa..6bead516 100644 --- a/third_party/WebKit/Source/devtools/front_end/network/NetworkLogView.js +++ b/third_party/WebKit/Source/devtools/front_end/network/NetworkLogView.js
@@ -30,7 +30,7 @@ /** * @constructor - * @extends {WebInspector.VBox} + * @extends {WebInspector.DataGridContainerWidget} * @implements {WebInspector.Searchable} * @implements {WebInspector.TargetManager.Observer} * @param {!WebInspector.FilterBar} filterBar @@ -39,7 +39,7 @@ */ WebInspector.NetworkLogView = function(filterBar, progressBarContainer, networkLogLargeRowsSetting) { - WebInspector.VBox.call(this); + WebInspector.DataGridContainerWidget.call(this); this.setMinimumSize(50, 64); this.registerRequiredCSS("network/networkLogView.css"); this.registerRequiredCSS("ui/filter.css"); @@ -491,7 +491,7 @@ this._dataGrid.element.addEventListener("mousedown", this._dataGridMouseDown.bind(this), true); this._dataGrid.element.addEventListener("mousemove", this._dataGridMouseMove.bind(this), true); this._dataGrid.element.addEventListener("mouseleave", this._highlightInitiatorChain.bind(this, null), true); - this._dataGrid.asWidget().show(this.element); + this.appendDataGrid(this._dataGrid); // Event listeners need to be added _after_ we attach to the document, so that owner document is properly update. this._dataGrid.addEventListener(WebInspector.DataGrid.Events.SortingChanged, this._sortItems, this); @@ -1932,7 +1932,7 @@ return command.join(" "); }, - __proto__: WebInspector.VBox.prototype + __proto__: WebInspector.DataGridContainerWidget.prototype } /** @typedef {function(!WebInspector.NetworkRequest): boolean} */
diff --git a/third_party/WebKit/Source/devtools/front_end/network/ResourceWebSocketFrameView.js b/third_party/WebKit/Source/devtools/front_end/network/ResourceWebSocketFrameView.js index 6a531426..63105e2 100644 --- a/third_party/WebKit/Source/devtools/front_end/network/ResourceWebSocketFrameView.js +++ b/third_party/WebKit/Source/devtools/front_end/network/ResourceWebSocketFrameView.js
@@ -47,7 +47,9 @@ this._dataGrid.setName("ResourceWebSocketFrameView"); this._dataGrid.addEventListener(WebInspector.DataGrid.Events.SelectedNode, this._onFrameSelected, this); - this._splitWidget.setMainWidget(this._dataGrid.asWidget()); + var dataGridWidget = new WebInspector.DataGridContainerWidget(); + dataGridWidget.appendDataGrid(this._dataGrid); + this._splitWidget.setMainWidget(dataGridWidget); this._messageView = new WebInspector.EmptyWidget("Select frame to browse its content."); this._splitWidget.setSidebarWidget(this._messageView);
diff --git a/third_party/WebKit/Source/devtools/front_end/profiler/CPUProfileView.js b/third_party/WebKit/Source/devtools/front_end/profiler/CPUProfileView.js index 5977ce5a..336b8ebf 100644 --- a/third_party/WebKit/Source/devtools/front_end/profiler/CPUProfileView.js +++ b/third_party/WebKit/Source/devtools/front_end/profiler/CPUProfileView.js
@@ -48,6 +48,8 @@ this.dataGrid = new WebInspector.DataGrid(columns); this.dataGrid.addEventListener(WebInspector.DataGrid.Events.SortingChanged, this._sortProfile, this); + this._dataGridContainer = new WebInspector.DataGridContainerWidget(); + this._dataGridContainer.appendDataGrid(this.dataGrid); this.viewSelectComboBox = new WebInspector.ToolbarComboBox(this._changeView.bind(this)); @@ -307,13 +309,13 @@ case WebInspector.CPUProfileView._TypeTree: this.profileDataGridTree = this._getTopDownProfileDataGridTree(); this._sortProfile(); - this._visibleView = this.dataGrid.asWidget(); + this._visibleView = this._dataGridContainer; this._searchableElement = this.profileDataGridTree; break; case WebInspector.CPUProfileView._TypeHeavy: this.profileDataGridTree = this._getBottomUpProfileDataGridTree(); this._sortProfile(); - this._visibleView = this.dataGrid.asWidget(); + this._visibleView = this._dataGridContainer; this._searchableElement = this.profileDataGridTree; break; }
diff --git a/third_party/WebKit/Source/devtools/front_end/profiler/HeapSnapshotView.js b/third_party/WebKit/Source/devtools/front_end/profiler/HeapSnapshotView.js index 1d67644..b363ca10 100644 --- a/third_party/WebKit/Source/devtools/front_end/profiler/HeapSnapshotView.js +++ b/third_party/WebKit/Source/devtools/front_end/profiler/HeapSnapshotView.js
@@ -59,28 +59,33 @@ this._splitWidget = new WebInspector.SplitWidget(false, true, "heapSnapshotSplitViewState", 200, 200); this._splitWidget.show(this._searchableView.element); + this._containmentWidget = new WebInspector.DataGridContainerWidget(); + this._containmentWidget.setMinimumSize(50, 25); this._containmentDataGrid = new WebInspector.HeapSnapshotContainmentDataGrid(this); this._containmentDataGrid.addEventListener(WebInspector.DataGrid.Events.SelectedNode, this._selectionChanged, this); - this._containmentWidget = this._containmentDataGrid.asWidget(); - this._containmentWidget.setMinimumSize(50, 25); + this._containmentWidget.appendDataGrid(this._containmentDataGrid); this._statisticsView = new WebInspector.HeapSnapshotStatisticsView(); - this._constructorsDataGrid = new WebInspector.HeapSnapshotConstructorsDataGrid(this); - this._constructorsDataGrid.addEventListener(WebInspector.DataGrid.Events.SelectedNode, this._selectionChanged, this); - this._constructorsWidget = this._constructorsDataGrid.asWidget(); + this._constructorsWidget = new WebInspector.DataGridContainerWidget(); this._constructorsWidget.setMinimumSize(50, 25); + this._constructorsDataGrid = new WebInspector.HeapSnapshotConstructorsDataGrid(this); + this._constructorsDataGrid.addEventListener(WebInspector.DataGrid.Events.SelectedNode, this._selectionChanged, this); + this._constructorsWidget.appendDataGrid(this._constructorsDataGrid); + + this._diffWidget = new WebInspector.DataGridContainerWidget(); + this._diffWidget.setMinimumSize(50, 25); this._diffDataGrid = new WebInspector.HeapSnapshotDiffDataGrid(this); this._diffDataGrid.addEventListener(WebInspector.DataGrid.Events.SelectedNode, this._selectionChanged, this); - this._diffWidget = this._diffDataGrid.asWidget(); - this._diffWidget.setMinimumSize(50, 25); + this._diffWidget.appendDataGrid(this._diffDataGrid); if (isHeapTimeline && WebInspector.moduleSetting("recordAllocationStacks").get()) { + this._allocationWidget = new WebInspector.DataGridContainerWidget(); + this._allocationWidget.setMinimumSize(50, 25); this._allocationDataGrid = new WebInspector.AllocationDataGrid(profile.target() , this); this._allocationDataGrid.addEventListener(WebInspector.DataGrid.Events.SelectedNode, this._onSelectAllocationNode, this); - this._allocationWidget = this._allocationDataGrid.asWidget(); - this._allocationWidget.setMinimumSize(50, 25); + this._allocationWidget.appendDataGrid(this._allocationDataGrid); this._allocationStackView = new WebInspector.HeapAllocationStackView(profile.target()); this._allocationStackView.setMinimumSize(50, 25); @@ -89,8 +94,7 @@ this._tabbedPane.headerElement().classList.add("heap-object-details-header"); } - this._retainmentDataGrid = new WebInspector.HeapSnapshotRetainmentDataGrid(this); - this._retainmentWidget = this._retainmentDataGrid.asWidget(); + this._retainmentWidget = new WebInspector.DataGridContainerWidget(); this._retainmentWidget.setMinimumSize(50, 21); this._retainmentWidget.element.classList.add("retaining-paths-view"); @@ -117,6 +121,8 @@ this._splitWidget.hideDefaultResizer(); this._splitWidget.installResizer(splitWidgetResizer); + this._retainmentDataGrid = new WebInspector.HeapSnapshotRetainmentDataGrid(this); + this._retainmentWidget.appendDataGrid(this._retainmentDataGrid); this._retainmentDataGrid.addEventListener(WebInspector.DataGrid.Events.SelectedNode, this._inspectedObjectChanged, this); this._retainmentDataGrid.reset(); @@ -346,7 +352,6 @@ { return heapSnapshotView._containmentDataGrid; }, - __proto__: WebInspector.HeapSnapshotView.Perspective.prototype }
diff --git a/third_party/WebKit/Source/devtools/front_end/promises/PromisePane.js b/third_party/WebKit/Source/devtools/front_end/promises/PromisePane.js index e9a6589b..92ff5a4 100644 --- a/third_party/WebKit/Source/devtools/front_end/promises/PromisePane.js +++ b/third_party/WebKit/Source/devtools/front_end/promises/PromisePane.js
@@ -48,6 +48,8 @@ resetFiltersLink.textContent = WebInspector.UIString("Show all promises."); resetFiltersLink.addEventListener("click", this._resetFilters.bind(this), true); + this._dataGridContainer = new WebInspector.DataGridContainerWidget(); + this._dataGridContainer.show(this.element); // FIXME: Make "status" column width fixed to ~16px. var columns = [ { id: "status", weight: 1 }, @@ -58,7 +60,7 @@ ]; this._dataGrid = new WebInspector.ViewportDataGrid(columns, undefined, undefined, undefined, this._onContextMenu.bind(this)); this._dataGrid.setStickToBottom(true); - this._dataGrid.asWidget().show(this.element); + this._dataGridContainer.appendDataGrid(this._dataGrid); this._linkifier = new WebInspector.Linkifier();
diff --git a/third_party/WebKit/Source/devtools/front_end/resources/ApplicationCacheItemsView.js b/third_party/WebKit/Source/devtools/front_end/resources/ApplicationCacheItemsView.js index bd31f76..83921fc 100644 --- a/third_party/WebKit/Source/devtools/front_end/resources/ApplicationCacheItemsView.js +++ b/third_party/WebKit/Source/devtools/front_end/resources/ApplicationCacheItemsView.js
@@ -25,11 +25,11 @@ /** * @constructor - * @extends {WebInspector.VBox} + * @extends {WebInspector.DataGridContainerWidget} */ WebInspector.ApplicationCacheItemsView = function(model, frameId) { - WebInspector.VBox.call(this); + WebInspector.DataGridContainerWidget.call(this); this._model = model; @@ -191,7 +191,7 @@ {title: WebInspector.UIString("Size"), align: WebInspector.DataGrid.Align.Right, sortable: true} ]; this._dataGrid = new WebInspector.DataGrid(columns); - this._dataGrid.asWidget().show(this.element); + this.appendDataGrid(this._dataGrid); this._dataGrid.addEventListener(WebInspector.DataGrid.Events.SortingChanged, this._populateDataGrid, this); }, @@ -257,6 +257,6 @@ // this._update(); }, - __proto__: WebInspector.VBox.prototype + __proto__: WebInspector.DataGridContainerWidget.prototype }
diff --git a/third_party/WebKit/Source/devtools/front_end/resources/DOMStorageItemsView.js b/third_party/WebKit/Source/devtools/front_end/resources/DOMStorageItemsView.js index 4e91995..34df4dd 100644 --- a/third_party/WebKit/Source/devtools/front_end/resources/DOMStorageItemsView.js +++ b/third_party/WebKit/Source/devtools/front_end/resources/DOMStorageItemsView.js
@@ -26,11 +26,11 @@ /** * @constructor - * @extends {WebInspector.VBox} + * @extends {WebInspector.DataGridContainerWidget} */ WebInspector.DOMStorageItemsView = function(domStorage) { - WebInspector.VBox.call(this); + WebInspector.DataGridContainerWidget.call(this); this.domStorage = domStorage; @@ -175,7 +175,7 @@ return; this._dataGrid = this._dataGridForDOMStorageItems(items); - this._dataGrid.asWidget().show(this.element); + this.appendDataGrid(this._dataGrid); this.deleteButton.setVisible(this._dataGrid.rootNode().children.length > 1); }, @@ -259,5 +259,5 @@ this.domStorage.removeItem(node.data.key); }, - __proto__: WebInspector.VBox.prototype + __proto__: WebInspector.DataGridContainerWidget.prototype }
diff --git a/third_party/WebKit/Source/devtools/front_end/resources/DatabaseQueryView.js b/third_party/WebKit/Source/devtools/front_end/resources/DatabaseQueryView.js index 55cf8d3..4a0b164d 100644 --- a/third_party/WebKit/Source/devtools/front_end/resources/DatabaseQueryView.js +++ b/third_party/WebKit/Source/devtools/front_end/resources/DatabaseQueryView.js
@@ -156,7 +156,9 @@ if (dataGrid) { dataGrid.renderInline(); - this._appendViewQueryResult(trimmedQuery, dataGrid.asWidget()); + var dataGridContainer = new WebInspector.DataGridContainerWidget(); + dataGridContainer.appendDataGrid(dataGrid); + this._appendViewQueryResult(trimmedQuery, dataGridContainer); dataGrid.autoSizeColumns(5); }
diff --git a/third_party/WebKit/Source/devtools/front_end/resources/DatabaseTableView.js b/third_party/WebKit/Source/devtools/front_end/resources/DatabaseTableView.js index 2ba9a584..2ceff7fa 100644 --- a/third_party/WebKit/Source/devtools/front_end/resources/DatabaseTableView.js +++ b/third_party/WebKit/Source/devtools/front_end/resources/DatabaseTableView.js
@@ -25,11 +25,11 @@ /** * @constructor - * @extends {WebInspector.VBox} + * @extends {WebInspector.DataGridContainerWidget} */ WebInspector.DatabaseTableView = function(database, tableName) { - WebInspector.VBox.call(this); + WebInspector.DataGridContainerWidget.call(this); this.database = database; this.tableName = tableName; @@ -84,7 +84,7 @@ this._emptyWidget.show(this.element); return; } - this._dataGrid.asWidget().show(this.element); + this.appendDataGrid(this._dataGrid); this._dataGrid.autoSizeColumns(5); this._columnsMap = new Map(); @@ -142,5 +142,5 @@ this.update(); }, - __proto__: WebInspector.VBox.prototype + __proto__: WebInspector.DataGridContainerWidget.prototype }
diff --git a/third_party/WebKit/Source/devtools/front_end/resources/IndexedDBViews.js b/third_party/WebKit/Source/devtools/front_end/resources/IndexedDBViews.js index c607d8a..9904322 100644 --- a/third_party/WebKit/Source/devtools/front_end/resources/IndexedDBViews.js +++ b/third_party/WebKit/Source/devtools/front_end/resources/IndexedDBViews.js
@@ -110,7 +110,7 @@ /** * @constructor - * @extends {WebInspector.VBox} + * @extends {WebInspector.DataGridContainerWidget} * @param {!WebInspector.IndexedDBModel} model * @param {!WebInspector.IndexedDBModel.DatabaseId} databaseId * @param {!WebInspector.IndexedDBModel.ObjectStore} objectStore @@ -118,7 +118,7 @@ */ WebInspector.IDBDataView = function(model, databaseId, objectStore, index) { - WebInspector.VBox.call(this); + WebInspector.DataGridContainerWidget.call(this); this.registerRequiredCSS("resources/indexedDBViews.css"); this._model = model; @@ -252,9 +252,9 @@ this._index = index; if (this._dataGrid) - this._dataGrid.asWidget().detach(); + this.removeDataGrid(this._dataGrid); this._dataGrid = this._createDataGrid(); - this._dataGrid.asWidget().show(this.element); + this.appendDataGrid(this._dataGrid); this._skipCount = 0; this._updateData(true); @@ -360,7 +360,7 @@ this._entries = []; }, - __proto__: WebInspector.VBox.prototype + __proto__: WebInspector.DataGridContainerWidget.prototype } /**
diff --git a/third_party/WebKit/Source/devtools/front_end/resources/ServiceWorkerCacheViews.js b/third_party/WebKit/Source/devtools/front_end/resources/ServiceWorkerCacheViews.js index db781fc..fb2ad90 100644 --- a/third_party/WebKit/Source/devtools/front_end/resources/ServiceWorkerCacheViews.js +++ b/third_party/WebKit/Source/devtools/front_end/resources/ServiceWorkerCacheViews.js
@@ -4,13 +4,13 @@ /** * @constructor - * @extends {WebInspector.VBox} + * @extends {WebInspector.DataGridContainerWidget} * @param {!WebInspector.ServiceWorkerCacheModel} model * @param {!WebInspector.ServiceWorkerCacheModel.Cache} cache */ WebInspector.ServiceWorkerCacheView = function(model, cache) { - WebInspector.VBox.call(this); + WebInspector.DataGridContainerWidget.call(this); this.registerRequiredCSS("resources/serviceWorkerCacheViews.css"); this._model = model; @@ -87,9 +87,10 @@ this._cache = cache; if (this._dataGrid) - this._dataGrid.asWidget().detach(); + this.removeDataGrid(this._dataGrid); this._dataGrid = this._createDataGrid(); - this._dataGrid.asWidget().show(this.element); + this.appendDataGrid(this._dataGrid); + this._skipCount = 0; this._updateData(true); }, @@ -158,5 +159,5 @@ this._entries = []; }, - __proto__: WebInspector.VBox.prototype + __proto__: WebInspector.DataGridContainerWidget.prototype }
diff --git a/third_party/WebKit/Source/devtools/front_end/screencast/ScreencastView.js b/third_party/WebKit/Source/devtools/front_end/screencast/ScreencastView.js index fc42e9b..aaab6f6f 100644 --- a/third_party/WebKit/Source/devtools/front_end/screencast/ScreencastView.js +++ b/third_party/WebKit/Source/devtools/front_end/screencast/ScreencastView.js
@@ -158,9 +158,6 @@ this._scrollOffsetX = metadata.scrollOffsetX; this._scrollOffsetY = metadata.scrollOffsetY; - if (event.data.frameNumber) - this._target.pageAgent().screencastFrameAck(event.data.frameNumber); - var deviceSizeRatio = metadata.deviceHeight / metadata.deviceWidth; var dimensionsCSS = this._viewportDimensions();
diff --git a/third_party/WebKit/Source/devtools/front_end/sdk/ContentProviders.js b/third_party/WebKit/Source/devtools/front_end/sdk/ContentProviders.js index 585645b..f743434 100644 --- a/third_party/WebKit/Source/devtools/front_end/sdk/ContentProviders.js +++ b/third_party/WebKit/Source/devtools/front_end/sdk/ContentProviders.js
@@ -65,7 +65,7 @@ */ requestContent: function(callback) { - WebInspector.ResourceLoader.loadUsingTargetUA(this._sourceURL, {}, contentLoaded.bind(this)); + WebInspector.multitargetNetworkManager.loadResource(this._sourceURL, contentLoaded.bind(this)); /** * @param {number} statusCode
diff --git a/third_party/WebKit/Source/devtools/front_end/sdk/NetworkManager.js b/third_party/WebKit/Source/devtools/front_end/sdk/NetworkManager.js index 0f9a165f..b0622e08 100644 --- a/third_party/WebKit/Source/devtools/front_end/sdk/NetworkManager.js +++ b/third_party/WebKit/Source/devtools/front_end/sdk/NetworkManager.js
@@ -842,6 +842,24 @@ target.networkAgent().showCertificateViewer(certificateId); }, + /** + * @param {string} url + * @param {function(number, !Object.<string, string>, string)} callback + */ + loadResource: function(url, callback) + { + var headers = {}; + + var currentUserAgent = this._currentUserAgent(); + if (currentUserAgent) + headers["User-Agent"] = currentUserAgent; + + if (WebInspector.moduleSetting("cacheDisabled").get()) + headers["Cache-Control"] = "no-cache"; + + WebInspector.ResourceLoader.load(url, headers, callback); + }, + __proto__: WebInspector.Object.prototype }
diff --git a/third_party/WebKit/Source/devtools/front_end/sdk/ResourceTreeModel.js b/third_party/WebKit/Source/devtools/front_end/sdk/ResourceTreeModel.js index ead0a78..dac82232 100644 --- a/third_party/WebKit/Source/devtools/front_end/sdk/ResourceTreeModel.js +++ b/third_party/WebKit/Source/devtools/front_end/sdk/ResourceTreeModel.js
@@ -830,11 +830,12 @@ * @override * @param {string} data * @param {!PageAgent.ScreencastFrameMetadata=} metadata - * @param {number=} frameNumber + * @param {number=} sessionId */ - screencastFrame: function(data, metadata, frameNumber) + screencastFrame: function(data, metadata, sessionId) { - this._resourceTreeModel.dispatchEventToListeners(WebInspector.ResourceTreeModel.EventTypes.ScreencastFrame, {data:data, metadata:metadata, frameNumber:frameNumber}); + this._resourceTreeModel._agent.screencastFrameAck(sessionId); + this._resourceTreeModel.dispatchEventToListeners(WebInspector.ResourceTreeModel.EventTypes.ScreencastFrame, { data: data, metadata: metadata }); }, /** @@ -843,7 +844,7 @@ */ screencastVisibilityChanged: function(visible) { - this._resourceTreeModel.dispatchEventToListeners(WebInspector.ResourceTreeModel.EventTypes.ScreencastVisibilityChanged, {visible:visible}); + this._resourceTreeModel.dispatchEventToListeners(WebInspector.ResourceTreeModel.EventTypes.ScreencastVisibilityChanged, { visible: visible }); }, /**
diff --git a/third_party/WebKit/Source/devtools/front_end/sdk/SourceMap.js b/third_party/WebKit/Source/devtools/front_end/sdk/SourceMap.js index 7d31463e..56aee44 100644 --- a/third_party/WebKit/Source/devtools/front_end/sdk/SourceMap.js +++ b/third_party/WebKit/Source/devtools/front_end/sdk/SourceMap.js
@@ -100,7 +100,7 @@ return; } - WebInspector.ResourceLoader.loadUsingTargetUA(sourceMapURL, null, contentLoaded); + WebInspector.multitargetNetworkManager.loadResource(sourceMapURL, contentLoaded); /** * @param {number} statusCode
diff --git a/third_party/WebKit/Source/devtools/front_end/timeline/LayerTreeOutline.js b/third_party/WebKit/Source/devtools/front_end/timeline/LayerTreeOutline.js index 50b6536..25590bd 100644 --- a/third_party/WebKit/Source/devtools/front_end/timeline/LayerTreeOutline.js +++ b/third_party/WebKit/Source/devtools/front_end/timeline/LayerTreeOutline.js
@@ -127,7 +127,7 @@ // Skip till nearest visible ancestor. while (parentLayer && parentLayer !== root && !parentLayer.drawsContent() && !showInternalLayers) parentLayer = parentLayer.parent(); - var parent = layer === root ? this._treeOutline : parentLayer[WebInspector.LayerTreeElement._symbol]; + var parent = layer === root ? this._treeOutline.rootElement() : parentLayer[WebInspector.LayerTreeElement._symbol]; if (!parent) { console.assert(false, "Parent is not in the tree"); return;
diff --git a/third_party/WebKit/Source/devtools/front_end/timeline/LayerViewHost.js b/third_party/WebKit/Source/devtools/front_end/timeline/LayerViewHost.js index b6d8789..be790dc8 100644 --- a/third_party/WebKit/Source/devtools/front_end/timeline/LayerViewHost.js +++ b/third_party/WebKit/Source/devtools/front_end/timeline/LayerViewHost.js
@@ -49,6 +49,16 @@ Tile: "Tile", } +/** + * @param {?WebInspector.LayerView.Selection} a + * @param {?WebInspector.LayerView.Selection} b + * @return {boolean} + */ +WebInspector.LayerView.Selection.isEqual = function(a, b) +{ + return a && b ? a._isEqual(b) : a === b; +} + WebInspector.LayerView.Selection.prototype = { /** * @return {!WebInspector.LayerView.Selection.Type} @@ -70,7 +80,7 @@ * @param {!WebInspector.LayerView.Selection} other * @return {boolean} */ - isEqual: function(other) + _isEqual: function(other) { return false; } @@ -93,7 +103,7 @@ * @param {!WebInspector.LayerView.Selection} other * @return {boolean} */ - isEqual: function(other) + _isEqual: function(other) { return other._type === WebInspector.LayerView.Selection.Type.Layer && other.layer().id() === this.layer().id(); }, @@ -119,7 +129,7 @@ * @param {!WebInspector.LayerView.Selection} other * @return {boolean} */ - isEqual: function(other) + _isEqual: function(other) { return other._type === WebInspector.LayerView.Selection.Type.ScrollRect && this.layer().id() === other.layer().id() && this.scrollRectIndex === other.scrollRectIndex; @@ -146,7 +156,7 @@ * @param {!WebInspector.LayerView.Selection} other * @return {boolean} */ - isEqual: function(other) + _isEqual: function(other) { return other._type === WebInspector.LayerView.Selection.Type.Tile && this.layer().id() === other.layer().id() && this.traceEvent === other.traceEvent; @@ -205,7 +215,7 @@ */ hoverObject: function(selection) { - if (this._hoveredObject === selection) + if (WebInspector.LayerView.Selection.isEqual(this._hoveredObject, selection)) return; this._hoveredObject = selection; var layer = selection && selection.layer(); @@ -219,7 +229,7 @@ */ selectObject: function(selection) { - if (this._selectedObject === selection) + if (WebInspector.LayerView.Selection.isEqual(this._selectedObject, selection)) return; this._selectedObject = selection; for (var view of this._views)
diff --git a/third_party/WebKit/Source/devtools/front_end/timeline/Layers3DView.js b/third_party/WebKit/Source/devtools/front_end/timeline/Layers3DView.js index a8e2b7f..5197e169 100644 --- a/third_party/WebKit/Source/devtools/front_end/timeline/Layers3DView.js +++ b/third_party/WebKit/Source/devtools/front_end/timeline/Layers3DView.js
@@ -190,13 +190,16 @@ onResize: function() { + this._resizeCanvas(); this._update(); }, wasShown: function() { - if (this._needsUpdate) - this._update(); + if (!this._needsUpdate) + return; + this._resizeCanvas(); + this._update(); }, /** @@ -279,8 +282,6 @@ { this._canvasElement.width = this._canvasElement.offsetWidth * window.devicePixelRatio; this._canvasElement.height = this._canvasElement.offsetHeight * window.devicePixelRatio; - this._gl.viewportWidth = this._canvasElement.width; - this._gl.viewportHeight = this._canvasElement.height; }, _updateTransformAndConstraints: function() @@ -394,15 +395,6 @@ }, /** - * @param {!WebInspector.Layers3DView.OutlineType} type - * @param {!WebInspector.LayerView.Selection} selection - */ - _isSelectionActive: function(type, selection) - { - return this._lastSelection[type] && this._lastSelection[type].isEqual(selection); - }, - - /** * @param {!WebInspector.Layer} layer * @return {number} */ @@ -454,8 +446,8 @@ _appendRect: function(rect) { var selection = rect.relatedObject; - var isSelected = this._isSelectionActive(WebInspector.Layers3DView.OutlineType.Selected, selection); - var isHovered = this._isSelectionActive(WebInspector.Layers3DView.OutlineType.Hovered, selection); + var isSelected = WebInspector.LayerView.Selection.isEqual(this._lastSelection[WebInspector.Layers3DView.OutlineType.Selected], selection); + var isHovered = WebInspector.LayerView.Selection.isEqual(this._lastSelection[WebInspector.Layers3DView.OutlineType.Hovered], selection); if (isSelected) { rect.borderColor = WebInspector.Layers3DView.SelectedBorderColor; } else if (isHovered) { @@ -664,8 +656,9 @@ return; } this._failBanner.detach(); + this._gl.viewportWidth = this._canvasElement.width; + this._gl.viewportHeight = this._canvasElement.height; - this._resizeCanvas(); this._calculateDepthsAndVisibility(); this._calculateRects(); this._updateTransformAndConstraints();
diff --git a/third_party/WebKit/Source/devtools/front_end/timeline/TimelineTreeView.js b/third_party/WebKit/Source/devtools/front_end/timeline/TimelineTreeView.js index 46abc3d..63529f4 100644 --- a/third_party/WebKit/Source/devtools/front_end/timeline/TimelineTreeView.js +++ b/third_party/WebKit/Source/devtools/front_end/timeline/TimelineTreeView.js
@@ -24,9 +24,9 @@ this._populateColumns(columns); this._dataGrid = new WebInspector.SortableDataGrid(columns); this._dataGrid.addEventListener(WebInspector.DataGrid.Events.SortingChanged, this._sortingChanged, this); - var dataGridContainerWidget = this._dataGrid.asWidget(); + var dataGridContainerWidget = new WebInspector.DataGridContainerWidget(); this._populateToolbar(dataGridContainerWidget.element); - dataGridContainerWidget.show(this.element); + dataGridContainerWidget.appendDataGrid(this._dataGrid); this._splitWidget = new WebInspector.SplitWidget(true, true, "timelineTreeViewDetailsSplitWidget"); this._splitWidget.show(this.element);
diff --git a/third_party/WebKit/Source/devtools/front_end/ui/SoftContextMenu.js b/third_party/WebKit/Source/devtools/front_end/ui/SoftContextMenu.js index c226fc1..5fdf280 100644 --- a/third_party/WebKit/Source/devtools/front_end/ui/SoftContextMenu.js +++ b/third_party/WebKit/Source/devtools/front_end/ui/SoftContextMenu.js
@@ -381,7 +381,7 @@ event.consume(true); } if (this._discardMenuOnResizeListener) { - this._document.defaultView.removeEventListener(this._discardMenuOnResizeListener); + this._document.defaultView.removeEventListener("resize", this._discardMenuOnResizeListener, false); delete this._discardMenuOnResizeListener; } },
diff --git a/third_party/WebKit/Source/devtools/front_end/ui_lazy/DataGrid.js b/third_party/WebKit/Source/devtools/front_end/ui_lazy/DataGrid.js index 5221cc6..7cbd38a 100644 --- a/third_party/WebKit/Source/devtools/front_end/ui_lazy/DataGrid.js +++ b/third_party/WebKit/Source/devtools/front_end/ui_lazy/DataGrid.js
@@ -1072,16 +1072,6 @@ this.dispatchEventToListeners(WebInspector.DataGrid.Events.ColumnsResized); }, - /** - * @return {!WebInspector.DataGridWidget} - */ - asWidget: function() - { - if (!this._dataGridWidget) - this._dataGridWidget = new WebInspector.DataGridWidget(this); - return this._dataGridWidget; - }, - ColumnResizePadding: 24, CenterResizerOverBorderAdjustment: 3, @@ -1808,22 +1798,39 @@ /** * @constructor * @extends {WebInspector.VBox} - * @param {!WebInspector.DataGrid} dataGrid */ -WebInspector.DataGridWidget = function(dataGrid) +WebInspector.DataGridContainerWidget = function() { WebInspector.VBox.call(this); - this._dataGrid = dataGrid; - this.element.appendChild(dataGrid.element); + this._dataGrids = []; } -WebInspector.DataGridWidget.prototype = { +WebInspector.DataGridContainerWidget.prototype = { + /** + * @param {!WebInspector.DataGrid} dataGrid + */ + appendDataGrid: function(dataGrid) + { + this._dataGrids.push(dataGrid); + this.element.appendChild(dataGrid.element); + }, + + /** + * @param {!WebInspector.DataGrid} dataGrid + */ + removeDataGrid: function(dataGrid) + { + this._dataGrids.remove(dataGrid); + this.element.removeChild(dataGrid.element); + }, + /** * @override */ wasShown: function() { - this._dataGrid.wasShown(); + for (var dataGrid of this._dataGrids) + dataGrid.wasShown(); }, /** @@ -1831,7 +1838,8 @@ */ willHide: function() { - this._dataGrid.willHide(); + for (var dataGrid of this._dataGrids) + dataGrid.willHide(); }, /** @@ -1839,7 +1847,8 @@ */ onResize: function() { - this._dataGrid.onResize(); + for (var dataGrid of this._dataGrids) + dataGrid.onResize(); }, /** @@ -1848,7 +1857,23 @@ */ elementsToRestoreScrollPositionsFor: function() { - return [ this._dataGrid._scrollContainer ]; + var result = []; + for (var dataGrid of this._dataGrids) { + if (!dataGrid._inline) + result.push(dataGrid._scrollContainer); + } + return result; + }, + + /** + * @override + */ + detachChildWidgets: function() + { + WebInspector.Widget.prototype.detachChildWidgets.call(this); + for (var dataGrid of this._dataGrids) + this.element.removeChild(dataGrid.element); + this._dataGrids = []; }, __proto__: WebInspector.VBox.prototype
diff --git a/third_party/WebKit/Source/devtools/protocol.json b/third_party/WebKit/Source/devtools/protocol.json index 813bb5d..bed495c 100644 --- a/third_party/WebKit/Source/devtools/protocol.json +++ b/third_party/WebKit/Source/devtools/protocol.json
@@ -413,7 +413,8 @@ { "name": "format", "type": "string", "optional": true, "enum": ["jpeg", "png"], "description": "Image compression format." }, { "name": "quality", "type": "integer", "optional": true, "description": "Compression quality from range [0..100]." }, { "name": "maxWidth", "type": "integer", "optional": true, "description": "Maximum screenshot width." }, - { "name": "maxHeight", "type": "integer", "optional": true, "description": "Maximum screenshot height." } + { "name": "maxHeight", "type": "integer", "optional": true, "description": "Maximum screenshot height." }, + { "name": "everyNthFrame", "type": "integer", "optional": true, "description": "Send every n-th frame." } ], "hidden": true, "handlers": ["browser", "renderer"] @@ -428,7 +429,7 @@ "name": "screencastFrameAck", "description": "Acknowledges that a screencast frame has been received by the frontend.", "parameters": [ - { "name": "frameNumber", "type": "integer", "description": "Frame number." } + { "name": "sessionId", "type": "integer", "description": "Frame number." } ], "hidden": true, "handlers": ["browser"] @@ -556,7 +557,7 @@ "parameters": [ { "name": "data", "type": "string", "description": "Base64-encoded compressed image." }, { "name": "metadata", "$ref": "ScreencastFrameMetadata", "description": "Screencast frame metadata."}, - { "name": "frameNumber", "type": "integer", "optional": true, "description": "Frame number."} + { "name": "sessionId", "type": "integer", "description": "Frame number."} ], "hidden": true, "handlers": ["browser"]
diff --git a/third_party/WebKit/Source/modules/BUILD.gn b/third_party/WebKit/Source/modules/BUILD.gn index 4a7d6fba..3d2f575 100644 --- a/third_party/WebKit/Source/modules/BUILD.gn +++ b/third_party/WebKit/Source/modules/BUILD.gn
@@ -98,8 +98,8 @@ # GYP version: WebKit/Source/modules/modules_generated.gyp:make_modules_generated group("make_modules_generated") { public_deps = [ - "//third_party/WebKit/Source/core:core_event_interfaces", - "//third_party/WebKit/Source/bindings/modules:bindings_modules_generated", ":module_names", + "//third_party/WebKit/Source/bindings/modules:bindings_modules_generated", + "//third_party/WebKit/Source/core:core_event_interfaces", ] }
diff --git a/third_party/WebKit/Source/modules/accessibility/AXLayoutObject.cpp b/third_party/WebKit/Source/modules/accessibility/AXLayoutObject.cpp index 1698981..0569076b 100644 --- a/third_party/WebKit/Source/modules/accessibility/AXLayoutObject.cpp +++ b/third_party/WebKit/Source/modules/accessibility/AXLayoutObject.cpp
@@ -544,6 +544,9 @@ ASSERT(m_initialized); #endif + if (!m_layoutObject) + return true; + // Check first if any of the common reasons cause this element to be ignored. // Then process other use cases that need to be applied to all the various roles // that AXLayoutObjects take on.
diff --git a/third_party/WebKit/Source/modules/canvas2d/CanvasRenderingContext2D.cpp b/third_party/WebKit/Source/modules/canvas2d/CanvasRenderingContext2D.cpp index da219d6..1145119 100644 --- a/third_party/WebKit/Source/modules/canvas2d/CanvasRenderingContext2D.cpp +++ b/third_party/WebKit/Source/modules/canvas2d/CanvasRenderingContext2D.cpp
@@ -82,7 +82,7 @@ static const char ltr[] = "ltr"; static const double TryRestoreContextInterval = 0.5; static const unsigned MaxTryRestoreContextAttempts = 4; -static const float cDeviceScaleFactor = 1.0f; // Canvas is device independent +static const double cDeviceScaleFactor = 1.0; // Canvas is device independent static bool contextLostRestoredEventsEnabled() { @@ -448,12 +448,12 @@ modifiableState().setUnparsedFillColor(colorString); } -float CanvasRenderingContext2D::lineWidth() const +double CanvasRenderingContext2D::lineWidth() const { return state().lineWidth(); } -void CanvasRenderingContext2D::setLineWidth(float width) +void CanvasRenderingContext2D::setLineWidth(double width) { if (!std::isfinite(width) || width <= 0) return; @@ -492,12 +492,12 @@ modifiableState().setLineJoin(join); } -float CanvasRenderingContext2D::miterLimit() const +double CanvasRenderingContext2D::miterLimit() const { return state().miterLimit(); } -void CanvasRenderingContext2D::setMiterLimit(float limit) +void CanvasRenderingContext2D::setMiterLimit(double limit) { if (!std::isfinite(limit) || limit <= 0) return; @@ -506,12 +506,12 @@ modifiableState().setMiterLimit(limit); } -float CanvasRenderingContext2D::shadowOffsetX() const +double CanvasRenderingContext2D::shadowOffsetX() const { return state().shadowOffset().width(); } -void CanvasRenderingContext2D::setShadowOffsetX(float x) +void CanvasRenderingContext2D::setShadowOffsetX(double x) { if (!std::isfinite(x)) return; @@ -520,12 +520,12 @@ modifiableState().setShadowOffsetX(x); } -float CanvasRenderingContext2D::shadowOffsetY() const +double CanvasRenderingContext2D::shadowOffsetY() const { return state().shadowOffset().height(); } -void CanvasRenderingContext2D::setShadowOffsetY(float y) +void CanvasRenderingContext2D::setShadowOffsetY(double y) { if (!std::isfinite(y)) return; @@ -534,12 +534,12 @@ modifiableState().setShadowOffsetY(y); } -float CanvasRenderingContext2D::shadowBlur() const +double CanvasRenderingContext2D::shadowBlur() const { return state().shadowBlur(); } -void CanvasRenderingContext2D::setShadowBlur(float blur) +void CanvasRenderingContext2D::setShadowBlur(double blur) { if (!std::isfinite(blur) || blur < 0) return; @@ -563,12 +563,12 @@ modifiableState().setShadowColor(color.rgb()); } -const Vector<float>& CanvasRenderingContext2D::getLineDash() const +const Vector<double>& CanvasRenderingContext2D::getLineDash() const { return state().lineDash(); } -static bool lineDashSequenceIsValid(const Vector<float>& dash) +static bool lineDashSequenceIsValid(const Vector<double>& dash) { for (size_t i = 0; i < dash.size(); i++) { if (!std::isfinite(dash[i]) || dash[i] < 0) @@ -577,31 +577,31 @@ return true; } -void CanvasRenderingContext2D::setLineDash(const Vector<float>& dash) +void CanvasRenderingContext2D::setLineDash(const Vector<double>& dash) { if (!lineDashSequenceIsValid(dash)) return; modifiableState().setLineDash(dash); } -float CanvasRenderingContext2D::lineDashOffset() const +double CanvasRenderingContext2D::lineDashOffset() const { return state().lineDashOffset(); } -void CanvasRenderingContext2D::setLineDashOffset(float offset) +void CanvasRenderingContext2D::setLineDashOffset(double offset) { if (!std::isfinite(offset) || state().lineDashOffset() == offset) return; modifiableState().setLineDashOffset(offset); } -float CanvasRenderingContext2D::globalAlpha() const +double CanvasRenderingContext2D::globalAlpha() const { return state().globalAlpha(); } -void CanvasRenderingContext2D::setGlobalAlpha(float alpha) +void CanvasRenderingContext2D::setGlobalAlpha(double alpha) { if (!(alpha >= 0 && alpha <= 1)) return; @@ -668,7 +668,7 @@ setTransform(transform.a(), transform.b(), transform.c(), transform.d(), transform.e(), transform.f()); } -void CanvasRenderingContext2D::scale(float sx, float sy) +void CanvasRenderingContext2D::scale(double sx, double sy) { SkCanvas* c = drawingCanvas(); if (!c) @@ -690,7 +690,7 @@ m_path.transform(AffineTransform().scaleNonUniform(1.0 / sx, 1.0 / sy)); } -void CanvasRenderingContext2D::rotate(float angleInRadians) +void CanvasRenderingContext2D::rotate(double angleInRadians) { SkCanvas* c = drawingCanvas(); if (!c) @@ -707,11 +707,11 @@ modifiableState().setTransform(newTransform); if (!state().isTransformInvertible()) return; - c->rotate(angleInRadians * (180.0f / piFloat)); + c->rotate(angleInRadians * (180.0 / piFloat)); m_path.transform(AffineTransform().rotateRadians(-angleInRadians)); } -void CanvasRenderingContext2D::translate(float tx, float ty) +void CanvasRenderingContext2D::translate(double tx, double ty) { SkCanvas* c = drawingCanvas(); if (!c) @@ -734,7 +734,7 @@ m_path.transform(AffineTransform().translate(-tx, -ty)); } -void CanvasRenderingContext2D::transform(float m11, float m12, float m21, float m22, float dx, float dy) +void CanvasRenderingContext2D::transform(double m11, double m12, double m21, double m22, double dx, double dy) { SkCanvas* c = drawingCanvas(); if (!c) @@ -779,7 +779,7 @@ // It means that resetTransform() restores m_path just before CTM became non-invertible. } -void CanvasRenderingContext2D::setTransform(float m11, float m12, float m21, float m22, float dx, float dy) +void CanvasRenderingContext2D::setTransform(double m11, double m12, double m21, double m22, double dx, double dy) { SkCanvas* c = drawingCanvas(); if (!c) @@ -797,7 +797,7 @@ m_path.clear(); } -static bool validateRectForCanvas(float& x, float& y, float& width, float& height) +static bool validateRectForCanvas(double& x, double& y, double& width, double& height) { if (!std::isfinite(x) || !std::isfinite(y) || !std::isfinite(width) || !std::isfinite(height)) return false; @@ -985,7 +985,7 @@ drawPathInternal(domPath->path(), CanvasRenderingContext2DState::StrokePaintType); } -void CanvasRenderingContext2D::fillRect(float x, float y, float width, float height) +void CanvasRenderingContext2D::fillRect(double x, double y, double width, double height) { if (!validateRectForCanvas(x, y, width, height)) return; @@ -1020,7 +1020,7 @@ canvas->drawRect(rect, *paint); } -void CanvasRenderingContext2D::strokeRect(float x, float y, float width, float height) +void CanvasRenderingContext2D::strokeRect(double x, double y, double width, double height) { if (!validateRectForCanvas(x, y, width, height)) return; @@ -1071,17 +1071,17 @@ clipInternal(domPath->path(), windingRuleString); } -bool CanvasRenderingContext2D::isPointInPath(const float x, const float y, const String& windingRuleString) +bool CanvasRenderingContext2D::isPointInPath(const double x, const double y, const String& windingRuleString) { return isPointInPathInternal(m_path, x, y, windingRuleString); } -bool CanvasRenderingContext2D::isPointInPath(Path2D* domPath, const float x, const float y, const String& windingRuleString) +bool CanvasRenderingContext2D::isPointInPath(Path2D* domPath, const double x, const double y, const String& windingRuleString) { return isPointInPathInternal(domPath->path(), x, y, windingRuleString); } -bool CanvasRenderingContext2D::isPointInPathInternal(const Path& path, const float x, const float y, const String& windingRuleString) +bool CanvasRenderingContext2D::isPointInPathInternal(const Path& path, const double x, const double y, const String& windingRuleString) { SkCanvas* c = drawingCanvas(); if (!c) @@ -1098,17 +1098,17 @@ return path.contains(transformedPoint, SkFillTypeToWindRule(parseWinding(windingRuleString))); } -bool CanvasRenderingContext2D::isPointInStroke(const float x, const float y) +bool CanvasRenderingContext2D::isPointInStroke(const double x, const double y) { return isPointInStrokeInternal(m_path, x, y); } -bool CanvasRenderingContext2D::isPointInStroke(Path2D* domPath, const float x, const float y) +bool CanvasRenderingContext2D::isPointInStroke(Path2D* domPath, const double x, const double y) { return isPointInStrokeInternal(domPath->path(), x, y); } -bool CanvasRenderingContext2D::isPointInStrokeInternal(const Path& path, const float x, const float y) +bool CanvasRenderingContext2D::isPointInStrokeInternal(const Path& path, const double x, const double y) { SkCanvas* c = drawingCanvas(); if (!c) @@ -1127,7 +1127,9 @@ strokeData.setLineCap(state().lineCap()); strokeData.setLineJoin(state().lineJoin()); strokeData.setMiterLimit(state().miterLimit()); - strokeData.setLineDash(state().lineDash(), state().lineDashOffset()); + Vector<float> lineDash(state().lineDash().size()); + std::copy(state().lineDash().begin(), state().lineDash().end(), lineDash.begin()); + strokeData.setLineDash(lineDash, state().lineDashOffset()); return path.strokeContains(transformedPoint, strokeData); } @@ -1170,7 +1172,7 @@ // selection the specified rectangle of the canvas. See http://crbug.com/357987 } -void CanvasRenderingContext2D::clearRect(float x, float y, float width, float height) +void CanvasRenderingContext2D::clearRect(double x, double y, double width, double height) { if (!validateRectForCanvas(x, y, width, height)) return; @@ -1249,7 +1251,7 @@ return nullptr; } -void CanvasRenderingContext2D::drawImage(const CanvasImageSourceUnion& imageSource, float x, float y, ExceptionState& exceptionState) +void CanvasRenderingContext2D::drawImage(const CanvasImageSourceUnion& imageSource, double x, double y, ExceptionState& exceptionState) { CanvasImageSource* imageSourceInternal = toImageSourceInternal(imageSource); FloatSize sourceRectSize = imageSourceInternal->elementSize(); @@ -1258,7 +1260,7 @@ } void CanvasRenderingContext2D::drawImage(const CanvasImageSourceUnion& imageSource, - float x, float y, float width, float height, ExceptionState& exceptionState) + double x, double y, double width, double height, ExceptionState& exceptionState) { CanvasImageSource* imageSourceInternal = toImageSourceInternal(imageSource); FloatSize sourceRectSize = imageSourceInternal->elementSize(); @@ -1266,8 +1268,8 @@ } void CanvasRenderingContext2D::drawImage(const CanvasImageSourceUnion& imageSource, - float sx, float sy, float sw, float sh, - float dx, float dy, float dw, float dh, ExceptionState& exceptionState) + double sx, double sy, double sw, double sh, + double dx, double dy, double dw, double dh, ExceptionState& exceptionState) { CanvasImageSource* imageSourceInternal = toImageSourceInternal(imageSource); drawImage(imageSourceInternal, sx, sy, sw, sh, dx, dy, dw, dh, exceptionState); @@ -1359,8 +1361,8 @@ } void CanvasRenderingContext2D::drawImage(CanvasImageSource* imageSource, - float sx, float sy, float sw, float sh, - float dx, float dy, float dw, float dh, ExceptionState& exceptionState) + double sx, double sy, double sw, double sh, + double dx, double dy, double dw, double dh, ExceptionState& exceptionState) { if (!drawingCanvas()) return; @@ -1452,13 +1454,13 @@ return state().transform().mapQuad(quad).containsQuad(transformedQuad); } -CanvasGradient* CanvasRenderingContext2D::createLinearGradient(float x0, float y0, float x1, float y1) +CanvasGradient* CanvasRenderingContext2D::createLinearGradient(double x0, double y0, double x1, double y1) { CanvasGradient* gradient = CanvasGradient::create(FloatPoint(x0, y0), FloatPoint(x1, y1)); return gradient; } -CanvasGradient* CanvasRenderingContext2D::createRadialGradient(float x0, float y0, float r0, float x1, float y1, float r1, ExceptionState& exceptionState) +CanvasGradient* CanvasRenderingContext2D::createRadialGradient(double x0, double y0, double r0, double x1, double y1, double r1, ExceptionState& exceptionState) { if (r0 < 0 || r1 < 0) { exceptionState.throwDOMException(IndexSizeError, String::format("The %s provided is less than 0.", r0 < 0 ? "r0" : "r1")); @@ -1560,7 +1562,7 @@ return ImageData::create(imageData->size()); } -ImageData* CanvasRenderingContext2D::createImageData(float sw, float sh, ExceptionState& exceptionState) const +ImageData* CanvasRenderingContext2D::createImageData(double sw, double sh, ExceptionState& exceptionState) const { if (!sw || !sh) { exceptionState.throwDOMException(IndexSizeError, String::format("The source %s is 0.", sw ? "height" : "width")); @@ -1580,7 +1582,7 @@ return ImageData::create(size); } -ImageData* CanvasRenderingContext2D::getImageData(float sx, float sy, float sw, float sh, ExceptionState& exceptionState) const +ImageData* CanvasRenderingContext2D::getImageData(double sx, double sy, double sw, double sh, ExceptionState& exceptionState) const { if (!canvas()->originClean()) exceptionState.throwSecurityError("The canvas has been tainted by cross-origin data."); @@ -1622,12 +1624,12 @@ DOMUint8ClampedArray::create(arrayBuffer, 0, arrayBuffer->byteLength())); } -void CanvasRenderingContext2D::putImageData(ImageData* data, float dx, float dy, ExceptionState& exceptionState) +void CanvasRenderingContext2D::putImageData(ImageData* data, double dx, double dy, ExceptionState& exceptionState) { putImageData(data, dx, dy, 0, 0, data->width(), data->height(), exceptionState); } -void CanvasRenderingContext2D::putImageData(ImageData* data, float dx, float dy, float dirtyX, float dirtyY, float dirtyWidth, float dirtyHeight, ExceptionState& exceptionState) +void CanvasRenderingContext2D::putImageData(ImageData* data, double dx, double dy, double dirtyX, double dirtyY, double dirtyWidth, double dirtyHeight, ExceptionState& exceptionState) { if (data->data()->bufferBase()->isNeutered()) { exceptionState.throwDOMException(InvalidStateError, "The source data has been neutered."); @@ -1873,22 +1875,22 @@ modifiableState().setDirection(direction); } -void CanvasRenderingContext2D::fillText(const String& text, float x, float y) +void CanvasRenderingContext2D::fillText(const String& text, double x, double y) { drawTextInternal(text, x, y, CanvasRenderingContext2DState::FillPaintType); } -void CanvasRenderingContext2D::fillText(const String& text, float x, float y, float maxWidth) +void CanvasRenderingContext2D::fillText(const String& text, double x, double y, double maxWidth) { drawTextInternal(text, x, y, CanvasRenderingContext2DState::FillPaintType, &maxWidth); } -void CanvasRenderingContext2D::strokeText(const String& text, float x, float y) +void CanvasRenderingContext2D::strokeText(const String& text, double x, double y) { drawTextInternal(text, x, y, CanvasRenderingContext2DState::StrokePaintType); } -void CanvasRenderingContext2D::strokeText(const String& text, float x, float y, float maxWidth) +void CanvasRenderingContext2D::strokeText(const String& text, double x, double y, double maxWidth) { drawTextInternal(text, x, y, CanvasRenderingContext2DState::StrokePaintType, &maxWidth); } @@ -1940,7 +1942,7 @@ return metrics; } -void CanvasRenderingContext2D::drawTextInternal(const String& text, float x, float y, CanvasRenderingContext2DState::PaintType paintType, float* maxWidth) +void CanvasRenderingContext2D::drawTextInternal(const String& text, double x, double y, CanvasRenderingContext2DState::PaintType paintType, double* maxWidth) { // The style resolution required for rendering text is not available in frame-less documents. if (!canvas()->document().frame()) @@ -1974,10 +1976,10 @@ textRun.setNormalizeSpace(true); // Draw the item text at the correct point. FloatPoint location(x, y + getFontBaseline(fontMetrics)); - float fontWidth = font.width(textRun); + double fontWidth = font.width(textRun); bool useMaxWidth = (maxWidth && *maxWidth < fontWidth); - float width = useMaxWidth ? *maxWidth : fontWidth; + double width = useMaxWidth ? *maxWidth : fontWidth; TextAlign align = state().textAlign(); if (align == StartTextAlign) @@ -2031,8 +2033,8 @@ // Fast approximation of the stroke's bounding rect. // This yields a slightly oversized rect but is very fast // compared to Path::strokeBoundingRect(). - static const float root2 = sqrtf(2); - float delta = state().lineWidth() / 2; + static const double root2 = sqrtf(2); + double delta = state().lineWidth() / 2; if (state().lineJoin() == MiterJoin) delta *= state().miterLimit(); else if (state().lineCap() == SquareCap)
diff --git a/third_party/WebKit/Source/modules/canvas2d/CanvasRenderingContext2D.h b/third_party/WebKit/Source/modules/canvas2d/CanvasRenderingContext2D.h index 3611fb80..d31e65a2 100644 --- a/third_party/WebKit/Source/modules/canvas2d/CanvasRenderingContext2D.h +++ b/third_party/WebKit/Source/modules/canvas2d/CanvasRenderingContext2D.h
@@ -86,8 +86,8 @@ void fillStyle(StringOrCanvasGradientOrCanvasPattern&) const; void setFillStyle(const StringOrCanvasGradientOrCanvasPattern&); - float lineWidth() const; - void setLineWidth(float); + double lineWidth() const; + void setLineWidth(double); String lineCap() const; void setLineCap(const String&); @@ -95,29 +95,29 @@ String lineJoin() const; void setLineJoin(const String&); - float miterLimit() const; - void setMiterLimit(float); + double miterLimit() const; + void setMiterLimit(double); - const Vector<float>& getLineDash() const; - void setLineDash(const Vector<float>&); + const Vector<double>& getLineDash() const; + void setLineDash(const Vector<double>&); - float lineDashOffset() const; - void setLineDashOffset(float); + double lineDashOffset() const; + void setLineDashOffset(double); - float shadowOffsetX() const; - void setShadowOffsetX(float); + double shadowOffsetX() const; + void setShadowOffsetX(double); - float shadowOffsetY() const; - void setShadowOffsetY(float); + double shadowOffsetY() const; + void setShadowOffsetY(double); - float shadowBlur() const; - void setShadowBlur(float); + double shadowBlur() const; + void setShadowBlur(double); String shadowColor() const; void setShadowColor(const String&); - float globalAlpha() const; - void setGlobalAlpha(float); + double globalAlpha() const; + void setGlobalAlpha(double); bool isContextLost() const override; @@ -136,11 +136,11 @@ PassRefPtrWillBeRawPtr<SVGMatrixTearOff> currentTransform() const; void setCurrentTransform(PassRefPtrWillBeRawPtr<SVGMatrixTearOff>); - void scale(float sx, float sy); - void rotate(float angleInRadians); - void translate(float tx, float ty); - void transform(float m11, float m12, float m21, float m22, float dx, float dy); - void setTransform(float m11, float m12, float m21, float m22, float dx, float dy); + void scale(double sx, double sy); + void rotate(double angleInRadians); + void translate(double tx, double ty); + void transform(double m11, double m12, double m21, double m22, double dx, double dy); + void setTransform(double m11, double m12, double m21, double m22, double dx, double dy); void resetTransform(); void beginPath(); @@ -152,32 +152,32 @@ void clip(const String& winding = "nonzero"); void clip(Path2D*, const String& winding = "nonzero"); - bool isPointInPath(const float x, const float y, const String& winding = "nonzero"); - bool isPointInPath(Path2D*, const float x, const float y, const String& winding = "nonzero"); - bool isPointInStroke(const float x, const float y); - bool isPointInStroke(Path2D*, const float x, const float y); + bool isPointInPath(const double x, const double y, const String& winding = "nonzero"); + bool isPointInPath(Path2D*, const double x, const double y, const String& winding = "nonzero"); + bool isPointInStroke(const double x, const double y); + bool isPointInStroke(Path2D*, const double x, const double y); void scrollPathIntoView(); void scrollPathIntoView(Path2D*); - void clearRect(float x, float y, float width, float height) override; - void fillRect(float x, float y, float width, float height); - void strokeRect(float x, float y, float width, float height); + void clearRect(double x, double y, double width, double height) override; + void fillRect(double x, double y, double width, double height); + void strokeRect(double x, double y, double width, double height); - void drawImage(const CanvasImageSourceUnion&, float x, float y, ExceptionState&); - void drawImage(const CanvasImageSourceUnion&, float x, float y, float width, float height, ExceptionState&); - void drawImage(const CanvasImageSourceUnion&, float sx, float sy, float sw, float sh, float dx, float dy, float dw, float dh, ExceptionState&); - void drawImage(CanvasImageSource*, float sx, float sy, float sw, float sh, float dx, float dy, float dw, float dh, ExceptionState&); + void drawImage(const CanvasImageSourceUnion&, double x, double y, ExceptionState&); + void drawImage(const CanvasImageSourceUnion&, double x, double y, double width, double height, ExceptionState&); + void drawImage(const CanvasImageSourceUnion&, double sx, double sy, double sw, double sh, double dx, double dy, double dw, double dh, ExceptionState&); + void drawImage(CanvasImageSource*, double sx, double sy, double sw, double sh, double dx, double dy, double dw, double dh, ExceptionState&); - CanvasGradient* createLinearGradient(float x0, float y0, float x1, float y1); - CanvasGradient* createRadialGradient(float x0, float y0, float r0, float x1, float y1, float r1, ExceptionState&); + CanvasGradient* createLinearGradient(double x0, double y0, double x1, double y1); + CanvasGradient* createRadialGradient(double x0, double y0, double r0, double x1, double y1, double r1, ExceptionState&); CanvasPattern* createPattern(const CanvasImageSourceUnion&, const String& repetitionType, ExceptionState&); ImageData* createImageData(ImageData*) const; - ImageData* createImageData(float width, float height, ExceptionState&) const; - ImageData* getImageData(float sx, float sy, float sw, float sh, ExceptionState&) const; - void putImageData(ImageData*, float dx, float dy, ExceptionState&); - void putImageData(ImageData*, float dx, float dy, float dirtyX, float dirtyY, float dirtyWidth, float dirtyHeight, ExceptionState&); + ImageData* createImageData(double width, double height, ExceptionState&) const; + ImageData* getImageData(double sx, double sy, double sw, double sh, ExceptionState&) const; + void putImageData(ImageData*, double dx, double dy, ExceptionState&); + void putImageData(ImageData*, double dx, double dy, double dirtyX, double dirtyY, double dirtyWidth, double dirtyHeight, ExceptionState&); void reset() override; @@ -193,10 +193,10 @@ String direction() const; void setDirection(const String&); - void fillText(const String& text, float x, float y); - void fillText(const String& text, float x, float y, float maxWidth); - void strokeText(const String& text, float x, float y); - void strokeText(const String& text, float x, float y, float maxWidth); + void fillText(const String& text, double x, double y); + void fillText(const String& text, double x, double y, double maxWidth); + void strokeText(const String& text, double x, double y); + void strokeText(const String& text, double x, double y, double maxWidth); TextMetrics* measureText(const String& text); bool imageSmoothingEnabled() const; @@ -234,7 +234,7 @@ CanvasRenderingContext2DState& modifiableState(); const CanvasRenderingContext2DState& state() const { return *m_stateStack.last(); } - void setShadow(const FloatSize& offset, float blur, RGBA32 color); + void setShadow(const FloatSize& offset, double blur, RGBA32 color); void dispatchContextLostEvent(Timer<CanvasRenderingContext2D>*); void dispatchContextRestoredEvent(Timer<CanvasRenderingContext2D>*); @@ -260,12 +260,12 @@ void drawImageInternal(SkCanvas*, CanvasImageSource*, Image*, const FloatRect& srcRect, const FloatRect& dstRect, const SkPaint*); void clipInternal(const Path&, const String& windingRuleString); - bool isPointInPathInternal(const Path&, const float x, const float y, const String& windingRuleString); - bool isPointInStrokeInternal(const Path&, const float x, const float y); + bool isPointInPathInternal(const Path&, const double x, const double y, const String& windingRuleString); + bool isPointInStrokeInternal(const Path&, const double x, const double y); void scrollPathIntoViewInternal(const Path&); - void drawTextInternal(const String&, float x, float y, CanvasRenderingContext2DState::PaintType, float* maxWidth = nullptr); + void drawTextInternal(const String&, double x, double y, CanvasRenderingContext2DState::PaintType, double* maxWidth = nullptr); const Font& accessFont(); int getFontBaseline(const FontMetrics&) const;
diff --git a/third_party/WebKit/Source/modules/canvas2d/CanvasRenderingContext2D.idl b/third_party/WebKit/Source/modules/canvas2d/CanvasRenderingContext2D.idl index 2a53fa86..d81da97 100644 --- a/third_party/WebKit/Source/modules/canvas2d/CanvasRenderingContext2D.idl +++ b/third_party/WebKit/Source/modules/canvas2d/CanvasRenderingContext2D.idl
@@ -25,7 +25,6 @@ // http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#canvasrenderingcontext2d -// FIXME: float => double throughout typedef (HTMLImageElement or HTMLVideoElement or HTMLCanvasElement or @@ -49,17 +48,17 @@ // transformations (default transform is the identity matrix) [RuntimeEnabled=ExperimentalCanvasFeatures] attribute SVGMatrix currentTransform; - void scale(unrestricted float x, unrestricted float y); - void rotate(unrestricted float angle); - void translate(unrestricted float x, unrestricted float y); - void transform(unrestricted float a, unrestricted float b, unrestricted float c, unrestricted float d, unrestricted float e, unrestricted float f); - void setTransform(unrestricted float a, unrestricted float b, unrestricted float c, unrestricted float d, unrestricted float e, unrestricted float f); + void scale(unrestricted double x, unrestricted double y); + void rotate(unrestricted double angle); + void translate(unrestricted double x, unrestricted double y); + void transform(unrestricted double a, unrestricted double b, unrestricted double c, unrestricted double d, unrestricted double e, unrestricted double f); + void setTransform(unrestricted double a, unrestricted double b, unrestricted double c, unrestricted double d, unrestricted double e, unrestricted double f); void resetTransform(); // compositing - attribute unrestricted float globalAlpha; // (default 1.0) + attribute unrestricted double globalAlpha; // (default 1.0) attribute DOMString globalCompositeOperation; // (default source-over) - [RuntimeEnabled=ExperimentalCanvasFeatures] attribute DOMString filter; // (default 'none') + [RuntimeEnabled=ExperimentalCanvasFeatures] attribute DOMString filter; // (default 'none') // image smoothing [ImplementedAs=imageSmoothingEnabled, DeprecateAs=PrefixedImageSmoothingEnabled] attribute boolean webkitImageSmoothingEnabled; @@ -69,20 +68,20 @@ // colors and styles (see also the CanvasDrawingStyles interface) attribute (DOMString or CanvasGradient or CanvasPattern) strokeStyle; // (default black) attribute (DOMString or CanvasGradient or CanvasPattern) fillStyle; // (default black) - CanvasGradient createLinearGradient(float x0, float y0, float x1, float y1); - [RaisesException] CanvasGradient createRadialGradient(float x0, float y0, float r0, float x1, float y1, float r1); + CanvasGradient createLinearGradient(double x0, double y0, double x1, double y1); + [RaisesException] CanvasGradient createRadialGradient(double x0, double y0, double r0, double x1, double y1, double r1); [RaisesException] CanvasPattern createPattern(CanvasImageSource image, DOMString? repetitionType); // shadows - attribute unrestricted float shadowOffsetX; - attribute unrestricted float shadowOffsetY; - attribute unrestricted float shadowBlur; + attribute unrestricted double shadowOffsetX; + attribute unrestricted double shadowOffsetY; + attribute unrestricted double shadowBlur; attribute DOMString shadowColor; // rects - void clearRect(unrestricted float x, unrestricted float y, unrestricted float width, unrestricted float height); - void fillRect(unrestricted float x, unrestricted float y, unrestricted float width, unrestricted float height); - void strokeRect(unrestricted float x, unrestricted float y, unrestricted float width, unrestricted float height); + void clearRect(unrestricted double x, unrestricted double y, unrestricted double width, unrestricted double height); + void fillRect(unrestricted double x, unrestricted double y, unrestricted double width, unrestricted double height); + void strokeRect(unrestricted double x, unrestricted double y, unrestricted double width, unrestricted double height); // path API (see also CanvasPathMethods) void beginPath(); @@ -97,20 +96,20 @@ [RuntimeEnabled=ExperimentalCanvasFeatures] void scrollPathIntoView(optional Path2D path); void clip(optional CanvasFillRule winding); void clip(Path2D path, optional CanvasFillRule winding); - boolean isPointInPath(unrestricted float x, unrestricted float y, optional CanvasFillRule winding); - boolean isPointInPath(Path2D path, unrestricted float x, unrestricted float y, optional CanvasFillRule winding); - boolean isPointInStroke(unrestricted float x, unrestricted float y); - boolean isPointInStroke(Path2D path, unrestricted float x, unrestricted float y); + boolean isPointInPath(unrestricted double x, unrestricted double y, optional CanvasFillRule winding); + boolean isPointInPath(Path2D path, unrestricted double x, unrestricted double y, optional CanvasFillRule winding); + boolean isPointInStroke(unrestricted double x, unrestricted double y); + boolean isPointInStroke(Path2D path, unrestricted double x, unrestricted double y); // text (see also the CanvasDrawingStyles interface) - void fillText(DOMString text, unrestricted float x, unrestricted float y, optional unrestricted float maxWidth); - void strokeText(DOMString text, unrestricted float x, unrestricted float y, optional unrestricted float maxWidth); + void fillText(DOMString text, unrestricted double x, unrestricted double y, optional unrestricted double maxWidth); + void strokeText(DOMString text, unrestricted double x, unrestricted double y, optional unrestricted double maxWidth); TextMetrics measureText(DOMString text); // drawing images - [RaisesException] void drawImage(CanvasImageSource image, unrestricted float x, unrestricted float y); - [RaisesException] void drawImage(CanvasImageSource image, unrestricted float x, unrestricted float y, unrestricted float width, unrestricted float height); - [RaisesException] void drawImage(CanvasImageSource image, unrestricted float sx, unrestricted float sy, unrestricted float sw, unrestricted float sh, unrestricted float dx, unrestricted float dy, unrestricted float dw, unrestricted float dh); + [RaisesException] void drawImage(CanvasImageSource image, unrestricted double x, unrestricted double y); + [RaisesException] void drawImage(CanvasImageSource image, unrestricted double x, unrestricted double y, unrestricted double width, unrestricted double height); + [RaisesException] void drawImage(CanvasImageSource image, unrestricted double sx, unrestricted double sy, unrestricted double sw, unrestricted double sh, unrestricted double dx, unrestricted double dy, unrestricted double dw, unrestricted double dh); // hit regions [RuntimeEnabled=ExperimentalCanvasFeatures, RaisesException] void addHitRegion(optional HitRegionOptions options); @@ -119,10 +118,10 @@ // pixel manipulation ImageData createImageData(ImageData imagedata); - [RaisesException] ImageData createImageData(float sw, float sh); - [RaisesException] ImageData getImageData(float sx, float sy, float sw, float sh); - [RaisesException] void putImageData(ImageData imagedata, float dx, float dy); - [RaisesException] void putImageData(ImageData imagedata, float dx, float dy, float dirtyX, float dirtyY, float dirtyWidth, float dirtyHeight); + [RaisesException] ImageData createImageData(double sw, double sh); + [RaisesException] ImageData getImageData(double sx, double sy, double sw, double sh); + [RaisesException] void putImageData(ImageData imagedata, double dx, double dy); + [RaisesException] void putImageData(ImageData imagedata, double dx, double dy, double dirtyX, double dirtyY, double dirtyWidth, double dirtyHeight); // Context state // Should be merged with WebGL counterpart in CanvasRenderingContext, once no-longer experimental @@ -132,15 +131,15 @@ // FIXME: factor out to CanvasDrawingStyles // line caps/joins - attribute unrestricted float lineWidth; // (default 1) + attribute unrestricted double lineWidth; // (default 1) attribute DOMString lineCap; // "butt", "round", "square" (default "butt") attribute DOMString lineJoin; // "round", "bevel", "miter" (default "miter") - attribute unrestricted float miterLimit; // (default 10) + attribute unrestricted double miterLimit; // (default 10) // dashed lines - void setLineDash(sequence<unrestricted float> dash); - sequence<unrestricted float> getLineDash(); - attribute unrestricted float lineDashOffset; + void setLineDash(sequence<unrestricted double> dash); + sequence<unrestricted double> getLineDash(); + attribute unrestricted double lineDashOffset; // text attribute DOMString font; // (default 10px sans-serif)
diff --git a/third_party/WebKit/Source/modules/canvas2d/CanvasRenderingContext2DAPITest.cpp b/third_party/WebKit/Source/modules/canvas2d/CanvasRenderingContext2DAPITest.cpp index fd27941..40457feb 100644 --- a/third_party/WebKit/Source/modules/canvas2d/CanvasRenderingContext2DAPITest.cpp +++ b/third_party/WebKit/Source/modules/canvas2d/CanvasRenderingContext2DAPITest.cpp
@@ -183,7 +183,7 @@ { createContext(NonOpaque); - Vector<float> simpleDash; + Vector<double> simpleDash; simpleDash.append(4); simpleDash.append(2);
diff --git a/third_party/WebKit/Source/modules/canvas2d/CanvasRenderingContext2DState.cpp b/third_party/WebKit/Source/modules/canvas2d/CanvasRenderingContext2DState.cpp index 17059a8e..bdd146b 100644 --- a/third_party/WebKit/Source/modules/canvas2d/CanvasRenderingContext2DState.cpp +++ b/third_party/WebKit/Source/modules/canvas2d/CanvasRenderingContext2DState.cpp
@@ -187,13 +187,13 @@ CSSFontSelectorClient::trace(visitor); } -void CanvasRenderingContext2DState::setLineDashOffset(float offset) +void CanvasRenderingContext2DState::setLineDashOffset(double offset) { m_lineDashOffset = offset; m_lineDashDirty = true; } -void CanvasRenderingContext2DState::setLineDash(const Vector<float>& dash) +void CanvasRenderingContext2DState::setLineDash(const Vector<double>& dash) { m_lineDash = dash; // Spec requires the concatenation of two copies the dash list when the @@ -204,10 +204,10 @@ m_lineDashDirty = true; } -static bool hasANonZeroElement(const Vector<float>& lineDash) +static bool hasANonZeroElement(const Vector<double>& lineDash) { for (size_t i = 0; i < lineDash.size(); i++) { - if (lineDash[i] != 0.0f) + if (lineDash[i] != 0.0) return true; } return false; @@ -221,7 +221,9 @@ if (!hasANonZeroElement(m_lineDash)) { m_strokePaint.setPathEffect(0); } else { - RefPtr<SkPathEffect> dashPathEffect = adoptRef(SkDashPathEffect::Create(m_lineDash.data(), m_lineDash.size(), m_lineDashOffset)); + Vector<float> lineDash(m_lineDash.size()); + std::copy(m_lineDash.begin(), m_lineDash.end(), lineDash.begin()); + RefPtr<SkPathEffect> dashPathEffect = adoptRef(SkDashPathEffect::Create(lineDash.data(), lineDash.size(), m_lineDashOffset)); m_strokePaint.setPathEffect(dashPathEffect.get()); } @@ -234,22 +236,12 @@ m_strokeStyleDirty = true; } -CanvasStyle* CanvasRenderingContext2DState::strokeStyle() const -{ - return m_strokeStyle.get(); -} - void CanvasRenderingContext2DState::setFillStyle(CanvasStyle* style) { m_fillStyle = style; m_fillStyleDirty = true; } -CanvasStyle* CanvasRenderingContext2DState::fillStyle() const -{ - return m_fillStyle.get(); -} - void CanvasRenderingContext2DState::updateStrokeStyle() const { if (!m_strokeStyleDirty) @@ -301,7 +293,7 @@ return m_fillPaint.isAntiAlias(); } -void CanvasRenderingContext2DState::setGlobalAlpha(float alpha) +void CanvasRenderingContext2DState::setGlobalAlpha(double alpha) { m_globalAlpha = alpha; m_strokeStyleDirty = true; @@ -368,7 +360,7 @@ // StrokePaint respectively for filters that reference SVG. StyleBuilder::applyProperty(CSSPropertyWebkitFilter, resolverState, m_filterValue.get()); RefPtrWillBeRawPtr<FilterEffectBuilder> filterEffectBuilder = FilterEffectBuilder::create(); - const float effectiveZoom = 1.0f; // Deliberately ignore zoom on the canvas element + const double effectiveZoom = 1.0; // Deliberately ignore zoom on the canvas element filterEffectBuilder->build(styleResolutionHost, filterStyle->filter(), effectiveZoom); SkiaImageFilterBuilder imageFilterBuilder; @@ -412,7 +404,7 @@ SkImageFilter* CanvasRenderingContext2DState::shadowOnlyImageFilter() const { if (!m_shadowOnlyImageFilter) { - float sigma = skBlurRadiusToSigma(m_shadowBlur); + double sigma = skBlurRadiusToSigma(m_shadowBlur); m_shadowOnlyImageFilter = adoptRef(SkDropShadowImageFilter::Create(m_shadowOffset.width(), m_shadowOffset.height(), sigma, sigma, m_shadowColor, SkDropShadowImageFilter::kDrawShadowOnly_ShadowMode)); } return m_shadowOnlyImageFilter.get(); @@ -421,7 +413,7 @@ SkImageFilter* CanvasRenderingContext2DState::shadowAndForegroundImageFilter() const { if (!m_shadowAndForegroundImageFilter) { - float sigma = skBlurRadiusToSigma(m_shadowBlur); + double sigma = skBlurRadiusToSigma(m_shadowBlur); m_shadowAndForegroundImageFilter = adoptRef(SkDropShadowImageFilter::Create(m_shadowOffset.width(), m_shadowOffset.height(), sigma, sigma, m_shadowColor, SkDropShadowImageFilter::kDrawShadowAndForeground_ShadowMode)); } return m_shadowAndForegroundImageFilter.get(); @@ -435,19 +427,19 @@ m_shadowAndForegroundImageFilter.clear(); } -void CanvasRenderingContext2DState::setShadowOffsetX(float x) +void CanvasRenderingContext2DState::setShadowOffsetX(double x) { m_shadowOffset.setWidth(x); shadowParameterChanged(); } -void CanvasRenderingContext2DState::setShadowOffsetY(float y) +void CanvasRenderingContext2DState::setShadowOffsetY(double y) { m_shadowOffset.setHeight(y); shadowParameterChanged(); } -void CanvasRenderingContext2DState::setShadowBlur(float shadowBlur) +void CanvasRenderingContext2DState::setShadowBlur(double shadowBlur) { m_shadowBlur = shadowBlur; shadowParameterChanged();
diff --git a/third_party/WebKit/Source/modules/canvas2d/CanvasRenderingContext2DState.h b/third_party/WebKit/Source/modules/canvas2d/CanvasRenderingContext2DState.h index 39905ed..326700a 100644 --- a/third_party/WebKit/Source/modules/canvas2d/CanvasRenderingContext2DState.h +++ b/third_party/WebKit/Source/modules/canvas2d/CanvasRenderingContext2DState.h
@@ -55,14 +55,14 @@ void restore() { --m_unrealizedSaveCount; } void resetUnrealizedSaveCount() { m_unrealizedSaveCount = 0; } - void setLineDash(const Vector<float>&); - const Vector<float>& lineDash() const { return m_lineDash; } + void setLineDash(const Vector<double>&); + const Vector<double>& lineDash() const { return m_lineDash; } void setShouldAntialias(bool); bool shouldAntialias() const; - void setLineDashOffset(float); - float lineDashOffset() const { return m_lineDashOffset; } + void setLineDashOffset(double); + double lineDashOffset() const { return m_lineDashOffset; } // setTransform returns true iff transform is invertible; void setTransform(const AffineTransform&); @@ -88,10 +88,10 @@ bool hasFilter() const { return m_filterValue; } void setStrokeStyle(CanvasStyle*); - CanvasStyle* strokeStyle() const; + CanvasStyle* strokeStyle() const { return m_strokeStyle.get(); } void setFillStyle(CanvasStyle*); - CanvasStyle* fillStyle() const; + CanvasStyle* fillStyle() const { return m_fillStyle.get(); } CanvasStyle* style(PaintType) const; @@ -110,8 +110,8 @@ void setTextBaseline(TextBaseline baseline) { m_textBaseline = baseline; } TextBaseline textBaseline() const { return m_textBaseline; } - void setLineWidth(float lineWidth) { m_strokePaint.setStrokeWidth(lineWidth); } - float lineWidth() const { return m_strokePaint.getStrokeWidth(); } + void setLineWidth(double lineWidth) { m_strokePaint.setStrokeWidth(lineWidth); } + double lineWidth() const { return m_strokePaint.getStrokeWidth(); } void setLineCap(LineCap lineCap) { m_strokePaint.setStrokeCap(static_cast<SkPaint::Cap>(lineCap)); } LineCap lineCap() const { return static_cast<LineCap>(m_strokePaint.getStrokeCap()); } @@ -119,21 +119,21 @@ void setLineJoin(LineJoin lineJoin) { m_strokePaint.setStrokeJoin(static_cast<SkPaint::Join>(lineJoin)); } LineJoin lineJoin() const { return static_cast<LineJoin>(m_strokePaint.getStrokeJoin()); } - void setMiterLimit(float miterLimit) { m_strokePaint.setStrokeMiter(miterLimit); } - float miterLimit() const { return m_strokePaint.getStrokeMiter(); } + void setMiterLimit(double miterLimit) { m_strokePaint.setStrokeMiter(miterLimit); } + double miterLimit() const { return m_strokePaint.getStrokeMiter(); } - void setShadowOffsetX(float); - void setShadowOffsetY(float); + void setShadowOffsetX(double); + void setShadowOffsetY(double); const FloatSize& shadowOffset() const { return m_shadowOffset; } - void setShadowBlur(float); - float shadowBlur() const { return m_shadowBlur; } + void setShadowBlur(double); + double shadowBlur() const { return m_shadowBlur; } void setShadowColor(SkColor); SkColor shadowColor() const { return m_shadowColor; } - void setGlobalAlpha(float); - float globalAlpha() const { return m_globalAlpha; } + void setGlobalAlpha(double); + double globalAlpha() const { return m_globalAlpha; } void setGlobalComposite(SkXfermode::Mode); SkXfermode::Mode globalComposite() const; @@ -188,7 +188,7 @@ mutable SkPaint m_imagePaint; FloatSize m_shadowOffset; - float m_shadowBlur; + double m_shadowBlur; SkColor m_shadowColor; mutable RefPtr<SkDrawLooper> m_emptyDrawLooper; mutable RefPtr<SkDrawLooper> m_shadowOnlyDrawLooper; @@ -196,10 +196,10 @@ mutable RefPtr<SkImageFilter> m_shadowOnlyImageFilter; mutable RefPtr<SkImageFilter> m_shadowAndForegroundImageFilter; - float m_globalAlpha; + double m_globalAlpha; AffineTransform m_transform; - Vector<float> m_lineDash; - float m_lineDashOffset; + Vector<double> m_lineDash; + double m_lineDashOffset; String m_unparsedFont; Font m_font;
diff --git a/third_party/WebKit/Source/modules/device_orientation/DeviceMotionEvent.cpp b/third_party/WebKit/Source/modules/device_orientation/DeviceMotionEvent.cpp index 13028f9..1fb8455 100644 --- a/third_party/WebKit/Source/modules/device_orientation/DeviceMotionEvent.cpp +++ b/third_party/WebKit/Source/modules/device_orientation/DeviceMotionEvent.cpp
@@ -60,11 +60,6 @@ m_rotationRate.clear(); } -DeviceMotionData* DeviceMotionEvent::deviceMotionData() const -{ - return m_deviceMotionData.get(); -} - DeviceAcceleration* DeviceMotionEvent::acceleration() { if (!m_deviceMotionData->acceleration())
diff --git a/third_party/WebKit/Source/modules/device_orientation/DeviceMotionEvent.h b/third_party/WebKit/Source/modules/device_orientation/DeviceMotionEvent.h index ae14b60f..7e06710 100644 --- a/third_party/WebKit/Source/modules/device_orientation/DeviceMotionEvent.h +++ b/third_party/WebKit/Source/modules/device_orientation/DeviceMotionEvent.h
@@ -50,7 +50,7 @@ void initDeviceMotionEvent(const AtomicString& type, bool bubbles, bool cancelable, DeviceMotionData*); - DeviceMotionData* deviceMotionData() const; + DeviceMotionData* deviceMotionData() const { return m_deviceMotionData.get(); } DeviceAcceleration* acceleration(); DeviceAcceleration* accelerationIncludingGravity();
diff --git a/third_party/WebKit/Source/modules/device_orientation/DeviceOrientationEvent.cpp b/third_party/WebKit/Source/modules/device_orientation/DeviceOrientationEvent.cpp index bc49411..d34d9ce2 100644 --- a/third_party/WebKit/Source/modules/device_orientation/DeviceOrientationEvent.cpp +++ b/third_party/WebKit/Source/modules/device_orientation/DeviceOrientationEvent.cpp
@@ -54,11 +54,6 @@ m_orientation = DeviceOrientationData::create(alpha, beta, gamma, absolute); } -DeviceOrientationData* DeviceOrientationEvent::orientation() const -{ - return m_orientation.get(); -} - double DeviceOrientationEvent::alpha(bool& isNull) const { if (m_orientation->canProvideAlpha())
diff --git a/third_party/WebKit/Source/modules/device_orientation/DeviceOrientationEvent.h b/third_party/WebKit/Source/modules/device_orientation/DeviceOrientationEvent.h index 6419217..48aa6c7 100644 --- a/third_party/WebKit/Source/modules/device_orientation/DeviceOrientationEvent.h +++ b/third_party/WebKit/Source/modules/device_orientation/DeviceOrientationEvent.h
@@ -49,7 +49,7 @@ void initDeviceOrientationEvent(const AtomicString& type, bool bubbles, bool cancelable, const Nullable<double>& alpha, const Nullable<double>& beta, const Nullable<double>& gamma, const Nullable<bool>& absolute); - DeviceOrientationData* orientation() const; + DeviceOrientationData* orientation() const { return m_orientation.get(); } double alpha(bool& isNull) const; double beta(bool& isNull) const;
diff --git a/third_party/WebKit/Source/modules/fetch/FetchRequestData.cpp b/third_party/WebKit/Source/modules/fetch/FetchRequestData.cpp index e48c29dd..88c6467 100644 --- a/third_party/WebKit/Source/modules/fetch/FetchRequestData.cpp +++ b/third_party/WebKit/Source/modules/fetch/FetchRequestData.cpp
@@ -100,16 +100,6 @@ { } -BodyStreamBuffer* FetchRequestData::buffer() const -{ - return m_buffer; -} - -void FetchRequestData::setBuffer(BodyStreamBuffer* buffer) -{ - m_buffer = buffer; -} - DEFINE_TRACE(FetchRequestData) { visitor->trace(m_buffer);
diff --git a/third_party/WebKit/Source/modules/fetch/FetchRequestData.h b/third_party/WebKit/Source/modules/fetch/FetchRequestData.h index af50d29..fd20e4fb 100644 --- a/third_party/WebKit/Source/modules/fetch/FetchRequestData.h +++ b/third_party/WebKit/Source/modules/fetch/FetchRequestData.h
@@ -64,9 +64,9 @@ Tainting tainting() const { return m_responseTainting; } FetchHeaderList* headerList() const { return m_headerList.get(); } void setHeaderList(FetchHeaderList* headerList) { m_headerList = headerList; } - BodyStreamBuffer* buffer() const; + BodyStreamBuffer* buffer() const { return m_buffer; } // Call Request::refreshBody() after calling setBuffer(). - void setBuffer(BodyStreamBuffer*); + void setBuffer(BodyStreamBuffer* buffer) { m_buffer = buffer; } String mimeType() const { return m_mimeType; } void setMIMEType(const String& type) { m_mimeType = type; } String integrity() const { return m_integrity; }
diff --git a/third_party/WebKit/Source/modules/fetch/Request.cpp b/third_party/WebKit/Source/modules/fetch/Request.cpp index 6a13627..60f7fa71 100644 --- a/third_party/WebKit/Source/modules/fetch/Request.cpp +++ b/third_party/WebKit/Source/modules/fetch/Request.cpp
@@ -50,7 +50,6 @@ Request* Request::createRequestWithRequestOrString(ScriptState* scriptState, Request* inputRequest, const String& inputString, RequestInit& init, ExceptionState& exceptionState) { - // "1. Let |temporaryBody| be null." BodyStreamBuffer* temporaryBody = nullptr; if (inputRequest) { @@ -62,11 +61,11 @@ } } - // "2. If |input| is a Request object and |input|'s body is non-null, run - // these substeps:" + // - "If |input| is a Request object and it is disturbed, throw a + // TypeError." + // - "Let |temporaryBody| be |input|'s request's body if |input| is a + // Request object, and null otherwise." if (inputRequest && inputRequest->hasBody()) { - // "1. If |input|'s used flag is set, throw a TypeError." - // "2. Set |temporaryBody| to |input|'s body." if (inputRequest->bodyUsed()) { exceptionState.throwTypeError("Cannot construct a Request with a Request object that has already been used."); return nullptr; @@ -74,109 +73,132 @@ temporaryBody = inputRequest->bodyBuffer(); } - // "3. Let |request| be |input|'s request, if |input| is a Request object, + // "Let |request| be |input|'s request, if |input| is a Request object, // and a new request otherwise." - // "4. Let origin be entry settings object's origin." + RefPtr<SecurityOrigin> origin = scriptState->executionContext()->securityOrigin(); - // TODO(yhirano): - // "5. Let window be client." - // "6. If request's window is an environment settings object and its - // origin is same origin with origin, set window to request's window." - // "7. If init's window member is present and it is not null, throw a + // TODO(yhirano): Implement the following steps: + // - "Let |window| be client." + // - "If |request|'s window is an environment settings object and its + // origin is same origin with entry settings object's origin, set + // |window| to |request|'s window." + // - "If |init|'s window member is present and it is not null, throw a // TypeError." - // "8. If init's window member is present, set window to no-window." - // "9. Set |request| to a new request whose url is |request|'s current url, - // method is |request|'s method, header list is a copy of |request|'s header - // list, unsafe-request flag is set, client is entry settings object, window - // is window, origin is origin, force-Origin-header flag is set, same-origin - // data-URL flag is set, referrer is request's referrer, referrer policy is - // |request|'s referrer policy, context is the empty string, mode is - // |request|'s mode, credentials mode is |request|'s credentials mode, cache - // mode is |request|'s cache mode, redirect mode is |request|'s redirect - // mode, and integrity metadata is |request|'s integrity metadata." + // - "If |init|'s window member is present, set |window| to no-window." + // + // "Set |request| to a new request whose url is |request|'s current url, + // method is |request|'s method, header list is a copy of |request|'s + // header list, unsafe-request flag is set, client is entry settings object, + // window is |window|, origin is "client", omit-Origin-header flag is + // |request|'s omit-Origin-header flag, same-origin data-URL flag is set, + // referrer is |request|'s referrer, referrer policy is |request|'s + // referrer policy, destination is the empty string, mode is |request|'s + // mode, credentials mode is |request|'s credentials mode, cache mode is + // |request|'s cache mode, redirect mode is |request|'s redirect mode, and + // integrity metadata is |request|'s integrity metadata." FetchRequestData* request = createCopyOfFetchRequestDataForFetch(scriptState, inputRequest ? inputRequest->request() : FetchRequestData::create()); - // "10. Let |fallbackMode| be null." - // "11. Let |fallbackCredentials| be null." - // "12. Let |baseURL| be entry settings object's API base URL." // We don't use fallback values. We set these flags directly in below. + // - "Let |fallbackMode| be null." + // - "Let |fallbackCredentials| be null." + // - "Let |baseURL| be entry settings object's API base URL." - // "13. If |input| is a string, run these substeps:" + // "If |input| is a string, run these substeps:" if (!inputRequest) { - // "1. Let |parsedURL| be the result of parsing |input| with |baseURL|." + // "Let |parsedURL| be the result of parsing |input| with |baseURL|." KURL parsedURL = scriptState->executionContext()->completeURL(inputString); - // "2. If |parsedURL| is failure, throw a TypeError." + // "If |parsedURL| is failure, throw a TypeError." if (!parsedURL.isValid()) { exceptionState.throwTypeError("Failed to parse URL from " + inputString); return nullptr; } - // TODO(yhirano): "3. If |parsedURL| includes credentials, throw a - // TypeError." - // "4. Set |request|'s url to |parsedURL|." + // TODO(yhirano): Implement the following substep: + // "If |parsedURL| includes credentials, throw a TypeError." + // + // "Set |request|'s url to |parsedURL| and replace |request|'s url list + // single URL with a copy of |parsedURL|." request->setURL(parsedURL); - // "5. Set |fallbackMode| to CORS." - // "6. Set |fallbackCredentials| to omit." + // We don't use fallback values. We set these flags directly in below. + // - "Set |fallbackMode| to "cors"." + // - "Set |fallbackCredentials| to "omit"." } - // "14. If any of |init|'s members are present, run these substeps:" + // "If any of |init|'s members are present, run these substeps:" if (init.areAnyMembersSet) { - // "1. If |request|'s |mode| is "navigate", throw a TypeError." + // "If |request|'s |mode| is "navigate", throw a TypeError." if (request->mode() == WebURLRequest::FetchRequestModeNavigate) { exceptionState.throwTypeError("Cannot construct a Request with a Request whose mode is 'navigate' and a non-empty RequestInit."); return nullptr; } - // "2. Unset |request|'s omit-Origin-header flag." - // "3. Set |request|'s referrer to "client"." - // "4. Set |request|'s referrer policy to the empty string." - // => RequestInit::RequestInit. + + // TODO(yhirano): Implement the following substep: + // "Unset |request|'s omit-Origin-header flag." + + // The substep "Set |request|'s referrer to "client"." is performed by + // the code below as follows: + // - |init.referrer.referrer| gets initialized by the RequestInit + // constructor to "about:client" when any of |options|'s members are + // present. + // - The code below does the equivalent as the step specified in the + // spec by processing the "about:client". + + // The substep "Set |request|'s referrer policy to the empty string." + // is also performed by the code below similarly. } - // 15. If |init|'s referrer member is present, run these substeps: - // Note that JS null and undefined are encoded as an empty string and thus - // a null string means referrer member is not set. - // 16. If |init|'s referrerPolicy member is present, set |request|'s - // referrer policy to it. - // areAnyMembersSet will be True, if any members in RequestInit are set and - // hence the referrer member + // The following if-clause performs the following two steps: + // - "If |init|'s referrer member is present, run these substeps:" + // - TODO(yhirano): Implement the following step: + // "If |init|'s referrerPolicy member is present, set |request|'s + // referrer policy to it." + // + // The condition "if any of |init|'s members are present" + // (areAnyMembersSet) is used for the if-clause instead of conditions + // indicating presence of each member as specified in the spec. This is to + // perform the substeps in the previous step together here. if (init.areAnyMembersSet) { - // 1. Let |referrer| be |init|'s referrer member. + // Nothing to do for the step "Let |referrer| be |init|'s referrer + // member." + if (init.referrer.referrer.isEmpty()) { - // 2. if |referrer| is the empty string, set |request|'s referrer to - // "no-referrer" and terminate these substeps. + // "If |referrer| is the empty string, set |request|'s referrer to + // "no-referrer" and terminate these substeps." request->setReferrerString(FetchRequestData::noReferrerString()); } else { - // 3. Let |parsedReferrer| be the result of parsing |referrer| with - // |baseURL|. + // "Let |parsedReferrer| be the result of parsing |referrer| with + // |baseURL|." KURL parsedReferrer = scriptState->executionContext()->completeURL(init.referrer.referrer); if (!parsedReferrer.isValid()) { - // 4. If |parsedReferrer| is failure, throw a TypeError. + // "If |parsedReferrer| is failure, throw a TypeError." exceptionState.throwTypeError("Referrer '" + init.referrer.referrer + "' is not a valid URL."); return nullptr; } if (parsedReferrer.protocolIsAbout() && parsedReferrer.host().isEmpty() && parsedReferrer.path() == "client") { - // 5. If |parsedReferrer|'s non-relative flag is set, scheme is + // "If |parsedReferrer|'s non-relative flag is set, scheme is // "about", and path contains a single string "client", set - // request's referrer to "client" and terminate these substeps. + // request's referrer to "client" and terminate these + // substeps." request->setReferrerString(FetchRequestData::clientReferrerString()); } else if (!origin->isSameSchemeHostPortAndSuborigin(SecurityOrigin::create(parsedReferrer).get())) { - // 6. If |parsedReferrer|'s origin is not same origin with - // |origin|, throw a TypeError. + // "If |parsedReferrer|'s origin is not same origin with + // |origin|, throw a TypeError." exceptionState.throwTypeError("The origin of '" + init.referrer.referrer + "' should be same as '" + origin->toString() + "'"); return nullptr; } else { - // 7. Set |request|'s referrer to |parsedReferrer|. + // "Set |request|'s referrer to |parsedReferrer|." request->setReferrerString(AtomicString(parsedReferrer.string())); } } request->setReferrerPolicy(init.referrer.referrerPolicy); } - // "16. Let |mode| be |init|'s mode member if it is present, and - // |fallbackMode| otherwise." - // "17. If |mode| is "navigate", throw a TypeError. - // "18. If |mode| is non-null, set |request|'s mode to |mode|." + // The following code performs the following steps: + // - "Let |mode| be |init|'s mode member if it is present, and + // |fallbackMode| otherwise." + // - "If |mode| is "navigate", throw a TypeError." + // - "If |mode| is non-null, set |request|'s mode to |mode|." if (init.mode == "navigate") { exceptionState.throwTypeError("Cannot construct a Request with a RequestInit whose mode member is set as 'navigate'."); return nullptr; @@ -188,14 +210,16 @@ } else if (init.mode == "cors") { request->setMode(WebURLRequest::FetchRequestModeCORS); } else { + // |inputRequest| is directly checked here instead of setting and + // checking |fallbackMode| as specified in the spec. if (!inputRequest) request->setMode(WebURLRequest::FetchRequestModeCORS); } - // "19. Let |credentials| be |init|'s credentials member if it is present, - // and |fallbackCredentials| otherwise." - // "20. If |credentials| is non-null, set |request|'s credentials mode to - // |credentials|. + // "Let |credentials| be |init|'s credentials member if it is present, and + // |fallbackCredentials| otherwise." + // "If |credentials| is non-null, set |request|'s credentials mode to + // |credentials|." if (init.credentials == "omit") { request->setCredentials(WebURLRequest::FetchCredentialsModeOmit); } else if (init.credentials == "same-origin") { @@ -207,11 +231,12 @@ request->setCredentials(WebURLRequest::FetchCredentialsModeOmit); } - // TODO(yhirano): "21. If |init|'s cache member is present, set |request|'s - // cache mode to it." + // TODO(yhirano): Implement the following step: + // "If |init|'s cache member is present, set |request|'s cache mode to + // it." - // "22. If |init|'s redirect member is present, set |request|'s redirect - // mode to it." + // "If |init|'s redirect member is present, set |request|'s redirect mode + // to it." if (init.redirect == "follow") { request->setRedirect(WebURLRequest::FetchRedirectModeFollow); } else if (init.redirect == "error") { @@ -225,11 +250,11 @@ if (!init.integrity.isNull()) request->setIntegrity(init.integrity); - // "24. If |init|'s method member is present, let |method| be it and run - // these substeps:" + // "If |init|'s method member is present, let |method| be it and run these + // substeps:" if (!init.method.isNull()) { - // "1. If |method| is not a method or method is a forbidden method, - // throw a TypeError." + // "If |method| is not a method or method is a forbidden method, throw + // a TypeError." if (!isValidHTTPToken(init.method)) { exceptionState.throwTypeError("'" + init.method + "' is not a valid HTTP method."); return nullptr; @@ -238,42 +263,44 @@ exceptionState.throwTypeError("'" + init.method + "' HTTP method is unsupported."); return nullptr; } - // "2. Normalize |method|." - // "3. Set |request|'s method to |method|." + // "Normalize |method|." + // "Set |request|'s method to |method|." request->setMethod(FetchUtils::normalizeMethod(AtomicString(init.method))); } - // "25. Let |r| be a new Request object associated with |request| and a new - // Headers object whose guard is request." + // "Let |r| be a new Request object associated with |request| and a new + // Headers object whose guard is "request"." Request* r = Request::create(scriptState->executionContext(), request); - // "26. Let |headers| be a copy of |r|'s Headers object." - // "27. If |init|'s headers member is present, set |headers| to |init|'s - // headers member." + // Perform the following steps: + // - "Let |headers| be a copy of |r|'s Headers object." + // - "If |init|'s headers member is present, set |headers| to |init|'s + // headers member." + // // We don't create a copy of r's Headers object when init's headers member // is present. Headers* headers = nullptr; if (!init.headers && init.headersDictionary.isUndefinedOrNull()) { headers = r->headers()->clone(); } - // "28. Empty |r|'s request's header list." + // "Empty |r|'s request's header list." r->m_request->headerList()->clearList(); - // "29. If |r|'s request's mode is no CORS, run these substeps: + // "If |r|'s request's mode is "no-cors", run these substeps: if (r->request()->mode() == WebURLRequest::FetchRequestModeNoCORS) { - // "1. If |r|'s request's method is not a simple method, throw a + // "If |r|'s request's method is not a simple method, throw a // TypeError." if (!FetchUtils::isSimpleMethod(r->request()->method())) { exceptionState.throwTypeError("'" + r->request()->method() + "' is unsupported in no-cors mode."); return nullptr; } - // "2. If |request|'s integrity metadata is not the empty string, throw - // a TypeError." + // "If |request|'s integrity metadata is not the empty string, throw a + // TypeError." if (!request->integrity().isEmpty()) { exceptionState.throwTypeError("The integrity attribute is unsupported in no-cors mode."); return nullptr; } - // "3. Set |r|'s Headers object's guard to |request-no-CORS|. + // "Set |r|'s Headers object's guard to "request-no-cors"." r->headers()->setGuard(Headers::RequestNoCORSGuard); } - // "30. Fill |r|'s Headers object with |headers|. Rethrow any exceptions." + // "Fill |r|'s Headers object with |headers|. Rethrow any exceptions." if (init.headers) { ASSERT(init.headersDictionary.isUndefinedOrNull()); r->headers()->fillWith(init.headers.get(), exceptionState); @@ -286,7 +313,7 @@ if (exceptionState.hadException()) return nullptr; - // "31. If either |init|'s body member is present or |temporaryBody| is + // "If either |init|'s body member is present or |temporaryBody| is // non-null, and |request|'s method is `GET` or `HEAD`, throw a TypeError. if (init.body || temporaryBody) { if (request->method() == "GET" || request->method() == "HEAD") { @@ -295,15 +322,16 @@ } } - // "32. If |init|'s body member is present, run these substeps:" + // "If |init|'s body member is present, run these substeps:" if (init.body) { - // "1. Let |stream| and |Content-Type| be the result of extracting - // |init|'s body member." - // "2. Set |temporaryBody| to |stream|. - // "3. If |Content-Type| is non-null and |r|'s request's header list - // contains no header named `Content-Type`, append - // `Content-Type`/|Content-Type| to |r|'s Headers object. Rethrow any - // exception." + // Perform the following steps: + // - "Let |stream| and |Content-Type| be the result of extracting + // |init|'s body member." + // - "Set |temporaryBody| to |stream|. + // - "If |Content-Type| is non-null and |r|'s request's header list + // contains no header named `Content-Type`, append + // `Content-Type`/|Content-Type| to |r|'s Headers object. Rethrow any + // exception." temporaryBody = new BodyStreamBuffer(init.body.release()); if (!init.contentType.isEmpty() && !r->headers()->has("Content-Type", exceptionState)) { r->headers()->append("Content-Type", init.contentType, exceptionState); @@ -312,7 +340,7 @@ return nullptr; } - // "33. Set |r|'s body to |temporaryBody|. + // "Set |r|'s request's body to |temporaryBody|. if (temporaryBody) r->m_request->setBuffer(temporaryBody); @@ -332,22 +360,23 @@ r->setOpaque(); } - // "34. Set |r|'s MIME type to the result of extracting a MIME type from - // |r|'s request's header list." + // "Set |r|'s MIME type to the result of extracting a MIME type from |r|'s + // request's header list." r->m_request->setMIMEType(r->m_request->headerList()->extractMIMEType()); - // "35. If |input| is a Request object and |input|'s body is non-null, run - // these substeps:" + // "If |input| is a Request object and |input|'s request's body is + // non-null, run these substeps:" + // // We set bodyUsed even when the body is null in spite of the // spec. See https://github.com/whatwg/fetch/issues/61 for details. if (inputRequest) { - // "1. Set |input|'s body to null." + // "Set |input|'s body to an empty byte stream." inputRequest->m_request->setBuffer(nullptr); - // "2. Set |input|'s used flag." + // "Set |input|'s disturbed flag." inputRequest->setBodyPassed(); } - // "36. Return |r|." + // "Return |r|." return r; }
diff --git a/third_party/WebKit/Source/modules/fetch/RequestInit.cpp b/third_party/WebKit/Source/modules/fetch/RequestInit.cpp index 703199c..a356d26 100644 --- a/third_party/WebKit/Source/modules/fetch/RequestInit.cpp +++ b/third_party/WebKit/Source/modules/fetch/RequestInit.cpp
@@ -54,10 +54,9 @@ areAnyMembersSet |= isBodySet; if (areAnyMembersSet) { - // If any of init's members are present, unset request's - // omit-Origin-header flag, set request's referrer to "client", - // and request's referrer policy to the empty string. - // + // A part of the Request constructor algorithm is performed here. See + // the comments in the Request constructor code for the detail. + // We need to use "about:client" instead of |clientReferrerString|, // because "about:client" => |clientReferrerString| conversion is done // in Request::createRequestWithRequestOrString.
diff --git a/third_party/WebKit/Source/modules/indexeddb/IDBTransaction.cpp b/third_party/WebKit/Source/modules/indexeddb/IDBTransaction.cpp index 871c758..c4e4763 100644 --- a/third_party/WebKit/Source/modules/indexeddb/IDBTransaction.cpp +++ b/third_party/WebKit/Source/modules/indexeddb/IDBTransaction.cpp
@@ -336,16 +336,6 @@ return objectStoreNames.release(); } -IDBDatabase* IDBTransaction::db() const -{ - return m_database; -} - -DOMException* IDBTransaction::error() const -{ - return m_error; -} - const AtomicString& IDBTransaction::interfaceName() const { return EventTargetNames::IDBTransaction;
diff --git a/third_party/WebKit/Source/modules/indexeddb/IDBTransaction.h b/third_party/WebKit/Source/modules/indexeddb/IDBTransaction.h index 29c94385..631c326 100644 --- a/third_party/WebKit/Source/modules/indexeddb/IDBTransaction.h +++ b/third_party/WebKit/Source/modules/indexeddb/IDBTransaction.h
@@ -75,8 +75,8 @@ // Implement the IDBTransaction IDL const String& mode() const; PassRefPtrWillBeRawPtr<DOMStringList> objectStoreNames() const; - IDBDatabase* db() const; - DOMException* error() const; + IDBDatabase* db() const { return m_database.get(); } + DOMException* error() const { return m_error; } IDBObjectStore* objectStore(const String& name, ExceptionState&); void abort(ExceptionState&);
diff --git a/third_party/WebKit/Source/modules/push_messaging/PushSubscription.cpp b/third_party/WebKit/Source/modules/push_messaging/PushSubscription.cpp index 007b19b..bec2c8e 100644 --- a/third_party/WebKit/Source/modules/push_messaging/PushSubscription.cpp +++ b/third_party/WebKit/Source/modules/push_messaging/PushSubscription.cpp
@@ -35,6 +35,7 @@ PushSubscription::PushSubscription(const WebPushSubscription& subscription, ServiceWorkerRegistration* serviceWorkerRegistration) : m_endpoint(subscription.endpoint) , m_p256dh(DOMArrayBuffer::create(subscription.p256dh.data(), subscription.p256dh.size())) + , m_auth(DOMArrayBuffer::create(subscription.auth.data(), subscription.auth.size())) , m_serviceWorkerRegistration(serviceWorkerRegistration) { } @@ -52,6 +53,8 @@ { if (name == "p256dh") return m_p256dh; + if (name == "auth") + return m_auth; return nullptr; } @@ -78,6 +81,7 @@ V8ObjectBuilder keys(scriptState); keys.add("p256dh", WTF::base64URLEncode(static_cast<const char*>(m_p256dh->data()), m_p256dh->byteLength())); + keys.add("auth", WTF::base64URLEncode(static_cast<const char*>(m_auth->data()), m_auth->byteLength())); result.add("keys", keys); }
diff --git a/third_party/WebKit/Source/modules/push_messaging/PushSubscription.h b/third_party/WebKit/Source/modules/push_messaging/PushSubscription.h index 3a2fac9..02df6adf 100644 --- a/third_party/WebKit/Source/modules/push_messaging/PushSubscription.h +++ b/third_party/WebKit/Source/modules/push_messaging/PushSubscription.h
@@ -42,7 +42,9 @@ PushSubscription(const WebPushSubscription&, ServiceWorkerRegistration*); KURL m_endpoint; + RefPtr<DOMArrayBuffer> m_p256dh; + RefPtr<DOMArrayBuffer> m_auth; Member<ServiceWorkerRegistration> m_serviceWorkerRegistration; };
diff --git a/third_party/WebKit/Source/modules/push_messaging/PushSubscription.idl b/third_party/WebKit/Source/modules/push_messaging/PushSubscription.idl index 7a59bc50..469bd8c 100644 --- a/third_party/WebKit/Source/modules/push_messaging/PushSubscription.idl +++ b/third_party/WebKit/Source/modules/push_messaging/PushSubscription.idl
@@ -5,7 +5,8 @@ // https://w3c.github.io/push-api/#pushsubscription-interface enum PushEncryptionKeyName { - "p256dh" + "p256dh", + "auth" }; [
diff --git a/third_party/WebKit/Source/modules/speech/SpeechRecognition.cpp b/third_party/WebKit/Source/modules/speech/SpeechRecognition.cpp index 3686ab0..bfe1b4e 100644 --- a/third_party/WebKit/Source/modules/speech/SpeechRecognition.cpp +++ b/third_party/WebKit/Source/modules/speech/SpeechRecognition.cpp
@@ -48,16 +48,6 @@ return speechRecognition; } -MediaStreamTrack* SpeechRecognition::audioTrack() const -{ - return m_audioTrack; -} - -void SpeechRecognition::setAudioTrack(MediaStreamTrack* audioTrack) -{ - m_audioTrack = audioTrack; -} - void SpeechRecognition::start(ExceptionState& exceptionState) { if (!m_controller)
diff --git a/third_party/WebKit/Source/modules/speech/SpeechRecognition.h b/third_party/WebKit/Source/modules/speech/SpeechRecognition.h index 8302545..741f2b7 100644 --- a/third_party/WebKit/Source/modules/speech/SpeechRecognition.h +++ b/third_party/WebKit/Source/modules/speech/SpeechRecognition.h
@@ -67,8 +67,8 @@ void setInterimResults(bool interimResults) { m_interimResults = interimResults; } unsigned maxAlternatives() { return m_maxAlternatives; } void setMaxAlternatives(unsigned maxAlternatives) { m_maxAlternatives = maxAlternatives; } - MediaStreamTrack* audioTrack() const; - void setAudioTrack(MediaStreamTrack*); + MediaStreamTrack* audioTrack() { return m_audioTrack; } + void setAudioTrack(MediaStreamTrack* audioTrack) { m_audioTrack = audioTrack; } // Callable by the user. void start(ExceptionState&);
diff --git a/third_party/WebKit/Source/modules/storage/DOMWindowStorage.cpp b/third_party/WebKit/Source/modules/storage/DOMWindowStorage.cpp index e302524..ce756a6 100644 --- a/third_party/WebKit/Source/modules/storage/DOMWindowStorage.cpp +++ b/third_party/WebKit/Source/modules/storage/DOMWindowStorage.cpp
@@ -143,14 +143,4 @@ return m_localStorage; } -Storage* DOMWindowStorage::optionalSessionStorage() const -{ - return m_sessionStorage.get(); -} - -Storage* DOMWindowStorage::optionalLocalStorage() const -{ - return m_localStorage.get(); -} - } // namespace blink
diff --git a/third_party/WebKit/Source/modules/storage/DOMWindowStorage.h b/third_party/WebKit/Source/modules/storage/DOMWindowStorage.h index 8b6e44eb..92e1cfab 100644 --- a/third_party/WebKit/Source/modules/storage/DOMWindowStorage.h +++ b/third_party/WebKit/Source/modules/storage/DOMWindowStorage.h
@@ -26,8 +26,8 @@ Storage* sessionStorage(ExceptionState&) const; Storage* localStorage(ExceptionState&) const; - Storage* optionalSessionStorage() const; - Storage* optionalLocalStorage() const; + Storage* optionalSessionStorage() const { return m_sessionStorage.get(); } + Storage* optionalLocalStorage() const { return m_localStorage.get(); } DECLARE_TRACE();
diff --git a/third_party/WebKit/Source/modules/storage/StorageEvent.cpp b/third_party/WebKit/Source/modules/storage/StorageEvent.cpp index 865e4d6..9100e47 100644 --- a/third_party/WebKit/Source/modules/storage/StorageEvent.cpp +++ b/third_party/WebKit/Source/modules/storage/StorageEvent.cpp
@@ -80,11 +80,6 @@ m_storageArea = initializer.storageArea(); } -Storage* StorageEvent::storageArea() const -{ - return m_storageArea.get(); -} - void StorageEvent::initStorageEvent(const AtomicString& type, bool canBubble, bool cancelable, const String& key, const String& oldValue, const String& newValue, const String& url, Storage* storageArea) { if (dispatched())
diff --git a/third_party/WebKit/Source/modules/storage/StorageEvent.h b/third_party/WebKit/Source/modules/storage/StorageEvent.h index 926c134..8c91631 100644 --- a/third_party/WebKit/Source/modules/storage/StorageEvent.h +++ b/third_party/WebKit/Source/modules/storage/StorageEvent.h
@@ -47,7 +47,7 @@ const String& oldValue() const { return m_oldValue; } const String& newValue() const { return m_newValue; } const String& url() const { return m_url; } - Storage* storageArea() const; + Storage* storageArea() const { return m_storageArea.get(); } void initStorageEvent(const AtomicString& type, bool canBubble, bool cancelable, const String& key, const String& oldValue, const String& newValue, const String& url, Storage* storageArea);
diff --git a/third_party/WebKit/Source/modules/storage/StorageNamespaceController.cpp b/third_party/WebKit/Source/modules/storage/StorageNamespaceController.cpp index e88c825..ee6e1c4c 100644 --- a/third_party/WebKit/Source/modules/storage/StorageNamespaceController.cpp +++ b/third_party/WebKit/Source/modules/storage/StorageNamespaceController.cpp
@@ -32,16 +32,6 @@ visitor->trace(m_inspectorAgent); } -InspectorDOMStorageAgent* StorageNamespaceController::inspectorAgent() -{ - return m_inspectorAgent; -} - -void StorageNamespaceController::setInspectorAgent(InspectorDOMStorageAgent* agent) -{ - m_inspectorAgent = agent; -} - StorageNamespace* StorageNamespaceController::sessionStorage(bool optionalCreate) { if (!m_sessionStorage && optionalCreate)
diff --git a/third_party/WebKit/Source/modules/storage/StorageNamespaceController.h b/third_party/WebKit/Source/modules/storage/StorageNamespaceController.h index d4a9195..849bcb61 100644 --- a/third_party/WebKit/Source/modules/storage/StorageNamespaceController.h +++ b/third_party/WebKit/Source/modules/storage/StorageNamespaceController.h
@@ -29,8 +29,8 @@ DECLARE_TRACE(); - InspectorDOMStorageAgent* inspectorAgent(); - void setInspectorAgent(InspectorDOMStorageAgent*); + InspectorDOMStorageAgent* inspectorAgent() { return m_inspectorAgent; } + void setInspectorAgent(InspectorDOMStorageAgent* agent) { m_inspectorAgent = agent; } private: explicit StorageNamespaceController(StorageClient*); static const char* supplementName();
diff --git a/third_party/WebKit/Source/modules/webaudio/AbstractAudioContext.cpp b/third_party/WebKit/Source/modules/webaudio/AbstractAudioContext.cpp index 712e9f6..fbf90f8 100644 --- a/third_party/WebKit/Source/modules/webaudio/AbstractAudioContext.cpp +++ b/third_party/WebKit/Source/modules/webaudio/AbstractAudioContext.cpp
@@ -213,11 +213,6 @@ m_audioDecoder.decodeAsync(audioData, sampleRate(), successCallback, errorCallback); } -AudioListener* AbstractAudioContext::listener() const -{ - return m_listener; -} - AudioBufferSourceNode* AbstractAudioContext::createBufferSource(ExceptionState& exceptionState) { ASSERT(isMainThread());
diff --git a/third_party/WebKit/Source/modules/webaudio/AbstractAudioContext.h b/third_party/WebKit/Source/modules/webaudio/AbstractAudioContext.h index 0b626f6..10c587f 100644 --- a/third_party/WebKit/Source/modules/webaudio/AbstractAudioContext.h +++ b/third_party/WebKit/Source/modules/webaudio/AbstractAudioContext.h
@@ -133,7 +133,7 @@ // Asynchronous audio file data decoding. void decodeAudioData(DOMArrayBuffer*, AudioBufferCallback*, AudioBufferCallback*, ExceptionState&); - AudioListener* listener() const; + AudioListener* listener() { return m_listener.get(); } virtual bool hasRealtimeConstraint() = 0;
diff --git a/third_party/WebKit/Source/modules/webdatabase/Database.cpp b/third_party/WebKit/Source/modules/webdatabase/Database.cpp index 63a7b21..737f4f8 100644 --- a/third_party/WebKit/Source/modules/webdatabase/Database.cpp +++ b/third_party/WebKit/Source/modules/webdatabase/Database.cpp
@@ -767,11 +767,6 @@ executionContext()->addConsoleMessage(ConsoleMessage::create(StorageMessageSource, ErrorMessageLevel, message)); } -DatabaseContext* Database::databaseContext() const -{ - return m_databaseContext; -} - ExecutionContext* Database::executionContext() const { return databaseContext()->executionContext();
diff --git a/third_party/WebKit/Source/modules/webdatabase/Database.h b/third_party/WebKit/Source/modules/webdatabase/Database.h index da7d4fda..d973a73 100644 --- a/third_party/WebKit/Source/modules/webdatabase/Database.h +++ b/third_party/WebKit/Source/modules/webdatabase/Database.h
@@ -108,7 +108,7 @@ void closeImmediately(); void closeDatabase(); - DatabaseContext* databaseContext() const; + DatabaseContext* databaseContext() const { return m_databaseContext.get(); } ExecutionContext* executionContext() const; private:
diff --git a/third_party/WebKit/Source/modules/webdatabase/DatabaseThread.cpp b/third_party/WebKit/Source/modules/webdatabase/DatabaseThread.cpp index 6235e74..d5da4d1 100644 --- a/third_party/WebKit/Source/modules/webdatabase/DatabaseThread.cpp +++ b/third_party/WebKit/Source/modules/webdatabase/DatabaseThread.cpp
@@ -152,11 +152,6 @@ return !m_terminationRequested && m_openDatabaseSet.contains(database); } -SQLTransactionCoordinator* DatabaseThread::transactionCoordinator() const -{ - return m_transactionCoordinator.get(); -} - void DatabaseThread::scheduleTask(PassOwnPtr<DatabaseTask> task) { ASSERT(m_thread);
diff --git a/third_party/WebKit/Source/modules/webdatabase/DatabaseThread.h b/third_party/WebKit/Source/modules/webdatabase/DatabaseThread.h index d168ad4..58678045 100644 --- a/third_party/WebKit/Source/modules/webdatabase/DatabaseThread.h +++ b/third_party/WebKit/Source/modules/webdatabase/DatabaseThread.h
@@ -64,7 +64,7 @@ bool isDatabaseThread() { return m_thread && m_thread->isCurrentThread(); } SQLTransactionClient* transactionClient() { return m_transactionClient.get(); } - SQLTransactionCoordinator* transactionCoordinator() const; + SQLTransactionCoordinator* transactionCoordinator() { return m_transactionCoordinator.get(); } private: DatabaseThread();
diff --git a/third_party/WebKit/Source/modules/webdatabase/SQLTransaction.cpp b/third_party/WebKit/Source/modules/webdatabase/SQLTransaction.cpp index e4530fa8..f7825b3 100644 --- a/third_party/WebKit/Source/modules/webdatabase/SQLTransaction.cpp +++ b/third_party/WebKit/Source/modules/webdatabase/SQLTransaction.cpp
@@ -334,11 +334,6 @@ m_errorCallback.clear(); } -Database* SQLTransaction::database() const -{ - return m_database; -} - SQLTransactionErrorCallback* SQLTransaction::releaseErrorCallback() { return m_errorCallback.release();
diff --git a/third_party/WebKit/Source/modules/webdatabase/SQLTransaction.h b/third_party/WebKit/Source/modules/webdatabase/SQLTransaction.h index 9e4930e..bd00e96 100644 --- a/third_party/WebKit/Source/modules/webdatabase/SQLTransaction.h +++ b/third_party/WebKit/Source/modules/webdatabase/SQLTransaction.h
@@ -69,7 +69,7 @@ void executeSql(ScriptState*, const String& sqlStatement, const Nullable<Vector<ScriptValue>>& arguments, SQLStatementCallback*, SQLStatementErrorCallback*, ExceptionState&); - Database* database() const; + Database* database() { return m_database.get(); } SQLTransactionErrorCallback* releaseErrorCallback();
diff --git a/third_party/WebKit/Source/modules/webgl/WebGL2RenderingContextBase.cpp b/third_party/WebKit/Source/modules/webgl/WebGL2RenderingContextBase.cpp index 03bf7267b..b14c4a7 100644 --- a/third_party/WebKit/Source/modules/webgl/WebGL2RenderingContextBase.cpp +++ b/third_party/WebKit/Source/modules/webgl/WebGL2RenderingContextBase.cpp
@@ -94,9 +94,6 @@ GL_DEPTH_COMPONENT32F, GL_DEPTH24_STENCIL8, GL_DEPTH32F_STENCIL8, -}; - -const GLenum kCompressedTextureFormatsETC2EAC[] = { GL_COMPRESSED_R11_EAC, GL_COMPRESSED_SIGNED_R11_EAC, GL_COMPRESSED_RG11_EAC, @@ -113,8 +110,6 @@ : WebGLRenderingContextBase(passedCanvas, context, requestedAttributes) { m_supportedInternalFormatsStorage.insert(kSupportedInternalFormatsStorage, kSupportedInternalFormatsStorage + arraysize(kSupportedInternalFormatsStorage)); - m_supportedInternalFormatsStorage.insert(kCompressedTextureFormatsETC2EAC, kCompressedTextureFormatsETC2EAC + arraysize(kCompressedTextureFormatsETC2EAC)); - m_compressedTextureFormatsETC2EAC.insert(kCompressedTextureFormatsETC2EAC, kCompressedTextureFormatsETC2EAC + arraysize(kCompressedTextureFormatsETC2EAC)); } WebGL2RenderingContextBase::~WebGL2RenderingContextBase() @@ -629,11 +624,6 @@ if (!tex) return false; - if (functionType == TexStorageType3D && target != GL_TEXTURE_2D_ARRAY && m_compressedTextureFormatsETC2EAC.find(internalformat) != m_compressedTextureFormatsETC2EAC.end()) { - synthesizeGLError(GL_INVALID_OPERATION, functionName, "target for ETC2/EAC internal formats must be TEXTURE_2D_ARRAY"); - return false; - } - if (m_supportedInternalFormatsStorage.find(internalformat) == m_supportedInternalFormatsStorage.end()) { synthesizeGLError(GL_INVALID_ENUM, functionName, "invalid internalformat"); return false;
diff --git a/third_party/WebKit/Source/modules/webgl/WebGL2RenderingContextBase.h b/third_party/WebKit/Source/modules/webgl/WebGL2RenderingContextBase.h index 70ad5200..3ab1aad 100644 --- a/third_party/WebKit/Source/modules/webgl/WebGL2RenderingContextBase.h +++ b/third_party/WebKit/Source/modules/webgl/WebGL2RenderingContextBase.h
@@ -237,7 +237,6 @@ GLint m_maxArrayTextureLayers; std::set<GLenum> m_supportedInternalFormatsStorage; - std::set<GLenum> m_compressedTextureFormatsETC2EAC; PersistentWillBeMember<WebGLBuffer> m_boundCopyReadBuffer; PersistentWillBeMember<WebGLBuffer> m_boundCopyWriteBuffer;
diff --git a/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.cpp b/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.cpp index bb263d73..a9ecf18 100644 --- a/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.cpp +++ b/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.cpp
@@ -121,22 +121,6 @@ } // namespace -WebGLRenderingContextBase::ScopedDrawingBufferBinder::ScopedDrawingBufferBinder(DrawingBuffer* drawingBuffer, WebGLFramebuffer* framebufferBinding) - : m_drawingBuffer(drawingBuffer) - , m_readFramebufferBinding(framebufferBinding) -{ - // Commit DrawingBuffer if needed (e.g., for multisampling) - if (!m_readFramebufferBinding && m_drawingBuffer) - m_drawingBuffer->commit(); -} - -WebGLRenderingContextBase::ScopedDrawingBufferBinder::~ScopedDrawingBufferBinder() -{ - // Restore DrawingBuffer if needed - if (!m_readFramebufferBinding && m_drawingBuffer) - m_drawingBuffer->restoreFramebufferBindings(); -} - void WebGLRenderingContextBase::forciblyLoseOldestContext(const String& reason) { WebGLRenderingContextBase* candidate = oldestContext();
diff --git a/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.h b/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.h index b8abf71a..748c4ed 100644 --- a/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.h +++ b/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.h
@@ -129,8 +129,21 @@ class ScopedDrawingBufferBinder { STACK_ALLOCATED(); public: - ScopedDrawingBufferBinder(DrawingBuffer*, WebGLFramebuffer*); - ~ScopedDrawingBufferBinder(); + ScopedDrawingBufferBinder(DrawingBuffer* drawingBuffer, WebGLFramebuffer* framebufferBinding) + : m_drawingBuffer(drawingBuffer) + , m_readFramebufferBinding(framebufferBinding) + { + // Commit DrawingBuffer if needed (e.g., for multisampling) + if (!m_readFramebufferBinding && m_drawingBuffer) + m_drawingBuffer->commit(); + } + + ~ScopedDrawingBufferBinder() + { + // Restore DrawingBuffer if needed + if (!m_readFramebufferBinding && m_drawingBuffer) + m_drawingBuffer->restoreFramebufferBindings(); + } private: DrawingBuffer* m_drawingBuffer; @@ -745,8 +758,21 @@ class ScopedDrawingBufferBinder { STACK_ALLOCATED(); public: - ScopedDrawingBufferBinder(DrawingBuffer*, WebGLFramebuffer*); - ~ScopedDrawingBufferBinder(); + ScopedDrawingBufferBinder(DrawingBuffer* drawingBuffer, WebGLFramebuffer* framebufferBinding) + : m_drawingBuffer(drawingBuffer) + , m_readFramebufferBinding(framebufferBinding) + { + // Commit DrawingBuffer if needed (e.g., for multisampling) + if (!m_readFramebufferBinding && m_drawingBuffer) + m_drawingBuffer->commit(); + } + + ~ScopedDrawingBufferBinder() + { + // Restore DrawingBuffer if needed + if (!m_readFramebufferBinding && m_drawingBuffer) + m_drawingBuffer->restoreFramebufferBindings(); + } private: DrawingBuffer* m_drawingBuffer;
diff --git a/third_party/WebKit/Source/platform/BUILD.gn b/third_party/WebKit/Source/platform/BUILD.gn index ec882fe..4fde690f 100644 --- a/third_party/WebKit/Source/platform/BUILD.gn +++ b/third_party/WebKit/Source/platform/BUILD.gn
@@ -397,6 +397,7 @@ "//base", "//base/allocator", "//base/test:test_support", + "//cc/blink", "//skia", "//testing/gmock", "//testing/gtest",
diff --git a/third_party/WebKit/Source/platform/PurgeableVectorTest.cpp b/third_party/WebKit/Source/platform/PurgeableVectorTest.cpp index 258c36e..474cb70 100644 --- a/third_party/WebKit/Source/platform/PurgeableVectorTest.cpp +++ b/third_party/WebKit/Source/platform/PurgeableVectorTest.cpp
@@ -31,7 +31,7 @@ #include "config.h" #include "platform/PurgeableVector.h" -#include "platform/TestingPlatformSupport.h" +#include "platform/testing/TestingPlatformSupport.h" #include "public/platform/WebDiscardableMemory.h" #include "testing/gtest/include/gtest/gtest.h" #include "wtf/Vector.h"
diff --git a/third_party/WebKit/Source/platform/SharedBufferTest.cpp b/third_party/WebKit/Source/platform/SharedBufferTest.cpp index 7f6696f..fe3d239f 100644 --- a/third_party/WebKit/Source/platform/SharedBufferTest.cpp +++ b/third_party/WebKit/Source/platform/SharedBufferTest.cpp
@@ -31,7 +31,7 @@ #include "config.h" #include "platform/SharedBuffer.h" -#include "platform/TestingPlatformSupport.h" +#include "platform/testing/TestingPlatformSupport.h" #include "public/platform/WebDiscardableMemory.h" #include "testing/gtest/include/gtest/gtest.h" #include "wtf/RefPtr.h"
diff --git a/third_party/WebKit/Source/platform/TimerTest.cpp b/third_party/WebKit/Source/platform/TimerTest.cpp index 0b14918e..4585d950 100644 --- a/third_party/WebKit/Source/platform/TimerTest.cpp +++ b/third_party/WebKit/Source/platform/TimerTest.cpp
@@ -5,6 +5,7 @@ #include "config.h" #include "platform/Timer.h" +#include "platform/testing/TestingPlatformSupport.h" #include "public/platform/Platform.h" #include "public/platform/WebScheduler.h" #include "public/platform/WebThread.h" @@ -236,7 +237,7 @@ OwnPtr<MockWebScheduler> m_webScheduler; }; -class TimerTestPlatform : public Platform { +class TimerTestPlatform : public TestingPlatformSupport { public: TimerTestPlatform() : m_webThread(adoptPtr(new FakeWebThread())) { } @@ -247,17 +248,6 @@ return m_webThread.get(); } - void cryptographicallyRandomValues(unsigned char*, size_t) override - { - ASSERT_NOT_REACHED(); - } - - const unsigned char* getTraceCategoryEnabledFlag(const char* categoryName) override - { - static const unsigned char enabled[] = {0}; - return enabled; - } - void runUntilIdle() { mockScheduler()->runUntilIdle(); @@ -296,9 +286,6 @@ public: void SetUp() override { - m_platform = adoptPtr(new TimerTestPlatform()); - m_oldPlatform = Platform::current(); - Platform::initialize(m_platform.get()); WTF::setMonotonicallyIncreasingTimeFunction(currentTime); m_runTimes.clear(); @@ -306,11 +293,6 @@ m_startTime = gCurrentTimeSecs; } - void TearDown() override - { - Platform::initialize(m_oldPlatform); - } - void countingTask(Timer<TimerTest>*) { m_runTimes.append(monotonicallyIncreasingTime()); @@ -328,27 +310,27 @@ void runUntilIdle() { - m_platform->runUntilIdle(); + m_platform.runUntilIdle(); } void runPendingTasks() { - m_platform->runPendingTasks(); + m_platform.runPendingTasks(); } void runUntilIdleOrDeadlinePassed(double deadline) { - m_platform->runUntilIdleOrDeadlinePassed(deadline); + m_platform.runUntilIdleOrDeadlinePassed(deadline); } bool hasOneTimerTask() const { - return m_platform->hasOneTimerTask(); + return m_platform.hasOneTimerTask(); } double nextTimerTaskDelaySecs() const { - return m_platform->nextTimerTaskDelaySecs(); + return m_platform.nextTimerTaskDelaySecs(); } protected: @@ -357,8 +339,7 @@ WTF::Vector<double> m_nextFireTimes; private: - OwnPtr<TimerTestPlatform> m_platform; - Platform* m_oldPlatform; + TimerTestPlatform m_platform; }; TEST_F(TimerTest, StartOneShot_Zero)
diff --git a/third_party/WebKit/Source/platform/animation/AnimationUtilities.h b/third_party/WebKit/Source/platform/animation/AnimationUtilities.h index ca0ff2a..59fe5b6 100644 --- a/third_party/WebKit/Source/platform/animation/AnimationUtilities.h +++ b/third_party/WebKit/Source/platform/animation/AnimationUtilities.h
@@ -31,7 +31,8 @@ #include "platform/geometry/FloatPoint.h" #include "platform/geometry/IntPoint.h" #include "wtf/MathExtras.h" -#include "wtf/TypeTraits.h" + +#include <type_traits> namespace blink { @@ -44,7 +45,7 @@ template <typename T> inline T blend(T from, T to, double progress) { - static_assert(WTF::IsInteger<T>::value, "blend can only be used with integer types"); + static_assert(std::is_integral<T>::value, "blend can only be used with integer types"); return clampTo<T>(round(to > from ? from + (to - from) * progress : from - (from - to) * progress)); }
diff --git a/third_party/WebKit/Source/platform/blink_platform.gypi b/third_party/WebKit/Source/platform/blink_platform.gypi index c1a9255..f0dbfe7 100644 --- a/third_party/WebKit/Source/platform/blink_platform.gypi +++ b/third_party/WebKit/Source/platform/blink_platform.gypi
@@ -500,6 +500,8 @@ 'graphics/Canvas2DImageBufferSurface.h', 'graphics/Canvas2DLayerBridge.cpp', 'graphics/Canvas2DLayerBridge.h', + 'graphics/CanvasMetrics.h', + 'graphics/CanvasMetrics.cpp', 'graphics/Color.cpp', 'graphics/Color.h', 'graphics/ColorSpace.cpp', @@ -971,8 +973,6 @@ 'PODRedBlackTreeTest.cpp', 'PurgeableVectorTest.cpp', 'SharedBufferTest.cpp', - 'TestingPlatformSupport.cpp', - 'TestingPlatformSupport.h', 'TimerTest.cpp', 'TracedValueTest.cpp', 'UUIDTest.cpp', @@ -1076,6 +1076,8 @@ 'testing/GeometryPrinters.h', 'testing/PaintPrinters.cpp', 'testing/PaintPrinters.h', + 'testing/TestingPlatformSupport.cpp', + 'testing/TestingPlatformSupport.h', 'testing/TransformPrinters.cpp', 'testing/TransformPrinters.h', ],
diff --git a/third_party/WebKit/Source/platform/blink_platform_tests.gyp b/third_party/WebKit/Source/platform/blink_platform_tests.gyp index ee8e54d7..0eef2e6 100644 --- a/third_party/WebKit/Source/platform/blink_platform_tests.gyp +++ b/third_party/WebKit/Source/platform/blink_platform_tests.gyp
@@ -82,6 +82,7 @@ '../wtf/wtf.gyp:wtf', '../wtf/wtf_tests.gyp:wtf_unittest_helpers', '<(DEPTH)/base/base.gyp:test_support_base', + '<(DEPTH)/cc/blink/cc_blink.gyp:cc_blink', '<(DEPTH)/skia/skia.gyp:skia', '<(DEPTH)/third_party/harfbuzz-ng/harfbuzz.gyp:harfbuzz-ng', '<(DEPTH)/url/url.gyp:url_lib', @@ -127,6 +128,8 @@ 'sources': [ '<@(platform_test_support_files)', ], + # Disable c4267 warnings until we fix size_t to int truncations. + 'msvs_disabled_warnings': [ 4267 ], }, ], 'conditions': [
diff --git a/third_party/WebKit/Source/platform/fonts/Font.cpp b/third_party/WebKit/Source/platform/fonts/Font.cpp index cdbd866..4bcd940 100644 --- a/third_party/WebKit/Source/platform/fonts/Font.cpp +++ b/third_party/WebKit/Source/platform/fonts/Font.cpp
@@ -451,6 +451,7 @@ node = GlyphPageTreeNode::getRootChild(fontDataAt(0), pageNumber); m_fontFallbackList->setPageNode(pageNumber, node); } + RELEASE_ASSERT(node); // Diagnosing crbug.com/446566 crash bug. GlyphPage* page = 0; if (variant == NormalVariant) {
diff --git a/third_party/WebKit/Source/platform/fonts/FontCacheTest.cpp b/third_party/WebKit/Source/platform/fonts/FontCacheTest.cpp index ae6b2c2..706f1694 100644 --- a/third_party/WebKit/Source/platform/fonts/FontCacheTest.cpp +++ b/third_party/WebKit/Source/platform/fonts/FontCacheTest.cpp
@@ -7,19 +7,16 @@ #include "platform/fonts/FontDescription.h" #include "platform/fonts/SimpleFontData.h" +#include "platform/testing/TestingPlatformSupport.h" #include "public/platform/Platform.h" #include "testing/gtest/include/gtest/gtest.h" namespace blink { -class EmptyPlatform : public Platform { +class EmptyPlatform : public TestingPlatformSupport { public: EmptyPlatform() {} ~EmptyPlatform() override {} - void cryptographicallyRandomValues(unsigned char* buffer, size_t length) override - { - RELEASE_ASSERT_NOT_REACHED(); - } }; TEST(FontCache, getLastResortFallbackFont) @@ -27,9 +24,7 @@ FontCache* fontCache = FontCache::fontCache(); ASSERT_TRUE(fontCache); - Platform* oldPlatform = Platform::current(); - OwnPtr<EmptyPlatform> platform = adoptPtr(new EmptyPlatform); - Platform::initialize(platform.get()); + EmptyPlatform platform; FontDescription fontDescription; fontDescription.setGenericFamily(FontDescription::StandardFamily); @@ -39,8 +34,6 @@ fontDescription.setGenericFamily(FontDescription::SansSerifFamily); fontData = fontCache->getLastResortFallbackFont(fontDescription, Retain); EXPECT_TRUE(fontData); - - Platform::initialize(oldPlatform); } } // namespace blink
diff --git a/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridge.cpp b/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridge.cpp index 93f225da..ebbcafa 100644 --- a/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridge.cpp +++ b/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridge.cpp
@@ -32,6 +32,7 @@ #include "SkSurface.h" #include "platform/TraceEvent.h" +#include "platform/graphics/CanvasMetrics.h" #include "platform/graphics/ExpensiveCanvasHeuristicParameters.h" #include "platform/graphics/GraphicsLayer.h" #include "platform/graphics/ImageBuffer.h" @@ -378,6 +379,7 @@ } if (m_imageBuffer) m_imageBuffer->notifySurfaceInvalid(); + CanvasMetrics::countCanvasContextUsage(CanvasMetrics::Accelerated2DCanvasGPUContextLost); } return m_surface; }
diff --git a/third_party/WebKit/Source/platform/graphics/CanvasMetrics.cpp b/third_party/WebKit/Source/platform/graphics/CanvasMetrics.cpp new file mode 100644 index 0000000..29ff842 --- /dev/null +++ b/third_party/WebKit/Source/platform/graphics/CanvasMetrics.cpp
@@ -0,0 +1,17 @@ +// Copyright 2015 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 "config.h" +#include "platform/graphics/CanvasMetrics.h" + +#include "public/platform/Platform.h" + +namespace blink { + +void CanvasMetrics::countCanvasContextUsage(const CanvasContextUsage canvasContextUsage) +{ + Platform::current()->histogramEnumeration("WebCore.CanvasContextUsage", canvasContextUsage, CanvasContextUsage::NumberOfUsages); +} + +} // namespace blink
diff --git a/third_party/WebKit/Source/platform/graphics/CanvasMetrics.h b/third_party/WebKit/Source/platform/graphics/CanvasMetrics.h new file mode 100644 index 0000000..fa9174d8 --- /dev/null +++ b/third_party/WebKit/Source/platform/graphics/CanvasMetrics.h
@@ -0,0 +1,31 @@ +// Copyright 2015 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 CanvasMetrics_h +#define CanvasMetrics_h + +#include "platform/PlatformExport.h" + +namespace blink { + +class PLATFORM_EXPORT CanvasMetrics { +public: + enum CanvasContextUsage { + CanvasCreated = 0, + GPUAccelerated2DCanvasImageBufferCreated = 1, + DisplayList2DCanvasImageBufferCreated = 2, + Unaccelerated2DCanvasImageBufferCreated = 3, + Accelerated2DCanvasGPUContextLost = 4, + Unaccelerated2DCanvasImageBufferCreationFailed = 5, + GPUAccelerated2DCanvasImageBufferCreationFailed = 6, + DisplayList2DCanvasFallbackToRaster = 7, + NumberOfUsages + }; + + static void countCanvasContextUsage(const CanvasContextUsage); +}; + +} // namespace blink + +#endif // CanvasMetrics_h
diff --git a/third_party/WebKit/Source/platform/graphics/ContentLayerDelegate.cpp b/third_party/WebKit/Source/platform/graphics/ContentLayerDelegate.cpp index cbf0c83..17f7d98 100644 --- a/third_party/WebKit/Source/platform/graphics/ContentLayerDelegate.cpp +++ b/third_party/WebKit/Source/platform/graphics/ContentLayerDelegate.cpp
@@ -87,14 +87,6 @@ { TRACE_EVENT1("blink,benchmark", "ContentLayerDelegate::paintContents", "clip_rect", toTracedValue(clip)); - // TODO(pdr): Remove when slimming paint v2 is further along. This is only - // here so the browser is usable during development and does not crash due - // to committing the new display items twice. - if (RuntimeEnabledFeatures::slimmingPaintSynchronizedPaintingEnabled()) { - paintArtifactToWebDisplayItemList(webDisplayItemList, m_painter->paintController()->paintArtifact(), clip); - return; - } - PaintController* paintController = m_painter->paintController(); ASSERT(paintController); paintController->setDisplayItemConstructionIsDisabled(
diff --git a/third_party/WebKit/Source/platform/graphics/RecordingImageBufferSurface.cpp b/third_party/WebKit/Source/platform/graphics/RecordingImageBufferSurface.cpp index 97c9c9a4..5c51f5b3 100644 --- a/third_party/WebKit/Source/platform/graphics/RecordingImageBufferSurface.cpp +++ b/third_party/WebKit/Source/platform/graphics/RecordingImageBufferSurface.cpp
@@ -6,6 +6,7 @@ #include "platform/graphics/RecordingImageBufferSurface.h" +#include "platform/graphics/CanvasMetrics.h" #include "platform/graphics/ExpensiveCanvasHeuristicParameters.h" #include "platform/graphics/GraphicsContext.h" #include "platform/graphics/ImageBuffer.h" @@ -95,6 +96,7 @@ m_imageBuffer->resetCanvas(m_fallbackSurface->canvas()); } + CanvasMetrics::countCanvasContextUsage(CanvasMetrics::DisplayList2DCanvasFallbackToRaster); } PassRefPtr<SkImage> RecordingImageBufferSurface::newImageSnapshot(AccelerationHint hint)
diff --git a/third_party/WebKit/Source/platform/graphics/RecordingImageBufferSurfaceTest.cpp b/third_party/WebKit/Source/platform/graphics/RecordingImageBufferSurfaceTest.cpp index 4187ec2b..e504997a 100644 --- a/third_party/WebKit/Source/platform/graphics/RecordingImageBufferSurfaceTest.cpp +++ b/third_party/WebKit/Source/platform/graphics/RecordingImageBufferSurfaceTest.cpp
@@ -9,6 +9,7 @@ #include "platform/graphics/ImageBuffer.h" #include "platform/graphics/ImageBufferClient.h" #include "platform/graphics/UnacceleratedImageBufferSurface.h" +#include "platform/testing/TestingPlatformSupport.h" #include "public/platform/Platform.h" #include "public/platform/WebTaskRunner.h" #include "public/platform/WebThread.h" @@ -236,24 +237,13 @@ // for the current thread. The Mock thread is capable of queuing a single non-delayed task // and registering a single task observer. The run loop exits immediately after running // the single task. -class AutoInstallCurrentThreadPlatformMock { + +class CurrentThreadPlatformMock : public TestingPlatformSupport { public: - AutoInstallCurrentThreadPlatformMock() - { - m_oldPlatform = Platform::current(); - Platform::initialize(&m_mockPlatform); - } + CurrentThreadPlatformMock() { } + WebThread* currentThread() override { return &m_currentThread; } - ~AutoInstallCurrentThreadPlatformMock() - { - Platform::initialize(m_oldPlatform); - } - - void enterRunLoop() - { - m_mockPlatform.enterRunLoop(); - } - + void enterRunLoop() { m_currentThread.enterRunLoop(); } private: class MockWebTaskRunner : public WebTaskRunner { public: @@ -335,22 +325,7 @@ TaskObserver* m_taskObserver; }; - class CurrentThreadPlatformMock : public Platform { - public: - CurrentThreadPlatformMock() { } - virtual void cryptographicallyRandomValues(unsigned char* buffer, size_t length) - { - RELEASE_ASSERT_NOT_REACHED(); - } - WebThread* currentThread() override { return &m_currentThread; } - - void enterRunLoop() { m_currentThread.enterRunLoop(); } - private: - CurrentThreadMock m_currentThread; - }; - - CurrentThreadPlatformMock m_mockPlatform; - Platform* m_oldPlatform; + CurrentThreadMock m_currentThread; }; } // anonymous namespace @@ -366,7 +341,7 @@ #define CALL_TEST_TASK_WRAPPER(TEST_METHOD) \ { \ - AutoInstallCurrentThreadPlatformMock ctpm; \ + CurrentThreadPlatformMock ctpm; \ Platform::current()->currentThread()->taskRunner()->postTask(BLINK_FROM_HERE, new TestWrapperTask_ ## TEST_METHOD(this)); \ ctpm.enterRunLoop(); \ }
diff --git a/third_party/WebKit/Source/platform/graphics/filters/Filter.cpp b/third_party/WebKit/Source/platform/graphics/filters/Filter.cpp index f0e4d1b..22ba718 100644 --- a/third_party/WebKit/Source/platform/graphics/filters/Filter.cpp +++ b/third_party/WebKit/Source/platform/graphics/filters/Filter.cpp
@@ -107,14 +107,4 @@ m_lastEffect = effect; } -FilterEffect* Filter::lastEffect() const -{ - return m_lastEffect.get(); -} - -SourceGraphic* Filter::sourceGraphic() const -{ - return m_sourceGraphic.get(); -} - } // namespace blink
diff --git a/third_party/WebKit/Source/platform/graphics/filters/Filter.h b/third_party/WebKit/Source/platform/graphics/filters/Filter.h index 74b7b471..a89510d 100644 --- a/third_party/WebKit/Source/platform/graphics/filters/Filter.h +++ b/third_party/WebKit/Source/platform/graphics/filters/Filter.h
@@ -30,8 +30,8 @@ namespace blink { -class FilterEffect; class SourceGraphic; +class FilterEffect; class PLATFORM_EXPORT Filter final : public RefCountedWillBeGarbageCollectedFinalized<Filter> { public: @@ -61,9 +61,9 @@ const FloatRect& referenceBox() const { return m_referenceBox; } void setLastEffect(PassRefPtrWillBeRawPtr<FilterEffect>); - FilterEffect* lastEffect() const; + FilterEffect* lastEffect() const { return m_lastEffect.get(); } - SourceGraphic* sourceGraphic() const; + SourceGraphic* sourceGraphic() const { return m_sourceGraphic.get(); } private: Filter(const FloatRect& referenceBox, const FloatRect& filterRegion, float scale, UnitScaling);
diff --git a/third_party/WebKit/Source/platform/heap/Handle.h b/third_party/WebKit/Source/platform/heap/Handle.h index 1c723468..64e43fd7 100644 --- a/third_party/WebKit/Source/platform/heap/Handle.h +++ b/third_party/WebKit/Source/platform/heap/Handle.h
@@ -771,11 +771,7 @@ checkPointer(); } - T* get() const - { - static_assert(IsFullyDefined<T>::value, "T is not fully defined."); - return m_raw; - } + T* get() const { return m_raw; } void clear() { m_raw = nullptr; } @@ -783,8 +779,6 @@ protected: void checkPointer() { - static_assert(IsFullyDefined<T>::value, "T is not fully defined."); - #if ENABLE(ASSERT) && defined(ADDRESS_SANITIZER) if (!m_raw) return;
diff --git a/third_party/WebKit/Source/platform/mhtml/MHTMLArchive.cpp b/third_party/WebKit/Source/platform/mhtml/MHTMLArchive.cpp index cea3bd3..892fa68 100644 --- a/third_party/WebKit/Source/platform/mhtml/MHTMLArchive.cpp +++ b/third_party/WebKit/Source/platform/mhtml/MHTMLArchive.cpp
@@ -227,11 +227,6 @@ outputBuffer.append(asciiString.data(), asciiString.length()); } -ArchiveResource* MHTMLArchive::mainResource() const -{ - return m_mainResource.get(); -} - #if !ENABLE(OILPAN) void MHTMLArchive::clearAllSubframeArchives() {
diff --git a/third_party/WebKit/Source/platform/mhtml/MHTMLArchive.h b/third_party/WebKit/Source/platform/mhtml/MHTMLArchive.h index c1c9372..cb8013a 100644 --- a/third_party/WebKit/Source/platform/mhtml/MHTMLArchive.h +++ b/third_party/WebKit/Source/platform/mhtml/MHTMLArchive.h
@@ -93,7 +93,7 @@ typedef WillBeHeapVector<RefPtrWillBeMember<ArchiveResource>> SubArchiveResources; typedef WillBeHeapVector<RefPtrWillBeMember<MHTMLArchive>> SubFrameArchives; - ArchiveResource* mainResource() const; + ArchiveResource* mainResource() { return m_mainResource.get(); } const SubArchiveResources& subresources() const { return m_subresources; } const SubFrameArchives& subframeArchives() const { return m_subframeArchives; }
diff --git a/third_party/WebKit/Source/platform/scroll/ScrollAnimator.cpp b/third_party/WebKit/Source/platform/scroll/ScrollAnimator.cpp index 56965a8..a01daa2 100644 --- a/third_party/WebKit/Source/platform/scroll/ScrollAnimator.cpp +++ b/third_party/WebKit/Source/platform/scroll/ScrollAnimator.cpp
@@ -33,16 +33,14 @@ #include "platform/TraceEvent.h" #include "platform/scroll/ScrollableArea.h" +#include "public/platform/Platform.h" +#include "public/platform/WebCompositorSupport.h" #include "wtf/CurrentTime.h" #include "wtf/PassRefPtr.h" #include <algorithm> namespace blink { -const double kFrameRate = 60; -const double kTickTime = 1 / kFrameRate; -const double kMinimumTimerInterval = .001; - PassOwnPtr<ScrollAnimatorBase> ScrollAnimatorBase::create(ScrollableArea* scrollableArea) { if (scrollableArea && scrollableArea->scrollAnimatorEnabled()) @@ -50,345 +48,15 @@ return adoptPtr(new ScrollAnimatorBase(scrollableArea)); } -ScrollAnimator::Parameters::Parameters() - : m_isEnabled(false) -{ -} - -ScrollAnimator::Parameters::Parameters(bool isEnabled, double animationTime, double repeatMinimumSustainTime, Curve attackCurve, double attackTime, Curve releaseCurve, double releaseTime, Curve coastTimeCurve, double maximumCoastTime) - : m_isEnabled(isEnabled) - , m_animationTime(animationTime) - , m_repeatMinimumSustainTime(repeatMinimumSustainTime) - , m_attackCurve(attackCurve) - , m_attackTime(attackTime) - , m_releaseCurve(releaseCurve) - , m_releaseTime(releaseTime) - , m_coastTimeCurve(coastTimeCurve) - , m_maximumCoastTime(maximumCoastTime) -{ -} - -double ScrollAnimator::PerAxisData::curveAt(Curve curve, double t) -{ - switch (curve) { - case Linear: - return t; - case Quadratic: - return t * t; - case Cubic: - return t * t * t; - case Quartic: - return t * t * t * t; - case Bounce: - // Time base is chosen to keep the bounce points simpler: - // 1 (half bounce coming in) + 1 + .5 + .25 - const double kTimeBase = 2.75; - const double kTimeBaseSquared = kTimeBase * kTimeBase; - if (t < 1 / kTimeBase) - return kTimeBaseSquared * t * t; - if (t < 2 / kTimeBase) { - // Invert a [-.5,.5] quadratic parabola, center it in [1,2]. - double t1 = t - 1.5 / kTimeBase; - const double kParabolaAtEdge = 1 - .5 * .5; - return kTimeBaseSquared * t1 * t1 + kParabolaAtEdge; - } - if (t < 2.5 / kTimeBase) { - // Invert a [-.25,.25] quadratic parabola, center it in [2,2.5]. - double t2 = t - 2.25 / kTimeBase; - const double kParabolaAtEdge = 1 - .25 * .25; - return kTimeBaseSquared * t2 * t2 + kParabolaAtEdge; - } - // Invert a [-.125,.125] quadratic parabola, center it in [2.5,2.75]. - const double kParabolaAtEdge = 1 - .125 * .125; - t -= 2.625 / kTimeBase; - return kTimeBaseSquared * t * t + kParabolaAtEdge; - } - ASSERT_NOT_REACHED(); - return 0; -} - -double ScrollAnimator::PerAxisData::attackCurve(Curve curve, double deltaTime, double curveT, double startPosition, double attackPosition) -{ - double t = deltaTime / curveT; - double positionFactor = curveAt(curve, t); - return startPosition + positionFactor * (attackPosition - startPosition); -} - -double ScrollAnimator::PerAxisData::releaseCurve(Curve curve, double deltaTime, double curveT, double releasePosition, double desiredPosition) -{ - double t = deltaTime / curveT; - double positionFactor = 1 - curveAt(curve, 1 - t); - return releasePosition + (positionFactor * (desiredPosition - releasePosition)); -} - -double ScrollAnimator::PerAxisData::coastCurve(Curve curve, double factor) -{ - return 1 - curveAt(curve, 1 - factor); -} - -double ScrollAnimator::PerAxisData::curveIntegralAt(Curve curve, double t) -{ - switch (curve) { - case Linear: - return t * t / 2; - case Quadratic: - return t * t * t / 3; - case Cubic: - return t * t * t * t / 4; - case Quartic: - return t * t * t * t * t / 5; - case Bounce: - const double kTimeBase = 2.75; - const double kTimeBaseSquared = kTimeBase * kTimeBase; - const double kTimeBaseSquaredOverThree = kTimeBaseSquared / 3; - double area; - double t1 = std::min(t, 1 / kTimeBase); - area = kTimeBaseSquaredOverThree * t1 * t1 * t1; - if (t < 1 / kTimeBase) - return area; - - t1 = std::min(t - 1 / kTimeBase, 1 / kTimeBase); - // The integral of kTimeBaseSquared * (t1 - .5 / kTimeBase) * (t1 - .5 / kTimeBase) + kParabolaAtEdge - const double kSecondInnerOffset = kTimeBaseSquared * .5 / kTimeBase; - double bounceArea = t1 * (t1 * (kTimeBaseSquaredOverThree * t1 - kSecondInnerOffset) + 1); - area += bounceArea; - if (t < 2 / kTimeBase) - return area; - - t1 = std::min(t - 2 / kTimeBase, 0.5 / kTimeBase); - // The integral of kTimeBaseSquared * (t1 - .25 / kTimeBase) * (t1 - .25 / kTimeBase) + kParabolaAtEdge - const double kThirdInnerOffset = kTimeBaseSquared * .25 / kTimeBase; - bounceArea = t1 * (t1 * (kTimeBaseSquaredOverThree * t1 - kThirdInnerOffset) + 1); - area += bounceArea; - if (t < 2.5 / kTimeBase) - return area; - - t1 = t - 2.5 / kTimeBase; - // The integral of kTimeBaseSquared * (t1 - .125 / kTimeBase) * (t1 - .125 / kTimeBase) + kParabolaAtEdge - const double kFourthInnerOffset = kTimeBaseSquared * .125 / kTimeBase; - bounceArea = t1 * (t1 * (kTimeBaseSquaredOverThree * t1 - kFourthInnerOffset) + 1); - area += bounceArea; - return area; - } - ASSERT_NOT_REACHED(); - return 0; -} - -double ScrollAnimator::PerAxisData::attackArea(Curve curve, double startT, double endT) -{ - double startValue = curveIntegralAt(curve, startT); - double endValue = curveIntegralAt(curve, endT); - return endValue - startValue; -} - -double ScrollAnimator::PerAxisData::releaseArea(Curve curve, double startT, double endT) -{ - double startValue = curveIntegralAt(curve, 1 - endT); - double endValue = curveIntegralAt(curve, 1 - startT); - return endValue - startValue; -} - -ScrollAnimator::PerAxisData::PerAxisData(float* currentPosition, int visibleLength) - : m_currentPosition(currentPosition) - , m_visibleLength(visibleLength) -{ - reset(); -} - -void ScrollAnimator::PerAxisData::reset() -{ - m_currentVelocity = 0; - - m_desiredPosition = 0; - m_desiredVelocity = 0; - - m_startPosition = 0; - m_startTime = 0; - m_startVelocity = 0; - - m_animationTime = 0; - m_lastAnimationTime = 0; - - m_attackPosition = 0; - m_attackTime = 0; - m_attackCurve = Quadratic; - - m_releasePosition = 0; - m_releaseTime = 0; - m_releaseCurve = Quadratic; -} - - -bool ScrollAnimator::PerAxisData::updateDataFromParameters(float step, float delta, float minScrollPos, float maxScrollPos, double currentTime, Parameters* parameters) -{ - float pixelDelta = step * delta; - if (!m_startTime || !pixelDelta || (pixelDelta < 0) != (m_desiredPosition - *m_currentPosition < 0)) { - m_desiredPosition = *m_currentPosition; - m_startTime = 0; - } - - float newPos = m_desiredPosition + pixelDelta; - float clampedPos = std::max(std::min(newPos, maxScrollPos), minScrollPos); - - if (clampedPos == m_desiredPosition) - return false; - - m_desiredPosition = clampedPos; - - if (!m_startTime) { - m_attackTime = parameters->m_attackTime; - m_attackCurve = parameters->m_attackCurve; - } - m_animationTime = parameters->m_animationTime; - m_releaseTime = parameters->m_releaseTime; - m_releaseCurve = parameters->m_releaseCurve; - - // Prioritize our way out of over constraint. - if (m_attackTime + m_releaseTime > m_animationTime) { - if (m_releaseTime > m_animationTime) - m_releaseTime = m_animationTime; - m_attackTime = m_animationTime - m_releaseTime; - } - - if (!m_startTime) { - // FIXME: This should be the time from the event that got us here. - m_startTime = currentTime - kTickTime / 2; - m_startPosition = *m_currentPosition; - m_lastAnimationTime = m_startTime; - } - m_startVelocity = m_currentVelocity; - - double remainingDelta = m_desiredPosition - *m_currentPosition; - - double attackAreaLeft = 0; - - double deltaTime = m_lastAnimationTime - m_startTime; - double attackTimeLeft = std::max(0., m_attackTime - deltaTime); - double timeLeft = m_animationTime - deltaTime; - double minTimeLeft = m_releaseTime + std::min(parameters->m_repeatMinimumSustainTime, m_animationTime - m_releaseTime - attackTimeLeft); - if (timeLeft < minTimeLeft) { - m_animationTime = deltaTime + minTimeLeft; - timeLeft = minTimeLeft; - } - - if (parameters->m_maximumCoastTime > (parameters->m_repeatMinimumSustainTime + parameters->m_releaseTime)) { - double targetMaxCoastVelocity = m_visibleLength * .25 * kFrameRate; - // This needs to be as minimal as possible while not being intrusive to page up/down. - double minCoastDelta = m_visibleLength; - - if (fabs(remainingDelta) > minCoastDelta) { - double maxCoastDelta = parameters->m_maximumCoastTime * targetMaxCoastVelocity; - double coastFactor = std::min(1., (fabs(remainingDelta) - minCoastDelta) / (maxCoastDelta - minCoastDelta)); - - // We could play with the curve here - linear seems a little soft. Initial testing makes me want to feed into the sustain time more aggressively. - double coastMinTimeLeft = std::min(parameters->m_maximumCoastTime, minTimeLeft + coastCurve(parameters->m_coastTimeCurve, coastFactor) * (parameters->m_maximumCoastTime - minTimeLeft)); - - double additionalTime = std::max(0., coastMinTimeLeft - minTimeLeft); - if (additionalTime) { - double additionalReleaseTime = std::min(additionalTime, parameters->m_releaseTime / (parameters->m_releaseTime + parameters->m_repeatMinimumSustainTime) * additionalTime); - m_releaseTime = parameters->m_releaseTime + additionalReleaseTime; - m_animationTime = deltaTime + coastMinTimeLeft; - timeLeft = coastMinTimeLeft; - } - } - } - - double releaseTimeLeft = std::min(timeLeft, m_releaseTime); - double sustainTimeLeft = std::max(0., timeLeft - releaseTimeLeft - attackTimeLeft); - - if (attackTimeLeft) { - double attackSpot = deltaTime / m_attackTime; - attackAreaLeft = attackArea(m_attackCurve, attackSpot, 1) * m_attackTime; - } - - double releaseSpot = (m_releaseTime - releaseTimeLeft) / m_releaseTime; - double releaseAreaLeft = releaseArea(m_releaseCurve, releaseSpot, 1) * m_releaseTime; - - m_desiredVelocity = remainingDelta / (attackAreaLeft + sustainTimeLeft + releaseAreaLeft); - m_releasePosition = m_desiredPosition - m_desiredVelocity * releaseAreaLeft; - if (attackAreaLeft) - m_attackPosition = m_startPosition + m_desiredVelocity * attackAreaLeft; - else - m_attackPosition = m_releasePosition - (m_animationTime - m_releaseTime - m_attackTime) * m_desiredVelocity; - - if (sustainTimeLeft) { - double roundOff = m_releasePosition - ((attackAreaLeft ? m_attackPosition : *m_currentPosition) + m_desiredVelocity * sustainTimeLeft); - m_desiredVelocity += roundOff / sustainTimeLeft; - } - - return true; -} - -inline double ScrollAnimator::PerAxisData::newScrollAnimationPosition(double deltaTime) -{ - if (deltaTime < m_attackTime) - return attackCurve(m_attackCurve, deltaTime, m_attackTime, m_startPosition, m_attackPosition); - if (deltaTime < (m_animationTime - m_releaseTime)) - return m_attackPosition + (deltaTime - m_attackTime) * m_desiredVelocity; - // release is based on targeting the exact final position. - double releaseDeltaT = deltaTime - (m_animationTime - m_releaseTime); - return releaseCurve(m_releaseCurve, releaseDeltaT, m_releaseTime, m_releasePosition, m_desiredPosition); -} - -// FIXME: Add in jank detection trace events into this function. -bool ScrollAnimator::PerAxisData::animateScroll(double currentTime) -{ - double lastScrollInterval = currentTime - m_lastAnimationTime; - if (lastScrollInterval < kMinimumTimerInterval) - return true; - - m_lastAnimationTime = currentTime; - - double deltaTime = currentTime - m_startTime; - - if (deltaTime > m_animationTime) { - *m_currentPosition = m_desiredPosition; - reset(); - return false; - } - double newPosition = newScrollAnimationPosition(deltaTime); - // Normalize velocity to a per second amount. Could be used to check for jank. - if (lastScrollInterval > 0) - m_currentVelocity = (newPosition - *m_currentPosition) / lastScrollInterval; - *m_currentPosition = newPosition; - - return true; -} - -void ScrollAnimator::PerAxisData::updateVisibleLength(int visibleLength) -{ - m_visibleLength = visibleLength; -} - -ScrollAnimator::ScrollAnimator(ScrollableArea* scrollableArea) +ScrollAnimator::ScrollAnimator(ScrollableArea* scrollableArea, WTF::TimeFunction timeFunction) : ScrollAnimatorBase(scrollableArea) - , m_horizontalData(&m_currentPosX, scrollableArea->visibleWidth()) - , m_verticalData(&m_currentPosY, scrollableArea->visibleHeight()) - , m_startTime(0) - , m_animationActive(false) + , m_timeFunction(timeFunction) { } ScrollAnimator::~ScrollAnimator() { - stopAnimationTimerIfNeeded(); -} - -ScrollAnimator::Parameters ScrollAnimator::parametersForScrollGranularity(ScrollGranularity granularity) const -{ - switch (granularity) { - case ScrollByDocument: - return Parameters(true, 20 * kTickTime, 10 * kTickTime, Cubic, 10 * kTickTime, Cubic, 10 * kTickTime, Linear, 1); - case ScrollByLine: - return Parameters(true, 10 * kTickTime, 7 * kTickTime, Cubic, 3 * kTickTime, Cubic, 3 * kTickTime, Linear, 1); - case ScrollByPage: - return Parameters(true, 15 * kTickTime, 10 * kTickTime, Cubic, 5 * kTickTime, Cubic, 5 * kTickTime, Linear, 1); - case ScrollByPixel: - return Parameters(true, 11 * kTickTime, 2 * kTickTime, Cubic, 3 * kTickTime, Cubic, 3 * kTickTime, Quadratic, 1.25); - default: - ASSERT_NOT_REACHED(); - } - return Parameters(); + cancelAnimations(); } ScrollResultOneDimensional ScrollAnimator::userScroll(ScrollbarOrientation orientation, ScrollGranularity granularity, float step, float delta) @@ -398,38 +66,40 @@ TRACE_EVENT0("blink", "ScrollAnimator::scroll"); - // FIXME: get the type passed in. MouseWheel could also be by line, but should still have different - // animation parameters than the keyboard. - Parameters parameters; - switch (granularity) { - case ScrollByDocument: - case ScrollByLine: - case ScrollByPage: - case ScrollByPixel: - parameters = parametersForScrollGranularity(granularity); - break; - case ScrollByPrecisePixel: - return ScrollAnimatorBase::userScroll(orientation, granularity, step, delta); - } - - // If the individual input setting is disabled, bail. - if (!parameters.m_isEnabled) + if (granularity == ScrollByPrecisePixel) return ScrollAnimatorBase::userScroll(orientation, granularity, step, delta); - // This is an animatable scroll. Set the animation in motion using the appropriate parameters. - float minScrollPos = static_cast<float>(m_scrollableArea->minimumScrollPosition(orientation)); - float maxScrollPos = static_cast<float>(m_scrollableArea->maximumScrollPosition(orientation)); + float pixelDelta = step * delta; + FloatPoint desiredDelta = (orientation == VerticalScrollbar ? FloatPoint(0, pixelDelta) : FloatPoint(pixelDelta, 0)); - PerAxisData& data = (orientation == VerticalScrollbar) ? m_verticalData : m_horizontalData; - bool needToScroll = data.updateDataFromParameters(step, delta, minScrollPos, maxScrollPos, WTF::monotonicallyIncreasingTime(), ¶meters); - float unusedDelta = needToScroll ? delta - (data.m_desiredPosition - *data.m_currentPosition) : delta; - if (needToScroll && !animationTimerActive()) { - m_startTime = data.m_startTime; - animationWillStart(); - animationTimerFired(); - scrollableArea()->registerForAnimation(); + FloatPoint targetPos = m_animationCurve ? FloatPoint(m_animationCurve->targetValue()) : currentPosition(); + targetPos.moveBy(desiredDelta); + targetPos = FloatPoint(m_scrollableArea->clampScrollPosition(targetPos)); + + if (m_animationCurve) { + if (!(targetPos - m_animationCurve->targetValue()).isZero()) + m_animationCurve->updateTarget(m_timeFunction() - m_startTime, targetPos); + return ScrollResultOneDimensional(/* didScroll */ true, /* unusedScrollDelta */ 0); } - return ScrollResultOneDimensional(needToScroll, unusedDelta); + + if ((targetPos - currentPosition()).isZero()) { + // Report unused delta only if there is no animation and we are not + // starting one. This ensures we latch for the duration of the + // animation rather than animating multiple scrollers at the same time. + return ScrollResultOneDimensional(/* didScroll */ false, pixelDelta); + } + + m_animationCurve = adoptPtr(Platform::current()->compositorSupport()->createScrollOffsetAnimationCurve( + targetPos, + WebCompositorAnimationCurve::TimingFunctionTypeEaseInOut, + WebScrollOffsetAnimationCurve::ScrollDurationConstant)); + + m_animationCurve->setInitialValue(currentPosition()); + m_startTime = m_timeFunction(); + + scrollableArea()->registerForAnimation(); + animationTimerFired(); + return ScrollResultOneDimensional(/* didScroll */ true, /* unusedScrollDelta */ 0); } void ScrollAnimator::scrollToOffsetWithoutAnimation(const FloatPoint& offset) @@ -437,98 +107,47 @@ m_currentPosX = offset.x(); m_currentPosY = offset.y(); - // Must be called after setting the position since canceling the animation resets - // the desired position to the current. cancelAnimations(); notifyPositionChanged(); } void ScrollAnimator::cancelAnimations() { - m_animationActive = false; - - m_horizontalData.reset(); - m_verticalData.reset(); - m_horizontalData.m_desiredPosition = m_currentPosX; - m_verticalData.m_desiredPosition = m_currentPosY; + if (m_animationCurve) + m_animationCurve.clear(); } void ScrollAnimator::serviceScrollAnimations() { - if (m_animationActive) + if (hasRunningAnimation()) animationTimerFired(); } bool ScrollAnimator::hasRunningAnimation() const { - return m_animationActive; -} - -void ScrollAnimator::updateAfterLayout() -{ - updateVisibleLengths(); -} - -void ScrollAnimator::willEndLiveResize() -{ - updateVisibleLengths(); -} - -void ScrollAnimator::didAddVerticalScrollbar(Scrollbar*) -{ - updateVisibleLengths(); -} - -void ScrollAnimator::didAddHorizontalScrollbar(Scrollbar*) -{ - updateVisibleLengths(); -} - -void ScrollAnimator::updateVisibleLengths() -{ - m_horizontalData.updateVisibleLength(scrollableArea()->visibleWidth()); - m_verticalData.updateVisibleLength(scrollableArea()->visibleHeight()); + return m_animationCurve; } void ScrollAnimator::animationTimerFired() { TRACE_EVENT0("blink", "ScrollAnimator::animationTimerFired"); + double elapsedTime = m_timeFunction() - m_startTime; - double currentTime = WTF::monotonicallyIncreasingTime(); + bool isFinished = (elapsedTime > m_animationCurve->duration()); + FloatPoint offset = isFinished ? m_animationCurve->targetValue() : m_animationCurve->getValue(elapsedTime); - bool continueAnimation = false; - if (m_horizontalData.m_startTime && m_horizontalData.animateScroll(currentTime)) - continueAnimation = true; - if (m_verticalData.m_startTime && m_verticalData.animateScroll(currentTime)) - continueAnimation = true; + offset = FloatPoint(m_scrollableArea->clampScrollPosition(offset)); - if (continueAnimation) - startNextTimer(); + m_currentPosX = offset.x(); + m_currentPosY = offset.y(); + + if (isFinished) + m_animationCurve.clear(); else - m_animationActive = false; + scrollableArea()->scheduleAnimation(); TRACE_EVENT0("blink", "ScrollAnimator::notifyPositionChanged"); notifyPositionChanged(); - - if (!continueAnimation) - animationDidFinish(); -} - -void ScrollAnimator::startNextTimer() -{ - if (scrollableArea()->scheduleAnimation()) - m_animationActive = true; -} - -bool ScrollAnimator::animationTimerActive() -{ - return m_animationActive; -} - -void ScrollAnimator::stopAnimationTimerIfNeeded() -{ - if (animationTimerActive()) - m_animationActive = false; } } // namespace blink
diff --git a/third_party/WebKit/Source/platform/scroll/ScrollAnimator.h b/third_party/WebKit/Source/platform/scroll/ScrollAnimator.h index 4db82e9..ae84f9c 100644 --- a/third_party/WebKit/Source/platform/scroll/ScrollAnimator.h +++ b/third_party/WebKit/Source/platform/scroll/ScrollAnimator.h
@@ -34,6 +34,7 @@ #include "platform/Timer.h" #include "platform/geometry/FloatPoint.h" #include "platform/scroll/ScrollAnimatorBase.h" +#include "public/platform/WebScrollOffsetAnimationCurve.h" namespace blink { @@ -41,7 +42,7 @@ class PLATFORM_EXPORT ScrollAnimator : public ScrollAnimatorBase { public: - explicit ScrollAnimator(ScrollableArea*); + explicit ScrollAnimator(ScrollableArea*, WTF::TimeFunction = WTF::monotonicallyIncreasingTime); ~ScrollAnimator() override; ScrollResultOneDimensional userScroll(ScrollbarOrientation, ScrollGranularity, float step, float delta) override; @@ -51,102 +52,12 @@ void serviceScrollAnimations() override; bool hasRunningAnimation() const override; - void updateAfterLayout() override; - void willEndLiveResize() override; - void didAddVerticalScrollbar(Scrollbar*) override; - void didAddHorizontalScrollbar(Scrollbar*) override; - - enum Curve { - Linear, - Quadratic, - Cubic, - Quartic, - Bounce - }; - - struct PLATFORM_EXPORT Parameters { - Parameters(); - Parameters(bool isEnabled, double animationTime, double repeatMinimumSustainTime, Curve attackCurve, double attackTime, Curve releaseCurve, double releaseTime, Curve coastTimeCurve, double maximumCoastTime); - - // Note that the times can be overspecified such that releaseTime or releaseTime and attackTime are greater - // than animationTime. animationTime takes priority over releaseTime, capping it. attackTime is capped at - // whatever time remains, or zero if none. - bool m_isEnabled; - double m_animationTime; - double m_repeatMinimumSustainTime; - - Curve m_attackCurve; - double m_attackTime; - - Curve m_releaseCurve; - double m_releaseTime; - - Curve m_coastTimeCurve; - double m_maximumCoastTime; - }; - protected: - virtual void animationWillStart() { } - virtual void animationDidFinish() { } - - Parameters parametersForScrollGranularity(ScrollGranularity) const; - - friend class ScrollAnimatorTest; - - struct PLATFORM_EXPORT PerAxisData { - PerAxisData(float* currentPos, int visibleLength); - void reset(); - bool updateDataFromParameters(float step, float delta, float minScrollPos, float maxScrollPos, double currentTime, Parameters*); - bool animateScroll(double currentTime); - void updateVisibleLength(int visibleLength); - - static double curveAt(Curve, double t); - static double attackCurve(Curve, double deltaT, double curveT, double startPos, double attackPos); - static double releaseCurve(Curve, double deltaT, double curveT, double releasePos, double desiredPos); - static double coastCurve(Curve, double factor); - - static double curveIntegralAt(Curve, double t); - static double attackArea(Curve, double startT, double endT); - static double releaseArea(Curve, double startT, double endT); - - double newScrollAnimationPosition(double deltaTime); - - float* m_currentPosition; - double m_currentVelocity; - - double m_desiredPosition; - double m_desiredVelocity; - - double m_startPosition; - double m_startTime; - double m_startVelocity; - - double m_animationTime; - double m_lastAnimationTime; - - double m_attackPosition; - double m_attackTime; - Curve m_attackCurve; - - double m_releasePosition; - double m_releaseTime; - Curve m_releaseCurve; - - int m_visibleLength; - }; - - void startNextTimer(); void animationTimerFired(); - void stopAnimationTimerIfNeeded(); - bool animationTimerActive(); - void updateVisibleLengths(); - - PerAxisData m_horizontalData; - PerAxisData m_verticalData; - + OwnPtr<WebScrollOffsetAnimationCurve> m_animationCurve; double m_startTime; - bool m_animationActive; + WTF::TimeFunction m_timeFunction; }; } // namespace blink
diff --git a/third_party/WebKit/Source/platform/scroll/ScrollAnimatorTest.cpp b/third_party/WebKit/Source/platform/scroll/ScrollAnimatorTest.cpp index a4c13be..310b11dd 100644 --- a/third_party/WebKit/Source/platform/scroll/ScrollAnimatorTest.cpp +++ b/third_party/WebKit/Source/platform/scroll/ScrollAnimatorTest.cpp
@@ -42,6 +42,13 @@ using testing::Return; using testing::_; +static double gMockedTime = 0.0; + +static double getMockedTime() +{ + return gMockedTime; +} + namespace { class MockScrollableArea : public NoBaseWillBeGarbageCollectedFinalized<MockScrollableArea>, public ScrollableArea { @@ -65,6 +72,7 @@ MOCK_CONST_METHOD0(contentsSize, IntSize()); MOCK_CONST_METHOD0(scrollbarsCanBeActive, bool()); MOCK_CONST_METHOD0(scrollableAreaBoundingBox, IntRect()); + MOCK_METHOD0(registerForAnimation, void()); bool userInputScrollable(ScrollbarOrientation) const override { return true; } bool shouldPlaceVerticalScrollbarOnLeft() const override { return false; } @@ -86,1012 +94,110 @@ bool m_scrollAnimatorEnabled; }; -class MockScrollAnimatorNone : public ScrollAnimator { -public: - static PassOwnPtr<MockScrollAnimatorNone> create(ScrollableArea* scrollableArea) - { - return adoptPtr(new MockScrollAnimatorNone(scrollableArea)); - } - - float currentX() { return m_currentPosX; } - float currentY() { return m_currentPosY; } - - FloatPoint m_fp; - int m_count; - - void reset() - { - stopAnimationTimerIfNeeded(); - m_currentPosX = 0; - m_currentPosY = 0; - m_horizontalData.reset(); - m_verticalData.reset(); - m_fp = FloatPoint::zero(); - m_count = 0; - } - - virtual void fireUpAnAnimation(FloatPoint fp) - { - m_fp = fp; - m_count++; - } - -private: - explicit MockScrollAnimatorNone(ScrollableArea* scrollableArea) - : ScrollAnimator(scrollableArea) { } - -}; - } // namespace -TEST(ScrollAnimatorEnabled, Enabled) +static void reset(ScrollAnimator& scrollAnimator) +{ + scrollAnimator.scrollToOffsetWithoutAnimation(FloatPoint()); +} + +TEST(ScrollAnimatorTest, Enabled) { OwnPtrWillBeRawPtr<MockScrollableArea> scrollableArea = MockScrollableArea::create(true); - OwnPtr<MockScrollAnimatorNone> scrollAnimatorNone = MockScrollAnimatorNone::create(scrollableArea.get()); + OwnPtr<ScrollAnimator> scrollAnimator = adoptPtr(new ScrollAnimator(scrollableArea.get(), getMockedTime)); EXPECT_CALL(*scrollableArea, minimumScrollPosition()).Times(AtLeast(1)).WillRepeatedly(Return(IntPoint())); EXPECT_CALL(*scrollableArea, maximumScrollPosition()).Times(AtLeast(1)).WillRepeatedly(Return(IntPoint(1000, 1000))); - EXPECT_CALL(*scrollableArea, setScrollOffset(_, _)).Times(4); + EXPECT_CALL(*scrollableArea, setScrollOffset(_, _)).Times(12); + EXPECT_CALL(*scrollableArea, registerForAnimation()).Times(3); - scrollAnimatorNone->userScroll(HorizontalScrollbar, ScrollByLine, 100, 1); - EXPECT_NE(100, scrollAnimatorNone->currentX()); - EXPECT_NE(0, scrollAnimatorNone->currentX()); - EXPECT_EQ(0, scrollAnimatorNone->currentY()); - scrollAnimatorNone->reset(); + EXPECT_FALSE(scrollAnimator->hasRunningAnimation()); - scrollAnimatorNone->userScroll(HorizontalScrollbar, ScrollByPage, 100, 1); - EXPECT_NE(100, scrollAnimatorNone->currentX()); - EXPECT_NE(0, scrollAnimatorNone->currentX()); - EXPECT_EQ(0, scrollAnimatorNone->currentY()); - scrollAnimatorNone->reset(); + ScrollResultOneDimensional result = scrollAnimator->userScroll(HorizontalScrollbar, ScrollByLine, 100, -1); + EXPECT_FALSE(scrollAnimator->hasRunningAnimation()); + EXPECT_FALSE(result.didScroll); + EXPECT_FLOAT_EQ(-100.0, result.unusedScrollDelta); - scrollAnimatorNone->userScroll(HorizontalScrollbar, ScrollByPixel, 4, 25); - EXPECT_NE(100, scrollAnimatorNone->currentX()); - EXPECT_NE(0, scrollAnimatorNone->currentX()); - EXPECT_EQ(0, scrollAnimatorNone->currentY()); - scrollAnimatorNone->reset(); + result = scrollAnimator->userScroll(HorizontalScrollbar, ScrollByLine, 100, 1); + EXPECT_TRUE(scrollAnimator->hasRunningAnimation()); + EXPECT_TRUE(result.didScroll); + EXPECT_FLOAT_EQ(0.0, result.unusedScrollDelta); - scrollAnimatorNone->userScroll(HorizontalScrollbar, ScrollByPrecisePixel, 4, 25); - EXPECT_EQ(100, scrollAnimatorNone->currentX()); - EXPECT_NE(0, scrollAnimatorNone->currentX()); - EXPECT_EQ(0, scrollAnimatorNone->currentY()); - scrollAnimatorNone->reset(); + gMockedTime += 0.05; + scrollAnimator->serviceScrollAnimations(); + + EXPECT_NE(100, scrollAnimator->currentPosition().x()); + EXPECT_NE(0, scrollAnimator->currentPosition().x()); + EXPECT_EQ(0, scrollAnimator->currentPosition().y()); + reset(*scrollAnimator); + + scrollAnimator->userScroll(HorizontalScrollbar, ScrollByPage, 100, 1); + EXPECT_TRUE(scrollAnimator->hasRunningAnimation()); + + gMockedTime += 0.05; + scrollAnimator->serviceScrollAnimations(); + + EXPECT_NE(100, scrollAnimator->currentPosition().x()); + EXPECT_NE(0, scrollAnimator->currentPosition().x()); + EXPECT_EQ(0, scrollAnimator->currentPosition().y()); + reset(*scrollAnimator); + + scrollAnimator->userScroll(HorizontalScrollbar, ScrollByPixel, 4, 25); + EXPECT_TRUE(scrollAnimator->hasRunningAnimation()); + + gMockedTime += 0.05; + scrollAnimator->serviceScrollAnimations(); + + EXPECT_NE(100, scrollAnimator->currentPosition().x()); + EXPECT_NE(0, scrollAnimator->currentPosition().x()); + EXPECT_EQ(0, scrollAnimator->currentPosition().y()); + + gMockedTime += 1.0; + scrollAnimator->serviceScrollAnimations(); + + EXPECT_FALSE(scrollAnimator->hasRunningAnimation()); + EXPECT_EQ(100, scrollAnimator->currentPosition().x()); + + reset(*scrollAnimator); + + scrollAnimator->userScroll(HorizontalScrollbar, ScrollByPrecisePixel, 4, 25); + EXPECT_FALSE(scrollAnimator->hasRunningAnimation()); + + EXPECT_EQ(100, scrollAnimator->currentPosition().x()); + EXPECT_NE(0, scrollAnimator->currentPosition().x()); + EXPECT_EQ(0, scrollAnimator->currentPosition().y()); + reset(*scrollAnimator); } -TEST(ScrollAnimatorEnabled, Disabled) +TEST(ScrollAnimatorTest, Disabled) { OwnPtrWillBeRawPtr<MockScrollableArea> scrollableArea = MockScrollableArea::create(false); - OwnPtr<MockScrollAnimatorNone> scrollAnimatorNone = MockScrollAnimatorNone::create(scrollableArea.get()); + OwnPtr<ScrollAnimator> scrollAnimator = adoptPtr(new ScrollAnimator(scrollableArea.get(), getMockedTime)); EXPECT_CALL(*scrollableArea, minimumScrollPosition()).Times(AtLeast(1)).WillRepeatedly(Return(IntPoint())); EXPECT_CALL(*scrollableArea, maximumScrollPosition()).Times(AtLeast(1)).WillRepeatedly(Return(IntPoint(1000, 1000))); - EXPECT_CALL(*scrollableArea, setScrollOffset(_, _)).Times(4); + EXPECT_CALL(*scrollableArea, setScrollOffset(_, _)).Times(8); + EXPECT_CALL(*scrollableArea, registerForAnimation()).Times(0); - scrollAnimatorNone->userScroll(HorizontalScrollbar, ScrollByLine, 100, 1); - EXPECT_EQ(100, scrollAnimatorNone->currentX()); - EXPECT_EQ(0, scrollAnimatorNone->currentY()); - scrollAnimatorNone->reset(); + scrollAnimator->userScroll(HorizontalScrollbar, ScrollByLine, 100, 1); + EXPECT_EQ(100, scrollAnimator->currentPosition().x()); + EXPECT_EQ(0, scrollAnimator->currentPosition().y()); + reset(*scrollAnimator); - scrollAnimatorNone->userScroll(HorizontalScrollbar, ScrollByPage, 100, 1); - EXPECT_EQ(100, scrollAnimatorNone->currentX()); - EXPECT_EQ(0, scrollAnimatorNone->currentY()); - scrollAnimatorNone->reset(); + scrollAnimator->userScroll(HorizontalScrollbar, ScrollByPage, 100, 1); + EXPECT_EQ(100, scrollAnimator->currentPosition().x()); + EXPECT_EQ(0, scrollAnimator->currentPosition().y()); + reset(*scrollAnimator); - scrollAnimatorNone->userScroll(HorizontalScrollbar, ScrollByDocument, 100, 1); - EXPECT_EQ(100, scrollAnimatorNone->currentX()); - EXPECT_EQ(0, scrollAnimatorNone->currentY()); - scrollAnimatorNone->reset(); + scrollAnimator->userScroll(HorizontalScrollbar, ScrollByDocument, 100, 1); + EXPECT_EQ(100, scrollAnimator->currentPosition().x()); + EXPECT_EQ(0, scrollAnimator->currentPosition().y()); + reset(*scrollAnimator); - scrollAnimatorNone->userScroll(HorizontalScrollbar, ScrollByPixel, 100, 1); - EXPECT_EQ(100, scrollAnimatorNone->currentX()); - EXPECT_EQ(0, scrollAnimatorNone->currentY()); - scrollAnimatorNone->reset(); -} - -class ScrollAnimatorTest : public testing::Test { -public: - struct SavePerAxisData : public ScrollAnimator::PerAxisData { - SavePerAxisData(const ScrollAnimator::PerAxisData& data) - : ScrollAnimator::PerAxisData(0, 768) - , m_mockScrollableArea(MockScrollableArea::create(true)) - , m_mockScrollAnimatorNone(MockScrollAnimatorNone::create(m_mockScrollableArea.get())) - { - this->m_currentVelocity = data.m_currentVelocity; - this->m_desiredPosition = data.m_desiredPosition; - this->m_desiredVelocity = data.m_desiredVelocity; - this->m_startPosition = data.m_startPosition; - this->m_startTime = data.m_startTime; - this->m_startVelocity = data.m_startVelocity; - this->m_animationTime = data.m_animationTime; - this->m_lastAnimationTime = data.m_lastAnimationTime; - this->m_attackPosition = data.m_attackPosition; - this->m_attackTime = data.m_attackTime; - this->m_attackCurve = data.m_attackCurve; - this->m_releasePosition = data.m_releasePosition; - this->m_releaseTime = data.m_releaseTime; - this->m_releaseCurve = data.m_releaseCurve; - } - - bool operator==(const SavePerAxisData& other) const - { - return m_currentVelocity == other.m_currentVelocity && m_desiredPosition == other.m_desiredPosition && m_desiredVelocity == other.m_desiredVelocity && m_startPosition == other.m_startPosition && m_startTime == other.m_startTime && m_startVelocity == other.m_startVelocity && m_animationTime == other.m_animationTime && m_lastAnimationTime == other.m_lastAnimationTime && m_attackPosition == other.m_attackPosition && m_attackTime == other.m_attackTime && m_attackCurve == other.m_attackCurve && m_releasePosition == other.m_releasePosition && m_releaseTime == other.m_releaseTime && m_releaseCurve == other.m_releaseCurve; - } - OwnPtrWillBePersistent<MockScrollableArea> m_mockScrollableArea; - OwnPtr<MockScrollAnimatorNone> m_mockScrollAnimatorNone; - }; - - ScrollAnimatorTest() - : m_mockScrollableArea(MockScrollableArea::create(true)) - , m_mockScrollAnimatorNone(MockScrollAnimatorNone::create(m_mockScrollableArea.get())) - { - } - - void SetUp() override - { - m_currentPosition = 100; - m_data = new ScrollAnimator::PerAxisData(&m_currentPosition, 768); - } - void TearDown() override - { - delete m_data; - } - - void reset(); - bool updateDataFromParameters(float step, float multiplier, float minScrollPos, float maxScrollPos, double currentTime, ScrollAnimator::Parameters*); - bool updateDataFromParameters(float step, float multiplier, float scrollableSize, double currentTime, ScrollAnimator::Parameters*); - bool animateScroll(double currentTime); - - double attackArea(ScrollAnimator::Curve, double startT, double endT); - double releaseArea(ScrollAnimator::Curve, double startT, double endT); - double attackCurve(ScrollAnimator::Curve, double deltaT, double curveT, double startPosition, double attackPosition); - double releaseCurve(ScrollAnimator::Curve, double deltaT, double curveT, double releasePosition, double desiredPosition); - double coastCurve(ScrollAnimator::Curve, double factor); - - void curveTestInner(ScrollAnimator::Curve, double step, double time); - void curveTest(ScrollAnimator::Curve); - - void checkDesiredPosition(float expectedPosition); - void checkSoftLanding(float expectedPosition); - - static double kTickTime; - static double kAnimationTime; - static double kStartTime; - static double kEndTime; - float m_currentPosition; - OwnPtrWillBePersistent<MockScrollableArea> m_mockScrollableArea; - OwnPtr<MockScrollAnimatorNone> m_mockScrollAnimatorNone; - bool m_scrollingDown; - ScrollAnimator::PerAxisData* m_data; -}; - -double ScrollAnimatorTest::kTickTime = 1 / 60.0; -double ScrollAnimatorTest::kAnimationTime = 0.01; -double ScrollAnimatorTest::kStartTime = 10.0; -double ScrollAnimatorTest::kEndTime = 20.0; - -void ScrollAnimatorTest::reset() -{ - m_data->reset(); - m_scrollingDown = true; -} - -bool ScrollAnimatorTest::updateDataFromParameters(float step, float multiplier, float minScrollPos, float maxScrollPos, double currentTime, ScrollAnimator::Parameters* parameters) -{ - if (step * multiplier) - m_scrollingDown = (step * multiplier > 0); - - double oldVelocity = m_data->m_currentVelocity; - double oldDesiredVelocity = m_data->m_desiredVelocity; - double oldTimeLeft = m_data->m_animationTime - (m_data->m_lastAnimationTime - m_data->m_startTime); - bool result = m_data->updateDataFromParameters(step, multiplier, minScrollPos, maxScrollPos, currentTime, parameters); - if (m_scrollingDown) - EXPECT_LE(oldVelocity, m_data->m_currentVelocity); - else - EXPECT_GE(oldVelocity, m_data->m_currentVelocity); - - double deltaTime = m_data->m_lastAnimationTime - m_data->m_startTime; - double timeLeft = m_data->m_animationTime - deltaTime; - double releaseTimeLeft = std::min(timeLeft, m_data->m_releaseTime); - double attackTimeLeft = std::max(0., m_data->m_attackTime - deltaTime); - double sustainTimeLeft = std::max(0., timeLeft - releaseTimeLeft - attackTimeLeft); - - // If we're getting near the finish, the desired velocity can decrease since the time left gets increased. - if (step * multiplier) { - double allowedVelocityDecreaseFactor = 0.99 * oldTimeLeft / timeLeft; - allowedVelocityDecreaseFactor *= allowedVelocityDecreaseFactor; - if (m_scrollingDown) - EXPECT_LE(oldDesiredVelocity * allowedVelocityDecreaseFactor, m_data->m_desiredVelocity); - else - EXPECT_GE(oldDesiredVelocity * allowedVelocityDecreaseFactor, m_data->m_desiredVelocity); - - double startPosition = attackTimeLeft ? m_data->m_attackPosition : m_currentPosition; - double expectedReleasePosition = startPosition + sustainTimeLeft * m_data->m_desiredVelocity; - EXPECT_NEAR(expectedReleasePosition, m_data->m_releasePosition, result ? .0001 : 1); - } - - return result; -} - -bool ScrollAnimatorTest::updateDataFromParameters(float step, float multiplier, float scrollableSize, double currentTime, ScrollAnimator::Parameters* parameters) -{ - return updateDataFromParameters(step, multiplier, 0, scrollableSize, currentTime, parameters); -} - -bool ScrollAnimatorTest::animateScroll(double currentTime) -{ - double oldPosition = *m_data->m_currentPosition; - bool testEstimatedMaxVelocity = m_data->m_startTime + m_data->m_animationTime - m_data->m_lastAnimationTime > m_data->m_releaseTime; - - bool result = m_data->animateScroll(currentTime); - - double deltaTime = m_data->m_lastAnimationTime - m_data->m_startTime; - double timeLeft = m_data->m_animationTime - deltaTime; - double releaseTimeLeft = std::min(timeLeft, m_data->m_releaseTime); - double attackTimeLeft = std::max(0., m_data->m_attackTime - deltaTime); - double sustainTimeLeft = std::max(0., timeLeft - releaseTimeLeft - attackTimeLeft); - double distanceLeft = m_data->m_desiredPosition - *m_data->m_currentPosition; - - if (m_scrollingDown) { - EXPECT_LE(0, m_data->m_currentVelocity); - EXPECT_LE(oldPosition, *m_data->m_currentPosition); - } else { - EXPECT_GE(0, m_data->m_currentVelocity); - EXPECT_GE(oldPosition, *m_data->m_currentPosition); - } - EXPECT_GE(fabs(m_data->m_desiredVelocity) * 2, fabs(m_data->m_currentVelocity)); - if (testEstimatedMaxVelocity) - EXPECT_GE(fabs(distanceLeft / sustainTimeLeft) * 1.2, fabs(m_data->m_currentVelocity)); - - return result; -} - -double ScrollAnimatorTest::attackArea(ScrollAnimator::Curve curve, double startT, double endT) -{ - return ScrollAnimator::PerAxisData::attackArea(curve, startT, endT); -} - -double ScrollAnimatorTest::releaseArea(ScrollAnimator::Curve curve, double startT, double endT) -{ - return ScrollAnimator::PerAxisData::releaseArea(curve, startT, endT); -} - -double ScrollAnimatorTest::attackCurve(ScrollAnimator::Curve curve, double deltaT, double curveT, double startPosition, double attackPosition) -{ - return ScrollAnimator::PerAxisData::attackCurve(curve, deltaT, curveT, startPosition, attackPosition); -} - -double ScrollAnimatorTest::releaseCurve(ScrollAnimator::Curve curve, double deltaT, double curveT, double releasePosition, double desiredPosition) -{ - return ScrollAnimator::PerAxisData::releaseCurve(curve, deltaT, curveT, releasePosition, desiredPosition); -} - -double ScrollAnimatorTest::coastCurve(ScrollAnimator::Curve curve, double factor) -{ - return ScrollAnimator::PerAxisData::coastCurve(curve, factor); -} - -void ScrollAnimatorTest::curveTestInner(ScrollAnimator::Curve curve, double step, double time) -{ - const double kPosition = 1000; - - double oldPos = 0; - double oldVelocity = 0; - double accumulate = 0; - - for (double t = step ; t <= time ; t += step) { - double newPos = attackCurve(curve, t, time, 0, kPosition); - double delta = newPos - oldPos; - double velocity = delta / step; - double velocityDelta = velocity - oldVelocity; - - accumulate += (oldPos + newPos) / 2 * (step / time); - oldPos = newPos; - oldVelocity = velocity; - if (curve != ScrollAnimator::Bounce) { - EXPECT_LE(-.0001, velocityDelta); - EXPECT_LT(0, delta); - } - - double area = attackArea(curve, 0, t / time) * kPosition; - EXPECT_LE(0, area); - EXPECT_NEAR(accumulate, area, 1.0); - } - - oldPos = 0; - oldVelocity *= 2; - accumulate = releaseArea(curve, 0, 1) * kPosition; - for (double t = step ; t <= time ; t += step) { - double newPos = releaseCurve(curve, t, time, 0, kPosition); - double delta = newPos - oldPos; - double velocity = delta / step; - double velocityDelta = velocity - oldVelocity; - - accumulate -= (kPosition - (oldPos + newPos) / 2) * (step / time); - oldPos = newPos; - oldVelocity = velocity; - if (curve != ScrollAnimator::Bounce) { - EXPECT_GE(0.01, velocityDelta); - EXPECT_LT(0, delta); - } - - double area = releaseArea(curve, t / time, 1) * kPosition; - EXPECT_LE(0, area); - EXPECT_NEAR(accumulate, area, 1.0); - } -} - -void ScrollAnimatorTest::curveTest(ScrollAnimator::Curve curve) -{ - curveTestInner(curve, 0.01, 0.25); - curveTestInner(curve, 0.2, 10); - curveTestInner(curve, 0.025, 10); - curveTestInner(curve, 0.01, 1); - curveTestInner(curve, 0.25, 40); -} - -void ScrollAnimatorTest::checkDesiredPosition(float expectedPosition) -{ - EXPECT_EQ(expectedPosition, m_data->m_desiredPosition); -} - -void ScrollAnimatorTest::checkSoftLanding(float expectedPosition) -{ - EXPECT_EQ(expectedPosition, m_currentPosition); - EXPECT_LE(m_data->m_desiredVelocity / 2, m_data->m_currentVelocity); -} - -TEST_F(ScrollAnimatorTest, CurveMathLinear) -{ - curveTest(ScrollAnimator::Linear); -} - -TEST_F(ScrollAnimatorTest, CurveMathQuadratic) -{ - curveTest(ScrollAnimator::Quadratic); -} - -TEST_F(ScrollAnimatorTest, CurveMathCubic) -{ - curveTest(ScrollAnimator::Cubic); -} - -TEST_F(ScrollAnimatorTest, CurveMathQuartic) -{ - curveTest(ScrollAnimator::Quartic); -} - -TEST_F(ScrollAnimatorTest, CurveMathBounce) -{ - curveTest(ScrollAnimator::Bounce); -} - -TEST_F(ScrollAnimatorTest, CurveMathCoast) -{ - for (double t = .25; t < 1; t += .25) { - EXPECT_EQ(t, coastCurve(ScrollAnimator::Linear, t)); - EXPECT_LT(t, coastCurve(ScrollAnimator::Quadratic, t)); - EXPECT_LT(t, coastCurve(ScrollAnimator::Cubic, t)); - EXPECT_LT(coastCurve(ScrollAnimator::Quadratic, t), coastCurve(ScrollAnimator::Cubic, t)); - EXPECT_LT(t, coastCurve(ScrollAnimator::Quartic, t)); - EXPECT_LT(coastCurve(ScrollAnimator::Cubic, t), coastCurve(ScrollAnimator::Quartic, t)); - } -} - -TEST_F(ScrollAnimatorTest, ScrollOnceLinear) -{ - ScrollAnimator::Parameters parameters(true, 7 * kTickTime, 0, ScrollAnimator::Linear, 3 * kTickTime, ScrollAnimator::Linear, 3 * kTickTime, ScrollAnimator::Linear, 0); - - EXPECT_TRUE(updateDataFromParameters(1, 40, 1000, kStartTime, ¶meters)); - bool result = true; - for (double t = kStartTime; result && t < kEndTime; t += kAnimationTime) - result = animateScroll(t); -} - -TEST_F(ScrollAnimatorTest, ScrollOnceQuadratic) -{ - ScrollAnimator::Parameters parameters(true, 7 * kTickTime, 0, ScrollAnimator::Quadratic, 3 * kTickTime, ScrollAnimator::Quadratic, 3 * kTickTime, ScrollAnimator::Linear, 0); - - EXPECT_TRUE(updateDataFromParameters(1, 40, 1000, kStartTime, ¶meters)); - bool result = true; - for (double t = kStartTime; result && t < kEndTime; t += kAnimationTime) - result = animateScroll(t); -} - -TEST_F(ScrollAnimatorTest, ScrollLongQuadratic) -{ - ScrollAnimator::Parameters parameters(true, 20 * kTickTime, 0, ScrollAnimator::Quadratic, 3 * kTickTime, ScrollAnimator::Quadratic, 3 * kTickTime, ScrollAnimator::Linear, 0); - - EXPECT_TRUE(updateDataFromParameters(1, 40, 1000, kStartTime, ¶meters)); - bool result = true; - for (double t = kStartTime; result && t < kEndTime; t += kAnimationTime) - result = animateScroll(t); -} - -TEST_F(ScrollAnimatorTest, ScrollQuadraticNoSustain) -{ - ScrollAnimator::Parameters parameters(true, 8 * kTickTime, 0, ScrollAnimator::Quadratic, 4 * kTickTime, ScrollAnimator::Quadratic, 4 * kTickTime, ScrollAnimator::Linear, 0); - - EXPECT_TRUE(updateDataFromParameters(1, 40, 1000, kStartTime, ¶meters)); - bool result = true; - for (double t = kStartTime; result && t < kEndTime; t += kAnimationTime) - result = animateScroll(t); -} - -TEST_F(ScrollAnimatorTest, ScrollQuadraticSmoothed) -{ - ScrollAnimator::Parameters parameters(true, 8 * kTickTime, 8 * kTickTime, ScrollAnimator::Quadratic, 4 * kTickTime, ScrollAnimator::Quadratic, 4 * kTickTime, ScrollAnimator::Linear, 0); - - EXPECT_TRUE(updateDataFromParameters(1, 40, 1000, kStartTime, ¶meters)); - bool result = true; - for (double t = kStartTime; result && t < kEndTime; t += kAnimationTime) - result = animateScroll(t); -} - -TEST_F(ScrollAnimatorTest, ScrollOnceCubic) -{ - ScrollAnimator::Parameters parameters(true, 7 * kTickTime, 0, ScrollAnimator::Cubic, 3 * kTickTime, ScrollAnimator::Cubic, 3 * kTickTime, ScrollAnimator::Linear, 0); - - EXPECT_TRUE(updateDataFromParameters(1, 40, 1000, kStartTime, ¶meters)); - bool result = true; - for (double t = kStartTime; result && t < kEndTime; t += kAnimationTime) - result = animateScroll(t); -} - -TEST_F(ScrollAnimatorTest, ScrollOnceQuartic) -{ - ScrollAnimator::Parameters parameters(true, 7 * kTickTime, 0, ScrollAnimator::Quartic, 3 * kTickTime, ScrollAnimator::Quartic, 3 * kTickTime, ScrollAnimator::Linear, 0); - - EXPECT_TRUE(updateDataFromParameters(1, 40, 1000, kStartTime, ¶meters)); - bool result = true; - for (double t = kStartTime; result && t < kEndTime; t += kAnimationTime) - result = animateScroll(t); -} - -TEST_F(ScrollAnimatorTest, ScrollOnceShort) -{ - ScrollAnimator::Parameters parameters(true, 7 * kTickTime, 0, ScrollAnimator::Cubic, 3 * kTickTime, ScrollAnimator::Cubic, 3 * kTickTime, ScrollAnimator::Linear, 0); - - EXPECT_TRUE(updateDataFromParameters(1, 40, 1000, kStartTime, ¶meters)); - bool result = true; - for (double t = kStartTime; result && t < kEndTime; t += kTickTime) - result = animateScroll(t); -} - -TEST_F(ScrollAnimatorTest, ScrollTwiceQuadratic) -{ - ScrollAnimator::Parameters parameters(true, 7 * kTickTime, 0, ScrollAnimator::Quadratic, 3 * kTickTime, ScrollAnimator::Quadratic, 3 * kTickTime, ScrollAnimator::Linear, 0); - - EXPECT_TRUE(updateDataFromParameters(1, 40, 1000, kStartTime, ¶meters)); - bool result = true; - double t; - for (t = kStartTime; result && t < kStartTime + 1.5 * kTickTime; t += kAnimationTime) - result = animateScroll(t); - - result = result && animateScroll(t); - double before = m_currentPosition; - result = result && updateDataFromParameters(1, 40, 1000, t, ¶meters); - result = result && animateScroll(t); - double after = m_currentPosition; - EXPECT_NEAR(before, after, 10); - - t += kAnimationTime; - - result = result && animateScroll(t); - before = m_currentPosition; - result = result && updateDataFromParameters(1, 40, 1000, t, ¶meters); - result = result && animateScroll(t); - after = m_currentPosition; - EXPECT_NEAR(before, after, 10); - - t += kAnimationTime; - for (; result && t < kEndTime; t += kAnimationTime) - result = animateScroll(t); -} - -TEST_F(ScrollAnimatorTest, ScrollLotsQuadratic) -{ - ScrollAnimator::Parameters parameters(true, 7 * kTickTime, 0, ScrollAnimator::Quadratic, 3 * kTickTime, ScrollAnimator::Quadratic, 3 * kTickTime, ScrollAnimator::Linear, 0); - - EXPECT_TRUE(updateDataFromParameters(1, 40, 10000, kStartTime, ¶meters)); - bool result = true; - double t; - for (t = kStartTime; result && t < kStartTime + 1.5 * kTickTime; t += kAnimationTime) - result = animateScroll(t); - - for (int i = 0; i < 20; ++i) { - t += kAnimationTime; - result = result && animateScroll(t); - result = result && updateDataFromParameters(3, 40, 10000, t, ¶meters); - } - - t += kAnimationTime; - for (; result && t < kEndTime; t += kAnimationTime) - result = result && animateScroll(t); -} - -TEST_F(ScrollAnimatorTest, ScrollLotsQuadraticSmoothed) -{ - ScrollAnimator::Parameters parameters(true, 10 * kTickTime, 6 * kTickTime, ScrollAnimator::Quadratic, 3 * kTickTime, ScrollAnimator::Quadratic, 3 * kTickTime, ScrollAnimator::Linear, 0); - - EXPECT_TRUE(updateDataFromParameters(1, 40, 10000, kStartTime, ¶meters)); - bool result = true; - double t; - for (t = kStartTime; result && t < kStartTime + 1.5 * kTickTime; t += kAnimationTime) - result = animateScroll(t); - - for (int i = 0; i < 20; ++i) { - t += kAnimationTime; - result = result && animateScroll(t); - result = result && updateDataFromParameters(3, 40, 10000, t, ¶meters); - } - - t += kAnimationTime; - for (; result && t < kEndTime; t += kAnimationTime) - result = result && animateScroll(t); -} - -TEST_F(ScrollAnimatorTest, ScrollTwiceCubic) -{ - ScrollAnimator::Parameters parameters(true, 7 * kTickTime, 0, ScrollAnimator::Cubic, 3 * kTickTime, ScrollAnimator::Cubic, 3 * kTickTime, ScrollAnimator::Linear, 0); - - EXPECT_TRUE(updateDataFromParameters(1, 40, 1000, kStartTime, ¶meters)); - bool result = true; - double t; - for (t = kStartTime; result && t < kStartTime + 1.5 * kTickTime; t += kAnimationTime) - result = animateScroll(t); - - result = result && animateScroll(t); - double before = m_currentPosition; - result = result && updateDataFromParameters(1, 40, 1000, t, ¶meters); - result = result && animateScroll(t); - double after = m_currentPosition; - EXPECT_NEAR(before, after, 10); - - t += kAnimationTime; - - result = result && animateScroll(t); - before = m_currentPosition; - result = result && updateDataFromParameters(1, 40, 1000, t, ¶meters); - result = result && animateScroll(t); - after = m_currentPosition; - EXPECT_NEAR(before, after, 10); - - t += kAnimationTime; - for (; result && t < kEndTime; t += kAnimationTime) - result = animateScroll(t); -} - -TEST_F(ScrollAnimatorTest, ScrollLotsCubic) -{ - ScrollAnimator::Parameters parameters(true, 7 * kTickTime, 0, ScrollAnimator::Cubic, 3 * kTickTime, ScrollAnimator::Cubic, 3 * kTickTime, ScrollAnimator::Linear, 0); - - EXPECT_TRUE(updateDataFromParameters(1, 40, 10000, kStartTime, ¶meters)); - bool result = true; - double t; - for (t = kStartTime; result && t < kStartTime + 1.5 * kTickTime; t += kAnimationTime) - result = animateScroll(t); - - for (int i = 0; i < 20; ++i) { - t += kAnimationTime; - result = result && animateScroll(t); - result = result && updateDataFromParameters(3, 40, 10000, t, ¶meters); - } - - t += kAnimationTime; - for (; result && t < kEndTime; t += kAnimationTime) - result = result && animateScroll(t); -} - -TEST_F(ScrollAnimatorTest, ScrollLotsCubicSmoothed) -{ - ScrollAnimator::Parameters parameters(true, 10 * kTickTime, 6 * kTickTime, ScrollAnimator::Cubic, 3 * kTickTime, ScrollAnimator::Cubic, 3 * kTickTime, ScrollAnimator::Linear, 0); - - EXPECT_TRUE(updateDataFromParameters(1, 40, 10000, kStartTime, ¶meters)); - bool result = true; - double t; - for (t = kStartTime; result && t < kStartTime + 1.5 * kTickTime; t += kAnimationTime) - result = animateScroll(t); - - for (int i = 0; i < 20; ++i) { - t += kAnimationTime; - result = result && animateScroll(t); - result = result && updateDataFromParameters(3, 40, 10000, t, ¶meters); - } - - t += kAnimationTime; - for (; result && t < kEndTime; t += kAnimationTime) - result = result && animateScroll(t); -} - -TEST_F(ScrollAnimatorTest, ScrollWheelTrace) -{ - ScrollAnimator::Parameters parameters(true, 11 * kTickTime, 0, ScrollAnimator::Cubic, 3 * kTickTime, ScrollAnimator::Cubic, 3 * kTickTime, ScrollAnimator::Linear, 0); - - // Constructed from an actual scroll wheel trace that exhibited a glitch. - bool result = updateDataFromParameters(1, 53.33f, 1000, 100.5781f, ¶meters); - result = animateScroll(100.5933); - result = result && animateScroll(100.6085); - result = result && updateDataFromParameters(1, 53.33f, 1000, 100.6485f, ¶meters); - result = result && animateScroll(100.6515); - result = result && animateScroll(100.6853); - result = result && updateDataFromParameters(1, 53.33f, 1000, 100.6863f, ¶meters); - result = result && animateScroll(100.7005); - result = result && animateScroll(100.7157); - result = result && animateScroll(100.7312); - result = result && updateDataFromParameters(1, 53.33f, 1000, 100.7379f, ¶meters); - result = result && animateScroll(100.7464); - result = result && animateScroll(100.7617); - result = result && animateScroll(100.7775); - result = result && updateDataFromParameters(1, 53.33f, 1000, 100.7779f, ¶meters); - for (double t = 100.7928; result && t < 200; t += 0.015) - result = result && animateScroll(t); -} - -TEST_F(ScrollAnimatorTest, ScrollWheelTraceSmoothed) -{ - ScrollAnimator::Parameters parameters(true, 11 * kTickTime, 7 * kTickTime, ScrollAnimator::Cubic, 3 * kTickTime, ScrollAnimator::Cubic, 3 * kTickTime, ScrollAnimator::Linear, 0); - - // Constructed from an actual scroll wheel trace that exhibited a glitch. - bool result = updateDataFromParameters(1, 53.33f, 1000, 100.5781f, ¶meters); - result = animateScroll(100.5933); - result = result && animateScroll(100.6085); - result = result && updateDataFromParameters(1, 53.33f, 1000, 100.6485f, ¶meters); - result = result && animateScroll(100.6515); - result = result && animateScroll(100.6853); - result = result && updateDataFromParameters(1, 53.33f, 1000, 100.6863f, ¶meters); - result = result && animateScroll(100.7005); - result = result && animateScroll(100.7157); - result = result && animateScroll(100.7312); - result = result && updateDataFromParameters(1, 53.33f, 1000, 100.7379f, ¶meters); - result = result && animateScroll(100.7464); - result = result && animateScroll(100.7617); - result = result && animateScroll(100.7775); - result = result && updateDataFromParameters(1, 53.33f, 1000, 100.7779f, ¶meters); - for (double t = 100.7928; result && t < 200; t += 0.015) - result = result && animateScroll(t); -} - -TEST_F(ScrollAnimatorTest, LinuxTrackPadTrace) -{ - ScrollAnimator::Parameters parameters(true, 11 * kTickTime, 0, ScrollAnimator::Cubic, 3 * kTickTime, ScrollAnimator::Cubic, 3 * kTickTime, ScrollAnimator::Linear, 0); - - bool result = updateDataFromParameters(1.00, 60.00, 1000, 100.6863, ¶meters); - result = result && updateDataFromParameters(1.00, 20.00, 1000, 100.6897, ¶meters); - result = result && updateDataFromParameters(1.00, 20.00, 1000, 100.7001, ¶meters); - result = result && animateScroll(100.7015); - result = result && animateScroll(100.7169); - result = result && updateDataFromParameters(1.00, 40.00, 1000, 100.7179, ¶meters); - result = result && animateScroll(100.7322); - result = result && updateDataFromParameters(1.00, 20.00, 1000, 100.7332, ¶meters); - result = result && animateScroll(100.7491); - result = result && updateDataFromParameters(1.00, 20.00, 1000, 100.7519, ¶meters); - result = result && animateScroll(100.7676); - result = result && updateDataFromParameters(1.00, 20.00, 1000, 100.7698, ¶meters); - result = result && updateDataFromParameters(1.00, 20.00, 1000, 100.7830, ¶meters); - result = result && animateScroll(100.7834); - result = result && animateScroll(100.7997); - result = result && updateDataFromParameters(1.00, 20.00, 1000, 100.8019, ¶meters); - result = result && animateScroll(100.8154); - result = result && updateDataFromParameters(1.00, 20.00, 1000, 100.8241, ¶meters); - result = result && animateScroll(100.8335); - result = result && updateDataFromParameters(1.00, 20.00, 1000, 100.8465, ¶meters); - result = result && animateScroll(100.8513); - result = result && updateDataFromParameters(1.00, 20.00, 1000, 100.8623, ¶meters); - for (double t = 100.8674; result && t < 200; t += 0.015) - result = result && animateScroll(t); -} - -TEST_F(ScrollAnimatorTest, LinuxTrackPadTraceSmoothed) -{ - ScrollAnimator::Parameters parameters(true, 11 * kTickTime, 7 * kTickTime, ScrollAnimator::Cubic, 3 * kTickTime, ScrollAnimator::Cubic, 3 * kTickTime, ScrollAnimator::Linear, 0); - - bool result = updateDataFromParameters(1.00, 60.00, 1000, 100.6863, ¶meters); - result = result && updateDataFromParameters(1.00, 20.00, 1000, 100.6897, ¶meters); - result = result && updateDataFromParameters(1.00, 20.00, 1000, 100.7001, ¶meters); - result = result && animateScroll(100.7015); - result = result && animateScroll(100.7169); - result = result && updateDataFromParameters(1.00, 40.00, 1000, 100.7179, ¶meters); - result = result && animateScroll(100.7322); - result = result && updateDataFromParameters(1.00, 20.00, 1000, 100.7332, ¶meters); - result = result && animateScroll(100.7491); - result = result && updateDataFromParameters(1.00, 20.00, 1000, 100.7519, ¶meters); - result = result && animateScroll(100.7676); - result = result && updateDataFromParameters(1.00, 20.00, 1000, 100.7698, ¶meters); - result = result && updateDataFromParameters(1.00, 20.00, 1000, 100.7830, ¶meters); - result = result && animateScroll(100.7834); - result = result && animateScroll(100.7997); - result = result && updateDataFromParameters(1.00, 20.00, 1000, 100.8019, ¶meters); - result = result && animateScroll(100.8154); - result = result && updateDataFromParameters(1.00, 20.00, 1000, 100.8241, ¶meters); - result = result && animateScroll(100.8335); - result = result && updateDataFromParameters(1.00, 20.00, 1000, 100.8465, ¶meters); - result = result && animateScroll(100.8513); - result = result && updateDataFromParameters(1.00, 20.00, 1000, 100.8623, ¶meters); - for (double t = 100.8674; result && t < 200; t += 0.015) - result = result && animateScroll(t); -} - -TEST_F(ScrollAnimatorTest, ScrollRightToBumperRTL) -{ - // Tests that scrolling works for a negative scroll bound. This is the case - // for RTL pages where the scroll position is always negative. - m_currentPosition = 0; - ScrollAnimator::Parameters parameters(true, 10 * kTickTime, 7 * kTickTime, ScrollAnimator::Cubic, 3 * kTickTime, ScrollAnimator::Cubic, 3 * kTickTime, ScrollAnimator::Linear, 0); - - EXPECT_TRUE(updateDataFromParameters(1, -20, -200, 0, kStartTime, ¶meters)); - bool result = true; - double t = kStartTime; - for (int i = 0; i < 10; ++i) { - t += kAnimationTime; - result = result && animateScroll(t); - updateDataFromParameters(1, -20, -200, 0, t, ¶meters); - } - checkDesiredPosition(-200); - - t += kAnimationTime; - for (; result && t < kEndTime; t += kAnimationTime) - result = result && animateScroll(t); - checkSoftLanding(-200); -} - -TEST_F(ScrollAnimatorTest, ScrollDownToBumper) -{ - ScrollAnimator::Parameters parameters(true, 10 * kTickTime, 7 * kTickTime, ScrollAnimator::Cubic, 3 * kTickTime, ScrollAnimator::Cubic, 3 * kTickTime, ScrollAnimator::Linear, 0); - - EXPECT_TRUE(updateDataFromParameters(1, 20, 200, kStartTime, ¶meters)); - bool result = true; - double t = kStartTime; - for (int i = 0; i < 10; ++i) { - t += kAnimationTime; - result = result && animateScroll(t); - updateDataFromParameters(1, 20, 200, t, ¶meters); - } - checkDesiredPosition(200); - - t += kAnimationTime; - for (; result && t < kEndTime; t += kAnimationTime) - result = result && animateScroll(t); - checkSoftLanding(200); -} - -TEST_F(ScrollAnimatorTest, ScrollUpToBumper) -{ - ScrollAnimator::Parameters parameters(true, 10 * kTickTime, 7 * kTickTime, ScrollAnimator::Cubic, 3 * kTickTime, ScrollAnimator::Cubic, 3 * kTickTime, ScrollAnimator::Linear, 0); - - EXPECT_TRUE(updateDataFromParameters(1, -20, 200, kStartTime, ¶meters)); - bool result = true; - double t = kStartTime; - for (int i = 0; i < 10; ++i) { - t += kAnimationTime; - result = result && animateScroll(t); - updateDataFromParameters(1, -20, 200, t, ¶meters); - } - checkDesiredPosition(0); - - t += kAnimationTime; - for (; result && t < kEndTime; t += kAnimationTime) - result = result && animateScroll(t); - checkSoftLanding(0); -} - -TEST_F(ScrollAnimatorTest, ScrollUpToBumperCoast) -{ - ScrollAnimator::Parameters parameters(true, 11 * kTickTime, 2 * kTickTime, ScrollAnimator::Cubic, 3 * kTickTime, ScrollAnimator::Cubic, 3 * kTickTime, ScrollAnimator::Linear, 1); - - m_currentPosition = 40000; - EXPECT_TRUE(updateDataFromParameters(1, -10000, 50000, kStartTime, ¶meters)); - bool result = true; - double t = kStartTime; - for (int i = 0; i < 10; ++i) { - t += kAnimationTime; - result = result && animateScroll(t); - updateDataFromParameters(1, -10000, 50000, t, ¶meters); - } - checkDesiredPosition(0); - - t += kAnimationTime; - for (; result && t < kEndTime; t += kAnimationTime) - result = result && animateScroll(t); - checkSoftLanding(0); -} - -TEST_F(ScrollAnimatorTest, ScrollDownToBumperCoast) -{ - ScrollAnimator::Parameters parameters(true, 11 * kTickTime, 2 * kTickTime, ScrollAnimator::Cubic, 3 * kTickTime, ScrollAnimator::Cubic, 3 * kTickTime, ScrollAnimator::Linear, 1); - - m_currentPosition = 10000; - EXPECT_TRUE(updateDataFromParameters(1, 10000, 50000, kStartTime, ¶meters)); - bool result = true; - double t = kStartTime; - for (int i = 0; i < 10; ++i) { - t += kAnimationTime; - result = result && animateScroll(t); - updateDataFromParameters(1, 10000, 50000, t, ¶meters); - } - checkDesiredPosition(50000); - - t += kAnimationTime; - for (; result && t < kEndTime; t += kAnimationTime) - result = result && animateScroll(t); - checkSoftLanding(50000); -} - -TEST_F(ScrollAnimatorTest, VaryingInputsEquivalency) -{ - ScrollAnimator::Parameters parameters(true, 15 * kTickTime, 10 * kTickTime, ScrollAnimator::Cubic, 5 * kTickTime, ScrollAnimator::Cubic, 5 * kTickTime, ScrollAnimator::Linear, 0); - - reset(); - EXPECT_TRUE(updateDataFromParameters(1, 300, 50000, kStartTime, ¶meters)); - SavePerAxisData dataSingle(*m_data); - - reset(); - EXPECT_TRUE(updateDataFromParameters(1, 150, 50000, kStartTime, ¶meters)); - EXPECT_TRUE(updateDataFromParameters(1, 150, 50000, kStartTime, ¶meters)); - SavePerAxisData dataDouble(*m_data); - - reset(); - EXPECT_TRUE(updateDataFromParameters(1, 100, 50000, kStartTime, ¶meters)); - EXPECT_TRUE(updateDataFromParameters(1, 100, 50000, kStartTime, ¶meters)); - EXPECT_TRUE(updateDataFromParameters(1, 100, 50000, kStartTime, ¶meters)); - SavePerAxisData dataTriple(*m_data); - - reset(); - EXPECT_TRUE(updateDataFromParameters(1, 50, 50000, kStartTime, ¶meters)); - EXPECT_TRUE(updateDataFromParameters(1, 50, 50000, kStartTime, ¶meters)); - EXPECT_TRUE(updateDataFromParameters(1, 50, 50000, kStartTime, ¶meters)); - EXPECT_TRUE(updateDataFromParameters(1, 50, 50000, kStartTime, ¶meters)); - EXPECT_TRUE(updateDataFromParameters(1, 50, 50000, kStartTime, ¶meters)); - EXPECT_TRUE(updateDataFromParameters(1, 50, 50000, kStartTime, ¶meters)); - SavePerAxisData dataMany(*m_data); - - EXPECT_EQ(dataSingle, dataDouble); - EXPECT_EQ(dataSingle, dataTriple); - EXPECT_EQ(dataSingle, dataMany); -} - -TEST_F(ScrollAnimatorTest, VaryingInputsEquivalencyCoast) -{ - ScrollAnimator::Parameters parameters(true, 15 * kTickTime, 10 * kTickTime, ScrollAnimator::Cubic, 5 * kTickTime, ScrollAnimator::Cubic, 5 * kTickTime, ScrollAnimator::Linear, 1); - - reset(); - updateDataFromParameters(1, 300, 50000, kStartTime, ¶meters); - SavePerAxisData dataSingle(*m_data); - - reset(); - updateDataFromParameters(1, 150, 50000, kStartTime, ¶meters); - updateDataFromParameters(1, 150, 50000, kStartTime, ¶meters); - SavePerAxisData dataDouble(*m_data); - - reset(); - updateDataFromParameters(1, 100, 50000, kStartTime, ¶meters); - updateDataFromParameters(1, 100, 50000, kStartTime, ¶meters); - updateDataFromParameters(1, 100, 50000, kStartTime, ¶meters); - SavePerAxisData dataTriple(*m_data); - - reset(); - updateDataFromParameters(1, 50, 50000, kStartTime, ¶meters); - updateDataFromParameters(1, 50, 50000, kStartTime, ¶meters); - updateDataFromParameters(1, 50, 50000, kStartTime, ¶meters); - updateDataFromParameters(1, 50, 50000, kStartTime, ¶meters); - updateDataFromParameters(1, 50, 50000, kStartTime, ¶meters); - updateDataFromParameters(1, 50, 50000, kStartTime, ¶meters); - SavePerAxisData dataMany(*m_data); - - EXPECT_EQ(dataSingle, dataDouble); - EXPECT_EQ(dataSingle, dataTriple); - EXPECT_EQ(dataSingle, dataMany); -} - -TEST_F(ScrollAnimatorTest, VaryingInputsEquivalencyCoastLarge) -{ - ScrollAnimator::Parameters parameters(true, 15 * kTickTime, 10 * kTickTime, ScrollAnimator::Cubic, 5 * kTickTime, ScrollAnimator::Cubic, 5 * kTickTime, ScrollAnimator::Linear, 1); - - reset(); - EXPECT_TRUE(updateDataFromParameters(1, 30000, 50000, kStartTime, ¶meters)); - SavePerAxisData dataSingle(*m_data); - - reset(); - EXPECT_TRUE(updateDataFromParameters(1, 15000, 50000, kStartTime, ¶meters)); - EXPECT_TRUE(updateDataFromParameters(1, 15000, 50000, kStartTime, ¶meters)); - SavePerAxisData dataDouble(*m_data); - - reset(); - EXPECT_TRUE(updateDataFromParameters(1, 10000, 50000, kStartTime, ¶meters)); - EXPECT_TRUE(updateDataFromParameters(1, 10000, 50000, kStartTime, ¶meters)); - EXPECT_TRUE(updateDataFromParameters(1, 10000, 50000, kStartTime, ¶meters)); - SavePerAxisData dataTriple(*m_data); - - reset(); - EXPECT_TRUE(updateDataFromParameters(1, 5000, 50000, kStartTime, ¶meters)); - EXPECT_TRUE(updateDataFromParameters(1, 5000, 50000, kStartTime, ¶meters)); - EXPECT_TRUE(updateDataFromParameters(1, 5000, 50000, kStartTime, ¶meters)); - EXPECT_TRUE(updateDataFromParameters(1, 5000, 50000, kStartTime, ¶meters)); - EXPECT_TRUE(updateDataFromParameters(1, 5000, 50000, kStartTime, ¶meters)); - EXPECT_TRUE(updateDataFromParameters(1, 5000, 50000, kStartTime, ¶meters)); - SavePerAxisData dataMany(*m_data); - - EXPECT_EQ(dataSingle, dataDouble); - EXPECT_EQ(dataSingle, dataTriple); - EXPECT_EQ(dataSingle, dataMany); -} - -TEST_F(ScrollAnimatorTest, VaryingInputsEquivalencyCoastSteep) -{ - ScrollAnimator::Parameters parameters(true, 15 * kTickTime, 10 * kTickTime, ScrollAnimator::Cubic, 5 * kTickTime, ScrollAnimator::Cubic, 5 * kTickTime, ScrollAnimator::Quadratic, 1); - - reset(); - EXPECT_TRUE(updateDataFromParameters(1, 30000, 50000, kStartTime, ¶meters)); - SavePerAxisData dataSingle(*m_data); - - reset(); - EXPECT_TRUE(updateDataFromParameters(1, 15000, 50000, kStartTime, ¶meters)); - EXPECT_TRUE(updateDataFromParameters(1, 15000, 50000, kStartTime, ¶meters)); - SavePerAxisData dataDouble(*m_data); - - reset(); - EXPECT_TRUE(updateDataFromParameters(1, 10000, 50000, kStartTime, ¶meters)); - EXPECT_TRUE(updateDataFromParameters(1, 10000, 50000, kStartTime, ¶meters)); - EXPECT_TRUE(updateDataFromParameters(1, 10000, 50000, kStartTime, ¶meters)); - SavePerAxisData dataTriple(*m_data); - - reset(); - EXPECT_TRUE(updateDataFromParameters(1, 5000, 50000, kStartTime, ¶meters)); - EXPECT_TRUE(updateDataFromParameters(1, 5000, 50000, kStartTime, ¶meters)); - EXPECT_TRUE(updateDataFromParameters(1, 5000, 50000, kStartTime, ¶meters)); - EXPECT_TRUE(updateDataFromParameters(1, 5000, 50000, kStartTime, ¶meters)); - EXPECT_TRUE(updateDataFromParameters(1, 5000, 50000, kStartTime, ¶meters)); - EXPECT_TRUE(updateDataFromParameters(1, 5000, 50000, kStartTime, ¶meters)); - SavePerAxisData dataMany(*m_data); - - EXPECT_EQ(dataSingle, dataDouble); - EXPECT_EQ(dataSingle, dataTriple); - EXPECT_EQ(dataSingle, dataMany); -} - -TEST_F(ScrollAnimatorTest, ScrollStopInMiddle) -{ - ScrollAnimator::Parameters parameters(true, 7 * kTickTime, 0, ScrollAnimator::Cubic, 3 * kTickTime, ScrollAnimator::Cubic, 3 * kTickTime, ScrollAnimator::Linear, 0); - - EXPECT_TRUE(updateDataFromParameters(1, 40, 1000, kStartTime, ¶meters)); - bool result = true; - double t; - for (t = kStartTime; result && t < kStartTime + 1.5 * kTickTime; t += kAnimationTime) - result = animateScroll(t); - - result = result && animateScroll(t); - EXPECT_TRUE(result); - double before = m_currentPosition; - result = result && updateDataFromParameters(0, 0, 1000, t, ¶meters); - EXPECT_FALSE(result); - result = result && animateScroll(t); - double after = m_currentPosition; - EXPECT_EQ(before, after); - checkDesiredPosition(after); -} - -TEST_F(ScrollAnimatorTest, ReverseInMiddle) -{ - ScrollAnimator::Parameters parameters(true, 7 * kTickTime, 0, ScrollAnimator::Cubic, 3 * kTickTime, ScrollAnimator::Cubic, 3 * kTickTime, ScrollAnimator::Linear, 0); - - EXPECT_TRUE(updateDataFromParameters(1, 40, 1000, kStartTime, ¶meters)); - bool result = true; - double t; - for (t = kStartTime; result && t < kStartTime + 1.5 * kTickTime; t += kAnimationTime) - result = animateScroll(t); - - result = result && animateScroll(t); - EXPECT_TRUE(result); - double before = m_currentPosition; - result = result && updateDataFromParameters(1, -10, 1000, t, ¶meters); - EXPECT_TRUE(result); - result = result && animateScroll(t); - double after = m_currentPosition; - EXPECT_GE(before, after); - - t += kAnimationTime; - for (; result && t < kEndTime; t += kAnimationTime) - result = result && animateScroll(t); - EXPECT_GE(before, m_currentPosition); + scrollAnimator->userScroll(HorizontalScrollbar, ScrollByPixel, 100, 1); + EXPECT_EQ(100, scrollAnimator->currentPosition().x()); + EXPECT_EQ(0, scrollAnimator->currentPosition().y()); + reset(*scrollAnimator); } } // namespace blink
diff --git a/third_party/WebKit/Source/platform/scroll/ScrollableAreaTest.cpp b/third_party/WebKit/Source/platform/scroll/ScrollableAreaTest.cpp index c7800f7..13487d83 100644 --- a/third_party/WebKit/Source/platform/scroll/ScrollableAreaTest.cpp +++ b/third_party/WebKit/Source/platform/scroll/ScrollableAreaTest.cpp
@@ -5,7 +5,7 @@ #include "config.h" #include "platform/scroll/ScrollableArea.h" -#include "platform/TestingPlatformSupport.h" +#include "platform/testing/TestingPlatformSupport.h" #include "public/platform/Platform.h" #include "public/platform/WebScheduler.h" #include "public/platform/WebThread.h" @@ -86,7 +86,7 @@ // We need just enough scaffolding for the Timer constructor to not segfault. class FakePlatform : public TestingPlatformSupport { public: - FakePlatform() : TestingPlatformSupport(TestingPlatformSupport::Config()) { } + FakePlatform() { } ~FakePlatform() override { } WebThread* currentThread() override
diff --git a/third_party/WebKit/Source/platform/testing/RunAllTests.cpp b/third_party/WebKit/Source/platform/testing/RunAllTests.cpp index dcf561c..3cf424c 100644 --- a/third_party/WebKit/Source/platform/testing/RunAllTests.cpp +++ b/third_party/WebKit/Source/platform/testing/RunAllTests.cpp
@@ -31,8 +31,8 @@ #include "config.h" #include "platform/EventTracer.h" -#include "platform/TestingPlatformSupport.h" #include "platform/heap/Heap.h" +#include "platform/testing/TestingPlatformSupport.h" #include "wtf/CryptographicallyRandomNumber.h" #include "wtf/MainThread.h" #include "wtf/Partitions.h" @@ -41,6 +41,7 @@ #include <base/bind_helpers.h> #include <base/test/launcher/unit_test_launcher.h> #include <base/test/test_suite.h> +#include <cc/blink/web_compositor_support_impl.h> #include <string.h> static double CurrentTime() @@ -67,6 +68,8 @@ WTF::initializeMainThread(0); blink::TestingPlatformSupport::Config platformConfig; + cc_blink::WebCompositorSupportImpl compositorSupport; + platformConfig.compositorSupport = &compositorSupport; blink::TestingPlatformSupport platform(platformConfig); blink::Heap::init();
diff --git a/third_party/WebKit/Source/platform/TestingPlatformSupport.cpp b/third_party/WebKit/Source/platform/testing/TestingPlatformSupport.cpp similarity index 88% rename from third_party/WebKit/Source/platform/TestingPlatformSupport.cpp rename to third_party/WebKit/Source/platform/testing/TestingPlatformSupport.cpp index 96fed1a..8939238 100644 --- a/third_party/WebKit/Source/platform/TestingPlatformSupport.cpp +++ b/third_party/WebKit/Source/platform/testing/TestingPlatformSupport.cpp
@@ -30,7 +30,7 @@ #include "config.h" -#include "platform/TestingPlatformSupport.h" +#include "platform/testing/TestingPlatformSupport.h" namespace blink { @@ -69,6 +69,11 @@ return nullptr; } +TestingPlatformSupport::TestingPlatformSupport() + : TestingPlatformSupport(TestingPlatformSupport::Config()) +{ +} + TestingPlatformSupport::TestingPlatformSupport(const Config& config) : m_config(config) , m_oldPlatform(Platform::current()) @@ -102,4 +107,14 @@ return WebString::fromUTF8("en-US"); } +WebCompositorSupport* TestingPlatformSupport::compositorSupport() +{ + return m_config.compositorSupport; +} + +WebThread* TestingPlatformSupport::currentThread() +{ + return m_oldPlatform ? m_oldPlatform->currentThread() : nullptr; +} + } // namespace blink
diff --git a/third_party/WebKit/Source/platform/TestingPlatformSupport.h b/third_party/WebKit/Source/platform/testing/TestingPlatformSupport.h similarity index 88% rename from third_party/WebKit/Source/platform/TestingPlatformSupport.h rename to third_party/WebKit/Source/platform/testing/TestingPlatformSupport.h index cf1e1fd..e1d5a49e 100644 --- a/third_party/WebKit/Source/platform/TestingPlatformSupport.h +++ b/third_party/WebKit/Source/platform/testing/TestingPlatformSupport.h
@@ -31,12 +31,16 @@ #ifndef TestingPlatformSupport_h #define TestingPlatformSupport_h +#include "platform/PlatformExport.h" #include "public/platform/Platform.h" #include "public/platform/WebDiscardableMemory.h" #include "wtf/Vector.h" namespace blink { +class WebCompositorSupport; +class WebThread; + class TestingDiscardableMemory : public WebDiscardableMemory { public: explicit TestingDiscardableMemory(size_t); @@ -56,11 +60,15 @@ class TestingPlatformSupport : public Platform { public: struct Config { - Config() : hasDiscardableMemorySupport(false) { } + Config() + : hasDiscardableMemorySupport(false) + , compositorSupport(nullptr) { } bool hasDiscardableMemorySupport; + WebCompositorSupport* compositorSupport; }; + TestingPlatformSupport(); explicit TestingPlatformSupport(const Config&); ~TestingPlatformSupport() override; @@ -70,8 +78,10 @@ void cryptographicallyRandomValues(unsigned char* buffer, size_t length) override; const unsigned char* getTraceCategoryEnabledFlag(const char* categoryName) override; WebString defaultLocale() override; + WebCompositorSupport* compositorSupport() override; + WebThread* currentThread() override; -private: +protected: const Config m_config; Platform* const m_oldPlatform; };
diff --git a/third_party/WebKit/Source/platform/text/LocaleMacTest.cpp b/third_party/WebKit/Source/platform/text/LocaleMacTest.cpp index d28c72b..05469d8 100644 --- a/third_party/WebKit/Source/platform/text/LocaleMacTest.cpp +++ b/third_party/WebKit/Source/platform/text/LocaleMacTest.cpp
@@ -27,7 +27,7 @@ #include "platform/text/LocaleMac.h" #include "platform/DateComponents.h" -#include "platform/TestingPlatformSupport.h" +#include "platform/testing/TestingPlatformSupport.h" #include "public/platform/Platform.h" #include "testing/gtest/include/gtest/gtest.h" #include "wtf/DateMath.h" @@ -39,8 +39,6 @@ class LocalePlatformSupport : public TestingPlatformSupport { public: - LocalePlatformSupport() : TestingPlatformSupport(TestingPlatformSupport::Config()) { } - WebString queryLocalizedString(WebLocalizedString::Name /*name*/) override { return WebString::fromUTF8("Week $2, $1");
diff --git a/third_party/WebKit/Source/platform/weborigin/OriginAccessEntryTest.cpp b/third_party/WebKit/Source/platform/weborigin/OriginAccessEntryTest.cpp index 549248e..49ea30e7 100644 --- a/third_party/WebKit/Source/platform/weborigin/OriginAccessEntryTest.cpp +++ b/third_party/WebKit/Source/platform/weborigin/OriginAccessEntryTest.cpp
@@ -31,6 +31,7 @@ #include "config.h" #include "platform/weborigin/OriginAccessEntry.h" +#include "platform/testing/TestingPlatformSupport.h" #include "platform/weborigin/KURL.h" #include "platform/weborigin/SecurityOrigin.h" #include "public/platform/Platform.h" @@ -55,43 +56,19 @@ size_t m_length; }; -class OriginAccessEntryTestPlatform : public blink::Platform { +class OriginAccessEntryTestPlatform : public TestingPlatformSupport { public: - OriginAccessEntryTestPlatform() - : m_oldPlatform(Platform::current()) - { - Platform::initialize(this); - } - - ~OriginAccessEntryTestPlatform() - { - Platform::initialize(m_oldPlatform); - } - blink::WebPublicSuffixList* publicSuffixList() override { return &m_suffixList; } - // Stub for pure virtual method. - void cryptographicallyRandomValues(unsigned char*, size_t) override - { - RELEASE_ASSERT_NOT_REACHED(); - } - - const unsigned char* getTraceCategoryEnabledFlag(const char* categoryName) override - { - static const unsigned char tracingIsDisabled = 0; - return &tracingIsDisabled; - } - void setPublicSuffix(const blink::WebString& suffix) { m_suffixList.setPublicSuffix(suffix); } private: - blink::Platform* m_oldPlatform; OriginAccessEntryTestSuffixList m_suffixList; }; @@ -313,4 +290,3 @@ } } // namespace blink -
diff --git a/third_party/WebKit/Source/web/BUILD.gn b/third_party/WebKit/Source/web/BUILD.gn index 779c6339..f19d290 100644 --- a/third_party/WebKit/Source/web/BUILD.gn +++ b/third_party/WebKit/Source/web/BUILD.gn
@@ -21,13 +21,13 @@ output_name = "blink_web" deps = [ + "//skia", "//third_party/WebKit/Source/core", "//third_party/WebKit/Source/modules", "//third_party/WebKit/Source/platform", - "//skia", + "//third_party/angle:translator", "//third_party/icu", "//v8", - "//third_party/angle:translator", ] include_dirs = [ "//third_party/skia/include/utils" ] @@ -105,12 +105,13 @@ ":test_support", ":web", "//base", - "//base/test:test_support", "//base:i18n", + "//base/test:test_support", "//content/test:test_support", "//testing/gmock", "//testing/gtest", "//third_party/WebKit/Source/platform:test_support", + "//third_party/WebKit/Source/wtf", "//third_party/WebKit/Source/wtf:test_support", "//third_party/libwebp", "//third_party/zlib",
diff --git a/third_party/WebKit/Source/web/ImageDecodeBench.cpp b/third_party/WebKit/Source/web/ImageDecodeBench.cpp index 988f2e8f..41c3870 100644 --- a/third_party/WebKit/Source/web/ImageDecodeBench.cpp +++ b/third_party/WebKit/Source/web/ImageDecodeBench.cpp
@@ -25,6 +25,7 @@ #include "platform/SharedBuffer.h" #include "platform/image-decoders/ImageDecoder.h" +#include "platform/testing/TestingPlatformSupport.h" #include "public/platform/Platform.h" #include "public/web/WebKit.h" #include "wtf/OwnPtr.h" @@ -360,18 +361,8 @@ // Create a web platform without V8. - class WebPlatform : public blink::Platform { + class WebPlatform : public TestingPlatformSupport { public: - const unsigned char* getTraceCategoryEnabledFlag(const char*) override - { - return reinterpret_cast<const unsigned char *>("nope-none-nada"); - } - - void cryptographicallyRandomValues(unsigned char*, size_t) override - { - RELEASE_ASSERT_NOT_REACHED(); - } - void screenColorProfile(WebVector<char>* profile) override { getScreenColorProfile(profile); // Returns a whacked color profile.
diff --git a/third_party/WebKit/Source/web/WebDevToolsAgentImpl.cpp b/third_party/WebKit/Source/web/WebDevToolsAgentImpl.cpp index 436a0c0..7eef0622 100644 --- a/third_party/WebKit/Source/web/WebDevToolsAgentImpl.cpp +++ b/third_party/WebKit/Source/web/WebDevToolsAgentImpl.cpp
@@ -254,8 +254,9 @@ class DebuggerTask : public InspectorTaskRunner::Task { public: - DebuggerTask(PassOwnPtr<WebDevToolsAgent::MessageDescriptor> descriptor) - : m_descriptor(descriptor) + DebuggerTask(int sessionId, PassOwnPtr<WebDevToolsAgent::MessageDescriptor> descriptor) + : m_sessionId(sessionId) + , m_descriptor(descriptor) { } @@ -268,10 +269,11 @@ WebDevToolsAgentImpl* agentImpl = static_cast<WebDevToolsAgentImpl*>(webagent); if (agentImpl->m_attached) - agentImpl->dispatchMessageFromFrontend(m_descriptor->message()); + agentImpl->dispatchMessageFromFrontend(m_sessionId, m_descriptor->message()); } private: + int m_sessionId; OwnPtr<WebDevToolsAgent::MessageDescriptor> m_descriptor; }; @@ -331,6 +333,7 @@ , m_pageConsoleAgent(nullptr) , m_agents(m_instrumentingAgents.get(), m_state.get()) , m_deferredAgentsInitialized(false) + , m_sessionId(0) { ASSERT(isMainThread()); ASSERT(m_webLocalFrameImpl->frame()); @@ -438,11 +441,6 @@ m_instrumentingAgents->reset(); } -InspectorOverlay* WebDevToolsAgentImpl::overlay() const -{ - return m_overlay.get(); -} - void WebDevToolsAgentImpl::initializeDeferredAgents() { if (m_deferredAgentsInitialized) @@ -503,13 +501,14 @@ m_agents.append(agent); } -void WebDevToolsAgentImpl::attach(const WebString& hostId) +void WebDevToolsAgentImpl::attach(const WebString& hostId, int sessionId) { if (m_attached) return; // Set the attached bit first so that sync notifications were delivered. m_attached = true; + m_sessionId = sessionId; initializeDeferredAgents(); m_resourceAgent->setHostId(hostId); @@ -528,12 +527,12 @@ Platform::current()->currentThread()->addTaskObserver(this); } -void WebDevToolsAgentImpl::reattach(const WebString& hostId, const WebString& savedState) +void WebDevToolsAgentImpl::reattach(const WebString& hostId, int sessionId, const WebString& savedState) { if (m_attached) return; - attach(hostId); + attach(hostId, sessionId); m_state->loadFromCookie(savedState); m_agents.restore(); } @@ -560,6 +559,7 @@ InspectorInstrumentation::frontendDeleted(); InspectorInstrumentation::unregisterInstrumentingAgents(m_instrumentingAgents.get()); + m_sessionId = 0; m_attached = false; } @@ -604,21 +604,21 @@ m_client->disableTracing(); } -void WebDevToolsAgentImpl::dispatchOnInspectorBackend(const WebString& message) +void WebDevToolsAgentImpl::dispatchOnInspectorBackend(int sessionId, const WebString& message) { if (!m_attached) return; if (WebDevToolsAgent::shouldInterruptForMessage(message)) MainThreadDebugger::instance()->taskRunner()->runPendingTasks(); else - dispatchMessageFromFrontend(message); + dispatchMessageFromFrontend(sessionId, message); } -void WebDevToolsAgentImpl::dispatchMessageFromFrontend(const String& message) +void WebDevToolsAgentImpl::dispatchMessageFromFrontend(int sessionId, const String& message) { InspectorTaskRunner::IgnoreInterruptsScope scope(MainThreadDebugger::instance()->taskRunner()); if (m_inspectorBackendDispatcher) - m_inspectorBackendDispatcher->dispatch(message); + m_inspectorBackendDispatcher->dispatch(sessionId, message); } void WebDevToolsAgentImpl::inspectElementAt(const WebPoint& pointInRootFrame) @@ -638,12 +638,12 @@ m_domAgent->inspect(node); } -void WebDevToolsAgentImpl::sendProtocolResponse(int callId, PassRefPtr<JSONObject> message) +void WebDevToolsAgentImpl::sendProtocolResponse(int sessionId, int callId, PassRefPtr<JSONObject> message) { if (!m_attached) return; flushPendingProtocolNotifications(); - m_client->sendProtocolMessage(callId, message->toJSONString(), m_stateCookie); + m_client->sendProtocolMessage(sessionId, callId, message->toJSONString(), m_stateCookie); m_stateCookie = String(); } @@ -651,7 +651,7 @@ { if (!m_attached) return; - m_notificationQueue.append(message); + m_notificationQueue.append(std::make_pair(m_sessionId, message)); } void WebDevToolsAgentImpl::flush() @@ -684,12 +684,11 @@ void WebDevToolsAgentImpl::flushPendingProtocolNotifications() { - if (!m_attached) - return; - - m_agents.flushPendingProtocolNotifications(); - for (size_t i = 0; i < m_notificationQueue.size(); ++i) - m_client->sendProtocolMessage(0, m_notificationQueue[i]->toJSONString(), WebString()); + if (m_attached) { + m_agents.flushPendingProtocolNotifications(); + for (size_t i = 0; i < m_notificationQueue.size(); ++i) + m_client->sendProtocolMessage(m_notificationQueue[i].first, 0, m_notificationQueue[i].second->toJSONString(), WebString()); + } m_notificationQueue.clear(); } @@ -710,11 +709,11 @@ flushPendingProtocolNotifications(); } -void WebDevToolsAgent::interruptAndDispatch(MessageDescriptor* rawDescriptor) +void WebDevToolsAgent::interruptAndDispatch(int sessionId, MessageDescriptor* rawDescriptor) { // rawDescriptor can't be a PassOwnPtr because interruptAndDispatch is a WebKit API function. OwnPtr<MessageDescriptor> descriptor = adoptPtr(rawDescriptor); - OwnPtr<DebuggerTask> task = adoptPtr(new DebuggerTask(descriptor.release())); + OwnPtr<DebuggerTask> task = adoptPtr(new DebuggerTask(sessionId, descriptor.release())); MainThreadDebugger::interruptMainThreadAndRun(task.release()); }
diff --git a/third_party/WebKit/Source/web/WebDevToolsAgentImpl.h b/third_party/WebKit/Source/web/WebDevToolsAgentImpl.h index f3e5a6b7..2e7f8e34 100644 --- a/third_party/WebKit/Source/web/WebDevToolsAgentImpl.h +++ b/third_party/WebKit/Source/web/WebDevToolsAgentImpl.h
@@ -83,9 +83,9 @@ void willBeDestroyed(); WebDevToolsAgentClient* client() { return m_client; } - InspectorOverlay* overlay() const; + InspectorOverlay* overlay() const { return m_overlay.get(); } void flushPendingProtocolNotifications(); - void dispatchMessageFromFrontend(const String& message); + void dispatchMessageFromFrontend(int sessionId, const String& message); void registerAgent(PassOwnPtrWillBeRawPtr<InspectorAgent>); static void webViewImplClosed(WebViewImpl*); static void webFrameWidgetImplClosed(WebFrameWidgetImpl*); @@ -98,11 +98,11 @@ void layerTreeViewChanged(WebLayerTreeView*); // WebDevToolsAgent implementation. - void attach(const WebString& hostId) override; - void reattach(const WebString& hostId, const WebString& savedState) override; + void attach(const WebString& hostId, int sessionId) override; + void reattach(const WebString& hostId, int sessionId, const WebString& savedState) override; void detach() override; void continueProgram() override; - void dispatchOnInspectorBackend(const WebString& message) override; + void dispatchOnInspectorBackend(int sessionId, const WebString& message) override; void inspectElementAt(const WebPoint&) override; void evaluateInWebInspector(long callId, const WebString& script) override; WebString evaluateInWebInspectorOverlay(const WebString& script) override; @@ -121,7 +121,7 @@ void resumeStartup() override; // InspectorFrontendChannel implementation. - void sendProtocolResponse(int callId, PassRefPtr<JSONObject> message) override; + void sendProtocolResponse(int sessionId, int callId, PassRefPtr<JSONObject> message) override; void sendProtocolNotification(PassRefPtr<JSONObject> message) override; void flush() override; @@ -159,8 +159,9 @@ InspectorAgentRegistry m_agents; bool m_deferredAgentsInitialized; - typedef Vector<RefPtr<JSONObject>> NotificationQueue; + typedef Vector<std::pair<int, RefPtr<JSONObject>>> NotificationQueue; NotificationQueue m_notificationQueue; + int m_sessionId; String m_stateCookie; friend class DebuggerTask;
diff --git a/third_party/WebKit/Source/web/WebEmbeddedWorkerImpl.cpp b/third_party/WebKit/Source/web/WebEmbeddedWorkerImpl.cpp index 2a4236d..6206efc2 100644 --- a/third_party/WebKit/Source/web/WebEmbeddedWorkerImpl.cpp +++ b/third_party/WebKit/Source/web/WebEmbeddedWorkerImpl.cpp
@@ -157,18 +157,18 @@ m_workerInspectorProxy->workerThreadTerminated(); } -void WebEmbeddedWorkerImpl::attachDevTools(const WebString& hostId) +void WebEmbeddedWorkerImpl::attachDevTools(const WebString& hostId, int sessionId) { WebDevToolsAgent* devtoolsAgent = m_mainFrame->devToolsAgent(); if (devtoolsAgent) - devtoolsAgent->attach(hostId); + devtoolsAgent->attach(hostId, sessionId); } -void WebEmbeddedWorkerImpl::reattachDevTools(const WebString& hostId, const WebString& savedState) +void WebEmbeddedWorkerImpl::reattachDevTools(const WebString& hostId, int sessionId, const WebString& savedState) { WebDevToolsAgent* devtoolsAgent = m_mainFrame->devToolsAgent(); if (devtoolsAgent) - devtoolsAgent->reattach(hostId, savedState); + devtoolsAgent->reattach(hostId, sessionId, savedState); resumeStartup(); } @@ -179,13 +179,13 @@ devtoolsAgent->detach(); } -void WebEmbeddedWorkerImpl::dispatchDevToolsMessage(const WebString& message) +void WebEmbeddedWorkerImpl::dispatchDevToolsMessage(int sessionId, const WebString& message) { if (m_askedToTerminate) return; WebDevToolsAgent* devtoolsAgent = m_mainFrame->devToolsAgent(); if (devtoolsAgent) - devtoolsAgent->dispatchOnInspectorBackend(message); + devtoolsAgent->dispatchOnInspectorBackend(sessionId, message); } void WebEmbeddedWorkerImpl::postMessageToPageInspector(const String& message) @@ -285,9 +285,9 @@ // invoked and |this| might have been deleted at this point. } -void WebEmbeddedWorkerImpl::sendProtocolMessage(int callId, const WebString& message, const WebString& state) +void WebEmbeddedWorkerImpl::sendProtocolMessage(int sessionId, int callId, const WebString& message, const WebString& state) { - m_workerContextClient->sendDevToolsMessage(callId, message, state); + m_workerContextClient->sendDevToolsMessage(sessionId, callId, message, state); } void WebEmbeddedWorkerImpl::resumeStartup()
diff --git a/third_party/WebKit/Source/web/WebEmbeddedWorkerImpl.h b/third_party/WebKit/Source/web/WebEmbeddedWorkerImpl.h index 55f53bb2..78a46de3 100644 --- a/third_party/WebKit/Source/web/WebEmbeddedWorkerImpl.h +++ b/third_party/WebKit/Source/web/WebEmbeddedWorkerImpl.h
@@ -62,10 +62,10 @@ // WebEmbeddedWorker overrides. void startWorkerContext(const WebEmbeddedWorkerStartData&) override; void terminateWorkerContext() override; - void attachDevTools(const WebString& hostId) override; - void reattachDevTools(const WebString& hostId, const WebString& savedState) override; + void attachDevTools(const WebString& hostId, int sessionId) override; + void reattachDevTools(const WebString& hostId, int sessionId, const WebString& savedState) override; void detachDevTools() override; - void dispatchDevToolsMessage(const WebString&) override; + void dispatchDevToolsMessage(int sessionId, const WebString&) override; void postMessageToPageInspector(const WTF::String&); @@ -80,7 +80,7 @@ void didFinishDocumentLoad(WebLocalFrame*, bool documentIsEmpty) override; // WebDevToolsAgentClient overrides. - void sendProtocolMessage(int callId, const WebString&, const WebString&) override; + void sendProtocolMessage(int sessionId, int callId, const WebString&, const WebString&) override; void resumeStartup() override; void onScriptLoaderFinished();
diff --git a/third_party/WebKit/Source/web/WebLocalFrameImpl.cpp b/third_party/WebKit/Source/web/WebLocalFrameImpl.cpp index 7428894f..4cb7d027 100644 --- a/third_party/WebKit/Source/web/WebLocalFrameImpl.cpp +++ b/third_party/WebKit/Source/web/WebLocalFrameImpl.cpp
@@ -1836,11 +1836,6 @@ return WebViewImpl::fromPage(frame()->page()); } -WebDevToolsAgentImpl* WebLocalFrameImpl::devToolsAgentImpl() const -{ - return m_devToolsAgent.get(); -} - WebDataSourceImpl* WebLocalFrameImpl::dataSourceImpl() const { return static_cast<WebDataSourceImpl*>(dataSource());
diff --git a/third_party/WebKit/Source/web/WebLocalFrameImpl.h b/third_party/WebKit/Source/web/WebLocalFrameImpl.h index 1daa161..79165d0 100644 --- a/third_party/WebKit/Source/web/WebLocalFrameImpl.h +++ b/third_party/WebKit/Source/web/WebLocalFrameImpl.h
@@ -287,7 +287,7 @@ FrameView* frameView() const { return frame() ? frame()->view() : 0; } - WebDevToolsAgentImpl* devToolsAgentImpl() const; + WebDevToolsAgentImpl* devToolsAgentImpl() const { return m_devToolsAgent.get(); } // Getters for the impls corresponding to Get(Provisional)DataSource. They // may return 0 if there is no corresponding data source.
diff --git a/third_party/WebKit/Source/web/WebPluginLoadObserver.cpp b/third_party/WebKit/Source/web/WebPluginLoadObserver.cpp index 526cae7..911a7519 100644 --- a/third_party/WebKit/Source/web/WebPluginLoadObserver.cpp +++ b/third_party/WebKit/Source/web/WebPluginLoadObserver.cpp
@@ -36,13 +36,6 @@ namespace blink { -WebPluginLoadObserver::WebPluginLoadObserver(WebPluginContainerImpl* pluginContainer, const WebURL& notifyURL, void* notifyData) - : m_pluginContainer(pluginContainer) - , m_notifyURL(notifyURL) - , m_notifyData(notifyData) -{ -} - WebPluginLoadObserver::~WebPluginLoadObserver() { #if !ENABLE(OILPAN)
diff --git a/third_party/WebKit/Source/web/WebPluginLoadObserver.h b/third_party/WebKit/Source/web/WebPluginLoadObserver.h index 7f731785..25ecd7a1 100644 --- a/third_party/WebKit/Source/web/WebPluginLoadObserver.h +++ b/third_party/WebKit/Source/web/WebPluginLoadObserver.h
@@ -58,7 +58,12 @@ DECLARE_TRACE(); private: - WebPluginLoadObserver(WebPluginContainerImpl*, const WebURL&, void*); + WebPluginLoadObserver(WebPluginContainerImpl* pluginContainer, const WebURL& notifyURL, void* notifyData) + : m_pluginContainer(pluginContainer) + , m_notifyURL(notifyURL) + , m_notifyData(notifyData) + { + } RawPtrWillBeWeakMember<WebPluginContainerImpl> m_pluginContainer; WebURL m_notifyURL;
diff --git a/third_party/WebKit/Source/web/WebRemoteFrameImpl.cpp b/third_party/WebKit/Source/web/WebRemoteFrameImpl.cpp index f0a8989..60f6c2b2 100644 --- a/third_party/WebKit/Source/web/WebRemoteFrameImpl.cpp +++ b/third_party/WebKit/Source/web/WebRemoteFrameImpl.cpp
@@ -739,11 +739,6 @@ m_frame = frame; } -RemoteFrame* WebRemoteFrameImpl::frame() const -{ - return m_frame.get(); -} - WebRemoteFrameImpl* WebRemoteFrameImpl::fromFrame(RemoteFrame& frame) { if (!frame.client())
diff --git a/third_party/WebKit/Source/web/WebRemoteFrameImpl.h b/third_party/WebKit/Source/web/WebRemoteFrameImpl.h index 2f4bbaf..2c2a59f 100644 --- a/third_party/WebKit/Source/web/WebRemoteFrameImpl.h +++ b/third_party/WebKit/Source/web/WebRemoteFrameImpl.h
@@ -171,7 +171,7 @@ void initializeCoreFrame(FrameHost*, FrameOwner*, const AtomicString& name); void setCoreFrame(PassRefPtrWillBeRawPtr<RemoteFrame>); - RemoteFrame* frame() const; + RemoteFrame* frame() const { return m_frame.get(); } WebRemoteFrameClient* client() const { return m_client; }
diff --git a/third_party/WebKit/Source/web/WebSharedWorkerImpl.cpp b/third_party/WebKit/Source/web/WebSharedWorkerImpl.cpp index e2df066..9839da9a 100644 --- a/third_party/WebKit/Source/web/WebSharedWorkerImpl.cpp +++ b/third_party/WebKit/Source/web/WebSharedWorkerImpl.cpp
@@ -197,9 +197,9 @@ return m_networkProvider->serviceWorkerID(dataSource); } -void WebSharedWorkerImpl::sendProtocolMessage(int callId, const WebString& message, const WebString& state) +void WebSharedWorkerImpl::sendProtocolMessage(int sessionId, int callId, const WebString& message, const WebString& state) { - m_client->sendDevToolsMessage(callId, message, state); + m_client->sendDevToolsMessage(sessionId, callId, message, state); } void WebSharedWorkerImpl::resumeStartup() @@ -364,18 +364,18 @@ m_pauseWorkerContextOnStart = true; } -void WebSharedWorkerImpl::attachDevTools(const WebString& hostId) +void WebSharedWorkerImpl::attachDevTools(const WebString& hostId, int sessionId) { WebDevToolsAgent* devtoolsAgent = m_mainFrame->devToolsAgent(); if (devtoolsAgent) - devtoolsAgent->attach(hostId); + devtoolsAgent->attach(hostId, sessionId); } -void WebSharedWorkerImpl::reattachDevTools(const WebString& hostId, const WebString& savedState) +void WebSharedWorkerImpl::reattachDevTools(const WebString& hostId, int sessionId, const WebString& savedState) { WebDevToolsAgent* devtoolsAgent = m_mainFrame->devToolsAgent(); if (devtoolsAgent) - devtoolsAgent->reattach(hostId, savedState); + devtoolsAgent->reattach(hostId, sessionId, savedState); resumeStartup(); } @@ -386,13 +386,13 @@ devtoolsAgent->detach(); } -void WebSharedWorkerImpl::dispatchDevToolsMessage(const WebString& message) +void WebSharedWorkerImpl::dispatchDevToolsMessage(int sessionId, const WebString& message) { if (m_askedToTerminate) return; WebDevToolsAgent* devtoolsAgent = m_mainFrame->devToolsAgent(); if (devtoolsAgent) - devtoolsAgent->dispatchOnInspectorBackend(message); + devtoolsAgent->dispatchOnInspectorBackend(sessionId, message); } WebSharedWorker* WebSharedWorker::create(WebSharedWorkerClient* client)
diff --git a/third_party/WebKit/Source/web/WebSharedWorkerImpl.h b/third_party/WebKit/Source/web/WebSharedWorkerImpl.h index 7845be60..76648cb6 100644 --- a/third_party/WebKit/Source/web/WebSharedWorkerImpl.h +++ b/third_party/WebKit/Source/web/WebSharedWorkerImpl.h
@@ -93,7 +93,7 @@ int64_t serviceWorkerID(WebDataSource&) override; // WebDevToolsAgentClient overrides. - void sendProtocolMessage(int callId, const WebString&, const WebString&) override; + void sendProtocolMessage(int sessionId, int callId, const WebString&, const WebString&) override; void resumeStartup() override; // WebSharedWorker methods: @@ -102,10 +102,10 @@ void terminateWorkerContext() override; void pauseWorkerContextOnStart() override; - void attachDevTools(const WebString& hostId) override; - void reattachDevTools(const WebString& hostId, const WebString& savedState) override; + void attachDevTools(const WebString& hostId, int sessionId) override; + void reattachDevTools(const WebString& hostId, int sesionId, const WebString& savedState) override; void detachDevTools() override; - void dispatchDevToolsMessage(const WebString&) override; + void dispatchDevToolsMessage(int sessionId, const WebString&) override; private: ~WebSharedWorkerImpl() override;
diff --git a/third_party/WebKit/Source/web/WebViewImpl.cpp b/third_party/WebKit/Source/web/WebViewImpl.cpp index 6d438f1..93970bc 100644 --- a/third_party/WebKit/Source/web/WebViewImpl.cpp +++ b/third_party/WebKit/Source/web/WebViewImpl.cpp
@@ -433,7 +433,6 @@ , m_layerTreeView(nullptr) , m_rootLayer(nullptr) , m_rootGraphicsLayer(nullptr) - , m_rootTransformLayer(nullptr) , m_graphicsLayerFactory(adoptPtr(new GraphicsLayerFactoryChromium(this))) , m_matchesHeuristicsForGpuRasterization(false) , m_recreatingGraphicsContext(false) @@ -4145,7 +4144,6 @@ if (layer) { m_rootGraphicsLayer = visualViewport.rootGraphicsLayer(); m_rootLayer = m_rootGraphicsLayer->platformLayer(); - m_rootTransformLayer = m_rootGraphicsLayer; updateRootLayerTransform(); m_layerTreeView->setRootLayer(*m_rootLayer); // We register viewport layers here since there may not be a layer @@ -4161,7 +4159,6 @@ } else { m_rootGraphicsLayer = nullptr; m_rootLayer = nullptr; - m_rootTransformLayer = nullptr; // This means that we're transitioning to a new page. Suppress // commits until Blink generates invalidations so we don't // attempt to paint too early in the next page load. @@ -4340,16 +4337,11 @@ void WebViewImpl::updateRootLayerTransform() { - // If we don't have a root graphics layer, we won't bother trying to find - // or update the transform layer. - if (!m_rootGraphicsLayer) - return; - - if (m_rootTransformLayer) { + if (m_rootGraphicsLayer) { TransformationMatrix transform; transform.translate(m_rootLayerOffset.width, m_rootLayerOffset.height); transform = transform.scale(m_rootLayerScale); - m_rootTransformLayer->setTransform(transform); + m_rootGraphicsLayer->setTransform(transform); } }
diff --git a/third_party/WebKit/Source/web/WebViewImpl.h b/third_party/WebKit/Source/web/WebViewImpl.h index 624b00e..719839f2 100644 --- a/third_party/WebKit/Source/web/WebViewImpl.h +++ b/third_party/WebKit/Source/web/WebViewImpl.h
@@ -721,7 +721,6 @@ WebLayerTreeView* m_layerTreeView; WebLayer* m_rootLayer; GraphicsLayer* m_rootGraphicsLayer; - GraphicsLayer* m_rootTransformLayer; OwnPtr<GraphicsLayerFactory> m_graphicsLayerFactory; bool m_matchesHeuristicsForGpuRasterization; // If true, the graphics context is being restored.
diff --git a/third_party/WebKit/Source/web/tests/TextFinderTest.cpp b/third_party/WebKit/Source/web/tests/TextFinderTest.cpp index a9ebd81..d3260d1 100644 --- a/third_party/WebKit/Source/web/tests/TextFinderTest.cpp +++ b/third_party/WebKit/Source/web/tests/TextFinderTest.cpp
@@ -14,6 +14,7 @@ #include "core/html/HTMLElement.h" #include "core/layout/TextAutosizer.h" #include "core/page/Page.h" +#include "platform/testing/TestingPlatformSupport.h" #include "platform/testing/UnitTestHelpers.h" #include "public/platform/Platform.h" #include "public/web/WebDocument.h" @@ -29,7 +30,15 @@ class TextFinderTest : public ::testing::Test { protected: - void SetUp() override; + TextFinderTest() + { + m_webViewHelper.initialize(); + WebLocalFrameImpl& frameImpl = *m_webViewHelper.webViewImpl()->mainFrameImpl(); + frameImpl.viewImpl()->resize(WebSize(640, 480)); + frameImpl.viewImpl()->updateAllLifecyclePhases(); + m_document = PassRefPtrWillBeRawPtr<Document>(frameImpl.document()); + m_textFinder = &frameImpl.ensureTextFinder(); + } Document& document() const; TextFinder& textFinder() const; @@ -42,16 +51,6 @@ RawPtrWillBePersistent<TextFinder> m_textFinder; }; -void TextFinderTest::SetUp() -{ - m_webViewHelper.initialize(); - WebLocalFrameImpl& frameImpl = *m_webViewHelper.webViewImpl()->mainFrameImpl(); - frameImpl.viewImpl()->resize(WebSize(640, 480)); - frameImpl.viewImpl()->updateAllLifecyclePhases(); - m_document = PassRefPtrWillBeRawPtr<Document>(frameImpl.document()); - m_textFinder = &frameImpl.ensureTextFinder(); -} - Document& TextFinderTest::document() const { return *m_document; @@ -398,41 +397,19 @@ class TextFinderFakeTimerTest : public TextFinderTest { protected: - void SetUp() override; - void TearDown() override; - // A simple platform that mocks out the clock. - class TimeProxyPlatform : public Platform { + class TimeProxyPlatform : public TestingPlatformSupport { public: TimeProxyPlatform() - : m_timeCounter(0.) - , m_fallbackPlatform(0) - { } - - void install() + : m_timeCounter(m_oldPlatform->currentTimeSeconds()) { - // Check that the proxy wasn't installed yet. - ASSERT_NE(Platform::current(), this); - m_fallbackPlatform = Platform::current(); - m_timeCounter = m_fallbackPlatform->currentTimeSeconds(); - Platform::initialize(this); - ASSERT_EQ(Platform::current(), this); - } - - void remove() - { - // Check that the proxy was installed. - ASSERT_EQ(Platform::current(), this); - Platform::initialize(m_fallbackPlatform); - ASSERT_EQ(Platform::current(), m_fallbackPlatform); - m_fallbackPlatform = 0; } private: Platform& ensureFallback() { - ASSERT(m_fallbackPlatform); - return *m_fallbackPlatform; + ASSERT(m_oldPlatform); + return *m_oldPlatform; } // From blink::Platform: @@ -441,47 +418,22 @@ return ++m_timeCounter; } - // These blink::Platform methods must be overriden to make a usable object. - void cryptographicallyRandomValues(unsigned char* buffer, size_t length) override - { - ensureFallback().cryptographicallyRandomValues(buffer, length); - } - - const unsigned char* getTraceCategoryEnabledFlag(const char* categoryName) override - { - return ensureFallback().getTraceCategoryEnabledFlag(categoryName); - } - // These two methods allow timers to work correctly. double monotonicallyIncreasingTimeSeconds() override { return ensureFallback().monotonicallyIncreasingTimeSeconds(); } - WebThread* currentThread() override { return ensureFallback().currentThread(); } WebUnitTestSupport* unitTestSupport() override { return ensureFallback().unitTestSupport(); } WebString defaultLocale() override { return ensureFallback().defaultLocale(); } WebCompositorSupport* compositorSupport() override { return ensureFallback().compositorSupport(); } double m_timeCounter; - Platform* m_fallbackPlatform; }; TimeProxyPlatform m_proxyTimePlatform; }; -void TextFinderFakeTimerTest::SetUp() -{ - TextFinderTest::SetUp(); - m_proxyTimePlatform.install(); -} - -void TextFinderFakeTimerTest::TearDown() -{ - m_proxyTimePlatform.remove(); - TextFinderTest::TearDown(); -} - TEST_F(TextFinderFakeTimerTest, ScopeWithTimeouts) { // Make a long string.
diff --git a/third_party/WebKit/Source/web/web_tests.gyp b/third_party/WebKit/Source/web/web_tests.gyp index 98807e31..acb59dc 100644 --- a/third_party/WebKit/Source/web/web_tests.gyp +++ b/third_party/WebKit/Source/web/web_tests.gyp
@@ -49,6 +49,7 @@ '../../public/blink.gyp:blink', '../config.gyp:unittest_config', '../platform/blink_platform_tests.gyp:blink_platform_test_support', + '../wtf/wtf.gyp:wtf', '../wtf/wtf_tests.gyp:wtf_unittest_helpers', 'web.gyp:blink_web_test_support', '<(DEPTH)/base/base.gyp:base',
diff --git a/third_party/WebKit/Source/wtf/HashTraits.h b/third_party/WebKit/Source/wtf/HashTraits.h index b131594..e280ea5 100644 --- a/third_party/WebKit/Source/wtf/HashTraits.h +++ b/third_party/WebKit/Source/wtf/HashTraits.h
@@ -27,6 +27,7 @@ #include "wtf/TypeTraits.h" #include <limits> #include <string.h> // For memset. +#include <type_traits> #include <utility> namespace WTF { @@ -76,7 +77,7 @@ static bool isDeletedValue(T value) { return value == static_cast<T>(-1); } }; -template <typename T> struct GenericHashTraits : GenericHashTraitsBase<IsInteger<T>::value, T> { +template <typename T> struct GenericHashTraits : GenericHashTraitsBase<std::is_integral<T>::value, T> { typedef T TraitType; typedef T EmptyValueType;
diff --git a/third_party/WebKit/Source/wtf/OwnPtr.h b/third_party/WebKit/Source/wtf/OwnPtr.h index abc5966b..cf25db3f 100644 --- a/third_party/WebKit/Source/wtf/OwnPtr.h +++ b/third_party/WebKit/Source/wtf/OwnPtr.h
@@ -125,7 +125,7 @@ template <typename U> inline OwnPtr<T>::OwnPtr(const PassOwnPtr<U>& o, EnsurePtrConvertibleArgDefn(U, T)) : m_ptr(o.leakPtr()) { - static_assert(!IsArray<T>::value, "pointers to array must never be converted"); + static_assert(!std::is_array<T>::value, "pointers to array must never be converted"); } template <typename T> inline void OwnPtr<T>::clear() @@ -151,7 +151,7 @@ template <typename T> inline typename OwnPtr<T>::ValueType& OwnPtr<T>::operator[](std::ptrdiff_t i) const { - static_assert(IsArray<T>::value, "elements access is possible for arrays only"); + static_assert(std::is_array<T>::value, "elements access is possible for arrays only"); ASSERT(m_ptr); ASSERT(i >= 0); return m_ptr[i]; @@ -169,7 +169,7 @@ template <typename T> template <typename U> inline OwnPtr<T>& OwnPtr<T>::operator=(const PassOwnPtr<U>& o) { - static_assert(!IsArray<T>::value, "pointers to array must never be converted"); + static_assert(!std::is_array<T>::value, "pointers to array must never be converted"); PtrType ptr = m_ptr; m_ptr = o.leakPtr(); ASSERT(!ptr || m_ptr != ptr); @@ -186,7 +186,7 @@ template <typename U> inline OwnPtr<T>::OwnPtr(OwnPtr<U>&& o) : m_ptr(o.leakPtr()) { - static_assert(!IsArray<T>::value, "pointers to array must never be converted"); + static_assert(!std::is_array<T>::value, "pointers to array must never be converted"); } template <typename T> inline OwnPtr<T>& OwnPtr<T>::operator=(OwnPtr<T>&& o) @@ -202,7 +202,7 @@ template <typename T> template <typename U> inline OwnPtr<T>& OwnPtr<T>::operator=(OwnPtr<U>&& o) { - static_assert(!IsArray<T>::value, "pointers to array must never be converted"); + static_assert(!std::is_array<T>::value, "pointers to array must never be converted"); PtrType ptr = m_ptr; m_ptr = o.leakPtr(); ASSERT(!ptr || m_ptr != ptr);
diff --git a/third_party/WebKit/Source/wtf/PassOwnPtr.h b/third_party/WebKit/Source/wtf/PassOwnPtr.h index 452a12b..a3ee6d65 100644 --- a/third_party/WebKit/Source/wtf/PassOwnPtr.h +++ b/third_party/WebKit/Source/wtf/PassOwnPtr.h
@@ -111,7 +111,7 @@ template <typename U> inline PassOwnPtr<T>::PassOwnPtr(const PassOwnPtr<U>& o, EnsurePtrConvertibleArgDefn(U, T)) : m_ptr(o.leakPtr()) { - static_assert(!IsArray<T>::value, "pointers to array must never be converted"); + static_assert(!std::is_array<T>::value, "pointers to array must never be converted"); } template <typename T> inline typename PassOwnPtr<T>::PtrType PassOwnPtr<T>::leakPtr() const @@ -153,7 +153,7 @@ template <typename T, typename U> inline PassOwnPtr<T> static_pointer_cast(const PassOwnPtr<U>& p) { - static_assert(!IsArray<T>::value, "pointers to array must never be converted"); + static_assert(!std::is_array<T>::value, "pointers to array must never be converted"); return adoptPtr(static_cast<T*>(p.leakPtr())); }
diff --git a/third_party/WebKit/Source/wtf/TypeTraits.cpp b/third_party/WebKit/Source/wtf/TypeTraits.cpp index fe757fa..e566e44 100644 --- a/third_party/WebKit/Source/wtf/TypeTraits.cpp +++ b/third_party/WebKit/Source/wtf/TypeTraits.cpp
@@ -25,78 +25,14 @@ #include "Assertions.h" #include "Noncopyable.h" +#include <type_traits> + namespace WTF { -static_assert(IsInteger<bool>::value, "bool should be an integer"); -static_assert(IsInteger<char>::value, "char should be an integer"); -static_assert(IsInteger<signed char>::value, "signed char should be an integer"); -static_assert(IsInteger<unsigned char>::value, "unsigned char should be an integer"); -static_assert(IsInteger<short>::value, "short should be an integer"); -static_assert(IsInteger<unsigned short>::value, "unsigned short should be an integer"); -static_assert(IsInteger<int>::value, "int should be an integer"); -static_assert(IsInteger<unsigned>::value, "unsigned int should be an integer"); -static_assert(IsInteger<long>::value, "long should be an integer"); -static_assert(IsInteger<unsigned long>::value, "unsigned long should be an integer"); -static_assert(IsInteger<long long>::value, "long long should be an integer"); -static_assert(IsInteger<unsigned long long>::value, "unsigned long long should be an integer"); -#if !COMPILER(MSVC) || defined(_NATIVE_WCHAR_T_DEFINED) -static_assert(IsInteger<wchar_t>::value, "wchar_t should be an integer"); -#endif -static_assert(!IsInteger<char*>::value, "char pointer should not be an integer"); -static_assert(!IsInteger<const char*>::value, "const char pointer should not be an integer"); -static_assert(!IsInteger<volatile char*>::value, "volatile char pointer should not be an integer"); -static_assert(!IsInteger<double>::value, "double should not be an integer"); -static_assert(!IsInteger<float>::value, "float should not be an integer"); - -static_assert(IsFloatingPoint<float>::value, "float should be floating point"); -static_assert(IsFloatingPoint<double>::value, "double should be floating point"); -static_assert(IsFloatingPoint<long double>::value, "long double should be floating point"); -static_assert(!IsFloatingPoint<int>::value, "int should not be floating point"); - -static_assert(IsPointer<void*>::value, "void* should be a pointer"); -static_assert(IsPointer<char*>::value, "char* should be a pointer"); -static_assert(IsPointer<const char*>::value, "const char* should be a pointer"); -static_assert(!IsPointer<char>::value, "char should not be a pointer"); -static_assert(!IsPointer<int>::value, "int should not be a pointer"); -static_assert(!IsPointer<long>::value, "long should not be a pointer"); - -enum TestEnum { TestEnumValue }; -static_assert(IsEnum<TestEnum>::value, "enum should be an enumerated type"); -static_assert(!IsEnum<int>::value, "int should not be an enumerated type"); -static_assert(!IsEnum<TestEnum*>::value, "enum* should not be an enumerated type"); - -static_assert(IsScalar<TestEnum>::value, "enum should be scalar"); -static_assert(IsScalar<int>::value, "int should be scalar"); -static_assert(IsScalar<TestEnum*>::value, "enum* should be scalar"); -static_assert(IsScalar<double>::value, "double should be scalar"); - -static_assert(IsPod<bool>::value, "bool should be a POD"); -static_assert(IsPod<char>::value, "char should be a POD"); -static_assert(IsPod<signed char>::value, "signed char should be a POD"); -static_assert(IsPod<unsigned char>::value, "unsigned char should be a POD"); -static_assert(IsPod<short>::value, "short should be a POD"); -static_assert(IsPod<unsigned short>::value, "unsigned short should be a POD"); -static_assert(IsPod<int>::value, "int should be a POD"); -static_assert(IsPod<unsigned>::value, "unsigned int should be a POD"); -static_assert(IsPod<long>::value, "long should be a POD"); -static_assert(IsPod<unsigned long>::value, "unsigned long should be a POD"); -static_assert(IsPod<long long>::value, "long long should be a POD"); -static_assert(IsPod<unsigned long long>::value, "unsigned long long should be a POD"); -#if !COMPILER(MSVC) || defined(_NATIVE_WCHAR_T_DEFINED) -static_assert(IsPod<wchar_t>::value, "wchar_t should be a POD"); -#endif -static_assert(IsPod<char*>::value, "char* should be a POD"); -static_assert(IsPod<const char*>::value, "const char* should be a POD"); -static_assert(IsPod<volatile char*>::value, "volatile char* should be a POD"); -static_assert(IsPod<double>::value, "double should be a POD"); -static_assert(IsPod<long double>::value, "long double should be a POD"); -static_assert(IsPod<float>::value, "float should be a POD"); struct VirtualClass { virtual void A() { } }; static_assert(!IsTriviallyMoveAssignable<VirtualClass>::value, "VirtualClass should not be trivially move assignable"); -static_assert(!IsScalar<VirtualClass>::value, "classes should not be scalar"); -static_assert(IsScalar<VirtualClass*>::value, "pointers to classes should be scalar"); struct DestructorClass { ~DestructorClass() { } @@ -225,13 +161,9 @@ static_assert((IsSameType<int, RemoveReference<int&>::Type>::value), "RemoveReference should produce the corresponding non-reference type"); static_assert((IsSameType<int, RemoveReference<int&&>::Type>::value), "RemoveReference should produce the corresponding non-reference type"); - typedef int IntArray[]; typedef int IntArraySized[4]; -static_assert((IsArray<IntArray>::value), "IsArray should recognize arrays"); -static_assert((IsArray<IntArraySized>::value), "IsArray should recognize sized arrays"); - static_assert((IsSameType<int, RemoveExtent<IntArray>::Type>::value), "RemoveExtent should return the array element type of an array"); static_assert((IsSameType<int, RemoveExtent<IntArraySized>::Type>::value), "RemoveExtent should return the array element type of a sized array");
diff --git a/third_party/WebKit/Source/wtf/TypeTraits.h b/third_party/WebKit/Source/wtf/TypeTraits.h index b561606e5..9adcb989 100644 --- a/third_party/WebKit/Source/wtf/TypeTraits.h +++ b/third_party/WebKit/Source/wtf/TypeTraits.h
@@ -31,12 +31,8 @@ // The following are provided in this file: // -// IsInteger<T>::value -// IsPod<T>::value // IsConvertibleToInteger<T>::value // -// IsArray<T>::value -// // IsSameType<T, U>::value // // RemovePointer<T>::Type @@ -51,50 +47,6 @@ template <bool Predicate, class T = void> struct EnableIf; template <class T> struct EnableIf<true, T> { typedef T Type; }; -template <typename T> struct IsInteger { static const bool value = false; }; -template <> struct IsInteger<bool> { static const bool value = true; }; -template <> struct IsInteger<char> { static const bool value = true; }; -template <> struct IsInteger<signed char> { static const bool value = true; }; -template <> struct IsInteger<unsigned char> { static const bool value = true; }; -template <> struct IsInteger<short> { static const bool value = true; }; -template <> struct IsInteger<unsigned short> { static const bool value = true; }; -template <> struct IsInteger<int> { static const bool value = true; }; -template <> struct IsInteger<unsigned> { static const bool value = true; }; -template <> struct IsInteger<long> { static const bool value = true; }; -template <> struct IsInteger<unsigned long> { static const bool value = true; }; -template <> struct IsInteger<long long> { static const bool value = true; }; -template <> struct IsInteger<unsigned long long> { static const bool value = true; }; -#if !COMPILER(MSVC) || defined(_NATIVE_WCHAR_T_DEFINED) -template <> struct IsInteger<wchar_t> { static const bool value = true; }; -#endif - -template <typename T> struct IsFloatingPoint { static const bool value = false; }; -template <> struct IsFloatingPoint<float> { static const bool value = true; }; -template <> struct IsFloatingPoint<double> { static const bool value = true; }; -template <> struct IsFloatingPoint<long double> { static const bool value = true; }; - -template <typename T> struct IsArithmetic { static const bool value = IsInteger<T>::value || IsFloatingPoint<T>::value; }; - -template <typename T> struct IsPointer { - static const bool value = false; -}; - -template <typename P> struct IsPointer<const P*> { - static const bool value = true; -}; - -template <typename P> struct IsPointer<P*> { - static const bool value = true; -}; - -template <typename T> struct IsEnum { - static const bool value = __is_enum(T); -}; - -template <typename T> struct IsScalar { - static const bool value = IsEnum<T>::value || IsArithmetic<T>::value || IsPointer<T>::value; -}; - template <typename T> struct IsWeak { static const bool value = false; }; @@ -104,10 +56,6 @@ WeakHandlingInCollections }; -template <typename T> struct IsPod { - static const bool value = __is_pod(T); -}; - template <typename T> struct IsTriviallyCopyAssignable { static const bool value = __has_trivial_assign(T); }; @@ -147,7 +95,7 @@ }; public: - static const bool value = IsInteger<T>::value || IsConvertibleToDouble<!IsInteger<T>::value, T>::value; + static const bool value = std::is_integral<T>::value || IsConvertibleToDouble<!std::is_integral<T>::value, T>::value; }; template <typename From, typename To> class IsPointerConvertible { @@ -164,18 +112,6 @@ }; }; -template <class T> struct IsArray { - static const bool value = false; -}; - -template <class T> struct IsArray<T[]> { - static const bool value = true; -}; - -template <class T, size_t N> struct IsArray<T[N]> { - static const bool value = true; -}; - template <typename T, typename U> struct IsSameType { static const bool value = false; };
diff --git a/third_party/WebKit/Source/wtf/VectorTraits.h b/third_party/WebKit/Source/wtf/VectorTraits.h index 11798ad..8d106849 100644 --- a/third_party/WebKit/Source/wtf/VectorTraits.h +++ b/third_party/WebKit/Source/wtf/VectorTraits.h
@@ -24,6 +24,7 @@ #include "wtf/OwnPtr.h" #include "wtf/RefPtr.h" #include "wtf/TypeTraits.h" +#include <type_traits> #include <utility> namespace WTF { @@ -45,7 +46,7 @@ static const bool canMoveWithMemcpy = IsTriviallyMoveAssignable<T>::value; static const bool canCopyWithMemcpy = IsTriviallyCopyAssignable<T>::value; static const bool canFillWithMemset = IsTriviallyDefaultConstructible<T>::value && (sizeof(T) == sizeof(char)); - static const bool canCompareWithMemcmp = IsScalar<T>::value; // Types without padding. + static const bool canCompareWithMemcmp = std::is_scalar<T>::value; // Types without padding. template <typename U = void> struct NeedsTracingLazily { static const bool value = NeedsTracing<T>::value; @@ -108,7 +109,7 @@ #define WTF_ALLOW_MOVE_INIT_AND_COMPARE_WITH_MEM_FUNCTIONS(ClassName) \ namespace WTF { \ -static_assert(!IsTriviallyDefaultConstructible<ClassName>::value || !IsTriviallyMoveAssignable<ClassName>::value || !IsScalar<ClassName>::value, "macro not needed"); \ +static_assert(!IsTriviallyDefaultConstructible<ClassName>::value || !IsTriviallyMoveAssignable<ClassName>::value || !std::is_scalar<ClassName>::value, "macro not needed"); \ template <> \ struct VectorTraits<ClassName> : SimpleClassVectorTraits<ClassName> {}; \ }
diff --git a/third_party/WebKit/public/BUILD.gn b/third_party/WebKit/public/BUILD.gn index bf80025..dde23d0 100644 --- a/third_party/WebKit/public/BUILD.gn +++ b/third_party/WebKit/public/BUILD.gn
@@ -19,8 +19,8 @@ public_deps = [ ":blink_headers", ":blink_minimal", - "//third_party/WebKit/Source/web", "//third_party/WebKit/Source/platform", + "//third_party/WebKit/Source/web", ] }
diff --git a/third_party/WebKit/public/platform/WebPrivateOwnPtr.h b/third_party/WebKit/public/platform/WebPrivateOwnPtr.h index 9dea900..085b2e4 100644 --- a/third_party/WebKit/public/platform/WebPrivateOwnPtr.h +++ b/third_party/WebKit/public/platform/WebPrivateOwnPtr.h
@@ -93,7 +93,7 @@ template<typename T> template<typename U> inline WebPrivateOwnPtr<T>::WebPrivateOwnPtr(const PassOwnPtr<U>& o, EnsurePtrConvertibleArgDefn(U, T)) : m_ptr(o.leakPtr()) { - static_assert(!WTF::IsArray<T>::value, "Pointers to array must never be converted"); + static_assert(!std::is_array<T>::value, "Pointers to array must never be converted"); } #endif
diff --git a/third_party/WebKit/public/platform/modules/push_messaging/WebPushSubscription.h b/third_party/WebKit/public/platform/modules/push_messaging/WebPushSubscription.h index 33c628b3..11f50a7 100644 --- a/third_party/WebKit/public/platform/modules/push_messaging/WebPushSubscription.h +++ b/third_party/WebKit/public/platform/modules/push_messaging/WebPushSubscription.h
@@ -12,15 +12,17 @@ namespace blink { struct WebPushSubscription { - // The |endpoint| and |p256dh| must both be unique for each subscription. - WebPushSubscription(const WebURL& endpoint, const WebVector<unsigned char>& p256dh) + // The |endpoint|, |p256dh| and |auth| must all be unique for each subscription. + WebPushSubscription(const WebURL& endpoint, const WebVector<unsigned char>& p256dh, const WebVector<unsigned char>& auth) : endpoint(endpoint) , p256dh(p256dh) + , auth(auth) { } WebURL endpoint; WebVector<unsigned char> p256dh; + WebVector<unsigned char> auth; }; } // namespace blink
diff --git a/third_party/WebKit/public/web/WebDevToolsAgent.h b/third_party/WebKit/public/web/WebDevToolsAgent.h index dcb76c8..05daf115 100644 --- a/third_party/WebKit/public/web/WebDevToolsAgent.h +++ b/third_party/WebKit/public/web/WebDevToolsAgent.h
@@ -43,13 +43,13 @@ public: virtual ~WebDevToolsAgent() {} - virtual void attach(const WebString& hostId) = 0; - virtual void reattach(const WebString& hostId, const WebString& savedState) = 0; + virtual void attach(const WebString& hostId, int sessionId) = 0; + virtual void reattach(const WebString& hostId, int sessionId, const WebString& savedState) = 0; virtual void detach() = 0; virtual void continueProgram() = 0; - virtual void dispatchOnInspectorBackend(const WebString& message) = 0; + virtual void dispatchOnInspectorBackend(int sessionId, const WebString& message) = 0; virtual void inspectElementAt(const WebPoint&) = 0; @@ -64,7 +64,7 @@ virtual WebString message() = 0; }; // Asynchronously request debugger to pause immediately and run the command. - BLINK_EXPORT static void interruptAndDispatch(MessageDescriptor*); + BLINK_EXPORT static void interruptAndDispatch(int sessionId, MessageDescriptor*); BLINK_EXPORT static bool shouldInterruptForMessage(const WebString&); };
diff --git a/third_party/WebKit/public/web/WebDevToolsAgentClient.h b/third_party/WebKit/public/web/WebDevToolsAgentClient.h index f674358..fa8c9b7 100644 --- a/third_party/WebKit/public/web/WebDevToolsAgentClient.h +++ b/third_party/WebKit/public/web/WebDevToolsAgentClient.h
@@ -44,7 +44,7 @@ public: // Sends response message over the protocol, update agent state on the browser side for // potential re-attach. |callId| for notifications is 0, |state| for notifications is empty. - virtual void sendProtocolMessage(int callId, const WebString& response, const WebString& state) { } + virtual void sendProtocolMessage(int sessionId, int callId, const WebString& response, const WebString& state) { } // Returns process id. virtual long processId() { return -1; }
diff --git a/third_party/WebKit/public/web/WebEmbeddedWorker.h b/third_party/WebKit/public/web/WebEmbeddedWorker.h index 0731215..027e030d 100644 --- a/third_party/WebKit/public/web/WebEmbeddedWorker.h +++ b/third_party/WebKit/public/web/WebEmbeddedWorker.h
@@ -59,10 +59,10 @@ virtual void terminateWorkerContext() = 0; // Inspector related methods. - virtual void attachDevTools(const WebString& hostId) = 0; - virtual void reattachDevTools(const WebString& hostId, const WebString& savedState) = 0; + virtual void attachDevTools(const WebString& hostId, int sessionId) = 0; + virtual void reattachDevTools(const WebString& hostId, int sessionId, const WebString& savedState) = 0; virtual void detachDevTools() = 0; - virtual void dispatchDevToolsMessage(const WebString&) = 0; + virtual void dispatchDevToolsMessage(int sessionId, const WebString&) = 0; }; } // namespace blink
diff --git a/third_party/WebKit/public/web/WebSharedWorker.h b/third_party/WebKit/public/web/WebSharedWorker.h index 407d3d1..8143de2 100644 --- a/third_party/WebKit/public/web/WebSharedWorker.h +++ b/third_party/WebKit/public/web/WebSharedWorker.h
@@ -62,10 +62,10 @@ virtual void terminateWorkerContext() = 0; virtual void pauseWorkerContextOnStart() = 0; - virtual void attachDevTools(const WebString& hostId) = 0; - virtual void reattachDevTools(const WebString& hostId, const WebString& savedState) = 0; + virtual void attachDevTools(const WebString& hostId, int sessionId) = 0; + virtual void reattachDevTools(const WebString& hostId, int sessionId, const WebString& savedState) = 0; virtual void detachDevTools() = 0; - virtual void dispatchDevToolsMessage(const WebString&) = 0; + virtual void dispatchDevToolsMessage(int sessionId, const WebString&) = 0; }; } // namespace blink
diff --git a/third_party/WebKit/public/web/WebSharedWorkerClient.h b/third_party/WebKit/public/web/WebSharedWorkerClient.h index cae3117..bca580d 100644 --- a/third_party/WebKit/public/web/WebSharedWorkerClient.h +++ b/third_party/WebKit/public/web/WebSharedWorkerClient.h
@@ -78,7 +78,7 @@ // Ownership of the returned object is transferred to the caller. virtual WebServiceWorkerNetworkProvider* createServiceWorkerNetworkProvider(WebDataSource*) { return nullptr; } - virtual void sendDevToolsMessage(int callId, const WebString& message, const WebString& state) { } + virtual void sendDevToolsMessage(int sessionId, int callId, const WebString& message, const WebString& state) { } }; } // namespace blink
diff --git a/third_party/WebKit/public/web/modules/serviceworker/WebServiceWorkerContextClient.h b/third_party/WebKit/public/web/modules/serviceworker/WebServiceWorkerContextClient.h index 473a176..18fadb68 100644 --- a/third_party/WebKit/public/web/modules/serviceworker/WebServiceWorkerContextClient.h +++ b/third_party/WebKit/public/web/modules/serviceworker/WebServiceWorkerContextClient.h
@@ -103,7 +103,7 @@ virtual void reportConsoleMessage(int source, int level, const WebString& message, int lineNumber, const WebString& sourceURL) { } // Inspector related messages. - virtual void sendDevToolsMessage(int callId, const WebString& message, const WebString& state) { } + virtual void sendDevToolsMessage(int sessionId, int callId, const WebString& message, const WebString& state) { } // ServiceWorker specific method. virtual void didHandleActivateEvent(int eventID, WebServiceWorkerEventResult result) { }
diff --git a/third_party/android_media/BUILD.gn b/third_party/android_media/BUILD.gn index 96bba5a9..3316f4b 100644 --- a/third_party/android_media/BUILD.gn +++ b/third_party/android_media/BUILD.gn
@@ -19,9 +19,9 @@ DEPRECATED_java_in_dir = "java/src" deps = [ ":android_media_resources", + "//third_party/android_tools:android_support_v13_java", + "//third_party/android_tools:android_support_v7_appcompat_java", "//third_party/android_tools:android_support_v7_mediarouter_java", "//third_party/android_tools:android_support_v7_mediarouter_resources", - "//third_party/android_tools:android_support_v7_appcompat_java", - "//third_party/android_tools:android_support_v13_java", ] }
diff --git a/third_party/cacheinvalidation/BUILD.gn b/third_party/cacheinvalidation/BUILD.gn index dbcae8a8..6035d5d 100644 --- a/third_party/cacheinvalidation/BUILD.gn +++ b/third_party/cacheinvalidation/BUILD.gn
@@ -115,11 +115,11 @@ deps = [ ":cacheinvalidation", - "src/google/cacheinvalidation:cacheinvalidation_proto_cpp", "//base", "//base/test:run_all_unittests", "//testing/gmock", "//testing/gtest", + "src/google/cacheinvalidation:cacheinvalidation_proto_cpp", ] } @@ -144,6 +144,7 @@ # GYP: //third_party/cacheinvalidation/cacheinvalidation.gyp:cacheinvalidation_javalib android_library("cacheinvalidation_javalib") { + emma_never_instrument = true deps = [ ":cacheinvalidation_proto_java", "//third_party/android_protobuf:protobuf_nano_javalib",
diff --git a/third_party/cld_2/BUILD.gn b/third_party/cld_2/BUILD.gn index 43217012..b308eb00 100644 --- a/third_party/cld_2/BUILD.gn +++ b/third_party/cld_2/BUILD.gn
@@ -113,8 +113,8 @@ ] public_deps = [ - ":cld_2", ":cld2_data", + ":cld_2", ] configs -= [ "//build/config/compiler:chromium_code" ] configs += [
diff --git a/third_party/closure_compiler/externs/bluetooth_private.js b/third_party/closure_compiler/externs/bluetooth_private.js index df57de6e..2d63de7 100644 --- a/third_party/closure_compiler/externs/bluetooth_private.js +++ b/third_party/closure_compiler/externs/bluetooth_private.js
@@ -96,7 +96,7 @@ /** * @typedef {{ * device: !chrome.bluetooth.Device, - * response: (!chrome.bluetoothPrivate.PairingResponse|undefined), + * response: !chrome.bluetoothPrivate.PairingResponse, * pincode: (string|undefined), * passkey: (number|undefined) * }}
diff --git a/third_party/custom_tabs_client/BUILD.gn b/third_party/custom_tabs_client/BUILD.gn index 830c70a8..443424c1 100644 --- a/third_party/custom_tabs_client/BUILD.gn +++ b/third_party/custom_tabs_client/BUILD.gn
@@ -16,8 +16,8 @@ apk_name = "CustomTabsClientExample" deps = [ ":chrome_tabs_client_example_apk_resources", - ":custom_tabs_support_lib", ":custom_tabs_client_shared_lib", + ":custom_tabs_support_lib", ] chromium_code = false }
diff --git a/third_party/dom_distiller_js/README.chromium b/third_party/dom_distiller_js/README.chromium index d1be45b8..b9b30e01 100644 --- a/third_party/dom_distiller_js/README.chromium +++ b/third_party/dom_distiller_js/README.chromium
@@ -1,6 +1,6 @@ Name: dom-distiller-js URL: https://github.com/chromium/dom-distiller -Version: 21145c3704 +Version: 6e47a6727c License: BSD Security Critical: yes
diff --git a/third_party/fontconfig/BUILD.gn b/third_party/fontconfig/BUILD.gn index 9af485f..d77d84da2 100644 --- a/third_party/fontconfig/BUILD.gn +++ b/third_party/fontconfig/BUILD.gn
@@ -52,8 +52,8 @@ ] deps = [ - "//third_party/zlib", "//third_party/libxml", + "//third_party/zlib", ] configs -= [ "//build/config/compiler:chromium_code" ]
diff --git a/third_party/freetype-android/BUILD.gn b/third_party/freetype-android/BUILD.gn index db8c629..4392162 100644 --- a/third_party/freetype-android/BUILD.gn +++ b/third_party/freetype-android/BUILD.gn
@@ -15,28 +15,28 @@ sources = [ # The following files are not sorted alphabetically, but in the # same order as in Android.mk to ease maintenance. + "src/src/autofit/autofit.c", + "src/src/base/ftbase.c", "src/src/base/ftbbox.c", "src/src/base/ftbitmap.c", "src/src/base/ftfntfmt.c", "src/src/base/ftfstype.c", - "src/src/base/ftglyph.c", - "src/src/base/ftlcdfil.c", - "src/src/base/ftstroke.c", - "src/src/base/fttype1.c", - "src/src/base/ftbase.c", - "src/src/base/ftsystem.c", - "src/src/base/ftinit.c", "src/src/base/ftgasp.c", + "src/src/base/ftglyph.c", + "src/src/base/ftinit.c", + "src/src/base/ftlcdfil.c", "src/src/base/ftmm.c", + "src/src/base/ftstroke.c", + "src/src/base/ftsystem.c", + "src/src/base/fttype1.c", + "src/src/cff/cff.c", "src/src/gzip/ftgzip.c", + "src/src/pshinter/pshinter.c", + "src/src/psnames/psnames.c", "src/src/raster/raster.c", "src/src/sfnt/sfnt.c", "src/src/smooth/smooth.c", - "src/src/autofit/autofit.c", "src/src/truetype/truetype.c", - "src/src/cff/cff.c", - "src/src/psnames/psnames.c", - "src/src/pshinter/pshinter.c", ] defines = [
diff --git a/third_party/libjingle/BUILD.gn b/third_party/libjingle/BUILD.gn index 40fdf658..45f7c51 100644 --- a/third_party/libjingle/BUILD.gn +++ b/third_party/libjingle/BUILD.gn
@@ -109,8 +109,8 @@ ] deps = [ "//base", - "//net", "//crypto:platform", + "//net", ] } @@ -233,8 +233,8 @@ ":jingle_deps", ] deps = [ - "//third_party/webrtc/base:rtc_base", ":libjingle_p2p_constants", + "//third_party/webrtc/base:rtc_base", ] # From libjingle_common.gypi's conditions list. @@ -492,8 +492,8 @@ ] deps = [ - "//third_party/webrtc/base:rtc_base", ":libjingle_webrtc_common", + "//third_party/webrtc/base:rtc_base", ] } } # enable_webrtc
diff --git a/third_party/libjingle/README.chromium b/third_party/libjingle/README.chromium index 0a60e04..781d381f 100644 --- a/third_party/libjingle/README.chromium +++ b/third_party/libjingle/README.chromium
@@ -1,7 +1,7 @@ Name: libjingle URL: http://www.webrtc.org Version: unknown -Revision: 10671 +Revision: 10725 License: BSD License File: source/talk/COPYING Security Critical: yes
diff --git a/third_party/libphonenumber/BUILD.gn b/third_party/libphonenumber/BUILD.gn index edd808a..b72c2ad 100644 --- a/third_party/libphonenumber/BUILD.gn +++ b/third_party/libphonenumber/BUILD.gn
@@ -113,8 +113,8 @@ "//base", "//base/test:run_all_unittests", "//base/third_party/dynamic_annotations", - "//third_party/icu", "//testing/gmock", "//testing/gtest", + "//third_party/icu", ] }
diff --git a/third_party/libvpx_new/BUILD.gn b/third_party/libvpx_new/BUILD.gn index e048871..e73f5100 100644 --- a/third_party/libvpx_new/BUILD.gn +++ b/third_party/libvpx_new/BUILD.gn
@@ -277,13 +277,13 @@ deps = [] if (current_cpu == "x86" || (current_cpu == "x64" && !is_msan)) { deps += [ - ":libvpx_yasm", - ":libvpx_intrinsics_mmx", - ":libvpx_intrinsics_sse2", - ":libvpx_intrinsics_ssse3", - ":libvpx_intrinsics_sse4_1", ":libvpx_intrinsics_avx", ":libvpx_intrinsics_avx2", + ":libvpx_intrinsics_mmx", + ":libvpx_intrinsics_sse2", + ":libvpx_intrinsics_sse4_1", + ":libvpx_intrinsics_ssse3", + ":libvpx_yasm", ] } if (cpu_arch_full == "arm-neon-cpu-detect") {
diff --git a/third_party/mesa/BUILD.gn b/third_party/mesa/BUILD.gn index 5ea0f305..73be8e6 100644 --- a/third_party/mesa/BUILD.gn +++ b/third_party/mesa/BUILD.gn
@@ -717,8 +717,8 @@ } deps = [ - ":mesa_headers", ":mesa", + ":mesa_headers", ":mesa_libglslcommon", "//build/config/sanitizers:deps", ] @@ -736,4 +736,28 @@ group("osmesa") { } } # !is_android + # TODO(GYP) Android osmesa_in_lib_dir target. + +if (is_linux) { + config("wayland_drm_protocol_config") { + include_dirs = [ "$generated_src_dir/egl/wayland/wayland-drm" ] + } + + source_set("wayland_drm_protocol") { + sources = [ + "$generated_src_dir/egl/wayland/wayland-drm/wayland-drm-client-protocol.h", + "$generated_src_dir/egl/wayland/wayland-drm/wayland-drm-protocol.c", + "$generated_src_dir/egl/wayland/wayland-drm/wayland-drm-server-protocol.h", + ] + + deps = [ + "//third_party/wayland:wayland_util", + ] + + configs -= [ "//build/config/compiler:chromium_code" ] + configs += [ "//build/config/compiler:no_chromium_code" ] + + public_configs = [ ":wayland_drm_protocol_config" ] + } +}
diff --git a/third_party/mesa/README.chromium b/third_party/mesa/README.chromium index bad24edf..9407f8a 100644 --- a/third_party/mesa/README.chromium +++ b/third_party/mesa/README.chromium
@@ -24,6 +24,9 @@ - Checked in sources normally autogenerated during Mesa's build process under src/chromium_gensrc. +- Checked in public headers normally autogenerated during Mesa's build + process under include. + - Modified _mesa_add_parameter to not read from uninitialized memory @@ -65,4 +68,4 @@ - Statically link libstdc++ in chromecast build - Merge http://cgit.freedesktop.org/mesa/mesa/commit/?id=5a6ec26 - Regenerated glsl_lexer.cc using Linux 3.13.0-63 (Ubuntu 14.04), Flex 2.5.39. \ No newline at end of file + Regenerated glsl_lexer.cc using Linux 3.13.0-63 (Ubuntu 14.04), Flex 2.5.39.
diff --git a/third_party/mesa/mesa.gyp b/third_party/mesa/mesa.gyp index 6e349468..37350ab 100644 --- a/third_party/mesa/mesa.gyp +++ b/third_party/mesa/mesa.gyp
@@ -762,5 +762,29 @@ }, ], }], + [ 'OS=="linux"', { + 'targets': [ + { + 'target_name': 'wayland_drm_protocol', + 'type': 'static_library', + 'dependencies' : [ + '../wayland/wayland.gyp:wayland_util', + ], + 'include_dirs': [ + '<(generated_src_dir)/egl/wayland/wayland-drm', + ], + 'sources': [ + '<(generated_src_dir)/egl/wayland/wayland-drm/wayland-drm-client-protocol.h', + '<(generated_src_dir)/egl/wayland/wayland-drm/wayland-drm-protocol.c', + '<(generated_src_dir)/egl/wayland/wayland-drm/wayland-drm-server-protocol.h', + ], + 'direct_dependent_settings': { + 'include_dirs': [ + '<(generated_src_dir)/egl/wayland/wayland-drm', + ], + }, + }, + ], + }], ], }
diff --git a/third_party/mockito/BUILD.gn b/third_party/mockito/BUILD.gn index 2f03b7c7..932788a 100644 --- a/third_party/mockito/BUILD.gn +++ b/third_party/mockito/BUILD.gn
@@ -21,8 +21,8 @@ deps = [ ":cglib_and_asm_java", ":objenesis_java", - "../junit:junit", "../junit:hamcrest", + "../junit:junit", ] DEPRECATED_java_in_dir = "src/src" }
diff --git a/third_party/mojo/mojo_edk_tests.gyp b/third_party/mojo/mojo_edk_tests.gyp index e607879..c64e025a 100644 --- a/third_party/mojo/mojo_edk_tests.gyp +++ b/third_party/mojo/mojo_edk_tests.gyp
@@ -56,7 +56,10 @@ '../../mojo/public/cpp/bindings/tests/map_unittest.cc', '../../mojo/public/cpp/bindings/tests/message_queue.cc', '../../mojo/public/cpp/bindings/tests/message_queue.h', + '../../mojo/public/cpp/bindings/tests/multiplex_router_unittest.cc', '../../mojo/public/cpp/bindings/tests/request_response_unittest.cc', + '../../mojo/public/cpp/bindings/tests/router_test_util.cc', + '../../mojo/public/cpp/bindings/tests/router_test_util.h', '../../mojo/public/cpp/bindings/tests/router_unittest.cc', '../../mojo/public/cpp/bindings/tests/sample_service_unittest.cc', '../../mojo/public/cpp/bindings/tests/serialization_warning_unittest.cc',
diff --git a/third_party/mojo/mojo_public.gyp b/third_party/mojo/mojo_public.gyp index 5174838..63c9b0ad 100644 --- a/third_party/mojo/mojo_public.gyp +++ b/third_party/mojo/mojo_public.gyp
@@ -122,6 +122,8 @@ '../../mojo/public/cpp/bindings/lib/fixed_buffer.cc', '../../mojo/public/cpp/bindings/lib/interface_id.h', '../../mojo/public/cpp/bindings/lib/fixed_buffer.h', + '../../mojo/public/cpp/bindings/lib/interface_endpoint_client.cc', + '../../mojo/public/cpp/bindings/lib/interface_endpoint_client.h', '../../mojo/public/cpp/bindings/lib/interface_ptr_internal.h', '../../mojo/public/cpp/bindings/lib/map_data_internal.h', '../../mojo/public/cpp/bindings/lib/map_internal.h', @@ -133,6 +135,8 @@ '../../mojo/public/cpp/bindings/lib/message_header_validator.cc', '../../mojo/public/cpp/bindings/lib/message_header_validator.h', '../../mojo/public/cpp/bindings/lib/message_internal.h', + '../../mojo/public/cpp/bindings/lib/multiplex_router.cc', + '../../mojo/public/cpp/bindings/lib/multiplex_router.h', '../../mojo/public/cpp/bindings/lib/no_interface.cc', '../../mojo/public/cpp/bindings/lib/pipe_control_message_handler.cc', '../../mojo/public/cpp/bindings/lib/pipe_control_message_handler.h', @@ -141,6 +145,8 @@ '../../mojo/public/cpp/bindings/lib/pipe_control_message_proxy.h', '../../mojo/public/cpp/bindings/lib/router.cc', '../../mojo/public/cpp/bindings/lib/router.h', + '../../mojo/public/cpp/bindings/lib/scoped_interface_endpoint_handle.cc', + '../../mojo/public/cpp/bindings/lib/scoped_interface_endpoint_handle.h', '../../mojo/public/cpp/bindings/lib/shared_data.h', '../../mojo/public/cpp/bindings/lib/shared_ptr.h', '../../mojo/public/cpp/bindings/lib/string_serialization.cc',
diff --git a/third_party/mojo/src/mojo/edk/embedder/BUILD.gn b/third_party/mojo/src/mojo/edk/embedder/BUILD.gn index 94d561f..d12b953 100644 --- a/third_party/mojo/src/mojo/edk/embedder/BUILD.gn +++ b/third_party/mojo/src/mojo/edk/embedder/BUILD.gn
@@ -138,8 +138,8 @@ "//base", "//base/test:test_support", "//testing/gtest", - "//third_party/mojo/src/mojo/edk/test:test_support", "//third_party/mojo/src/mojo/edk/system", "//third_party/mojo/src/mojo/edk/system:test_utils", + "//third_party/mojo/src/mojo/edk/test:test_support", ] }
diff --git a/third_party/mojo/src/mojo/edk/js/BUILD.gn b/third_party/mojo/src/mojo/edk/js/BUILD.gn index 057c4e83..303514a 100644 --- a/third_party/mojo/src/mojo/edk/js/BUILD.gn +++ b/third_party/mojo/src/mojo/edk/js/BUILD.gn
@@ -11,8 +11,8 @@ group("tests") { testonly = true deps = [ - "test:js_unittests", "test:js_integration_tests", + "test:js_unittests", ] }
diff --git a/third_party/mojo/src/mojo/edk/system/BUILD.gn b/third_party/mojo/src/mojo/edk/system/BUILD.gn index c782a785..71dcac2 100644 --- a/third_party/mojo/src/mojo/edk/system/BUILD.gn +++ b/third_party/mojo/src/mojo/edk/system/BUILD.gn
@@ -145,8 +145,8 @@ group("tests") { testonly = true deps = [ - ":mojo_system_unittests", ":mojo_message_pipe_perftests", + ":mojo_system_unittests", ] }
diff --git a/third_party/polymer/v1_0/reproduce.sh b/third_party/polymer/v1_0/reproduce.sh index 2590237..063e61e 100755 --- a/third_party/polymer/v1_0/reproduce.sh +++ b/third_party/polymer/v1_0/reproduce.sh
@@ -18,6 +18,8 @@ bower install +rm components/*/.travis.yml + mv components/web-animations-js ../../web-animations-js/sources cp ../../web-animations-js/sources/COPYING ../../web-animations-js/LICENSE @@ -64,3 +66,25 @@ # and apply additional chrome specific patches. NOTE: Where possible create # a Polymer issue and/or pull request to minimize these patches. patch -p1 < chromium.patch + +new=$(git status --porcelain components-chromium | grep '^??' | \ + cut -d' ' -f2 | egrep '\.(html|js|css)$') + +if [[ ! -z "${new}" ]]; then + echo + echo 'These files appear to have been added:' + echo "${new}" | sed 's/^/ /' +fi + +deleted=$(git status --porcelain components-chromium | grep '^.D' | \ + sed 's/^.//' | cut -d' ' -f2 | egrep '\.(html|js|css)$') + +if [[ ! -z "${deleted}" ]]; then + echo + echo 'These files appear to have been removed:' + echo "${deleted}" | sed 's/^/ /' +fi + +if [[ ! -z "${new}${deleted}" ]]; then + echo +fi
diff --git a/third_party/robolectric/BUILD.gn b/third_party/robolectric/BUILD.gn index 211c3d6..790b53d 100644 --- a/third_party/robolectric/BUILD.gn +++ b/third_party/robolectric/BUILD.gn
@@ -25,7 +25,7 @@ jar_path = "lib/robolectric-2.4-jar-with-dependencies.jar" deps = [ ":android-all-4.3_r2-robolectric-0", - ":tagsoup-1.2", ":json-20080701", + ":tagsoup-1.2", ] }
diff --git a/third_party/widevine/cdm/BUILD.gn b/third_party/widevine/cdm/BUILD.gn index 803d0ab..66034cc 100644 --- a/third_party/widevine/cdm/BUILD.gn +++ b/third_party/widevine/cdm/BUILD.gn
@@ -125,9 +125,9 @@ ppapi_cdm_adapter("widevinecdmadapter") { defines = [] deps = [ - ":widevinecdmadapter_resources", - ":widevinecdm", ":version_h", + ":widevinecdm", + ":widevinecdmadapter_resources", "//ppapi/cpp", ]
diff --git a/third_party/yasm/BUILD.gn b/third_party/yasm/BUILD.gn index 36937b8..95903e8e 100644 --- a/third_party/yasm/BUILD.gn +++ b/third_party/yasm/BUILD.gn
@@ -299,10 +299,10 @@ ":compile_gperf_for_include", ":compile_nasm_macros", ":compile_nasm_version", + ":compile_re2c", ":compile_re2c_lc3b", ":compile_win64_gas", ":compile_win64_nasm", - ":compile_re2c", ":generate_license", ":generate_module", ":generate_version",
diff --git a/tools/android/heap_profiler/BUILD.gn b/tools/android/heap_profiler/BUILD.gn index dd8da99e..41366e5 100644 --- a/tools/android/heap_profiler/BUILD.gn +++ b/tools/android/heap_profiler/BUILD.gn
@@ -54,8 +54,8 @@ "heap_profiler_integrationtest.cc", ] deps = [ - "//testing/gtest", ":heap_profiler", + "//testing/gtest", ] configs -= [ "//build/config/compiler:chromium_code" ]
diff --git a/tools/android/kerberos/SpnegoAuthenticator/BUILD.gn b/tools/android/kerberos/SpnegoAuthenticator/BUILD.gn index 03fc64d..3ce7ea4 100644 --- a/tools/android/kerberos/SpnegoAuthenticator/BUILD.gn +++ b/tools/android/kerberos/SpnegoAuthenticator/BUILD.gn
@@ -12,9 +12,9 @@ apk_name = "SpnegoAuthenticator" deps = [ + ":spnego_authenticator_apk_assets", "//base:base_java", "//net/android:net_java", - ":spnego_authenticator_apk_assets", ] java_files = [
diff --git a/tools/battor_agent/BUILD.gn b/tools/battor_agent/BUILD.gn index 381b02e..4432f25d 100644 --- a/tools/battor_agent/BUILD.gn +++ b/tools/battor_agent/BUILD.gn
@@ -18,6 +18,9 @@ sources = [ "battor_agent.cc", "battor_agent.h", + "battor_connection.cc", + "battor_connection.h", + "battor_error.h", ] deps = [ "//base",
diff --git a/tools/battor_agent/battor_agent.cc b/tools/battor_agent/battor_agent.cc index e90934e..835bff6 100644 --- a/tools/battor_agent/battor_agent.cc +++ b/tools/battor_agent/battor_agent.cc
@@ -4,55 +4,12 @@ #include "tools/battor_agent/battor_agent.h" -#include <iostream> - -#include "base/bind.h" -#include "base/callback.h" -#include "base/location.h" -#include "base/message_loop/message_loop.h" -#include "base/run_loop.h" -#include "base/time/time.h" -#include "device/serial/serial.mojom.h" - -namespace { - -// Callback for when the connection is opened. If an error occurs, error will be -// set to BATTOR_ERROR_CONNECTION_FAILED. -void OnConnectionOpened(battor::BattOrAgent::BattOrError* error, - const base::Closure& callback, - bool success) { - *error = success ? battor::BattOrAgent::BATTOR_ERROR_NONE - : battor::BattOrAgent::BATTOR_ERROR_CONNECTION_FAILED; - callback.Run(); -} - -// Callback for when a command times out. If a timeout occurs, error will be set -// to BATTOR_ERROR_TIMEOUT. -void OnTimeout(battor::BattOrAgent::BattOrError* error, - const base::Closure& callback) { - *error = battor::BattOrAgent::BATTOR_ERROR_TIMEOUT; - callback.Run(); -} - -// Serial configuration parameters for the BattOr. -const base::TimeDelta kSerialCommandTimeout = base::TimeDelta::FromSeconds(10); -const uint32 kBattOrBitrate = 2000000; -const device::serial::DataBits kBattOrDataBits = - device::serial::DATA_BITS_EIGHT; -const device::serial::ParityBit kBattOrParityBit = - device::serial::PARITY_BIT_NONE; -const device::serial::StopBits kBattOrStopBit = device::serial::STOP_BITS_ONE; -const bool kBattOrCtsFlowControl = true; -const bool kBattOrHasCtsFlowControl = true; - -} // namespace - namespace battor { BattOrAgent::BattOrAgent(const std::string& path) : path_(path) {} BattOrAgent::~BattOrAgent() {} -BattOrAgent::BattOrError BattOrAgent::StartTracing() { +BattOrError BattOrAgent::StartTracing() { BattOrError error = ConnectIfNeeded(); if (error != BATTOR_ERROR_NONE) return error; @@ -61,7 +18,7 @@ return BATTOR_ERROR_NONE; } -BattOrAgent::BattOrError BattOrAgent::StopTracing(std::string* trace_output) { +BattOrError BattOrAgent::StopTracing(std::string* trace_output) { BattOrError error = ConnectIfNeeded(); if (error != BATTOR_ERROR_NONE) return error; @@ -73,8 +30,7 @@ return BATTOR_ERROR_NONE; } -BattOrAgent::BattOrError BattOrAgent::RecordClockSyncMarker( - const std::string& marker) { +BattOrError BattOrAgent::RecordClockSyncMarker(const std::string& marker) { BattOrError error = ConnectIfNeeded(); if (error != BATTOR_ERROR_NONE) return error; @@ -83,7 +39,7 @@ return BATTOR_ERROR_NONE; } -BattOrAgent::BattOrError BattOrAgent::IssueClockSyncMarker() { +BattOrError BattOrAgent::IssueClockSyncMarker() { BattOrError error = ConnectIfNeeded(); if (error != BATTOR_ERROR_NONE) return error; @@ -93,43 +49,16 @@ } void BattOrAgent::ResetConnection() { - io_handler_ = nullptr; + connection_ = nullptr; } -BattOrAgent::BattOrError BattOrAgent::ConnectIfNeeded() { - if (io_handler_) +BattOrError BattOrAgent::ConnectIfNeeded() { + if (connection_) return BATTOR_ERROR_NONE; - io_handler_ = device::SerialIoHandler::Create( - base::MessageLoop::current()->task_runner(), - base::MessageLoop::current()->task_runner()); + connection_ = BattOrConnection::Create(path_); - device::serial::ConnectionOptions options; - options.bitrate = kBattOrBitrate; - options.data_bits = kBattOrDataBits; - options.parity_bit = kBattOrParityBit; - options.stop_bits = kBattOrStopBit; - options.cts_flow_control = kBattOrCtsFlowControl; - options.has_cts_flow_control = kBattOrHasCtsFlowControl; - - BattOrError error; - base::RunLoop run_loop; - base::MessageLoop::current()->task_runner()->PostDelayedTask( - FROM_HERE, base::Bind(&OnTimeout, &error, run_loop.QuitClosure()), - kSerialCommandTimeout); - io_handler_->Open(path_, options, base::Bind(&OnConnectionOpened, &error, - run_loop.QuitClosure())); - run_loop.Run(); - - if (error != BATTOR_ERROR_NONE) { - error = BATTOR_ERROR_CONNECTION_FAILED; - ResetConnection(); - } - - // TODO(charliea): Complete the inialization routine by sending the init - // message, setting the gain, reading the EEPROM, and setting the sample rate. - - return error; + return connection_ ? BATTOR_ERROR_NONE : BATTOR_ERROR_CONNECTION_FAILED; } } // namespace battor
diff --git a/tools/battor_agent/battor_agent.gyp b/tools/battor_agent/battor_agent.gyp index cae7218c6..0df051c 100644 --- a/tools/battor_agent/battor_agent.gyp +++ b/tools/battor_agent/battor_agent.gyp
@@ -29,6 +29,9 @@ 'sources': [ 'battor_agent.cc', 'battor_agent.h', + 'battor_connection.cc', + 'battor_connection.h', + 'battor_error.h', ], 'dependencies': [ '../../base/base.gyp:base',
diff --git a/tools/battor_agent/battor_agent.h b/tools/battor_agent/battor_agent.h index b93f2cd..62b1ad8 100644 --- a/tools/battor_agent/battor_agent.h +++ b/tools/battor_agent/battor_agent.h
@@ -2,12 +2,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#ifndef TOOLS_BATTOR_AGENT_BATTOR_AGENT_H_ +#define TOOLS_BATTOR_AGENT_BATTOR_AGENT_H_ + #include <string> -#include "base/callback_forward.h" #include "base/macros.h" -#include "base/memory/ref_counted.h" -#include "device/serial/serial_io_handler.h" +#include "tools/battor_agent/battor_connection.h" +#include "tools/battor_agent/battor_error.h" namespace battor { @@ -30,12 +32,6 @@ // This class is NOT thread safe. class BattOrAgent { public: - enum BattOrError { - BATTOR_ERROR_NONE, - BATTOR_ERROR_CONNECTION_FAILED, - BATTOR_ERROR_TIMEOUT, - }; - explicit BattOrAgent(const std::string& path); virtual ~BattOrAgent(); @@ -68,10 +64,12 @@ // The path of the BattOr (e.g. "/dev/tty.battor_serial"). std::string path_; - // IO handler capable of reading from and writing to the serial connection. - scoped_refptr<device::SerialIoHandler> io_handler_; + // Serial connection the BattOr. + scoped_ptr<BattOrConnection> connection_; DISALLOW_COPY_AND_ASSIGN(BattOrAgent); }; } // namespace battor + +#endif // TOOLS_BATTOR_AGENT_BATTOR_AGENT_H_
diff --git a/tools/battor_agent/battor_agent_bin.cc b/tools/battor_agent/battor_agent_bin.cc index 8532c49..c1c9bd3d 100644 --- a/tools/battor_agent/battor_agent_bin.cc +++ b/tools/battor_agent/battor_agent_bin.cc
@@ -13,6 +13,7 @@ #include "base/threading/thread.h" #include "device/serial/serial.mojom.h" #include "tools/battor_agent/battor_agent.h" +#include "tools/battor_agent/battor_error.h" using std::cerr; using std::cout; @@ -50,8 +51,8 @@ // Checks if an error occurred and, if it did, prints the error and exits // with an error code. -void CheckError(battor::BattOrAgent::BattOrError error) { - if (error != battor::BattOrAgent::BATTOR_ERROR_NONE) { +void CheckError(battor::BattOrError error) { + if (error != battor::BATTOR_ERROR_NONE) { cerr << "Error when communicating with the BattOr: " << error << endl; exit(1); }
diff --git a/tools/battor_agent/battor_connection.cc b/tools/battor_agent/battor_connection.cc new file mode 100644 index 0000000..4d9a352 --- /dev/null +++ b/tools/battor_agent/battor_connection.cc
@@ -0,0 +1,79 @@ +// Copyright 2015 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 "tools/battor_agent/battor_connection.h" + +#include "base/bind.h" +#include "base/callback.h" +#include "base/location.h" +#include "base/message_loop/message_loop.h" +#include "base/run_loop.h" +#include "base/time/time.h" +#include "device/serial/serial.mojom.h" + +namespace { + +// Serial configuration parameters for the BattOr. +const base::TimeDelta kSerialCommandTimeout = base::TimeDelta::FromSeconds(10); +const uint32 kBattOrBitrate = 2000000; +const device::serial::DataBits kBattOrDataBits = + device::serial::DATA_BITS_EIGHT; +const device::serial::ParityBit kBattOrParityBit = + device::serial::PARITY_BIT_NONE; +const device::serial::StopBits kBattOrStopBit = device::serial::STOP_BITS_ONE; +const bool kBattOrCtsFlowControl = true; +const bool kBattOrHasCtsFlowControl = true; + +// Callback for when the connection is opened. If an error occurs, error will be +// set to BATTOR_ERROR_CONNECTION_FAILED. +void OnConnectionOpened(bool* success_return, + const base::Closure& callback, + bool success) { + *success_return = success; + callback.Run(); +} + +// Callback for when a command times out. If a timeout occurs, error will be set +// to BATTOR_ERROR_TIMEOUT. +void OnTimeout(bool* success, const base::Closure& callback) { + *success = false; + callback.Run(); +} + +} // namespace + +namespace battor { + +BattOrConnection::BattOrConnection() {} +BattOrConnection::~BattOrConnection() {} + +scoped_ptr<BattOrConnection> BattOrConnection::Create(const std::string& path) { + scoped_ptr<BattOrConnection> conn(new BattOrConnection()); + + conn->io_handler_ = device::SerialIoHandler::Create( + base::MessageLoop::current()->task_runner(), + base::MessageLoop::current()->task_runner()); + + device::serial::ConnectionOptions options; + options.bitrate = kBattOrBitrate; + options.data_bits = kBattOrDataBits; + options.parity_bit = kBattOrParityBit; + options.stop_bits = kBattOrStopBit; + options.cts_flow_control = kBattOrCtsFlowControl; + options.has_cts_flow_control = kBattOrHasCtsFlowControl; + + bool success; + base::RunLoop run_loop; + base::MessageLoop::current()->task_runner()->PostDelayedTask( + FROM_HERE, base::Bind(&OnTimeout, &success, run_loop.QuitClosure()), + kSerialCommandTimeout); + conn->io_handler_->Open( + path, options, + base::Bind(&OnConnectionOpened, &success, run_loop.QuitClosure())); + run_loop.Run(); + + return success ? conn.Pass() : nullptr; +} + +} // namespace battor
diff --git a/tools/battor_agent/battor_connection.h b/tools/battor_agent/battor_connection.h new file mode 100644 index 0000000..134df3a --- /dev/null +++ b/tools/battor_agent/battor_connection.h
@@ -0,0 +1,38 @@ +// Copyright 2015 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 TOOLS_BATTOR_AGENT_BATTOR_CONNECTION_H_ +#define TOOLS_BATTOR_AGENT_BATTOR_CONNECTION_H_ + +#include "base/macros.h" +#include "base/memory/ref_counted.h" +#include "device/serial/serial_io_handler.h" + +namespace battor { + +// A BattOrConnection is a serial connection to the BattOr. It's essentially +// just a thin wrapper around device::serial::SerialIoHandler that provides +// reasonable defaults for the serial connection for the BattOr and provides a +// synchronous interface. +// +// The serial connection remains open for the lifetime of the object. +class BattOrConnection { + public: + // Creates a BattOrConnection to the BattOr at the given path. + // If creation is unsuccessful, a null pointer is returned. + static scoped_ptr<BattOrConnection> Create(const std::string& path); + virtual ~BattOrConnection(); + + private: + BattOrConnection(); + + // IO handler capable of reading from and writing to the serial connection. + scoped_refptr<device::SerialIoHandler> io_handler_; + + DISALLOW_COPY_AND_ASSIGN(BattOrConnection); +}; + +} // namespace battor + +#endif // TOOLS_BATTOR_AGENT_BATTOR_CONNECTION_H_
diff --git a/tools/battor_agent/battor_error.h b/tools/battor_agent/battor_error.h new file mode 100644 index 0000000..bc66e16a --- /dev/null +++ b/tools/battor_agent/battor_error.h
@@ -0,0 +1,19 @@ +// Copyright 2015 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 TOOLS_BATTOR_AGENT_BATTOR_ERROR_H_ +#define TOOLS_BATTOR_AGENT_BATTOR_ERROR_H_ + +namespace battor { + +// A BattOrError is an error that occurs when communicating with a BattOr. +enum BattOrError { + BATTOR_ERROR_NONE, + BATTOR_ERROR_CONNECTION_FAILED, + BATTOR_ERROR_TIMEOUT, +}; + +} + +#endif // TOOLS_BATTOR_AGENT_BATTOR_ERROR_H_
diff --git a/tools/gen_keyboard_overlay_data/gen_keyboard_overlay_data.py b/tools/gen_keyboard_overlay_data/gen_keyboard_overlay_data.py index 67b5beb..073ef0b 100755 --- a/tools/gen_keyboard_overlay_data/gen_keyboard_overlay_data.py +++ b/tools/gen_keyboard_overlay_data/gen_keyboard_overlay_data.py
@@ -135,7 +135,9 @@ 'xkb:us:dvorak:eng': 'en_US_dvorak', 'xkb:us:intl:eng': 'en_US_intl', 'xkb:us:intl:nld': 'en_US_intl', - 'xkb:us:intl:por': 'en_US_intl' + 'xkb:us:intl:por': 'en_US_intl', + 'xkb:us:workman:eng': 'en_US_workman', + 'xkb:us:workman-intl:eng': 'en_US_workman_intl', } # The file was first generated in 2012 and we have a policy of not updating
diff --git a/tools/gn/function_get_label_info.cc b/tools/gn/function_get_label_info.cc index dd5e5867..be22cca2 100644 --- a/tools/gn/function_get_label_info.cc +++ b/tools/gn/function_get_label_info.cc
@@ -63,7 +63,7 @@ "\n" " \"root_out_dir\"\n" " The root of the output file tree for the target. This will\n" - " match the value of the \"root_gen_dir\" variable when inside that\n" + " match the value of the \"root_out_dir\" variable when inside that\n" " target's declaration.\n" "\n" " \"label_no_toolchain\"\n"
diff --git a/tools/gn/scheduler.cc b/tools/gn/scheduler.cc index 622019e..dfc877d 100644 --- a/tools/gn/scheduler.cc +++ b/tools/gn/scheduler.cc
@@ -4,25 +4,59 @@ #include "tools/gn/scheduler.h" +#include <algorithm> + #include "base/bind.h" #include "base/command_line.h" #include "base/strings/string_number_conversions.h" +#include "build/build_config.h" #include "tools/gn/standard_out.h" #include "tools/gn/switches.h" +#if defined(OS_WIN) +#include <windows.h> +#else +#include <unistd.h> +#endif + Scheduler* g_scheduler = nullptr; namespace { +#if defined(OS_WIN) +int GetCPUCount() { + SYSTEM_INFO sysinfo; + ::GetSystemInfo(&sysinfo); + return sysinfo.dwNumberOfProcessors; +} +#else +int GetCPUCount() { + return static_cast<int>(sysconf(_SC_NPROCESSORS_ONLN)); +} +#endif + int GetThreadCount() { std::string thread_count = base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII( switches::kThreads); + // See if an override was specified on the command line. int result; - if (thread_count.empty() || !base::StringToInt(thread_count, &result)) - return 32; - return result; + if (!thread_count.empty() && base::StringToInt(thread_count, &result)) + return result; + + // Base the default number of worker threads on number of cores in the + // system. When building large projects, the speed can be limited by how fast + // the main thread can dispatch work and connect the dependency graph. If + // there are too many worker threads, the main thread can be starved and it + // will run slower overall. + // + // One less worker thread than the number of physical CPUs seems to be a + // good value, both theoretically and experimentally. But always use at + // least three workers to prevent us from being too sensitive to I/O latency + // on low-end systems. + int num_cores = GetCPUCount() / 2; // Almost all CPUs now are hyperthreaded. + return std::max(num_cores - 1, 3); } } // namespace
diff --git a/tools/gn/setup.cc b/tools/gn/setup.cc index 033dab4f..87339ca4 100644 --- a/tools/gn/setup.cc +++ b/tools/gn/setup.cc
@@ -148,6 +148,42 @@ g_scheduler->DecrementWorkCount(); } +#if defined(OS_WIN) +const base::char16 kPythonExeName[] = L"python.exe"; + +base::FilePath FindWindowsPython() { + base::char16 current_directory[MAX_PATH]; + ::GetCurrentDirectory(MAX_PATH, current_directory); + + // First search for python.exe in the current directory. + base::FilePath cur_dir_candidate_exe = + base::FilePath(current_directory).Append(kPythonExeName); + if (base::PathExists(cur_dir_candidate_exe)) + return cur_dir_candidate_exe; + + // Get the path. + const base::char16 kPathEnvVarName[] = L"Path"; + DWORD path_length = ::GetEnvironmentVariable(kPathEnvVarName, nullptr, 0); + if (path_length == 0) + return base::FilePath(); + scoped_ptr<base::char16[]> full_path(new base::char16[path_length]); + DWORD actual_path_length = + ::GetEnvironmentVariable(kPathEnvVarName, full_path.get(), path_length); + CHECK_EQ(path_length, actual_path_length + 1); + + // Search for python.exe in the path. + for (const auto& component : base::SplitStringPiece( + base::StringPiece16(full_path.get(), path_length), L";", + base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY)) { + base::FilePath candidate_exe = + base::FilePath(component).Append(kPythonExeName); + if (base::PathExists(candidate_exe)) + return candidate_exe; + } + return base::FilePath(); +} +#endif + } // namespace const char Setup::kBuildArgFileName[] = "args.gn"; @@ -478,21 +514,13 @@ // Trace this since it tends to be a bit slow on Windows. ScopedTrace setup_trace(TraceItem::TRACE_SETUP, "Fill Python Path"); #if defined(OS_WIN) - // Find Python on the path so we can use the absolute path in the build. - const base::char16 kGetPython[] = - L"cmd.exe /c python -c \"import sys; print sys.executable\""; - std::string python_path; - if (base::GetAppOutput(kGetPython, &python_path)) { - base::TrimWhitespaceASCII(python_path, base::TRIM_ALL, &python_path); - if (scheduler_.verbose_logging()) - scheduler_.Log("Found python", python_path); - } else { + base::FilePath python_path = FindWindowsPython(); + if (python_path.empty()) { scheduler_.Log("WARNING", "Could not find python on path, using " "just \"python.exe\""); - python_path = "python.exe"; + python_path = base::FilePath(kPythonExeName); } - build_settings_.set_python_path(base::FilePath(base::UTF8ToUTF16(python_path)) - .NormalizePathSeparatorsTo('/')); + build_settings_.set_python_path(python_path.NormalizePathSeparatorsTo('/')); #else build_settings_.set_python_path(base::FilePath("python")); #endif
diff --git a/tools/gn/target.cc b/tools/gn/target.cc index 3655982..4a93abc2 100644 --- a/tools/gn/target.cc +++ b/tools/gn/target.cc
@@ -12,6 +12,7 @@ #include "tools/gn/filesystem_utils.h" #include "tools/gn/scheduler.h" #include "tools/gn/substitution_writer.h" +#include "tools/gn/trace.h" namespace { @@ -156,6 +157,9 @@ DCHECK(output_type_ != UNKNOWN); DCHECK(toolchain_) << "Toolchain should have been set before resolving."; + ScopedTrace trace(TraceItem::TRACE_ON_RESOLVED, label()); + trace.SetToolchain(settings()->toolchain_label()); + // Copy our own dependent configs to the list of configs applying to us. configs_.Append(all_dependent_configs_.begin(), all_dependent_configs_.end()); MergePublicConfigsFrom(this, &configs_);
diff --git a/tools/gn/trace.cc b/tools/gn/trace.cc index c8107931..4746310 100644 --- a/tools/gn/trace.cc +++ b/tools/gn/trace.cc
@@ -202,6 +202,7 @@ case TraceItem::TRACE_FILE_LOAD: case TraceItem::TRACE_FILE_WRITE: case TraceItem::TRACE_DEFINE_TARGET: + case TraceItem::TRACE_ON_RESOLVED: break; // Ignore these for the summary. } } @@ -281,6 +282,9 @@ case TraceItem::TRACE_DEFINE_TARGET: out << "\"define\""; break; + case TraceItem::TRACE_ON_RESOLVED: + out << "\"onresolved\""; + break; case TraceItem::TRACE_CHECK_HEADER: out << "\"hdr\""; break;
diff --git a/tools/gn/trace.h b/tools/gn/trace.h index 384907b..e32f319e 100644 --- a/tools/gn/trace.h +++ b/tools/gn/trace.h
@@ -25,6 +25,7 @@ TRACE_FILE_WRITE, TRACE_SCRIPT_EXECUTE, TRACE_DEFINE_TARGET, + TRACE_ON_RESOLVED, TRACE_CHECK_HEADER, // One file. TRACE_CHECK_HEADERS, // All files. };
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index 4b4fd28..cb2bee4 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml
@@ -3478,7 +3478,8 @@ </histogram> <histogram name="Canvas.ContextType" enum="CanvasContextType"> - <owner>Please list the metric's owners. Add more owner tags as needed.</owner> + <owner>junov@chromium.org</owner> + <owner>kbr@chromium.org</owner> <summary> Records the context type names used to create canvas rendering contexts. </summary> @@ -5229,6 +5230,28 @@ <summary>Intervals between access time updates for each cookie.</summary> </histogram> +<histogram name="Cookie.CookiePrefix" enum="CookiePrefix"> + <owner>estark@chromium.org</owner> + <summary> + Number of times a cookie was set with a name prefixed by + "$Secure-" or "$Host-" (prefixes reserved by + https://tools.ietf.org/html/draft-west-cookie-prefixes). + </summary> +</histogram> + +<histogram name="Cookie.CookiePrefixBlocked" enum="CookiePrefix"> + <owner>estark@chromium.org</owner> + <summary> + Number of times a cookie was set with a name prefixed by + "$Secure-" or "$Host-" that violate cookie prefix rules. + That is, a $Secure- cookie must be set over a secure connection with the + Secure attribute, and a $Host- cookie must be set over a secure connection, + with the Secure attribute, with no Domain attribute, and with a Path + attribute of "/". (As defined in + https://tools.ietf.org/html/draft-west-cookie-prefixes.) + </summary> +</histogram> + <histogram name="Cookie.CookieSourceScheme" enum="CookieSourceScheme"> <owner>estark@chromium.org</owner> <summary> @@ -5739,6 +5762,14 @@ </summary> </histogram> +<histogram name="Cryptohome.ChecksumStatus" enum="CryptohomeChecksumStatus"> + <owner>dkrahn@chromium.org</owner> + <summary> + Checksum status of critical persistent data used by Cryptohome. This status + is recorded every time the cryptohomed daemon reads a file. + </summary> +</histogram> + <histogram name="Cryptohome.Errors" enum="CryptohomeError"> <owner>dkrahn@chromium.org</owner> <summary>Cryptohome errors.</summary> @@ -8738,6 +8769,15 @@ </summary> </histogram> +<histogram name="Download.IOSDownloadPassKitResult" + enum="DownloadPassKitResult"> + <owner>gchatz@chromium.org</owner> + <summary> + Result when a user attempts to download a PassKit file on iOS with + WKWebView. + </summary> +</histogram> + <histogram name="Download.MaliciousDownloadClassified" enum="DownloadItem.DangerType"> <owner>asanka@chromium.org</owner> @@ -30011,6 +30051,14 @@ </summary> </histogram> +<histogram name="OAuth2Login.SeedState" enum="OAuth2LoginSeedState"> + <owner>knn@chromium.org</owner> + <summary> + Only applicable on M47 on Android. Measure the frequency of a suppressed + error state when the account is not seeded. + </summary> +</histogram> + <histogram name="OAuth2Login.SessionRestore" enum="GaiaSessionRestoreOutcome"> <owner>zelidrag@chromium.org</owner> <summary>Outcome of Chrome OS GAIA cookie session restore process.</summary> @@ -51448,6 +51496,14 @@ </summary> </histogram> +<histogram name="WebCore.CanvasContextUsage" enum="CanvasContextUsage"> + <owner>zmin@chromium.org</owner> + <owner>junov@chromium.org</owner> + <summary> + The usage of Canvas 2D Context API. Logged when the particular API is used. + </summary> +</histogram> + <histogram name="WebCore.DistillabilityUs" units="microseconds"> <owner>wychen@chromium.org</owner> <summary> @@ -52760,6 +52816,42 @@ </summary> </histogram> +<histogram name="WebRTC.Call.AudioBitrateReceivedInKbps" units="kbits/s"> + <owner>holmer@chromium.org</owner> + <summary> + Average audio bitrate received during a call, counted from first packet + received until Call instance is destroyed. Only mesured for calls that are + at least 10 seconds long. + </summary> +</histogram> + +<histogram name="WebRTC.Call.BitrateReceivedInKbps" units="kbits/s"> + <owner>holmer@chromium.org</owner> + <summary> + Average total bitrate received during a call (audio + video + RTCP), counted + from first packet received until Call instance is destroyed. Only mesured + for calls that are at least 10 seconds long. + </summary> +</histogram> + +<histogram name="WebRTC.Call.RtcpBitrateReceivedInBps" units="bits/s"> + <owner>holmer@chromium.org</owner> + <summary> + Average RTCP bitrate received during a call, counted from first packet + received until Call instance is destroyed. Only mesured for calls that are + at least 10 seconds long. + </summary> +</histogram> + +<histogram name="WebRTC.Call.VideoBitrateReceivedInKbps" units="kbits/s"> + <owner>holmer@chromium.org</owner> + <summary> + Average video bitrate received during a call, counted from first packet + received until Call instance is destroyed. Only mesured for calls that are + at least 10 seconds long. + </summary> +</histogram> + <histogram name="WebRTC.DataChannelCounters" enum="DataChannelCounters"> <owner>perkj@chromium.org</owner> <summary> @@ -53459,6 +53551,126 @@ </summary> </histogram> +<histogram name="WebRTC.Video.Screenshare.BandwidthLimitedResolutionInPercent" + units="%"> + <owner>sprang@chromium.org</owner> + <summary> + Percentage of sent frames that are limited in resolution due to bandwidth + for a sent (screen content) video stream. Recorded when a stream is removed. + </summary> +</histogram> + +<histogram name="WebRTC.Video.Screenshare.BandwidthLimitedResolutionsDisabled" + units="disabled resolutions"> + <owner>sprang@chromium.org</owner> + <summary> + For frames that are limited in resolution due to bandwidth, the average + number of disabled resolutions is recorded for a sent (screen content) video + stream. Recorded when a stream is removed. + </summary> +</histogram> + +<histogram name="WebRTC.Video.Screenshare.EncodeTimeInMs" units="ms"> + <owner>sprang@chromium.org</owner> + <summary> + The average encode time per frame for a sent (screen content) video stream. + Recorded when a stream is removed. + </summary> +</histogram> + +<histogram name="WebRTC.Video.Screenshare.InputHeightInPixels" units="pixels"> + <owner>sprang@chromium.org</owner> + <summary> + The average input height per frame (for incoming frames to video engine) for + a sent (screen content) video stream. Recorded when a stream is removed. + </summary> +</histogram> + +<histogram name="WebRTC.Video.Screenshare.InputWidthInPixels" units="pixels"> + <owner>sprang@chromium.org</owner> + <summary> + The average input width per frame (for incoming frames to video engine) for + a sent (screen content) video stream. Recorded when a stream is removed. + </summary> +</histogram> + +<histogram name="WebRTC.Video.Screenshare.KeyFramesSentInPermille" + units="permille"> + <owner>sprang@chromium.org</owner> + <summary> + Permille of frames that are key frames for a sent (screen content) video + stream. Recorded when a stream is removed. + </summary> +</histogram> + +<histogram name="WebRTC.Video.Screenshare.QualityLimitedResolutionDownscales" + units="downscales"> + <owner>sprang@chromium.org</owner> + <summary> + For frames that are downscaled in resolution due to quality, the average + number of downscales is recorded for a sent (screen content) video stream. + Recorded when a stream is removed. + </summary> +</histogram> + +<histogram name="WebRTC.Video.Screenshare.QualityLimitedResolutionInPercent" + units="%"> + <owner>sprang@chromium.org</owner> + <summary> + Percentage of sent frames that are downscaled in resolution due to quality + for a sent (screen content) video stream. Recorded when a stream is removed. + </summary> +</histogram> + +<histogram name="WebRTC.Video.Screenshare.SendSideDelayInMs" units="ms"> + <owner>sprang@chromium.org</owner> + <summary> + The average delay (of average delays) of sent packets for a sent (screen + content) video stream. Recorded when a stream is removed. The delay is + measured from a frame is input to video engine until a packet is sent to the + network. For each sent packet, the average delay of all sent packets over + the last second is reported. The average of these reported delays is + recorded. + </summary> +</histogram> + +<histogram name="WebRTC.Video.Screenshare.SendSideDelayMaxInMs" units="ms"> + <owner>sprang@chromium.org</owner> + <summary> + The average delay (of max delays) of sent packets for a sent (screen + content) video stream. Recorded when a stream is removed. The delay is + measured from a frame is input to video engine until a packet is sent to the + network. For each sent packet, the maximum delay of all sent packets over + the last second is reported. The average of these reported delays is + recorded. + </summary> +</histogram> + +<histogram name="WebRTC.Video.Screenshare.SentFramesPerSecond" units="fps"> + <owner>sprang@chromium.org</owner> + <summary> + The number of sent frames per second for a sent (screen content) video + stream. Recorded when a stream is removed. The total number of frames is + divided by the time the video stream exists. + </summary> +</histogram> + +<histogram name="WebRTC.Video.Screenshare.SentHeightInPixels" units="pixels"> + <owner>sprang@chromium.org</owner> + <summary> + The average sent height per frame for a sent (screen content) video stream. + Recorded when a stream is removed. + </summary> +</histogram> + +<histogram name="WebRTC.Video.Screenshare.SentWidthInPixels" units="pixels"> + <owner>sprang@chromium.org</owner> + <summary> + The average sent width per frame for a sent (screen content) video stream. + Recorded when a stream is removed. + </summary> +</histogram> + <histogram name="WebRTC.Video.SendSideDelayInMs" units="ms"> <owner>asapersson@chromium.org</owner> <summary> @@ -54435,6 +54647,7 @@ <int value="11" label="kCodecPCM_S24BE"/> <int value="12" label="kCodecOpus"/> <int value="14" label="kCodecPCM_ALAW"/> + <int value="15" label="kCodecALAC"/> </enum> <enum name="AudioFramesPerBuffer" type="int"> @@ -55617,9 +55830,21 @@ <enum name="CanvasContextType" type="int"> <int value="0" label="2d"/> - <int value="1" label="webkit-3d"/> + <int value="1" label="(obsolete) webkit-3d"/> <int value="2" label="experimental-webgl"/> <int value="3" label="webgl"/> + <int value="4" label="webgl2"/> +</enum> + +<enum name="CanvasContextUsage" type="int"> + <int value="0" label="CanvasCreated"/> + <int value="1" label="GPUAccelerated2DCanvasImageBufferCreated"/> + <int value="2" label="DisplayList2DCanvasImageBufferCreated"/> + <int value="3" label="Unaccelerated2DCanvasImageBufferCreated"/> + <int value="4" label="Accelerated2DCanvasGPUContextLost"/> + <int value="5" label="Unaccelerated2DCanvasImageBufferCreationFailed"/> + <int value="6" label="GPUAccelerated2DCanvasImageBufferCreationFailed"/> + <int value="7" label="DisplayList2DCanvasFallbackToRaster"/> </enum> <enum name="CAPSUpdaterStep" type="int"> @@ -56578,6 +56803,12 @@ <int value="3" label="Both"/> </enum> +<enum name="CookiePrefix" type="int"> + <int value="0" label="No special prefix"/> + <int value="1" label="Secure prefix"/> + <int value="2" label="Host prefix"/> +</enum> + <enum name="CookieSourceScheme" type="int"> <int value="0" label="Secure cookie, source scheme is cryptographic"/> <int value="1" label="Secure cookie, source scheme is not cryptographic"/> @@ -56771,6 +57002,13 @@ <int value="5" label="Failed to query dictionary attack counter"/> </enum> +<enum name="CryptohomeChecksumStatus" type="int"> + <int value="0" label="Checksum OK"/> + <int value="1" label="Checksum does not exist"/> + <int value="2" label="Checksum read error"/> + <int value="3" label="Checksum mismatch"/> +</enum> + <enum name="CryptohomeError" type="int"> <int value="1" label="TPM returned TPM_E_FAIL"/> <int value="2" label="TCS key load failed"/> @@ -57878,6 +58116,13 @@ <int value="7" label="New redirects + validators + Content-Disposition"/> </enum> +<enum name="DownloadPassKitResult" type="int"> + <int value="0" label="Successful"/> + <int value="1" label="Other Failure"/> + <int value="2" label="Unauthorized Failure"/> + <int value="3" label="Wrong MIME Type Failure"/> +</enum> + <enum name="DownloadSavePackageEvent" type="int"> <int value="0" label="Started"/> <int value="1" label="Cancelled"/> @@ -68069,6 +68314,7 @@ <int value="7" label="EAC3"/> <int value="8" label="MP3"/> <int value="9" label="OPUS"/> + <int value="10" label="HEVC"/> </enum> <enum name="MultiProfileSessionMode" type="int"> @@ -69111,6 +69357,14 @@ <int value="3" label="Too few URLs, didn't flip tiles 1 and 4"/> </enum> +<enum name="OAuth2LoginSeedState" type="int"> + <int value="0" label="Account was seeded before FireRefreshTokenRevoked"/> + <int value="1" label="Account was seeded before FireRefreshTokenAvailable"/> + <int value="2" label="Account was not seeded before FireRefreshTokenRevoked"/> + <int value="3" + label="Account was not seeded before FireRefreshTokenAvailable"/> +</enum> + <enum name="OfflinePagesClearAllStatus" type="int"> <int value="0" label="Success"/> <int value="1" label="Store reset failed"/>
diff --git a/tools/perf/benchmarks/blink_perf.py b/tools/perf/benchmarks/blink_perf.py index 2bb4639..03384a1 100644 --- a/tools/perf/benchmarks/blink_perf.py +++ b/tools/perf/benchmarks/blink_perf.py
@@ -232,8 +232,7 @@ return CreateStorySetFromPath(path, SKIPPED_FILE) -@benchmark.Disabled('win8', # http://crbug.com/462350 - 'android') #http://crbug.com/551950 +@benchmark.Disabled('win8') # http://crbug.com/462350 class BlinkPerfLayout(perf_benchmark.PerfBenchmark): tag = 'layout' test = _BlinkPerfMeasurement @@ -246,6 +245,10 @@ path = os.path.join(BLINK_PERF_BASE_DIR, 'Layout') return CreateStorySetFromPath(path, SKIPPED_FILE) + @classmethod + def ShouldDisable(cls, possible_browser): + return cls.IsSvelte(possible_browser) # http://crbug.com/551950 + @benchmark.Enabled('content-shell') class BlinkPerfLayoutFullLayout(BlinkPerfLayout): @@ -325,8 +328,7 @@ # Disabled on Windows and ChromeOS due to https://crbug.com/521887 # Disabled on reference builds due to https://crbug.com/530374 -# Disabled on Android due to http://crbug.com/551950 -@benchmark.Disabled('win', 'chromeos', 'reference', 'android') +@benchmark.Disabled('win', 'chromeos', 'reference') class BlinkPerfPywebsocket(perf_benchmark.PerfBenchmark): tag = 'pywebsocket' test = _BlinkPerfPywebsocketMeasurement @@ -339,3 +341,7 @@ path = os.path.join(BLINK_PERF_BASE_DIR, 'Pywebsocket') return CreateStorySetFromPath(path, SKIPPED_FILE, shared_page_state_class=_SharedPywebsocketPageState) + + @classmethod + def ShouldDisable(cls, possible_browser): + return cls.IsSvelte(possible_browser) # http://crbug.com/551950
diff --git a/tools/perf/benchmarks/memory.py b/tools/perf/benchmarks/memory.py index 0eaa7be8..0dd9650 100644 --- a/tools/perf/benchmarks/memory.py +++ b/tools/perf/benchmarks/memory.py
@@ -33,6 +33,10 @@ def Name(cls): return 'memory.top_7_stress' + @classmethod + def ShouldDisable(cls, possible_browser): + return cls.IsSvelte(possible_browser) # http://crbug.com/555092 + class MemoryLongRunningIdleGmail(perf_benchmark.PerfBenchmark): """Use (recorded) real world web sites and measure memory consumption
diff --git a/tools/perf/benchmarks/smoothness.py b/tools/perf/benchmarks/smoothness.py index 53686b2..3987fa61 100644 --- a/tools/perf/benchmarks/smoothness.py +++ b/tools/perf/benchmarks/smoothness.py
@@ -462,6 +462,9 @@ def Name(cls): return 'smoothness.tough_ad_cases' + @classmethod + def ShouldDisable(cls, possible_browser): + return cls.IsSvelte(possible_browser) # http://crbug.com/555089 # http://crbug.com/496684 (reference) # http://crbug.com/522619 (mac/win)
diff --git a/tools/perf/benchmarks/start_with_url2.py b/tools/perf/benchmarks/start_with_url2.py new file mode 100644 index 0000000..a6747fb --- /dev/null +++ b/tools/perf/benchmarks/start_with_url2.py
@@ -0,0 +1,67 @@ +# Copyright 2015 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. + +from core import perf_benchmark +import page_sets + +from telemetry import benchmark +from telemetry.timeline import tracing_category_filter +from telemetry.web_perf import timeline_based_measurement +from telemetry.web_perf.metrics import startup + + +class _StartWithUrlTBM(perf_benchmark.PerfBenchmark): + """Measures time to start Chrome with startup URLs.""" + + page_set = page_sets.StartupPagesPageSetTBM + + @classmethod + def Name(cls): + # TODO(gabadie): change to start_with_url.* after confirming that both + # benchmarks produce the same results. + return 'start_with_url2.startup_pages' + + def SetExtraBrowserOptions(self, options): + options.AppendExtraBrowserArgs([ + '--enable-stats-collection-bindings' + ]) + + def CreateTimelineBasedMeasurementOptions(self): + startup_category_filter = tracing_category_filter.TracingCategoryFilter( + filter_string='startup,blink.user_timing') + options = timeline_based_measurement.Options( + overhead_level=startup_category_filter) + options.SetTimelineBasedMetrics( + [startup.StartupTimelineMetric()]) + return options + + +@benchmark.Enabled('has tabs') +@benchmark.Enabled('android') +@benchmark.Disabled('chromeos', 'linux', 'mac', 'win') +class StartWithUrlColdTBM(_StartWithUrlTBM): + """Measures time to start Chrome cold with startup URLs.""" + + options = {'pageset_repeat': 5} + + def SetExtraBrowserOptions(self, options): + options.clear_sytem_cache_for_browser_and_profile_on_start = True + super(StartWithUrlColdTBM, self).SetExtraBrowserOptions(options) + + @classmethod + def Name(cls): + return 'start_with_url2.cold.startup_pages' + + +@benchmark.Enabled('has tabs') +@benchmark.Enabled('android') +@benchmark.Disabled('chromeos', 'linux', 'mac', 'win') +class StartWithUrlWarmTBM(_StartWithUrlTBM): + """Measures stimetime to start Chrome warm with startup URLs.""" + + options = {'pageset_repeat': 10} + + @classmethod + def Name(cls): + return 'start_with_url2.warm.startup_pages'
diff --git a/tools/perf/core/perf_benchmark.py b/tools/perf/core/perf_benchmark.py index 7b89f3a..297f2d6 100644 --- a/tools/perf/core/perf_benchmark.py +++ b/tools/perf/core/perf_benchmark.py
@@ -62,3 +62,10 @@ os.path.join(variations_dir, 'fieldtrial_testing_config_%s.json' % self._FixupTargetOS( possible_browser.target_os))) + + @staticmethod + def IsSvelte(possible_browser): + """Returns whether a possible_browser is on a svelte Android build.""" + if possible_browser.target_os == 'android': + return possible_browser.platform.IsSvelte() + return False
diff --git a/tools/perf/page_sets/startup_pages.py b/tools/perf/page_sets/startup_pages.py index 2ca04ae..5678b54d 100644 --- a/tools/perf/page_sets/startup_pages.py +++ b/tools/perf/page_sets/startup_pages.py
@@ -2,9 +2,22 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. from telemetry.page import page as page_module +from telemetry.page import shared_page_state from telemetry import story +class BrowserStartupSharedState(shared_page_state.SharedPageState): + """Shared state that restarts the browser for every single story.""" + + def __init__(self, test, finder_options, story_set): + super(BrowserStartupSharedState, self).__init__( + test, finder_options, story_set) + + def DidRunStory(self, results): + super(BrowserStartupSharedState, self).DidRunStory(results) + self._StopBrowser() + + class StartedPage(page_module.Page): def __init__(self, url, startup_url, page_set): @@ -39,3 +52,42 @@ # Horribly complex page - stress test! self.AddStory(StartedPage( 'http://kapook.com', 'http://kapook.com', self)) + + +class StartedPageTBM(page_module.Page): + + def __init__(self, url, page_set): + super(StartedPageTBM, self).__init__( + url=url, page_set=page_set, startup_url=url, + shared_page_state_class=BrowserStartupSharedState) + self.archive_data_file = 'data/startup_pages.json' + + def RunNavigateSteps(self, action_runner): + # Do not call super.RunNavigateSteps() to avoid reloading the page that has + # already been opened with startup_url. + + # TODO(gabadie): Get rid of this (crbug.com/555504) + action_runner.Wait(10) + + def RunPageInteractions(self, action_runner): + self.RunNavigateSteps(action_runner) + + +class StartupPagesPageSetTBM(story.StorySet): + """Pages for testing starting Chrome with a URL. + + Note that this file can't be used with record_wpr, since record_wpr requires + a true navigate step, which we do not want for startup testing. Instead use + record_wpr startup_pages_record to record data for this test.""" + + def __init__(self): + super(StartupPagesPageSetTBM, self).__init__( + archive_data_file='data/startup_pages.json', + cloud_storage_bucket=story.PARTNER_BUCKET) + + # Typical page. + self.AddStory(StartedPageTBM('about:blank', self)) + # Typical page. + self.AddStory(StartedPageTBM('http://bbc.co.uk', self)) + # Horribly complex page - stress test! + self.AddStory(StartedPageTBM('http://kapook.com', self))
diff --git a/tools/telemetry/telemetry/internal/backends/chrome/desktop_browser_backend.py b/tools/telemetry/telemetry/internal/backends/chrome/desktop_browser_backend.py index 34bc7a6e..603e769 100644 --- a/tools/telemetry/telemetry/internal/backends/chrome/desktop_browser_backend.py +++ b/tools/telemetry/telemetry/internal/backends/chrome/desktop_browser_backend.py
@@ -143,11 +143,15 @@ '--no-window', '--dumps-dir=%s' % self._tmp_minidump_dir, '--pipe-name=%s' % self._GetCrashServicePipeName()]) - except: + except Exception: logging.error( 'Failed to run %s --no-window --dump-dir=%s --pip-name=%s' % ( command, self._tmp_minidump_dir, self._GetCrashServicePipeName())) logging.error('Running on platform: %s and arch: %s.', os_name, arch_name) + wmic_stdout, _ = subprocess.Popen( + ['wmic', 'process', 'get', 'CommandLine,Name,ProcessId,ParentProcessId', + '/format:csv'], stdout=subprocess.PIPE).communicate() + logging.error('Current running processes:\n%s' % wmic_stdout) raise return crash_service
diff --git a/tools/telemetry/telemetry/internal/platform/android_platform_backend.py b/tools/telemetry/telemetry/internal/platform/android_platform_backend.py index bbd9f50..5c8f333 100644 --- a/tools/telemetry/telemetry/internal/platform/android_platform_backend.py +++ b/tools/telemetry/telemetry/internal/platform/android_platform_backend.py
@@ -24,7 +24,8 @@ from telemetry.internal.platform.power_monitor import android_fuelgauge_power_monitor from telemetry.internal.platform.power_monitor import android_temperature_monitor from telemetry.internal.platform.power_monitor import monsoon_power_monitor -from telemetry.internal.platform.power_monitor import power_monitor_controller +from telemetry.internal.platform.power_monitor import ( + android_power_monitor_controller) from telemetry.internal.platform.power_monitor import sysfs_power_monitor from telemetry.internal.platform.profiler import android_prebuilt_profiler_helper from telemetry.internal.util import exception_formatter @@ -162,14 +163,16 @@ logging.exception('New exception caused by DeviceUtils conversion') raise self._device_copy_script = None - self._power_monitor = power_monitor_controller.PowerMonitorController([ + self._power_monitor = ( + android_power_monitor_controller.AndroidPowerMonitorController([ android_temperature_monitor.AndroidTemperatureMonitor(self._device), monsoon_power_monitor.MonsoonPowerMonitor(self._device, self), - android_dumpsys_power_monitor.DumpsysPowerMonitor(self._battery, self), + android_dumpsys_power_monitor.DumpsysPowerMonitor( + self._battery, self), sysfs_power_monitor.SysfsPowerMonitor(self, standalone=True), android_fuelgauge_power_monitor.FuelGaugePowerMonitor( self._battery, self), - ], self._battery) + ], self._battery)) self._video_recorder = None self._installed_applications = None
diff --git a/tools/telemetry/telemetry/internal/platform/power_monitor/android_dumpsys_power_monitor.py b/tools/telemetry/telemetry/internal/platform/power_monitor/android_dumpsys_power_monitor.py index eefdae88..e7980f44 100644 --- a/tools/telemetry/telemetry/internal/platform/power_monitor/android_dumpsys_power_monitor.py +++ b/tools/telemetry/telemetry/internal/platform/power_monitor/android_dumpsys_power_monitor.py
@@ -39,12 +39,10 @@ # Disable the charging of the device over USB. This is necessary because the # device only collects information about power usage when the device is not # charging. - self._ChargingOff(self._battery) def StopMonitoringPower(self): self._CheckStop() assert self._browser - self._ChargingOn(self._battery) package = self._browser._browser_backend.package self._browser = None
diff --git a/tools/telemetry/telemetry/internal/platform/power_monitor/android_dumpsys_power_monitor_unittest.py b/tools/telemetry/telemetry/internal/platform/power_monitor/android_dumpsys_power_monitor_unittest.py index 2f61b78..e38ebc5b 100644 --- a/tools/telemetry/telemetry/internal/platform/power_monitor/android_dumpsys_power_monitor_unittest.py +++ b/tools/telemetry/telemetry/internal/platform/power_monitor/android_dumpsys_power_monitor_unittest.py
@@ -84,7 +84,7 @@ pm = android_dumpsys_power_monitor.DumpsysPowerMonitor(battery, backend) self.assertEqual(battery.GetCharging(), True) pm.StartMonitoringPower(browser) - self.assertEqual(battery.GetCharging(), False) + self.assertEqual(battery.GetCharging(), True) pm.StopMonitoringPower() self.assertEqual(battery.GetCharging(), True)
diff --git a/tools/telemetry/telemetry/internal/platform/power_monitor/android_fuelgauge_power_monitor.py b/tools/telemetry/telemetry/internal/platform/power_monitor/android_fuelgauge_power_monitor.py index 0e7fe306..c3bb569 100644 --- a/tools/telemetry/telemetry/internal/platform/power_monitor/android_fuelgauge_power_monitor.py +++ b/tools/telemetry/telemetry/internal/platform/power_monitor/android_fuelgauge_power_monitor.py
@@ -25,7 +25,6 @@ def StartMonitoringPower(self, browser): self._CheckStart() - self._ChargingOff(self._battery) self._starting_fuel_gauge = self._battery.GetFuelGaugeChargeCounter() def StopMonitoringPower(self): @@ -34,7 +33,6 @@ fuel_gauge_delta = ( float((self._starting_fuel_gauge) - self._battery.GetFuelGaugeChargeCounter()) / 1000000) - self._ChargingOn(self._battery) voltage = self._ParseVoltage(self._battery.GetBatteryInfo().get('voltage')) return self.ProcessPowerData(voltage, fuel_gauge_delta)
diff --git a/tools/telemetry/telemetry/internal/platform/power_monitor/android_fuelgauge_power_monitor_unittest.py b/tools/telemetry/telemetry/internal/platform/power_monitor/android_fuelgauge_power_monitor_unittest.py index a40bae8b8..46cab41 100644 --- a/tools/telemetry/telemetry/internal/platform/power_monitor/android_fuelgauge_power_monitor_unittest.py +++ b/tools/telemetry/telemetry/internal/platform/power_monitor/android_fuelgauge_power_monitor_unittest.py
@@ -11,7 +11,7 @@ class FuelGaugePowerMonitorMonitorTest(unittest.TestCase): - def testEnergyComsumption(self): + def testEnergyConsumption(self): fuel_gauge_delta = 100 results = ( android_fuelgauge_power_monitor.FuelGaugePowerMonitor.ProcessPowerData(
diff --git a/tools/telemetry/telemetry/internal/platform/power_monitor/android_power_monitor_base.py b/tools/telemetry/telemetry/internal/platform/power_monitor/android_power_monitor_base.py index d140892..afcc87d9b 100644 --- a/tools/telemetry/telemetry/internal/platform/power_monitor/android_power_monitor_base.py +++ b/tools/telemetry/telemetry/internal/platform/power_monitor/android_power_monitor_base.py
@@ -34,12 +34,3 @@ if power_data['application_energy_consumption_mwh'] == 0: logging.warning('Power data is returning 0 usage for %s. %s' % (package, power_data)) - - def _ChargingOff(self, battery): - battery.SetCharging(False) - - def _ChargingOn(self, battery): - if battery.GetCharging(): - logging.warning('Charging re-enabled during test.' - 'Results may be inaccurate.') - battery.SetCharging(True)
diff --git a/tools/telemetry/telemetry/internal/platform/power_monitor/power_monitor_controller.py b/tools/telemetry/telemetry/internal/platform/power_monitor/android_power_monitor_controller.py similarity index 83% rename from tools/telemetry/telemetry/internal/platform/power_monitor/power_monitor_controller.py rename to tools/telemetry/telemetry/internal/platform/power_monitor/android_power_monitor_controller.py index 5b42c5e..dcd2d29 100644 --- a/tools/telemetry/telemetry/internal/platform/power_monitor/power_monitor_controller.py +++ b/tools/telemetry/telemetry/internal/platform/power_monitor/android_power_monitor_controller.py
@@ -5,20 +5,20 @@ import atexit import logging -import telemetry.internal.platform.power_monitor as power_monitor - +from telemetry.internal.platform.power_monitor import android_power_monitor_base def _ReenableChargingIfNeeded(battery): if not battery.GetCharging(): battery.SetCharging(True) -class PowerMonitorController(power_monitor.PowerMonitor): +class AndroidPowerMonitorController( + android_power_monitor_base.AndroidPowerMonitorBase): """ PowerMonitor that acts as facade for a list of PowerMonitor objects and uses the first available one. """ def __init__(self, power_monitors, battery): - super(PowerMonitorController, self).__init__() + super(AndroidPowerMonitorController, self).__init__() self._candidate_power_monitors = power_monitors self._active_monitors = [] self._battery = battery @@ -35,6 +35,7 @@ 'results are likely not reported.') self.StopMonitoringPower() self._CheckStart() + self._ChargingOff(self._battery) self._active_monitors = ( [m for m in self._candidate_power_monitors if m.CanMonitorPower()]) assert self._active_monitors, 'No available monitor.' @@ -70,6 +71,7 @@ def StopMonitoringPower(self): self._CheckStop() + self._ChargingOn(self._battery) try: results = {'platform_info': {}, 'component_utilization': {}} for monitor in self._active_monitors: @@ -77,3 +79,12 @@ return results finally: self._active_monitors = [] + + def _ChargingOff(self, battery): + battery.SetCharging(False) + + def _ChargingOn(self, battery): + if battery.GetCharging(): + logging.warning('Charging re-enabled during test.' + 'Results may be inaccurate.') + battery.SetCharging(True)
diff --git a/tools/telemetry/telemetry/internal/platform/power_monitor/power_monitor_controller_unittest.py b/tools/telemetry/telemetry/internal/platform/power_monitor/android_power_monitor_controller_unittest.py similarity index 81% rename from tools/telemetry/telemetry/internal/platform/power_monitor/power_monitor_controller_unittest.py rename to tools/telemetry/telemetry/internal/platform/power_monitor/android_power_monitor_controller_unittest.py index 2794f342..0968f4d 100644 --- a/tools/telemetry/telemetry/internal/platform/power_monitor/power_monitor_controller_unittest.py +++ b/tools/telemetry/telemetry/internal/platform/power_monitor/android_power_monitor_controller_unittest.py
@@ -5,12 +5,13 @@ import unittest from telemetry.internal.platform import power_monitor as power_monitor -from telemetry.internal.platform.power_monitor import power_monitor_controller +from telemetry.internal.platform.power_monitor import ( + android_power_monitor_controller) import mock from devil.android import battery_utils # pylint: disable=import-error -class PowerMonitorControllerTest(unittest.TestCase): +class AndroidPowerMonitorControllerTest(unittest.TestCase): @mock.patch.object(battery_utils, 'BatteryUtils') def testComposition(self, _): @@ -43,7 +44,7 @@ return self._value battery = battery_utils.BatteryUtils(None) - controller = power_monitor_controller.PowerMonitorController( + controller = android_power_monitor_controller.AndroidPowerMonitorController( [P1(), P2(1), P3(2)], battery) self.assertEqual(controller.CanMonitorPower(), True) controller.StartMonitoringPower(None) @@ -52,10 +53,10 @@ self.assertEqual(controller_returns['P3'], 2) @mock.patch.object(battery_utils, 'BatteryUtils') - def testReenableCharingIfNeeded(self, mock_battery): + def testReenableChargingIfNeeded(self, mock_battery): battery = battery_utils.BatteryUtils(None) battery.GetCharging.return_value = False - power_monitor_controller._ReenableChargingIfNeeded(battery) + android_power_monitor_controller._ReenableChargingIfNeeded(battery) def testMergePowerResultsOneEmpty(self): dict_one = {'platform_info': {}, 'component_utilization': {}} @@ -65,8 +66,8 @@ 'component_utilization': {'test': 2}, 'test': 1 } - power_monitor_controller.PowerMonitorController._MergePowerResults( - dict_one, dict_two) + (android_power_monitor_controller.AndroidPowerMonitorController. + _MergePowerResults(dict_one, dict_two)) self.assertDictEqual(dict_one, results) def testMergePowerResultsSameEntry(self): @@ -81,6 +82,6 @@ 'component_utilization': {'test': 2}, 'platform_info': {'test': 4, 'test2': 'a'} } - power_monitor_controller.PowerMonitorController._MergePowerResults( - dict_one, dict_two) + (android_power_monitor_controller.AndroidPowerMonitorController. + _MergePowerResults(dict_one, dict_two)) self.assertDictEqual(dict_one, results)
diff --git a/tools/telemetry/telemetry/web_perf/metrics/startup.py b/tools/telemetry/telemetry/web_perf/metrics/startup.py new file mode 100644 index 0000000..18025df --- /dev/null +++ b/tools/telemetry/telemetry/web_perf/metrics/startup.py
@@ -0,0 +1,95 @@ +# Copyright 2015 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. + +from telemetry import value +from telemetry.web_perf.metrics import timeline_based_metric + +_PROCESS_CREATION = 'Startup.BrowserProcessCreation' +_MAIN_ENTRY_POINT = 'Startup.BrowserMainEntryPoint' + +# A dictionary that maps metric names to a value, which can be either of +# the two: +# 1. A tuple of one event name if the event itself contains reported duration +# 2. A tuple of two event names if the value to report is the time difference +# between starting these events +_METRICS = { + 'messageloop_start_time': + ('Startup.BrowserMessageLoopStartTimeFromMainEntry',), + + 'window_display_time': + ('Startup.BrowserWindowDisplay',), + + 'open_tabs_time': + ('Startup.BrowserOpenTabs',), + + 'first_non_empty_paint_time': + ('Startup.FirstWebContents.NonEmptyPaint2',), + + 'first_main_frame_load_time': + ('Startup.FirstWebContents.MainFrameLoad2',), + + 'foreground_tab_load_complete': + (_MAIN_ENTRY_POINT, 'loadEventEnd'), + + # TODO(gabadie): Implement foreground_tab_request_start between + # _MAIN_ENTRY_POINT and 'requestStart' once crbug.com/552472 fixed. +} + +_TRACKED_EVENT_NAMES = set() +for i in _METRICS.values(): + _TRACKED_EVENT_NAMES.add(i[0]) + if len(i) == 2: + _TRACKED_EVENT_NAMES.add(i[1]) + + +class StartupTimelineMetric(timeline_based_metric.TimelineBasedMetric): + """Reports summary stats from important startup events.""" + + def __init__(self): + super(StartupTimelineMetric, self).__init__() + + def AddResults(self, model, _renderer_thread, interactions, results): + pass + + def AddWholeTraceResults(self, model, results): + browser = model.browser_process + + if not browser: + return + + # Produce a map of events to track. + tracked_events = {} + for event in browser.parent.IterAllEvents( + event_predicate=lambda event: event.name in _TRACKED_EVENT_NAMES): + # In case of a begin/end trace event, only track the begin that contain + # the duration. + if event.name in tracked_events: + continue + + tracked_events[event.name] = event + + # Generate the metric values according to the tracked events. + for display_name, event_names in _METRICS.iteritems(): + if event_names[0] not in tracked_events: + continue + + duration = None + if len(event_names) == 1: + # The single event contains the duration to report. + duration = tracked_events[event_names[0]].duration + + elif len(event_names) == 2: + # The duration is defined as the difference between two event starts. + if event_names[1] not in tracked_events: + continue + + duration = (tracked_events[event_names[1]].start - + tracked_events[event_names[0]].start) + + results.AddValue(value.scalar.ScalarValue( + page=results.current_page, + name=display_name, + units='ms', + value=duration, + improvement_direction=value.improvement_direction.DOWN))
diff --git a/tools/telemetry/telemetry/web_perf/metrics/startup_unittest.py b/tools/telemetry/telemetry/web_perf/metrics/startup_unittest.py new file mode 100644 index 0000000..a601334 --- /dev/null +++ b/tools/telemetry/telemetry/web_perf/metrics/startup_unittest.py
@@ -0,0 +1,94 @@ +# Copyright 2015 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. + +import unittest + +import telemetry.timeline.event as timeline_event +from telemetry.testing import test_page_test_results +from telemetry.web_perf.metrics import startup + + +class StartupTimelineMetricTest(unittest.TestCase): + + def setUp(self): + self.events = [] + + def AddEvent(self, event_name, start, duration=None): + event = timeline_event.TimelineEvent('my_category', event_name, + start, duration) + self.events.append(event) + + # Attributes defined outside __init__ + # pylint: disable=W0201 + def ComputeStartupMetrics(self): + results = test_page_test_results.TestPageTestResults(self) + + # Create a mock model usable by + # StartupTimelineMetric.AddWholeTraceResults(). + def IterateEvents(event_predicate): + for event in self.events: + if event_predicate(event): + yield event + class MockClass(object): + pass + model = MockClass() + model.browser_process = MockClass() + model.browser_process.parent = MockClass() + model.browser_process.parent.IterAllEvents = IterateEvents + + startup.StartupTimelineMetric().AddWholeTraceResults(model, results) + return results + + def testUntrackedvents(self): + # Code coverage for untracked events + self.AddEvent('uknown_event_0', 0) + self.AddEvent('uknown_event_1', 1) + self.ComputeStartupMetrics() + + def testInstantEventsBasedValue(self): + # Test case with instant events to measure the duration between the first + # occurrences of two distinct events. + START0 = 7 + START1 = 8 + DURATION0 = 17 + DURATION1 = 18 + + # Generate duplicated events to make sure we consider only the first one. + self.AddEvent(startup._MAIN_ENTRY_POINT, START0) + self.AddEvent(startup._MAIN_ENTRY_POINT, START1) + self.AddEvent('loadEventEnd', START0 + DURATION0) + self.AddEvent('loadEventEnd', START1 + DURATION1) + + results = self.ComputeStartupMetrics() + results.AssertHasPageSpecificScalarValue('foreground_tab_load_complete', + 'ms', DURATION0) + + def testBeginEndEventsBasedValue(self): + # Test case to get the duration of the first occurrence of a duration event. + i = 1 + for event_names in startup._METRICS.values(): + if len(event_names) != 1: + continue + + duration = 13 * i + i += 1 + + # Generate duplicated events to make sure only the first event is + # considered. + self.AddEvent(event_names[0], 5, duration) + self.AddEvent(event_names[0], 6, duration + 2) + + self.assertTrue(i > 1) + + results = self.ComputeStartupMetrics() + + i = 1 + for display_name, event_names in startup._METRICS.iteritems(): + if len(event_names) != 1: + continue + + duration = 13 * i + i += 1 + + results.AssertHasPageSpecificScalarValue(display_name, 'ms', duration)
diff --git a/tools/vim/PRESUBMIT.py b/tools/vim/PRESUBMIT.py index 8b0e945b..0456d37 100644 --- a/tools/vim/PRESUBMIT.py +++ b/tools/vim/PRESUBMIT.py
@@ -8,5 +8,23 @@ """ def CheckChangeOnUpload(input_api, output_api): - return input_api.canned_checks.RunUnitTestsInDirectory( - input_api, output_api, 'tests', whitelist=r'.*test.py') + results = [] + + # affected_files is list of files affected by this change. The paths are + # relative to the directory containing PRESUBMIT.py. + affected_files = [ + input_api.os_path.relpath(f, input_api.PresubmitLocalPath()) + for f in input_api.AbsoluteLocalPaths()] + + # Run the chromium.ycm_extra_conf_unittest test if the YCM config file is + # changed or if any change is affecting the tests directory. This specific + # test requires access to 'ninja' and hasn't been tested on platforms other + # than Linux. + if 'chromium.ycm_extra_conf.py' in affected_files or \ + any([input_api.re.match(r'tests(/|\\)',f) for f in affected_files]): + results += input_api.RunTests( + input_api.canned_checks.GetUnitTests( + input_api, output_api, + ['tests/chromium.ycm_extra_conf_unittest.py'])) + + return results
diff --git a/ui/accessibility/platform/ax_platform_node.cc b/ui/accessibility/platform/ax_platform_node.cc index ec268a0b..43ac5c23 100644 --- a/ui/accessibility/platform/ax_platform_node.cc +++ b/ui/accessibility/platform/ax_platform_node.cc
@@ -9,12 +9,12 @@ namespace ui { -#if !defined(OS_MACOSX) && !defined(OS_WIN) && !(defined(OS_LINUX) && !defined(OS_CHROMEOS)) +#if !defined(PLATFORM_HAS_AX_PLATFORM_NODE_IMPL) // static AXPlatformNode* AXPlatformNode::Create(AXPlatformNodeDelegate* delegate) { return nullptr; } -#endif +#endif // !defined(PLATFORM_HAS_AX_PLATFORM_NODE_IMPL) #if !defined(OS_WIN) // This is the default implementation for platforms where native views
diff --git a/ui/accessibility/platform/ax_platform_node.h b/ui/accessibility/platform/ax_platform_node.h index 8fa4286..9c4e9e3 100644 --- a/ui/accessibility/platform/ax_platform_node.h +++ b/ui/accessibility/platform/ax_platform_node.h
@@ -9,6 +9,22 @@ #include "ui/accessibility/ax_export.h" #include "ui/gfx/native_widget_types.h" +// Set PLATFORM_HAS_AX_PLATFORM_NODE_IMPL if this platform has a specific +// implementation of AxPlatfromNode::Create(). +#undef PLATFORM_HAS_AX_PLATFORM_NODE_IMPL + +#if defined(OS_WIN) +#define PLATFORM_HAS_AX_PLATFORM_NODE_IMPL 1 +#endif + +#if defined(OS_MACOSX) +#define PLATFORM_HAS_AX_PLATFORM_NODE_IMPL 1 +#endif + +#if defined(OS_LINUX) && !defined(OS_CHROMEOS) && defined(USE_X11) +#define PLATFORM_HAS_AX_PLATFORM_NODE_IMPL 1 +#endif + namespace ui { class AXPlatformNodeDelegate;
diff --git a/ui/android/BUILD.gn b/ui/android/BUILD.gn index 1b5b547..412f4d79 100644 --- a/ui/android/BUILD.gn +++ b/ui/android/BUILD.gn
@@ -43,12 +43,12 @@ defines = [ "UI_ANDROID_IMPLEMENTATION" ] deps = [ + ":ui_android_jni_headers", "//base", "//cc", "//skia", "//ui/gfx", "//ui/gfx/geometry", - ":ui_android_jni_headers", ] } @@ -143,8 +143,8 @@ DEPRECATED_java_in_dir = "javatests/src" testonly = true deps = [ - ":ui_java_resources", ":ui_java", + ":ui_java_resources", "//base:base_java", "//base:base_java_test_support", ]
diff --git a/ui/app_list/BUILD.gn b/ui/app_list/BUILD.gn index 7261a6e..090eaf17 100644 --- a/ui/app_list/BUILD.gn +++ b/ui/app_list/BUILD.gn
@@ -245,22 +245,22 @@ "//content", "//content/public/browser", "//skia", - "//url", "//ui/base", "//ui/events", "//ui/resources", "//ui/resources:ui_test_pak", "//ui/views", - "//ui/views_content_client", "//ui/views/controls/webview", + "//ui/views_content_client", + "//url", ] if (is_win) { configs -= [ "//build/config/win:console" ] configs += [ "//build/config/win:windowed" ] deps += [ - "//sandbox", "//content:sandbox_helper_win", + "//sandbox", ] } }
diff --git a/ui/aura/BUILD.gn b/ui/aura/BUILD.gn index 16820f6..2e0f78c9 100644 --- a/ui/aura/BUILD.gn +++ b/ui/aura/BUILD.gn
@@ -231,8 +231,8 @@ ":aura", ":test_support", "//base", - "//build/config/sanitizers:deps", "//base:i18n", + "//build/config/sanitizers:deps", "//skia", "//third_party/icu", "//ui/base", @@ -306,8 +306,8 @@ "//testing/gtest", "//ui/base:test_support", "//ui/compositor:test_support", - "//ui/events:test_support", "//ui/events:gesture_detection", + "//ui/events:test_support", "//ui/gfx", "//ui/gfx/geometry", "//ui/gl",
diff --git a/ui/aura/window_targeter.cc b/ui/aura/window_targeter.cc index df4e064..4b72051 100644 --- a/ui/aura/window_targeter.cc +++ b/ui/aura/window_targeter.cc
@@ -71,6 +71,7 @@ // |window|. So do not allow dispatching from here. Instead, dispatch the // event through the WindowEventDispatcher that owns |target|. Window* new_root = target->GetRootWindow(); + DCHECK(new_root); if (event->IsLocatedEvent()) { // The event has been transformed to be in |target|'s coordinate system. // But dispatching the event through the EventProcessor requires the event
diff --git a/ui/base/BUILD.gn b/ui/base/BUILD.gn index 61caad5..a17bc1116 100644 --- a/ui/base/BUILD.gn +++ b/ui/base/BUILD.gn
@@ -320,15 +320,15 @@ public_deps = [ "//base", "//skia", - "//ui/events/platform", "//ui/events:events_base", + "//ui/events/platform", "//ui/gfx", "//ui/gfx/geometry", ] deps = [ - "//base/third_party/dynamic_annotations", "//base:base_static", "//base:i18n", + "//base/third_party/dynamic_annotations", "//net", "//third_party/icu", "//ui/events",
diff --git a/ui/base/ime/BUILD.gn b/ui/base/ime/BUILD.gn index 9169679..b915757c0 100644 --- a/ui/base/ime/BUILD.gn +++ b/ui/base/ime/BUILD.gn
@@ -105,8 +105,8 @@ deps = [ "//base", - "//base/third_party/dynamic_annotations", "//base:i18n", + "//base/third_party/dynamic_annotations", "//net", "//third_party/icu", "//ui/base", @@ -181,8 +181,8 @@ if (use_ozone) { deps += [ - "//ui/ozone", "//ui/events/ozone:events_ozone_layout", + "//ui/ozone", ] } }
diff --git a/ui/base/ime/chromeos/component_extension_ime_manager.cc b/ui/base/ime/chromeos/component_extension_ime_manager.cc index 97ed38c6..664f6e0 100644 --- a/ui/base/ime/chromeos/component_extension_ime_manager.cc +++ b/ui/base/ime/chromeos/component_extension_ime_manager.cc
@@ -58,7 +58,9 @@ "us(colemak)", "us(dvorak)", "us(dvp)", - "us(intl)" + "us(intl)", + "us(workman)", + "us(workman-intl)" }; // Gets the input method category according to the given input method id.
diff --git a/ui/compositor/BUILD.gn b/ui/compositor/BUILD.gn index dcc25568..6c12191 100644 --- a/ui/compositor/BUILD.gn +++ b/ui/compositor/BUILD.gn
@@ -86,9 +86,9 @@ # TODO(sky): before we make this real need to remove # IDR_BITMAP_BRUSH_IMAGE. deps += [ - "//ui/resources", "//third_party/angle:libEGL", "//third_party/angle:libGLESv2", + "//ui/resources", ] } } @@ -130,8 +130,8 @@ deps = [ "//base/test:test_support", "//cc", - "//cc/surfaces", "//cc:test_support", + "//cc/surfaces", "//gpu/command_buffer/client:gl_in_process_context", "//gpu/command_buffer/client:gles2_c_lib", "//gpu/command_buffer/client:gles2_implementation",
diff --git a/ui/file_manager/BUILD.gn b/ui/file_manager/BUILD.gn index c6a7c999..369a695 100644 --- a/ui/file_manager/BUILD.gn +++ b/ui/file_manager/BUILD.gn
@@ -22,8 +22,8 @@ "file_manager_resource_util.h", ] deps = [ - "//base", ":resources", + "//base", ] defines = [ "FILE_MANAGER_IMPLEMENTATION" ] }
diff --git a/ui/gfx/BUILD.gn b/ui/gfx/BUILD.gn index 114d476a..c70843d 100644 --- a/ui/gfx/BUILD.gn +++ b/ui/gfx/BUILD.gn
@@ -258,8 +258,8 @@ deps = [ ":gfx_export", "//base", - "//base:i18n", "//base:base_static", + "//base:i18n", "//base/third_party/dynamic_annotations", "//skia", "//third_party/harfbuzz-ng", @@ -687,10 +687,10 @@ "//base", "//base/test:test_support", "//skia", + "//testing/gtest", "//third_party/icu:icuuc", "//third_party/libpng", "//third_party/zlib", - "//testing/gtest", "//ui/base", "//ui/gfx/geometry", "//ui/resources:ui_test_pak",
diff --git a/ui/gfx/vector_icons/incognito.1x.icon b/ui/gfx/vector_icons/incognito.1x.icon index 3d4e21e..fbb73fb 100644 --- a/ui/gfx/vector_icons/incognito.1x.icon +++ b/ui/gfx/vector_icons/incognito.1x.icon
@@ -27,6 +27,7 @@ R_CUBIC_TO, 1.11f, 0, 2, -0.89f, 2, -2, R_CUBIC_TO, 0, -1.1f, -0.89f, -2, -2, -2, CLOSE, +NEW_PATH, MOVE_TO, 12, 18, R_CUBIC_TO, 0.93f, 0, 1.71f, 0.64f, 1.93f, 1.5f, R_CUBIC_TO, 0.04f, -0.16f, 0.07f, -0.33f, 0.07f, -0.5f, @@ -34,6 +35,7 @@ R_CUBIC_TO, -1.1f, 0, -2, 0.9f, -2, 2, R_CUBIC_TO, 0, 0.17f, 0.03f, 0.34f, 0.07f, 0.5f, R_CUBIC_TO, 0.22f, -0.86f, 1, -1.5f, 1.93f, -1.5f, +NEW_PATH, MOVE_TO, 16.39f, 9, LINE_TO, 15, 5, R_LINE_TO, -3, 1,
diff --git a/ui/gfx/vector_icons/incognito.icon b/ui/gfx/vector_icons/incognito.icon index cd65f43..0798668 100644 --- a/ui/gfx/vector_icons/incognito.icon +++ b/ui/gfx/vector_icons/incognito.icon
@@ -26,6 +26,7 @@ R_CUBIC_TO, 2.04f, 0, 3.69f, -1.66f, 3.69f, -3.69f, R_CUBIC_TO, 0, -2.04f, -1.66f, -3.69f, -3.69f, -3.69f, CLOSE, +NEW_PATH, MOVE_TO, 24, 33.23f, R_CUBIC_TO, 1.72f, 0, 3.15f, 1.18f, 3.56f, 2.77f, R_CUBIC_TO, 0.08f, -0.3f, 0.13f, -0.6f, 0.13f, -0.92f, @@ -33,6 +34,7 @@ R_CUBIC_TO, -2.04f, 0, -3.69f, 1.65f, -3.69f, 3.69f, R_CUBIC_TO, 0, 0.32f, 0.05f, 0.63f, 0.13f, 0.92f, R_CUBIC_TO, 0.41f, -1.59f, 1.84f, -2.77f, 3.56f, -2.77f, +NEW_PATH, MOVE_TO, 33.29f, 20, R_LINE_TO, 0.06f, 0.18f, LINE_TO, 40.62f, 24,
diff --git a/ui/keyboard/BUILD.gn b/ui/keyboard/BUILD.gn index 4600fbc..a1ce72c 100644 --- a/ui/keyboard/BUILD.gn +++ b/ui/keyboard/BUILD.gn
@@ -142,8 +142,8 @@ "//testing/gtest", "//ui/aura:test_support", "//ui/base", - "//ui/base/ime", "//ui/base:test_support", + "//ui/base/ime", "//ui/compositor:test_support", "//ui/events:test_support", "//ui/gfx",
diff --git a/ui/message_center/BUILD.gn b/ui/message_center/BUILD.gn index 6139e1e..850dc2d 100644 --- a/ui/message_center/BUILD.gn +++ b/ui/message_center/BUILD.gn
@@ -115,9 +115,9 @@ "views/toast_contents_view.h", ] deps += [ + "//ui/compositor", "//ui/events", "//ui/views", - "//ui/compositor", ] }
diff --git a/ui/ozone/platform/cast/BUILD.gn b/ui/ozone/platform/cast/BUILD.gn index 4e82eb1d..5d2a21b 100644 --- a/ui/ozone/platform/cast/BUILD.gn +++ b/ui/ozone/platform/cast/BUILD.gn
@@ -34,8 +34,8 @@ deps = [ "//base", - "//chromecast/media/base:message_loop", "//chromecast/graphics:libcast_graphics_1.0", + "//chromecast/media/base:message_loop", "//ui/gfx", "//ui/gfx/geometry", "//ui/ozone:ozone_base",
diff --git a/ui/ozone/platform/cast/surface_factory_cast.cc b/ui/ozone/platform/cast/surface_factory_cast.cc index 1d4bee3b..bb3e60dc 100644 --- a/ui/ozone/platform/cast/surface_factory_cast.cc +++ b/ui/ozone/platform/cast/surface_factory_cast.cc
@@ -192,7 +192,7 @@ int GetDmaBufFd() override { return -1; } int GetDmaBufPitch() override { return 0; } gfx::BufferFormat GetBufferFormat() override { - return gfx::BufferFormat::LAST; + return gfx::BufferFormat::BGRA_8888; } bool ScheduleOverlayPlane(gfx::AcceleratedWidget widget, int plane_z_order,
diff --git a/ui/ozone/platform/drm/common/drm_util.cc b/ui/ozone/platform/drm/common/drm_util.cc index 00d4333..57f3488 100644 --- a/ui/ozone/platform/drm/common/drm_util.cc +++ b/ui/ozone/platform/drm/common/drm_util.cc
@@ -295,7 +295,7 @@ return gfx::BufferFormat::UYVY_422; default: NOTREACHED(); - return gfx::BufferFormat::LAST; + return gfx::BufferFormat::BGRA_8888; } } } // namespace ui
diff --git a/ui/ozone/platform/headless/BUILD.gn b/ui/ozone/platform/headless/BUILD.gn index fb731a2..e473a62 100644 --- a/ui/ozone/platform/headless/BUILD.gn +++ b/ui/ozone/platform/headless/BUILD.gn
@@ -20,8 +20,8 @@ "//base", "//skia", "//ui/base", - "//ui/gfx/geometry", "//ui/events/ozone:events_ozone_layout", "//ui/events/platform", + "//ui/gfx/geometry", ] }
diff --git a/ui/platform_window/android/BUILD.gn b/ui/platform_window/android/BUILD.gn index aae7a97..3a1f6d4 100644 --- a/ui/platform_window/android/BUILD.gn +++ b/ui/platform_window/android/BUILD.gn
@@ -20,14 +20,14 @@ defines = [ "ANDROID_WINDOW_IMPLEMENTATION" ] deps = [ + ":jni_headers", + ":platform_window_java", "//base", "//skia", "//ui/events:events", "//ui/events:events_base", "//ui/gfx", "//ui/gfx/geometry", - ":jni_headers", - ":platform_window_java", ] libs = [ "android" ]
diff --git a/ui/resources/BUILD.gn b/ui/resources/BUILD.gn index 414f145..eaf4646 100644 --- a/ui/resources/BUILD.gn +++ b/ui/resources/BUILD.gn
@@ -67,8 +67,8 @@ if (is_ios || is_mac) { group("ui_test_pak") { public_deps = [ - ":repack_ui_test_pak", ":repack_ui_test_mac_locale_pack", + ":repack_ui_test_pak", ] } } else {
diff --git a/ui/shell_dialogs/BUILD.gn b/ui/shell_dialogs/BUILD.gn index 9696e98..4ecd64c 100644 --- a/ui/shell_dialogs/BUILD.gn +++ b/ui/shell_dialogs/BUILD.gn
@@ -84,8 +84,8 @@ deps = [ ":shell_dialogs", "//base", - "//base/test:test_support", "//base/test:run_all_unittests", + "//base/test:test_support", "//testing/gtest", ] }
diff --git a/ui/strings/BUILD.gn b/ui/strings/BUILD.gn index 82cad9f..b5f471a 100644 --- a/ui/strings/BUILD.gn +++ b/ui/strings/BUILD.gn
@@ -8,8 +8,8 @@ # targets want both. You can depend on the individually if you need to. group("strings") { public_deps = [ - ":ui_strings", ":app_locale_settings", + ":ui_strings", ] }
diff --git a/ui/views/BUILD.gn b/ui/views/BUILD.gn index 12187f5..44e854cd 100644 --- a/ui/views/BUILD.gn +++ b/ui/views/BUILD.gn
@@ -113,7 +113,7 @@ "//ui/touch_selection", "//ui/wm", ] - if (!is_chromeos) { + if (!is_chromeos && !is_android) { sources += gypi_values.views_desktop_aura_sources if (use_x11) { sources += gypi_values.views_desktop_aura_x11_sources @@ -200,11 +200,11 @@ "//third_party/icu", "//ui/accessibility", "//ui/base", - "//ui/base/ime", "//ui/base:test_support", + "//ui/base/ime", "//ui/compositor:test_support", - "//ui/events:test_support", "//ui/events:events_base", + "//ui/events:test_support", "//ui/events/platform", "//ui/gfx", "//ui/gfx/geometry",
diff --git a/ui/views/accessibility/native_view_accessibility.cc b/ui/views/accessibility/native_view_accessibility.cc index db8367f..431268f 100644 --- a/ui/views/accessibility/native_view_accessibility.cc +++ b/ui/views/accessibility/native_view_accessibility.cc
@@ -13,12 +13,12 @@ namespace views { -#if !defined(OS_WIN) && !(defined(OS_LINUX) && !defined(OS_CHROMEOS)) +#if !defined(PLATFORM_HAS_NATIVE_VIEW_ACCESSIBILITY_IMPL) // static NativeViewAccessibility* NativeViewAccessibility::Create(View* view) { return new NativeViewAccessibility(view); } -#endif +#endif // !defined(PLATFORM_HAS_NATIVE_VIEW_ACCESSIBILITY_IMPL) NativeViewAccessibility::NativeViewAccessibility(View* view) : view_(view),
diff --git a/ui/views/accessibility/native_view_accessibility.h b/ui/views/accessibility/native_view_accessibility.h index 5c5c135..12b4342 100644 --- a/ui/views/accessibility/native_view_accessibility.h +++ b/ui/views/accessibility/native_view_accessibility.h
@@ -12,6 +12,18 @@ #include "ui/views/views_export.h" #include "ui/views/widget/widget_observer.h" +// Set PLATFORM_HAS_NATIVE_VIEW_ACCESSIBILITY_IMPL if this platform has a +// specific implementation of NativeViewAccessibility::Create(). +#undef PLATFORM_HAS_NATIVE_VIEW_ACCESSIBILITY_IMPL + +#if defined(OS_WIN) +#define PLATFORM_HAS_NATIVE_VIEW_ACCESSIBILITY_IMPL 1 +#endif + +#if defined(OS_LINUX) && defined(USE_X11) && !defined(OS_CHROMEOS) +#define PLATFORM_HAS_NATIVE_VIEW_ACCESSIBILITY_IMPL 1 +#endif + namespace views { class View;
diff --git a/ui/views/bubble/bubble_delegate.cc b/ui/views/bubble/bubble_delegate.cc index 184a8ac..11dc4ff 100644 --- a/ui/views/bubble/bubble_delegate.cc +++ b/ui/views/bubble/bubble_delegate.cc
@@ -51,25 +51,10 @@ const char BubbleDelegateView::kViewClassName[] = "BubbleDelegateView"; BubbleDelegateView::BubbleDelegateView() - : close_on_esc_(true), - close_on_deactivate_(true), - anchor_view_storage_id_(ViewStorage::GetInstance()->CreateStorageID()), - anchor_widget_(NULL), - arrow_(BubbleBorder::TOP_LEFT), - shadow_(BubbleBorder::SMALL_SHADOW), - color_explicitly_set_(false), - margins_(kDefaultMargin, kDefaultMargin, kDefaultMargin, kDefaultMargin), - accept_events_(true), - border_accepts_events_(true), - adjust_if_offscreen_(true), - parent_window_(NULL) { - AddAccelerator(ui::Accelerator(ui::VKEY_ESCAPE, ui::EF_NONE)); - UpdateColorsFromTheme(GetNativeTheme()); -} + : BubbleDelegateView(nullptr, BubbleBorder::TOP_LEFT) {} -BubbleDelegateView::BubbleDelegateView( - View* anchor_view, - BubbleBorder::Arrow arrow) +BubbleDelegateView::BubbleDelegateView(View* anchor_view, + BubbleBorder::Arrow arrow) : close_on_esc_(true), close_on_deactivate_(true), anchor_view_storage_id_(ViewStorage::GetInstance()->CreateStorageID()), @@ -81,8 +66,10 @@ accept_events_(true), border_accepts_events_(true), adjust_if_offscreen_(true), - parent_window_(NULL) { - SetAnchorView(anchor_view); + parent_window_(NULL), + close_reason_(CloseReason::UNKNOWN) { + if (anchor_view) + SetAnchorView(anchor_view); AddAccelerator(ui::Accelerator(ui::VKEY_ESCAPE, ui::EF_NONE)); UpdateColorsFromTheme(GetNativeTheme()); } @@ -151,6 +138,14 @@ return kViewClassName; } +void BubbleDelegateView::OnWidgetClosing(Widget* widget) { + DCHECK(GetBubbleFrameView()); + if (widget == GetWidget() && close_reason_ == CloseReason::UNKNOWN && + GetBubbleFrameView()->close_button_clicked()) { + close_reason_ = CloseReason::CLOSE_BUTTON; + } +} + void BubbleDelegateView::OnWidgetDestroying(Widget* widget) { if (anchor_widget() == widget) SetAnchorView(NULL); @@ -175,8 +170,11 @@ void BubbleDelegateView::OnWidgetActivationChanged(Widget* widget, bool active) { - if (close_on_deactivate() && widget == GetWidget() && !active) + if (close_on_deactivate() && widget == GetWidget() && !active) { + if (close_reason_ == CloseReason::UNKNOWN) + close_reason_ = CloseReason::DEACTIVATION; GetWidget()->Close(); + } } void BubbleDelegateView::OnWidgetBoundsChanged(Widget* widget, @@ -221,6 +219,7 @@ const ui::Accelerator& accelerator) { if (!close_on_esc() || accelerator.key_code() != ui::VKEY_ESCAPE) return false; + close_reason_ = CloseReason::ESCAPE; GetWidget()->Close(); return true; }
diff --git a/ui/views/bubble/bubble_delegate.h b/ui/views/bubble/bubble_delegate.h index 3bc73f8..1bd96340 100644 --- a/ui/views/bubble/bubble_delegate.h +++ b/ui/views/bubble/bubble_delegate.h
@@ -28,6 +28,13 @@ // Internal class name. static const char kViewClassName[]; + enum class CloseReason { + DEACTIVATION, + ESCAPE, + CLOSE_BUTTON, + UNKNOWN, + }; + BubbleDelegateView(); BubbleDelegateView(View* anchor_view, BubbleBorder::Arrow arrow); ~BubbleDelegateView() override; @@ -44,6 +51,7 @@ const char* GetClassName() const override; // WidgetObserver overrides: + void OnWidgetClosing(Widget* widget) override; void OnWidgetDestroying(Widget* widget) override; void OnWidgetVisibilityChanging(Widget* widget, bool visible) override; void OnWidgetVisibilityChanged(Widget* widget, bool visible) override; @@ -93,6 +101,8 @@ bool adjust_if_offscreen() const { return adjust_if_offscreen_; } void set_adjust_if_offscreen(bool adjust) { adjust_if_offscreen_ = adjust; } + CloseReason close_reason() const { return close_reason_; } + // Get the arrow's anchor rect in screen space. virtual gfx::Rect GetAnchorRect() const; @@ -192,6 +202,8 @@ // Parent native window of the bubble. gfx::NativeView parent_window_; + CloseReason close_reason_; + DISALLOW_COPY_AND_ASSIGN(BubbleDelegateView); };
diff --git a/ui/views/bubble/bubble_delegate_unittest.cc b/ui/views/bubble/bubble_delegate_unittest.cc index 16f14c59..1ec4e395 100644 --- a/ui/views/bubble/bubble_delegate_unittest.cc +++ b/ui/views/bubble/bubble_delegate_unittest.cc
@@ -3,8 +3,10 @@ // found in the LICENSE file. #include "ui/base/hit_test.h" +#include "ui/events/event_utils.h" #include "ui/views/bubble/bubble_delegate.h" #include "ui/views/bubble/bubble_frame_view.h" +#include "ui/views/controls/button/label_button.h" #include "ui/views/test/test_widget_observer.h" #include "ui/views/test/views_test_base.h" #include "ui/views/widget/widget.h" @@ -36,6 +38,10 @@ View* GetInitiallyFocusedView() override { return view_; } gfx::Size GetPreferredSize() const override { return gfx::Size(200, 200); } + BubbleFrameView* GetBubbleFrameViewForTest() const { + return GetBubbleFrameView(); + } + private: View* view_; @@ -261,4 +267,53 @@ EXPECT_FALSE(bubble_widget->CanActivate()); } +TEST_F(BubbleDelegateTest, CloseReasons) { + { + scoped_ptr<Widget> anchor_widget(CreateTestWidget()); + BubbleDelegateView* bubble_delegate = new BubbleDelegateView( + anchor_widget->GetContentsView(), BubbleBorder::NONE); + bubble_delegate->set_close_on_deactivate(true); + Widget* bubble_widget = BubbleDelegateView::CreateBubble(bubble_delegate); + bubble_widget->Show(); + anchor_widget->Activate(); + EXPECT_TRUE(bubble_widget->IsClosed()); + EXPECT_EQ(BubbleDelegateView::CloseReason::DEACTIVATION, + bubble_delegate->close_reason()); + } + + { + scoped_ptr<Widget> anchor_widget(CreateTestWidget()); + BubbleDelegateView* bubble_delegate = new BubbleDelegateView( + anchor_widget->GetContentsView(), BubbleBorder::NONE); + bubble_delegate->set_close_on_esc(true); + Widget* bubble_widget = BubbleDelegateView::CreateBubble(bubble_delegate); + bubble_widget->Show(); + // Cast as a test hack to access AcceleratorPressed() (which is protected + // in BubbleDelegate). + static_cast<View*>(bubble_delegate) + ->AcceleratorPressed(ui::Accelerator(ui::VKEY_ESCAPE, ui::EF_NONE)); + EXPECT_TRUE(bubble_widget->IsClosed()); + EXPECT_EQ(BubbleDelegateView::CloseReason::ESCAPE, + bubble_delegate->close_reason()); + } + + { + scoped_ptr<Widget> anchor_widget(CreateTestWidget()); + TestBubbleDelegateView* bubble_delegate = + new TestBubbleDelegateView(anchor_widget->GetContentsView()); + Widget* bubble_widget = BubbleDelegateView::CreateBubble(bubble_delegate); + bubble_widget->Show(); + BubbleFrameView* frame_view = bubble_delegate->GetBubbleFrameViewForTest(); + LabelButton* close_button = frame_view->close_; + ASSERT_TRUE(close_button); + frame_view->ButtonPressed( + close_button, + ui::MouseEvent(ui::ET_MOUSE_PRESSED, gfx::Point(0, 0), gfx::Point(0, 0), + ui::EventTimeForNow(), ui::EF_NONE, ui::EF_NONE)); + EXPECT_TRUE(bubble_widget->IsClosed()); + EXPECT_EQ(BubbleDelegateView::CloseReason::CLOSE_BUTTON, + bubble_delegate->close_reason()); + } +} + } // namespace views
diff --git a/ui/views/bubble/bubble_frame_view.cc b/ui/views/bubble/bubble_frame_view.cc index 88025b0..c9fcd40 100644 --- a/ui/views/bubble/bubble_frame_view.cc +++ b/ui/views/bubble/bubble_frame_view.cc
@@ -70,7 +70,8 @@ title_icon_(new views::ImageView()), title_(nullptr), close_(nullptr), - titlebar_extra_view_(nullptr) { + titlebar_extra_view_(nullptr), + close_button_clicked_(false) { AddChildView(title_icon_); ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); @@ -321,8 +322,10 @@ } void BubbleFrameView::ButtonPressed(Button* sender, const ui::Event& event) { - if (sender == close_) + if (sender == close_) { + close_button_clicked_ = true; GetWidget()->Close(); + } } void BubbleFrameView::SetBubbleBorder(scoped_ptr<BubbleBorder> border) {
diff --git a/ui/views/bubble/bubble_frame_view.h b/ui/views/bubble/bubble_frame_view.h index b21215c..28750c3 100644 --- a/ui/views/bubble/bubble_frame_view.h +++ b/ui/views/bubble/bubble_frame_view.h
@@ -84,6 +84,8 @@ gfx::Size client_size, bool adjust_if_offscreen); + bool close_button_clicked() const { return close_button_clicked_; } + protected: // Returns the available screen bounds if the frame were to show in |rect|. virtual gfx::Rect GetAvailableScreenBounds(const gfx::Rect& rect) const; @@ -93,6 +95,7 @@ private: FRIEND_TEST_ALL_PREFIXES(BubbleFrameViewTest, GetBoundsForClientView); + FRIEND_TEST_ALL_PREFIXES(BubbleDelegateTest, CloseReasons); // Mirrors the bubble's arrow location on the |vertical| or horizontal axis, // if the generated window bounds don't fit in the monitor bounds. @@ -123,6 +126,9 @@ // (x) close button. View* titlebar_extra_view_; + // Whether the close button was clicked. + bool close_button_clicked_; + DISALLOW_COPY_AND_ASSIGN(BubbleFrameView); };
diff --git a/ui/views/controls/styled_label.cc b/ui/views/controls/styled_label.cc index 91eb933..6c0ec76 100644 --- a/ui/views/controls/styled_label.cc +++ b/ui/views/controls/styled_label.cc
@@ -215,7 +215,7 @@ void StyledLabel::LinkClicked(Link* source, int event_flags) { if (listener_) - listener_->StyledLabelLinkClicked(link_targets_[source], event_flags); + listener_->StyledLabelLinkClicked(this, link_targets_[source], event_flags); } gfx::Size StyledLabel::CalculateAndDoLayout(int width, bool dry_run) {
diff --git a/ui/views/controls/styled_label_listener.h b/ui/views/controls/styled_label_listener.h index 13c08fd..0ff98eb 100644 --- a/ui/views/controls/styled_label_listener.h +++ b/ui/views/controls/styled_label_listener.h
@@ -13,10 +13,13 @@ namespace views { +class StyledLabel; + // A listener interface for StyledLabel. class VIEWS_EXPORT StyledLabelListener { public: - virtual void StyledLabelLinkClicked(const gfx::Range& range, + virtual void StyledLabelLinkClicked(StyledLabel* label, + const gfx::Range& range, int event_flags) = 0; protected:
diff --git a/ui/views/controls/styled_label_unittest.cc b/ui/views/controls/styled_label_unittest.cc index 7a2a7f58..cda5ed9 100644 --- a/ui/views/controls/styled_label_unittest.cc +++ b/ui/views/controls/styled_label_unittest.cc
@@ -27,7 +27,8 @@ ~StyledLabelTest() override {} // StyledLabelListener implementation. - void StyledLabelLinkClicked(const gfx::Range& range, + void StyledLabelLinkClicked(StyledLabel* label, + const gfx::Range& range, int event_flags) override {} protected:
diff --git a/ui/views/examples/BUILD.gn b/ui/views/examples/BUILD.gn index 03db107..68e05ef6a 100644 --- a/ui/views/examples/BUILD.gn +++ b/ui/views/examples/BUILD.gn
@@ -103,8 +103,8 @@ deps = [ ":views_examples_lib", "//base", - "//build/config/sanitizers:deps", "//base:i18n", + "//build/config/sanitizers:deps", "//ui/base", "//ui/compositor", "//ui/compositor:test_support",
diff --git a/ui/views/mus/BUILD.gn b/ui/views/mus/BUILD.gn index 5ab84dc6..d3b39a2 100644 --- a/ui/views/mus/BUILD.gn +++ b/ui/views/mus/BUILD.gn
@@ -48,7 +48,6 @@ "//components/mus/public/interfaces", "//components/resource_provider/public/cpp", "//components/resource_provider/public/interfaces", - "//skia", "//mojo/application/public/cpp", "//mojo/application/public/interfaces", "//mojo/converters/geometry", @@ -59,6 +58,7 @@ "//mojo/platform_handle:for_component", "//mojo/public/c/system:for_component", "//mojo/public/cpp/bindings", + "//skia", "//third_party/icu", "//ui/aura", "//ui/compositor", @@ -93,8 +93,8 @@ ] output = "$root_out_dir/views_mus_resources.pak" deps = [ - "//ui/strings", "//ui/resources", + "//ui/strings", "//ui/views/resources", ] }
diff --git a/ui/views/mus/native_widget_mus.cc b/ui/views/mus/native_widget_mus.cc index bbcc75d1..d51516d 100644 --- a/ui/views/mus/native_widget_mus.cc +++ b/ui/views/mus/native_widget_mus.cc
@@ -179,7 +179,6 @@ surface_type_(surface_type), show_state_before_fullscreen_(ui::PLATFORM_WINDOW_STATE_UNKNOWN), ownership_(Widget::InitParams::NATIVE_WIDGET_OWNS_WIDGET), - context_factory_(new SurfaceContextFactory(shell, window, surface_type)), content_(new aura::Window(this)), close_widget_factory_(this) {} @@ -263,8 +262,13 @@ // For Chrome, we need the GpuProcessTransportFactory so that renderer and // browser pixels are composited into a single backing // SoftwareOutputDeviceMus. - if (!default_context_factory) + if (!default_context_factory) { + if (!context_factory_) { + context_factory_.reset(new SurfaceContextFactory(shell_, window_, + surface_type_)); + } aura::Env::GetInstance()->set_context_factory(context_factory_.get()); + } window_tree_host_.reset( new WindowTreeHostMus(shell_, this, window_, surface_type_)); window_tree_host_->InitHost();
diff --git a/ui/views/mus/platform_window_mus.cc b/ui/views/mus/platform_window_mus.cc index 3a9c85f5..132e4b4 100644 --- a/ui/views/mus/platform_window_mus.cc +++ b/ui/views/mus/platform_window_mus.cc
@@ -31,7 +31,7 @@ // We need accelerated widget numbers to be different for each // window and fit in the smallest sizeof(AcceleratedWidget) uint32_t // has this property. -#if defined(OS_WIN) +#if defined(OS_WIN) || defined(OS_ANDROID) delegate_->OnAcceleratedWidgetAvailable( reinterpret_cast<gfx::AcceleratedWidget>(accelerated_widget_count++), mus_window_->viewport_metrics().device_pixel_ratio);
diff --git a/ui/views/mus/window_manager_connection.cc b/ui/views/mus/window_manager_connection.cc index 65e2804..3c068b8 100644 --- a/ui/views/mus/window_manager_connection.cc +++ b/ui/views/mus/window_manager_connection.cc
@@ -121,8 +121,7 @@ WindowManagerConnection::WindowManagerConnection(mojo::ApplicationImpl* app) : app_(app) { - app->ConnectToService(mojo::URLRequest::From(std::string("mojo:mus")), - &window_manager_); + app->ConnectToService("mojo:mus", &window_manager_); ui_init_.reset(new ui::mojo::UIInit( GetDisplaysFromWindowManager(&window_manager_)));
diff --git a/ui/views/widget/desktop_aura/desktop_capture_client.cc b/ui/views/widget/desktop_aura/desktop_capture_client.cc index 6b2df26..f2f3cf1 100644 --- a/ui/views/widget/desktop_aura/desktop_capture_client.cc +++ b/ui/views/widget/desktop_aura/desktop_capture_client.cc
@@ -6,6 +6,7 @@ #include "ui/aura/window.h" #include "ui/aura/window_event_dispatcher.h" +#include "ui/aura/window_tracker.h" #include "ui/aura/window_tree_host.h" namespace views { @@ -42,8 +43,16 @@ // If we're starting a new capture, cancel all touches that aren't // targeted to the capturing window. - if (new_capture_window) + if (new_capture_window) { + // Cancelling touches might cause |new_capture_window| to get deleted. + // Track |new_capture_window| and check if it still exists before + // committing |capture_window_|. + aura::WindowTracker tracker; + tracker.Add(new_capture_window); ui::GestureRecognizer::Get()->CancelActiveTouchesExcept(new_capture_window); + if (!tracker.Contains(new_capture_window)) + new_capture_window = nullptr; + } capture_window_ = new_capture_window;
diff --git a/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.cc b/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.cc index d02dede8..b717445 100644 --- a/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.cc +++ b/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.cc
@@ -29,6 +29,7 @@ #include "ui/events/devices/x11/device_list_cache_x11.h" #include "ui/events/devices/x11/touch_factory_x11.h" #include "ui/events/event_utils.h" +#include "ui/events/null_event_targeter.h" #include "ui/events/platform/platform_event_source.h" #include "ui/events/platform/x11/x11_event_source.h" #include "ui/gfx/display.h" @@ -173,6 +174,7 @@ custom_window_shape_(false), urgency_hint_set_(false), activatable_(true), + modal_dialog_xid_(0), close_widget_factory_(this) { } @@ -1529,7 +1531,8 @@ } void DesktopWindowTreeHostX11::DispatchKeyEvent(ui::KeyEvent* event) { - GetInputMethod()->DispatchKeyEvent(event); + if (native_widget_delegate_->AsWidget()->IsActive()) + GetInputMethod()->DispatchKeyEvent(event); } void DesktopWindowTreeHostX11::ConvertEventToDifferentHost( @@ -2049,6 +2052,26 @@ return gfx::ToEnclosingRect(rect_in_pixels); } +const XID DesktopWindowTreeHostX11::GetModalDialog() { + return modal_dialog_xid_; +} + +void DesktopWindowTreeHostX11::DisableEventListening(XID dialog) { + DCHECK(dialog); + DCHECK(!modal_dialog_xid_); + modal_dialog_xid_ = dialog; + // ScopedWindowTargeter is used to temporarily replace the event-targeter + // with NullEventTargeter to make |dialog| modal. + targeter_for_modal_.reset(new aura::ScopedWindowTargeter(window(), + scoped_ptr<ui::EventTargeter>(new ui::NullEventTargeter))); +} + +void DesktopWindowTreeHostX11::EnableEventListening() { + DCHECK(modal_dialog_xid_); + modal_dialog_xid_ = 0; + targeter_for_modal_.reset(); +} + //////////////////////////////////////////////////////////////////////////////// // DesktopWindowTreeHost, public:
diff --git a/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.h b/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.h index 09b5993f..20399df 100644 --- a/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.h +++ b/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.h
@@ -13,6 +13,7 @@ #include "base/cancelable_callback.h" #include "base/memory/weak_ptr.h" #include "base/observer_list.h" +#include "ui/aura/scoped_window_targeter.h" #include "ui/aura/window_tree_host.h" #include "ui/base/cursor/cursor_loader_x11.h" #include "ui/events/platform/platform_event_dispatcher.h" @@ -85,6 +86,16 @@ // internal list of open windows. static void CleanUpWindowList(void (*func)(aura::Window* window)); + // Disables event listening to make |dialog| modal. + void DisableEventListening(XID dialog); + + // Enables event listening after closing |dialog|. + void EnableEventListening(); + + // Returns XID of dialog currently displayed. When it returns 0, + // there is no dialog on the host window. + const XID GetModalDialog(); + protected: // Overridden from DesktopWindowTreeHost: void Init(aura::Window* content_window, @@ -351,6 +362,10 @@ base::CancelableCallback<void()> delayed_resize_task_; + scoped_ptr<aura::ScopedWindowTargeter> targeter_for_modal_; + + XID modal_dialog_xid_; + base::WeakPtrFactory<DesktopWindowTreeHostX11> close_widget_factory_; DISALLOW_COPY_AND_ASSIGN(DesktopWindowTreeHostX11);
diff --git a/ui/views/widget/desktop_aura/x11_desktop_handler.cc b/ui/views/widget/desktop_aura/x11_desktop_handler.cc index 5ab84f9..9b20295 100644 --- a/ui/views/widget/desktop_aura/x11_desktop_handler.cc +++ b/ui/views/widget/desktop_aura/x11_desktop_handler.cc
@@ -228,8 +228,15 @@ if (active_state == ACTIVE) { DesktopWindowTreeHostX11* new_host = views::DesktopWindowTreeHostX11::GetHostForXID(xid); - if (new_host) - new_host->HandleNativeWidgetActivationChanged(true); + if (new_host) { + // Set focus to the modal dialog instead of the host window. + if (new_host->GetModalDialog()) { + XSetInputFocus(xdisplay_, new_host->GetModalDialog(), + RevertToParent, CurrentTime); + } else { + new_host->HandleNativeWidgetActivationChanged(true); + } + } } }
diff --git a/ui/wm/BUILD.gn b/ui/wm/BUILD.gn index 1c113756..39fb4c0e 100644 --- a/ui/wm/BUILD.gn +++ b/ui/wm/BUILD.gn
@@ -81,9 +81,9 @@ "//ui/base/ime", "//ui/compositor", "//ui/events", + "//ui/events:events_base", "//ui/events/devices", "//ui/events/platform", - "//ui/events:events_base", "//ui/events/platform", "//ui/gfx", "//ui/gfx/geometry",
diff --git a/ui/wm/core/capture_controller.cc b/ui/wm/core/capture_controller.cc index 3024a7d..b10cc1a 100644 --- a/ui/wm/core/capture_controller.cc +++ b/ui/wm/core/capture_controller.cc
@@ -6,6 +6,7 @@ #include "ui/aura/window.h" #include "ui/aura/window_event_dispatcher.h" +#include "ui/aura/window_tracker.h" #include "ui/aura/window_tree_host.h" namespace wm { @@ -44,8 +45,16 @@ // If we're starting a new capture, cancel all touches that aren't // targeted to the capturing window. - if (new_capture_window) + if (new_capture_window) { + // Cancelling touches might cause |new_capture_window| to get deleted. + // Track |new_capture_window| and check if it still exists before + // committing |capture_window_|. + aura::WindowTracker tracker; + tracker.Add(new_capture_window); ui::GestureRecognizer::Get()->CancelActiveTouchesExcept(new_capture_window); + if (!tracker.Contains(new_capture_window)) + new_capture_window = nullptr; + } capture_window_ = new_capture_window; aura::Window* capture_root_window =
diff --git a/ui/wm/core/capture_controller_unittest.cc b/ui/wm/core/capture_controller_unittest.cc index ff072b7..e3ced50198 100644 --- a/ui/wm/core/capture_controller_unittest.cc +++ b/ui/wm/core/capture_controller_unittest.cc
@@ -15,6 +15,7 @@ #include "ui/events/event.h" #include "ui/events/event_utils.h" #include "ui/events/test/event_generator.h" +#include "ui/wm/core/capture_controller.h" namespace wm { @@ -75,6 +76,22 @@ AuraTestBase::TearDown(); } + aura::Window* CreateNormalWindowWithBounds(int id, + aura::Window* parent, + const gfx::Rect& bounds, + aura::WindowDelegate* delegate) { + aura::Window* window = new aura::Window( + delegate + ? delegate + : aura::test::TestWindowDelegate::CreateSelfDestroyingDelegate()); + window->set_id(id); + window->Init(ui::LAYER_TEXTURED); + parent->AddChild(window); + window->SetBounds(bounds); + window->Show(); + return window; + } + aura::Window* GetCaptureWindow() { return capture_controller_->capture_client()->GetCaptureWindow(); } @@ -192,4 +209,68 @@ EXPECT_FALSE(delegate2->HasNativeCapture()); } +// A delegate that deletes a window on scroll cancel gesture event. +class GestureEventDeleteWindowOnScrollEnd + : public aura::test::TestWindowDelegate { + public: + GestureEventDeleteWindowOnScrollEnd() {} + + void SetWindow(scoped_ptr<aura::Window> window) { window_ = window.Pass(); } + aura::Window* window() { return window_.get(); } + + // aura::test::TestWindowDelegate: + void OnGestureEvent(ui::GestureEvent* gesture) override { + TestWindowDelegate::OnGestureEvent(gesture); + if (gesture->type() != ui::ET_GESTURE_SCROLL_END) + return; + window_.reset(); + } + + private: + scoped_ptr<aura::Window> window_; + DISALLOW_COPY_AND_ASSIGN(GestureEventDeleteWindowOnScrollEnd); +}; + +// Tests a scenario when a window gets deleted while a capture is being set on +// it and when that window releases its capture prior to being deleted. +// This scenario should end safely without capture being set. +TEST_F(CaptureControllerTest, GestureResetWithCapture) { + scoped_ptr<GestureEventDeleteWindowOnScrollEnd> delegate( + new GestureEventDeleteWindowOnScrollEnd()); + const int kWindowWidth = 123; + const int kWindowHeight = 45; + gfx::Rect bounds(100, 200, kWindowWidth, kWindowHeight); + scoped_ptr<aura::Window> window1( + CreateNormalWindowWithBounds(-1235, root_window(), bounds, nullptr)); + + bounds.Offset(0, 100); + scoped_ptr<aura::Window> window2(CreateNormalWindowWithBounds( + -1234, root_window(), bounds, delegate.get())); + delegate->SetWindow(window1.Pass()); + + ui::test::EventGenerator event_generator(root_window()); + const int position_x = bounds.x() + 1; + int position_y = bounds.y() + 1; + event_generator.MoveTouch(gfx::Point(position_x, position_y)); + event_generator.PressTouch(); + for (int idx = 0 ; idx < 20 ; idx++, position_y++) + event_generator.MoveTouch(gfx::Point(position_x, position_y)); + + // Setting capture on |window1| cancels touch gestures that are active on + // |window2|. GestureEventDeleteWindowOnScrollEnd will then delete |window1| + // and should release capture on it. + delegate->window()->SetCapture(); + + // capture should not be set upon exit from SetCapture() above. + aura::client::CaptureClient* capture_client = + aura::client::GetCaptureClient(root_window()); + ASSERT_NE(nullptr, capture_client); + EXPECT_EQ(nullptr, capture_client->GetCaptureWindow()); + + // Send a mouse click. We no longer hold capture so this should not crash. + ui::MouseEvent mouse_press(ui::ET_MOUSE_PRESSED, gfx::Point(), gfx::Point(), + base::TimeDelta(), 0, 0); + DispatchEventUsingWindowDispatcher(&mouse_press); +} + } // namespace wm
diff --git a/url/BUILD.gn b/url/BUILD.gn index 7cedd400..2f3678c 100644 --- a/url/BUILD.gn +++ b/url/BUILD.gn
@@ -66,8 +66,8 @@ deps = [ "//base", "//base/third_party/dynamic_annotations", - "//third_party/icu:icudata", "//third_party/icu", + "//third_party/icu:icudata", ] }
diff --git a/win8/BUILD.gn b/win8/BUILD.gn index a064c15..1d4343d 100644 --- a/win8/BUILD.gn +++ b/win8/BUILD.gn
@@ -11,11 +11,11 @@ component("metro_viewer") { deps = [ + ":metro_viewer_constants", "//base", "//ipc", "//ui/aura", "//ui/metro_viewer", - ":metro_viewer_constants", ] sources = [ "viewer/metro_viewer_process_host.cc", @@ -26,8 +26,8 @@ source_set("test_support_win8") { deps = [ - "//base", ":test_registrar_constants", + "//base", ] # TODO(jschuh): crbug.com/167187 fix size_t to int truncations.